-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[css-scoping] Implement :has-slotted
pseudo-class
#34599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
EWS run on previous version of this PR (hash d4507cc) |
d4507cc
to
69f2c29
Compare
EWS run on previous version of this PR (hash 69f2c29) |
69f2c29
to
3a5e5b1
Compare
EWS run on previous version of this PR (hash 3a5e5b1) |
3a5e5b1
to
8918c55
Compare
EWS run on previous version of this PR (hash 8918c55) |
8918c55
to
f93071a
Compare
EWS run on previous version of this PR (hash f93071a) |
f93071a
to
83cf06c
Compare
EWS run on previous version of this PR (hash 83cf06c) |
211de82
to
2ce8230
Compare
EWS run on previous version of this PR (hash 2ce8230) |
2ce8230
to
201a2cb
Compare
EWS run on previous version of this PR (hash 201a2cb) |
201a2cb
to
642b383
Compare
EWS run on previous version of this PR (hash 642b383) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is OK as is.
...eb-platform-tests/css/css-scoping/has-slotted-functional-changing-001.tentative-expected.txt
Show resolved
Hide resolved
...eb-platform-tests/css/css-scoping/has-slotted-functional-changing-003.tentative-expected.txt
Show resolved
Hide resolved
std::optional<Style::PseudoClassChangeInvalidation> styleInvalidation; | ||
if (auto* slotElement = slot->element.get()) | ||
styleInvalidation.emplace(*slotElement, CSSSelector::PseudoClass::HasSlotted, slotElement->hasFlattenedSlottedContent()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to share more of this code? This sequence of three lines of code is pretty repetitive, shows up 5 times almost identically, and I think a helper function could improve clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style::PseudoClassChangeInvalidation
is scope-dependent. It would be possible to define another scope that wraps this scope, but not worth it IMO
Vector<Ref<Node>> nodes; | ||
flattenAssignedNodes(nodes, *this); | ||
return !nodes.isEmpty(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems inefficient to build the list of nodes just to check if it’s empty. Can we do it more efficiently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need more than 1 bits for context.mode
.
:has-slotted
pseudo-class
642b383
to
2621c0b
Compare
EWS run on previous version of this PR (hash 2621c0b) |
2621c0b
to
62fd2c2
Compare
EWS run on previous version of this PR (hash 62fd2c2) |
https://bugs.webkit.org/show_bug.cgi?id=280608 Reviewed by NOBODY (OOPS!). This implements the :has-slotted pseudo selector as specified in CSSWG https://drafts.csswg.org/css-scoping/#the-has-slotted-pseudo. * LayoutTests/TestExpectations: * LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/has-slotted-changing-001-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/has-slotted-changing-002-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/has-slotted-functional-changing-001.tentative-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/has-slotted-functional-changing-003.tentative-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/has-slotted-manual-assignment-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-scoping/has-slotted-query-selector-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/selectors/parsing/parse-has-slotted.tentative-expected.txt: * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: * Source/WebCore/css/CSSPseudoSelectors.json: * Source/WebCore/css/SelectorChecker.cpp: (WebCore::SelectorChecker::checkOne const): * Source/WebCore/css/SelectorCheckerTestFunctions.h: (WebCore::matchesHasSlottedPseudoClass): * Source/WebCore/css/parser/CSSParserContext.cpp: (WebCore::add): * Source/WebCore/css/parser/CSSParserContext.h: * Source/WebCore/css/parser/CSSSelectorParserContext.cpp: (WebCore::CSSSelectorParserContext::CSSSelectorParserContext): (WebCore::add): * Source/WebCore/css/parser/CSSSelectorParserContext.h: * Source/WebCore/cssjit/SelectorCompiler.cpp: (WebCore::SelectorCompiler::JSC_DEFINE_NOEXCEPT_JIT_OPERATION): (WebCore::SelectorCompiler::addPseudoClassType): * Source/WebCore/dom/Node.cpp: (WebCore::Node::setManuallyAssignedSlot): * Source/WebCore/dom/SlotAssignment.cpp: (WebCore::NamedSlotAssignment::didChangeSlot): (WebCore::NamedSlotAssignment::willRemoveAssignedNode): (WebCore::NamedSlotAssignment::assignToSlot): * Source/WebCore/html/HTMLSlotElement.cpp: (WebCore::containsAssignedNodeIgnoringSlots): (WebCore::HTMLSlotElement::hasFlattenedSlottedContent const): * Source/WebCore/html/HTMLSlotElement.h:
62fd2c2
to
91135a2
Compare
EWS run on current version of this PR (hash 91135a2) |
@@ -112,6 +112,7 @@ CSSParserContext::CSSParserContext(const Document& document, const URL& sheetBas | |||
, cssAxisRelativePositionKeywordsEnabled { document.settings().cssAxisRelativePositionKeywordsEnabled() } | |||
, cssDynamicRangeLimitMixEnabled { document.settings().cssDynamicRangeLimitMixEnabled() } | |||
, cssConstrainedDynamicRangeLimitEnabled { document.settings().cssConstrainedDynamicRangeLimitEnabled() } | |||
, cssHasSlottedEnabled { document.settings().cssHasSlottedEnabled() } | |||
, webkitMediaTextTrackDisplayQuirkEnabled { document.quirks().needsWebKitMediaTextTrackDisplayQuirk() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this value not being included in the hash computation?
@@ -1375,8 +1376,17 @@ void Node::setManuallyAssignedSlot(HTMLSlotElement* slotElement) | |||
else if (RefPtr text = dynamicDowncast<Text>(*this)) | |||
RenderTreeUpdater::tearDownRenderer(*text); | |||
|
|||
auto* oldSlotElement = manuallyAssignedSlot(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use RefPtr
instead.
auto assignedNodes = std::exchange(slot->assignedNodes, { }); | ||
m_slotAssignmentsIsValid = false; | ||
|
||
if (auto* slotElement = slot->element.get()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use findFirstSlotElement
and RefPtr
instead.
slot->assignedNodes.removeFirstMatching([&node](const auto& item) { | ||
return item.get() == &node; | ||
}); | ||
|
||
if (auto* slotElement = slot->element.get()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
defaultSlotEntry->value->assignedNodes.append(child); | ||
if (auto* slotElement = defaultSlotEntry->value->element.get()) | ||
styleInvalidation.emplace(*slotElement, CSSSelector::PseudoClass::HasSlotted, slotElement->hasFlattenedSlottedContent()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is too late. NamedSlotAssignment::assignSlots
is only called lazily.
We need to detect when :has-slotted
is used and eagerly resolve the assignment.
See how shadowRoot.shouldFireSlotchangeEvent() && hasAssignedNodes(shadowRoot, slot)
is checked to enqueue slotchange
event.
auto* assignedNodes = slot.assignedNodes(); | ||
if (!assignedNodes) { | ||
for (RefPtr<Node> child = slot.firstChild(); child; child = child->nextSibling()) { | ||
if (auto* slot = dynamicDowncast<HTMLSlotElement>(*child)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use RefPtr.
ASSERT_NOT_REACHED(); | ||
continue; | ||
} | ||
if (auto* slot = dynamicDowncast<HTMLSlotElement>(*weakNode)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
@@ -56,6 +56,9 @@ class HTMLSlotElement final : public HTMLElement { | |||
bool isInInsertedIntoAncestor() const { return m_isInInsertedIntoAncestor; } | |||
|
|||
void updateAccessibilityOnSlotChange() const; | |||
|
|||
bool hasFlattenedSlottedContent() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add this code right beneath assignedElements
instead.
91135a2
91135a2