From 660ec504ca4707ee02e17fdc21a8472defbb0fd2 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 28 Mar 2020 09:12:13 +0100 Subject: [PATCH] LibWeb: Move get_element_by_id() to a NonElementParentNode mixin class This matches the current version of the DOM spec. And since C++ doesn't have mixins this is actually a CRTP class. --- Libraries/LibWeb/DOM/Document.cpp | 13 ----- Libraries/LibWeb/DOM/Document.h | 6 ++- Libraries/LibWeb/DOM/DocumentFragment.h | 5 +- Libraries/LibWeb/DOM/NonElementParentNode.h | 59 +++++++++++++++++++++ Libraries/LibWeb/HtmlView.cpp | 2 +- 5 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 Libraries/LibWeb/DOM/NonElementParentNode.h diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 0816775695..c95128a5e8 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -295,19 +295,6 @@ void Document::set_hovered_node(Node* node) invalidate_style(); } -const Element* Document::get_element_by_id(const String& id) const -{ - const Element* found_element = nullptr; - for_each_in_subtree_of_type([&](auto& element) { - if (element.attribute("id") == id) { - found_element = &element; - return IterationDecision::Break; - } - return IterationDecision::Continue; - }); - return found_element; -} - Vector Document::get_elements_by_name(const String& name) const { Vector elements; diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index c80f6dfe98..dab8e4db0f 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -37,6 +37,7 @@ #include #include #include +#include #include namespace Web { @@ -50,7 +51,9 @@ class LayoutNode; class StyleResolver; class StyleSheet; -class Document : public ParentNode { +class Document + : public ParentNode + , public NonElementParentNode { public: using WrapperType = Bindings::DocumentWrapper; @@ -119,7 +122,6 @@ public: void schedule_style_update(); - const Element* get_element_by_id(const String&) const; Vector get_elements_by_name(const String&) const; const String& source() const { return m_source; } diff --git a/Libraries/LibWeb/DOM/DocumentFragment.h b/Libraries/LibWeb/DOM/DocumentFragment.h index 7b4f6acf28..d7e35b9c53 100644 --- a/Libraries/LibWeb/DOM/DocumentFragment.h +++ b/Libraries/LibWeb/DOM/DocumentFragment.h @@ -27,11 +27,14 @@ #pragma once #include +#include #include namespace Web { -class DocumentFragment : public ParentNode { +class DocumentFragment + : public ParentNode + , public NonElementParentNode { public: DocumentFragment(Document& document) : ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE) diff --git a/Libraries/LibWeb/DOM/NonElementParentNode.h b/Libraries/LibWeb/DOM/NonElementParentNode.h new file mode 100644 index 0000000000..1b06098846 --- /dev/null +++ b/Libraries/LibWeb/DOM/NonElementParentNode.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 +#include +#include + +namespace Web { + +template +class NonElementParentNode { +public: + const Element* get_element_by_id(const FlyString& id) const + { + const Element* found_element = nullptr; + static_cast(this)->template for_each_in_subtree_of_type([&](auto& element) { + if (element.attribute("id") == id) { + found_element = &element; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + return found_element; + } + Element* get_element_by_id(const FlyString& id) + { + return const_cast(const_cast(this)->get_element_by_id(id)); + } + +protected: + NonElementParentNode() {} +}; + +} diff --git a/Libraries/LibWeb/HtmlView.cpp b/Libraries/LibWeb/HtmlView.cpp index 45b643dff1..c4224a9f7e 100644 --- a/Libraries/LibWeb/HtmlView.cpp +++ b/Libraries/LibWeb/HtmlView.cpp @@ -382,7 +382,7 @@ void HtmlView::scroll_to_anchor(const StringView& name) if (!document()) return; - auto* element = document()->get_element_by_id(name); + const auto* element = document()->get_element_by_id(name); if (!element) { auto candidates = document()->get_elements_by_name(name); for (auto* candidate : candidates) {