From c57d395a48ae8bc547d8e454e2a1da493e6e4bfd Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Sat, 4 May 2024 14:59:52 +0100 Subject: [PATCH] LibWeb: Use `IterationDecision` in single level Node iteration methods `Node::for_each_child()` and `Node::for_each_child_of_type()` callbacks now return an `IterationDecision`, which allows us to break early if required. --- Userland/Libraries/LibWeb/DOM/Node.cpp | 14 ++++++++++++-- Userland/Libraries/LibWeb/DOM/Node.h | 12 ++++++++---- Userland/Libraries/LibWeb/DOM/ParentNode.h | 12 ++++++++---- Userland/Libraries/LibWeb/DOM/Slottable.cpp | 4 +++- Userland/Libraries/LibWeb/Dump.cpp | 2 ++ .../Libraries/LibWeb/HTML/HTMLImageElement.cpp | 1 + .../Libraries/LibWeb/HTML/HTMLInputElement.cpp | 1 + .../Libraries/LibWeb/HTML/HTMLOptionElement.cpp | 2 ++ .../Libraries/LibWeb/HTML/HTMLSelectElement.cpp | 3 +++ .../Libraries/LibWeb/HTML/HTMLTemplateElement.cpp | 2 ++ .../Libraries/LibWeb/HTML/Parser/HTMLParser.cpp | 4 ++-- .../LibWeb/Layout/BlockFormattingContext.cpp | 1 + .../LibWeb/Layout/FlexFormattingContext.cpp | 1 + .../Libraries/LibWeb/Layout/FormattingContext.cpp | 1 + .../LibWeb/Layout/GridFormattingContext.cpp | 1 + Userland/Libraries/LibWeb/Layout/LayoutState.cpp | 2 ++ Userland/Libraries/LibWeb/Layout/Node.cpp | 1 + .../LibWeb/Layout/SVGFormattingContext.cpp | 6 +++++- Userland/Libraries/LibWeb/Layout/TableGrid.h | 1 + Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp | 3 +++ .../Libraries/LibWeb/Painting/InlinePaintable.cpp | 9 +++++---- .../Libraries/LibWeb/Painting/StackingContext.cpp | 10 ++++++---- .../LibWeb/Painting/TableBordersPainting.cpp | 2 +- Userland/Libraries/LibWeb/SVG/SVGGradientElement.h | 1 + Userland/Libraries/LibWeb/TreeNode.h | 12 ++++++++---- 25 files changed, 81 insertions(+), 27 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 83630fd16de..48a733d56e7 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -300,6 +300,7 @@ String Node::child_text_content() const if (maybe_content.has_value()) builder.append(maybe_content.value()); } + return IterationDecision::Continue; }); return MUST(builder.to_string()); } @@ -903,6 +904,7 @@ JS::NonnullGCPtr Node::clone_node(Document* document, bool clone_children) if (clone_children) { for_each_child([&](auto& child) { MUST(copy->append_child(child.clone_node(document, true))); + return IterationDecision::Continue; }); } @@ -1032,6 +1034,7 @@ Vector> Node::children_as_vector() const for_each_child([&](auto& child) { nodes.append(JS::make_handle(child)); + return IterationDecision::Continue; }); return nodes; @@ -1223,10 +1226,11 @@ void Node::serialize_tree_as_json(JsonObjectSerializer& object) c auto children = MUST(object.add_array("children"sv)); auto add_child = [&children](DOM::Node const& child) { if (child.is_uninteresting_whitespace_node()) - return; + return IterationDecision::Continue; JsonObjectSerializer child_object = MUST(children.add_object()); child.serialize_tree_as_json(child_object); MUST(child_object.finish()); + return IterationDecision::Continue; }; for_each_child(add_child); @@ -1741,6 +1745,7 @@ void Node::build_accessibility_tree(AccessibilityTreeNode& parent) if (document_element->has_child_nodes()) document_element->for_each_child([&parent](DOM::Node& child) { child.build_accessibility_tree(parent); + return IterationDecision::Continue; }); } } else if (is_element()) { @@ -1755,11 +1760,13 @@ void Node::build_accessibility_tree(AccessibilityTreeNode& parent) if (has_child_nodes()) { for_each_child([¤t_node](DOM::Node& child) { child.build_accessibility_tree(*current_node); + return IterationDecision::Continue; }); } } else if (has_child_nodes()) { for_each_child([&parent](DOM::Node& child) { child.build_accessibility_tree(parent); + return IterationDecision::Continue; }); } } else if (is_text()) { @@ -1767,6 +1774,7 @@ void Node::build_accessibility_tree(AccessibilityTreeNode& parent) if (has_child_nodes()) { for_each_child([&parent](DOM::Node& child) { child.build_accessibility_tree(parent); + return IterationDecision::Continue; }); } } @@ -1865,7 +1873,7 @@ ErrorOr Node::name_or_description(NameOrDescription target, Document con element->for_each_child([&total_accumulated_text, current_node, target, &document, &visited_nodes]( DOM::Node const& child_node) mutable { if (visited_nodes.contains(child_node.unique_id())) - return; + return IterationDecision::Continue; // a. Set the current node to the child node. current_node = &child_node; @@ -1875,6 +1883,8 @@ ErrorOr Node::name_or_description(NameOrDescription target, Document con // c. Append the result to the accumulated text. total_accumulated_text.append(result); + + return IterationDecision::Continue; }); // iv. Return the accumulated text. return total_accumulated_text.to_string(); diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h index fbd2bbc4b1b..10f0aff3051 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -560,16 +560,20 @@ public: template void for_each_child(Callback callback) { - for (auto* node = first_child(); node; node = node->next_sibling()) - callback(*node); + for (auto* node = first_child(); node; node = node->next_sibling()) { + if (callback(*node) == IterationDecision::Break) + return; + } } template void for_each_child_of_type(Callback callback) { for (auto* node = first_child(); node; node = node->next_sibling()) { - if (is(node)) - callback(verify_cast(*node)); + if (is(node)) { + if (callback(verify_cast(*node)) == IterationDecision::Break) + return; + } } } diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.h b/Userland/Libraries/LibWeb/DOM/ParentNode.h index a84d23d07a6..a8a56571dc5 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.h +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.h @@ -70,15 +70,19 @@ inline U* Node::shadow_including_first_ancestor_of_type() template inline void ParentNode::for_each_child(Callback callback) const { - for (auto* node = first_child(); node; node = node->next_sibling()) - callback(*node); + for (auto* node = first_child(); node; node = node->next_sibling()) { + if (callback(*node) == IterationDecision::Break) + return; + } } template inline void ParentNode::for_each_child(Callback callback) { - for (auto* node = first_child(); node; node = node->next_sibling()) - callback(*node); + for (auto* node = first_child(); node; node = node->next_sibling()) { + if (callback(*node) == IterationDecision::Break) + return; + } } } diff --git a/Userland/Libraries/LibWeb/DOM/Slottable.cpp b/Userland/Libraries/LibWeb/DOM/Slottable.cpp index db732420ed2..b48a268d59c 100644 --- a/Userland/Libraries/LibWeb/DOM/Slottable.cpp +++ b/Userland/Libraries/LibWeb/DOM/Slottable.cpp @@ -134,7 +134,7 @@ Vector find_slottables(JS::NonnullGCPtr slot) else { host->for_each_child([&](auto& node) { if (!node.is_slottable()) - return; + return IterationDecision::Continue; auto slottable = node.as_slottable(); @@ -144,6 +144,8 @@ Vector find_slottables(JS::NonnullGCPtr slot) // 2. If foundSlot is slot, then append slottable to result. if (found_slot == slot) result.append(move(slottable)); + + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index 2f5727da1a7..93cdc187a24 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -118,6 +118,7 @@ void dump_tree(StringBuilder& builder, DOM::Node const& node) if (!is(node)) { static_cast(node).for_each_child([&](auto& child) { dump_tree(builder, child); + return IterationDecision::Continue; }); } else { auto& template_element = verify_cast(node); @@ -403,6 +404,7 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho ++indent; layout_node.for_each_child([&](auto& child) { dump_tree(builder, child, show_box_model, show_specified_style, interactive); + return IterationDecision::Continue; }); --indent; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 4d7a6288f5c..a15ae9d3e12 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -864,6 +864,7 @@ static void update_the_source_set(DOM::Element& element) elements.clear(); element.parent()->for_each_child_of_type([&](auto& child) { elements.append(&child); + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index fa1792d9bc3..5155c1da098 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -135,6 +135,7 @@ void HTMLInputElement::set_checked(bool checked, ChangeSource change_source) if (parent()) { parent()->for_each_child([&](auto& child) { child.invalidate_style(); + return IterationDecision::Continue; }); } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp index 82703e56011..27d19a1d007 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp @@ -85,6 +85,7 @@ static void concatenate_descendants_text_content(DOM::Node const* node, StringBu builder.append(verify_cast(node)->data()); node->for_each_child([&](auto const& node) { concatenate_descendants_text_content(&node, builder); + return IterationDecision::Continue; }); } @@ -98,6 +99,7 @@ String HTMLOptionElement::text() const // script or SVG script elements. for_each_child([&](auto const& node) { concatenate_descendants_text_content(&node, builder); + return IterationDecision::Continue; }); // Return the result of stripping and collapsing ASCII whitespace from the above concatenation. diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp index 997450e2a6e..bee35291fda 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp @@ -174,12 +174,15 @@ Vector> HTMLSelectElement::list_of_options() const for_each_child_of_type([&](HTMLOptionElement& option_element) { list.append(JS::make_handle(option_element)); + return IterationDecision::Continue; }); for_each_child_of_type([&](HTMLOptGroupElement const& optgroup_element) { optgroup_element.for_each_child_of_type([&](HTMLOptionElement& option_element) { list.append(JS::make_handle(option_element)); + return IterationDecision::Continue; }); + return IterationDecision::Continue; }); return list; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp index 7be0a0d4290..ef6b08b1fe0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp @@ -58,6 +58,8 @@ void HTMLTemplateElement::cloned(Node& copy, bool clone_children) // FIXME: Should this use TreeNode::append_child instead? MUST(template_clone.content()->append_child(cloned_child)); + + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index 1abf7646c41..a6056d86d5f 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -4418,7 +4418,8 @@ String HTMLParser::serialize_html_fragment(DOM::Node const& node, DOM::FragmentS if (is(current_node)) { // -> If current node is an Element auto& element = verify_cast(current_node); - return serialize_element(element); + serialize_element(element); + return IterationDecision::Continue; } if (is(current_node)) { @@ -4440,7 +4441,6 @@ String HTMLParser::serialize_html_fragment(DOM::Node const& node, DOM::FragmentS // 2. Otherwise, append the value of current node's data IDL attribute, escaped as described below. builder.append(escape_string(text_node.data(), AttributeMode::No)); - return IterationDecision::Continue; } if (is(current_node)) { diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index ecb34e65991..1643ca7f75c 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -1215,6 +1215,7 @@ CSSPixels BlockFormattingContext::greatest_child_width(Box const& box) const box.for_each_child_of_type([&](Box const& child) { if (!child.is_absolutely_positioned()) max_width = max(max_width, m_state.get(child).margin_box_width()); + return IterationDecision::Continue; }); } return max_width; diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index b6f6416e14b..d7b40be447a 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -199,6 +199,7 @@ void FlexFormattingContext::parent_context_did_dimension_child_root_box() auto available_height = AvailableSize::make_definite(cb_state.content_height() + cb_state.padding_top + cb_state.padding_bottom); layout_absolutely_positioned_element(box, AvailableSpace(available_width, available_height)); } + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index c5f56b8f95a..bc8d76fdc8d 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -243,6 +243,7 @@ CSSPixels FormattingContext::greatest_child_width(Box const& box) const box.for_each_child_of_type([&](Box const& child) { if (!child.is_absolutely_positioned()) max_width = max(max_width, m_state.get(child).margin_box_width()); + return IterationDecision::Continue; }); } return max_width; diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 2a76ce7fc99..eb443015677 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1940,6 +1940,7 @@ void GridFormattingContext::parent_context_did_dimension_child_root_box() auto available_height = AvailableSize::make_definite(cb_state.content_height() + cb_state.padding_top + cb_state.padding_bottom); layout_absolutely_positioned_element(box, AvailableSpace(available_width, available_height)); } + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index 2f079d5f773..62160c56f26 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -127,6 +127,8 @@ static CSSPixelRect measure_scrollable_overflow(Box const& box) for (auto const& fragment : static_cast(*child.paintable()).fragments()) scrollable_overflow_rect = scrollable_overflow_rect.united(fragment.absolute_rect()); } + + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 5e8c80f4f28..3a5f4a4ec9d 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -882,6 +882,7 @@ void NodeWithStyle::propagate_style_to_anonymous_wrappers() auto& child_computed_values = static_cast(static_cast(const_cast(child.computed_values()))); child_computed_values.inherit_from(computed_values()); } + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index 0424b923665..800b0873cad 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -250,6 +250,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& box.for_each_child_of_type([&](Box const& child) { layout_svg_element(child); + return IterationDecision::Continue; }); } @@ -264,6 +265,7 @@ void SVGFormattingContext::layout_svg_element(Box const& child) child_state.set_content_offset(child_state.offset.translated(m_svg_offset)); child.for_each_child_of_type([&](SVGMaskBox const& child) { layout_svg_element(child); + return IterationDecision::Continue; }); } else if (is(child)) { layout_graphics_element(static_cast(child)); @@ -369,6 +371,7 @@ void SVGFormattingContext::layout_path_like_element(SVGGraphicsBox const& graphi text_box.for_each_child_of_type([&](auto& child) { if (is(child) || is(child)) layout_graphics_element(child); + return IterationDecision::Continue; }); } else if (is(graphics_box)) { // FIXME: Support in . @@ -446,11 +449,12 @@ void SVGFormattingContext::layout_container_element(SVGBox const& container) container.for_each_child_of_type([&](Box const& child) { // Masks/clips do not change the bounding box of their parents. if (is(child) || is(child)) - return; + return IterationDecision::Continue; layout_svg_element(child); auto& child_state = m_state.get(child); bounding_box.add_point(child_state.offset); bounding_box.add_point(child_state.offset.translated(child_state.content_width(), child_state.content_height())); + return IterationDecision::Continue; }); box_state.set_content_x(bounding_box.x()); box_state.set_content_y(bounding_box.y()); diff --git a/Userland/Libraries/LibWeb/Layout/TableGrid.h b/Userland/Libraries/LibWeb/Layout/TableGrid.h index 231a300edb7..de1ae3699ba 100644 --- a/Userland/Libraries/LibWeb/Layout/TableGrid.h +++ b/Userland/Libraries/LibWeb/Layout/TableGrid.h @@ -76,6 +76,7 @@ public: parent.for_each_child_of_type([&](Box const& child_box) { if (matcher(child_box)) callback(child_box); + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index dd157a6f6d6..b14d2e121a0 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -553,6 +553,7 @@ void TreeBuilder::remove_irrelevant_boxes(NodeWithStyle& root) for_each_in_tree_with_internal_display(root, [&](Box& table_column) { table_column.for_each_child([&](auto& child) { to_remove.append(child); + return IterationDecision::Continue; }); }); @@ -561,6 +562,7 @@ void TreeBuilder::remove_irrelevant_boxes(NodeWithStyle& root) table_column_group.for_each_child([&](auto& child) { if (!child.display().is_table_column()) to_remove.append(child); + return IterationDecision::Continue; }); }); @@ -770,6 +772,7 @@ static void for_each_child_box_matching(Box& parent, Matcher matcher, Callback c parent.for_each_child_of_type([&](Box& child_box) { if (matcher(child_box)) callback(child_box); + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index 198b978c8c7..de4152f75ff 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -211,12 +211,13 @@ TraversalDecision InlinePaintable::hit_test(CSSPixelPoint position, HitTestType bool should_exit = false; for_each_child([&](Paintable const& child) { - if (should_exit) - return; if (child.stacking_context()) - return; - if (child.hit_test(position, type, callback) == TraversalDecision::Break) + return IterationDecision::Continue; + if (child.hit_test(position, type, callback) == TraversalDecision::Break) { should_exit = true; + return IterationDecision::Break; + } + return IterationDecision::Continue; }); if (should_exit) diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 15d6186d3bf..820b3448807 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -112,13 +112,13 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const& // FIXME: This may not be fully correct with respect to the paint phases. if (phase == StackingContextPaintPhase::Foreground) paint_node_as_stacking_context(child, context); - return; + return IterationDecision::Continue; } if (stacking_context && z_index.value_or(0) != 0) - return; + return IterationDecision::Continue; if (child.is_positioned() && z_index.value_or(0) == 0) - return; + return IterationDecision::Continue; if (stacking_context) { // FIXME: This may not be fully correct with respect to the paint phases. @@ -126,7 +126,7 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const& paint_child(context, *stacking_context); } // Note: Don't further recurse into descendants as paint_child() will do that. - return; + return IterationDecision::Continue; } bool child_is_inline_or_replaced = child.is_inline() || is(child.layout_node()); @@ -171,6 +171,8 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const& paint_descendants(context, child, phase); break; } + + return IterationDecision::Continue; }); paintable.after_children_paint(context, to_paint_phase(phase)); diff --git a/Userland/Libraries/LibWeb/Painting/TableBordersPainting.cpp b/Userland/Libraries/LibWeb/Painting/TableBordersPainting.cpp index fe0399a1b3b..1a06ddc14ca 100644 --- a/Userland/Libraries/LibWeb/Painting/TableBordersPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/TableBordersPainting.cpp @@ -38,7 +38,7 @@ static void collect_cell_boxes(Vector& cell_boxes, Paintabl } else { collect_cell_boxes(cell_boxes, child); } - return TraversalDecision::Continue; + return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/SVG/SVGGradientElement.h b/Userland/Libraries/LibWeb/SVG/SVGGradientElement.h index 096d9b6705b..f03e38cd597 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGradientElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGGradientElement.h @@ -76,6 +76,7 @@ private: for_each_child_of_type([&](auto& stop) { color_stops_found = true; callback(stop); + return IterationDecision::Continue; }); if (!color_stops_found) { if (auto gradient = linked_gradient(seen_gradients)) diff --git a/Userland/Libraries/LibWeb/TreeNode.h b/Userland/Libraries/LibWeb/TreeNode.h index 2c045e53fd8..a419c978215 100644 --- a/Userland/Libraries/LibWeb/TreeNode.h +++ b/Userland/Libraries/LibWeb/TreeNode.h @@ -224,16 +224,20 @@ public: template void for_each_child(Callback callback) { - for (auto* node = first_child(); node; node = node->next_sibling()) - callback(*node); + for (auto* node = first_child(); node; node = node->next_sibling()) { + if (callback(*node) == IterationDecision::Break) + return; + } } template void for_each_child_of_type(Callback callback) { for (auto* node = first_child(); node; node = node->next_sibling()) { - if (is(node)) - callback(verify_cast(*node)); + if (is(node)) { + if (callback(verify_cast(*node)) == IterationDecision::Break) + return; + } } }