mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
LibWeb: Implement pending promises in BaseAudioContext
Move the pending promises list from AudioContext to BaseAudioContext and deal with all remaining FIXMEs.
This commit is contained in:
parent
0310b47a7b
commit
2df3488840
Notes:
github-actions[bot]
2024-10-17 12:49:07 +00:00
Author: https://github.com/gmta Commit: https://github.com/LadybirdBrowser/ladybird/commit/2df3488840c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1839
4 changed files with 25 additions and 17 deletions
|
@ -92,7 +92,6 @@ void AudioContext::initialize(JS::Realm& realm)
|
|||
void AudioContext::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_pending_promises);
|
||||
visitor.visit(m_pending_resume_promises);
|
||||
}
|
||||
|
||||
|
@ -107,7 +106,6 @@ AudioTimestamp AudioContext::get_output_timestamp()
|
|||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> AudioContext::resume()
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. If this's relevant global object's associated Document is not fully active then return a promise rejected with "InvalidStateError" DOMException.
|
||||
auto const& associated_document = verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).associated_document();
|
||||
|
@ -128,8 +126,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> AudioContext::resume()
|
|||
|
||||
// 5. If the context is not allowed to start, append promise to [[pending promises]] and [[pending resume promises]] and abort these steps, returning promise.
|
||||
if (m_allowed_to_start) {
|
||||
TRY_OR_THROW_OOM(vm, m_pending_promises.try_append(promise));
|
||||
TRY_OR_THROW_OOM(vm, m_pending_resume_promises.try_append(promise));
|
||||
m_pending_promises.append(promise);
|
||||
m_pending_resume_promises.append(promise);
|
||||
}
|
||||
|
||||
// 6. Set the [[control thread state]] on the AudioContext to running.
|
||||
|
@ -150,25 +148,29 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> AudioContext::resume()
|
|||
// 7.4.1: Reject all promises from [[pending resume promises]] in order, then clear [[pending resume promises]].
|
||||
for (auto const& promise : m_pending_resume_promises) {
|
||||
WebIDL::reject_promise(realm, promise, JS::js_null());
|
||||
|
||||
// 7.4.2: Additionally, remove those promises from [[pending promises]].
|
||||
m_pending_promises.remove_first_matching([&promise](auto& pending_promise) {
|
||||
return pending_promise == promise;
|
||||
});
|
||||
}
|
||||
m_pending_resume_promises.clear();
|
||||
|
||||
// FIXME: 7.4.2: Additionally, remove those promises from [[pending promises]].
|
||||
}));
|
||||
}
|
||||
|
||||
// 7.5: queue a media element task to execute the following steps:
|
||||
queue_a_media_element_task(JS::create_heap_function(heap(), [&realm, promise, this]() {
|
||||
// 7.5.1: Resolve all promises from [[pending resume promises]] in order.
|
||||
// 7.5.2: Clear [[pending resume promises]]. Additionally, remove those promises from
|
||||
// [[pending promises]].
|
||||
for (auto const& pending_resume_promise : m_pending_resume_promises) {
|
||||
*pending_resume_promise->resolve();
|
||||
m_pending_promises.remove_first_matching([&pending_resume_promise](auto& pending_promise) {
|
||||
return pending_promise == pending_resume_promise;
|
||||
});
|
||||
}
|
||||
|
||||
// 7.5.2: Clear [[pending resume promises]].
|
||||
m_pending_resume_promises.clear();
|
||||
|
||||
// FIXME: Additionally, remove those promises from [[pending promises]].
|
||||
|
||||
// 7.5.3: Resolve promise.
|
||||
*promise->resolve();
|
||||
|
||||
|
@ -192,7 +194,6 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> AudioContext::resume()
|
|||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> AudioContext::suspend()
|
||||
{
|
||||
auto& realm = this->realm();
|
||||
auto& vm = realm.vm();
|
||||
|
||||
// 1. If this's relevant global object's associated Document is not fully active then return a promise rejected with "InvalidStateError" DOMException.
|
||||
auto const& associated_document = verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).associated_document();
|
||||
|
@ -209,7 +210,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Promise>> AudioContext::suspend()
|
|||
}
|
||||
|
||||
// 4. Append promise to [[pending promises]].
|
||||
TRY_OR_THROW_OOM(vm, m_pending_promises.try_append(promise));
|
||||
m_pending_promises.append(promise);
|
||||
|
||||
// 5. Set [[suspended by user]] to true.
|
||||
m_suspended_by_user = true;
|
||||
|
|
|
@ -49,7 +49,6 @@ private:
|
|||
double m_output_latency { 0 };
|
||||
|
||||
bool m_allowed_to_start = true;
|
||||
Vector<JS::NonnullGCPtr<WebIDL::Promise>> m_pending_promises;
|
||||
Vector<JS::NonnullGCPtr<WebIDL::Promise>> m_pending_resume_promises;
|
||||
bool m_suspended_by_user = false;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ void BaseAudioContext::visit_edges(Cell::Visitor& visitor)
|
|||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_destination);
|
||||
visitor.visit(m_pending_promises);
|
||||
}
|
||||
|
||||
void BaseAudioContext::set_onstatechange(WebIDL::CallbackType* event_handler)
|
||||
|
@ -144,7 +145,8 @@ JS::NonnullGCPtr<JS::Promise> BaseAudioContext::decode_audio_data(JS::Handle<Web
|
|||
|
||||
// FIXME: 3. If audioData is detached, execute the following steps:
|
||||
if (true) {
|
||||
// FIXME: 3.1. Append promise to [[pending promises]].
|
||||
// 3.1. Append promise to [[pending promises]].
|
||||
m_pending_promises.append(promise);
|
||||
|
||||
// FIXME: 3.2. Detach the audioData ArrayBuffer. If this operations throws, jump to the step 3.
|
||||
|
||||
|
@ -159,6 +161,9 @@ JS::NonnullGCPtr<JS::Promise> BaseAudioContext::decode_audio_data(JS::Handle<Web
|
|||
|
||||
// 4.2. Reject promise with error, and remove it from [[pending promises]].
|
||||
WebIDL::reject_promise(realm, promise, error);
|
||||
m_pending_promises.remove_first_matching([&promise](auto& pending_promise) {
|
||||
return pending_promise == promise;
|
||||
});
|
||||
|
||||
// 4.3. Queue a media element task to invoke errorCallback with error.
|
||||
if (error_callback) {
|
||||
|
@ -201,13 +206,15 @@ void BaseAudioContext::queue_a_decoding_operation(JS::NonnullGCPtr<JS::PromiseCa
|
|||
// 4. If can decode is false,
|
||||
if (!can_decode) {
|
||||
// queue a media element task to execute the following steps:
|
||||
queue_a_media_element_task(JS::create_heap_function(heap(), [&realm, promise, error_callback] {
|
||||
queue_a_media_element_task(JS::create_heap_function(heap(), [this, &realm, promise, error_callback] {
|
||||
// 4.1. Let error be a DOMException whose name is EncodingError.
|
||||
auto error = WebIDL::EncodingError::create(realm, "Unable to decode."_string);
|
||||
|
||||
// 4.1.2. Reject promise with error,
|
||||
// 4.1.2. Reject promise with error, and remove it from [[pending promises]].
|
||||
WebIDL::reject_promise(realm, promise, error);
|
||||
// FIXME: and remove it from [[pending promises]].
|
||||
m_pending_promises.remove_first_matching([&promise](auto& pending_promise) {
|
||||
return pending_promise == promise;
|
||||
});
|
||||
|
||||
// 4.2. If errorCallback is not missing, invoke errorCallback with error.
|
||||
if (error_callback) {
|
||||
|
|
|
@ -70,6 +70,7 @@ protected:
|
|||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
JS::NonnullGCPtr<AudioDestinationNode> m_destination;
|
||||
Vector<JS::NonnullGCPtr<WebIDL::Promise>> m_pending_promises;
|
||||
|
||||
private:
|
||||
void queue_a_decoding_operation(JS::NonnullGCPtr<JS::PromiseCapability>, JS::Handle<WebIDL::BufferSource>, JS::GCPtr<WebIDL::CallbackType>, JS::GCPtr<WebIDL::CallbackType>);
|
||||
|
|
Loading…
Reference in a new issue