Ver código fonte

LibWeb: Move "element sibling" getters to NonDocumentTypeChildNode

Here's another CRTP mixin since that's the best we can do with C++.
This prepares exposing these via IDL on Element and CharacterData.
Andreas Kling 5 anos atrás
pai
commit
d367044e67

+ 4 - 1
Libraries/LibWeb/DOM/CharacterData.h

@@ -28,10 +28,13 @@
 
 #include <AK/String.h>
 #include <LibWeb/DOM/Node.h>
+#include <LibWeb/DOM/NonDocumentTypeChildNode.h>
 
 namespace Web::DOM {
 
-class CharacterData : public Node {
+class CharacterData
+    : public Node
+    , public NonDocumentTypeChildNode<CharacterData> {
 public:
     virtual ~CharacterData() override;
 

+ 5 - 1
Libraries/LibWeb/DOM/Element.h

@@ -30,13 +30,17 @@
 #include <AK/String.h>
 #include <LibWeb/DOM/Attribute.h>
 #include <LibWeb/DOM/AttributeNames.h>
+#include <LibWeb/DOM/NonDocumentTypeChildNode.h>
 #include <LibWeb/DOM/ParentNode.h>
 #include <LibWeb/DOM/TagNames.h>
 #include <LibWeb/Layout/LayoutNode.h>
 
 namespace Web::DOM {
 
-class Element : public ParentNode {
+class Element
+    : public ParentNode
+    , public NonDocumentTypeChildNode<Element> {
+
 public:
     using WrapperType = Bindings::ElementWrapper;
 

+ 0 - 18
Libraries/LibWeb/DOM/Node.cpp

@@ -92,24 +92,6 @@ String Node::text_content() const
     return builder.to_string();
 }
 
-const Element* Node::next_element_sibling() const
-{
-    for (auto* node = next_sibling(); node; node = node->next_sibling()) {
-        if (node->is_element())
-            return static_cast<const Element*>(node);
-    }
-    return nullptr;
-}
-
-const Element* Node::previous_element_sibling() const
-{
-    for (auto* node = previous_sibling(); node; node = node->previous_sibling()) {
-        if (node->is_element())
-            return static_cast<const Element*>(node);
-    }
-    return nullptr;
-}
-
 RefPtr<LayoutNode> Node::create_layout_node(const CSS::StyleProperties*)
 {
     return nullptr;

+ 0 - 3
Libraries/LibWeb/DOM/Node.h

@@ -120,9 +120,6 @@ public:
 
     void set_layout_node(Badge<LayoutNode>, LayoutNode* layout_node) const { m_layout_node = layout_node; }
 
-    const Element* previous_element_sibling() const;
-    const Element* next_element_sibling() const;
-
     virtual bool is_child_allowed(const Node&) const { return true; }
 
     bool needs_style_update() const { return m_needs_style_update; }

+ 63 - 0
Libraries/LibWeb/DOM/NonDocumentTypeChildNode.h

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Forward.h>
+#include <LibWeb/Forward.h>
+#include <LibWeb/TreeNode.h>
+
+namespace Web::DOM {
+
+template<typename NodeType>
+class NonDocumentTypeChildNode {
+public:
+    Element* previous_element_sibling()
+    {
+        for (auto* sibling = static_cast<NodeType*>(this)->previous_sibling(); sibling; sibling = sibling->previous_sibling()) {
+            if (is<Element>(*sibling))
+                return downcast<Element>(sibling);
+        }
+        return nullptr;
+    }
+
+    Element* next_element_sibling()
+    {
+        for (auto* sibling = static_cast<NodeType*>(this)->next_sibling(); sibling; sibling = sibling->next_sibling()) {
+            if (is<Element>(*sibling))
+                return downcast<Element>(sibling);
+        }
+        return nullptr;
+    }
+
+    const Element* previous_element_sibling() const { return const_cast<NonDocumentTypeChildNode*>(this)->previous_element_sibling(); }
+    const Element* next_element_sibling() const { return const_cast<NonDocumentTypeChildNode*>(this)->next_element_sibling(); }
+
+protected:
+    NonDocumentTypeChildNode() { }
+};
+
+}