style: Allow to export a shadow part under multiple names.

Other browsers allow this and the spec doesn't really disallow it, so fix it,
add a test and carry on.

Differential Revision: https://phabricator.services.mozilla.com/D65107
This commit is contained in:
Emilio Cobos Álvarez 2020-03-09 13:04:21 +00:00
parent 614d3e746f
commit 635f5fbf1b
8 changed files with 46 additions and 46 deletions

View file

@ -117,13 +117,6 @@ pub trait Element: Sized + Clone + Debug {
case_sensitivity: CaseSensitivity, case_sensitivity: CaseSensitivity,
) -> bool; ) -> bool;
/// Returns the mapping from the `exportparts` attribute in the regular
/// direction, that is, inner-tree -> outer-tree.
fn exported_part(
&self,
name: &<Self::Impl as SelectorImpl>::PartName,
) -> Option<<Self::Impl as SelectorImpl>::PartName>;
/// Returns the mapping from the `exportparts` attribute in the reverse /// Returns the mapping from the `exportparts` attribute in the reverse
/// direction, that is, in an outer-tree -> inner-tree direction. /// direction, that is, in an outer-tree -> inner-tree direction.
fn imported_part( fn imported_part(

View file

@ -522,6 +522,14 @@ pub trait TElement:
{ {
} }
/// Internal iterator for the part names that this element exports for a
/// given part name.
fn each_exported_part<F>(&self, _name: &Atom, _callback: F)
where
F: FnMut(&Atom),
{
}
/// Whether a given element may generate a pseudo-element. /// Whether a given element may generate a pseudo-element.
/// ///
/// This is useful to avoid computing, for example, pseudo styles for /// This is useful to avoid computing, for example, pseudo styles for

View file

@ -193,11 +193,6 @@ impl ElementSnapshot for GeckoElementSnapshot {
snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr) snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr)
} }
#[inline]
fn exported_part(&self, name: &Atom) -> Option<Atom> {
snapshot_helpers::exported_part(&*self.mAttrs, name)
}
#[inline] #[inline]
fn imported_part(&self, name: &Atom) -> Option<Atom> { fn imported_part(&self, name: &Atom) -> Option<Atom> {
snapshot_helpers::imported_part(&*self.mAttrs, name) snapshot_helpers::imported_part(&*self.mAttrs, name)

View file

@ -83,16 +83,32 @@ pub fn get_id(attrs: &[structs::AttrArray_InternalAttr]) -> Option<&WeakAtom> {
} }
#[inline(always)] #[inline(always)]
pub(super) fn exported_part( pub(super) fn each_exported_part(
attrs: &[structs::AttrArray_InternalAttr], attrs: &[structs::AttrArray_InternalAttr],
name: &Atom, name: &Atom,
) -> Option<Atom> { mut callback: impl FnMut(&Atom),
let attr = find_attr(attrs, &atom!("exportparts"))?; ) {
let atom = unsafe { bindings::Gecko_Element_ExportedPart(attr, name.as_ptr()) }; let attr = match find_attr(attrs, &atom!("exportparts")) {
if atom.is_null() { Some(attr) => attr,
return None; None => return,
};
let mut length = 0;
let atoms = unsafe {
bindings::Gecko_Element_ExportedParts(
attr,
name.as_ptr(),
&mut length,
)
};
if atoms.is_null() {
return;
}
unsafe {
for atom in std::slice::from_raw_parts(atoms, length) {
Atom::with(*atom, &mut callback)
}
} }
Some(unsafe { Atom::from_raw(atom) })
} }
#[inline(always)] #[inline(always)]

View file

@ -1281,6 +1281,14 @@ impl<'le> TElement for GeckoElement<'le> {
snapshot_helpers::each_class_or_part(attr, callback) snapshot_helpers::each_class_or_part(attr, callback)
} }
#[inline]
fn each_exported_part<F>(&self, name: &Atom, callback: F)
where
F: FnMut(&Atom),
{
snapshot_helpers::each_exported_part(self.attrs(), name, callback)
}
fn each_part<F>(&self, callback: F) fn each_part<F>(&self, callback: F)
where where
F: FnMut(&Atom), F: FnMut(&Atom),
@ -2226,11 +2234,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr) snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr)
} }
#[inline]
fn exported_part(&self, name: &Atom) -> Option<Atom> {
snapshot_helpers::exported_part(self.attrs(), name)
}
#[inline] #[inline]
fn imported_part(&self, name: &Atom) -> Option<Atom> { fn imported_part(&self, name: &Atom) -> Option<Atom> {
snapshot_helpers::imported_part(self.attrs(), name) snapshot_helpers::imported_part(self.attrs(), name)

View file

@ -62,9 +62,6 @@ pub trait ElementSnapshot: Sized {
/// called if `has_attrs()` returns true. /// called if `has_attrs()` returns true.
fn is_part(&self, name: &Atom) -> bool; fn is_part(&self, name: &Atom) -> bool;
/// See Element::exported_part.
fn exported_part(&self, name: &Atom) -> Option<Atom>;
/// See Element::imported_part. /// See Element::imported_part.
fn imported_part(&self, name: &Atom) -> Option<Atom>; fn imported_part(&self, name: &Atom) -> Option<Atom>;
@ -371,13 +368,6 @@ where
} }
} }
fn exported_part(&self, name: &Atom) -> Option<Atom> {
match self.snapshot() {
Some(snapshot) if snapshot.has_attrs() => snapshot.exported_part(name),
_ => self.element.exported_part(name),
}
}
fn imported_part(&self, name: &Atom) -> Option<Atom> { fn imported_part(&self, name: &Atom) -> Option<Atom> {
match self.snapshot() { match self.snapshot() {
Some(snapshot) if snapshot.has_attrs() => snapshot.imported_part(name), Some(snapshot) if snapshot.has_attrs() => snapshot.imported_part(name),

View file

@ -393,14 +393,13 @@ where
None => break, // Nowhere to export to. None => break, // Nowhere to export to.
}; };
parts.retain(|part| { let mut new_parts = SmallVec::new();
let exported_part = match inner_shadow_host.exported_part(part) { for part in &parts {
Some(part) => part, inner_shadow_host.each_exported_part(part, |exported_part| {
None => return false, new_parts.push(exported_part.clone());
}; });
std::mem::replace(part, exported_part); }
true parts = new_parts;
});
} }
} }

View file

@ -709,10 +709,6 @@ impl ElementSnapshot for ServoElementSnapshot {
false false
} }
fn exported_part(&self, _: &Atom) -> Option<Atom> {
None
}
fn imported_part(&self, _: &Atom) -> Option<Atom> { fn imported_part(&self, _: &Atom) -> Option<Atom> {
None None
} }