/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Different checks done during the style sharing process in order to determine //! quickly whether it's worth to share style, and whether two different //! elements can indeed share the same style.
usecrate::bloom::StyleBloom; usecrate::context::SharedStyleContext; usecrate::dom::{TElement, TShadowRoot}; usecrate::properties::ComputedValues; usecrate::sharing::{StyleSharingCandidate, StyleSharingTarget}; usecrate::values::specified::TreeCountingFunction; use selectors::matching::SelectorCaches;
/// Determines whether a target and a candidate have compatible parents for /// sharing. pubfn parents_allow_sharing<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
) -> bool where
E: TElement,
{ // If the identity of the parent style isn't equal, we can't share. We check // this first, because the result is cached. if target.parent_style_identity() != candidate.parent_style_identity() { returnfalse;
}
// Siblings can always share. let parent = target.inheritance_parent().unwrap(); let candidate_parent = candidate.element.inheritance_parent().unwrap(); if parent == candidate_parent { returntrue;
}
// If a parent element was already styled and we traversed past it without // restyling it, that may be because our clever invalidation logic was able // to prove that the styles of that element would remain unchanged despite // changes to the id or class attributes. However, style sharing relies in // the strong guarantee that all the classes and ids up the respective parent // chains are identical. As such, if we skipped styling for one (or both) of // the parents on this traversal, we can't share styles across cousins. // // This is a somewhat conservative check. We could tighten it by having the // invalidation logic explicitly flag elements for which it ellided styling. let parent_data = parent.borrow_data().unwrap(); let candidate_parent_data = candidate_parent.borrow_data().unwrap(); if !parent_data.safe_for_cousin_sharing() || !candidate_parent_data.safe_for_cousin_sharing() { returnfalse;
}
true
}
/// Whether two elements have the same style attribute. /// /// First checks pointer identity (fast path), then falls back to value comparison. pubfn have_same_style_attribute<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
shared_context: &SharedStyleContext,
) -> bool where
E: TElement,
{ match (target.style_attribute(), candidate.style_attribute()) {
(None, None) => true,
(Some(_), None) | (None, Some(_)) => false,
(Some(a), Some(b)) => { if std::ptr::eq(&*a, &*b) { returntrue;
} let guard = shared_context.guards.author;
*a.read_with(guard) == *b.read_with(guard)
},
}
}
/// Whether two elements have the same same presentational attributes. pubfn have_same_presentational_hints<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
) -> bool where
E: TElement,
{
target.pres_hints() == candidate.pres_hints()
}
/// Whether a given element has the same class attribute as a given candidate. /// /// We don't try to share style across elements with different class attributes. pubfn have_same_class<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
) -> bool where
E: TElement,
{
target.class_list() == candidate.class_list()
}
/// Whether a given element has the same part attribute as a given candidate. /// /// We don't try to share style across elements with different part attributes. pubfn have_same_parts<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
) -> bool where
E: TElement,
{
target.part_list() == candidate.part_list()
}
/// Whether a given element and a candidate match the same set of "revalidation" /// selectors. /// /// Revalidation selectors are those that depend on the DOM structure, like /// :first-child, etc, or on attributes that we don't check off-hand (pretty /// much every attribute selector except `id` and `class`. #[inline] pubfn revalidate<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
shared_context: &SharedStyleContext,
bloom: &StyleBloom<E>,
selector_caches: &mut SelectorCaches,
) -> bool where
E: TElement,
{ let stylist = &shared_context.stylist;
let for_element = target.revalidation_match_results(stylist, bloom, selector_caches);
let for_candidate = candidate.revalidation_match_results(stylist, bloom, selector_caches);
for_element == for_candidate
}
/// Whether the given element and a candidate have the same values for the the /// attributes used in an `attr()` function. #[inline] pubfn have_same_referenced_attrs<E>(
target: &StyleSharingTarget<E>,
candidate: &StyleSharingCandidate<E>,
) -> bool where
E: TElement,
{ // The candidate must be styled in order to be in the cache. let borrowed_data = candidate.element.borrow_data().unwrap(); let styles = &borrowed_data.styles;
if !check_style(styles.primary()) { returnfalse;
}
for pseudo_styles in styles.pseudos.as_array() { let Some(ref styles) = pseudo_styles else { continue;
}; if !check_style(styles) { returnfalse;
}
} true
}
/// Whether two elements have compatible tree-counting functions. pubfn have_shareable_tree_counting_functions<E>(
target: &StyleSharingTarget<E>,
candidate: &StyleSharingCandidate<E>,
) -> bool where
E: TElement,
{ let borrowed_data = candidate.element.borrow_data().unwrap(); let styles = &borrowed_data.styles;
if styles.uses_tree_counting_function(TreeCountingFunction::SiblingIndex) { // Two elements with the same parent will always have a different index returnfalse;
}
if styles.uses_tree_counting_function(TreeCountingFunction::SiblingCount)
&& target.parent_element() != candidate.parent_element()
{ returnfalse;
}
true
}
/// Whether a given element and a candidate share a set of scope activations /// for revalidation. #[inline] pubfn revalidate_scope<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>,
shared_context: &SharedStyleContext,
selector_caches: &mut SelectorCaches,
) -> bool where
E: TElement,
{ let stylist = &shared_context.stylist; let for_element = target.scope_revalidation_results(stylist, selector_caches); let for_candidate = candidate.scope_revalidation_results(stylist, selector_caches);
for_element == for_candidate
}
/// Checks whether we might have rules for either of the two ids. #[inline] pubfn may_match_different_id_rules<E>(
shared_context: &SharedStyleContext,
element: E,
candidate: E,
) -> bool where
E: TElement,
{ let element_id = element.id(); let candidate_id = candidate.id();
if element_id == candidate_id { returnfalse;
}
let stylist = &shared_context.stylist;
let may_have_rules_for_element = match element_id {
Some(id) => stylist.may_have_rules_for_id(id, element),
None => false,
};
/// Returns whether the cascade data of the given shadow roots is the same. #[inline] pubfn shadow_root_style_data_equals<S>(l: Option<S>, r: Option<S>) -> bool where
S: TShadowRoot,
{ if l == r { returntrue;
} let (Some(l), Some(r)) = (l, r) else { returnfalse;
}; match (l.style_data(), r.style_data()) {
(Some(l), Some(r)) => std::ptr::eq(l, r),
(None, None) => true,
_ => false,
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.