diff --git a/Userland/Libraries/LibWeb/DOM/Document.idl b/Userland/Libraries/LibWeb/DOM/Document.idl index ef5cb53e28..66c6bf8766 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.idl +++ b/Userland/Libraries/LibWeb/DOM/Document.idl @@ -64,6 +64,8 @@ interface Document : Node { Element? querySelector(DOMString selectors); ArrayFromVector querySelectorAll(DOMString selectors); + [SameObject] readonly attribute HTMLCollection children; + // FIXME: These should all come from a GlobalEventHandlers mixin attribute EventHandler onabort; attribute EventHandler onauxclick; diff --git a/Userland/Libraries/LibWeb/DOM/DocumentFragment.idl b/Userland/Libraries/LibWeb/DOM/DocumentFragment.idl index 55f336dda4..666f6007ec 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentFragment.idl +++ b/Userland/Libraries/LibWeb/DOM/DocumentFragment.idl @@ -12,4 +12,6 @@ interface DocumentFragment : Node { Element? querySelector(DOMString selectors); ArrayFromVector querySelectorAll(DOMString selectors); + [SameObject] readonly attribute HTMLCollection children; + }; diff --git a/Userland/Libraries/LibWeb/DOM/Element.idl b/Userland/Libraries/LibWeb/DOM/Element.idl index 031e8d94d4..e791e9a88d 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.idl +++ b/Userland/Libraries/LibWeb/DOM/Element.idl @@ -31,4 +31,6 @@ interface Element : Node { Element? querySelector(DOMString selectors); ArrayFromVector querySelectorAll(DOMString selectors); + + [SameObject] readonly attribute HTMLCollection children; }; diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp index f2136a1662..a13f29f647 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -75,4 +76,15 @@ u32 ParentNode::child_element_count() const return count; } +// https://dom.spec.whatwg.org/#dom-parentnode-children +NonnullRefPtr ParentNode::children() +{ + // The children getter steps are to return an HTMLCollection collection rooted at this matching only element children. + // FIXME: This should return the same HTMLCollection object every time, + // but that would cause a reference cycle since HTMLCollection refs the root. + return HTMLCollection::create(*this, [this](Element const& element) { + return is_parent_of(element); + }); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.h b/Userland/Libraries/LibWeb/DOM/ParentNode.h index d977cc8f7d..fbbe4e0c3d 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.h +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.h @@ -25,6 +25,8 @@ public: ExceptionOr> query_selector(StringView); ExceptionOr> query_selector_all(StringView); + NonnullRefPtr children(); + protected: ParentNode(Document& document, NodeType type) : Node(document, type) diff --git a/Userland/Libraries/LibWeb/TreeNode.h b/Userland/Libraries/LibWeb/TreeNode.h index 466e8ef517..1fd4ef135a 100644 --- a/Userland/Libraries/LibWeb/TreeNode.h +++ b/Userland/Libraries/LibWeb/TreeNode.h @@ -398,6 +398,15 @@ public: return nullptr; } + bool is_parent_of(T const& other) const + { + for (auto* child = first_child(); child; child = child->next_sibling()) { + if (&other == child) + return true; + } + return false; + } + ~TreeNode() { VERIFY(!m_parent);