Browse Source

LibWeb: Switch to using AK::is and AK::downcast

Andreas Kling 5 năm trước cách đây
mục cha
commit
71556e39a4
73 tập tin đã thay đổi với 249 bổ sung433 xóa
  1. 6 6
      Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp
  2. 2 2
      Libraries/LibWeb/CSS/SelectorEngine.cpp
  3. 3 5
      Libraries/LibWeb/DOM/CharacterData.h
  4. 3 5
      Libraries/LibWeb/DOM/Comment.h
  5. 4 5
      Libraries/LibWeb/DOM/Document.h
  6. 3 5
      Libraries/LibWeb/DOM/DocumentFragment.h
  7. 3 5
      Libraries/LibWeb/DOM/DocumentType.h
  8. 3 3
      Libraries/LibWeb/DOM/Element.cpp
  9. 3 5
      Libraries/LibWeb/DOM/Element.h
  10. 6 6
      Libraries/LibWeb/DOM/Node.cpp
  11. 8 59
      Libraries/LibWeb/DOM/Node.h
  12. 4 0
      Libraries/LibWeb/DOM/ParentNode.h
  13. 3 5
      Libraries/LibWeb/DOM/Text.h
  14. 2 2
      Libraries/LibWeb/DOMTreeModel.cpp
  15. 6 6
      Libraries/LibWeb/Dump.cpp
  16. 3 3
      Libraries/LibWeb/Frame/EventHandler.cpp
  17. 2 2
      Libraries/LibWeb/Frame/Frame.cpp
  18. 3 5
      Libraries/LibWeb/HTML/HTMLAnchorElement.h
  19. 3 5
      Libraries/LibWeb/HTML/HTMLBRElement.h
  20. 3 5
      Libraries/LibWeb/HTML/HTMLBlinkElement.h
  21. 3 5
      Libraries/LibWeb/HTML/HTMLBodyElement.h
  22. 3 5
      Libraries/LibWeb/HTML/HTMLCanvasElement.h
  23. 3 5
      Libraries/LibWeb/HTML/HTMLElement.h
  24. 3 5
      Libraries/LibWeb/HTML/HTMLFontElement.h
  25. 1 1
      Libraries/LibWeb/HTML/HTMLFormElement.cpp
  26. 3 5
      Libraries/LibWeb/HTML/HTMLFormElement.h
  27. 3 5
      Libraries/LibWeb/HTML/HTMLHRElement.h
  28. 3 5
      Libraries/LibWeb/HTML/HTMLHeadElement.h
  29. 3 5
      Libraries/LibWeb/HTML/HTMLHtmlElement.h
  30. 3 5
      Libraries/LibWeb/HTML/HTMLIFrameElement.h
  31. 3 5
      Libraries/LibWeb/HTML/HTMLImageElement.h
  32. 1 1
      Libraries/LibWeb/HTML/HTMLInputElement.cpp
  33. 3 5
      Libraries/LibWeb/HTML/HTMLInputElement.h
  34. 3 5
      Libraries/LibWeb/HTML/HTMLLinkElement.h
  35. 3 5
      Libraries/LibWeb/HTML/HTMLObjectElement.h
  36. 3 5
      Libraries/LibWeb/HTML/HTMLScriptElement.h
  37. 1 1
      Libraries/LibWeb/HTML/HTMLStyleElement.cpp
  38. 3 6
      Libraries/LibWeb/HTML/HTMLStyleElement.h
  39. 3 5
      Libraries/LibWeb/HTML/HTMLTableCellElement.h
  40. 3 5
      Libraries/LibWeb/HTML/HTMLTableElement.h
  41. 3 5
      Libraries/LibWeb/HTML/HTMLTableRowElement.h
  42. 3 5
      Libraries/LibWeb/HTML/HTMLTitleElement.h
  43. 7 7
      Libraries/LibWeb/Layout/LayoutBlock.cpp
  44. 7 9
      Libraries/LibWeb/Layout/LayoutBlock.h
  45. 2 2
      Libraries/LibWeb/Layout/LayoutBox.cpp
  46. 3 5
      Libraries/LibWeb/Layout/LayoutBox.h
  47. 6 1
      Libraries/LibWeb/Layout/LayoutBreak.h
  48. 4 5
      Libraries/LibWeb/Layout/LayoutCanvas.h
  49. 1 1
      Libraries/LibWeb/Layout/LayoutDocument.cpp
  50. 3 6
      Libraries/LibWeb/Layout/LayoutDocument.h
  51. 3 5
      Libraries/LibWeb/Layout/LayoutFrame.h
  52. 2 2
      Libraries/LibWeb/Layout/LayoutImage.cpp
  53. 3 5
      Libraries/LibWeb/Layout/LayoutImage.h
  54. 5 5
      Libraries/LibWeb/Layout/LayoutNode.cpp
  55. 15 62
      Libraries/LibWeb/Layout/LayoutNode.h
  56. 5 7
      Libraries/LibWeb/Layout/LayoutReplaced.h
  57. 3 5
      Libraries/LibWeb/Layout/LayoutTable.h
  58. 1 1
      Libraries/LibWeb/Layout/LayoutTableCell.cpp
  59. 3 5
      Libraries/LibWeb/Layout/LayoutTableCell.h
  60. 3 5
      Libraries/LibWeb/Layout/LayoutTableRow.h
  61. 3 5
      Libraries/LibWeb/Layout/LayoutTableRowGroup.h
  62. 3 5
      Libraries/LibWeb/Layout/LayoutText.h
  63. 2 2
      Libraries/LibWeb/Layout/LayoutTreeBuilder.cpp
  64. 3 5
      Libraries/LibWeb/Layout/LayoutWidget.h
  65. 1 1
      Libraries/LibWeb/Layout/LineBox.cpp
  66. 3 3
      Libraries/LibWeb/Layout/LineBoxFragment.cpp
  67. 2 2
      Libraries/LibWeb/LayoutTreeModel.cpp
  68. 5 5
      Libraries/LibWeb/PageView.cpp
  69. 2 2
      Libraries/LibWeb/Painting/StackingContext.cpp
  70. 9 9
      Libraries/LibWeb/Parser/HTMLDocumentParser.cpp
  71. 5 8
      Libraries/LibWeb/SVG/SVGGraphicsElement.h
  72. 1 1
      Libraries/LibWeb/SVG/SVGSVGElement.cpp
  73. 1 9
      Libraries/LibWeb/TreeNode.h

+ 6 - 6
Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp

