mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
style: Hook in the document invalidator.
Bug: 1409672 Reviewed-by: xidorn MozReview-Commit-ID: EoSMrYPS7dl
This commit is contained in:
parent
75af7c0b41
commit
665690bba6
3 changed files with 69 additions and 16 deletions
|
@ -30,20 +30,20 @@ impl Default for InvalidationMatchingData {
|
||||||
|
|
||||||
/// An invalidation processor for style changes due to state and attribute
|
/// An invalidation processor for style changes due to state and attribute
|
||||||
/// changes.
|
/// 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
|
// 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
|
// binding along with the document data, or just apply the XBL stuff to the
|
||||||
// bound subtrees.
|
// bound subtrees.
|
||||||
rules: &'a CascadeData,
|
rules: I,
|
||||||
matching_context: MatchingContext<'a, E::Impl>,
|
matching_context: MatchingContext<'a, E::Impl>,
|
||||||
document_states_changed: DocumentState,
|
document_states_changed: DocumentState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> {
|
impl<'a, E: TElement, I> DocumentStateInvalidationProcessor<'a, E, I> {
|
||||||
/// Creates a new DocumentStateInvalidationProcessor.
|
/// Creates a new DocumentStateInvalidationProcessor.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
rules: &'a CascadeData,
|
rules: I,
|
||||||
document_states_changed: DocumentState,
|
document_states_changed: DocumentState,
|
||||||
quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
) -> Self {
|
) -> 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(
|
fn collect_invalidations(
|
||||||
&mut self,
|
&mut self,
|
||||||
_element: E,
|
_element: E,
|
||||||
|
@ -71,14 +75,15 @@ impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidation
|
||||||
_descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
_descendant_invalidations: &mut DescendantInvalidationLists<'a>,
|
||||||
_sibling_invalidations: &mut InvalidationVector<'a>,
|
_sibling_invalidations: &mut InvalidationVector<'a>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let map = self.rules.invalidation_map();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
for dependency in &map.document_state_selectors {
|
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
|
||||||
if !dependency.state.intersects(self.document_states_changed) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
|
|
|
@ -534,6 +534,20 @@ where
|
||||||
|
|
||||||
let mut any_descendant = false;
|
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() {
|
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
||||||
any_descendant |=
|
any_descendant |=
|
||||||
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
self.invalidate_dom_descendants_of(anon_content, invalidations);
|
||||||
|
|
|
@ -9,6 +9,7 @@ use malloc_size_of::MallocSizeOfOps;
|
||||||
use selectors::{Element, NthIndexCache};
|
use selectors::{Element, NthIndexCache};
|
||||||
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
||||||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
@ -1774,7 +1775,6 @@ pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
|
||||||
content_list: *mut structs::nsSimpleContentList,
|
content_list: *mut structs::nsSimpleContentList,
|
||||||
may_use_invalidation: bool,
|
may_use_invalidation: bool,
|
||||||
) {
|
) {
|
||||||
use smallvec::SmallVec;
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
||||||
|
|
||||||
|
@ -2391,10 +2391,10 @@ pub extern "C" fn Servo_ComputedValues_EqualCustomProperties(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoStyleContextBorrowed,
|
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
|
||||||
rules: RawGeckoServoStyleRuleListBorrowedMut) {
|
values: ServoStyleContextBorrowed,
|
||||||
use smallvec::SmallVec;
|
rules: RawGeckoServoStyleRuleListBorrowedMut,
|
||||||
|
) {
|
||||||
let rule_node = match values.rules {
|
let rule_node = match values.rules {
|
||||||
Some(ref r) => r,
|
Some(ref r) => r,
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -4930,6 +4930,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]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ParseCounterStyleDescriptor(
|
pub extern "C" fn Servo_ParseCounterStyleDescriptor(
|
||||||
descriptor: nsCSSCounterDesc,
|
descriptor: nsCSSCounterDesc,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue