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