diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index d738ef1151f..a0c1a8b7a61 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -715,6 +715,14 @@ impl<'le> TElement for ServoLayoutElement<'le> { .map(ServoShadowRoot::from_layout_js) } } + + fn local_name(&self) -> &LocalName { + self.element.local_name() + } + + fn namespace(&self) -> &Namespace { + self.element.namespace() + } } impl<'le> PartialEq for ServoLayoutElement<'le> { @@ -879,13 +887,19 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> { } #[inline] - fn local_name(&self) -> &LocalName { - self.element.local_name() + fn has_local_name(&self, name: &LocalName) -> bool { + self.element.local_name() == name } #[inline] - fn namespace(&self) -> &Namespace { - self.element.namespace() + fn has_namespace(&self, ns: &Namespace) -> bool { + self.element.namespace() == ns + } + + #[inline] + fn is_same_type(&self, other: &Self) -> bool { + self.element.local_name() == other.element.local_name() && + self.element.namespace() == other.element.namespace() } fn is_pseudo_element(&self) -> bool { @@ -1266,8 +1280,8 @@ where loop { let next_node = if let Some(ref node) = current_node { if let Some(element) = node.as_element() { - if element.local_name() == &local_name!("summary") && - element.namespace() == &ns!(html) + if element.has_local_name(&local_name!("summary")) && + element.has_namespace(&ns!(html)) { self.current_node = None; return Some(node.clone()); @@ -1286,8 +1300,10 @@ where let node = self.current_node.clone(); let node = node.and_then(|node| { if node.is_element() && - node.as_element().unwrap().local_name() == &local_name!("summary") && - node.as_element().unwrap().namespace() == &ns!(html) + node.as_element() + .unwrap() + .has_local_name(&local_name!("summary")) && + node.as_element().unwrap().has_namespace(&ns!(html)) { unsafe { node.dangerous_next_sibling() } } else { @@ -1437,13 +1453,19 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> { } #[inline] - fn local_name(&self) -> &LocalName { - self.element.local_name() + fn has_local_name(&self, name: &LocalName) -> bool { + self.element.local_name() == name } #[inline] - fn namespace(&self) -> &Namespace { - self.element.namespace() + fn has_namespace(&self, ns: &Namespace) -> bool { + self.element.namespace() == ns + } + + #[inline] + fn is_same_type(&self, other: &Self) -> bool { + self.element.local_name() == other.element.local_name() && + self.element.namespace() == other.element.namespace() } fn match_pseudo_element( diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index c4174309af9..8063b63811b 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -3004,12 +3004,17 @@ impl<'a> SelectorsElement for DomRoot { }) } - fn local_name(&self) -> &LocalName { - Element::local_name(self) + fn has_local_name(&self, local_name: &LocalName) -> bool { + Element::local_name(self) == local_name } - fn namespace(&self) -> &Namespace { - Element::namespace(self) + fn has_namespace(&self, ns: &Namespace) -> bool { + Element::namespace(self) == ns + } + + fn is_same_type(&self, other: &Self) -> bool { + Element::local_name(self) == Element::local_name(other) && + Element::namespace(self) == Element::namespace(other) } fn match_non_ts_pseudo_class( diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 0e1df2ac4c8..ae559474d06 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -391,7 +391,7 @@ pub trait ThreadSafeLayoutElement: #[inline] fn get_details_summary_pseudo(&self) -> Option { - if self.local_name() == &local_name!("details") && self.namespace() == &ns!(html) { + if self.has_local_name(&local_name!("details")) && self.has_namespace(&ns!(html)) { Some(self.with_pseudo(PseudoElementType::DetailsSummary)) } else { None @@ -400,8 +400,8 @@ pub trait ThreadSafeLayoutElement: #[inline] fn get_details_content_pseudo(&self) -> Option { - if self.local_name() == &local_name!("details") && - self.namespace() == &ns!(html) && + if self.has_local_name(&local_name!("details")) && + self.has_namespace(&ns!(html)) && self.get_attr(&ns!(), &local_name!("open")).is_some() { Some(self.with_pseudo(PseudoElementType::DetailsContent)) diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 6554f2f9cc4..45acc13e7e1 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -596,7 +596,7 @@ where &local_name.lower_name, ) .borrow(); - element.local_name() == name + element.has_local_name(name) } /// Determines whether the given element matches the given compound selector. @@ -681,11 +681,11 @@ where Component::LocalName(ref local_name) => matches_local_name(element, local_name), Component::ExplicitUniversalType | Component::ExplicitAnyNamespace => true, Component::Namespace(_, ref url) | Component::DefaultNamespace(ref url) => { - element.namespace() == url.borrow() + element.has_namespace(&url.borrow()) }, Component::ExplicitNoNamespace => { let ns = crate::parser::namespace_empty_string::(); - element.namespace() == ns.borrow() + element.has_namespace(&ns.borrow()) }, Component::ID(ref id) => { element.has_id(id, context.shared.classes_and_ids_case_sensitivity()) @@ -897,11 +897,6 @@ where } } -#[inline] -fn same_type(a: &E, b: &E) -> bool { - a.local_name() == b.local_name() && a.namespace() == b.namespace() -} - #[inline] fn nth_child_index( element: &E, @@ -924,7 +919,7 @@ where let mut curr = element.clone(); while let Some(e) = curr.prev_sibling_element() { curr = e; - if !is_of_type || same_type(element, &curr) { + if !is_of_type || element.is_same_type(&curr) { if let Some(i) = c.lookup(curr.opaque()) { return i - index; } @@ -945,7 +940,7 @@ where }; while let Some(e) = next(curr) { curr = e; - if !is_of_type || same_type(element, &curr) { + if !is_of_type || element.is_same_type(&curr) { // If we're computing indices from the left, check each element in the // cache. We handle the indices-from-the-right case at the top of this // function. diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs index 611e40d6027..f892abd4e94 100644 --- a/components/selectors/tree.rs +++ b/components/selectors/tree.rs @@ -62,10 +62,13 @@ pub trait Element: Sized + Clone + Debug { fn is_html_element_in_html_document(&self) -> bool; - fn local_name(&self) -> &::BorrowedLocalName; + fn has_local_name(&self, local_name: &::BorrowedLocalName) -> bool; /// Empty string for no namespace - fn namespace(&self) -> &::BorrowedNamespaceUrl; + fn has_namespace(&self, ns: &::BorrowedNamespaceUrl) -> bool; + + /// Whether this element and the `other` element have the same local name and namespace. + fn is_same_type(&self, other: &Self) -> bool; fn attr_matches( &self, diff --git a/components/style/dom.rs b/components/style/dom.rs index 5ee8443b91d..04d6a79b384 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -882,6 +882,13 @@ pub trait TElement: hints: &mut V, ) where V: Push; + + /// Returns element's local name. + fn local_name(&self) -> &::BorrowedLocalName; + + /// Returns element's namespace. + fn namespace(&self) + -> &::BorrowedNamespaceUrl; } /// TNode and TElement aren't Send because we want to be careful and explicit diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index fadb0aefe52..3ce9e6fe6ab 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -1166,6 +1166,19 @@ impl<'le> TElement for GeckoElement<'le> { self.namespace_id() == structs::root::kNameSpaceID_XUL as i32 } + #[inline] + fn local_name(&self) -> &WeakAtom { + unsafe { WeakAtom::new(self.as_node().node_info().mInner.mName) } + } + + #[inline] + fn namespace(&self) -> &WeakNamespace { + unsafe { + let namespace_manager = structs::nsContentUtils_sNameSpaceManager; + WeakNamespace::new((*namespace_manager).mURIArray[self.namespace_id() as usize].mRawPtr) + } + } + /// Return the list of slotted nodes of this node. #[inline] fn slotted_nodes(&self) -> &[Self::ConcreteNode] { @@ -2071,16 +2084,18 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } #[inline] - fn local_name(&self) -> &WeakAtom { - unsafe { WeakAtom::new(self.as_node().node_info().mInner.mName) } + fn has_local_name(&self, name: &WeakAtom) -> bool { + self.local_name() == name } #[inline] - fn namespace(&self) -> &WeakNamespace { - unsafe { - let namespace_manager = structs::nsContentUtils_sNameSpaceManager; - WeakNamespace::new((*namespace_manager).mURIArray[self.namespace_id() as usize].mRawPtr) - } + fn has_namespace(&self, ns: &WeakNamespace) -> bool { + self.namespace() == ns + } + + #[inline] + fn is_same_type(&self, other: &Self) -> bool { + self.local_name() == other.local_name() && self.namespace() == other.namespace() } fn match_non_ts_pseudo_class( diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs index 91f0705853c..cb63e611348 100644 --- a/components/style/invalidation/element/element_wrapper.rs +++ b/components/style/invalidation/element/element_wrapper.rs @@ -312,13 +312,24 @@ where } #[inline] - fn local_name(&self) -> &::BorrowedLocalName { - self.element.local_name() + fn has_local_name( + &self, + local_name: &::BorrowedLocalName, + ) -> bool { + self.element.has_local_name(local_name) } #[inline] - fn namespace(&self) -> &::BorrowedNamespaceUrl { - self.element.namespace() + fn has_namespace( + &self, + ns: &::BorrowedNamespaceUrl, + ) -> bool { + self.element.has_namespace(ns) + } + + #[inline] + fn is_same_type(&self, other: &Self) -> bool { + self.element.is_same_type(&other.element) } fn attr_matches(