@@ -41,17 +41,17 @@ namespace Bindings {
 NodeWrapper* wrap(JS::GlobalObject& global_object, Node& node)
 {
     if (is<Document>(node))
-        return static_cast<NodeWrapper*>(wrap_impl(global_object, to<Document>(node)));
+        return static_cast<NodeWrapper*>(wrap_impl(global_object, downcast<Document>(node)));
     if (is<DocumentType>(node))
-        return static_cast<NodeWrapper*>(wrap_impl(global_object, to<DocumentType>(node)));
+        return static_cast<NodeWrapper*>(wrap_impl(global_object, downcast<DocumentType>(node)));
     if (is<HTMLCanvasElement>(node))
-        return static_cast<NodeWrapper*>(wrap_impl(global_object, to<HTMLCanvasElement>(node)));
+        return static_cast<NodeWrapper*>(wrap_impl(global_object, downcast<HTMLCanvasElement>(node)));
     if (is<HTMLImageElement>(node))
-        return static_cast<NodeWrapper*>(wrap_impl(global_object, to<HTMLImageElement>(node)));
+        return static_cast<NodeWrapper*>(wrap_impl(global_object, downcast<HTMLImageElement>(node)));
     if (is<HTMLElement>(node))
-        return static_cast<NodeWrapper*>(wrap_impl(global_object, to<HTMLElement>(node)));
+        return static_cast<NodeWrapper*>(wrap_impl(global_object, downcast<HTMLElement>(node)));
     if (is<Element>(node))
-        return static_cast<NodeWrapper*>(wrap_impl(global_object, to<Element>(node)));
+        return static_cast<NodeWrapper*>(wrap_impl(global_object, downcast<Element>(node)));
     return static_cast<NodeWrapper*>(wrap_impl(global_object, node));
 }
 

+ 2 - 2
Libraries/LibWeb/CSS/SelectorEngine.cpp

@@ -131,7 +131,7 @@ bool matches(const Selector& selector, int component_list_index, const Element&
         for (auto* ancestor = element.parent(); ancestor; ancestor = ancestor->parent()) {
             if (!is<Element>(*ancestor))
                 continue;
-            if (matches(selector, component_list_index - 1, to<Element>(*ancestor)))
+            if (matches(selector, component_list_index - 1, downcast<Element>(*ancestor)))
                 return true;
         }
         return false;
@@ -139,7 +139,7 @@ bool matches(const Selector& selector, int component_list_index, const Element&
         ASSERT(component_list_index != 0);
         if (!element.parent() || !is<Element>(*element.parent()))
             return false;
-        return matches(selector, component_list_index - 1, to<Element>(*element.parent()));
+        return matches(selector, component_list_index - 1, downcast<Element>(*element.parent()));
     case Selector::ComplexSelector::Relation::AdjacentSibling:
         ASSERT(component_list_index != 0);
         if (auto* sibling = element.previous_element_sibling())

+ 3 - 5
Libraries/LibWeb/DOM/CharacterData.h

@@ -47,10 +47,8 @@ private:
     String m_data;
 };
 
-template<>
-inline bool is<CharacterData>(const Node& node)
-{
-    return node.is_character_data();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::CharacterData)
+static bool is_type(const Web::Node& node) { return node.is_character_data(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/DOM/Comment.h

@@ -39,10 +39,8 @@ public:
     virtual FlyString node_name() const override { return "#comment"; }
 };
 
-template<>
-inline bool is<Comment>(const Node& node)
-{
-    return node.is_comment();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::Comment)
+static bool is_type(const Web::Node& node) { return node.is_comment(); }
+AK_END_TYPE_TRAITS()

+ 4 - 5
Libraries/LibWeb/DOM/Document.h

@@ -188,10 +188,9 @@ private:
     QuirksMode m_quirks_mode { QuirksMode::No };
 };
 
-template<>
-inline bool is<Document>(const Node& node)
-{
-    return node.is_document();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::Document)
+static bool is_type(const Web::Node& node) { return node.is_document(); }
+AK_END_TYPE_TRAITS()
+

+ 3 - 5
Libraries/LibWeb/DOM/DocumentFragment.h

@@ -44,10 +44,8 @@ public:
     virtual FlyString node_name() const override { return "#document-fragment"; }
 };
 
-template<>
-inline bool is<DocumentFragment>(const Node& node)
-{
-    return node.is_document_fragment();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::DocumentFragment)
+static bool is_type(const Web::Node& node) { return node.is_document_fragment(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/DOM/DocumentType.h

@@ -55,10 +55,8 @@ private:
     String m_system_id;
 };
 
-template<>
-inline bool is<DocumentType>(const Node& node)
-{
-    return node.type() == NodeType::DOCUMENT_TYPE_NODE;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::DocumentType)
+static bool is_type(const Web::Node& node) { return node.type() == Web::NodeType::DOCUMENT_TYPE_NODE; }
+AK_END_TYPE_TRAITS()

+ 3 - 3
Libraries/LibWeb/DOM/Element.cpp

@@ -271,17 +271,17 @@ String Element::inner_html() const
         for (auto* child = node.first_child(); child; child = child->next_sibling()) {
             if (child->is_element()) {
                 builder.append('<');
-                builder.append(to<Element>(*child).local_name());
+                builder.append(downcast<Element>(*child).local_name());
                 builder.append('>');
 
                 recurse(*child);
 
                 builder.append("</");
-                builder.append(to<Element>(*child).local_name());
+                builder.append(downcast<Element>(*child).local_name());
                 builder.append('>');
             }
             if (child->is_text()) {
-                builder.append(to<Text>(*child).data());
+                builder.append(downcast<Text>(*child).data());
             }
         }
     };

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

@@ -99,10 +99,8 @@ private:
     Vector<FlyString> m_classes;
 };
 
-template<>
-inline bool is<Element>(const Node& node)
-{
-    return node.is_element();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::Element)
+static bool is_type(const Web::Node& node) { return node.is_element(); }
+AK_END_TYPE_TRAITS()

+ 6 - 6
Libraries/LibWeb/DOM/Node.cpp

@@ -65,8 +65,8 @@ Node::~Node()
 const HTMLAnchorElement* Node::enclosing_link_element() const
 {
     for (auto* node = this; node; node = node->parent()) {
-        if (is<HTMLAnchorElement>(*node) && to<HTMLAnchorElement>(*node).has_attribute(HTML::AttributeNames::href))
-            return to<HTMLAnchorElement>(node);
+        if (is<HTMLAnchorElement>(*node) && downcast<HTMLAnchorElement>(*node).has_attribute(HTML::AttributeNames::href))
+            return downcast<HTMLAnchorElement>(node);
     }
     return nullptr;
 }
@@ -160,9 +160,9 @@ String Node::child_text_content() const
         return String::empty();
 
     StringBuilder builder;
-    to<ParentNode>(*this).for_each_child([&](auto& child) {
+    downcast<ParentNode>(*this).for_each_child([&](auto& child) {
         if (is<Text>(child))
-            builder.append(to<Text>(child).text_content());
+            builder.append(downcast<Text>(child).text_content());
     });
     return builder.build();
 }
@@ -184,14 +184,14 @@ Element* Node::parent_element()
 {
     if (!parent() || !is<Element>(parent()))
         return nullptr;
-    return to<Element>(parent());
+    return downcast<Element>(parent());
 }
 
 const Element* Node::parent_element() const
 {
     if (!parent() || !is<Element>(parent()))
         return nullptr;
-    return to<Element>(parent());
+    return downcast<Element>(parent());
 }
 
 RefPtr<Node> Node::append_child(NonnullRefPtr<Node> node, bool notify)

+ 8 - 59
Libraries/LibWeb/DOM/Node.h

@@ -29,6 +29,7 @@
 #include <AK/Badge.h>
 #include <AK/RefPtr.h>
 #include <AK/String.h>
+#include <AK/TypeCasts.h>
 #include <AK/Vector.h>
 #include <LibWeb/Bindings/Wrappable.h>
 #include <LibWeb/DOM/EventTarget.h>
@@ -116,9 +117,9 @@ public:
     template<typename T>
     const T* first_ancestor_of_type() const;
 
-    virtual void inserted_into(Node&) {}
-    virtual void removed_from(Node&) {}
-    virtual void children_changed() {}
+    virtual void inserted_into(Node&) { }
+    virtual void removed_from(Node&) { }
+    virtual void children_changed() { }
 
     const LayoutNode* layout_node() const { return m_layout_node; }
     LayoutNode* layout_node() { return m_layout_node; }
@@ -137,8 +138,8 @@ public:
 
     bool is_link() const;
 
-    virtual void document_did_attach_to_frame(Frame&) {}
-    virtual void document_will_detach_from_frame(Frame&) {}
+    virtual void document_did_attach_to_frame(Frame&) { }
+    virtual void document_will_detach_from_frame(Frame&) { }
 
     void set_document(Badge<Document>, Document&);
 
@@ -151,64 +152,12 @@ protected:
     bool m_needs_style_update { true };
 };
 
-template<typename T>
-inline bool is(const Node&)
-{
-    return false;
-}
-
-template<typename T>
-inline bool is(const Node* node)
-{
-    return !node || is<T>(*node);
-}
-
-template<>
-inline bool is<Node>(const Node&)
-{
-    return true;
-}
-
-template<>
-inline bool is<ParentNode>(const Node& node)
-{
-    return node.is_parent_node();
-}
-
-template<typename T>
-inline const T& to(const Node& node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<const T&>(node);
-}
-
-template<typename T>
-inline T* to(Node* node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<T*>(node);
-}
-
-template<typename T>
-inline const T* to(const Node* node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<const T*>(node);
-}
-
-template<typename T>
-inline T& to(Node& node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<T&>(node);
-}
-
 template<typename T>
 inline const T* Node::first_child_of_type() const
 {
     for (auto* child = first_child(); child; child = child->next_sibling()) {
         if (is<T>(*child))
-            return to<T>(child);
+            return downcast<T>(child);
     }
     return nullptr;
 }
