Skip to content

Commit

Permalink
style: Implement selector-matching for ::part().
Browse files Browse the repository at this point in the history
Also fairly straight-forward. This may get more complicated when we do part
forwarding, if any.

I've opened w3c/csswg-drafts#3841 in what I think
would be a cleaner model for forwarding.

Differential Revision: https://phabricator.services.mozilla.com/D28063
  • Loading branch information
emilio committed May 7, 2019
1 parent a23ad3b commit 627514b
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 12 deletions.
12 changes: 11 additions & 1 deletion components/style/gecko/snapshot.rs
Expand Up @@ -183,13 +183,23 @@ impl ElementSnapshot for GeckoElementSnapshot {
snapshot_helpers::get_id(&*self.mAttrs) snapshot_helpers::get_id(&*self.mAttrs)
} }


#[inline]
fn is_part(&self, name: &Atom) -> bool {
let attr = match snapshot_helpers::find_attr(&*self.mAttrs, &atom!("part")) {
Some(attr) => attr,
None => return false,
};

snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr)
}

#[inline] #[inline]
fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool { fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {
if !self.has_any(Flags::MaybeClass) { if !self.has_any(Flags::MaybeClass) {
return false; return false;
} }


snapshot_helpers::has_class(name, case_sensitivity, &self.mClass) snapshot_helpers::has_class_or_part(name, case_sensitivity, &self.mClass)
} }


#[inline] #[inline]
Expand Down
12 changes: 6 additions & 6 deletions components/style/gecko/snapshot_helpers.rs
Expand Up @@ -29,7 +29,7 @@ unsafe fn ptr<T>(attr: &structs::nsAttrValue) -> *const T {
} }


#[inline(always)] #[inline(always)]
unsafe fn get_class_from_attr(attr: &structs::nsAttrValue) -> Class { unsafe fn get_class_or_part_from_attr(attr: &structs::nsAttrValue) -> Class {
debug_assert!(bindings::Gecko_AssertClassAttrValueIsSane(attr)); debug_assert!(bindings::Gecko_AssertClassAttrValueIsSane(attr));
let base_type = base_type(attr); let base_type = base_type(attr);
if base_type == structs::nsAttrValue_ValueBaseType_eStringBase { if base_type == structs::nsAttrValue_ValueBaseType_eStringBase {
Expand Down Expand Up @@ -82,15 +82,15 @@ pub fn get_id(attrs: &[structs::AttrArray_InternalAttr]) -> Option<&WeakAtom> {
Some(unsafe { get_id_from_attr(find_attr(attrs, &atom!("id"))?) }) Some(unsafe { get_id_from_attr(find_attr(attrs, &atom!("id"))?) })
} }


/// Given a class name, a case sensitivity, and an array of attributes, returns /// Given a class or part name, a case sensitivity, and an array of attributes,
/// whether the class has the attribute that name represents. /// returns whether the attribute has that name.
#[inline(always)] #[inline(always)]
pub fn has_class( pub fn has_class_or_part(
name: &Atom, name: &Atom,
case_sensitivity: CaseSensitivity, case_sensitivity: CaseSensitivity,
attr: &structs::nsAttrValue, attr: &structs::nsAttrValue,
) -> bool { ) -> bool {
match unsafe { get_class_from_attr(attr) } { match unsafe { get_class_or_part_from_attr(attr) } {
Class::None => false, Class::None => false,
Class::One(atom) => unsafe { case_sensitivity.eq_atom(name, WeakAtom::new(atom)) }, Class::One(atom) => unsafe { case_sensitivity.eq_atom(name, WeakAtom::new(atom)) },
Class::More(atoms) => match case_sensitivity { Class::More(atoms) => match case_sensitivity {
Expand All @@ -114,7 +114,7 @@ where
F: FnMut(&Atom), F: FnMut(&Atom),
{ {
unsafe { unsafe {
match get_class_from_attr(attr) { match get_class_or_part_from_attr(attr) {
Class::None => {}, Class::None => {},
Class::One(atom) => Atom::with(atom, callback), Class::One(atom) => Atom::with(atom, callback),
Class::More(atoms) => { Class::More(atoms) => {
Expand Down
17 changes: 14 additions & 3 deletions components/style/gecko/wrapper.rs
Expand Up @@ -573,6 +573,11 @@ impl<'le> GeckoElement<'le> {
} }
} }


#[inline(always)]
fn get_part_attr(&self) -> Option<&structs::nsAttrValue> {
snapshot_helpers::find_attr(self.attrs(), &atom!("part"))
}

#[inline(always)] #[inline(always)]
fn get_class_attr(&self) -> Option<&structs::nsAttrValue> { fn get_class_attr(&self) -> Option<&structs::nsAttrValue> {
if !self.may_have_class() { if !self.may_have_class() {
Expand Down Expand Up @@ -2259,8 +2264,14 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
case_sensitivity.eq_atom(element_id, id) case_sensitivity.eq_atom(element_id, id)
} }


fn is_part(&self, _name: &Atom) -> bool { #[inline]
unimplemented!(); fn is_part(&self, name: &Atom) -> bool {
let attr = match self.get_part_attr() {
Some(c) => c,
None => return false,
};

snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr)
} }


#[inline(always)] #[inline(always)]
Expand All @@ -2270,7 +2281,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
None => return false, None => return false,
}; };


snapshot_helpers::has_class(name, case_sensitivity, attr) snapshot_helpers::has_class_or_part(name, case_sensitivity, attr)
} }


#[inline] #[inline]
Expand Down
11 changes: 9 additions & 2 deletions components/style/invalidation/element/element_wrapper.rs
Expand Up @@ -58,6 +58,10 @@ pub trait ElementSnapshot: Sized {
/// if `has_attrs()` returns true. /// if `has_attrs()` returns true.
fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool; fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool;


/// Whether this snapshot represents the part named `name`. Should only be
/// called if `has_attrs()` returns true.
fn is_part(&self, name: &Atom) -> bool;

/// A callback that should be called for each class of the snapshot. Should /// A callback that should be called for each class of the snapshot. Should
/// only be called if `has_attrs()` returns true. /// only be called if `has_attrs()` returns true.
fn each_class<F>(&self, _: F) fn each_class<F>(&self, _: F)
Expand Down Expand Up @@ -340,8 +344,11 @@ where
} }
} }


fn is_part(&self, _name: &Atom) -> bool { fn is_part(&self, name: &Atom) -> bool {
unimplemented!(); match self.snapshot() {
Some(snapshot) if snapshot.has_attrs() => snapshot.is_part(name),
_ => self.element.is_part(name),
}
} }


fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool { fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {
Expand Down

0 comments on commit 627514b

Please sign in to comment.