summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-27 23:01:04 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-27 23:02:03 +0200
commit4c9c6b3a7bf58343bf4da116ffbf87e4cadb623c (patch)
tree5374e65f4065ee6044955b2bc36cd861e97e4992 /Libraries
parent2cb50f6750d07fad48e8d51bf12f2ca144ff2ccd (diff)
downloadserenity-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.cpp5
-rw-r--r--Libraries/LibWeb/DOM/Document.h2
-rw-r--r--Libraries/LibWeb/DOM/HTMLScriptElement.cpp5
-rw-r--r--Libraries/LibWeb/DOM/HTMLScriptElement.h3
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.cpp40
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.h2
-rw-r--r--Libraries/LibWeb/Parser/HTMLTokenizer.h6
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 };
};
+
}