mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
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:
parent
73ee36be00
commit
0fa3de3937
36 changed files with 119 additions and 348 deletions
|
@ -861,8 +861,14 @@ pub(crate) fn get_attr_for_layout<'dom>(
|
|||
|
||||
pub(crate) trait LayoutElementHelpers<'dom> {
|
||||
fn attrs(self) -> &'dom [LayoutDom<'dom, Attr>];
|
||||
fn has_class_for_layout(self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool;
|
||||
fn has_class_or_part_for_layout(
|
||||
self,
|
||||
name: &AtomIdent,
|
||||
attr_name: &LocalName,
|
||||
case_sensitivity: CaseSensitivity,
|
||||
) -> bool;
|
||||
fn get_classes_for_layout(self) -> Option<&'dom [Atom]>;
|
||||
fn get_parts_for_layout(self) -> Option<&'dom [Atom]>;
|
||||
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(self, hints: &mut V)
|
||||
where
|
||||
|
@ -905,8 +911,13 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn has_class_for_layout(self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool {
|
||||
get_attr_for_layout(self, &ns!(), &local_name!("class")).is_some_and(|attr| {
|
||||
fn has_class_or_part_for_layout(
|
||||
self,
|
||||
name: &AtomIdent,
|
||||
attr_name: &LocalName,
|
||||
case_sensitivity: CaseSensitivity,
|
||||
) -> bool {
|
||||
get_attr_for_layout(self, &ns!(), attr_name).is_some_and(|attr| {
|
||||
attr.to_tokens()
|
||||
.unwrap()
|
||||
.iter()
|
||||
|
@ -920,6 +931,11 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
|
|||
.map(|attr| attr.to_tokens().unwrap())
|
||||
}
|
||||
|
||||
fn get_parts_for_layout(self) -> Option<&'dom [Atom]> {
|
||||
get_attr_for_layout(self, &ns!(), &local_name!("part"))
|
||||
.map(|attr| attr.to_tokens().unwrap())
|
||||
}
|
||||
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(self, hints: &mut V)
|
||||
where
|
||||
V: Push<ApplicableDeclarationBlock>,
|
||||
|
@ -1995,6 +2011,16 @@ impl Element {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn is_part(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {
|
||||
self.get_attribute(&ns!(), &LocalName::from("part"))
|
||||
.is_some_and(|attr| {
|
||||
attr.value()
|
||||
.as_tokens()
|
||||
.iter()
|
||||
.any(|atom| case_sensitivity.eq_atom(name, atom))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn set_atomic_attribute(
|
||||
&self,
|
||||
local_name: &LocalName,
|
||||
|
@ -4051,6 +4077,13 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
rooted!(in(*cx) let slottable = Slottable(Dom::from_ref(self.upcast::<Node>())));
|
||||
slottable.find_a_slot(true)
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-shadow-parts/#dom-element-part>
|
||||
fn Part(&self) -> DomRoot<DOMTokenList> {
|
||||
self.ensure_rare_data()
|
||||
.part
|
||||
.or_init(|| DOMTokenList::new(self, &local_name!("part"), None, CanGc::note()))
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMethods for Element {
|
||||
|
@ -4190,7 +4223,9 @@ impl VirtualMethods for Element {
|
|||
match *name {
|
||||
local_name!("id") => AttrValue::from_atomic(value.into()),
|
||||
local_name!("name") => AttrValue::from_atomic(value.into()),
|
||||
local_name!("class") => AttrValue::from_serialized_tokenlist(value.into()),
|
||||
local_name!("class") | local_name!("part") => {
|
||||
AttrValue::from_serialized_tokenlist(value.into())
|
||||
},
|
||||
_ => self
|
||||
.super_type()
|
||||
.unwrap()
|
||||
|
@ -4564,8 +4599,8 @@ impl SelectorsElement for SelectorWrapper<'_> {
|
|||
.is_some_and(|atom| case_sensitivity.eq_atom(id, atom))
|
||||
}
|
||||
|
||||
fn is_part(&self, _name: &AtomIdent) -> bool {
|
||||
false
|
||||
fn is_part(&self, name: &AtomIdent) -> bool {
|
||||
Element::is_part(self, name, CaseSensitivity::CaseSensitive)
|
||||
}
|
||||
|
||||
fn imported_part(&self, _: &AtomIdent) -> Option<AtomIdent> {
|
||||
|
|
|
@ -437,7 +437,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
document.request_focus(None, FocusInitiator::Local, can_gc);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetparent>
|
||||
fn GetOffsetParent(&self, can_gc: CanGc) -> Option<DomRoot<Element>> {
|
||||
if self.is::<HTMLBodyElement>() || self.is::<HTMLHtmlElement>() {
|
||||
return None;
|
||||
|
|
|
@ -1583,6 +1583,7 @@ pub(crate) unsafe fn from_untrusted_node_address(candidate: UntrustedNodeAddress
|
|||
pub(crate) trait LayoutNodeHelpers<'dom> {
|
||||
fn type_id_for_layout(self) -> NodeTypeId;
|
||||
|
||||
fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
|
||||
fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>>;
|
||||
fn first_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
|
||||
fn last_child_ref(self) -> Option<LayoutDom<'dom, Node>>;
|
||||
|
@ -1645,7 +1646,7 @@ pub(crate) trait LayoutNodeHelpers<'dom> {
|
|||
impl<'dom> LayoutDom<'dom, Node> {
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
|
||||
pub(crate) fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
|
||||
unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
|
||||
}
|
||||
}
|
||||
|
@ -1661,6 +1662,12 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
(*self).is::<Element>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unsafe_code)]
|
||||
fn parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
|
||||
unsafe { self.unsafe_get().parent_node.get_inner_as_layout() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn composed_parent_node_ref(self) -> Option<LayoutDom<'dom, Node>> {
|
||||
let parent = self.parent_node_ref();
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::dom::bindings::root::{Dom, MutNullableDom};
|
|||
use crate::dom::customelementregistry::{
|
||||
CustomElementDefinition, CustomElementReaction, CustomElementState,
|
||||
};
|
||||
use crate::dom::domtokenlist::DOMTokenList;
|
||||
use crate::dom::elementinternals::ElementInternals;
|
||||
use crate::dom::htmlslotelement::SlottableData;
|
||||
use crate::dom::intersectionobserver::IntersectionObserverRegistration;
|
||||
|
@ -76,4 +77,10 @@ pub(crate) struct ElementRareData {
|
|||
/// > which is initialized to an empty list. This list holds IntersectionObserverRegistration records, which have:
|
||||
pub(crate) registered_intersection_observers: Vec<IntersectionObserverRegistration>,
|
||||
pub(crate) cryptographic_nonce: String,
|
||||
|
||||
/// <https://drafts.csswg.org/css-shadow-parts/#element-forwarded-part-name-list>
|
||||
pub(crate) forwarded_part_names: Vec<(String, String)>,
|
||||
|
||||
/// <https://drafts.csswg.org/css-shadow-parts/#dom-element-part>
|
||||
pub(crate) part: MutNullableDom<DOMTokenList>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue