Skip to main content

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