diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-27 23:01:04 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-27 23:02:03 +0200 |
commit | 4c9c6b3a7bf58343bf4da116ffbf87e4cadb623c (patch) | |
tree | 5374e65f4065ee6044955b2bc36cd861e97e4992 /Libraries | |
parent | 2cb50f6750d07fad48e8d51bf12f2ca144ff2ccd (diff) | |
download | serenity-4c9c6b3a7bf58343bf4da116ffbf87e4cadb623c.zip |
LibWeb: Bring up basic external script execution in the new parser
This only works in some narrow cases, but should be enough for our own
welcome.html at least. :^)
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibWeb/DOM/Document.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLScriptElement.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLScriptElement.h | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/Parser/HTMLDocumentParser.cpp | 40 | ||||
-rw-r--r-- | Libraries/LibWeb/Parser/HTMLDocumentParser.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Parser/HTMLTokenizer.h | 6 |
7 files changed, 60 insertions, 3 deletions
diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 78f0f8d7c0..2b2d242f13 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -424,4 +424,9 @@ void Document::set_pending_parsing_blocking_script(Badge<HTMLScriptElement>, HTM m_pending_parsing_blocking_script = script; } +NonnullRefPtr<HTMLScriptElement> Document::take_pending_parsing_blocking_script(Badge<HTMLDocumentParser>) +{ + return m_pending_parsing_blocking_script.release_nonnull(); +} + } diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 8829171c7a..baf1418187 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -130,6 +130,8 @@ public: NonnullRefPtr<Text> create_text_node(const String& data); void set_pending_parsing_blocking_script(Badge<HTMLScriptElement>, HTMLScriptElement*); + HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; } + NonnullRefPtr<HTMLScriptElement> take_pending_parsing_blocking_script(Badge<HTMLDocumentParser>); private: virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override; diff --git a/Libraries/LibWeb/DOM/HTMLScriptElement.cpp b/Libraries/LibWeb/DOM/HTMLScriptElement.cpp index f66a96d5f7..df9e1df5f6 100644 --- a/Libraries/LibWeb/DOM/HTMLScriptElement.cpp +++ b/Libraries/LibWeb/DOM/HTMLScriptElement.cpp @@ -189,7 +189,8 @@ void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>) // FIXME: Check classic vs. module script type - ResourceLoader::the().load(url, [this, url](auto& data, auto&) { + // FIXME: This load should be made asynchronous and the parser should spin an event loop etc. + ResourceLoader::the().load_sync(url, [this, url](auto& data, auto&) { if (data.is_null()) { dbg() << "HTMLScriptElement: Failed to load " << url; return; @@ -212,6 +213,7 @@ void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>) } else if (has_attribute("src") && m_parser_inserted && !has_attribute("async")) { + document().set_pending_parsing_blocking_script({}, this); when_the_script_is_ready([this] { m_ready_to_be_parser_executed = true; @@ -234,6 +236,7 @@ void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>) void HTMLScriptElement::script_became_ready() { + m_script_ready = true; if (!m_script_ready_callback) return; m_script_ready_callback(); diff --git a/Libraries/LibWeb/DOM/HTMLScriptElement.h b/Libraries/LibWeb/DOM/HTMLScriptElement.h index 96c65a173c..f5bfe82286 100644 --- a/Libraries/LibWeb/DOM/HTMLScriptElement.h +++ b/Libraries/LibWeb/DOM/HTMLScriptElement.h @@ -40,15 +40,16 @@ public: virtual void children_changed() override; bool is_non_blocking() const { return m_non_blocking; } + bool is_ready_to_be_parser_executed() const { return m_ready_to_be_parser_executed; } void set_parser_document(Badge<HTMLDocumentParser>, Document&); void set_non_blocking(Badge<HTMLDocumentParser>, bool); void prepare_script(Badge<HTMLDocumentParser>); + void execute_script(); private: void script_became_ready(); void when_the_script_is_ready(Function<void()>); - void execute_script(); WeakPtr<Document> m_parser_document; WeakPtr<Document> m_preparation_time_document; diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp index 591e781d88..24f7e967c5 100644 --- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp +++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp @@ -704,8 +704,48 @@ void HTMLDocumentParser::handle_text(HTMLToken& token) if (script_nesting_level() == 0) m_parser_pause_flag = false; // FIXME: Handle tokenizer insertion point stuff here too. + + while (document().pending_parsing_blocking_script()) { + if (script_nesting_level() != 0) { + m_parser_pause_flag = true; + // FIXME: Abort the processing of any nested invocations of the tokenizer, + // yielding control back to the caller. (Tokenization will resume when + // the caller returns to the "outer" tree construction stage.) + TODO(); + } else { + auto the_script = document().take_pending_parsing_blocking_script({}); + m_tokenizer.set_blocked(true); + + // FIXME: If the parser's Document has a style sheet that is blocking scripts + // or the script's "ready to be parser-executed" flag is not set: + // spin the event loop until the parser's Document has no style sheet + // that is blocking scripts and the script's "ready to be parser-executed" + // flag is set. + + ASSERT(the_script->is_ready_to_be_parser_executed()); + + if (m_aborted) + return; + + m_tokenizer.set_blocked(false); + + // FIXME: Handle tokenizer insertion point stuff here too. + + ASSERT(script_nesting_level() == 0); + increment_script_nesting_level(); + + the_script->execute_script(); + + decrement_script_nesting_level(); + ASSERT(script_nesting_level() == 0); + m_parser_pause_flag = false; + + // FIXME: Handle tokenizer insertion point stuff here too. + } + } return; } + if (token.is_end_tag()) { m_stack_of_open_elements.pop(); m_insertion_mode = m_original_insertion_mode; diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.h b/Libraries/LibWeb/Parser/HTMLDocumentParser.h index a57826b00e..6eeff69220 100644 --- a/Libraries/LibWeb/Parser/HTMLDocumentParser.h +++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.h @@ -121,7 +121,7 @@ private: bool m_parsing_fragment { false }; bool m_scripting_enabled { true }; bool m_invoked_via_document_write { false }; - + bool m_aborted { false }; bool m_parser_pause_flag { false }; size_t m_script_nesting_level { 0 }; diff --git a/Libraries/LibWeb/Parser/HTMLTokenizer.h b/Libraries/LibWeb/Parser/HTMLTokenizer.h index f3787705ea..42efde3400 100644 --- a/Libraries/LibWeb/Parser/HTMLTokenizer.h +++ b/Libraries/LibWeb/Parser/HTMLTokenizer.h @@ -130,6 +130,9 @@ public: void switch_to(Badge<HTMLDocumentParser>, State new_state); + void set_blocked(bool b) { m_blocked = b; } + bool is_blocked() const { return m_blocked; } + private: Optional<u32> next_codepoint(); Optional<u32> peek_codepoint(size_t offset) const; @@ -172,5 +175,8 @@ private: Queue<HTMLToken> m_queued_tokens; u32 m_character_reference_code { 0 }; + + bool m_blocked { false }; }; + } |