mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
style: Add invalidation support for ::slotted().
Bug: 1424607 Reviewed-by: heycam MozReview-Commit-ID: 8pIVUx27o7x
This commit is contained in:
parent
040379208e
commit
b26f3280d2
7 changed files with 294 additions and 110 deletions
|
@ -363,6 +363,10 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
|||
LayoutIterator(self.as_node().dom_children())
|
||||
}
|
||||
|
||||
fn is_html_element(&self) -> bool {
|
||||
unsafe { self.element.is_html_element() }
|
||||
}
|
||||
|
||||
fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
|
||||
unsafe {
|
||||
(*self.element.style_attribute()).as_ref().map(|x| x.borrow_arc())
|
||||
|
|
|
@ -416,6 +416,20 @@ pub trait TElement
|
|||
F: FnMut(Self),
|
||||
{}
|
||||
|
||||
/// Return whether this element is an element in the HTML namespace.
|
||||
fn is_html_element(&self) -> bool;
|
||||
|
||||
/// Returns whether this element is a <html:slot> element.
|
||||
fn is_html_slot_element(&self) -> bool {
|
||||
self.get_local_name() == &*local_name!("slot") &&
|
||||
self.is_html_element()
|
||||
}
|
||||
|
||||
/// Return the list of slotted nodes of this node.
|
||||
fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
|
||||
&[]
|
||||
}
|
||||
|
||||
/// For a given NAC element, return the closest non-NAC ancestor, which is
|
||||
/// guaranteed to exist.
|
||||
fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> {
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
use Atom;
|
||||
use context::QuirksMode;
|
||||
use dom::{TDocument, TElement, TNode};
|
||||
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
|
||||
use invalidation::element::invalidator::{DescendantInvalidationLists, Invalidation};
|
||||
use invalidation::element::invalidator::{InvalidationProcessor, InvalidationVector};
|
||||
use selectors::{Element, NthIndexCache, SelectorList};
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::matching::{self, MatchingContext, MatchingMode};
|
||||
|
@ -143,7 +144,7 @@ where
|
|||
&mut self,
|
||||
element: E,
|
||||
self_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
||||
_sibling_invalidations: &mut InvalidationVector<'a>,
|
||||
) -> bool {
|
||||
// TODO(emilio): If the element is not a root element, and
|
||||
|
@ -163,7 +164,7 @@ where
|
|||
|
||||
let target_vector =
|
||||
if self.matching_context.scope_element.is_some() {
|
||||
descendant_invalidations
|
||||
&mut descendant_invalidations.dom_descendants
|
||||
} else {
|
||||
self_invalidations
|
||||
};
|
||||
|
|
|
@ -610,10 +610,7 @@ impl<'le> GeckoElement<'le> {
|
|||
self.as_node().node_info().mInner.mNamespaceID
|
||||
}
|
||||
|
||||
fn is_html_element(&self) -> bool {
|
||||
self.namespace_id() == (structs::root::kNameSpaceID_XHTML as i32)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_xul_element(&self) -> bool {
|
||||
self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32)
|
||||
}
|
||||
|
@ -974,6 +971,40 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
self.as_node().owner_doc().as_node()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn is_html_element(&self) -> bool {
|
||||
self.namespace_id() == (structs::root::kNameSpaceID_XHTML as i32)
|
||||
}
|
||||
|
||||
/// Return the list of slotted nodes of this node.
|
||||
#[inline]
|
||||
fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
|
||||
if !self.is_html_slot_element() || !self.is_in_shadow_tree() {
|
||||
return &[];
|
||||
}
|
||||
|
||||
let slot: &structs::HTMLSlotElement = unsafe {
|
||||
mem::transmute(self.0)
|
||||
};
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
let base: &RawGeckoElement = &slot._base._base._base._base;
|
||||
assert_eq!(base as *const _, self.0 as *const _, "Bad cast");
|
||||
}
|
||||
|
||||
let assigned_nodes: &[structs::RefPtr<structs::nsINode>] =
|
||||
&*slot.mAssignedNodes;
|
||||
|
||||
debug_assert_eq!(
|
||||
mem::size_of::<structs::RefPtr<structs::nsINode>>(),
|
||||
mem::size_of::<Self::ConcreteNode>(),
|
||||
"Bad cast!"
|
||||
);
|
||||
|
||||
unsafe { mem::transmute(assigned_nodes) }
|
||||
}
|
||||
|
||||
/// Execute `f` for each anonymous content child element (apart from
|
||||
/// ::before and ::after) whose originating element is `self`.
|
||||
fn each_anonymous_content_child<F>(&self, mut f: F)
|
||||
|
|
|
@ -13,7 +13,8 @@ use dom::TElement;
|
|||
use element_state::ElementState;
|
||||
use invalidation::element::element_wrapper::{ElementSnapshot, ElementWrapper};
|
||||
use invalidation::element::invalidation_map::*;
|
||||
use invalidation::element::invalidator::{InvalidationVector, Invalidation, InvalidationProcessor};
|
||||
use invalidation::element::invalidator::{DescendantInvalidationLists, InvalidationVector};
|
||||
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
|
||||
use invalidation::element::restyle_hints::RestyleHint;
|
||||
use selector_map::SelectorMap;
|
||||
use selector_parser::Snapshot;
|
||||
|
@ -47,7 +48,7 @@ where
|
|||
classes_removed: &'a SmallVec<[Atom; 8]>,
|
||||
classes_added: &'a SmallVec<[Atom; 8]>,
|
||||
state_changes: ElementState,
|
||||
descendant_invalidations: &'a mut InvalidationVector<'selectors>,
|
||||
descendant_invalidations: &'a mut DescendantInvalidationLists<'selectors>,
|
||||
sibling_invalidations: &'a mut InvalidationVector<'selectors>,
|
||||
invalidates_self: bool,
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ where
|
|||
&mut self,
|
||||
element: E,
|
||||
_self_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
||||
sibling_invalidations: &mut InvalidationVector<'a>,
|
||||
) -> bool {
|
||||
debug_assert!(element.has_snapshot(), "Why bothering?");
|
||||
|
@ -236,7 +237,10 @@ where
|
|||
//
|
||||
// This number is completely made-up, but the page that made us add this
|
||||
// code generated 1960+ invalidations (bug 1420741).
|
||||
if descendant_invalidations.len() > 150 {
|
||||
//
|
||||
// We don't look at slotted_descendants because those don't propagate
|
||||
// down more than one level anyway.
|
||||
if descendant_invalidations.dom_descendants.len() > 150 {
|
||||
self.data.hint.insert(RestyleHint::RESTYLE_DESCENDANTS);
|
||||
}
|
||||
|
||||
|
@ -509,36 +513,52 @@ where
|
|||
}
|
||||
|
||||
fn note_dependency(&mut self, dependency: &'selectors Dependency) {
|
||||
if dependency.affects_self() {
|
||||
debug_assert!(self.dependency_may_be_relevant(dependency));
|
||||
|
||||
let invalidation_kind = dependency.invalidation_kind();
|
||||
if matches!(invalidation_kind, DependencyInvalidationKind::Element) {
|
||||
self.invalidates_self = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if dependency.affects_descendants() {
|
||||
debug_assert_ne!(dependency.selector_offset, 0);
|
||||
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
||||
debug_assert!(!dependency.affects_later_siblings());
|
||||
self.descendant_invalidations.push(Invalidation::new(
|
||||
&dependency.selector,
|
||||
dependency.selector.len() - dependency.selector_offset + 1,
|
||||
));
|
||||
} else if dependency.affects_later_siblings() {
|
||||
debug_assert_ne!(dependency.selector_offset, 0);
|
||||
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
||||
self.sibling_invalidations.push(Invalidation::new(
|
||||
&dependency.selector,
|
||||
dependency.selector.len() - dependency.selector_offset + 1,
|
||||
));
|
||||
debug_assert_ne!(dependency.selector_offset, 0);
|
||||
debug_assert_ne!(
|
||||
dependency.selector_offset,
|
||||
dependency.selector.len()
|
||||
);
|
||||
|
||||
let invalidation = Invalidation::new(
|
||||
&dependency.selector,
|
||||
dependency.selector.len() - dependency.selector_offset + 1,
|
||||
);
|
||||
|
||||
match invalidation_kind {
|
||||
DependencyInvalidationKind::Element => unreachable!(),
|
||||
DependencyInvalidationKind::ElementAndDescendants => {
|
||||
self.invalidates_self = true;
|
||||
self.descendant_invalidations.dom_descendants.push(invalidation);
|
||||
}
|
||||
DependencyInvalidationKind::Descendants => {
|
||||
self.descendant_invalidations.dom_descendants.push(invalidation);
|
||||
}
|
||||
DependencyInvalidationKind::Siblings => {
|
||||
self.sibling_invalidations.push(invalidation);
|
||||
}
|
||||
DependencyInvalidationKind::SlottedElements => {
|
||||
self.descendant_invalidations.slotted_descendants.push(invalidation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether `dependency` may cause us to invalidate the style of
|
||||
/// more elements than what we've already invalidated.
|
||||
fn dependency_may_be_relevant(&self, dependency: &Dependency) -> bool {
|
||||
if dependency.affects_descendants() || dependency.affects_later_siblings() {
|
||||
return true;
|
||||
match dependency.invalidation_kind() {
|
||||
DependencyInvalidationKind::Element => !self.invalidates_self,
|
||||
DependencyInvalidationKind::SlottedElements => self.element.is_html_slot_element(),
|
||||
DependencyInvalidationKind::ElementAndDescendants |
|
||||
DependencyInvalidationKind::Siblings |
|
||||
DependencyInvalidationKind::Descendants => true,
|
||||
}
|
||||
|
||||
debug_assert!(dependency.affects_self());
|
||||
!self.invalidates_self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,25 @@ pub struct Dependency {
|
|||
pub selector_offset: usize,
|
||||
}
|
||||
|
||||
/// The kind of elements down the tree this dependency may affect.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum DependencyInvalidationKind {
|
||||
/// This dependency may affect the element that changed itself.
|
||||
Element,
|
||||
/// This dependency affects the style of the element itself, and also the
|
||||
/// style of its descendants.
|
||||
///
|
||||
/// TODO(emilio): Each time this feels more of a hack for eager pseudos...
|
||||
ElementAndDescendants,
|
||||
/// This dependency may affect descendants down the tree.
|
||||
Descendants,
|
||||
/// This dependency may affect siblings to the right of the element that
|
||||
/// changed.
|
||||
Siblings,
|
||||
/// This dependency may affect slotted elements of the element that changed.
|
||||
SlottedElements,
|
||||
}
|
||||
|
||||
impl Dependency {
|
||||
/// Returns the combinator to the right of the partial selector this
|
||||
/// dependency represents.
|
||||
|
@ -76,28 +95,19 @@ impl Dependency {
|
|||
Some(self.selector.combinator_at_match_order(self.selector_offset - 1))
|
||||
}
|
||||
|
||||
/// Whether this dependency affects the style of the element.
|
||||
///
|
||||
/// NOTE(emilio): pseudo-elements need to be here to account for eager
|
||||
/// pseudos, since they just grab the style from the originating element.
|
||||
///
|
||||
/// TODO(emilio): We could look at the selector itself to see if it's an
|
||||
/// eager pseudo, and return false here if not.
|
||||
pub fn affects_self(&self) -> bool {
|
||||
matches!(self.combinator(), None | Some(Combinator::PseudoElement))
|
||||
}
|
||||
|
||||
/// Whether this dependency may affect style of any of our descendants.
|
||||
pub fn affects_descendants(&self) -> bool {
|
||||
matches!(self.combinator(), Some(Combinator::PseudoElement) |
|
||||
Some(Combinator::Child) |
|
||||
Some(Combinator::Descendant))
|
||||
}
|
||||
|
||||
/// Whether this dependency may affect style of any of our later siblings.
|
||||
pub fn affects_later_siblings(&self) -> bool {
|
||||
matches!(self.combinator(), Some(Combinator::NextSibling) |
|
||||
Some(Combinator::LaterSibling))
|
||||
/// The kind of invalidation that this would generate.
|
||||
pub fn invalidation_kind(&self) -> DependencyInvalidationKind {
|
||||
match self.combinator() {
|
||||
None => DependencyInvalidationKind::Element,
|
||||
Some(Combinator::Child) |
|
||||
Some(Combinator::Descendant) => DependencyInvalidationKind::Descendants,
|
||||
Some(Combinator::LaterSibling) |
|
||||
Some(Combinator::NextSibling) => DependencyInvalidationKind::Siblings,
|
||||
// TODO(emilio): We could look at the selector itself to see if it's
|
||||
// an eager pseudo, and return only Descendants here if not.
|
||||
Some(Combinator::PseudoElement) => DependencyInvalidationKind::ElementAndDescendants,
|
||||
Some(Combinator::SlotAssignment) => DependencyInvalidationKind::SlottedElements,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ where
|
|||
&mut self,
|
||||
element: E,
|
||||
self_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||
descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
||||
sibling_invalidations: &mut InvalidationVector<'a>,
|
||||
) -> bool;
|
||||
|
||||
|
@ -58,6 +58,25 @@ where
|
|||
fn invalidated_descendants(&mut self, element: E, child: E);
|
||||
}
|
||||
|
||||
/// Different invalidation lists for descendants.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DescendantInvalidationLists<'a> {
|
||||
/// Invalidations for normal DOM children and pseudo-elements.
|
||||
///
|
||||
/// TODO(emilio): Having a list of invalidations just for pseudo-elements
|
||||
/// may save some work here and there.
|
||||
pub dom_descendants: InvalidationVector<'a>,
|
||||
/// Invalidations for slotted children of an element.
|
||||
pub slotted_descendants: InvalidationVector<'a>,
|
||||
}
|
||||
|
||||
impl<'a> DescendantInvalidationLists<'a> {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.dom_descendants.is_empty() &&
|
||||
self.slotted_descendants.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// The struct that takes care of encapsulating all the logic on where and how
|
||||
/// element styles need to be invalidated.
|
||||
pub struct TreeStyleInvalidator<'a, 'b, E, P: 'a>
|
||||
|
@ -75,13 +94,22 @@ where
|
|||
/// A vector of invalidations, optimized for small invalidation sets.
|
||||
pub type InvalidationVector<'a> = SmallVec<[Invalidation<'a>; 10]>;
|
||||
|
||||
/// The kind of descendant invalidation we're processing.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum DescendantInvalidationKind {
|
||||
/// A DOM descendant invalidation.
|
||||
Dom,
|
||||
/// A ::slotted() descendant invalidation.
|
||||
Slotted,
|
||||
}
|
||||
|
||||
/// The kind of invalidation we're processing.
|
||||
///
|
||||
/// We can use this to avoid pushing invalidations of the same kind to our
|
||||
/// descendants or siblings.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum InvalidationKind {
|
||||
Descendant,
|
||||
Descendant(DescendantInvalidationKind),
|
||||
Sibling,
|
||||
}
|
||||
|
||||
|
@ -126,21 +154,27 @@ impl<'a> Invalidation<'a> {
|
|||
//
|
||||
// We should be able to do better here!
|
||||
match self.selector.combinator_at_parse_order(self.offset - 1) {
|
||||
Combinator::Descendant |
|
||||
Combinator::LaterSibling |
|
||||
Combinator::PseudoElement => true,
|
||||
Combinator::SlotAssignment |
|
||||
Combinator::NextSibling |
|
||||
Combinator::Child => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn kind(&self) -> InvalidationKind {
|
||||
if self.offset == 0 {
|
||||
return InvalidationKind::Descendant;
|
||||
return InvalidationKind::Descendant(DescendantInvalidationKind::Dom);
|
||||
}
|
||||
|
||||
if self.selector.combinator_at_parse_order(self.offset - 1).is_ancestor() {
|
||||
InvalidationKind::Descendant
|
||||
} else {
|
||||
InvalidationKind::Sibling
|
||||
match self.selector.combinator_at_parse_order(self.offset - 1) {
|
||||
Combinator::Child |
|
||||
Combinator::Descendant |
|
||||
Combinator::PseudoElement => InvalidationKind::Descendant(DescendantInvalidationKind::Dom),
|
||||
Combinator::SlotAssignment => InvalidationKind::Descendant(DescendantInvalidationKind::Slotted),
|
||||
Combinator::NextSibling |
|
||||
Combinator::LaterSibling => InvalidationKind::Sibling,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +264,7 @@ where
|
|||
debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
|
||||
|
||||
let mut self_invalidations = InvalidationVector::new();
|
||||
let mut descendant_invalidations = InvalidationVector::new();
|
||||
let mut descendant_invalidations = DescendantInvalidationLists::default();
|
||||
let mut sibling_invalidations = InvalidationVector::new();
|
||||
|
||||
let mut invalidated_self = self.processor.collect_invalidations(
|
||||
|
@ -242,7 +276,7 @@ where
|
|||
|
||||
debug!("Collected invalidations (self: {}): ", invalidated_self);
|
||||
debug!(" > self: {}, {:?}", self_invalidations.len(), self_invalidations);
|
||||
debug!(" > descendants: {}, {:?}", descendant_invalidations.len(), descendant_invalidations);
|
||||
debug!(" > descendants: {:?}", descendant_invalidations);
|
||||
debug!(" > siblings: {}, {:?}", sibling_invalidations.len(), sibling_invalidations);
|
||||
|
||||
let invalidated_self_from_collection = invalidated_self;
|
||||
|
@ -251,6 +285,7 @@ where
|
|||
&self_invalidations,
|
||||
&mut descendant_invalidations,
|
||||
&mut sibling_invalidations,
|
||||
DescendantInvalidationKind::Dom,
|
||||
);
|
||||
|
||||
if invalidated_self && !invalidated_self_from_collection {
|
||||
|
@ -260,7 +295,11 @@ where
|
|||
let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
|
||||
let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
|
||||
|
||||
InvalidationResult { invalidated_self, invalidated_descendants, invalidated_siblings }
|
||||
InvalidationResult {
|
||||
invalidated_self,
|
||||
invalidated_descendants,
|
||||
invalidated_siblings,
|
||||
}
|
||||
}
|
||||
|
||||
/// Go through later DOM siblings, invalidating style as needed using the
|
||||
|
@ -286,7 +325,8 @@ where
|
|||
self.processor,
|
||||
);
|
||||
|
||||
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||
let mut invalidations_for_descendants =
|
||||
DescendantInvalidationLists::default();
|
||||
let invalidated_sibling =
|
||||
sibling_invalidator.process_sibling_invalidations(
|
||||
&mut invalidations_for_descendants,
|
||||
|
@ -301,7 +341,7 @@ where
|
|||
|
||||
any_invalidated |=
|
||||
sibling_invalidator.invalidate_descendants(
|
||||
&invalidations_for_descendants
|
||||
&invalidations_for_descendants,
|
||||
);
|
||||
|
||||
if sibling_invalidations.is_empty() {
|
||||
|
@ -324,7 +364,8 @@ where
|
|||
let result = self.invalidate_child(
|
||||
child,
|
||||
invalidations,
|
||||
&mut sibling_invalidations
|
||||
&mut sibling_invalidations,
|
||||
DescendantInvalidationKind::Dom,
|
||||
);
|
||||
|
||||
// Roots of NAC subtrees can indeed generate sibling invalidations, but
|
||||
|
@ -344,8 +385,10 @@ where
|
|||
child: E,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||
descendant_invalidation_kind: DescendantInvalidationKind,
|
||||
) -> bool {
|
||||
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||
let mut invalidations_for_descendants =
|
||||
DescendantInvalidationLists::default();
|
||||
|
||||
let mut invalidated_child = false;
|
||||
let invalidated_descendants = {
|
||||
|
@ -366,13 +409,16 @@ where
|
|||
invalidations,
|
||||
&mut invalidations_for_descendants,
|
||||
sibling_invalidations,
|
||||
descendant_invalidation_kind,
|
||||
);
|
||||
|
||||
if invalidated_child {
|
||||
child_invalidator.processor.invalidated_self(child);
|
||||
}
|
||||
|
||||
child_invalidator.invalidate_descendants(&invalidations_for_descendants)
|
||||
child_invalidator.invalidate_descendants(
|
||||
&invalidations_for_descendants,
|
||||
)
|
||||
};
|
||||
|
||||
// The child may not be a flattened tree child of the current element,
|
||||
|
@ -418,10 +464,6 @@ where
|
|||
//
|
||||
// This probably needs a shadow root check on `child` here, and
|
||||
// recursing if that's the case.
|
||||
//
|
||||
// Also, what's the deal with HTML <content>? We don't need to
|
||||
// support that for now, though we probably need to recurse into the
|
||||
// distributed children too.
|
||||
let child = match child.as_element() {
|
||||
Some(e) => e,
|
||||
None => continue,
|
||||
|
@ -431,15 +473,14 @@ where
|
|||
child,
|
||||
invalidations,
|
||||
&mut sibling_invalidations,
|
||||
DescendantInvalidationKind::Dom,
|
||||
);
|
||||
}
|
||||
|
||||
any_descendant
|
||||
}
|
||||
|
||||
/// Given a descendant invalidation list, go through the current element's
|
||||
/// descendants, and invalidate style on them.
|
||||
fn invalidate_descendants(
|
||||
fn invalidate_slotted_elements(
|
||||
&mut self,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
) -> bool {
|
||||
|
@ -447,6 +488,83 @@ where
|
|||
return false;
|
||||
}
|
||||
|
||||
let mut any = false;
|
||||
|
||||
let mut sibling_invalidations = InvalidationVector::new();
|
||||
let element = self.element;
|
||||
for node in element.slotted_nodes() {
|
||||
let element = match node.as_element() {
|
||||
Some(e) => e,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
any |= self.invalidate_child(
|
||||
element,
|
||||
invalidations,
|
||||
&mut sibling_invalidations,
|
||||
DescendantInvalidationKind::Slotted,
|
||||
);
|
||||
|
||||
debug_assert!(
|
||||
sibling_invalidations.is_empty(),
|
||||
"::slotted() shouldn't have sibling combinators to the right, \
|
||||
this makes no sense! {:?}",
|
||||
sibling_invalidations
|
||||
);
|
||||
}
|
||||
|
||||
any
|
||||
}
|
||||
|
||||
fn invalidate_non_slotted_descendants(
|
||||
&mut self,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
) -> bool {
|
||||
if invalidations.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.processor.light_tree_only() {
|
||||
let node = self.element.as_node();
|
||||
return self.invalidate_dom_descendants_of(node, invalidations);
|
||||
}
|
||||
|
||||
let mut any_descendant = false;
|
||||
|
||||
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
||||
}
|
||||
|
||||
if let Some(before) = self.element.before_pseudo_element() {
|
||||
any_descendant |=
|
||||
self.invalidate_pseudo_element_or_nac(before, invalidations);
|
||||
}
|
||||
|
||||
let node = self.element.as_node();
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(node, invalidations);
|
||||
|
||||
if let Some(after) = self.element.after_pseudo_element() {
|
||||
any_descendant |=
|
||||
self.invalidate_pseudo_element_or_nac(after, invalidations);
|
||||
}
|
||||
|
||||
any_descendant |= self.invalidate_nac(invalidations);
|
||||
|
||||
any_descendant
|
||||
}
|
||||
|
||||
/// Given the descendant invalidation lists, go through the current
|
||||
/// element's descendants, and invalidate style on them.
|
||||
fn invalidate_descendants(
|
||||
&mut self,
|
||||
invalidations: &DescendantInvalidationLists<'b>,
|
||||
) -> bool {
|
||||
if invalidations.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
debug!("StyleTreeInvalidator::invalidate_descendants({:?})",
|
||||
self.element);
|
||||
debug!(" > {:?}", invalidations);
|
||||
|
@ -465,35 +583,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if self.processor.light_tree_only() {
|
||||
let node = self.element.as_node();
|
||||
return self.invalidate_dom_descendants_of(node, invalidations);
|
||||
}
|
||||
|
||||
let mut any_descendant = false;
|
||||
|
||||
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
||||
}
|
||||
|
||||
// TODO(emilio): Having a list of invalidations just for pseudo-elements
|
||||
// may save some work here and there.
|
||||
if let Some(before) = self.element.before_pseudo_element() {
|
||||
any_descendant |=
|
||||
self.invalidate_pseudo_element_or_nac(before, invalidations);
|
||||
}
|
||||
|
||||
let node = self.element.as_node();
|
||||
any_descendant |=
|
||||
self.invalidate_dom_descendants_of(node, invalidations);
|
||||
|
||||
if let Some(after) = self.element.after_pseudo_element() {
|
||||
any_descendant |=
|
||||
self.invalidate_pseudo_element_or_nac(after, invalidations);
|
||||
}
|
||||
|
||||
any_descendant |= self.invalidate_nac(invalidations);
|
||||
self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
|
||||
any_descendant |=
|
||||
self.invalidate_slotted_elements(&invalidations.slotted_descendants);
|
||||
|
||||
any_descendant
|
||||
}
|
||||
|
@ -511,7 +606,7 @@ where
|
|||
/// Returns whether invalidated the current element's style.
|
||||
fn process_sibling_invalidations(
|
||||
&mut self,
|
||||
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||
descendant_invalidations: &mut DescendantInvalidationLists<'b>,
|
||||
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
let mut i = 0;
|
||||
|
@ -547,8 +642,9 @@ where
|
|||
fn process_descendant_invalidations(
|
||||
&mut self,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||
descendant_invalidations: &mut DescendantInvalidationLists<'b>,
|
||||
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||
descendant_invalidation_kind: DescendantInvalidationKind,
|
||||
) -> bool {
|
||||
let mut invalidated = false;
|
||||
|
||||
|
@ -557,14 +653,19 @@ where
|
|||
invalidation,
|
||||
descendant_invalidations,
|
||||
sibling_invalidations,
|
||||
InvalidationKind::Descendant,
|
||||
InvalidationKind::Descendant(descendant_invalidation_kind),
|
||||
);
|
||||
|
||||
invalidated |= result.invalidated_self;
|
||||
if invalidation.effective_for_next() {
|
||||
let mut invalidation = invalidation.clone();
|
||||
invalidation.matched_by_any_previous |= result.matched;
|
||||
descendant_invalidations.push(invalidation.clone());
|
||||
debug_assert_eq!(
|
||||
descendant_invalidation_kind,
|
||||
DescendantInvalidationKind::Dom,
|
||||
"Slotted invalidations don't propagate."
|
||||
);
|
||||
descendant_invalidations.dom_descendants.push(invalidation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,7 +681,7 @@ where
|
|||
fn process_invalidation(
|
||||
&mut self,
|
||||
invalidation: &Invalidation<'b>,
|
||||
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||
descendant_invalidations: &mut DescendantInvalidationLists<'b>,
|
||||
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||
invalidation_kind: InvalidationKind,
|
||||
) -> SingleInvalidationResult {
|
||||
|
@ -732,8 +833,11 @@ where
|
|||
already been matched before");
|
||||
} else {
|
||||
match next_invalidation_kind {
|
||||
InvalidationKind::Descendant => {
|
||||
descendant_invalidations.push(next_invalidation);
|
||||
InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
|
||||
descendant_invalidations.dom_descendants.push(next_invalidation);
|
||||
}
|
||||
InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
|
||||
descendant_invalidations.slotted_descendants.push(next_invalidation);
|
||||
}
|
||||
InvalidationKind::Sibling => {
|
||||
sibling_invalidations.push(next_invalidation);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue