diff --git a/Tests/LibWeb/Text/expected/DOM/AbortSignal-any-crash.txt b/Tests/LibWeb/Text/expected/DOM/AbortSignal-any-crash.txt new file mode 100644 index 00000000000..47a5310842d --- /dev/null +++ b/Tests/LibWeb/Text/expected/DOM/AbortSignal-any-crash.txt @@ -0,0 +1 @@ +PASS (didn't crash) \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/DOM/AbortSignal-any-crash.html b/Tests/LibWeb/Text/input/DOM/AbortSignal-any-crash.html new file mode 100644 index 00000000000..1204b6200d7 --- /dev/null +++ b/Tests/LibWeb/Text/input/DOM/AbortSignal-any-crash.html @@ -0,0 +1,11 @@ + + + diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp index d333b9611a0..26234e4b522 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2021, Luke Wilde - * Copyright (c) 2024, Tim Ledbetter + * Copyright (c) 2024, Tim Ledbetter * * SPDX-License-Identifier: BSD-2-Clause */ @@ -58,21 +58,42 @@ void AbortSignal::signal_abort(JS::Value reason) else m_abort_reason = WebIDL::AbortError::create(realm(), "Aborted without reason"_fly_string).ptr(); - // 3. For each algorithm in signal’s abort algorithms: run algorithm. - for (auto& algorithm : m_abort_algorithms) - algorithm->function()(); + // 3. Let dependentSignalsToAbort be a new list. + Vector> dependent_signals_to_abort; - // 4. Empty signal’s abort algorithms. - m_abort_algorithms.clear(); + // 4. For each dependentSignal of signal’s dependent signals: + for (auto const& dependent_signal : m_dependent_signals) { + // 1. If dependentSignal is not aborted, then: + if (!dependent_signal->aborted()) { + // 1. Set dependentSignal’s abort reason to signal’s abort reason. + dependent_signal->set_reason(m_abort_reason); - // 5. Fire an event named abort at signal. - auto abort_event = Event::create(realm(), HTML::EventNames::abort); - abort_event->set_is_trusted(true); - dispatch_event(abort_event); + // 2. Append dependentSignal to dependentSignalsToAbort. + dependent_signals_to_abort.append(*dependent_signal); + } + } - // 6. For each dependentSignal of signal’s dependent signals, signal abort on dependentSignal with signal’s abort reason. - for (auto const& dependent_signal : m_dependent_signals) - dependent_signal->signal_abort(reason); + // https://dom.spec.whatwg.org/#run-the-abort-steps + auto run_the_abort_steps = [](auto& signal) { + // 1. For each algorithm in signal’s abort algorithms: run algorithm. + for (auto& algorithm : signal.m_abort_algorithms) + algorithm->function()(); + + // 2. Empty signal’s abort algorithms. + signal.m_abort_algorithms.clear(); + + // 3. Fire an event named abort at signal. + auto abort_event = Event::create(signal.realm(), HTML::EventNames::abort); + abort_event->set_is_trusted(true); + signal.dispatch_event(abort_event); + }; + + // 5. Run the abort steps for signal. + run_the_abort_steps(*this); + + // 6. For each dependentSignal of dependentSignalsToAbort, run the abort steps for dependentSignal. + for (auto const& dependent_signal : dependent_signals_to_abort) + run_the_abort_steps(*dependent_signal); } void AbortSignal::set_onabort(WebIDL::CallbackType* event_handler)