diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp
index 5d1eaf19c5d..fb631bd1410 100644
--- a/Libraries/LibHTML/DOM/Document.cpp
+++ b/Libraries/LibHTML/DOM/Document.cpp
@@ -177,9 +177,9 @@ void Document::layout()
void Document::update_style()
{
- for_each_in_subtree([&](Node& node) {
- if (node.needs_style_update())
- to(node).recompute_style();
+ for_each_in_subtree_of_type([&](auto& element) {
+ if (element.needs_style_update())
+ element.recompute_style();
return IterationDecision::Continue;
});
update_layout();
@@ -252,23 +252,23 @@ void Document::set_hovered_node(Node* node)
const Element* Document::get_element_by_id(const String& id) const
{
- const Element* element = nullptr;
- for_each_in_subtree([&](auto& node) {
- if (is(node) && to(node).attribute("id") == id) {
- element = &to(node);
+ 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 element;
+ return found_element;
}
Vector Document::get_elements_by_name(const String& name) const
{
Vector elements;
- for_each_in_subtree([&](auto& node) {
- if (is(node) && to(node).attribute("name") == name)
- elements.append(&to(node));
+ for_each_in_subtree_of_type([&](auto& element) {
+ if (element.attribute("name") == name)
+ elements.append(&element);
return IterationDecision::Continue;
});
return elements;
diff --git a/Libraries/LibHTML/DOM/HTMLFormElement.cpp b/Libraries/LibHTML/DOM/HTMLFormElement.cpp
index 1e0f047533e..a6fb478f07b 100644
--- a/Libraries/LibHTML/DOM/HTMLFormElement.cpp
+++ b/Libraries/LibHTML/DOM/HTMLFormElement.cpp
@@ -34,12 +34,10 @@ void HTMLFormElement::submit()
Vector parameters;
- for_each_in_subtree([&](auto& node) {
- if (is(node)) {
- auto& input = to(node);
- if (!input.name().is_null())
- parameters.append({ input.name(), input.value() });
- }
+ for_each_in_subtree_of_type([&](auto& node) {
+ auto& input = to(node);
+ if (!input.name().is_null())
+ parameters.append({ input.name(), input.value() });
return IterationDecision::Continue;
});
diff --git a/Libraries/LibHTML/DOM/Node.cpp b/Libraries/LibHTML/DOM/Node.cpp
index bebf6b23be6..78ccf41ad11 100644
--- a/Libraries/LibHTML/DOM/Node.cpp
+++ b/Libraries/LibHTML/DOM/Node.cpp
@@ -74,9 +74,8 @@ RefPtr Node::create_layout_node(const StyleProperties*) const
void Node::invalidate_style()
{
- for_each_in_subtree([&](auto& node) {
- if (is(node))
- node.set_needs_style_update(true);
+ for_each_in_subtree_of_type([&](auto& element) {
+ element.set_needs_style_update(true);
return IterationDecision::Continue;
});
document().schedule_style_update();
diff --git a/Libraries/LibHTML/Layout/LayoutDocument.cpp b/Libraries/LibHTML/Layout/LayoutDocument.cpp
index 279fb810cbf..9ff55e20745 100644
--- a/Libraries/LibHTML/Layout/LayoutDocument.cpp
+++ b/Libraries/LibHTML/Layout/LayoutDocument.cpp
@@ -34,11 +34,8 @@ void LayoutDocument::layout()
void LayoutDocument::did_set_viewport_rect(Badge, const Rect& a_viewport_rect)
{
FloatRect viewport_rect(a_viewport_rect.x(), a_viewport_rect.y(), a_viewport_rect.width(), a_viewport_rect.height());
- for_each_in_subtree([&](auto& layout_node) {
- if (is(layout_node)) {
- auto& image = to(layout_node);
- const_cast(image.node()).set_volatile({}, !viewport_rect.intersects(image.rect()));
- }
+ for_each_in_subtree_of_type([&](auto& layout_image) {
+ const_cast(layout_image.node()).set_volatile({}, !viewport_rect.intersects(layout_image.rect()));
return IterationDecision::Continue;
});
}
diff --git a/Libraries/LibHTML/TreeNode.h b/Libraries/LibHTML/TreeNode.h
index d87b8e0a6f1..5ad07f8daf5 100644
--- a/Libraries/LibHTML/TreeNode.h
+++ b/Libraries/LibHTML/TreeNode.h
@@ -4,6 +4,15 @@
#include
#include
+// 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 inline here.
+class Node;
+class LayoutNode;
+template
+bool is(const Node&);
+template
+bool is(const LayoutNode&);
+
template
class TreeNode : public Weakable {
public:
@@ -122,6 +131,34 @@ public:
return IterationDecision::Continue;
}
+ template
+ IterationDecision for_each_in_subtree_of_type(Callback callback)
+ {
+ if (is(static_cast(*this))) {
+ if (callback(static_cast(*this)) == IterationDecision::Break)
+ return IterationDecision::Break;
+ }
+ for (auto* child = first_child(); child; child = child->next_sibling()) {
+ if (child->template for_each_in_subtree_of_type(callback) == IterationDecision::Break)
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
+ }
+
+ template
+ IterationDecision for_each_in_subtree_of_type(Callback callback) const
+ {
+ if (is(static_cast(*this))) {
+ if (callback(static_cast(*this)) == IterationDecision::Break)
+ return IterationDecision::Break;
+ }
+ for (auto* child = first_child(); child; child = child->next_sibling()) {
+ if (child->template for_each_in_subtree_of_type(callback) == IterationDecision::Break)
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
+ }
+
protected:
TreeNode() {}