LibWeb: Only wait for document to be ready for scripts if executing one

HTML fragments are parsed with a temporary HTML document that never has
its flag set to say that it is ready to have scripts executed. For these
fragments, in the HTMLParser, these scripts are prepared, but
execute_script is never called on them.

This results in the HTMLParser waiting forever on the document to be
ready to have scripts executed.

To fix this, only wait for the document to be ready if we are definitely
going to execute a script.

This fixes a hang processing the HTML in the attached test, as seen on:
https://github.com/SerenityOS/serenity

Fixes: #22735
This commit is contained in:
Shannon Booth 2024-01-14 15:59:38 +13:00 committed by Sam Atkins
parent 48a3a02238
commit 4135c3885c
4 changed files with 16 additions and 7 deletions

View file

@ -0,0 +1 @@
PASS

View file

@ -0,0 +1,9 @@
<script src="../include.js"></script>
<div id=container></div>
<script type="text/javascript">
test(() => {
let container = document.getElementById("container");
container.innerHTML = '<script><\/script>';
println("PASS");
});
</script>

View file

@ -71,6 +71,11 @@ void HTMLScriptElement::begin_delaying_document_load_event(DOM::Document& docume
// https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-block
void HTMLScriptElement::execute_script()
{
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#read-html
// Before any script execution occurs, the user agent must wait for scripts may run for the newly-created document to be true for document.
if (!m_document->ready_to_run_scripts())
main_thread_event_loop().spin_until([&] { return m_document->ready_to_run_scripts(); });
// 1. Let document be el's node document.
JS::NonnullGCPtr<DOM::Document> document = this->document();

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2023-2024, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -2729,12 +2729,6 @@ void HTMLParser::handle_text(HTMLToken& token)
// -> An end tag whose tag name is "script"
if (token.is_end_tag() && token.tag_name() == HTML::TagNames::script) {
// https://html.spec.whatwg.org/multipage/document-lifecycle.html#read-html
// Before any script execution occurs, the user agent must wait for scripts may run for the newly-created document to be true for document.
if (!m_document->ready_to_run_scripts()) {
main_thread_event_loop().spin_until([&] { return m_document->ready_to_run_scripts(); });
}
// FIXME: If the active speculative HTML parser is null and the JavaScript execution context stack is empty, then perform a microtask checkpoint.
// Non-standard: Make sure the <script> element has up-to-date text content before preparing the script.