style: Do not incorrectly share style across elements with different part names.

Do the same we do for classes for now. We could be more precise and achieve a
bit more sharing with some more effort (left a comment there), but it seems
unlikely to matter in practice (and if we did that, we'd probably want to do the
same for classes).

Differential Revision: https://phabricator.services.mozilla.com/D58453
This commit is contained in:
Emilio Cobos Álvarez 2019-12-31 18:14:35 +00:00
parent 69bf0e40a6
commit 4f4d480326
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
2 changed files with 60 additions and 8 deletions

View file

@ -124,10 +124,16 @@ impl OpaqueComputedValues {
pub struct ValidationData {
/// The class list of this element.
///
/// TODO(emilio): See if it's worth to sort them, or doing something else in
/// a similar fashion as what Boris is doing for the ID attribute.
/// TODO(emilio): Maybe check whether rules for these classes apply to the
/// element?
class_list: Option<SmallVec<[Atom; 5]>>,
/// The part list of this element.
///
/// TODO(emilio): Maybe check whether rules with these part names apply to
/// the element?
part_list: Option<SmallVec<[Atom; 5]>>,
/// The list of presentational attributes of the element.
pres_hints: Option<SmallVec<[ApplicableDeclarationBlock; 5]>>,
@ -161,22 +167,41 @@ impl ValidationData {
})
}
/// Get or compute the part-list associated with this element.
pub fn part_list<E>(&mut self, element: E) -> &[Atom]
where
E: TElement,
{
if !element.has_part_attr() {
return &[]
}
self.part_list.get_or_insert_with(|| {
let mut list = SmallVec::<[Atom; 5]>::new();
element.each_part(|p| list.push(p.clone()));
// See below for the reasoning.
if !list.spilled() {
list.sort_unstable_by_key(|a| a.get_hash());
}
list
})
}
/// Get or compute the class-list associated with this element.
pub fn class_list<E>(&mut self, element: E) -> &[Atom]
where
E: TElement,
{
self.class_list.get_or_insert_with(|| {
let mut class_list = SmallVec::<[Atom; 5]>::new();
element.each_class(|c| class_list.push(c.clone()));
let mut list = SmallVec::<[Atom; 5]>::new();
element.each_class(|c| list.push(c.clone()));
// Assuming there are a reasonable number of classes (we use the
// inline capacity as "reasonable number"), sort them to so that
// we don't mistakenly reject sharing candidates when one element
// has "foo bar" and the other has "bar foo".
if !class_list.spilled() {
class_list.sort_by(|a, b| a.get_hash().cmp(&b.get_hash()));
if !list.spilled() {
list.sort_unstable_by_key(|a| a.get_hash());
}
class_list
list
})
}
@ -273,6 +298,11 @@ impl<E: TElement> StyleSharingCandidate<E> {
self.validation_data.class_list(self.element)
}
/// Get the part list of this candidate.
fn part_list(&mut self) -> &[Atom] {
self.validation_data.part_list(self.element)
}
/// Get the pres hints of this candidate.
fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] {
self.validation_data.pres_hints(self.element)
@ -335,6 +365,10 @@ impl<E: TElement> StyleSharingTarget<E> {
self.validation_data.class_list(self.element)
}
fn part_list(&mut self) -> &[Atom] {
self.validation_data.part_list(self.element)
}
/// Get the pres hints of this candidate.
fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] {
self.validation_data.pres_hints(self.element)
@ -772,6 +806,11 @@ impl<E: TElement> StyleSharingCache<E> {
return None;
}
if !checks::have_same_parts(target, candidate) {
trace!("Miss: Shadow parts");
return None;
}
if !checks::revalidate(
target,
candidate,