@@ -218,7 +167,7 @@ inline const T* Node::first_ancestor_of_type() const
 {
     for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
         if (is<T>(*ancestor))
-            return to<T>(ancestor);
+            return downcast<T>(ancestor);
     }
     return nullptr;
 }

+ 4 - 0
Libraries/LibWeb/DOM/ParentNode.h

@@ -59,3 +59,7 @@ inline void ParentNode::for_each_child(Callback callback)
 }
 
 }
+
+AK_BEGIN_TYPE_TRAITS(Web::ParentNode)
+static bool is_type(const Web::Node& node) { return node.is_parent_node(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/DOM/Text.h

@@ -43,10 +43,8 @@ private:
     virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 };
 
-template<>
-inline bool is<Text>(const Node& node)
-{
-    return node.is_text();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::Text)
+static bool is_type(const Web::Node& node) { return node.is_text(); }
+AK_END_TYPE_TRAITS()

+ 2 - 2
Libraries/LibWeb/DOMTreeModel.cpp

@@ -128,10 +128,10 @@ GUI::Variant DOMTreeModel::data(const GUI::ModelIndex& index, Role role) const
     }
     if (role == Role::Display) {
         if (node.is_text())
-            return String::format("%s", with_whitespace_collapsed(to<Text>(node).data()).characters());
+            return String::format("%s", with_whitespace_collapsed(downcast<Text>(node).data()).characters());
         if (!node.is_element())
             return node.node_name();
-        auto& element = to<Element>(node);
+        auto& element = downcast<Element>(node);
         StringBuilder builder;
         builder.append('<');
         builder.append(element.local_name());

+ 6 - 6
Libraries/LibWeb/Dump.cpp

@@ -51,8 +51,8 @@ void dump_tree(const Node& node)
     if (is<Document>(node)) {
         dbgprintf("*Document*\n");
     } else if (is<Element>(node)) {
-        dbgprintf("<%s", to<Element>(node).local_name().characters());
-        to<Element>(node).for_each_attribute([](auto& name, auto& value) {
+        dbgprintf("<%s", downcast<Element>(node).local_name().characters());
+        downcast<Element>(node).for_each_attribute([](auto& name, auto& value) {
             dbgprintf(" %s=%s", name.characters(), value.characters());
         });
         dbgprintf(">\n");
@@ -61,7 +61,7 @@ void dump_tree(const Node& node)
     } else if (is<DocumentType>(node)) {
         dbgprintf("<!DOCTYPE html>\n");
     } else if (is<Comment>(node)) {
-        dbgprintf("<!--%s-->\n", to<Comment>(node).data().characters());
+        dbgprintf("<!--%s-->\n", downcast<Comment>(node).data().characters());
     } else if (is<DocumentFragment>(node)) {
         dbgprintf("#document-fragment\n");
     }
@@ -88,13 +88,13 @@ void dump_tree(const LayoutNode& layout_node)
     else if (is<Document>(layout_node.node()))
         tag_name = "#document";
     else if (is<Element>(layout_node.node()))
-        tag_name = to<Element>(*layout_node.node()).local_name();
+        tag_name = downcast<Element>(*layout_node.node()).local_name();
     else
         tag_name = "???";
 
     String identifier = "";
     if (layout_node.node() && is<Element>(*layout_node.node())) {
-        auto& element = to<Element>(*layout_node.node());
+        auto& element = downcast<Element>(*layout_node.node());
         StringBuilder builder;
         auto id = element.attribute(HTML::AttributeNames::id);
         if (!id.is_empty()) {
@@ -111,7 +111,7 @@ void dump_tree(const LayoutNode& layout_node)
     if (!layout_node.is_box()) {
         dbgprintf("%s {\033[33m%s\033[0m%s}\n", layout_node.class_name(), tag_name.characters(), identifier.characters());
     } else {
-        auto& layout_box = to<LayoutBox>(layout_node);
+        auto& layout_box = downcast<LayoutBox>(layout_node);
         dbgprintf("%s {\033[34m%s\033[0m%s} at (%g,%g) size %gx%g",
             layout_box.class_name(),
             tag_name.characters(),

+ 3 - 3
Libraries/LibWeb/Frame/EventHandler.cpp

@@ -80,7 +80,7 @@ bool EventHandler::handle_mouseup(const Gfx::IntPoint& position, unsigned button
     if (result.layout_node && result.layout_node->node()) {
         RefPtr<Node> node = result.layout_node->node();
         if (is<HTMLIFrameElement>(*node)) {
-            if (auto* subframe = to<HTMLIFrameElement>(*node).hosted_frame())
+            if (auto* subframe = downcast<HTMLIFrameElement>(*node).hosted_frame())
                 return subframe->event_handler().handle_mouseup(position.translated(compute_mouse_event_offset({}, *result.layout_node)), button, modifiers);
             return false;
         }
@@ -113,7 +113,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt
         return false;
 
     if (is<HTMLIFrameElement>(*node)) {
-        if (auto* subframe = to<HTMLIFrameElement>(*node).hosted_frame())
+        if (auto* subframe = downcast<HTMLIFrameElement>(*node).hosted_frame())
             return subframe->event_handler().handle_mousedown(position.translated(compute_mouse_event_offset({}, *result.layout_node)), button, modifiers);
         return false;
     }
@@ -176,7 +176,7 @@ bool EventHandler::handle_mousemove(const Gfx::IntPoint& position, unsigned butt
         RefPtr<Node> node = result.layout_node->node();
 
         if (node && is<HTMLIFrameElement>(*node)) {
-            if (auto* subframe = to<HTMLIFrameElement>(*node).hosted_frame())
+            if (auto* subframe = downcast<HTMLIFrameElement>(*node).hosted_frame())
                 return subframe->event_handler().handle_mousemove(position.translated(compute_mouse_event_offset({}, *result.layout_node)), buttons, modifiers);
             return false;
         }

+ 2 - 2
Libraries/LibWeb/Frame/Frame.cpp

@@ -125,7 +125,7 @@ void Frame::scroll_to_anchor(const String& fragment)
         auto candidates = document()->get_elements_by_name(fragment);
         for (auto* candidate : candidates) {
             if (is<HTMLAnchorElement>(*candidate)) {
-                element = to<HTMLAnchorElement>(candidate);
+                element = downcast<HTMLAnchorElement>(candidate);
                 break;
             }
         }
@@ -138,7 +138,7 @@ void Frame::scroll_to_anchor(const String& fragment)
 
     Gfx::FloatRect float_rect { layout_node.box_type_agnostic_position(), { (float)viewport_rect().width(), (float)viewport_rect().height() } };
     if (is<LayoutBox>(layout_node)) {
-        auto& layout_box = to<LayoutBox>(layout_node);
+        auto& layout_box = downcast<LayoutBox>(layout_node);
         auto padding_box = layout_box.box_model().padding_box(layout_box);
         float_rect.move_by(-padding_box.left, -padding_box.top);
     }

+ 3 - 5
Libraries/LibWeb/HTML/HTMLAnchorElement.h

@@ -39,10 +39,8 @@ public:
     String target() const { return attribute(HTML::AttributeNames::target); }
 };
 
-template<>
-inline bool is<HTMLAnchorElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::a;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLAnchorElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::a; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLBRElement.h

@@ -38,10 +38,8 @@ public:
     virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 };
 
-template<>
-inline bool is<HTMLBRElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::br;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLBRElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::br; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLBlinkElement.h

@@ -42,10 +42,8 @@ private:
     NonnullRefPtr<Core::Timer> m_timer;
 };
 
-template<>
-inline bool is<HTMLBlinkElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::blink;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLBlinkElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::blink; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLBodyElement.h

@@ -42,10 +42,8 @@ private:
     RefPtr<ImageStyleValue> m_background_style_value;
 };
 
-template<>
-inline bool is<HTMLBodyElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::body;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLBodyElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::body; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLCanvasElement.h

@@ -57,10 +57,8 @@ private:
     RefPtr<CanvasRenderingContext2D> m_context;
 };
 
-template<>
-inline bool is<HTMLCanvasElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::canvas;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLCanvasElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::canvas; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLElement.h

@@ -43,10 +43,8 @@ private:
     virtual bool is_html_element() const final { return true; }
 };
 
-template<>
-inline bool is<HTMLElement>(const Node& node)
-{
-    return node.is_html_element();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLFontElement.h

@@ -38,10 +38,8 @@ public:
     virtual void apply_presentational_hints(StyleProperties&) const override;
 };
 
-template<>
-inline bool is<HTMLFontElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::font;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLFontElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::font; }
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/HTML/HTMLFormElement.cpp

@@ -63,7 +63,7 @@ void HTMLFormElement::submit(RefPtr<HTMLInputElement> submitter)
     Vector<URLQueryParam> parameters;
 
     for_each_in_subtree_of_type<HTMLInputElement>([&](auto& node) {
-        auto& input = to<HTMLInputElement>(node);
+        auto& input = downcast<HTMLInputElement>(node);
         if (!input.name().is_null() && (input.type() != "submit" || &input == submitter))
             parameters.append({ input.name(), input.value() });
         return IterationDecision::Continue;

+ 3 - 5
Libraries/LibWeb/HTML/HTMLFormElement.h

@@ -42,10 +42,8 @@ public:
     void submit(RefPtr<HTMLInputElement> submitter);
 };
 
-template<>
-inline bool is<HTMLFormElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::form;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLFormElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::form; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLHRElement.h

@@ -36,10 +36,8 @@ public:
     virtual ~HTMLHRElement() override;
 };
 
-template<>
-inline bool is<HTMLHRElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::hr;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLHRElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::hr; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLHeadElement.h

@@ -36,10 +36,8 @@ public:
     virtual ~HTMLHeadElement() override;
 };
 
-template<>
-inline bool is<HTMLHeadElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name().equals_ignoring_case("head");
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLHeadElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::head; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLHtmlElement.h

@@ -36,10 +36,8 @@ public:
     virtual ~HTMLHtmlElement() override;
 };
 
-template<>
-inline bool is<HTMLHtmlElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name().equals_ignoring_case("html");
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLHtmlElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::html; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLIFrameElement.h

@@ -51,10 +51,8 @@ private:
     RefPtr<Frame> m_hosted_frame;
 };
 
