diff --git a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp index 08200a38f0..026f8f0733 100644 --- a/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp +++ b/Libraries/LibWeb/Parser/HTMLDocumentParser.cpp @@ -400,10 +400,43 @@ void HTMLDocumentParser::handle_after_after_body(HTMLToken& token) void HTMLDocumentParser::reconstruct_the_active_formatting_elements() { + // FIXME: This needs to care about "markers" + if (m_list_of_active_formatting_elements.is_empty()) return; - ASSERT_NOT_REACHED(); + if (m_stack_of_open_elements.contains(m_list_of_active_formatting_elements.last())) + return; + + ssize_t index = m_list_of_active_formatting_elements.size() - 1; + RefPtr entry = m_list_of_active_formatting_elements.at(index); + +Rewind: + if (m_list_of_active_formatting_elements.size() == 1) { + goto Create; + } + + --index; + entry = m_list_of_active_formatting_elements.at(index); + + if (!m_stack_of_open_elements.contains(*entry)) + goto Rewind; + +Advance: + ++index; + entry = m_list_of_active_formatting_elements.at(index); + +Create: + // FIXME: Hold on to the real token! + HTMLToken fake_token; + fake_token.m_type = HTMLToken::Type::StartTag; + fake_token.m_tag.tag_name.append(entry->tag_name()); + auto new_element = insert_html_element(fake_token); + + m_list_of_active_formatting_elements.ptr_at(index) = *new_element; + + if (index != (ssize_t)m_list_of_active_formatting_elements.size() - 1) + goto Advance; } void HTMLDocumentParser::handle_in_body(HTMLToken& token) @@ -535,6 +568,27 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token) return; } + if (token.is_end_tag()) { + RefPtr node; + for (ssize_t i = m_stack_of_open_elements.elements().size() - 1; i >= 0; --i) { + node = m_stack_of_open_elements.elements()[i]; + if (node->tag_name() == token.tag_name()) { + generate_implied_end_tags(token.tag_name()); + if (node != current_node()) { + // It's a parse error + TODO(); + } + while (¤t_node() != node) { + m_stack_of_open_elements.pop(); + } + m_stack_of_open_elements.pop(); + break; + } + // FIXME: Handle special elements! + } + return; + } + ASSERT_NOT_REACHED(); } diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp index 1c99624446..506bc88d00 100644 --- a/Libraries/LibWeb/Parser/StackOfOpenElements.cpp +++ b/Libraries/LibWeb/Parser/StackOfOpenElements.cpp @@ -33,4 +33,13 @@ bool StackOfOpenElements::has_in_button_scope(const FlyString& tag_name) const return has_in_scope_impl(tag_name, list); } +bool StackOfOpenElements::contains(const Element& element) const +{ + for (auto& element_on_stack : m_elements) { + if (&element == &element_on_stack) + return true; + } + return false; +} + } diff --git a/Libraries/LibWeb/Parser/StackOfOpenElements.h b/Libraries/LibWeb/Parser/StackOfOpenElements.h index 98ac36434b..8403f36158 100644 --- a/Libraries/LibWeb/Parser/StackOfOpenElements.h +++ b/Libraries/LibWeb/Parser/StackOfOpenElements.h @@ -47,6 +47,10 @@ public: bool has_in_scope(const FlyString& tag_name) const; bool has_in_button_scope(const FlyString& tag_name) const; + bool contains(const Element&) const; + + const NonnullRefPtrVector& elements() const { return m_elements; } + private: bool has_in_scope_impl(const FlyString& tag_name, const Vector&) const;