Support ::part selector (#37307)

This is pretty much just wiring up the necessary stylo methods. Note
that the `exportparts` attribute is not yet supported, I'll do that in a
followup change

Testing: Covered by existing web platform tests.
This is the first half of https://github.com/servo/servo/issues/35349

Fixes https://github.com/servo/servo/issues/37325

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-06-09 12:17:28 +02:00 committed by GitHub
parent 73ee36be00
commit 0fa3de3937
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 119 additions and 348 deletions

View file

@ -216,11 +216,15 @@ impl<'dom> style::dom::TElement for ServoLayoutElement<'dom> {
}
fn has_part_attr(&self) -> bool {
false
self.element
.get_attr_for_layout(&ns!(), &local_name!("part"))
.is_some()
}
fn exports_any_part(&self) -> bool {
false
self.element
.get_attr_for_layout(&ns!(), &local_name!("exportparts"))
.is_some()
}
fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
@ -292,6 +296,17 @@ impl<'dom> style::dom::TElement for ServoLayoutElement<'dom> {
}
}
fn each_part<F>(&self, mut callback: F)
where
F: FnMut(&AtomIdent),
{
if let Some(parts) = self.element.get_parts_for_layout() {
for part in parts {
callback(AtomIdent::cast(part))
}
}
}
fn has_dirty_descendants(&self) -> bool {
unsafe {
self.as_node()
@ -728,8 +743,12 @@ impl<'dom> ::selectors::Element for ServoLayoutElement<'dom> {
}
#[inline]
fn is_part(&self, _name: &AtomIdent) -> bool {
false
fn is_part(&self, name: &AtomIdent) -> bool {
self.element.has_class_or_part_for_layout(
name,
&local_name!("part"),
CaseSensitivity::CaseSensitive,
)
}
fn imported_part(&self, _: &AtomIdent) -> Option<AtomIdent> {
@ -738,7 +757,8 @@ impl<'dom> ::selectors::Element for ServoLayoutElement<'dom> {
#[inline]
fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool {
self.element.has_class_for_layout(name, case_sensitivity)
self.element
.has_class_or_part_for_layout(name, &local_name!("class"), case_sensitivity)
}
fn is_html_slot_element(&self) -> bool {