-template<>
-inline bool is<HTMLIFrameElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::iframe;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLIFrameElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::iframe; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLImageElement.h

@@ -60,10 +60,8 @@ private:
     ImageLoader m_image_loader;
 };
 
-template<>
-inline bool is<HTMLImageElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::img;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLImageElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::img; }
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/HTML/HTMLInputElement.cpp

@@ -83,7 +83,7 @@ RefPtr<LayoutNode> HTMLInputElement::create_layout_node(const StyleProperties* p
         auto& text_box = page_view.add<GUI::TextBox>();
         text_box.set_text(value());
         text_box.on_change = [this] {
-            auto& widget = to<LayoutWidget>(layout_node())->widget();
+            auto& widget = downcast<LayoutWidget>(layout_node())->widget();
             const_cast<HTMLInputElement*>(this)->set_attribute(HTML::AttributeNames::value, static_cast<const GUI::TextBox&>(widget).text());
         };
         int text_width = Gfx::Font::default_font().width(value());

+ 3 - 5
Libraries/LibWeb/HTML/HTMLInputElement.h

@@ -42,10 +42,8 @@ public:
     String name() const { return attribute(HTML::AttributeNames::name); }
 };
 
-template<>
-inline bool is<HTMLInputElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::input;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLInputElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::input; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLLinkElement.h

@@ -64,10 +64,8 @@ private:
     RefPtr<StyleSheet> m_style_sheet;
 };
 
-template<>
-inline bool is<HTMLLinkElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::link;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLLinkElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::link; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLObjectElement.h

@@ -52,10 +52,8 @@ private:
     bool m_should_show_fallback_content { false };
 };
 
-template<>
-inline bool is<HTMLObjectElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::object;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLObjectElement)
+static bool is_type(const Web::Node& node) { return node.is_element() && downcast<Web::Element>(node).local_name() == Web::HTML::TagNames::object; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLScriptElement.h

@@ -65,10 +65,8 @@ private:
     String m_script_source;
 };
 
-template<>
-inline bool is<HTMLScriptElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::script;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLScriptElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::script; }
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/HTML/HTMLStyleElement.cpp

@@ -46,7 +46,7 @@ void HTMLStyleElement::children_changed()
     StringBuilder builder;
     for_each_child([&](auto& child) {
         if (is<Text>(child))
-            builder.append(to<Text>(child).text_content());
+            builder.append(downcast<Text>(child).text_content());
     });
     m_stylesheet = parse_css(CSS::ParsingContext(document()), builder.to_string());
     if (m_stylesheet)

+ 3 - 6
Libraries/LibWeb/HTML/HTMLStyleElement.h

@@ -44,11 +44,8 @@ private:
     RefPtr<StyleSheet> m_stylesheet;
 };
 
-template<>
-inline bool is<HTMLStyleElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::style;
 }
 
-
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLStyleElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::style; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLTableCellElement.h

@@ -39,10 +39,8 @@ private:
     virtual void apply_presentational_hints(StyleProperties&) const override;
 };
 
-template<>
-inline bool is<HTMLTableCellElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name().is_one_of(HTML::TagNames::td, HTML::TagNames::th);
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLTableCellElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::td; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLTableElement.h

@@ -39,10 +39,8 @@ private:
     virtual void apply_presentational_hints(StyleProperties&) const override;
 };
 
-template<>
-inline bool is<HTMLTableElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::table;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLTableElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::table; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLTableRowElement.h

@@ -36,10 +36,8 @@ public:
     virtual ~HTMLTableRowElement() override;
 };
 
-template<>
-inline bool is<HTMLTableRowElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name() == HTML::TagNames::tr;
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLTableRowElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::tr; }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/HTML/HTMLTitleElement.h

@@ -36,10 +36,8 @@ public:
     virtual ~HTMLTitleElement() override;
 };
 
-template<>
-inline bool is<HTMLTitleElement>(const Node& node)
-{
-    return is<Element>(node) && to<Element>(node).local_name().equals_ignoring_case("title");
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::HTMLTitleElement)
+static bool is_type(const Web::Node& node) { return node.is_html_element() && downcast<Web::HTMLElement>(node).local_name() == Web::HTML::TagNames::title; }
+AK_END_TYPE_TRAITS()

+ 7 - 7
Libraries/LibWeb/Layout/LayoutBlock.cpp

@@ -155,13 +155,13 @@ void LayoutBlock::layout_contained_boxes(LayoutMode layout_mode)
             return IterationDecision::Continue;
         box.layout(layout_mode);
         if (box.is_replaced())
-            place_block_level_replaced_element_in_normal_flow(to<LayoutReplaced>(box));
+            place_block_level_replaced_element_in_normal_flow(downcast<LayoutReplaced>(box));
         else if (box.is_block())
-            place_block_level_non_replaced_element_in_normal_flow(to<LayoutBlock>(box));
+            place_block_level_non_replaced_element_in_normal_flow(downcast<LayoutBlock>(box));
         else
             dbg() << "FIXME: LayoutBlock::layout_contained_boxes doesn't know how to place a " << box.class_name();
         content_height = max(content_height, box.effective_offset().y() + box.height() + box.box_model().margin_box(*this).bottom);
-        content_width = max(content_width, to<LayoutBox>(box).width());
+        content_width = max(content_width, downcast<LayoutBox>(box).width());
         return IterationDecision::Continue;
     });
 
@@ -257,7 +257,7 @@ void LayoutBlock::layout_inline_children(LayoutMode layout_mode)
             }
 
             if (fragment.layout_node().is_inline_block()) {
-                auto& inline_block = const_cast<LayoutBlock&>(to<LayoutBlock>(fragment.layout_node()));
+                auto& inline_block = const_cast<LayoutBlock&>(downcast<LayoutBlock>(fragment.layout_node()));
                 inline_block.set_size(fragment.size());
                 inline_block.layout(layout_mode);
             }
@@ -587,7 +587,7 @@ LayoutBlock::ShrinkToFitResult LayoutBlock::calculate_shrink_to_fit_width()
         } else {
             for_each_child([&](auto& child) {
                 if (child.is_box())
-                    max_width = max(max_width, to<LayoutBox>(child).width());
+                    max_width = max(max_width, downcast<LayoutBox>(child).width());
             });
         }
         return max_width;
@@ -725,11 +725,11 @@ HitTestResult LayoutBlock::hit_test(const Gfx::IntPoint& position) const
     HitTestResult last_good_candidate;
     for (auto& line_box : m_line_boxes) {
         for (auto& fragment : line_box.fragments()) {
-            if (is<LayoutBox>(fragment.layout_node()) && to<LayoutBox>(fragment.layout_node()).stacking_context())
+            if (is<LayoutBox>(fragment.layout_node()) && downcast<LayoutBox>(fragment.layout_node()).stacking_context())
                 continue;
             if (enclosing_int_rect(fragment.absolute_rect()).contains(position)) {
                 if (fragment.layout_node().is_block())
-                    return to<LayoutBlock>(fragment.layout_node()).hit_test(position);
+                    return downcast<LayoutBlock>(fragment.layout_node()).hit_test(position);
                 return { fragment.layout_node(), fragment.text_index_at(position.x()) };
             }
             if (fragment.absolute_rect().top() <= position.y())

+ 7 - 9
Libraries/LibWeb/Layout/LayoutBlock.h

@@ -53,10 +53,10 @@ public:
 
     virtual HitTestResult hit_test(const Gfx::IntPoint&) const override;
 
-    LayoutBlock* previous_sibling() { return to<LayoutBlock>(LayoutNode::previous_sibling()); }
-    const LayoutBlock* previous_sibling() const { return to<LayoutBlock>(LayoutNode::previous_sibling()); }
-    LayoutBlock* next_sibling() { return to<LayoutBlock>(LayoutNode::next_sibling()); }
-    const LayoutBlock* next_sibling() const { return to<LayoutBlock>(LayoutNode::next_sibling()); }
+    LayoutBlock* previous_sibling() { return downcast<LayoutBlock>(LayoutNode::previous_sibling()); }
+    const LayoutBlock* previous_sibling() const { return downcast<LayoutBlock>(LayoutNode::previous_sibling()); }
+    LayoutBlock* next_sibling() { return downcast<LayoutBlock>(LayoutNode::next_sibling()); }
+    const LayoutBlock* next_sibling() const { return downcast<LayoutBlock>(LayoutNode::next_sibling()); }
 
     template<typename Callback>
     void for_each_fragment(Callback);
@@ -119,10 +119,8 @@ void LayoutBlock::for_each_fragment(Callback callback) const
     }
 }
 
-template<>
-ALWAYS_INLINE bool is<LayoutBlock>(const LayoutNode& node)
-{
-    return node.is_block();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutBlock)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_block(); }
+AK_END_TYPE_TRAITS()

+ 2 - 2
Libraries/LibWeb/Layout/LayoutBox.cpp

@@ -231,7 +231,7 @@ HitTestResult LayoutBox::hit_test(const Gfx::IntPoint& position) const
     //        m_rect.contains() since inline text rects can't be trusted..
     HitTestResult result { absolute_rect().contains(position.x(), position.y()) ? this : nullptr };
     for_each_child([&](auto& child) {
-        if (is<LayoutBox>(child) && to<LayoutBox>(child).stacking_context())
+        if (is<LayoutBox>(child) && downcast<LayoutBox>(child).stacking_context())
             return;
         auto child_result = child.hit_test(position);
         if (child_result.layout_node)
@@ -297,7 +297,7 @@ StackingContext* LayoutBox::enclosing_stacking_context()
     for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
         if (!ancestor->is_box())
             continue;
-        auto& ancestor_box = to<LayoutBox>(*ancestor);
+        auto& ancestor_box = downcast<LayoutBox>(*ancestor);
         if (!ancestor_box.establishes_stacking_context())
             continue;
         ASSERT(ancestor_box.stacking_context());

+ 3 - 5
Libraries/LibWeb/Layout/LayoutBox.h

@@ -98,10 +98,8 @@ private:
     OwnPtr<StackingContext> m_stacking_context;
 };
 
-template<>
-ALWAYS_INLINE bool is<LayoutBox>(const LayoutNode& node)
-{
-    return node.is_box();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutBox)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_box(); }
+AK_END_TYPE_TRAITS()

+ 6 - 1
Libraries/LibWeb/Layout/LayoutBreak.h

@@ -36,11 +36,16 @@ public:
     LayoutBreak(Document&, const HTMLBRElement&);
     virtual ~LayoutBreak() override;
 
-    const HTMLBRElement& node() const { return to<HTMLBRElement>(*LayoutNode::node()); }
+    const HTMLBRElement& node() const { return downcast<HTMLBRElement>(*LayoutNode::node()); }
 
 private:
+    virtual bool is_break() const override { return true; }
     virtual const char* class_name() const override { return "LayoutBreak"; }
     virtual void split_into_lines(LayoutBlock&, LayoutMode) override;
 };
 
 }
+
+AK_BEGIN_TYPE_TRAITS(Web::LayoutBreak)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_break(); }
+AK_END_TYPE_TRAITS()

+ 4 - 5
Libraries/LibWeb/Layout/LayoutCanvas.h

@@ -48,10 +48,9 @@ private:
     virtual bool is_canvas() const override { return true; }
 };
 
-template<>
-inline bool is<LayoutCanvas>(const LayoutNode& node)
-{
-    return node.is_canvas();
-}
 
 }
+
+AK_BEGIN_TYPE_TRAITS(Web::LayoutCanvas)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_canvas(); }
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/Layout/LayoutDocument.cpp

@@ -76,7 +76,7 @@ void LayoutDocument::layout(LayoutMode layout_mode)
     float lowest_bottom = 0;
     for_each_child([&](auto& child) {
         ASSERT(is<LayoutBlock>(child));
-        auto& child_block = to<LayoutBlock>(child);
+        auto& child_block = downcast<LayoutBlock>(child);
         lowest_bottom = max(lowest_bottom, child_block.absolute_rect().bottom());
     });
     set_height(lowest_bottom);

+ 3 - 6
Libraries/LibWeb/Layout/LayoutDocument.h

@@ -58,11 +58,8 @@ private:
     LayoutRange m_selection;
 };
 
-template<>
-inline bool is<LayoutDocument>(const LayoutNode& node)
-{
-    return node.is_root();
 }
 
-
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutDocument)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_root(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/Layout/LayoutFrame.h

@@ -48,10 +48,8 @@ private:
     virtual void did_set_rect() override;
 };
 
-template<>
-inline bool is<LayoutFrame>(const LayoutNode& node)
-{
-    return node.is_frame();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutFrame)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_frame(); }
+AK_END_TYPE_TRAITS()

+ 2 - 2
Libraries/LibWeb/Layout/LayoutImage.cpp

@@ -71,7 +71,7 @@ void LayoutImage::layout(LayoutMode layout_mode)
     }
 
     if (renders_as_alt_text()) {
-        auto& image_element = to<HTMLImageElement>(node());
+        auto& image_element = downcast<HTMLImageElement>(node());
         auto& font = Gfx::Font::default_font();
         auto alt = image_element.alt();
         if (alt.is_empty())
@@ -101,7 +101,7 @@ void LayoutImage::paint(PaintContext& context, PaintPhase phase)
 
     if (phase == PaintPhase::Foreground) {
         if (renders_as_alt_text()) {
-            auto& image_element = to<HTMLImageElement>(node());
+            auto& image_element = downcast<HTMLImageElement>(node());
             context.painter().set_font(Gfx::Font::default_font());
             Gfx::StylePainter::paint_frame(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), Gfx::FrameShape::Container, Gfx::FrameShadow::Sunken, 2);
             auto alt = image_element.alt();

+ 3 - 5
Libraries/LibWeb/Layout/LayoutImage.h

@@ -57,10 +57,8 @@ private:
     const ImageLoader& m_image_loader;
 };
 
-template<>
-inline bool is<LayoutImage>(const LayoutNode& node)
-{
-    return node.is_image();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutImage)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_image(); }
+AK_END_TYPE_TRAITS()

+ 5 - 5
Libraries/LibWeb/Layout/LayoutNode.cpp

@@ -67,7 +67,7 @@ const LayoutBlock* LayoutNode::containing_block() const
         auto* ancestor = parent();
         while (ancestor && !is<LayoutBlock>(*ancestor))
             ancestor = ancestor->parent();
