Skip to main content

selectors/
tree.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//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency
6//! between layout and style.
7
8use crate::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
9use crate::bloom::BloomFilter;
10use crate::matching::{ElementSelectorFlags, MatchingContext};
11use crate::parser::SelectorImpl;
12use std::fmt::Debug;
13use std::ptr::NonNull;
14
15/// Opaque representation of an Element, for identity comparisons.
16#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
17pub struct OpaqueElement(NonNull<()>);
18
19unsafe impl Send for OpaqueElement {}
20// This should be safe given that we do not provide a way to recover
21// the original reference.
22unsafe impl Sync for OpaqueElement {}
23
24impl OpaqueElement {
25    /// Creates a new OpaqueElement from an arbitrarily-typed pointer.
26    pub fn new<T>(ptr: &T) -> Self {
27        // TODO: with rust 1.89, this can just be
28        // `OpaqueElement(NonNull::from_ref(ptr).cast())`
29        unsafe {
30            OpaqueElement(NonNull::new_unchecked(
31                ptr as *const T as *const () as *mut (),
32            ))
33        }
34    }
35
36    /// Creates a new OpaqueElement from a type-erased non-null pointer
37    pub fn from_ptr(ptr: NonNull<()>) -> Self {
38        Self(ptr)
39    }
40
41    /// Returns the reference as an untyped pointer.
42    #[inline]
43    pub fn to_ptr(&self) -> NonNull<()> {
44        self.0
45    }
46}
47
48pub trait Element: Sized + Copy + Clone + Debug {
49    type Impl: SelectorImpl;
50
51    /// Converts self into an opaque representation.
52    fn opaque(&self) -> OpaqueElement;
53
54    fn parent_element(&self) -> Option<Self>;
55
56    /// Whether the parent node of this element is a shadow root.
57    fn parent_node_is_shadow_root(&self) -> bool;
58
59    /// The host of the containing shadow root, if any.
60    fn containing_shadow_host(&self) -> Option<Self>;
61
62    /// The parent of a given pseudo-element, after matching a pseudo-element
63    /// selector.
64    ///
65    /// This is guaranteed to be called in a pseudo-element.
66    fn pseudo_element_originating_element(&self) -> Option<Self> {
67        debug_assert!(self.is_pseudo_element());
68        self.parent_element()
69    }
70
71    /// Whether we're matching on a pseudo-element.
72    fn is_pseudo_element(&self) -> bool;
73
74    /// Skips non-element nodes
75    fn prev_sibling_element(&self) -> Option<Self>;
76
77    /// Skips non-element nodes
78    fn next_sibling_element(&self) -> Option<Self>;
79
80    /// Skips non-element nodes
81    fn first_element_child(&self) -> Option<Self>;
82
83    fn is_html_element_in_html_document(&self) -> bool;
84
85    fn has_local_name(&self, local_name: &<Self::Impl as SelectorImpl>::BorrowedLocalName) -> bool;
86
87    /// Empty string for no namespace
88    fn has_namespace(&self, ns: &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl) -> bool;
89
90    /// Whether this element and the `other` element have the same local name and namespace.
91    fn is_same_type(&self, other: &Self) -> bool;
92
93    fn attr_matches(
94        &self,
95        ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
96        local_name: &<Self::Impl as SelectorImpl>::LocalName,
97        operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>,
98    ) -> bool;
99
100    fn has_attr_in_no_namespace(
101        &self,
102        local_name: &<Self::Impl as SelectorImpl>::LocalName,
103    ) -> bool {
104        self.attr_matches(
105            &NamespaceConstraint::Specific(&crate::parser::namespace_empty_string::<Self::Impl>()),
106            local_name,
107            &AttrSelectorOperation::Exists,
108        )
109    }
110
111    fn match_non_ts_pseudo_class(
112        &self,
113        pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
114        context: &mut MatchingContext<Self::Impl>,
115    ) -> bool;
116
117    fn match_pseudo_element(
118        &self,
119        pe: &<Self::Impl as SelectorImpl>::PseudoElement,
120        context: &mut MatchingContext<Self::Impl>,
121    ) -> bool;
122
123    /// Sets selector flags on the elemnt itself or the parent, depending on the
124    /// flags, which indicate what kind of work may need to be performed when
125    /// DOM state changes.
126    fn apply_selector_flags(&self, flags: ElementSelectorFlags);
127
128    /// Whether this element is a `link`.
129    fn is_link(&self) -> bool;
130
131    /// Returns whether the element is an HTML <slot> element.
132    fn is_html_slot_element(&self) -> bool;
133
134    /// Returns the assigned <slot> element this element is assigned to.
135    ///
136    /// Necessary for the `::slotted` pseudo-class.
137    fn assigned_slot(&self) -> Option<Self> {
138        None
139    }
140
141    fn has_id(
142        &self,
143        id: &<Self::Impl as SelectorImpl>::Identifier,
144        case_sensitivity: CaseSensitivity,
145    ) -> bool;
146
147    fn has_class(
148        &self,
149        name: &<Self::Impl as SelectorImpl>::Identifier,
150        case_sensitivity: CaseSensitivity,
151    ) -> bool;
152
153    fn has_custom_state(&self, name: &<Self::Impl as SelectorImpl>::Identifier) -> bool;
154
155    /// Returns the mapping from the `exportparts` attribute in the reverse
156    /// direction, that is, in an outer-tree -> inner-tree direction.
157    fn imported_part(
158        &self,
159        name: &<Self::Impl as SelectorImpl>::Identifier,
160    ) -> Option<<Self::Impl as SelectorImpl>::Identifier>;
161
162    fn is_part(&self, name: &<Self::Impl as SelectorImpl>::Identifier) -> bool;
163
164    /// Returns whether this element matches `:empty`.
165    ///
166    /// That is, whether it does not contain any child element or any non-zero-length text node.
167    /// See http://dev.w3.org/csswg/selectors-3/#empty-pseudo
168    fn is_empty(&self) -> bool;
169
170    /// Returns whether this element matches `:root`,
171    /// i.e. whether it is the root element of a document.
172    ///
173    /// Note: this can be false even if `.parent_element()` is `None`
174    /// if the parent node is a `DocumentFragment`.
175    fn is_root(&self) -> bool;
176
177    /// Returns whether this element should ignore matching nth child
178    /// selector.
179    fn ignores_nth_child_selectors(&self) -> bool {
180        false
181    }
182
183    /// Add hashes unique to this element to the given filter, returning true
184    /// if any got added.
185    fn add_element_unique_hashes(&self, filter: &mut BloomFilter) -> bool;
186
187    /// The filter summarizing the names present in this element's subtree,
188    /// including the element itself. See the `subtree_filter` module.
189    ///
190    /// The default implementation has every bit set, which never rejects.
191    fn subtree_filter(&self) -> u64 {
192        u64::MAX
193    }
194
195    /// Whether this element's subtree may contain all of the required hashes.
196    #[inline]
197    fn subtree_may_have_hashes(&self, hashes: u64) -> bool {
198        (self.subtree_filter() & hashes) == hashes
199    }
200}