aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2018-01-16 15:14:39 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2018-01-17 18:03:16 +0100
commit665690bba642562aed7a49daf953555b793022f6 (patch)
tree27430963d7bee6e7c92f99b950e685bd18e81e75
parent75af7c0b411e0332eec06cdb9f32d6c7145859e7 (diff)
downloadservo-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.rs29
-rw-r--r--components/style/invalidation/element/invalidator.rs14
-rw-r--r--ports/geckolib/glue.rs44
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,