-        return to<LayoutBlock>(ancestor);
+        return downcast<LayoutBlock>(ancestor);
     };
 
     if (is_text())
@@ -81,7 +81,7 @@ const LayoutBlock* LayoutNode::containing_block() const
             ancestor = ancestor->parent();
         while (ancestor && (!is<LayoutBlock>(ancestor) || ancestor->is_anonymous()))
             ancestor = ancestor->containing_block();
-        return to<LayoutBlock>(ancestor);
+        return downcast<LayoutBlock>(ancestor);
     }
 
     if (position == CSS::Position::Fixed)
@@ -96,7 +96,7 @@ void LayoutNode::paint(PaintContext& context, PaintPhase phase)
         return;
 
     for_each_child([&](auto& child) {
-        if (child.is_box() && to<LayoutBox>(child).stacking_context())
+        if (child.is_box() && downcast<LayoutBox>(child).stacking_context())
             return;
         child.paint(context, phase);
     });
@@ -108,7 +108,7 @@ HitTestResult LayoutNode::hit_test(const Gfx::IntPoint& position) const
     for_each_child([&](auto& child) {
         // Skip over children that establish their own stacking context.
         // The outer loop who called us will take care of those.
-        if (is<LayoutBox>(child) && to<LayoutBox>(child).stacking_context())
+        if (is<LayoutBox>(child) && downcast<LayoutBox>(child).stacking_context())
             return;
         auto child_result = child.hit_test(position);
         if (child_result.layout_node)
@@ -170,7 +170,7 @@ float LayoutNode::font_size() const
 Gfx::FloatPoint LayoutNode::box_type_agnostic_position() const
 {
     if (is_box())
-        return to<LayoutBox>(*this).absolute_position();
+        return downcast<LayoutBox>(*this).absolute_position();
     ASSERT(is_inline());
     Gfx::FloatPoint position;
     if (auto* block = containing_block()) {

+ 15 - 62
Libraries/LibWeb/Layout/LayoutNode.h

@@ -27,6 +27,7 @@
 #pragma once
 
 #include <AK/NonnullRefPtr.h>
+#include <AK/TypeCasts.h>
 #include <AK/Vector.h>
 #include <LibGfx/FloatRect.h>
 #include <LibGfx/Rect.h>
@@ -40,52 +41,6 @@
 
 namespace Web {
 
-template<typename T>
-inline bool is(const LayoutNode&)
-{
-    return false;
-}
-
-template<typename T>
-inline bool is(const LayoutNode* node)
-{
-    return !node || is<T>(*node);
-}
-
-template<>
-inline bool is<LayoutNode>(const LayoutNode&)
-{
-    return true;
-}
-
-template<typename T>
-inline const T& to(const LayoutNode& node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<const T&>(node);
-}
-
-template<typename T>
-inline T* to(LayoutNode* node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<T*>(node);
-}
-
-template<typename T>
-inline const T* to(const LayoutNode* node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<const T*>(node);
-}
-
-template<typename T>
-inline T& to(LayoutNode& node)
-{
-    ASSERT(is<T>(node));
-    return static_cast<T&>(node);
-}
-
 struct HitTestResult {
     RefPtr<LayoutNode> layout_node;
     int index_in_node { 0 };
@@ -130,7 +85,7 @@ public:
         for (auto* node = first_child(); node; node = node->next_sibling()) {
             if (!is<T>(node))
                 continue;
-            callback(to<T>(*node));
+            callback(downcast<T>(*node));
         }
     }
 
@@ -140,7 +95,7 @@ public:
         for (auto* node = first_child(); node; node = node->next_sibling()) {
             if (!is<T>(node))
                 continue;
-            callback(to<T>(*node));
+            callback(downcast<T>(*node));
         }
     }
 
@@ -158,6 +113,7 @@ public:
     virtual bool is_table_row() const { return false; }
     virtual bool is_table_cell() const { return false; }
     virtual bool is_table_row_group() const { return false; }
+    virtual bool is_break() const { return false; }
     bool has_style() const { return m_has_style; }
 
     bool is_inline() const { return m_inline; }
@@ -269,7 +225,6 @@ protected:
     LayoutNodeWithStyle(Document&, const Node*, NonnullRefPtr<StyleProperties>);
 
 private:
-
     LayoutStyle m_style;
 
     NonnullRefPtr<StyleProperties> m_specified_style;
@@ -321,7 +276,7 @@ inline const T* LayoutNode::next_sibling_of_type() const
 {
     for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
         if (is<T>(*sibling))
-            return &to<T>(*sibling);
+            return &downcast<T>(*sibling);
     }
     return nullptr;
 }
@@ -331,7 +286,7 @@ inline T* LayoutNode::next_sibling_of_type()
 {
     for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
         if (is<T>(*sibling))
-            return &to<T>(*sibling);
+            return &downcast<T>(*sibling);
     }
     return nullptr;
 }
@@ -341,7 +296,7 @@ inline const T* LayoutNode::previous_sibling_of_type() const
 {
     for (auto* sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) {
         if (is<T>(*sibling))
-            return &to<T>(*sibling);
+            return &downcast<T>(*sibling);
     }
     return nullptr;
 }
@@ -351,7 +306,7 @@ inline T* LayoutNode::previous_sibling_of_type()
 {
     for (auto* sibling = previous_sibling(); sibling; sibling = sibling->previous_sibling()) {
         if (is<T>(*sibling))
-            return &to<T>(*sibling);
+            return &downcast<T>(*sibling);
     }
     return nullptr;
 }
@@ -361,7 +316,7 @@ inline const T* LayoutNode::first_child_of_type() const
 {
     for (auto* child = first_child(); child; child = child->next_sibling()) {
         if (is<T>(*child))
-            return &to<T>(*child);
+            return &downcast<T>(*child);
     }
     return nullptr;
 }
@@ -371,7 +326,7 @@ inline T* LayoutNode::first_child_of_type()
 {
     for (auto* child = first_child(); child; child = child->next_sibling()) {
         if (is<T>(*child))
-            return &to<T>(*child);
+            return &downcast<T>(*child);
     }
     return nullptr;
 }
@@ -381,7 +336,7 @@ inline const T* LayoutNode::first_ancestor_of_type() const
 {
     for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
         if (is<T>(*ancestor))
-            return &to<T>(*ancestor);
+            return &downcast<T>(*ancestor);
     }
     return nullptr;
 }
@@ -391,15 +346,13 @@ inline T* LayoutNode::first_ancestor_of_type()
 {
     for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
         if (is<T>(*ancestor))
-            return &to<T>(*ancestor);
+            return &downcast<T>(*ancestor);
     }
     return nullptr;
 }
 
-template<>
-inline bool is<LayoutNodeWithStyle>(const LayoutNode& node)
-{
-    return node.has_style();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutNodeWithStyle)
+static bool is_type(const Web::LayoutNode& node) { return node.has_style(); }
+AK_END_TYPE_TRAITS()

+ 5 - 7
Libraries/LibWeb/Layout/LayoutReplaced.h

@@ -36,8 +36,8 @@ public:
     LayoutReplaced(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutReplaced() override;
 
-    const Element& node() const { return to<Element>(*LayoutNode::node()); }
-    Element& node() { return to<Element>(*LayoutNode::node()); }
+    const Element& node() const { return downcast<Element>(*LayoutNode::node()); }
+    Element& node() { return downcast<Element>(*LayoutNode::node()); }
 
     virtual bool is_replaced() const final { return true; }
 
@@ -75,10 +75,8 @@ private:
     float m_intrinsic_ratio { 0 };
 };
 
-template<>
-inline bool is<LayoutReplaced>(const LayoutNode& node)
-{
-    return node.is_replaced();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutReplaced)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_replaced(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/Layout/LayoutTable.h

@@ -44,10 +44,8 @@ private:
     virtual const char* class_name() const override { return "LayoutTable"; }
 };
 
-template<>
-inline bool is<LayoutTable>(const LayoutNode& node)
-{
-    return node.is_table();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutTable)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_table(); }
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/Layout/LayoutTableCell.cpp

@@ -42,7 +42,7 @@ LayoutTableCell::~LayoutTableCell()
 size_t LayoutTableCell::colspan() const
 {
     ASSERT(node());
-    return to<Element>(*node()).attribute(HTML::AttributeNames::colspan).to_uint().value_or(1);
+    return downcast<Element>(*node()).attribute(HTML::AttributeNames::colspan).to_uint().value_or(1);
 }
 
 float LayoutTableCell::width_of_logical_containing_block() const

