From 49730156ae7f5bab430051f22e0140498611bdc7 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 12 Jun 2026 17:46:21 +0200 Subject: [PATCH] LibWeb: Avoid media rule reevaluation for matchMedia Separate MediaQueryList change reporting from stylesheet media rule invalidation. Creating matchMedia() objects evaluates their own baseline state, but should not make the next style update walk all active stylesheets when the media environment has not changed. This avoids continuous stylesheet media query reevaluation during YouTube video playback, where repeated matchMedia() creation can make style flushes do unnecessary work. --- .../Invalidation/MediaQueryInvalidator.cpp | 2 + Libraries/LibWeb/DOM/Document.cpp | 77 ++++++++++--------- Libraries/LibWeb/DOM/Document.h | 10 ++- Libraries/LibWeb/Internals/Internals.cpp | 1 + .../match-media-does-not-evaluate-rules.txt | 1 + .../match-media-does-not-evaluate-rules.html | 27 +++++++ 6 files changed, 81 insertions(+), 37 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/style-invalidation/match-media-does-not-evaluate-rules.txt create mode 100644 Tests/LibWeb/Text/input/css/style-invalidation/match-media-does-not-evaluate-rules.html diff --git a/Libraries/LibWeb/CSS/Invalidation/MediaQueryInvalidator.cpp b/Libraries/LibWeb/CSS/Invalidation/MediaQueryInvalidator.cpp index aef93b368c..0324b0fd20 100644 --- a/Libraries/LibWeb/CSS/Invalidation/MediaQueryInvalidator.cpp +++ b/Libraries/LibWeb/CSS/Invalidation/MediaQueryInvalidator.cpp @@ -44,6 +44,8 @@ static void invalidate_style_after_media_rule_changes(DOM::Node& root, MediaQuer void evaluate_media_rules_and_invalidate_style(DOM::Document& document) { + ++document.style_invalidation_counters().media_rule_evaluations; + bool document_media_queries_changed_match_state = false; MediaQueryRuleInvalidation document_invalidation; document.style_scope().for_each_active_css_style_sheet([&](CSS::CSSStyleSheet& style_sheet) { diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index c2142ad2ed..2607e92f8b 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -237,7 +237,7 @@ static Optional s_style_invalidation_counter_dump_interval; static void dump_style_invalidation_counters(Document const& document) { auto const& counters = document.style_invalidation_counters(); - dbgln("Style invalidation counters for {}: styleInvalidations={}, fullStyleInvalidations={}, elementStyleRecomputations={}, elementStyleNoopRecomputations={}, elementInheritedStyleRecomputations={}, elementInheritedStyleNoopRecomputations={}, previousSiblingInvalidationWalkVisits={}, hasAncestorWalkInvocations={}, hasAncestorWalkVisits={}, hasAncestorSiblingElementChecks={}, hasInvalidationMetadataCandidates={}, hasMatchInvocations={}, hasResultCacheHits={}, hasResultCacheMisses={}", + dbgln("Style invalidation counters for {}: styleInvalidations={}, fullStyleInvalidations={}, elementStyleRecomputations={}, elementStyleNoopRecomputations={}, elementInheritedStyleRecomputations={}, elementInheritedStyleNoopRecomputations={}, previousSiblingInvalidationWalkVisits={}, mediaRuleEvaluations={}, hasAncestorWalkInvocations={}, hasAncestorWalkVisits={}, hasAncestorSiblingElementChecks={}, hasInvalidationMetadataCandidates={}, hasMatchInvocations={}, hasResultCacheHits={}, hasResultCacheMisses={}", document.url_string(), counters.style_invalidations, counters.full_style_invalidations, @@ -246,6 +246,7 @@ static void dump_style_invalidation_counters(Document const& document) counters.element_inherited_style_recomputations, counters.element_inherited_style_noop_recomputations, counters.previous_sibling_invalidation_walk_visits, + counters.media_rule_evaluations, counters.has_ancestor_walk_invocations, counters.has_ancestor_walk_visits, counters.has_ancestor_sibling_element_checks, @@ -2201,14 +2202,14 @@ void Document::update_style() CSS::Invalidation::invalidate_style_for_pending_has_mutations(*this); } - if (!m_style_invalidator->has_pending_invalidations() && !needs_full_style_update() && !needs_style_update() && !child_needs_style_update() && !m_needs_media_query_evaluation) + if (!m_style_invalidator->has_pending_invalidations() && !needs_full_style_update() && !needs_style_update() && !child_needs_style_update() && !m_needs_media_rule_evaluation) return; // NOTE: If this is a document hosting