diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-01-16 15:14:39 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-01-17 18:03:16 +0100 |
commit | 665690bba642562aed7a49daf953555b793022f6 (patch) | |
tree | 27430963d7bee6e7c92f99b950e685bd18e81e75 | |
parent | 75af7c0b411e0332eec06cdb9f32d6c7145859e7 (diff) | |
download | servo-665690bba642562aed7a49daf953555b793022f6.tar.gz servo-665690bba642562aed7a49daf953555b793022f6.zip |
style: Hook in the document invalidator.
Bug: 1409672
Reviewed-by: xidorn
MozReview-Commit-ID: EoSMrYPS7dl
-rw-r--r-- | components/style/invalidation/element/document_state.rs | 29 | ||||
-rw-r--r-- | components/style/invalidation/element/invalidator.rs | 14 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 44 |
3 files changed, 70 insertions, 17 deletions
diff --git a/components/style/invalidation/element/document_state.rs b/components/style/invalidation/element/document_state.rs index 77b0034531a..4ceb2762ccf 100644 --- a/components/style/invalidation/element/document_state.rs +++ b/components/style/invalidation/element/document_state.rs @@ -30,20 +30,20 @@ impl Default for InvalidationMatchingData { /// An invalidation processor for style changes due to state and attribute /// changes. -pub struct DocumentStateInvalidationProcessor<'a, E: TElement> { +pub struct DocumentStateInvalidationProcessor<'a, E: TElement, I> { // TODO(emilio): We might want to just run everything for every possible // binding along with the document data, or just apply the XBL stuff to the // bound subtrees. - rules: &'a CascadeData, + rules: I, matching_context: MatchingContext<'a, E::Impl>, document_states_changed: DocumentState, } -impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> { +impl<'a, E: TElement, I> DocumentStateInvalidationProcessor<'a, E, I> { /// Creates a new DocumentStateInvalidationProcessor. #[inline] pub fn new( - rules: &'a CascadeData, + rules: I, document_states_changed: DocumentState, quirks_mode: QuirksMode, ) -> Self { @@ -63,7 +63,11 @@ impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> { } } -impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidationProcessor<'a, E> { +impl<'a, E, I> InvalidationProcessor<'a, E> for DocumentStateInvalidationProcessor<'a, E, I> +where + E: TElement, + I: Iterator<Item = &'a CascadeData>, +{ fn collect_invalidations( &mut self, _element: E, @@ -71,14 +75,15 @@ impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidation _descendant_invalidations: &mut DescendantInvalidationLists<'a>, _sibling_invalidations: &mut InvalidationVector<'a>, ) -> bool { - let map = self.rules.invalidation_map(); - - for dependency in &map.document_state_selectors { - if !dependency.state.intersects(self.document_states_changed) { - continue; + for cascade_data in &mut self.rules { + let map = cascade_data.invalidation_map(); + for dependency in &map.document_state_selectors { + if !dependency.state.intersects(self.document_states_changed) { + continue; + } + + self_invalidations.push(Invalidation::new(&dependency.selector, 0)); } - - self_invalidations.push(Invalidation::new(&dependency.selector, 0)); } false diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs index 47f66576ebe..77e9f875bdd 100644 --- a/components/style/invalidation/element/invalidator.rs +++ b/components/style/invalidation/element/invalidator.rs @@ -534,6 +534,20 @@ where let mut any_descendant = false; + // NOTE(emilio): This should not be needed for Shadow DOM for normal + // element state / attribute invalidations (it's needed for XBL though, + // due to the weird way the anon content there works (it doesn't block + // combinators)). + // + // However, it's needed as of right now for document state invalidation, + // were we rely on iterating every element that ends up in the composed + // doc. + // + // Also, we could avoid having that special-case for document state + // invalidations if we invalidate for document state changes per + // subtree, though that's kind of annoying because we need to invalidate + // the shadow host subtree (to handle :host and ::slotted), and the + // actual shadow tree (to handle all other rules in the ShadowRoot). if let Some(anon_content) = self.element.xbl_binding_anonymous_content() { any_descendant |= self.invalidate_dom_descendants_of(anon_content, invalidations); diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index e8872a4a25e..2ee79abc56c 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -9,6 +9,7 @@ use malloc_size_of::MallocSizeOfOps; use selectors::{Element, NthIndexCache}; use selectors::matching::{MatchingContext, MatchingMode, matches_selector}; use servo_arc::{Arc, ArcBorrow, RawOffsetArc}; +use smallvec::SmallVec; use std::cell::RefCell; use std::env; use std::fmt::Write; @@ -1774,7 +1775,6 @@ pub unsafe extern "C" fn Servo_SelectorList_QueryAll( content_list: *mut structs::nsSimpleContentList, may_use_invalidation: bool, ) { - use smallvec::SmallVec; use std::borrow::Borrow; use style::dom_apis::{self, MayUseInvalidation, QueryAll}; @@ -2391,10 +2391,10 @@ pub extern "C" fn Servo_ComputedValues_EqualCustomProperties( } #[no_mangle] -pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoStyleContextBorrowed, - rules: RawGeckoServoStyleRuleListBorrowedMut) { - use smallvec::SmallVec; - +pub extern "C" fn Servo_ComputedValues_GetStyleRuleList( + values: ServoStyleContextBorrowed, + rules: RawGeckoServoStyleRuleListBorrowedMut, +) { let rule_node = match values.rules { Some(ref r) => r, None => return, @@ -4931,6 +4931,40 @@ pub extern "C" fn Servo_ParseCounterStyleName( } #[no_mangle] +pub unsafe extern "C" fn Servo_InvalidateStyleForDocStateChanges( + root: RawGeckoElementBorrowed, + raw_style_sets: *const nsTArray<RawServoStyleSetBorrowed>, + states_changed: u64, +) { + use style::invalidation::element::document_state::DocumentStateInvalidationProcessor; + use style::invalidation::element::invalidator::TreeStyleInvalidator; + + let mut borrows = SmallVec::<[_; 20]>::with_capacity((*raw_style_sets).len()); + for style_set in &**raw_style_sets { + borrows.push(PerDocumentStyleData::from_ffi(*style_set).borrow()); + } + let root = GeckoElement(root); + let mut processor = DocumentStateInvalidationProcessor::new( + borrows.iter().flat_map(|b| b.stylist.iter_origins().map(|(data, _origin)| data)), + DocumentState::from_bits_truncate(states_changed), + root.as_node().owner_doc().quirks_mode(), + ); + + let result = TreeStyleInvalidator::new( + root, + /* stack_limit_checker = */ None, + &mut processor, + ).invalidate(); + + debug_assert!(!result.has_invalidated_siblings(), "How in the world?"); + if result.has_invalidated_descendants() { + bindings::Gecko_NoteDirtySubtreeForInvalidation(root.0); + } else if result.has_invalidated_self() { + bindings::Gecko_NoteDirtyElement(root.0); + } +} + +#[no_mangle] pub extern "C" fn Servo_ParseCounterStyleDescriptor( descriptor: nsCSSCounterDesc, value: *const nsACString, |