Skip to content

[:has() perf] Include full selector context to :has() invalidation selectors#63132

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
anttijk:has-full-invalidation-selector
Apr 21, 2026
Merged

[:has() perf] Include full selector context to :has() invalidation selectors#63132
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
anttijk:has-full-invalidation-selector

Conversation

@anttijk
Copy link
Copy Markdown
Contributor

@anttijk anttijk commented Apr 20, 2026

e538024

[:has() perf] Include full selector context to :has() invalidation selectors
https://bugs.webkit.org/show_bug.cgi?id=312786
rdar://175177078

Reviewed by Alan Baradlay.

When there is a mutation that may affect :has() we run the selector in has argument to see if any of the
added or removed elements match. Previously this was done with the argument as is. For

    .foo:has(.bar) .baz

the invalidation selector was

    <has-scope> .bar

where <has-scope> would always match. Any appearance of .bar would trigger invalidation traversal.

With this patch we include the full context to invalidation selector so in above case it will be

    .foo .bar

potentially ruling out many cases where .bar alone matches.

Test: fast/selectors/has-invalidation-traversal-size.html

Document some traversal sizes.

* LayoutTests/fast/selectors/has-invalidation-traversal-size-expected.txt: Added.
* LayoutTests/fast/selectors/has-invalidation-traversal-size.html: Added.
* Source/WebCore/css/parser/CSSSelectorParser.cpp:
(WebCore::CSSSelectorParser::makeHasArgumentReplacingScope):

Add helper for resolving <has-scope>.

* Source/WebCore/css/parser/CSSSelectorParser.h:
* Source/WebCore/dom/Document.h:
(WebCore::Document::styleInvalidationTraversalCountForTesting const):
(WebCore::Document::incrementStyleInvalidationTraversalCountForTesting):
(WebCore::Document::resetStyleInvalidationTraversalCountForTesting):
* Source/WebCore/style/RuleFeature.cpp:
(WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
(WebCore::Style::RuleFeatureSet::collectFeatures):

Resolve the scope.

* Source/WebCore/style/RuleFeature.h:
* Source/WebCore/style/StyleInvalidator.cpp:
(WebCore::Style::Invalidator::invalidateIfNeeded):
(WebCore::Style::Invalidator::invalidateWithMatchElementRuleSets):
* Source/WebCore/style/StyleInvalidator.h:
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::styleInvalidationTraversalCount const):
(WebCore::Internals::resetStyleInvalidationTraversalCount):

Add testing support

* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:

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

61b1526

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win loading 🛠 ios-apple
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ✅ 🧪 win-tests loading 🛠 mac-apple
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe loading 🛠 vision-apple
✅ 🧪 ios-wk2-wpt ✅ 🧪 api-mac-debug ✅ 🛠 gtk3-libwebrtc
✅ 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 ios-safer-cpp ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🛠 🧪 merge ✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🛠 playstation
✅ 🧪 vision-wk2 loading 🧪 mac-intel-wk2
✅ 🛠 tv ✅ 🛠 mac-safer-cpp
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@anttijk anttijk requested review from cdumez and rniwa as code owners April 20, 2026 17:48
@anttijk anttijk self-assigned this Apr 20, 2026
@anttijk anttijk added the CSS Cascading Style Sheets implementation label Apr 20, 2026
@anttijk anttijk force-pushed the has-full-invalidation-selector branch from b1a1edf to 61b1526 Compare April 20, 2026 18:59
@anttijk anttijk added the merge-queue Applied to send a pull request to merge-queue label Apr 21, 2026
…lectors

https://bugs.webkit.org/show_bug.cgi?id=312786
rdar://175177078

Reviewed by Alan Baradlay.

When there is a mutation that may affect :has() we run the selector in has argument to see if any of the
added or removed elements match. Previously this was done with the argument as is. For

    .foo:has(.bar) .baz

the invalidation selector was

    <has-scope> .bar

where <has-scope> would always match. Any appearance of .bar would trigger invalidation traversal.

With this patch we include the full context to invalidation selector so in above case it will be

    .foo .bar

potentially ruling out many cases where .bar alone matches.

Test: fast/selectors/has-invalidation-traversal-size.html

Document some traversal sizes.

* LayoutTests/fast/selectors/has-invalidation-traversal-size-expected.txt: Added.
* LayoutTests/fast/selectors/has-invalidation-traversal-size.html: Added.
* Source/WebCore/css/parser/CSSSelectorParser.cpp:
(WebCore::CSSSelectorParser::makeHasArgumentReplacingScope):

Add helper for resolving <has-scope>.

* Source/WebCore/css/parser/CSSSelectorParser.h:
* Source/WebCore/dom/Document.h:
(WebCore::Document::styleInvalidationTraversalCountForTesting const):
(WebCore::Document::incrementStyleInvalidationTraversalCountForTesting):
(WebCore::Document::resetStyleInvalidationTraversalCountForTesting):
* Source/WebCore/style/RuleFeature.cpp:
(WebCore::Style::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
(WebCore::Style::RuleFeatureSet::collectFeatures):

Resolve the scope.

* Source/WebCore/style/RuleFeature.h:
* Source/WebCore/style/StyleInvalidator.cpp:
(WebCore::Style::Invalidator::invalidateIfNeeded):
(WebCore::Style::Invalidator::invalidateWithMatchElementRuleSets):
* Source/WebCore/style/StyleInvalidator.h:
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::styleInvalidationTraversalCount const):
(WebCore::Internals::resetStyleInvalidationTraversalCount):

Add testing support

* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:

Canonical link: https://commits.webkit.org/311642@main
@webkit-commit-queue webkit-commit-queue force-pushed the has-full-invalidation-selector branch from 61b1526 to e538024 Compare April 21, 2026 04:32
@webkit-commit-queue
Copy link
Copy Markdown
Collaborator

Committed 311642@main (e538024): https://commits.webkit.org/311642@main

Reviewed commits have been landed. Closing PR #63132 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit e538024 into WebKit:main Apr 21, 2026
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CSS Cascading Style Sheets implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants