LibWeb: Avoid invalidation on .textContent setter no-op

When setting the textContent of an element with no children to null or
the empty string, nothing happens. Even so, we were still invalidating
style, layout and collections, causing pointless churn.

Skipping invalidation in this case also revealed that we were missing
invalidation when changing the selected state of HTMLOptionElement.
This was all caught by existing tests already in-tree. :^)
This commit is contained in:
Andreas Kling 2025-01-03 14:46:24 +01:00 committed by Andreas Kling
parent 8214371ad5
commit 49a7a0f378
Notes: github-actions[bot] 2025-01-05 12:37:11 +00:00
3 changed files with 8 additions and 0 deletions

View file

@ -202,6 +202,10 @@ void Node::set_text_content(Optional<String> const& maybe_content)
// If DocumentFragment or Element, string replace all with the given value within this.
if (is<DocumentFragment>(this) || is<Element>(this)) {
// OPTIMIZATION: Replacing nothing with nothing is a no-op. Avoid all invalidation in this case.
if (!first_child() && content.is_empty()) {
return;
}
string_replace_all(content);
}

View file

@ -74,6 +74,7 @@ enum class IsDescendant {
X(HTMLIFrameElementGeometryChange) \
X(HTMLInputElementSetChecked) \
X(HTMLObjectElementUpdateLayoutAndChildObjects) \
X(HTMLOptionElementSelectedChange) \
X(HTMLSelectElementSetIsOpen) \
X(Hover) \
X(MediaQueryChangedMatchState) \

View file

@ -68,6 +68,9 @@ void HTMLOptionElement::set_selected(bool selected)
void HTMLOptionElement::set_selected_internal(bool selected)
{
if (m_selected != selected)
invalidate_style(DOM::StyleInvalidationReason::HTMLOptionElementSelectedChange);
m_selected = selected;
if (selected)
m_selectedness_update_index = m_next_selectedness_update_index++;