LibWeb: Don't treat first media-query evaluation as a flip

CSSStyleSheet::evaluate_media_queries previously flagged "no recorded
result yet" as a match-state change, so every freshly-loaded sheet
fired MediaQueryChangedMatchState on the first pass through
Document::evaluate_media_rules. For sheets added through
adoptedStyleSheets that piled an extra full-document style invalidation
on top of the AdoptedStyleSheetsList one, recomputing every element a
second time for nothing.

Drop the !has_value() leg so the very first evaluation establishes the
baseline silently. The sheet's rules already entered the cascade through
StyleSheetListAddSheet, AdoptedStyleSheetsList, or invalidate_owners,
each of which performs its own targeted invalidation.

Two callers relied on the implicit "first eval forces a refresh"
behavior to handle freshly-mutated state:

- invalidate_owners resets m_did_match, then leans on the next eval to
  repopulate it. With the new semantics it must also re-evaluate the
  sheet eagerly so MediaList::matches() and inner @media state are
  fresh before the next rule cache build reads them.
- The adoptedStyleSheets on_set callback didn't evaluate at all,
  relying on Document::evaluate_media_rules to populate
  MediaList::m_matches. That worked accidentally because the false
  flip retriggered invalidate_rule_cache after the matches had been
  populated. Mirror StyleSheetList::add_sheet by evaluating the sheet
  at adopt time so the rule cache build sees the correct match state
  even if it runs first (e.g. via a :has() invalidation pass).
This commit is contained in:
Andreas Kling 2026-04-28 15:32:45 +02:00 committed by Andreas Kling
parent 3b098c08ea
commit f10f651e49
6 changed files with 72 additions and 43 deletions

View file

@ -439,6 +439,13 @@ void CSSStyleSheet::invalidate_owners(DOM::StyleInvalidationReason reason, Shado
{
m_did_match = {};
invalidate_shared_style_cache();
// The MediaList may have been mutated (e.g. via MediaList::set_media_text), and owner invalidation computes
// shadow-root effects from effective rules. Refresh the media state first so host-side shadow invalidation
// sees the updated definitions.
if (auto document = owning_document())
evaluate_media_queries(*document);
invalidate_style_for_style_sheet_owners(*this, reason, ShouldInvalidateRuleCache::Yes, previous_sheet_effects);
}
@ -470,7 +477,11 @@ bool CSSStyleSheet::evaluate_media_queries(DOM::Document const& document)
bool any_media_queries_changed_match_state = false;
bool now_matches = m_media->evaluate(document);
if (!m_did_match.has_value() || m_did_match.value() != now_matches)
// The first evaluation establishes the baseline. The sheet's rules already entered the cascade through
// StyleSheetListAddSheet, AdoptedStyleSheetsList, or invalidate_owners (each of which performs its own
// invalidation), so we don't need to also report a match-state change just because no prior result was
// recorded.
if (m_did_match.has_value() && m_did_match.value() != now_matches)
any_media_queries_changed_match_state = true;
if (now_matches && m_rules->evaluate_media_queries(document))
any_media_queries_changed_match_state = true;

View file

@ -10,6 +10,7 @@
#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/MediaList.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleSheetInvalidation.h>
#include <LibWeb/Dump.h>
#include <LibWeb/WebIDL/DOMException.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
@ -51,9 +52,13 @@ String MediaList::media_text() const
// https://www.w3.org/TR/cssom-1/#dom-medialist-mediatext
void MediaList::set_media_text(StringView text)
{
auto previous_sheet_effects = m_associated_style_sheet
? Optional<ShadowRootStylesheetEffects> { determine_shadow_root_stylesheet_effects(as<CSS::CSSStyleSheet>(*m_associated_style_sheet)) }
: Optional<ShadowRootStylesheetEffects> {};
ScopeGuard guard = [&] {
if (m_associated_style_sheet)
as<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListSetMediaText);
as<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListSetMediaText, previous_sheet_effects.has_value() ? &previous_sheet_effects.value() : nullptr);
};
m_media.clear();
@ -88,11 +93,15 @@ void MediaList::append_medium(StringView medium)
return;
}
auto previous_sheet_effects = m_associated_style_sheet
? Optional<ShadowRootStylesheetEffects> { determine_shadow_root_stylesheet_effects(as<CSS::CSSStyleSheet>(*m_associated_style_sheet)) }
: Optional<ShadowRootStylesheetEffects> {};
// 4. Append m to the collection of media queries.
m_media.append(m.release_nonnull());
if (m_associated_style_sheet)
as<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListAppendMedium);
as<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListAppendMedium, previous_sheet_effects.has_value() ? &previous_sheet_effects.value() : nullptr);
}
// https://www.w3.org/TR/cssom-1/#dom-medialist-deletemedium
@ -105,6 +114,10 @@ WebIDL::ExceptionOr<void> MediaList::delete_medium(StringView medium)
if (!m)
return {};
auto previous_sheet_effects = m_associated_style_sheet
? Optional<ShadowRootStylesheetEffects> { determine_shadow_root_stylesheet_effects(as<CSS::CSSStyleSheet>(*m_associated_style_sheet)) }
: Optional<ShadowRootStylesheetEffects> {};
// 3. Remove any media query from the collection of media queries for which comparing the media query with m
// returns true. If nothing was removed, then throw a NotFoundError exception.
bool was_removed = m_media.remove_all_matching([&](auto& existing) -> bool {
@ -114,7 +127,7 @@ WebIDL::ExceptionOr<void> MediaList::delete_medium(StringView medium)
return WebIDL::NotFoundError::create(realm(), "Media query not found in list"_utf16);
if (m_associated_style_sheet)
as<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListDeleteMedium);
as<CSS::CSSStyleSheet>(*m_associated_style_sheet).invalidate_owners(DOM::StyleInvalidationReason::MediaListDeleteMedium, previous_sheet_effects.has_value() ? &previous_sheet_effects.value() : nullptr);
return {};
}

View file

@ -32,6 +32,11 @@ GC::Ref<WebIDL::ObservableArray> create_adopted_style_sheets_list(Node& document
style_sheet->load_pending_image_resources(document_or_shadow_root.document());
// Evaluate the sheet's media queries before the next style update so the cascade can see its rules.
// Otherwise the rule cache may be rebuilt (e.g. via a :has() invalidation pass) before
// Document::evaluate_media_rules has a chance to populate MediaList::m_matches.
style_sheet->evaluate_media_queries(document_or_shadow_root.document());
auto& style_scope = document_or_shadow_root.is_shadow_root() ? as<DOM::ShadowRoot>(document_or_shadow_root).style_scope() : document_or_shadow_root.document().style_scope();
style_scope.invalidate_rule_cache();
document_or_shadow_root.invalidate_style(DOM::StyleInvalidationReason::AdoptedStyleSheetsList);

View file

@ -1,3 +1,3 @@
PASS: shadow-local replaceSync ignores matching light-DOM bystanders (0 invalidations)
PASS: shadow-local replaceSync stays bounded on subsequent updates (0 invalidations)
PASS: shadow-local replaceSync clearing the sheet avoids extra full-document restyles (1 full invalidations)
PASS: shadow-local replaceSync clearing the sheet avoids extra full-document restyles (0 full invalidations)

View file

@ -1,15 +1,15 @@
PASS: adopt sheet with empty outer media | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer media=all | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer media=screen (matches) | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer media=print (does not match) | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer width media that matches | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer width media that does not match | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with rule that matches no element | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with inner @media that matches | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with inner @media that does not match | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with non-matching outer media wrapping a matching inner @media | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with multiple inner @media rules, all matching | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with multiple inner @media rules, none matching | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with mixed matching and non-matching inner @media rules | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with nested inner @media rules | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with @supports wrapping an inner @media | styleInvalidations=0, fullStyleInvalidations=2, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with empty outer media | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer media=all | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer media=screen (matches) | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer media=print (does not match) | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer width media that matches | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with outer width media that does not match | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with rule that matches no element | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with inner @media that matches | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with inner @media that does not match | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with non-matching outer media wrapping a matching inner @media | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with multiple inner @media rules, all matching | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with multiple inner @media rules, none matching | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=11, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with mixed matching and non-matching inner @media rules | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with nested inner @media rules | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: adopt sheet with @supports wrapping an inner @media | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=11, elementStyleNoopRecomputations=10, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0

View file

@ -1,24 +1,24 @@
PASS: shadow media mutation activates bare :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates classed :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates attributed :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates negated :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates :host :is selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates :host :where selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation deactivates classed :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media appendMedium activates :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media deleteMedium deactivates :host selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates internal rule guarded by :host | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted class selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted type and class selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted attribute selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted :is selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted :not selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates named-slot ::slotted selector | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates slotted background style | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates bare slot inheritance | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=12, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates named slot inheritance | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=12, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates descendant slot inheritance | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=12, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates nested host structure | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates paragraph assigned node | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates bare :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates classed :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates attributed :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates negated :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates :host :is selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates :host :where selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation deactivates classed :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media appendMedium activates :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media deleteMedium deactivates :host selector | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates internal rule guarded by :host | styleInvalidations=0, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=13, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted class selector | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted type and class selector | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted attribute selector | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted :is selector | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates ::slotted :not selector | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates named-slot ::slotted selector | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates slotted background style | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates bare slot inheritance | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=3, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates named slot inheritance | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=3, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates descendant slot inheritance | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=3, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates nested host structure | styleInvalidations=1, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=0, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates paragraph assigned node | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=4, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates compound host and slotted selectors | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=9, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates inner and slotted selectors together | styleInvalidations=1, fullStyleInvalidations=1, elementStyleRecomputations=14, elementStyleNoopRecomputations=12, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0
PASS: shadow media mutation activates inner and slotted selectors together | styleInvalidations=0, fullStyleInvalidations=0, elementStyleRecomputations=5, elementStyleNoopRecomputations=3, elementInheritedStyleRecomputations=0, elementInheritedStyleNoopRecomputations=0, hasAncestorWalkInvocations=0, hasInvalidationMetadataCandidates=0, hasMatchInvocations=0, hasResultCacheHits=0, hasResultCacheMisses=0