Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 108882fa38bbbc35c63c7048cd5670ec6af5344e
      
https://github.com/WebKit/WebKit/commit/108882fa38bbbc35c63c7048cd5670ec6af5344e
  Author: Antti Koivisto <[email protected]>
  Date:   2026-04-27 (Mon, 27 Apr 2026)

  Changed paths:
    M LayoutTests/fast/selectors/has-invalidation-traversal-size-expected.txt
    R LayoutTests/fast/selectors/has-scope-breaking-classification-expected.txt
    R LayoutTests/fast/selectors/has-scope-breaking-classification.html
    M 
LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-nth-child-expected.txt
    M Source/WebCore/css/SelectorChecker.cpp
    M Source/WebCore/style/ChildChangeInvalidation.cpp
    M Source/WebCore/style/ChildChangeInvalidation.h
    M Source/WebCore/style/ClassChangeInvalidation.cpp
    M Source/WebCore/style/RuleFeature.cpp
    M Source/WebCore/style/RuleFeature.h
    M Source/WebCore/style/StyleInvalidator.cpp
    M Source/WebCore/style/StyleInvalidator.h
    M Source/WebCore/style/StyleScopeRuleSets.cpp
    M Source/WebCore/style/StyleScopeRuleSets.h
    M Source/WebCore/testing/Internals.cpp
    M Source/WebCore/testing/Internals.h
    M Source/WebCore/testing/Internals.idl

  Log Message:
  -----------
  [:has() perf] Remove separate handling of scope breaking selectors
https://bugs.webkit.org/show_bug.cgi?id=313420
rdar://175668439

Reviewed by Alan Baradlay.

With this patch we can handle scope breaking cases like

:has(:is(.this-breaks-scope .foo))

within our normal invalidation system. Scope-breaking entries are now
emitted with no scope selector (instead of being collected into a
separate rule set that triggered full-document traversal on every
mutation). This also lets us emit and properly bound entries for
combinators inside :is()/:not() that stay within the :has() scope.

* LayoutTests/fast/selectors/has-invalidation-traversal-size-expected.txt:

c6 (:has(:is(.trigger + .other))) now invalidates correctly:
count goes from 0 (FAIL) to 14 (PASS).

* LayoutTests/fast/selectors/has-scope-breaking-classification-expected.txt: 
Removed.
* LayoutTests/fast/selectors/has-scope-breaking-classification.html: Removed.

Test deleted along with the SPI it tested.

* 
LayoutTests/imported/w3c/web-platform-tests/css/selectors/invalidation/has-with-nth-child-expected.txt:

Two :nth-child() in non-subject FAILs become PASSes.

* Source/WebCore/css/SelectorChecker.cpp:
(WebCore::SelectorChecker::matchHasPseudoClass const):

Forward DescendantsAffectedByForward/BackwardPositionalRules to the
directional AffectedByHasWith*SiblingRelationship flags so positional
rules inside :has() get proper sibling invalidation.

* Source/WebCore/style/ChildChangeInvalidation.cpp:
(WebCore::Style::isSiblingHasRelation):
(WebCore::Style::ChildChangeInvalidation::invalidateForHasBeforeMutation):
(WebCore::Style::ChildChangeInvalidation::invalidateForHasAfterMutation):
(WebCore::Style::ChildChangeInvalidation::invalidateForChangeOutsideHasScope): 
Deleted.
* Source/WebCore/style/ChildChangeInvalidation.h:

Drop the per-mutation full-document traversal helper.

* Source/WebCore/style/ClassChangeInvalidation.cpp:
(WebCore::Style::ClassChangeInvalidation::computeInvalidation):

Drop the ScopeBreaking-forces-before-and-after special case.

* Source/WebCore/style/RuleFeature.cpp:
(WebCore::Style::isHasScopeBreakingCombinator):

Now classifies a combinator inside :is()/:not() within :has() as
scope-breaking based on the combinator and the :has() argument's
relation to the bearer.

(WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):

Track isNestedInLogicalCombination and crossedScopeBreakingCombinator
in the recursion context. Emit per-compound entries inside :is()/:not()
at sibling-combinator and positional-pseudo-class boundaries, attaching
a scope selector unless we crossed a scope-breaking combinator.

(WebCore::Style::RuleFeatureSet::collectFeatures):
(WebCore::Style::RuleFeatureSet::add):
(WebCore::Style::RuleFeatureSet::clear):
(WebCore::Style::RuleFeatureSet::shrinkToFit):

Remove scopeBreakingHasPseudoClassRules bookkeeping.

* Source/WebCore/style/RuleFeature.h:

Remove MatchElement::HasRelation::ScopeBreaking enum value and the
scopeBreakingHasPseudoClassRules vector.

* Source/WebCore/style/StyleInvalidator.cpp:
(WebCore::Style::Invalidator::invalidateStyleWithMatchElement):

Drop the ScopeBreaking-takes-the-whole-document early return.

(WebCore::Style::Invalidator::invalidateWithScopeBreakingHasPseudoClassRuleSet):
 Deleted.
* Source/WebCore/style/StyleInvalidator.h:
* Source/WebCore/style/StyleScopeRuleSets.cpp:
(WebCore::Style::ScopeRuleSets::collectFeatures const):
(WebCore::Style::makeRuleSet): Deleted.
* Source/WebCore/style/StyleScopeRuleSets.h:
(WebCore::Style::ScopeRuleSets::scopeBreakingHasPseudoClassInvalidationRuleSet 
const): Deleted.

Drop the separate scope-breaking rule set and its plumbing.

* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::hasScopeBreakingHasSelectors const): Deleted.
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:

Drop the hasScopeBreakingHasSelectors test SPI together with its
backing classification test.

Canonical link: https://commits.webkit.org/312103@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to