LibWeb: Implement window.stop()

Fixes a handful of timeouts on WPT.
This commit is contained in:
Andreas Kling 2024-12-05 10:56:47 +01:00 committed by Andreas Kling
parent fdee82d203
commit 3f461b96df
Notes: github-actions[bot] 2024-12-05 11:39:56 +00:00
11 changed files with 94 additions and 0 deletions

View file

@ -2234,4 +2234,18 @@ void Navigable::unregister_navigation_observer(Badge<NavigationObserver>, Naviga
VERIFY(was_removed); VERIFY(was_removed);
} }
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#nav-stop
void Navigable::stop_loading()
{
// 1. Let document be navigable's active document.
auto document = active_document();
// 2. If document's unload counter is 0, and navigable's ongoing navigation is a navigation ID, then set the ongoing navigation for navigable to null.
if (document->unload_counter() == 0 && ongoing_navigation().has<String>())
set_ongoing_navigation(Empty {});
// 3. Abort a document and its descendants given document.
document->abort_a_document_and_its_descendants();
}
} }

View file

@ -74,6 +74,8 @@ public:
void set_closing(bool value) { m_closing = value; } void set_closing(bool value) { m_closing = value; }
bool is_script_closable(); bool is_script_closable();
void stop_loading();
void set_delaying_load_events(bool value); void set_delaying_load_events(bool value);
bool is_delaying_load_events() const { return m_delaying_the_load_event.has_value(); } bool is_delaying_load_events() const { return m_delaying_the_load_event.has_value(); }

View file

@ -856,6 +856,18 @@ GC::Ref<History> Window::history() const
return associated_document().history(); return associated_document().history();
} }
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-stop
void Window::stop()
{
// 1. If this's navigable is null, then return.
auto navigable = this->navigable();
if (!navigable)
return;
// 2. Stop loading this's navigable.
navigable->stop_loading();
}
// https://html.spec.whatwg.org/multipage/interaction.html#dom-window-focus // https://html.spec.whatwg.org/multipage/interaction.html#dom-window-focus
void Window::focus() void Window::focus()
{ {

View file

@ -154,6 +154,7 @@ public:
[[nodiscard]] GC::Ref<Location> location(); [[nodiscard]] GC::Ref<Location> location();
GC::Ref<History> history() const; GC::Ref<History> history() const;
GC::Ref<Navigation> navigation(); GC::Ref<Navigation> navigation();
void stop();
void focus(); void focus();
void blur(); void blur();

View file

@ -30,6 +30,7 @@ interface Window : EventTarget {
readonly attribute History history; readonly attribute History history;
readonly attribute Navigation navigation; readonly attribute Navigation navigation;
readonly attribute CustomElementRegistry customElements; readonly attribute CustomElementRegistry customElements;
undefined stop();
undefined focus(); undefined focus();
undefined blur(); undefined blur();

View file

@ -47,6 +47,8 @@ Text/input/wpt-import/html/syntax/parsing/support/no-doctype-name-line.html
Text/input/wpt-import/html/syntax/parsing/support/no-doctype-name-space.html Text/input/wpt-import/html/syntax/parsing/support/no-doctype-name-space.html
Text/input/wpt-import/html/semantics/embedded-content/the-iframe-element/support/sandbox_allow_script.html Text/input/wpt-import/html/semantics/embedded-content/the-iframe-element/support/sandbox_allow_script.html
Text/input/wpt-import/html/semantics/embedded-content/the-iframe-element/support/blank.htm Text/input/wpt-import/html/semantics/embedded-content/the-iframe-element/support/blank.htm
Text/input/wpt-import/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/aborted-parser-frame.html
Text/input/wpt-import/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/aborted-parser-async-frame.html
; Unknown, imported as skipped in #2148 ; Unknown, imported as skipped in #2148
Text/input/wpt-import/html/infrastructure/safe-passing-of-structured-data/structuredclone_0.html Text/input/wpt-import/html/infrastructure/safe-passing-of-structured-data/structuredclone_0.html

View file

@ -0,0 +1,7 @@
Harness status: OK
Found 2 tests
2 Pass
Pass document.open() after parser is aborted
Pass async document.open() after parser is aborted

View file

@ -0,0 +1,8 @@
<!doctype html>
<meta charset=utf-8>
<script src="../../../../resources/testharness.js"></script>
<script src="../../../../resources/testharnessreport.js"></script>
<div id=log></div>
<script src="../../../../html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.js"></script>

View file

@ -0,0 +1,31 @@
// document.open() bails out early if there is an active parser with non-zero
// script nesting level or if a load was aborted while there was an active
// parser. window.stop() aborts the current parser, so once it has been called
// while a parser is active, document.open() will no longer do anything to that
// document,
window.handlers = {};
async_test(t => {
const frame = document.body.appendChild(document.createElement("iframe"));
t.add_cleanup(() => frame.remove());
frame.src = "resources/aborted-parser-frame.html";
window.handlers.afterOpen = t.step_func_done(() => {
const openCalled = frame.contentDocument.childNodes.length === 0;
assert_false(openCalled, "child document should not be empty");
assert_equals(frame.contentDocument.querySelector("p").textContent,
"Text", "Should still have our paragraph");
});
}, "document.open() after parser is aborted");
async_test(t => {
const frame = document.body.appendChild(document.createElement("iframe"));
t.add_cleanup(() => frame.remove());
frame.src = "resources/aborted-parser-async-frame.html";
window.handlers.afterOpenAsync = t.step_func_done(() => {
const openCalled = frame.contentDocument.childNodes.length === 0;
assert_false(openCalled, "child document should not be empty");
assert_equals(frame.contentDocument.querySelector("p").textContent,
"Text", "Should still have our paragraph");
});
}, "async document.open() after parser is aborted");

View file

@ -0,0 +1,9 @@
<!doctype html>
<p>Text</p>
<script>
window.stop();
parent.step_timeout(() => {
document.open();
parent.handlers.afterOpenAsync();
}, 10);
</script>

View file

@ -0,0 +1,7 @@
<!doctype html>
<p>Text</p>
<script>
window.stop();
document.open();
parent.handlers.afterOpen();
</script>