mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-05 09:06:08 +00:00
LibWeb: Abort dependent signals before firing abort event
Previously, there was a bug in the specification that would cause an assertion failure, due to the abort event being fired before all dependent signals were aborted.
This commit is contained in:
parent
68fcc37531
commit
3ae4ea7b10
Notes:
github-actions[bot]
2024-09-09 13:12:26 +00:00
Author: https://github.com/tcl3
Commit: 3ae4ea7b10
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1336
3 changed files with 46 additions and 13 deletions
1
Tests/LibWeb/Text/expected/DOM/AbortSignal-any-crash.txt
Normal file
1
Tests/LibWeb/Text/expected/DOM/AbortSignal-any-crash.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
PASS (didn't crash)
|
11
Tests/LibWeb/Text/input/DOM/AbortSignal-any-crash.html
Normal file
11
Tests/LibWeb/Text/input/DOM/AbortSignal-any-crash.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const signal = AbortSignal.any([abortController.signal]);
|
||||||
|
abortController.signal.addEventListener("abort", () => { AbortSignal.any([signal]) });
|
||||||
|
abortController.abort();
|
||||||
|
println("PASS (didn't crash)");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||||
* Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com>
|
* Copyright (c) 2024, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -58,21 +58,42 @@ void AbortSignal::signal_abort(JS::Value reason)
|
||||||
else
|
else
|
||||||
m_abort_reason = WebIDL::AbortError::create(realm(), "Aborted without reason"_fly_string).ptr();
|
m_abort_reason = WebIDL::AbortError::create(realm(), "Aborted without reason"_fly_string).ptr();
|
||||||
|
|
||||||
// 3. For each algorithm in signal’s abort algorithms: run algorithm.
|
// 3. Let dependentSignalsToAbort be a new list.
|
||||||
for (auto& algorithm : m_abort_algorithms)
|
Vector<JS::Handle<AbortSignal>> dependent_signals_to_abort;
|
||||||
algorithm->function()();
|
|
||||||
|
|
||||||
// 4. Empty signal’s abort algorithms.
|
// 4. For each dependentSignal of signal’s dependent signals:
|
||||||
m_abort_algorithms.clear();
|
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.
|
// 2. Append dependentSignal to dependentSignalsToAbort.
|
||||||
auto abort_event = Event::create(realm(), HTML::EventNames::abort);
|
dependent_signals_to_abort.append(*dependent_signal);
|
||||||
abort_event->set_is_trusted(true);
|
}
|
||||||
dispatch_event(abort_event);
|
}
|
||||||
|
|
||||||
// 6. For each dependentSignal of signal’s dependent signals, signal abort on dependentSignal with signal’s abort reason.
|
// https://dom.spec.whatwg.org/#run-the-abort-steps
|
||||||
for (auto const& dependent_signal : m_dependent_signals)
|
auto run_the_abort_steps = [](auto& signal) {
|
||||||
dependent_signal->signal_abort(reason);
|
// 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)
|
void AbortSignal::set_onabort(WebIDL::CallbackType* event_handler)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue