tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

document_state.rs (5374B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 //! An invalidation processor for style changes due to document state changes.
      6 
      7 use crate::dom::TElement;
      8 use crate::invalidation::element::invalidation_map::Dependency;
      9 use crate::invalidation::element::invalidator::{
     10    DescendantInvalidationLists, InvalidationVector, SiblingTraversalMap,
     11 };
     12 use crate::invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
     13 use crate::invalidation::element::state_and_attributes;
     14 use crate::stylist::CascadeData;
     15 use dom::DocumentState;
     16 use selectors::matching::{
     17    IncludeStartingStyle, MatchingContext, MatchingForInvalidation, MatchingMode,
     18    NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
     19 };
     20 use selectors::OpaqueElement;
     21 
     22 /// A struct holding the members necessary to invalidate document state
     23 /// selectors.
     24 #[derive(Debug)]
     25 pub struct InvalidationMatchingData {
     26    /// The document state that has changed, which makes it always match.
     27    pub document_state: DocumentState,
     28 }
     29 
     30 impl Default for InvalidationMatchingData {
     31    #[inline(always)]
     32    fn default() -> Self {
     33        Self {
     34            document_state: DocumentState::empty(),
     35        }
     36    }
     37 }
     38 
     39 /// An invalidation processor for style changes due to state and attribute
     40 /// changes.
     41 pub struct DocumentStateInvalidationProcessor<'a, 'b, E: TElement, I> {
     42    rules: I,
     43    matching_context: MatchingContext<'a, E::Impl>,
     44    traversal_map: SiblingTraversalMap<E>,
     45    document_states_changed: DocumentState,
     46    _marker: std::marker::PhantomData<&'b ()>,
     47 }
     48 
     49 impl<'a, 'b, E: TElement, I> DocumentStateInvalidationProcessor<'a, 'b, E, I> {
     50    /// Creates a new DocumentStateInvalidationProcessor.
     51    #[inline]
     52    pub fn new(
     53        rules: I,
     54        document_states_changed: DocumentState,
     55        selector_caches: &'a mut SelectorCaches,
     56        quirks_mode: QuirksMode,
     57    ) -> Self {
     58        let mut matching_context = MatchingContext::<'a, E::Impl>::new_for_visited(
     59            MatchingMode::Normal,
     60            None,
     61            selector_caches,
     62            VisitedHandlingMode::AllLinksVisitedAndUnvisited,
     63            IncludeStartingStyle::No,
     64            quirks_mode,
     65            NeedsSelectorFlags::No,
     66            MatchingForInvalidation::No,
     67        );
     68 
     69        matching_context.extra_data.invalidation_data.document_state = document_states_changed;
     70 
     71        Self {
     72            rules,
     73            document_states_changed,
     74            matching_context,
     75            traversal_map: SiblingTraversalMap::default(),
     76            _marker: std::marker::PhantomData,
     77        }
     78    }
     79 }
     80 
     81 impl<'a, 'b, E, I> InvalidationProcessor<'b, 'a, E>
     82    for DocumentStateInvalidationProcessor<'a, 'b, E, I>
     83 where
     84    E: TElement,
     85    I: Iterator<Item = &'b CascadeData>,
     86 {
     87    fn check_outer_dependency(&mut self, _: &Dependency, _: E, _: Option<OpaqueElement>) -> bool {
     88        debug_assert!(
     89            false,
     90            "how, we should only have parent-less dependencies here!"
     91        );
     92        true
     93    }
     94 
     95    fn collect_invalidations(
     96        &mut self,
     97        _element: E,
     98        self_invalidations: &mut InvalidationVector<'b>,
     99        _descendant_invalidations: &mut DescendantInvalidationLists<'b>,
    100        _sibling_invalidations: &mut InvalidationVector<'b>,
    101    ) -> bool {
    102        for cascade_data in &mut self.rules {
    103            let map = cascade_data.invalidation_map();
    104            for dependency in &map.document_state_selectors {
    105                if !dependency.state.intersects(self.document_states_changed) {
    106                    continue;
    107                }
    108 
    109                // We pass `None` as a scope, as document state selectors aren't
    110                // affected by the current scope.
    111                //
    112                // FIXME(emilio): We should really pass the relevant host for
    113                // self.rules, so that we invalidate correctly if the selector
    114                // happens to have something like :host(:-moz-window-inactive)
    115                // for example.
    116                self_invalidations.push(Invalidation::new(
    117                    &dependency.dependency,
    118                    /* host = */ None,
    119                    /* scope = */ None,
    120                ));
    121            }
    122        }
    123 
    124        false
    125    }
    126 
    127    fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
    128        &mut self.matching_context
    129    }
    130 
    131    fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
    132        &self.traversal_map
    133    }
    134 
    135    fn recursion_limit_exceeded(&mut self, _: E) {
    136        unreachable!("We don't run document state invalidation with stack limits")
    137    }
    138 
    139    fn should_process_descendants(&mut self, element: E) -> bool {
    140        match element.borrow_data() {
    141            Some(d) => state_and_attributes::should_process_descendants(&d),
    142            None => false,
    143        }
    144    }
    145 
    146    fn invalidated_descendants(&mut self, element: E, child: E) {
    147        state_and_attributes::invalidated_descendants(element, child)
    148    }
    149 
    150    fn invalidated_self(&mut self, element: E) {
    151        state_and_attributes::invalidated_self(element);
    152    }
    153 
    154    fn invalidated_sibling(&mut self, sibling: E, of: E) {
    155        state_and_attributes::invalidated_sibling(sibling, of);
    156    }
    157 }