diff --git a/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp b/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp index ca0d9758e7d..cebe94f64a2 100644 --- a/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp +++ b/Libraries/LibWeb/WebAudio/AudioBufferSourceNode.cpp @@ -18,8 +18,8 @@ GC_DEFINE_ALLOCATOR(AudioBufferSourceNode); AudioBufferSourceNode::AudioBufferSourceNode(JS::Realm& realm, GC::Ref context, AudioBufferSourceOptions const& options) : AudioScheduledSourceNode(realm, context) , m_buffer(options.buffer) - , m_playback_rate(AudioParam::create(realm, options.playback_rate, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_detune(AudioParam::create(realm, options.detune, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_playback_rate(AudioParam::create(realm, context, options.playback_rate, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_detune(AudioParam::create(realm, context, options.detune, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) , m_loop(options.loop) , m_loop_start(options.loop_start) , m_loop_end(options.loop_end) diff --git a/Libraries/LibWeb/WebAudio/AudioListener.cpp b/Libraries/LibWeb/WebAudio/AudioListener.cpp index 5ff515d1575..31b70333b35 100644 --- a/Libraries/LibWeb/WebAudio/AudioListener.cpp +++ b/Libraries/LibWeb/WebAudio/AudioListener.cpp @@ -12,23 +12,23 @@ namespace Web::WebAudio { GC_DEFINE_ALLOCATOR(AudioListener); -AudioListener::AudioListener(JS::Realm& realm) +AudioListener::AudioListener(JS::Realm& realm, GC::Ref context) : Bindings::PlatformObject(realm) - , m_forward_x(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_forward_y(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_forward_z(AudioParam::create(realm, -1.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_position_x(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_position_y(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_position_z(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_up_x(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_up_y(AudioParam::create(realm, 1.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_up_z(AudioParam::create(realm, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_forward_x(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_forward_y(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_forward_z(AudioParam::create(realm, context, -1.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_x(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_y(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_z(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_up_x(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_up_y(AudioParam::create(realm, context, 1.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_up_z(AudioParam::create(realm, context, 0.f, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) { } -GC::Ref AudioListener::create(JS::Realm& realm) +GC::Ref AudioListener::create(JS::Realm& realm, GC::Ref context) { - return realm.create(realm); + return realm.create(realm, context); } AudioListener::~AudioListener() = default; diff --git a/Libraries/LibWeb/WebAudio/AudioListener.h b/Libraries/LibWeb/WebAudio/AudioListener.h index 9d44e3ac2bd..bd4aaf53bc7 100644 --- a/Libraries/LibWeb/WebAudio/AudioListener.h +++ b/Libraries/LibWeb/WebAudio/AudioListener.h @@ -20,7 +20,7 @@ class AudioListener final : public Bindings::PlatformObject { GC_DECLARE_ALLOCATOR(AudioListener); public: - static GC::Ref create(JS::Realm&); + static GC::Ref create(JS::Realm&, GC::Ref); virtual ~AudioListener() override; GC::Ref forward_x() const { return m_forward_x; } @@ -37,7 +37,7 @@ public: WebIDL::ExceptionOr set_orientation(float x, float y, float z, float x_up, float y_up, float z_up); private: - explicit AudioListener(JS::Realm&); + explicit AudioListener(JS::Realm&, GC::Ref); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; diff --git a/Libraries/LibWeb/WebAudio/AudioNode.cpp b/Libraries/LibWeb/WebAudio/AudioNode.cpp index 8a5cf702cc8..965bf590db4 100644 --- a/Libraries/LibWeb/WebAudio/AudioNode.cpp +++ b/Libraries/LibWeb/WebAudio/AudioNode.cpp @@ -78,7 +78,11 @@ WebIDL::ExceptionOr> AudioNode::connect(GC::Ref de // https://webaudio.github.io/web-audio-api/#dom-audionode-connect-destinationparam-output WebIDL::ExceptionOr AudioNode::connect(GC::Ref destination_param, WebIDL::UnsignedLong output) { - (void)destination_param; + // If destinationParam belongs to an AudioNode that belongs to a BaseAudioContext that is different from the BaseAudioContext + // that has created the AudioNode on which this method was called, an InvalidAccessError MUST be thrown. + if (m_context != destination_param->context()) { + return WebIDL::InvalidAccessError::create(realm(), "Cannot connect to an AudioParam in a different AudioContext"_string); + } // 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. diff --git a/Libraries/LibWeb/WebAudio/AudioParam.cpp b/Libraries/LibWeb/WebAudio/AudioParam.cpp index 7ed53fa5098..60a18f1363c 100644 --- a/Libraries/LibWeb/WebAudio/AudioParam.cpp +++ b/Libraries/LibWeb/WebAudio/AudioParam.cpp @@ -7,14 +7,16 @@ #include #include #include +#include #include namespace Web::WebAudio { GC_DEFINE_ALLOCATOR(AudioParam); -AudioParam::AudioParam(JS::Realm& realm, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate) +AudioParam::AudioParam(JS::Realm& realm, GC::Ref context, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate) : Bindings::PlatformObject(realm) + , m_context(context) , m_current_value(default_value) , m_default_value(default_value) , m_min_value(min_value) @@ -23,9 +25,9 @@ AudioParam::AudioParam(JS::Realm& realm, float default_value, float min_value, f { } -GC::Ref AudioParam::create(JS::Realm& realm, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate) +GC::Ref AudioParam::create(JS::Realm& realm, GC::Ref context, float default_value, float min_value, float max_value, Bindings::AutomationRate automation_rate) { - return realm.create(realm, default_value, min_value, max_value, automation_rate); + return realm.create(realm, context, default_value, min_value, max_value, automation_rate); } AudioParam::~AudioParam() = default; @@ -143,6 +145,7 @@ void AudioParam::initialize(JS::Realm& realm) void AudioParam::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + visitor.visit(m_context); } } diff --git a/Libraries/LibWeb/WebAudio/AudioParam.h b/Libraries/LibWeb/WebAudio/AudioParam.h index 6d8a66a0efe..43ccbd9ded6 100644 --- a/Libraries/LibWeb/WebAudio/AudioParam.h +++ b/Libraries/LibWeb/WebAudio/AudioParam.h @@ -18,10 +18,12 @@ class AudioParam final : public Bindings::PlatformObject { GC_DECLARE_ALLOCATOR(AudioParam); public: - static GC::Ref create(JS::Realm&, float default_value, float min_value, float max_value, Bindings::AutomationRate); + static GC::Ref create(JS::Realm&, GC::Ref, float default_value, float min_value, float max_value, Bindings::AutomationRate); virtual ~AudioParam() override; + GC::Ref context() const { return m_context; } + float value() const; void set_value(float); @@ -41,7 +43,9 @@ public: WebIDL::ExceptionOr> cancel_and_hold_at_time(double cancel_time); private: - AudioParam(JS::Realm&, float default_value, float min_value, float max_value, Bindings::AutomationRate); + AudioParam(JS::Realm&, GC::Ref, float default_value, float min_value, float max_value, Bindings::AutomationRate); + + GC::Ref m_context; // https://webaudio.github.io/web-audio-api/#dom-audioparam-current-value-slot float m_current_value {}; // [[current value]] diff --git a/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp b/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp index 8c7cfc98b29..9842e48265f 100644 --- a/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp +++ b/Libraries/LibWeb/WebAudio/BaseAudioContext.cpp @@ -29,7 +29,7 @@ namespace Web::WebAudio { BaseAudioContext::BaseAudioContext(JS::Realm& realm, float sample_rate) : DOM::EventTarget(realm) , m_sample_rate(sample_rate) - , m_listener(AudioListener::create(realm)) + , m_listener(AudioListener::create(realm, *this)) { } diff --git a/Libraries/LibWeb/WebAudio/BiquadFilterNode.cpp b/Libraries/LibWeb/WebAudio/BiquadFilterNode.cpp index a93f2462c7d..aa33f53d112 100644 --- a/Libraries/LibWeb/WebAudio/BiquadFilterNode.cpp +++ b/Libraries/LibWeb/WebAudio/BiquadFilterNode.cpp @@ -20,10 +20,10 @@ GC_DEFINE_ALLOCATOR(BiquadFilterNode); BiquadFilterNode::BiquadFilterNode(JS::Realm& realm, GC::Ref context, BiquadFilterOptions const& options) : AudioNode(realm, context) , m_type(options.type) - , m_frequency(AudioParam::create(realm, options.frequency, 0, context->nyquist_frequency(), Bindings::AutomationRate::ARate)) - , m_detune(AudioParam::create(realm, options.detune, -1200 * AK::log2(NumericLimits::max()), 1200 * AK::log2(NumericLimits::max()), Bindings::AutomationRate::ARate)) - , m_q(AudioParam::create(realm, options.q, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_gain(AudioParam::create(realm, options.gain, NumericLimits::lowest(), 40 * AK::log10(NumericLimits::max()), Bindings::AutomationRate::ARate)) + , m_frequency(AudioParam::create(realm, context, options.frequency, 0, context->nyquist_frequency(), Bindings::AutomationRate::ARate)) + , m_detune(AudioParam::create(realm, context, options.detune, -1200 * AK::log2(NumericLimits::max()), 1200 * AK::log2(NumericLimits::max()), Bindings::AutomationRate::ARate)) + , m_q(AudioParam::create(realm, context, options.q, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_gain(AudioParam::create(realm, context, options.gain, NumericLimits::lowest(), 40 * AK::log10(NumericLimits::max()), Bindings::AutomationRate::ARate)) { } diff --git a/Libraries/LibWeb/WebAudio/ConstantSourceNode.cpp b/Libraries/LibWeb/WebAudio/ConstantSourceNode.cpp index bcf5f72c796..a85b03aee57 100644 --- a/Libraries/LibWeb/WebAudio/ConstantSourceNode.cpp +++ b/Libraries/LibWeb/WebAudio/ConstantSourceNode.cpp @@ -16,7 +16,7 @@ GC_DEFINE_ALLOCATOR(ConstantSourceNode); ConstantSourceNode::ConstantSourceNode(JS::Realm& realm, GC::Ref context, ConstantSourceOptions const& options) : AudioScheduledSourceNode(realm, context) - , m_offset(AudioParam::create(realm, options.offset, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_offset(AudioParam::create(realm, context, options.offset, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) { } diff --git a/Libraries/LibWeb/WebAudio/DelayNode.cpp b/Libraries/LibWeb/WebAudio/DelayNode.cpp index ebdea38fb22..307474ea255 100644 --- a/Libraries/LibWeb/WebAudio/DelayNode.cpp +++ b/Libraries/LibWeb/WebAudio/DelayNode.cpp @@ -15,7 +15,7 @@ GC_DEFINE_ALLOCATOR(DelayNode); DelayNode::DelayNode(JS::Realm& realm, GC::Ref context, DelayOptions const& options) : AudioNode(realm, context) - , m_delay_time(AudioParam::create(realm, options.delay_time, 0, options.max_delay_time, Bindings::AutomationRate::ARate)) + , m_delay_time(AudioParam::create(realm, context, options.delay_time, 0, options.max_delay_time, Bindings::AutomationRate::ARate)) { } diff --git a/Libraries/LibWeb/WebAudio/DynamicsCompressorNode.cpp b/Libraries/LibWeb/WebAudio/DynamicsCompressorNode.cpp index a0170a0a027..957865c6000 100644 --- a/Libraries/LibWeb/WebAudio/DynamicsCompressorNode.cpp +++ b/Libraries/LibWeb/WebAudio/DynamicsCompressorNode.cpp @@ -41,11 +41,11 @@ WebIDL::ExceptionOr> DynamicsCompressorNode::con DynamicsCompressorNode::DynamicsCompressorNode(JS::Realm& realm, GC::Ref context, DynamicsCompressorOptions const& options) : AudioNode(realm, context) - , m_threshold(AudioParam::create(realm, options.threshold, -100, 0, Bindings::AutomationRate::KRate)) - , m_knee(AudioParam::create(realm, options.knee, 0, 40, Bindings::AutomationRate::KRate)) - , m_ratio(AudioParam::create(realm, options.ratio, 1, 20, Bindings::AutomationRate::KRate)) - , m_attack(AudioParam::create(realm, options.attack, 0, 1, Bindings::AutomationRate::KRate)) - , m_release(AudioParam::create(realm, options.release, 0, 1, Bindings::AutomationRate::KRate)) + , m_threshold(AudioParam::create(realm, context, options.threshold, -100, 0, Bindings::AutomationRate::KRate)) + , m_knee(AudioParam::create(realm, context, options.knee, 0, 40, Bindings::AutomationRate::KRate)) + , m_ratio(AudioParam::create(realm, context, options.ratio, 1, 20, Bindings::AutomationRate::KRate)) + , m_attack(AudioParam::create(realm, context, options.attack, 0, 1, Bindings::AutomationRate::KRate)) + , m_release(AudioParam::create(realm, context, options.release, 0, 1, Bindings::AutomationRate::KRate)) { } diff --git a/Libraries/LibWeb/WebAudio/GainNode.cpp b/Libraries/LibWeb/WebAudio/GainNode.cpp index 69f2a6b935f..616854d5836 100644 --- a/Libraries/LibWeb/WebAudio/GainNode.cpp +++ b/Libraries/LibWeb/WebAudio/GainNode.cpp @@ -41,7 +41,7 @@ WebIDL::ExceptionOr> GainNode::construct_impl(JS::Realm& realm GainNode::GainNode(JS::Realm& realm, GC::Ref context, GainOptions const& options) : AudioNode(realm, context) - , m_gain(AudioParam::create(realm, options.gain, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_gain(AudioParam::create(realm, context, options.gain, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) { } diff --git a/Libraries/LibWeb/WebAudio/OscillatorNode.cpp b/Libraries/LibWeb/WebAudio/OscillatorNode.cpp index a0ed5c16b37..ac6521b8041 100644 --- a/Libraries/LibWeb/WebAudio/OscillatorNode.cpp +++ b/Libraries/LibWeb/WebAudio/OscillatorNode.cpp @@ -50,8 +50,8 @@ WebIDL::ExceptionOr> OscillatorNode::construct_impl(JS:: OscillatorNode::OscillatorNode(JS::Realm& realm, GC::Ref context, OscillatorOptions const& options) : AudioScheduledSourceNode(realm, context) , m_type(options.type) - , m_frequency(AudioParam::create(realm, options.frequency, -context->nyquist_frequency(), context->nyquist_frequency(), Bindings::AutomationRate::ARate)) - , m_detune(AudioParam::create(realm, options.detune, -1200 * AK::log2(NumericLimits::max()), 1200 * AK::log2(NumericLimits::max()), Bindings::AutomationRate::ARate)) + , m_frequency(AudioParam::create(realm, context, options.frequency, -context->nyquist_frequency(), context->nyquist_frequency(), Bindings::AutomationRate::ARate)) + , m_detune(AudioParam::create(realm, context, options.detune, -1200 * AK::log2(NumericLimits::max()), 1200 * AK::log2(NumericLimits::max()), Bindings::AutomationRate::ARate)) { } diff --git a/Libraries/LibWeb/WebAudio/PannerNode.cpp b/Libraries/LibWeb/WebAudio/PannerNode.cpp index 1b801aa6295..71367f49aab 100644 --- a/Libraries/LibWeb/WebAudio/PannerNode.cpp +++ b/Libraries/LibWeb/WebAudio/PannerNode.cpp @@ -62,12 +62,12 @@ WebIDL::ExceptionOr> PannerNode::construct_impl(JS::Realm& r PannerNode::PannerNode(JS::Realm& realm, GC::Ref context, PannerOptions const& options) : AudioNode(realm, context) , m_panning_model(options.panning_model) - , m_position_x(AudioParam::create(realm, options.position_x, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_position_y(AudioParam::create(realm, options.position_y, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_position_z(AudioParam::create(realm, options.position_z, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_orientation_x(AudioParam::create(realm, options.orientation_x, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_orientation_y(AudioParam::create(realm, options.orientation_y, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) - , m_orientation_z(AudioParam::create(realm, options.orientation_z, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_x(AudioParam::create(realm, context, options.position_x, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_y(AudioParam::create(realm, context, options.position_y, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_position_z(AudioParam::create(realm, context, options.position_z, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_orientation_x(AudioParam::create(realm, context, options.orientation_x, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_orientation_y(AudioParam::create(realm, context, options.orientation_y, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) + , m_orientation_z(AudioParam::create(realm, context, options.orientation_z, NumericLimits::lowest(), NumericLimits::max(), Bindings::AutomationRate::ARate)) , m_distance_model(options.distance_model) , m_ref_distance(options.ref_distance) , m_max_distance(options.max_distance)