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 
8 use crate::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
9 use crate::matching::{ElementSelectorFlags, MatchingContext};
10 use crate::parser::SelectorImpl;
11 use std::fmt::Debug;
12 use std::ptr::NonNull;
13 
14 /// Opaque representation of an Element, for identity comparisons.
15 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
16 pub struct OpaqueElement(NonNull<()>);
17 
18 unsafe impl Send for OpaqueElement {}
19 
20 impl OpaqueElement {
21     /// Creates a new OpaqueElement from an arbitrarily-typed pointer.
new<T>(ptr: &T) -> Self22     pub fn new<T>(ptr: &T) -> Self {
23         unsafe {
24             OpaqueElement(NonNull::new_unchecked(
25                 ptr as *const T as *const () as *mut (),
26             ))
27         }
28     }
29 }
30 
31 pub trait Element: Sized + Clone + Debug {
32     type Impl: SelectorImpl;
33 
34     /// Converts self into an opaque representation.
opaque(&self) -> OpaqueElement35     fn opaque(&self) -> OpaqueElement;
36 
parent_element(&self) -> Option<Self>37     fn parent_element(&self) -> Option<Self>;
38 
39     /// Whether the parent node of this element is a shadow root.
parent_node_is_shadow_root(&self) -> bool40     fn parent_node_is_shadow_root(&self) -> bool;
41 
42     /// The host of the containing shadow root, if any.
containing_shadow_host(&self) -> Option<Self>43     fn containing_shadow_host(&self) -> Option<Self>;
44 
45     /// The parent of a given pseudo-element, after matching a pseudo-element
46     /// selector.
47     ///
48     /// This is guaranteed to be called in a pseudo-element.
pseudo_element_originating_element(&self) -> Option<Self>49     fn pseudo_element_originating_element(&self) -> Option<Self> {
50         debug_assert!(self.is_pseudo_element());
51         self.parent_element()
52     }
53 
54     /// Whether we're matching on a pseudo-element.
is_pseudo_element(&self) -> bool55     fn is_pseudo_element(&self) -> bool;
56 
57     /// Skips non-element nodes
prev_sibling_element(&self) -> Option<Self>58     fn prev_sibling_element(&self) -> Option<Self>;
59 
60     /// Skips non-element nodes
next_sibling_element(&self) -> Option<Self>61     fn next_sibling_element(&self) -> Option<Self>;
62 
is_html_element_in_html_document(&self) -> bool63     fn is_html_element_in_html_document(&self) -> bool;
64 
has_local_name(&self, local_name: &<Self::Impl as SelectorImpl>::BorrowedLocalName) -> bool65     fn has_local_name(&self, local_name: &<Self::Impl as SelectorImpl>::BorrowedLocalName) -> bool;
66 
67     /// Empty string for no namespace
has_namespace(&self, ns: &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl) -> bool68     fn has_namespace(&self, ns: &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl) -> bool;
69 
70     /// Whether this element and the `other` element have the same local name and namespace.
is_same_type(&self, other: &Self) -> bool71     fn is_same_type(&self, other: &Self) -> bool;
72 
attr_matches( &self, ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>, local_name: &<Self::Impl as SelectorImpl>::LocalName, operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>, ) -> bool73     fn attr_matches(
74         &self,
75         ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
76         local_name: &<Self::Impl as SelectorImpl>::LocalName,
77         operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>,
78     ) -> bool;
79 
match_non_ts_pseudo_class<F>( &self, pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass, context: &mut MatchingContext<Self::Impl>, flags_setter: &mut F, ) -> bool where F: FnMut(&Self, ElementSelectorFlags)80     fn match_non_ts_pseudo_class<F>(
81         &self,
82         pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
83         context: &mut MatchingContext<Self::Impl>,
84         flags_setter: &mut F,
85     ) -> bool
86     where
87         F: FnMut(&Self, ElementSelectorFlags);
88 
match_pseudo_element( &self, pe: &<Self::Impl as SelectorImpl>::PseudoElement, context: &mut MatchingContext<Self::Impl>, ) -> bool89     fn match_pseudo_element(
90         &self,
91         pe: &<Self::Impl as SelectorImpl>::PseudoElement,
92         context: &mut MatchingContext<Self::Impl>,
93     ) -> bool;
94 
95     /// Whether this element is a `link`.
is_link(&self) -> bool96     fn is_link(&self) -> bool;
97 
98     /// Returns whether the element is an HTML <slot> element.
is_html_slot_element(&self) -> bool99     fn is_html_slot_element(&self) -> bool;
100 
101     /// Returns the assigned <slot> element this element is assigned to.
102     ///
103     /// Necessary for the `::slotted` pseudo-class.
assigned_slot(&self) -> Option<Self>104     fn assigned_slot(&self) -> Option<Self> {
105         None
106     }
107 
has_id( &self, id: &<Self::Impl as SelectorImpl>::Identifier, case_sensitivity: CaseSensitivity, ) -> bool108     fn has_id(
109         &self,
110         id: &<Self::Impl as SelectorImpl>::Identifier,
111         case_sensitivity: CaseSensitivity,
112     ) -> bool;
113 
has_class( &self, name: &<Self::Impl as SelectorImpl>::Identifier, case_sensitivity: CaseSensitivity, ) -> bool114     fn has_class(
115         &self,
116         name: &<Self::Impl as SelectorImpl>::Identifier,
117         case_sensitivity: CaseSensitivity,
118     ) -> bool;
119 
120     /// Returns the mapping from the `exportparts` attribute in the reverse
121     /// direction, that is, in an outer-tree -> inner-tree direction.
imported_part( &self, name: &<Self::Impl as SelectorImpl>::Identifier, ) -> Option<<Self::Impl as SelectorImpl>::Identifier>122     fn imported_part(
123         &self,
124         name: &<Self::Impl as SelectorImpl>::Identifier,
125     ) -> Option<<Self::Impl as SelectorImpl>::Identifier>;
126 
is_part(&self, name: &<Self::Impl as SelectorImpl>::Identifier) -> bool127     fn is_part(&self, name: &<Self::Impl as SelectorImpl>::Identifier) -> bool;
128 
129     /// Returns whether this element matches `:empty`.
130     ///
131     /// That is, whether it does not contain any child element or any non-zero-length text node.
132     /// See http://dev.w3.org/csswg/selectors-3/#empty-pseudo
is_empty(&self) -> bool133     fn is_empty(&self) -> bool;
134 
135     /// Returns whether this element matches `:root`,
136     /// i.e. whether it is the root element of a document.
137     ///
138     /// Note: this can be false even if `.parent_element()` is `None`
139     /// if the parent node is a `DocumentFragment`.
is_root(&self) -> bool140     fn is_root(&self) -> bool;
141 
142     /// Returns whether this element should ignore matching nth child
143     /// selector.
ignores_nth_child_selectors(&self) -> bool144     fn ignores_nth_child_selectors(&self) -> bool {
145         false
146     }
147 }
148