tor-browser

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

dom.rs (36181B)


      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 //! Types and traits used to access the DOM from style calculation.
      6 
      7 #![allow(unsafe_code)]
      8 #![deny(missing_docs)]
      9 
     10 use crate::applicable_declarations::ApplicableDeclarationBlock;
     11 use crate::context::SharedStyleContext;
     12 #[cfg(feature = "gecko")]
     13 use crate::context::UpdateAnimationsTasks;
     14 use crate::data::ElementData;
     15 use crate::media_queries::Device;
     16 use crate::properties::{AnimationDeclarations, ComputedValues, PropertyDeclarationBlock};
     17 use crate::selector_parser::{AttrValue, Lang, PseudoElement, RestyleDamage, SelectorImpl};
     18 use crate::shared_lock::{Locked, SharedRwLock};
     19 use crate::stylesheets::scope_rule::ImplicitScopeRoot;
     20 use crate::stylist::CascadeData;
     21 use crate::values::computed::Display;
     22 use crate::values::AtomIdent;
     23 use crate::{LocalName, WeakAtom};
     24 use atomic_refcell::{AtomicRef, AtomicRefMut};
     25 use dom::ElementState;
     26 use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
     27 use selectors::sink::Push;
     28 use selectors::{Element as SelectorsElement, OpaqueElement};
     29 use servo_arc::{Arc, ArcBorrow};
     30 use std::fmt;
     31 use std::fmt::Debug;
     32 use std::hash::Hash;
     33 use std::ops::Deref;
     34 
     35 pub use style_traits::dom::OpaqueNode;
     36 
     37 /// Simple trait to provide basic information about the type of an element.
     38 ///
     39 /// We avoid exposing the full type id, since computing it in the general case
     40 /// would be difficult for Gecko nodes.
     41 pub trait NodeInfo {
     42    /// Whether this node is an element.
     43    fn is_element(&self) -> bool;
     44    /// Whether this node is a text node.
     45    fn is_text_node(&self) -> bool;
     46 }
     47 
     48 /// A node iterator that only returns node that don't need layout.
     49 pub struct LayoutIterator<T>(pub T);
     50 
     51 impl<T, N> Iterator for LayoutIterator<T>
     52 where
     53    T: Iterator<Item = N>,
     54    N: NodeInfo,
     55 {
     56    type Item = N;
     57 
     58    fn next(&mut self) -> Option<N> {
     59        loop {
     60            let n = self.0.next()?;
     61            // Filter out nodes that layout should ignore.
     62            if n.is_text_node() || n.is_element() {
     63                return Some(n);
     64            }
     65        }
     66    }
     67 }
     68 
     69 /// An iterator over the DOM children of a node.
     70 pub struct DomChildren<N>(Option<N>);
     71 impl<N> Iterator for DomChildren<N>
     72 where
     73    N: TNode,
     74 {
     75    type Item = N;
     76 
     77    fn next(&mut self) -> Option<N> {
     78        let n = self.0.take()?;
     79        self.0 = n.next_sibling();
     80        Some(n)
     81    }
     82 }
     83 
     84 /// An iterator over the DOM descendants of a node in pre-order.
     85 pub struct DomDescendants<N> {
     86    previous: Option<N>,
     87    scope: N,
     88 }
     89 
     90 impl<N> DomDescendants<N>
     91 where
     92    N: TNode,
     93 {
     94    /// Returns the next element ignoring all of our subtree.
     95    #[inline]
     96    pub fn next_skipping_children(&mut self) -> Option<N> {
     97        let prev = self.previous.take()?;
     98        self.previous = prev.next_in_preorder_skipping_children(self.scope);
     99        self.previous
    100    }
    101 }
    102 
    103 impl<N> Iterator for DomDescendants<N>
    104 where
    105    N: TNode,
    106 {
    107    type Item = N;
    108 
    109    #[inline]
    110    fn next(&mut self) -> Option<N> {
    111        let prev = self.previous.take()?;
    112        self.previous = prev.next_in_preorder(self.scope);
    113        self.previous
    114    }
    115 }
    116 
    117 /// The `TDocument` trait, to represent a document node.
    118 pub trait TDocument: Sized + Copy + Clone {
    119    /// The concrete `TNode` type.
    120    type ConcreteNode: TNode<ConcreteDocument = Self>;
    121 
    122    /// Get this document as a `TNode`.
    123    fn as_node(&self) -> Self::ConcreteNode;
    124 
    125    /// Returns whether this document is an HTML document.
    126    fn is_html_document(&self) -> bool;
    127 
    128    /// Returns the quirks mode of this document.
    129    fn quirks_mode(&self) -> QuirksMode;
    130 
    131    /// Get a list of elements with a given ID in this document, sorted by
    132    /// tree position.
    133    ///
    134    /// Can return an error to signal that this list is not available, or also
    135    /// return an empty slice.
    136    fn elements_with_id<'a>(
    137        &self,
    138        _id: &AtomIdent,
    139    ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()>
    140    where
    141        Self: 'a,
    142    {
    143        Err(())
    144    }
    145 
    146    /// This document's shared lock.
    147    fn shared_lock(&self) -> &SharedRwLock;
    148 }
    149 
    150 /// The `TNode` trait. This is the main generic trait over which the style
    151 /// system can be implemented.
    152 pub trait TNode: Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
    153    /// The concrete `TElement` type.
    154    type ConcreteElement: TElement<ConcreteNode = Self>;
    155 
    156    /// The concrete `TDocument` type.
    157    type ConcreteDocument: TDocument<ConcreteNode = Self>;
    158 
    159    /// The concrete `TShadowRoot` type.
    160    type ConcreteShadowRoot: TShadowRoot<ConcreteNode = Self>;
    161 
    162    /// Get this node's parent node.
    163    fn parent_node(&self) -> Option<Self>;
    164 
    165    /// Get this node's first child.
    166    fn first_child(&self) -> Option<Self>;
    167 
    168    /// Get this node's last child.
    169    fn last_child(&self) -> Option<Self>;
    170 
    171    /// Get this node's previous sibling.
    172    fn prev_sibling(&self) -> Option<Self>;
    173 
    174    /// Get this node's next sibling.
    175    fn next_sibling(&self) -> Option<Self>;
    176 
    177    /// Get the owner document of this node.
    178    fn owner_doc(&self) -> Self::ConcreteDocument;
    179 
    180    /// Iterate over the DOM children of a node.
    181    #[inline(always)]
    182    fn dom_children(&self) -> DomChildren<Self> {
    183        DomChildren(self.first_child())
    184    }
    185 
    186    /// Returns whether the node is attached to a document.
    187    fn is_in_document(&self) -> bool;
    188 
    189    /// Iterate over the DOM children of a node, in preorder.
    190    #[inline(always)]
    191    fn dom_descendants(&self) -> DomDescendants<Self> {
    192        DomDescendants {
    193            previous: Some(*self),
    194            scope: *self,
    195        }
    196    }
    197 
    198    /// Returns the next node after this one, in a pre-order tree-traversal of
    199    /// the subtree rooted at scoped_to.
    200    #[inline]
    201    fn next_in_preorder(&self, scoped_to: Self) -> Option<Self> {
    202        if let Some(c) = self.first_child() {
    203            return Some(c);
    204        }
    205        self.next_in_preorder_skipping_children(scoped_to)
    206    }
    207 
    208    /// Returns the next node in tree order, skipping the children of the current node.
    209    ///
    210    /// This is useful when we know that a subtree cannot contain matches, allowing us
    211    /// to skip entire subtrees during traversal.
    212    #[inline]
    213    fn next_in_preorder_skipping_children(&self, scoped_to: Self) -> Option<Self> {
    214        let mut current = *self;
    215        loop {
    216            if current == scoped_to {
    217                return None;
    218            }
    219 
    220            if let Some(s) = current.next_sibling() {
    221                return Some(s);
    222            }
    223 
    224            debug_assert!(
    225                current.parent_node().is_some(),
    226                "Not a descendant of the scope?"
    227            );
    228            current = current.parent_node()?;
    229        }
    230    }
    231 
    232    /// Returns the depth of this node in the DOM.
    233    fn depth(&self) -> usize {
    234        let mut depth = 0;
    235        let mut curr = *self;
    236        while let Some(parent) = curr.traversal_parent() {
    237            depth += 1;
    238            curr = parent.as_node();
    239        }
    240        depth
    241    }
    242 
    243    /// Get this node's parent element from the perspective of a restyle
    244    /// traversal.
    245    fn traversal_parent(&self) -> Option<Self::ConcreteElement>;
    246 
    247    /// Get this node's parent element if present.
    248    fn parent_element(&self) -> Option<Self::ConcreteElement> {
    249        self.parent_node().and_then(|n| n.as_element())
    250    }
    251 
    252    /// Get this node's parent element, or shadow host if it's a shadow root.
    253    fn parent_element_or_host(&self) -> Option<Self::ConcreteElement> {
    254        let parent = self.parent_node()?;
    255        if let Some(e) = parent.as_element() {
    256            return Some(e);
    257        }
    258        if let Some(root) = parent.as_shadow_root() {
    259            return Some(root.host());
    260        }
    261        None
    262    }
    263 
    264    /// Converts self into an `OpaqueNode`.
    265    fn opaque(&self) -> OpaqueNode;
    266 
    267    /// A debug id, only useful, mm... for debugging.
    268    fn debug_id(self) -> usize;
    269 
    270    /// Get this node as an element, if it's one.
    271    fn as_element(&self) -> Option<Self::ConcreteElement>;
    272 
    273    /// Get this node as a document, if it's one.
    274    fn as_document(&self) -> Option<Self::ConcreteDocument>;
    275 
    276    /// Get this node as a ShadowRoot, if it's one.
    277    fn as_shadow_root(&self) -> Option<Self::ConcreteShadowRoot>;
    278 }
    279 
    280 /// Wrapper to output the subtree rather than the single node when formatting
    281 /// for Debug.
    282 pub struct ShowSubtree<N: TNode>(pub N);
    283 impl<N: TNode> Debug for ShowSubtree<N> {
    284    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    285        writeln!(f, "DOM Subtree:")?;
    286        fmt_subtree(f, &|f, n| write!(f, "{:?}", n), self.0, 1)
    287    }
    288 }
    289 
    290 /// Wrapper to output the subtree along with the ElementData when formatting
    291 /// for Debug.
    292 pub struct ShowSubtreeData<N: TNode>(pub N);
    293 impl<N: TNode> Debug for ShowSubtreeData<N> {
    294    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    295        writeln!(f, "DOM Subtree:")?;
    296        fmt_subtree(f, &|f, n| fmt_with_data(f, n), self.0, 1)
    297    }
    298 }
    299 
    300 /// Wrapper to output the subtree along with the ElementData and primary
    301 /// ComputedValues when formatting for Debug. This is extremely verbose.
    302 #[cfg(feature = "servo")]
    303 pub struct ShowSubtreeDataAndPrimaryValues<N: TNode>(pub N);
    304 #[cfg(feature = "servo")]
    305 impl<N: TNode> Debug for ShowSubtreeDataAndPrimaryValues<N> {
    306    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    307        writeln!(f, "DOM Subtree:")?;
    308        fmt_subtree(f, &|f, n| fmt_with_data_and_primary_values(f, n), self.0, 1)
    309    }
    310 }
    311 
    312 fn fmt_with_data<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
    313    if let Some(el) = n.as_element() {
    314        write!(
    315            f,
    316            "{:?} dd={} aodd={} data={:?}",
    317            el,
    318            el.has_dirty_descendants(),
    319            el.has_animation_only_dirty_descendants(),
    320            el.borrow_data(),
    321        )
    322    } else {
    323        write!(f, "{:?}", n)
    324    }
    325 }
    326 
    327 #[cfg(feature = "servo")]
    328 fn fmt_with_data_and_primary_values<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
    329    if let Some(el) = n.as_element() {
    330        let dd = el.has_dirty_descendants();
    331        let aodd = el.has_animation_only_dirty_descendants();
    332        let data = el.borrow_data();
    333        let values = data.as_ref().and_then(|d| d.styles.get_primary());
    334        write!(
    335            f,
    336            "{:?} dd={} aodd={} data={:?} values={:?}",
    337            el, dd, aodd, &data, values
    338        )
    339    } else {
    340        write!(f, "{:?}", n)
    341    }
    342 }
    343 
    344 fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N, indent: u32) -> fmt::Result
    345 where
    346    F: Fn(&mut fmt::Formatter, N) -> fmt::Result,
    347 {
    348    for _ in 0..indent {
    349        write!(f, "  ")?;
    350    }
    351    stringify(f, n)?;
    352    if let Some(e) = n.as_element() {
    353        for kid in e.traversal_children() {
    354            writeln!(f, "")?;
    355            fmt_subtree(f, stringify, kid, indent + 1)?;
    356        }
    357    }
    358 
    359    Ok(())
    360 }
    361 
    362 /// The ShadowRoot trait.
    363 pub trait TShadowRoot: Sized + Copy + Clone + Debug + PartialEq {
    364    /// The concrete node type.
    365    type ConcreteNode: TNode<ConcreteShadowRoot = Self>;
    366 
    367    /// Get this ShadowRoot as a node.
    368    fn as_node(&self) -> Self::ConcreteNode;
    369 
    370    /// Get the shadow host that hosts this ShadowRoot.
    371    fn host(&self) -> <Self::ConcreteNode as TNode>::ConcreteElement;
    372 
    373    /// Get the style data for this ShadowRoot.
    374    fn style_data<'a>(&self) -> Option<&'a CascadeData>
    375    where
    376        Self: 'a;
    377 
    378    /// Get the list of shadow parts for this shadow root.
    379    fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::ConcreteElement]
    380    where
    381        Self: 'a,
    382    {
    383        &[]
    384    }
    385 
    386    /// Get a list of elements with a given ID in this shadow root, sorted by
    387    /// tree position.
    388    ///
    389    /// Can return an error to signal that this list is not available, or also
    390    /// return an empty slice.
    391    fn elements_with_id<'a>(
    392        &self,
    393        _id: &AtomIdent,
    394    ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()>
    395    where
    396        Self: 'a,
    397    {
    398        Err(())
    399    }
    400 
    401    /// Get the implicit scope for a stylesheet in given index.
    402    fn implicit_scope_for_sheet(&self, _sheet_index: usize) -> Option<ImplicitScopeRoot> {
    403        None
    404    }
    405 }
    406 
    407 /// The element trait, the main abstraction the style crate acts over.
    408 pub trait TElement:
    409    Eq
    410    + PartialEq
    411    + Debug
    412    + Hash
    413    + Sized
    414    + Copy
    415    + Clone
    416    + SelectorsElement<Impl = SelectorImpl>
    417    + AttributeProvider
    418 {
    419    /// The concrete node type.
    420    type ConcreteNode: TNode<ConcreteElement = Self>;
    421 
    422    /// A concrete children iterator type in order to iterate over the `Node`s.
    423    ///
    424    /// TODO(emilio): We should eventually replace this with the `impl Trait`
    425    /// syntax.
    426    type TraversalChildrenIterator: Iterator<Item = Self::ConcreteNode>;
    427 
    428    /// Get this element as a node.
    429    fn as_node(&self) -> Self::ConcreteNode;
    430 
    431    /// A debug-only check that the device's owner doc matches the actual doc
    432    /// we're the root of.
    433    ///
    434    /// Otherwise we may set document-level state incorrectly, like the root
    435    /// font-size used for rem units.
    436    fn owner_doc_matches_for_testing(&self, _: &Device) -> bool {
    437        true
    438    }
    439 
    440    /// Whether this element should match user and content rules.
    441    ///
    442    /// We use this for Native Anonymous Content in Gecko.
    443    fn matches_user_and_content_rules(&self) -> bool {
    444        true
    445    }
    446 
    447    /// Get this node's parent element from the perspective of a restyle
    448    /// traversal.
    449    fn traversal_parent(&self) -> Option<Self> {
    450        self.as_node().traversal_parent()
    451    }
    452 
    453    /// Get this node's children from the perspective of a restyle traversal.
    454    fn traversal_children(&self) -> LayoutIterator<Self::TraversalChildrenIterator>;
    455 
    456    /// Returns the parent element we should inherit from.
    457    ///
    458    /// This is pretty much always the parent element itself, except in the case
    459    /// of Gecko's Native Anonymous Content, which uses the traversal parent
    460    /// (i.e. the flattened tree parent) and which also may need to find the
    461    /// closest non-NAC ancestor.
    462    fn inheritance_parent(&self) -> Option<Self> {
    463        self.parent_element()
    464    }
    465 
    466    /// Execute `f` for each anonymous content child (apart from ::before and
    467    /// ::after) whose originating element is `self`.
    468    fn each_anonymous_content_child<F>(&self, _f: F)
    469    where
    470        F: FnMut(Self),
    471    {
    472    }
    473 
    474    /// Return whether this element is an element in the HTML namespace.
    475    fn is_html_element(&self) -> bool;
    476 
    477    /// Return whether this element is an element in the MathML namespace.
    478    fn is_mathml_element(&self) -> bool;
    479 
    480    /// Return whether this element is an element in the SVG namespace.
    481    fn is_svg_element(&self) -> bool;
    482 
    483    /// Return whether this element is an element in the XUL namespace.
    484    fn is_xul_element(&self) -> bool {
    485        false
    486    }
    487 
    488    /// Returns the bloom filter for this element's subtree, used for fast
    489    /// querySelector optimization by allowing subtrees to be skipped.
    490    /// Each element's filter includes hashes for all of it's class names and
    491    /// attribute names (not values), along with the names for all descendent
    492    /// elements.
    493    ///
    494    /// The default implementation returns all bits set, meaning the bloom filter
    495    /// never filters anything.
    496    fn subtree_bloom_filter(&self) -> u64 {
    497        u64::MAX
    498    }
    499 
    500    /// Check if this element's subtree may contain elements with the given bloom hash.
    501    fn bloom_may_have_hash(&self, bloom_hash: u64) -> bool {
    502        let bloom = self.subtree_bloom_filter();
    503        (bloom & bloom_hash) == bloom_hash
    504    }
    505 
    506    /// Convert a 32-bit atom hash to a bloom filter value using k=2 hash functions.
    507    /// This must match the C++ implementation of HashForBloomFilter in Element.cpp
    508    fn hash_for_bloom_filter(hash: u32) -> u64 {
    509        // On 32-bit platforms, we have 31 bits available + 1 tag bit.
    510        // On 64-bit platforms, we have 63 bits available + 1 tag bit.
    511        #[cfg(target_pointer_width = "32")]
    512        const BLOOM_BITS: u32 = 31;
    513 
    514        #[cfg(target_pointer_width = "64")]
    515        const BLOOM_BITS: u32 = 63;
    516 
    517        let mut filter = 1u64;
    518        filter |= 1u64 << (1 + (hash % BLOOM_BITS));
    519        filter |= 1u64 << (1 + ((hash >> 6) % BLOOM_BITS));
    520        filter
    521    }
    522 
    523    /// Return the list of slotted nodes of this node.
    524    fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
    525        &[]
    526    }
    527 
    528    /// Get this element's style attribute.
    529    fn style_attribute(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarationBlock>>>;
    530 
    531    /// Unset the style attribute's dirty bit.
    532    /// Servo doesn't need to manage ditry bit for style attribute.
    533    fn unset_dirty_style_attribute(&self) {}
    534 
    535    /// Get this element's SMIL override declarations.
    536    fn smil_override(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarationBlock>>> {
    537        None
    538    }
    539 
    540    /// Get the combined animation and transition rules.
    541    ///
    542    /// FIXME(emilio): Is this really useful?
    543    fn animation_declarations(&self, context: &SharedStyleContext) -> AnimationDeclarations {
    544        if !self.may_have_animations() {
    545            return Default::default();
    546        }
    547 
    548        AnimationDeclarations {
    549            animations: self.animation_rule(context),
    550            transitions: self.transition_rule(context),
    551        }
    552    }
    553 
    554    /// Get this element's animation rule.
    555    fn animation_rule(
    556        &self,
    557        _: &SharedStyleContext,
    558    ) -> Option<Arc<Locked<PropertyDeclarationBlock>>>;
    559 
    560    /// Get this element's transition rule.
    561    fn transition_rule(
    562        &self,
    563        context: &SharedStyleContext,
    564    ) -> Option<Arc<Locked<PropertyDeclarationBlock>>>;
    565 
    566    /// Get this element's state, for non-tree-structural pseudos.
    567    fn state(&self) -> ElementState;
    568 
    569    /// Returns whether this element has a `part` attribute.
    570    fn has_part_attr(&self) -> bool;
    571 
    572    /// Returns whether this element exports any part from its shadow tree.
    573    fn exports_any_part(&self) -> bool;
    574 
    575    /// The ID for this element.
    576    fn id(&self) -> Option<&WeakAtom>;
    577 
    578    /// Internal iterator for the classes of this element.
    579    fn each_class<F>(&self, callback: F)
    580    where
    581        F: FnMut(&AtomIdent);
    582 
    583    /// Internal iterator for the classes of this element.
    584    fn each_custom_state<F>(&self, callback: F)
    585    where
    586        F: FnMut(&AtomIdent);
    587 
    588    /// Internal iterator for the part names of this element.
    589    fn each_part<F>(&self, _callback: F)
    590    where
    591        F: FnMut(&AtomIdent),
    592    {
    593    }
    594 
    595    /// Internal iterator for the attribute names of this element.
    596    fn each_attr_name<F>(&self, callback: F)
    597    where
    598        F: FnMut(&LocalName);
    599 
    600    /// Internal iterator for the part names that this element exports for a
    601    /// given part name.
    602    fn each_exported_part<F>(&self, _name: &AtomIdent, _callback: F)
    603    where
    604        F: FnMut(&AtomIdent),
    605    {
    606    }
    607 
    608    /// Whether a given element may generate a pseudo-element.
    609    ///
    610    /// This is useful to avoid computing, for example, pseudo styles for
    611    /// `::-first-line` or `::-first-letter`, when we know it won't affect us.
    612    ///
    613    /// TODO(emilio, bz): actually implement the logic for it.
    614    fn may_generate_pseudo(&self, pseudo: &PseudoElement, _primary_style: &ComputedValues) -> bool {
    615        // ::before/::after are always supported for now, though we could try to
    616        // optimize out leaf elements.
    617 
    618        // ::first-letter and ::first-line are only supported for block-inside
    619        // things, and only in Gecko, not Servo.  Unfortunately, Gecko has
    620        // block-inside things that might have any computed display value due to
    621        // things like fieldsets, legends, etc.  Need to figure out how this
    622        // should work.
    623        debug_assert!(
    624            pseudo.is_eager(),
    625            "Someone called may_generate_pseudo with a non-eager pseudo."
    626        );
    627        true
    628    }
    629 
    630    /// Returns true if this element may have a descendant needing style processing.
    631    ///
    632    /// Note that we cannot guarantee the existence of such an element, because
    633    /// it may have been removed from the DOM between marking it for restyle and
    634    /// the actual restyle traversal.
    635    fn has_dirty_descendants(&self) -> bool;
    636 
    637    /// Returns whether state or attributes that may change style have changed
    638    /// on the element, and thus whether the element has been snapshotted to do
    639    /// restyle hint computation.
    640    fn has_snapshot(&self) -> bool;
    641 
    642    /// Returns whether the current snapshot if present has been handled.
    643    fn handled_snapshot(&self) -> bool;
    644 
    645    /// Flags this element as having handled already its snapshot.
    646    unsafe fn set_handled_snapshot(&self);
    647 
    648    /// Returns whether the element's styles are up-to-date after traversal
    649    /// (i.e. in post traversal).
    650    fn has_current_styles(&self, data: &ElementData) -> bool {
    651        if self.has_snapshot() && !self.handled_snapshot() {
    652            return false;
    653        }
    654 
    655        data.has_styles() &&
    656        // TODO(hiro): When an animating element moved into subtree of
    657        // contenteditable element, there remains animation restyle hints in
    658        // post traversal. It's generally harmless since the hints will be
    659        // processed in a next styling but ideally it should be processed soon.
    660        //
    661        // Without this, we get failures in:
    662        //   layout/style/crashtests/1383319.html
    663        //   layout/style/crashtests/1383001.html
    664        //
    665        // https://bugzilla.mozilla.org/show_bug.cgi?id=1389675 tracks fixing
    666        // this.
    667        !data.hint.has_non_animation_invalidations()
    668    }
    669 
    670    /// Flag that this element has a descendant for style processing.
    671    ///
    672    /// Only safe to call with exclusive access to the element.
    673    unsafe fn set_dirty_descendants(&self);
    674 
    675    /// Flag that this element has no descendant for style processing.
    676    ///
    677    /// Only safe to call with exclusive access to the element.
    678    unsafe fn unset_dirty_descendants(&self);
    679 
    680    /// Similar to the dirty_descendants but for representing a descendant of
    681    /// the element needs to be updated in animation-only traversal.
    682    fn has_animation_only_dirty_descendants(&self) -> bool {
    683        false
    684    }
    685 
    686    /// Flag that this element has a descendant for animation-only restyle
    687    /// processing.
    688    ///
    689    /// Only safe to call with exclusive access to the element.
    690    unsafe fn set_animation_only_dirty_descendants(&self) {}
    691 
    692    /// Flag that this element has no descendant for animation-only restyle processing.
    693    ///
    694    /// Only safe to call with exclusive access to the element.
    695    unsafe fn unset_animation_only_dirty_descendants(&self) {}
    696 
    697    /// Clear all bits related describing the dirtiness of descendants.
    698    ///
    699    /// In Gecko, this corresponds to the regular dirty descendants bit, the
    700    /// animation-only dirty descendants bit, and the lazy frame construction
    701    /// descendants bit.
    702    unsafe fn clear_descendant_bits(&self) {
    703        self.unset_dirty_descendants();
    704    }
    705 
    706    /// Returns true if this element is a visited link.
    707    ///
    708    /// Servo doesn't support visited styles yet.
    709    fn is_visited_link(&self) -> bool {
    710        false
    711    }
    712 
    713    /// Returns the pseudo-element implemented by this element, if any.
    714    ///
    715    /// Gecko traverses pseudo-elements during the style traversal, and we need
    716    /// to know this so we can properly grab the pseudo-element style from the
    717    /// parent element.
    718    ///
    719    /// Note that we still need to compute the pseudo-elements before-hand,
    720    /// given otherwise we don't know if we need to create an element or not.
    721    fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
    722        None
    723    }
    724 
    725    /// Atomically stores the number of children of this node that we will
    726    /// need to process during bottom-up traversal.
    727    fn store_children_to_process(&self, n: isize);
    728 
    729    /// Atomically notes that a child has been processed during bottom-up
    730    /// traversal. Returns the number of children left to process.
    731    fn did_process_child(&self) -> isize;
    732 
    733    /// Gets a reference to the ElementData container, or creates one.
    734    ///
    735    /// Unsafe because it can race to allocate and leak if not used with
    736    /// exclusive access to the element.
    737    unsafe fn ensure_data(&self) -> AtomicRefMut<'_, ElementData>;
    738 
    739    /// Clears the element data reference, if any.
    740    ///
    741    /// Unsafe following the same reasoning as ensure_data.
    742    unsafe fn clear_data(&self);
    743 
    744    /// Whether there is an ElementData container.
    745    fn has_data(&self) -> bool;
    746 
    747    /// Immutably borrows the ElementData.
    748    fn borrow_data(&self) -> Option<AtomicRef<'_, ElementData>>;
    749 
    750    /// Mutably borrows the ElementData.
    751    fn mutate_data(&self) -> Option<AtomicRefMut<'_, ElementData>>;
    752 
    753    /// Whether we should skip any root- or item-based display property
    754    /// blockification on this element.  (This function exists so that Gecko
    755    /// native anonymous content can opt out of this style fixup.)
    756    fn skip_item_display_fixup(&self) -> bool;
    757 
    758    /// In Gecko, element has a flag that represents the element may have
    759    /// any type of animations or not to bail out animation stuff early.
    760    /// Whereas Servo doesn't have such flag.
    761    fn may_have_animations(&self) -> bool;
    762 
    763    /// Creates a task to update various animation state on a given (pseudo-)element.
    764    #[cfg(feature = "gecko")]
    765    fn update_animations(
    766        &self,
    767        before_change_style: Option<Arc<ComputedValues>>,
    768        tasks: UpdateAnimationsTasks,
    769    );
    770 
    771    /// Returns true if the element has relevant animations. Relevant
    772    /// animations are those animations that are affecting the element's style
    773    /// or are scheduled to do so in the future.
    774    fn has_animations(&self, context: &SharedStyleContext) -> bool;
    775 
    776    /// Returns true if the element has a CSS animation. The `context` and `pseudo_element`
    777    /// arguments are only used by Servo, since it stores animations globally and pseudo-elements
    778    /// are not in the DOM.
    779    fn has_css_animations(
    780        &self,
    781        context: &SharedStyleContext,
    782        pseudo_element: Option<PseudoElement>,
    783    ) -> bool;
    784 
    785    /// Returns true if the element has a CSS transition (including running transitions and
    786    /// completed transitions). The `context` and `pseudo_element` arguments are only used
    787    /// by Servo, since it stores animations globally and pseudo-elements are not in the DOM.
    788    fn has_css_transitions(
    789        &self,
    790        context: &SharedStyleContext,
    791        pseudo_element: Option<PseudoElement>,
    792    ) -> bool;
    793 
    794    /// Returns true if the element has animation restyle hints.
    795    fn has_animation_restyle_hints(&self) -> bool {
    796        let data = match self.borrow_data() {
    797            Some(d) => d,
    798            None => return false,
    799        };
    800        return data.hint.has_animation_hint();
    801    }
    802 
    803    /// The shadow root this element is a host of.
    804    fn shadow_root(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>;
    805 
    806    /// The shadow root which roots the subtree this element is contained in.
    807    fn containing_shadow(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>;
    808 
    809    /// Return the element which we can use to look up rules in the selector
    810    /// maps.
    811    ///
    812    /// This is always the element itself, except in the case where we are an
    813    /// element-backed pseudo-element, in which case we return the originating
    814    /// element.
    815    fn rule_hash_target(&self) -> Self {
    816        let mut cur = *self;
    817        while cur.is_pseudo_element() {
    818            cur = cur
    819                .pseudo_element_originating_element()
    820                .expect("Trying to collect rules for a detached pseudo-element")
    821        }
    822        cur
    823    }
    824 
    825    /// Executes the callback for each applicable style rule data which isn't
    826    /// the main document's data (which stores UA / author rules).
    827    ///
    828    /// The element passed to the callback is the containing shadow host for the
    829    /// data if it comes from Shadow DOM.
    830    ///
    831    /// Returns whether normal document author rules should apply.
    832    ///
    833    /// TODO(emilio): We could separate the invalidation data for elements
    834    /// matching in other scopes to avoid over-invalidation.
    835    fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
    836    where
    837        Self: 'a,
    838        F: FnMut(&'a CascadeData, Self),
    839    {
    840        use crate::rule_collector::containing_shadow_ignoring_svg_use;
    841 
    842        let target = self.rule_hash_target();
    843        let matches_user_and_content_rules = target.matches_user_and_content_rules();
    844        let mut doc_rules_apply = matches_user_and_content_rules;
    845 
    846        // Use the same rules to look for the containing host as we do for rule
    847        // collection.
    848        if let Some(shadow) = containing_shadow_ignoring_svg_use(target) {
    849            doc_rules_apply = false;
    850            if let Some(data) = shadow.style_data() {
    851                f(data, shadow.host());
    852            }
    853        }
    854 
    855        if let Some(shadow) = target.shadow_root() {
    856            if let Some(data) = shadow.style_data() {
    857                f(data, shadow.host());
    858            }
    859        }
    860 
    861        let mut current = target.assigned_slot();
    862        while let Some(slot) = current {
    863            // Slots can only have assigned nodes when in a shadow tree.
    864            let shadow = slot.containing_shadow().unwrap();
    865            if let Some(data) = shadow.style_data() {
    866                if data.any_slotted_rule() {
    867                    f(data, shadow.host());
    868                }
    869            }
    870            current = slot.assigned_slot();
    871        }
    872 
    873        if target.has_part_attr() {
    874            if let Some(mut inner_shadow) = target.containing_shadow() {
    875                loop {
    876                    let inner_shadow_host = inner_shadow.host();
    877                    match inner_shadow_host.containing_shadow() {
    878                        Some(shadow) => {
    879                            if let Some(data) = shadow.style_data() {
    880                                if data.any_part_rule() {
    881                                    f(data, shadow.host())
    882                                }
    883                            }
    884                            // TODO: Could be more granular.
    885                            if !inner_shadow_host.exports_any_part() {
    886                                break;
    887                            }
    888                            inner_shadow = shadow;
    889                        },
    890                        None => {
    891                            // TODO(emilio): Should probably distinguish with
    892                            // MatchesDocumentRules::{No,Yes,IfPart} or something so that we could
    893                            // skip some work.
    894                            doc_rules_apply = matches_user_and_content_rules;
    895                            break;
    896                        },
    897                    }
    898                }
    899            }
    900        }
    901 
    902        doc_rules_apply
    903    }
    904 
    905    /// Returns true if one of the transitions needs to be updated on this element. We check all
    906    /// the transition properties to make sure that updating transitions is necessary.
    907    /// This method should only be called if might_needs_transitions_update returns true when
    908    /// passed the same parameters.
    909    #[cfg(feature = "gecko")]
    910    fn needs_transitions_update(
    911        &self,
    912        before_change_style: &ComputedValues,
    913        after_change_style: &ComputedValues,
    914    ) -> bool;
    915 
    916    /// Returns the value of the `xml:lang=""` attribute (or, if appropriate,
    917    /// the `lang=""` attribute) on this element.
    918    fn lang_attr(&self) -> Option<AttrValue>;
    919 
    920    /// Returns whether this element's language matches the language tag
    921    /// `value`.  If `override_lang` is not `None`, it specifies the value
    922    /// of the `xml:lang=""` or `lang=""` attribute to use in place of
    923    /// looking at the element and its ancestors.  (This argument is used
    924    /// to implement matching of `:lang()` against snapshots.)
    925    fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, value: &Lang) -> bool;
    926 
    927    /// Returns whether this element is the main body element of the HTML
    928    /// document it is on.
    929    fn is_html_document_body_element(&self) -> bool;
    930 
    931    /// Generate the proper applicable declarations due to presentational hints,
    932    /// and insert them into `hints`.
    933    fn synthesize_presentational_hints_for_legacy_attributes<V>(
    934        &self,
    935        visited_handling: VisitedHandlingMode,
    936        hints: &mut V,
    937    ) where
    938        V: Push<ApplicableDeclarationBlock>;
    939 
    940    /// Generate the proper applicable declarations due to view transition dynamic rules, and
    941    /// insert them into `rules`.
    942    /// https://drafts.csswg.org/css-view-transitions-1/#document-dynamic-view-transition-style-sheet
    943    fn synthesize_view_transition_dynamic_rules<V>(&self, _rules: &mut V)
    944    where
    945        V: Push<ApplicableDeclarationBlock>,
    946    {
    947    }
    948 
    949    /// Returns element's local name.
    950    fn local_name(&self) -> &<SelectorImpl as selectors::parser::SelectorImpl>::BorrowedLocalName;
    951 
    952    /// Returns element's namespace.
    953    fn namespace(&self)
    954        -> &<SelectorImpl as selectors::parser::SelectorImpl>::BorrowedNamespaceUrl;
    955 
    956    /// Returns the size of the element to be used in container size queries.
    957    /// This will usually be the size of the content area of the primary box,
    958    /// but can be None if there is no box or if some axis lacks size containment.
    959    fn query_container_size(
    960        &self,
    961        display: &Display,
    962    ) -> euclid::default::Size2D<Option<app_units::Au>>;
    963 
    964    /// Returns true if the element has all of specified selector flags.
    965    fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
    966 
    967    /// Returns the search direction for relative selector invalidation, if it is on the search path.
    968    fn relative_selector_search_direction(&self) -> ElementSelectorFlags;
    969 
    970    /// Returns the implicit scope root for given sheet index and host.
    971    fn implicit_scope_for_sheet_in_shadow_root(
    972        _opaque_host: OpaqueElement,
    973        _sheet_index: usize,
    974    ) -> Option<ImplicitScopeRoot> {
    975        None
    976    }
    977 
    978    /// Compute the damage incurred by the change from the `_old` to `_new`.
    979    fn compute_layout_damage(_old: &ComputedValues, _new: &ComputedValues) -> RestyleDamage {
    980        Default::default()
    981    }
    982 }
    983 
    984 /// The attribute provider trait
    985 pub trait AttributeProvider {
    986    /// Return the value of the given custom attibute if it exists.
    987    fn get_attr(&self, attr: &LocalName) -> Option<String>;
    988 }
    989 
    990 /// A dummy AttributeProvider that returns none to any attribute query.
    991 #[derive(Clone, Debug, PartialEq)]
    992 pub struct DummyAttributeProvider;
    993 
    994 impl AttributeProvider for DummyAttributeProvider {
    995    fn get_attr(&self, _attr: &LocalName) -> Option<String> {
    996        None
    997    }
    998 }
    999 
   1000 /// TNode and TElement aren't Send because we want to be careful and explicit
   1001 /// about our parallel traversal. However, there are certain situations
   1002 /// (including but not limited to the traversal) where we need to send DOM
   1003 /// objects to other threads.
   1004 ///
   1005 /// That's the reason why `SendNode` exists.
   1006 #[derive(Clone, Debug, PartialEq)]
   1007 pub struct SendNode<N: TNode>(N);
   1008 unsafe impl<N: TNode> Send for SendNode<N> {}
   1009 impl<N: TNode> SendNode<N> {
   1010    /// Unsafely construct a SendNode.
   1011    pub unsafe fn new(node: N) -> Self {
   1012        SendNode(node)
   1013    }
   1014 }
   1015 impl<N: TNode> Deref for SendNode<N> {
   1016    type Target = N;
   1017    fn deref(&self) -> &N {
   1018        &self.0
   1019    }
   1020 }
   1021 
   1022 /// Same reason as for the existence of SendNode, SendElement does the proper
   1023 /// things for a given `TElement`.
   1024 #[derive(Debug, Eq, Hash, PartialEq)]
   1025 pub struct SendElement<E: TElement>(E);
   1026 unsafe impl<E: TElement> Send for SendElement<E> {}
   1027 impl<E: TElement> SendElement<E> {
   1028    /// Unsafely construct a SendElement.
   1029    pub unsafe fn new(el: E) -> Self {
   1030        SendElement(el)
   1031    }
   1032 }
   1033 impl<E: TElement> Deref for SendElement<E> {
   1034    type Target = E;
   1035    fn deref(&self) -> &E {
   1036        &self.0
   1037    }
   1038 }