+ 3 - 5
Libraries/LibWeb/Layout/LayoutTableCell.h

@@ -46,10 +46,8 @@ private:
     virtual float width_of_logical_containing_block() const override;
 };
 
-template<>
-inline bool is<LayoutTableCell>(const LayoutNode& node)
-{
-    return node.is_table_cell();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutTableCell)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_table_cell(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/Layout/LayoutTableRow.h

@@ -46,10 +46,8 @@ private:
     virtual const char* class_name() const override { return "LayoutTableRow"; }
 };
 
-template<>
-inline bool is<LayoutTableRow>(const LayoutNode& node)
-{
-    return node.is_table_row();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutTableRow)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_table_row(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/Layout/LayoutTableRowGroup.h

@@ -44,10 +44,8 @@ private:
     virtual const char* class_name() const override { return "LayoutTableRowGroup"; }
 };
 
-template<>
-inline bool is<LayoutTableRowGroup>(const LayoutNode& node)
-{
-    return node.is_table_row_group();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutTableRowGroup)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_table_row_group(); }
+AK_END_TYPE_TRAITS()

+ 3 - 5
Libraries/LibWeb/Layout/LayoutText.h

@@ -61,10 +61,8 @@ private:
     String m_text_for_rendering;
 };
 
-template<>
-inline bool is<LayoutText>(const LayoutNode& node)
-{
-    return node.is_text();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutText)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_text(); }
+AK_END_TYPE_TRAITS()

+ 2 - 2
Libraries/LibWeb/Layout/LayoutTreeBuilder.cpp

