瀏覽代碼

LibWeb: Move element_child_count to ParentNode and add its IDL attribute

I initially had it in Node just because, but then saw it was part of
ParentNode in the spec.
Luke 4 年之前
父節點
當前提交
83d2c3f2f5

+ 8 - 6
Userland/Libraries/LibWeb/DOM/Document.idl

@@ -18,12 +18,6 @@ interface Document : Node {
     ArrayFromVector getElementsByTagName(DOMString tagName);
     ArrayFromVector getElementsByClassName(DOMString className);
 
-    readonly attribute Element? firstElementChild;
-    readonly attribute Element? lastElementChild;
-
-    Element? querySelector(DOMString selectors);
-    ArrayFromVector querySelectorAll(DOMString selectors);
-
     Element createElement(DOMString tagName);
     Element createElementNS(DOMString? namespace, DOMString qualifiedName);
     DocumentFragment createDocumentFragment();
@@ -48,6 +42,14 @@ interface Document : Node {
 
     attribute DOMString title;
 
+    // FIXME: These should all come from a ParentNode mixin
+    readonly attribute Element? firstElementChild;
+    readonly attribute Element? lastElementChild;
+    readonly attribute unsigned long childElementCount;
+
+    Element? querySelector(DOMString selectors);
+    ArrayFromVector querySelectorAll(DOMString selectors);
+
     // FIXME: These should all come from a GlobalEventHandlers mixin
     attribute EventHandler onabort;
     attribute EventHandler onauxclick;

+ 2 - 0
Userland/Libraries/LibWeb/DOM/DocumentFragment.idl

@@ -2,8 +2,10 @@ interface DocumentFragment : Node {
 
     Element? getElementById(DOMString id);
 
+    // FIXME: These should all come from a ParentNode mixin
     readonly attribute Element? firstElementChild;
     readonly attribute Element? lastElementChild;
+    readonly attribute unsigned long childElementCount;
 
     Element? querySelector(DOMString selectors);
     ArrayFromVector querySelectorAll(DOMString selectors);

+ 8 - 6
Userland/Libraries/LibWeb/DOM/Element.idl

@@ -11,12 +11,6 @@ interface Element : Node {
     ArrayFromVector getElementsByTagName(DOMString tagName);
     ArrayFromVector getElementsByClassName(DOMString className);
 
-    readonly attribute Element? firstElementChild;
-    readonly attribute Element? lastElementChild;
-
-    Element? querySelector(DOMString selectors);
-    ArrayFromVector querySelectorAll(DOMString selectors);
-
     [LegacyNullToEmptyString] attribute DOMString innerHTML;
     [Reflect] attribute DOMString id;
     [Reflect=class] attribute DOMString className;
@@ -25,4 +19,12 @@ interface Element : Node {
     readonly attribute Element? previousElementSibling;
 
     [ImplementedAs=style_for_bindings] readonly attribute CSSStyleDeclaration style;
+
+    // FIXME: These should all come from a ParentNode mixin
+    readonly attribute Element? firstElementChild;
+    readonly attribute Element? lastElementChild;
+    readonly attribute unsigned long childElementCount;
+
+    Element? querySelector(DOMString selectors);
+    ArrayFromVector querySelectorAll(DOMString selectors);
 };

+ 1 - 11
Userland/Libraries/LibWeb/DOM/Node.cpp

@@ -204,7 +204,7 @@ ExceptionOr<void> Node::ensure_pre_insertion_validity(NonnullRefPtr<Node> node,
 
     if (is<Document>(this)) {
         if (is<DocumentFragment>(*node)) {
-            auto node_element_child_count = node->element_child_count();
+            auto node_element_child_count = downcast<DocumentFragment>(*node).child_element_count();
             if ((node_element_child_count > 1 || node->has_child_of_type<Text>())
                 || (node_element_child_count == 1 && (has_child_of_type<Element>() || is<DocumentType>(child.ptr()) /* FIXME: or child is non-null and a doctype is following child. */))) {
                 return DOM::HierarchyRequestError::create("Invalid node type for insertion");
@@ -497,14 +497,4 @@ bool Node::is_host_including_inclusive_ancestor_of(const Node& other) const
     return is_inclusive_ancestor_of(other) || (is<DocumentFragment>(other.root()) && downcast<DocumentFragment>(other.root())->host() && is_inclusive_ancestor_of(*downcast<DocumentFragment>(other.root())->host().ptr()));
 }
 
-size_t Node::element_child_count() const
-{
-    size_t count = 0;
-    for (auto* child = first_child(); child; child = child->next_sibling()) {
-        if (is<Element>(child))
-            ++count;
-    }
-    return count;
-}
-
 }

+ 0 - 2
Userland/Libraries/LibWeb/DOM/Node.h

@@ -175,8 +175,6 @@ public:
 
     bool is_host_including_inclusive_ancestor_of(const Node&) const;
 
-    size_t element_child_count() const;
-
 protected:
     Node(Document&, NodeType);
 

+ 11 - 0
Userland/Libraries/LibWeb/DOM/ParentNode.cpp

@@ -80,4 +80,15 @@ RefPtr<Element> ParentNode::last_element_child()
     return last_child_of_type<Element>();
 }
 
+// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
+u32 ParentNode::child_element_count() const
+{
+    u32 count = 0;
+    for (auto* child = first_child(); child; child = child->next_sibling()) {
+        if (is<Element>(child))
+            ++count;
+    }
+    return count;
+}
+
 }

+ 1 - 0
Userland/Libraries/LibWeb/DOM/ParentNode.h

@@ -40,6 +40,7 @@ public:
 
     RefPtr<Element> first_element_child();
     RefPtr<Element> last_element_child();
+    u32 child_element_count() const;
 
     RefPtr<Element> query_selector(const StringView&);
     NonnullRefPtrVector<Element> query_selector_all(const StringView&);