diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp index 821ee3fc4e..e524fe0edd 100644 --- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp +++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp @@ -817,7 +817,16 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token) } if (token.is_start_tag() && token.tag_name() == "form") { - TODO(); + if (m_form_element && m_stack_of_open_elements.contains("template")) { + PARSE_ERROR(); + return; + } + if (m_stack_of_open_elements.has_in_button_scope("p")) + close_a_p_element(); + auto element = insert_html_element(token); + if (!m_stack_of_open_elements.contains("template")) + m_form_element = to(*element); + return; } if (token.is_start_tag() && token.tag_name() == "li") { @@ -887,7 +896,22 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token) } if (token.is_end_tag() && token.tag_name() == "form") { - TODO(); + if (!m_stack_of_open_elements.contains("template")) { + auto node = m_form_element; + m_form_element = nullptr; + if (!node || m_stack_of_open_elements.has_in_scope(*node)) { + PARSE_ERROR(); + return; + } + generate_implied_end_tags(); + if (¤t_node() != node) { + PARSE_ERROR(); + } + m_stack_of_open_elements.elements().remove_first_matching([&](auto& entry) { return entry.ptr() == node.ptr(); }); + } else { + TODO(); + } + return; } if (token.is_end_tag() && token.tag_name() == "p") { diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp index 807fc40c0e..5048b83fc8 100644 --- a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp +++ b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp @@ -103,6 +103,15 @@ bool StackOfOpenElements::contains(const Element& element) const return false; } +bool StackOfOpenElements::contains(const FlyString& tag_name) const +{ + for (auto& element_on_stack : m_elements) { + if (element_on_stack.tag_name() == tag_name) + return true; + } + return false; +} + void StackOfOpenElements::pop_until_an_element_with_tag_name_has_been_popped(const FlyString& tag_name) { while (m_elements.last().tag_name() != tag_name) diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.h b/Libraries/LibWeb/Parser/StackOfOpenElements.h index d6dbd18d27..6fb4455def 100644 --- a/Libraries/LibWeb/Parser/StackOfOpenElements.h +++ b/Libraries/LibWeb/Parser/StackOfOpenElements.h @@ -55,6 +55,7 @@ public: bool has_in_scope(const Element&) const; bool contains(const Element&) const; + bool contains(const FlyString& tag_name) const; const NonnullRefPtrVector& elements() const { return m_elements; } NonnullRefPtrVector& elements() { return m_elements; }