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