mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-23 17:33:12 +00:00
LibWeb: Support removing callbacks from AbortSignal
This will be needed by Streams. To support this, we now store callbacks in a hash table, keyed by an ID. Callers may use that ID to remove the callback at a later point.
This commit is contained in:
parent
f268f24dd5
commit
4010c4643a
Notes:
github-actions[bot]
2025-04-11 16:11:54 +00:00
Author: https://github.com/trflynn89
Commit: 4010c4643a
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4311
Reviewed-by: https://github.com/ADKaster
Reviewed-by: https://github.com/shannonbooth ✅
5 changed files with 22 additions and 11 deletions
|
@ -35,14 +35,22 @@ void AbortSignal::initialize(JS::Realm& realm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#abortsignal-add
|
// https://dom.spec.whatwg.org/#abortsignal-add
|
||||||
void AbortSignal::add_abort_algorithm(Function<void()> abort_algorithm)
|
Optional<AbortSignal::AbortAlgorithmID> AbortSignal::add_abort_algorithm(Function<void()> abort_algorithm)
|
||||||
{
|
{
|
||||||
// 1. If signal is aborted, then return.
|
// 1. If signal is aborted, then return.
|
||||||
if (aborted())
|
if (aborted())
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
// 2. Append algorithm to signal’s abort algorithms.
|
// 2. Append algorithm to signal’s abort algorithms.
|
||||||
m_abort_algorithms.append(GC::create_function(vm().heap(), move(abort_algorithm)));
|
m_abort_algorithms.set(++m_next_abort_algorithm_id, GC::create_function(vm().heap(), move(abort_algorithm)));
|
||||||
|
return m_next_abort_algorithm_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#abortsignal-remove
|
||||||
|
void AbortSignal::remove_abort_algorithm(AbortAlgorithmID id)
|
||||||
|
{
|
||||||
|
// To remove an algorithm algorithm from an AbortSignal signal, remove algorithm from signal’s abort algorithms.
|
||||||
|
m_abort_algorithms.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#abortsignal-signal-abort
|
// https://dom.spec.whatwg.org/#abortsignal-signal-abort
|
||||||
|
@ -76,8 +84,8 @@ void AbortSignal::signal_abort(JS::Value reason)
|
||||||
// https://dom.spec.whatwg.org/#run-the-abort-steps
|
// https://dom.spec.whatwg.org/#run-the-abort-steps
|
||||||
auto run_the_abort_steps = [](auto& signal) {
|
auto run_the_abort_steps = [](auto& signal) {
|
||||||
// 1. For each algorithm in signal’s abort algorithms: run algorithm.
|
// 1. For each algorithm in signal’s abort algorithms: run algorithm.
|
||||||
for (auto& algorithm : signal.m_abort_algorithms)
|
for (auto const& algorithm : signal.m_abort_algorithms)
|
||||||
algorithm->function()();
|
algorithm.value->function()();
|
||||||
|
|
||||||
// 2. Empty signal’s abort algorithms.
|
// 2. Empty signal’s abort algorithms.
|
||||||
signal.m_abort_algorithms.clear();
|
signal.m_abort_algorithms.clear();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashMap.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/Weakable.h>
|
#include <AK/Weakable.h>
|
||||||
#include <LibGC/Function.h>
|
#include <LibGC/Function.h>
|
||||||
|
@ -26,7 +27,9 @@ public:
|
||||||
|
|
||||||
virtual ~AbortSignal() override = default;
|
virtual ~AbortSignal() override = default;
|
||||||
|
|
||||||
void add_abort_algorithm(ESCAPING Function<void()>);
|
using AbortAlgorithmID = u64;
|
||||||
|
Optional<AbortAlgorithmID> add_abort_algorithm(Function<void()>);
|
||||||
|
void remove_abort_algorithm(AbortAlgorithmID);
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-abortsignal-aborted
|
// https://dom.spec.whatwg.org/#dom-abortsignal-aborted
|
||||||
// An AbortSignal object is aborted when its abort reason is not undefined.
|
// An AbortSignal object is aborted when its abort reason is not undefined.
|
||||||
|
@ -68,8 +71,8 @@ private:
|
||||||
JS::Value m_abort_reason { JS::js_undefined() };
|
JS::Value m_abort_reason { JS::js_undefined() };
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#abortsignal-abort-algorithms
|
// https://dom.spec.whatwg.org/#abortsignal-abort-algorithms
|
||||||
// FIXME: This should be a set.
|
OrderedHashMap<AbortAlgorithmID, GC::Ref<GC::Function<void()>>> m_abort_algorithms;
|
||||||
Vector<GC::Ref<GC::Function<void()>>> m_abort_algorithms;
|
AbortAlgorithmID m_next_abort_algorithm_id { 0 };
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#abortsignal-source-signals
|
// https://dom.spec.whatwg.org/#abortsignal-source-signals
|
||||||
// An AbortSignal object has associated source signals (a weak set of AbortSignal objects that the object is dependent on for its aborted state), which is initially empty.
|
// An AbortSignal object has associated source signals (a weak set of AbortSignal objects that the object is dependent on for its aborted state), which is initially empty.
|
||||||
|
|
|
@ -231,7 +231,7 @@ void EventTarget::add_an_event_listener(DOMEventListener& listener)
|
||||||
// 6. If listener’s signal is not null, then add the following abort steps to it:
|
// 6. If listener’s signal is not null, then add the following abort steps to it:
|
||||||
if (listener.signal) {
|
if (listener.signal) {
|
||||||
// NOTE: `this` and `listener` are protected by AbortSignal using GC::HeapFunction.
|
// NOTE: `this` and `listener` are protected by AbortSignal using GC::HeapFunction.
|
||||||
listener.signal->add_abort_algorithm([this, &listener] {
|
(void)listener.signal->add_abort_algorithm([this, &listener] {
|
||||||
// 1. Remove an event listener with eventTarget and listener.
|
// 1. Remove an event listener with eventTarget and listener.
|
||||||
remove_an_event_listener(listener);
|
remove_an_event_listener(listener);
|
||||||
});
|
});
|
||||||
|
|
|
@ -130,7 +130,7 @@ GC::Ref<WebIDL::Promise> fetch(JS::VM& vm, RequestInfo const& input, RequestInit
|
||||||
}))));
|
}))));
|
||||||
|
|
||||||
// 11. Add the following abort steps to requestObject’s signal:
|
// 11. Add the following abort steps to requestObject’s signal:
|
||||||
request_object->signal()->add_abort_algorithm([locally_aborted, request, controller_holder, promise_capability, request_object, response_object, &relevant_realm] {
|
(void)request_object->signal()->add_abort_algorithm([locally_aborted, request, controller_holder, promise_capability, request_object, response_object, &relevant_realm] {
|
||||||
dbgln_if(WEB_FETCH_DEBUG, "Fetch: Request object signal's abort algorithm called");
|
dbgln_if(WEB_FETCH_DEBUG, "Fetch: Request object signal's abort algorithm called");
|
||||||
|
|
||||||
// 1. Set locallyAborted to true.
|
// 1. Set locallyAborted to true.
|
||||||
|
|
|
@ -65,7 +65,7 @@ WebIDL::ExceptionOr<GC::Ref<CloseWatcher>> CloseWatcher::construct_impl(JS::Real
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3.2 Add the following steps to options["signal"]:
|
// 3.2 Add the following steps to options["signal"]:
|
||||||
signal->add_abort_algorithm([close_watcher] {
|
(void)signal->add_abort_algorithm([close_watcher] {
|
||||||
// 3.2.1 Destroy closeWatcher.
|
// 3.2.1 Destroy closeWatcher.
|
||||||
close_watcher->destroy();
|
close_watcher->destroy();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue