style: Add a document state invalidator.

This commit is contained in:
Emilio Cobos Álvarez 2018-01-11 15:53:36 +01:00
parent 2c1d72ad1a
commit 5b7d9eb94a
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
5 changed files with 102 additions and 10 deletions

View file

@ -9,6 +9,7 @@ use element_state::{DocumentState, ElementState};
use gecko_bindings::structs::{self, CSSPseudoClassType};
use gecko_bindings::structs::RawServoSelectorList;
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use invalidation::element::document_state::InvalidationMatchingData;
use selector_parser::{Direction, SelectorParser};
use selectors::SelectorList;
use selectors::parser::{self as selector_parser, Selector, SelectorMethods, SelectorParseErrorKind};
@ -277,13 +278,6 @@ impl NonTSPseudoClass {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SelectorImpl;
/// A struct holding the members necessary to invalidate document state
/// selectors.
pub struct InvalidationMatchingData {
/// The document state that has changed, which makes it always match.
pub document_state: DocumentState,
}
impl ::selectors::SelectorImpl for SelectorImpl {
type ExtraMatchingData = InvalidationMatchingData;
type AttrValue = Atom;

View file

@ -0,0 +1,98 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! An invalidation processor for style changes due to document state changes.
use dom::TElement;
use element_state::DocumentState;
use invalidation::element::invalidator::{DescendantInvalidationLists, InvalidationVector};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
use invalidation::element::state_and_attributes;
use selectors::matching::{MatchingContext, MatchingMode, QuirksMode, VisitedHandlingMode};
use stylist::StyleRuleCascadeData;
/// A struct holding the members necessary to invalidate document state
/// selectors.
pub struct InvalidationMatchingData {
/// The document state that has changed, which makes it always match.
pub document_state: DocumentState,
}
/// An invalidation processor for style changes due to state and attribute
/// changes.
pub struct DocumentStateInvalidationProcessor<'a, E: TElement> {
rules: &'a StyleRuleCascadeData,
matching_context: MatchingContext<'a, E::Impl>,
document_states_changed: DocumentState,
}
impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> {
/// Creates a new DocumentStateInvalidationProcessor.
#[inline]
pub fn new(
rules: &'a StyleRuleCascadeData,
document_states_changed: DocumentState,
quirks_mode: QuirksMode,
) -> Self {
let mut matching_context = MatchingContext::new_for_visited(
MatchingMode::Normal,
None,
None,
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
quirks_mode,
);
matching_context.extra_data = Some(InvalidationMatchingData {
document_state: document_states_changed,
});
Self { rules, document_states_changed, matching_context }
}
}
impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidationProcessor<'a, E> {
fn collect_invalidations(
&mut self,
_element: E,
self_invalidations: &mut InvalidationVector<'a>,
_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;
}
self_invalidations.push(Invalidation::new(&dependency.selector, 0));
}
false
}
fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
&mut self.matching_context
}
fn recursion_limit_exceeded(&mut self, _: E) {
unreachable!("We don't run document state invalidation with stack limits")
}
fn should_process_descendants(&mut self, element: E) -> bool {
let data = match element.borrow_data() {
Some(d) => d,
None => return false,
};
state_and_attributes::should_process_descendants(&data)
}
fn invalidated_descendants(&mut self, element: E, child: E) {
state_and_attributes::invalidated_descendants(element, child)
}
fn invalidated_self(&mut self, element: E) {
state_and_attributes::invalidated_self(element);
}
}

View file

@ -4,6 +4,7 @@
//! Invalidation of element styles due to attribute or style changes.
pub mod document_state;
pub mod element_wrapper;
pub mod invalidation_map;
pub mod invalidator;

View file

@ -26,8 +26,6 @@
#![deny(warnings)]
#![deny(missing_docs)]
#![cfg_attr(feature = "servo", feature(never_type))]
#![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance
extern crate app_units;

View file

@ -12,6 +12,7 @@ use cssparser::{Parser as CssParser, ToCss, serialize_identifier, CowRcStr, Sour
use dom::{OpaqueNode, TElement, TNode};
use element_state::{DocumentState, ElementState};
use fnv::FnvHashMap;
use invalidation::element::document_state::InvalidationMatchingData;
use invalidation::element::element_wrapper::ElementSnapshot;
use properties::ComputedValues;
use properties::PropertyFlags;
@ -377,7 +378,7 @@ impl ::selectors::SelectorImpl for SelectorImpl {
type PseudoElement = PseudoElement;
type NonTSPseudoClass = NonTSPseudoClass;
type ExtraMatchingData = !;
type ExtraMatchingData = InvalidationMatchingData;
type AttrValue = String;
type Identifier = Atom;
type ClassName = Atom;