diff --git a/Libraries/LibWeb/Animations/KeyframeEffect.cpp b/Libraries/LibWeb/Animations/KeyframeEffect.cpp index 136f3b08b8d..b7db16ffdea 100644 --- a/Libraries/LibWeb/Animations/KeyframeEffect.cpp +++ b/Libraries/LibWeb/Animations/KeyframeEffect.cpp @@ -964,7 +964,7 @@ void KeyframeEffect::update_computed_properties() if (invalidation.relayout) document.set_needs_layout(); if (invalidation.rebuild_layout_tree) - document.invalidate_layout_tree(); + document.invalidate_layout_tree(DOM::InvalidateLayoutTreeReason::KeyframeEffect); if (invalidation.repaint) { document.set_needs_display(); document.set_needs_to_resolve_paint_only_properties(); diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index d94e72c3605..26d9eaf3810 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -1219,8 +1219,10 @@ void Document::set_needs_layout() schedule_layout_update(); } -void Document::invalidate_layout_tree() +void Document::invalidate_layout_tree(InvalidateLayoutTreeReason reason) { + if (m_layout_root) + dbgln_if(UPDATE_LAYOUT_DEBUG, "DROP TREE {}", to_string(reason)); tear_down_layout_tree(); schedule_layout_update(); } @@ -3394,7 +3396,7 @@ void Document::evaluate_media_rules() if (any_media_queries_changed_match_state) { style_computer().invalidate_rule_cache(); invalidate_style(StyleInvalidationReason::MediaQueryChangedMatchState); - invalidate_layout_tree(); + invalidate_layout_tree(InvalidateLayoutTreeReason::MediaQueryChangedMatchState); } } @@ -5953,7 +5955,7 @@ void Document::add_an_element_to_the_top_layer(GC::Ref element) // FIXME: 4. At the UA !important cascade origin, add a rule targeting el containing an overlay: auto declaration. element->set_rendered_in_top_layer(true); element->set_needs_style_update(true); - invalidate_layout_tree(); + invalidate_layout_tree(InvalidateLayoutTreeReason::DocumentAddAnElementToTheTopLayer); } // https://drafts.csswg.org/css-position-4/#request-an-element-to-be-removed-from-the-top-layer @@ -5968,7 +5970,7 @@ void Document::request_an_element_to_be_remove_from_the_top_layer(GC::Refset_rendered_in_top_layer(false); element->set_needs_style_update(true); - invalidate_layout_tree(); + invalidate_layout_tree(InvalidateLayoutTreeReason::DocumentRequestAnElementToBeRemovedFromTheTopLayer); // 4. Append el to doc’s pending top layer removals. m_top_layer_pending_removals.set(element); @@ -6403,6 +6405,18 @@ void Document::set_onvisibilitychange(WebIDL::CallbackType* value) set_event_handler_attribute(HTML::EventNames::visibilitychange, value); } +StringView to_string(InvalidateLayoutTreeReason reason) +{ + switch (reason) { +#define ENUMERATE_INVALIDATE_LAYOUT_TREE_REASON(e) \ + case InvalidateLayoutTreeReason::e: \ + return #e##sv; + ENUMERATE_INVALIDATE_LAYOUT_TREE_REASONS(ENUMERATE_INVALIDATE_LAYOUT_TREE_REASON) +#undef ENUMERATE_INVALIDATE_LAYOUT_TREE_REASON + } + VERIFY_NOT_REACHED(); +} + StringView to_string(UpdateLayoutReason reason) { switch (reason) { diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index a9e4be402e0..07a4488da49 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -50,6 +50,26 @@ enum class QuirksMode { Yes }; +#define ENUMERATE_INVALIDATE_LAYOUT_TREE_REASONS(X) \ + X(DocumentAddAnElementToTheTopLayer) \ + X(DocumentRequestAnElementToBeRemovedFromTheTopLayer) \ + X(HTMLInputElementSrcAttributeChange) \ + X(HTMLObjectElement) \ + X(KeyframeEffect) \ + X(MediaQueryChangedMatchState) \ + X(SVGGraphicsElementTransformAttributeChange) \ + X(SVGUseElement) \ + X(ShadowRootSetInnerHTML) \ + X(UpdateFileInputShadowTree) + +enum class InvalidateLayoutTreeReason { +#define ENUMERATE_INVALIDATE_LAYOUT_TREE_REASON(e) e, + ENUMERATE_INVALIDATE_LAYOUT_TREE_REASONS(ENUMERATE_INVALIDATE_LAYOUT_TREE_REASON) +#undef ENUMERATE_INVALIDATE_LAYOUT_TREE_REASON +}; + +[[nodiscard]] StringView to_string(InvalidateLayoutTreeReason); + #define ENUMERATE_UPDATE_LAYOUT_REASONS(X) \ X(CanvasRenderingContext2DSetFilter) \ X(CursorBlinkTimer) \ @@ -322,7 +342,7 @@ public: void set_needs_layout(); - void invalidate_layout_tree(); + void invalidate_layout_tree(InvalidateLayoutTreeReason); void invalidate_stacking_context_tree(); virtual bool is_child_allowed(Node const&) const override; diff --git a/Libraries/LibWeb/DOM/ShadowRoot.cpp b/Libraries/LibWeb/DOM/ShadowRoot.cpp index 6e6b19f47ad..d84a92ec958 100644 --- a/Libraries/LibWeb/DOM/ShadowRoot.cpp +++ b/Libraries/LibWeb/DOM/ShadowRoot.cpp @@ -88,7 +88,7 @@ WebIDL::ExceptionOr ShadowRoot::set_inner_html(StringView value) if (this->is_connected()) { // NOTE: Since the DOM has changed, we have to rebuild the layout tree. - this->document().invalidate_layout_tree(); + this->document().invalidate_layout_tree(InvalidateLayoutTreeReason::ShadowRootSetInnerHTML); } } diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 2480d631bed..c9784955c22 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -1129,7 +1129,7 @@ void HTMLInputElement::update_file_input_shadow_tree() m_file_label->set_text_content(MUST(String::formatted("No {} selected.", files_label))); } - document().invalidate_layout_tree(); + document().invalidate_layout_tree(DOM::InvalidateLayoutTreeReason::UpdateFileInputShadowTree); } void HTMLInputElement::create_range_input_shadow_tree() @@ -1458,7 +1458,7 @@ WebIDL::ExceptionOr HTMLInputElement::handle_src_attribute(String const& v }); m_load_event_delayer.clear(); - document().invalidate_layout_tree(); + document().invalidate_layout_tree(DOM::InvalidateLayoutTreeReason::HTMLInputElementSrcAttributeChange); }, [this, &realm]() { // 2. Otherwise, if the fetching process fails without a response from the remote server, or completes but the diff --git a/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index 4796d4d7b9e..86c257cdfe6 100644 --- a/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -561,7 +561,7 @@ void HTMLObjectElement::update_layout_and_child_objects(Representation represent m_representation = representation; invalidate_style(DOM::StyleInvalidationReason::HTMLObjectElementUpdateLayoutAndChildObjects); - document().invalidate_layout_tree(); + document().invalidate_layout_tree(DOM::InvalidateLayoutTreeReason::HTMLObjectElement); } // https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex diff --git a/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp b/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp index aa0aa49163e..a0135980514 100644 --- a/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp +++ b/Libraries/LibWeb/SVG/SVGGraphicsElement.cpp @@ -46,7 +46,7 @@ void SVGGraphicsElement::attribute_changed(FlyString const& name, Optional