@@ -50,7 +50,7 @@ static RefPtr<LayoutNode> create_layout_tree(Node& node, const StyleProperties*
     bool have_inline_children = false;
     bool have_noninline_children = false;
 
-    to<ParentNode>(node).for_each_child([&](Node& child) {
+    downcast<ParentNode>(node).for_each_child([&](Node& child) {
         auto layout_child = create_layout_tree(child, &layout_node->specified_style());
         if (!layout_child)
             return;
@@ -63,7 +63,7 @@ static RefPtr<LayoutNode> create_layout_tree(Node& node, const StyleProperties*
 
     for (auto& layout_child : layout_children) {
         if (have_noninline_children && have_inline_children && layout_child.is_inline()) {
-            if (is<LayoutText>(layout_child) && to<LayoutText>(layout_child).text_for_style(*parent_style) == " ")
+            if (is<LayoutText>(layout_child) && downcast<LayoutText>(layout_child).text_for_style(*parent_style) == " ")
                 continue;
             layout_node->inline_wrapper().append_child(layout_child);
         } else {

+ 3 - 5
Libraries/LibWeb/Layout/LayoutWidget.h

@@ -50,10 +50,8 @@ private:
     NonnullRefPtr<GUI::Widget> m_widget;
 };
 
-template<>
-inline bool is<LayoutWidget>(const LayoutNode& node)
-{
-    return node.is_widget();
 }
 
-}
+AK_BEGIN_TYPE_TRAITS(Web::LayoutWidget)
+static bool is_type(const Web::LayoutNode& layout_node) { return layout_node.is_widget(); }
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/Layout/LineBox.cpp

@@ -47,7 +47,7 @@ void LineBox::add_fragment(const LayoutNode& layout_node, int start, int length,
     m_width += width;
 
     if (is<LayoutBox>(layout_node))
-        const_cast<LayoutBox&>(to<LayoutBox>(layout_node)).set_containing_line_box_fragment(m_fragments.last());
+        const_cast<LayoutBox&>(downcast<LayoutBox>(layout_node)).set_containing_line_box_fragment(m_fragments.last());
 }
 
 void LineBox::trim_trailing_whitespace()

+ 3 - 3
Libraries/LibWeb/Layout/LineBoxFragment.cpp

@@ -42,7 +42,7 @@ void LineBoxFragment::paint(PaintContext& context)
     }
 
     if (is<LayoutText>(layout_node())) {
-        to<LayoutText>(layout_node()).paint_fragment(context, *this);
+        downcast<LayoutText>(layout_node()).paint_fragment(context, *this);
     }
 }
 
@@ -63,7 +63,7 @@ StringView LineBoxFragment::text() const
 {
     if (!is<LayoutText>(layout_node()))
         return {};
-    return to<LayoutText>(layout_node()).text_for_rendering().substring_view(m_start, m_length);
+    return downcast<LayoutText>(layout_node()).text_for_rendering().substring_view(m_start, m_length);
 }
 
 const Gfx::FloatRect LineBoxFragment::absolute_rect() const
@@ -78,7 +78,7 @@ int LineBoxFragment::text_index_at(float x) const
 {
     if (!layout_node().is_text())
         return 0;
-    auto& layout_text = to<LayoutText>(layout_node());
+    auto& layout_text = downcast<LayoutText>(layout_node());
     auto& font = layout_text.specified_style().font();
     Utf8View view(text());
 

+ 2 - 2
Libraries/LibWeb/LayoutTreeModel.cpp

@@ -127,7 +127,7 @@ GUI::Variant LayoutTreeModel::data(const GUI::ModelIndex& index, Role role) cons
     }
     if (role == Role::Display) {
         if (node.is_text())
-            return String::format("LayoutText: %s", with_whitespace_collapsed(to<LayoutText>(node).text_for_rendering()).characters());
+            return String::format("LayoutText: %s", with_whitespace_collapsed(downcast<LayoutText>(node).text_for_rendering()).characters());
         StringBuilder builder;
         builder.append(node.class_name());
         builder.append(' ');
@@ -136,7 +136,7 @@ GUI::Variant LayoutTreeModel::data(const GUI::ModelIndex& index, Role role) cons
         } else if (!node.node()->is_element()) {
             builder.append(node.node()->node_name());
         } else {
-            auto& element = to<Element>(*node.node());
+            auto& element = downcast<Element>(*node.node());
             builder.append('<');
             builder.append(element.local_name());
             element.for_each_attribute([&](auto& name, auto& value) {

+ 5 - 5
Libraries/LibWeb/PageView.cpp

@@ -107,7 +107,7 @@ void PageView::select_all()
 
     int last_layout_node_index_in_node = 0;
     if (is<LayoutText>(*last_layout_node))
-        last_layout_node_index_in_node = to<LayoutText>(*last_layout_node).text_for_rendering().length() - 1;
+        last_layout_node_index_in_node = downcast<LayoutText>(*last_layout_node).text_for_rendering().length() - 1;
 
     layout_root->selection().set({ first_layout_node, 0 }, { last_layout_node, last_layout_node_index_in_node });
     update();
@@ -127,13 +127,13 @@ String PageView::selected_text() const
     if (selection.start().layout_node == selection.end().layout_node) {
         if (!is<LayoutText>(*selection.start().layout_node))
             return "";
-        return to<LayoutText>(*selection.start().layout_node).text_for_rendering().substring(selection.start().index_in_node, selection.end().index_in_node - selection.start().index_in_node + 1);
+        return downcast<LayoutText>(*selection.start().layout_node).text_for_rendering().substring(selection.start().index_in_node, selection.end().index_in_node - selection.start().index_in_node + 1);
     }
 
     // Start node
     auto layout_node = selection.start().layout_node;
     if (is<LayoutText>(*layout_node)) {
-        auto& text = to<LayoutText>(*layout_node).text_for_rendering();
+        auto& text = downcast<LayoutText>(*layout_node).text_for_rendering();
         builder.append(text.substring(selection.start().index_in_node, text.length() - selection.start().index_in_node));
     }
 
@@ -141,7 +141,7 @@ String PageView::selected_text() const
     layout_node = layout_node->next_in_pre_order();
     while (layout_node && layout_node != selection.end().layout_node) {
         if (is<LayoutText>(*layout_node))
-            builder.append(to<LayoutText>(*layout_node).text_for_rendering());
+            builder.append(downcast<LayoutText>(*layout_node).text_for_rendering());
         else if (is<LayoutBreak>(*layout_node) || is<LayoutBlock>(*layout_node))
             builder.append('\n');
 
@@ -151,7 +151,7 @@ String PageView::selected_text() const
     // End node
     ASSERT(layout_node == selection.end().layout_node);
     if (is<LayoutText>(*layout_node)) {
-        auto& text = to<LayoutText>(*layout_node).text_for_rendering();
+        auto& text = downcast<LayoutText>(*layout_node).text_for_rendering();
         builder.append(text.substring(0, selection.end().index_in_node + 1));
     }
 

+ 2 - 2
Libraries/LibWeb/Painting/StackingContext.cpp

@@ -54,7 +54,7 @@ void StackingContext::paint(PaintContext& context, LayoutNode::PaintPhase phase)
     } else {
         // NOTE: LayoutDocument::paint() merely calls StackingContext::paint()
         //       so we call its base class instead.
-        to<LayoutDocument>(m_box).LayoutBlock::paint(context, phase);
+        downcast<LayoutDocument>(m_box).LayoutBlock::paint(context, phase);
     }
     for (auto* child : m_children) {
         child->paint(context, phase);
@@ -69,7 +69,7 @@ HitTestResult StackingContext::hit_test(const Gfx::IntPoint& position) const
     } else {
         // NOTE: LayoutDocument::hit_test() merely calls StackingContext::hit_test()
         //       so we call its base class instead.
-        result = to<LayoutDocument>(m_box).LayoutBlock::hit_test(position);
+        result = downcast<LayoutDocument>(m_box).LayoutBlock::hit_test(position);
     }
 
     for (auto* child : m_children) {

+ 9 - 9
Libraries/LibWeb/Parser/HTMLDocumentParser.cpp

@@ -441,7 +441,7 @@ void HTMLDocumentParser::handle_before_head(HTMLToken& token)
 
     if (token.is_start_tag() && token.tag_name() == HTML::TagNames::head) {
         auto element = insert_html_element(token);
-        m_head_element = to<HTMLHeadElement>(element);
+        m_head_element = downcast<HTMLHeadElement>(*element);
         m_insertion_mode = InsertionMode::InHead;
         return;
     }
@@ -456,7 +456,7 @@ void HTMLDocumentParser::handle_before_head(HTMLToken& token)
     }
 
 AnythingElse:
-    m_head_element = to<HTMLHeadElement>(insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head)));
+    m_head_element = downcast<HTMLHeadElement>(*insert_html_element(HTMLToken::make_start_tag(HTML::TagNames::head)));
     m_insertion_mode = InsertionMode::InHead;
     process_using_the_rules_for(InsertionMode::InHead, token);
     return;
@@ -527,7 +527,7 @@ void HTMLDocumentParser::handle_in_head(HTMLToken& token)
     if (token.is_start_tag() && token.tag_name() == HTML::TagNames::script) {
         auto adjusted_insertion_location = find_appropriate_place_for_inserting_node();
         auto element = create_element_for(token);
-        auto& script_element = to<HTMLScriptElement>(*element);
+        auto& script_element = downcast<HTMLScriptElement>(*element);
         script_element.set_parser_document({}, document());
         script_element.set_non_blocking({}, false);
 
@@ -636,7 +636,7 @@ Text* HTMLDocumentParser::find_character_insertion_node()
     if (adjusted_insertion_location.parent->is_document())
         return nullptr;
     if (adjusted_insertion_location.parent->last_child() && adjusted_insertion_location.parent->last_child()->is_text())
-        return to<Text>(adjusted_insertion_location.parent->last_child());
+        return downcast<Text>(adjusted_insertion_location.parent->last_child());
     auto new_text_node = adopt(*new Text(document(), ""));
     adjusted_insertion_location.parent->append_child(new_text_node);
     return new_text_node;
@@ -1179,7 +1179,7 @@ void HTMLDocumentParser::handle_in_body(HTMLToken& token)
             close_a_p_element();
         auto element = insert_html_element(token);
         if (!m_stack_of_open_elements.contains(HTML::TagNames::template_))
-            m_form_element = to<HTMLFormElement>(*element);
+            m_form_element = downcast<HTMLFormElement>(*element);
         return;
     }
 
@@ -1756,7 +1756,7 @@ void HTMLDocumentParser::handle_text(HTMLToken& token)
     if (token.is_end_of_file()) {
         PARSE_ERROR();
         if (current_node().local_name() == HTML::TagNames::script)
-            to<HTMLScriptElement>(current_node()).set_already_started({}, true);
+            downcast<HTMLScriptElement>(current_node()).set_already_started({}, true);
         m_stack_of_open_elements.pop();
         m_insertion_mode = m_original_insertion_mode;
         process_using_the_rules_for(m_insertion_mode, token);
@@ -1766,7 +1766,7 @@ void HTMLDocumentParser::handle_text(HTMLToken& token)
         // Make sure the <script> element has up-to-date text content before preparing the script.
         flush_character_insertions();
 
-        NonnullRefPtr<HTMLScriptElement> script = to<HTMLScriptElement>(current_node());
+        NonnullRefPtr<HTMLScriptElement> script = downcast<HTMLScriptElement>(current_node());
         m_stack_of_open_elements.pop();
         m_insertion_mode = m_original_insertion_mode;
         // FIXME: Handle tokenizer insertion point stuff here.
@@ -2164,7 +2164,7 @@ void HTMLDocumentParser::handle_in_table(HTMLToken& token)
             return;
         }
 
-        m_form_element = to<HTMLFormElement>(insert_html_element(token));
+        m_form_element = downcast<HTMLFormElement>(*insert_html_element(token));
 
         // FIXME: See previous FIXME, as this is the same situation but for form.
         m_stack_of_open_elements.pop();
@@ -2783,7 +2783,7 @@ NonnullRefPtrVector<Node> HTMLDocumentParser::parse_html_fragment(Element& conte
 
     for (auto* form_candidate = &context_element; form_candidate; form_candidate = form_candidate->parent_element()) {
         if (is<HTMLFormElement>(*form_candidate)) {
-            parser.m_form_element = to<HTMLFormElement>(*form_candidate);
+            parser.m_form_element = downcast<HTMLFormElement>(*form_candidate);
             break;
         }
     }

+ 5 - 8
Libraries/LibWeb/SVG/SVGGraphicsElement.h

@@ -63,15 +63,13 @@ protected:
 
 }
 
-namespace Web {
-
-template<>
-inline bool is<SVG::SVGGraphicsElement>(const Node& node)
+AK_BEGIN_TYPE_TRAITS(Web::SVG::SVGGraphicsElement)
+static bool is_type(const Web::Node& node)
 {
-    if (!is<Element>(node))
+    if (!is<Web::Element>(node))
         return false;
 
-    auto tag_name = to<Element>(node).tag_name();
+    auto tag_name = downcast<Web::Element>(node).tag_name();
 
 #define __ENUMERATE_SVG_TAG(name) \
     if (tag_name == #name)        \
@@ -81,5 +79,4 @@ inline bool is<SVG::SVGGraphicsElement>(const Node& node)
 
     return false;
 }
-
-}
+AK_END_TYPE_TRAITS()

+ 1 - 1
Libraries/LibWeb/SVG/SVGSVGElement.cpp

@@ -101,7 +101,7 @@ void SVGSVGElement::paint(Gfx::Painter& painter, const SVGPaintingContext& conte
 {
     for_each_child([&](Node& child) {
         if (is<SVGGraphicsElement>(child)) {
-            to<SVGGraphicsElement>(child).paint(painter, make_painting_context_from(context));
+            downcast<SVGGraphicsElement>(child).paint(painter, make_painting_context_from(context));
         }
     });
 }

+ 1 - 9
Libraries/LibWeb/TreeNode.h

@@ -28,19 +28,11 @@
 
 #include <AK/Assertions.h>
 #include <AK/NonnullRefPtr.h>
+#include <AK/TypeCasts.h>
 #include <AK/Weakable.h>
 
 namespace Web {
 
-// FIXME: I wish I didn't have to forward declare these, but I can't seem to avoid
-//        it if I still want to have for_each_in_subtree_of_type<U> inline here.
-class Node;
-class LayoutNode;
-template<typename T>
-bool is(const Node&);
-template<typename T>
-bool is(const LayoutNode&);
-
 template<typename T>
 class TreeNode : public Weakable<T> {
 public: