style/
dom.rs

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
10use crate::applicable_declarations::ApplicableDeclarationBlock;
11use crate::context::SharedStyleContext;
12#[cfg(feature = "gecko")]
13use crate::context::UpdateAnimationsTasks;
14use crate::data::ElementData;
15use crate::media_queries::Device;
16use crate::properties::{AnimationDeclarations, ComputedValues, PropertyDeclarationBlock};
17use crate::selector_parser::{AttrValue, Lang, PseudoElement, RestyleDamage, SelectorImpl};
18use crate::shared_lock::{Locked, SharedRwLock};
19use crate::stylesheets::scope_rule::ImplicitScopeRoot;
20use crate::stylist::CascadeData;
21use crate::values::computed::Display;
22use crate::values::AtomIdent;
23use crate::{LocalName, WeakAtom};
24use atomic_refcell::{AtomicRef, AtomicRefMut};
25use dom::ElementState;
26use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
27use selectors::sink::Push;
28use selectors::{Element as SelectorsElement, OpaqueElement};
29use servo_arc::{Arc, ArcBorrow};
30use std::fmt;
31use std::fmt::Debug;
32use std::hash::Hash;
33use std::ops::Deref;
34
35pub 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.
41pub 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.
49pub struct LayoutIterator<T>(pub T);
50
51impl<T, N> Iterator for LayoutIterator<T>
52where
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.
70pub struct DomChildren<N>(Option<N>);
71impl<N> Iterator for DomChildren<N>
72where
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.
85pub struct DomDescendants<N> {
86    previous: Option<N>,
87    scope: N,
88}
89
90impl<N> DomDescendants<N>
91where
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
103impl<N> Iterator for DomDescendants<N>
104where
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.
118pub 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.
152pub 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.
282pub struct ShowSubtree<N: TNode>(pub N);
283impl<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.
292pub struct ShowSubtreeData<N: TNode>(pub N);
293impl<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")]
303pub struct ShowSubtreeDataAndPrimaryValues<N: TNode>(pub N);
304#[cfg(feature = "servo")]
305impl<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
312fn 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")]
328fn 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
344fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N, indent: u32) -> fmt::Result
345where
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.
363pub 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.
408pub 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
985pub 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)]
992pub struct DummyAttributeProvider;
993
994impl 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)]
1007pub struct SendNode<N: TNode>(N);
1008unsafe impl<N: TNode> Send for SendNode<N> {}
1009impl<N: TNode> SendNode<N> {
1010    /// Unsafely construct a SendNode.
1011    pub unsafe fn new(node: N) -> Self {
1012        SendNode(node)
1013    }
1014}
1015impl<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)]
1025pub struct SendElement<E: TElement>(E);
1026unsafe impl<E: TElement> Send for SendElement<E> {}
1027impl<E: TElement> SendElement<E> {
1028    /// Unsafely construct a SendElement.
1029    pub unsafe fn new(el: E) -> Self {
1030        SendElement(el)
1031    }
1032}
1033impl<E: TElement> Deref for SendElement<E> {
1034    type Target = E;
1035    fn deref(&self) -> &E {
1036        &self.0
1037    }
1038}