diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp index d779dabce8..5bf12f9665 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.cpp @@ -25,6 +25,13 @@ HTMLTableElement::HTMLTableElement(DOM::Document& document, DOM::QualifiedName q HTMLTableElement::~HTMLTableElement() = default; +void HTMLTableElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_rows); + visitor.visit(m_t_bodies); +} + void HTMLTableElement::apply_presentational_hints(CSS::StyleProperties& style) const { for_each_attribute([&](auto& name, auto& value) { @@ -221,11 +228,17 @@ void HTMLTableElement::delete_t_foot() } } +// https://html.spec.whatwg.org/multipage/tables.html#dom-table-tbodies JS::NonnullGCPtr HTMLTableElement::t_bodies() { - return DOM::HTMLCollection::create(*this, [](DOM::Element const& element) { - return element.local_name() == TagNames::tbody; - }); + // The tBodies attribute must return an HTMLCollection rooted at the table node, + // whose filter matches only tbody elements that are children of the table element. + if (!m_t_bodies) { + m_t_bodies = DOM::HTMLCollection::create(*this, [](DOM::Element const& element) { + return element.local_name() == TagNames::tbody; + }); + } + return *m_t_bodies; } JS::NonnullGCPtr HTMLTableElement::create_t_body() @@ -252,6 +265,7 @@ JS::NonnullGCPtr HTMLTableElement::create_t_body() return static_cast(*tbody); } +// https://html.spec.whatwg.org/multipage/tables.html#dom-table-rows JS::NonnullGCPtr HTMLTableElement::rows() { HTMLTableElement* table_node = this; @@ -261,23 +275,26 @@ JS::NonnullGCPtr HTMLTableElement::rows() // still in tree order. // How do you sort HTMLCollection? - return DOM::HTMLCollection::create(*this, [table_node](DOM::Element const& element) { - // Only match TR elements which are: - // * children of the table element - // * children of the thead, tbody, or tfoot elements that are themselves children of the table element - if (!is(element)) { + if (!m_rows) { + m_rows = DOM::HTMLCollection::create(*this, [table_node](DOM::Element const& element) { + // Only match TR elements which are: + // * children of the table element + // * children of the thead, tbody, or tfoot elements that are themselves children of the table element + if (!is(element)) { + return false; + } + if (element.parent_element() == table_node) + return true; + + if (element.parent_element() && (element.parent_element()->local_name() == TagNames::thead || element.parent_element()->local_name() == TagNames::tbody || element.parent_element()->local_name() == TagNames::tfoot) + && element.parent()->parent() == table_node) { + return true; + } + return false; - } - if (element.parent_element() == table_node) - return true; - - if (element.parent_element() && (element.parent_element()->local_name() == TagNames::thead || element.parent_element()->local_name() == TagNames::tbody || element.parent_element()->local_name() == TagNames::tfoot) - && element.parent()->parent() == table_node) { - return true; - } - - return false; - }); + }); + } + return *m_rows; } WebIDL::ExceptionOr> HTMLTableElement::insert_row(long index) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h index e18dd4058b..d9fa4e9e9f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h @@ -45,7 +45,12 @@ public: private: HTMLTableElement(DOM::Document&, DOM::QualifiedName); + virtual void visit_edges(Cell::Visitor&) override; + virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + + JS::GCPtr mutable m_rows; + JS::GCPtr mutable m_t_bodies; }; }