summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb/Parser
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-06-03 21:53:08 +0200
committerAndreas Kling <kling@serenityos.org>2020-06-03 21:53:08 +0200
commitc40de9275a9850034362877ccaf7a1a979960221 (patch)
treef7f6f9af52d5eacc2af0a8efbb4cd4c4e1d60543 /Libraries/LibWeb/Parser
parent214982026080f411ea38e1dbb1a51186d10362fe (diff)
downloadserenity-c40de9275a9850034362877ccaf7a1a979960221.zip
LibWeb: Buffer text node character insertions in the new parser
Instead of appending character-at-a-time, we now buffer character insertions in a StringBuilder, and flush them to the relevant node whenever we start inserting into a new node (and when parsing ends.)
Diffstat (limited to 'Libraries/LibWeb/Parser')
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.cpp47
-rw-r--r--Libraries/LibWeb/Parser/HTMLDocumentParser.h5
2 files changed, 38 insertions, 14 deletions
diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
index c71cc8ded1..d9a18c04a3 100644
--- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
+++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
@@ -78,6 +78,8 @@ void HTMLDocumentParser::run(const URL& url)
}
}
+ flush_character_insertions();
+
// "The end"
auto scripts_to_execute_when_parsing_has_finished = m_document->take_scripts_to_execute_when_parsing_has_finished({});
@@ -431,24 +433,41 @@ void HTMLDocumentParser::parse_generic_raw_text_element(HTMLToken& token)
m_insertion_mode = InsertionMode::Text;
}
-void HTMLDocumentParser::insert_character(u32 data)
+Text* HTMLDocumentParser::find_character_insertion_node()
{
auto adjusted_insertion_location = find_appropriate_place_for_inserting_node();
if (adjusted_insertion_location->is_document())
+ return nullptr;
+ if (adjusted_insertion_location->last_child() && adjusted_insertion_location->last_child()->is_text())
+ return to<Text>(adjusted_insertion_location->last_child());
+ auto new_text_node = adopt(*new Text(document(), ""));
+ adjusted_insertion_location->append_child(new_text_node);
+ return new_text_node;
+}
+
+void HTMLDocumentParser::flush_character_insertions()
+{
+ if (m_character_insertion_builder.is_empty())
return;
- if (adjusted_insertion_location->last_child() && adjusted_insertion_location->last_child()->is_text()) {
- auto& existing_text_node = to<Text>(*adjusted_insertion_location->last_child());
- StringBuilder builder;
- builder.append(existing_text_node.data());
- builder.append(Utf32View { &data, 1 });
- existing_text_node.set_data(builder.to_string());
+ m_character_insertion_node->set_data(m_character_insertion_builder.to_string());
+ m_character_insertion_builder.clear();
+}
+
+void HTMLDocumentParser::insert_character(u32 data)
+{
+ auto node = find_character_insertion_node();
+ if (node == m_character_insertion_node) {
+ m_character_insertion_builder.append(Utf32View { &data, 1 });
return;
}
- auto new_text_node = adopt(*new Text(document(), ""));
- adjusted_insertion_location->append_child(new_text_node);
- StringBuilder builder;
- builder.append(Utf32View { &data, 1 });
- new_text_node->set_data(builder.to_string());
+ if (!m_character_insertion_node) {
+ m_character_insertion_node = node;
+ m_character_insertion_builder.append(Utf32View { &data, 1 });
+ return;
+ }
+ flush_character_insertions();
+ m_character_insertion_node = node;
+ m_character_insertion_builder.append(Utf32View { &data, 1 });
}
void HTMLDocumentParser::handle_after_head(HTMLToken& token)
@@ -836,8 +855,8 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token)
if (token.is_start_tag() && token.tag_name() == "body") {
PARSE_ERROR();
if (m_stack_of_open_elements.elements().size() == 1
- || node_before_current_node().tag_name() != "body"
- || m_stack_of_open_elements.contains("template")) {
+ || node_before_current_node().tag_name() != "body"
+ || m_stack_of_open_elements.contains("template")) {
return;
}
m_frameset_ok = false;
diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.h b/Libraries/LibWeb/Parser/HTMLDocumentParser.h
index 0a334bf31c..199129606d 100644
--- a/Libraries/LibWeb/Parser/HTMLDocumentParser.h
+++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.h
@@ -105,6 +105,8 @@ private:
bool stack_of_open_elements_has_element_with_tag_name_in_scope(const FlyString& tag_name);
NonnullRefPtr<Element> create_element_for(HTMLToken&);
RefPtr<Node> find_appropriate_place_for_inserting_node();
+ Text* find_character_insertion_node();
+ void flush_character_insertions();
RefPtr<Element> insert_html_element(HTMLToken&);
Element& current_node();
Element& node_before_current_node();
@@ -153,6 +155,9 @@ private:
RefPtr<HTMLFormElement> m_form_element;
Vector<HTMLToken> m_pending_table_character_tokens;
+
+ RefPtr<Text> m_character_insertion_node;
+ StringBuilder m_character_insertion_builder;
};
}