tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1fae47ef94c8c474d3837bb0a120e0230dd904f8
parent 0345ccee7c6a06b1ef162a6910f8848483d764d7
Author: Diego Escalante <descalante@mozilla.com>
Date:   Tue,  2 Dec 2025 20:31:22 +0000

Bug 1986629 - Create AttributeProvider trait and  bindings to query element attribute values. r=emilio,firefox-style-system-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D274611

Diffstat:
Mlayout/style/GeckoBindings.cpp | 5+++++
Mlayout/style/GeckoBindings.h | 2++
Mservo/components/style/dom.rs | 26+++++++++++++++++++++++++-
Mservo/components/style/gecko/wrapper.rs | 19++++++++++++++++++-
4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/layout/style/GeckoBindings.cpp b/layout/style/GeckoBindings.cpp @@ -869,6 +869,11 @@ bool Gecko_IsSelectListBox(const Element* aElement) { return select && !select->IsCombobox(); } +bool Gecko_LookupAttrValue(const Element* aElement, const nsAtom& aName, + nsAString& aResult) { + return aElement->GetAttr(&aName, aResult); +} + template <typename Implementor> static nsAtom* LangValue(Implementor* aElement) { // TODO(emilio): Deduplicate a bit with nsIContent::GetLang(). diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h @@ -154,6 +154,8 @@ bool Gecko_HasActiveViewTransitionTypes( #define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \ nsAtom* prefix_##LangValue(implementor_ element); +bool Gecko_LookupAttrValue(const mozilla::dom::Element* aElement, + const nsAtom& aName, nsAString& aResult); bool Gecko_AttrEquals(const nsAttrValue*, const nsAtom*, bool aIgnoreCase); bool Gecko_AttrDashEquals(const nsAttrValue*, const nsAtom*, bool aIgnoreCase); bool Gecko_AttrIncludes(const nsAttrValue*, const nsAtom*, bool aIgnoreCase); diff --git a/servo/components/style/dom.rs b/servo/components/style/dom.rs @@ -385,7 +385,15 @@ pub trait TShadowRoot: Sized + Copy + Clone + Debug + PartialEq { /// The element trait, the main abstraction the style crate acts over. pub trait TElement: - Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + SelectorsElement<Impl = SelectorImpl> + Eq + + PartialEq + + Debug + + Hash + + Sized + + Copy + + Clone + + SelectorsElement<Impl = SelectorImpl> + + AttributeProvider { /// The concrete node type. type ConcreteNode: TNode<ConcreteElement = Self>; @@ -917,6 +925,22 @@ pub trait TElement: } } +/// The attribute provider trait +pub trait AttributeProvider { + /// Return the value of the given custom attibute if it exists. + fn get_attr(&self, attr: &LocalName) -> Option<String>; +} + +/// A dummy AttributeProvider that returns none to any attribute query. +#[derive(Clone, Debug, PartialEq)] +pub struct DummyAttributeProvider; + +impl AttributeProvider for DummyAttributeProvider { + fn get_attr(&self, _attr: &LocalName) -> Option<String> { + None + } +} + /// TNode and TElement aren't Send because we want to be careful and explicit /// about our parallel traversal. However, there are certain situations /// (including but not limited to the traversal) where we need to send DOM diff --git a/servo/components/style/gecko/wrapper.rs b/servo/components/style/gecko/wrapper.rs @@ -18,7 +18,10 @@ use crate::applicable_declarations::ApplicableDeclarationBlock; use crate::bloom::each_relevant_element_hash; use crate::context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks}; use crate::data::ElementData; -use crate::dom::{LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNode, TShadowRoot}; +use crate::dom::{ + AttributeProvider, LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNode, + TShadowRoot, +}; use crate::gecko::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl}; use crate::gecko::snapshot_helpers; use crate::gecko_bindings::bindings; @@ -71,6 +74,7 @@ use app_units::Au; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use dom::{DocumentState, ElementState}; use euclid::default::Size2D; +use nsstring::nsString; use rustc_hash::FxHashMap; use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint}; use selectors::bloom::{BloomFilter, BLOOM_HASH_MASK}; @@ -1818,6 +1822,19 @@ impl<'le> TElement for GeckoElement<'le> { } } +impl<'le> AttributeProvider for GeckoElement<'le> { + fn get_attr(&self, attr: &LocalName) -> Option<String> { + //TODO(bug 2003334): Avoid unnecessary string copies/conversions here. + let mut result = nsString::new(); + + if unsafe { bindings::Gecko_LookupAttrValue(self.0, attr.0.as_ptr(), &mut *result) } { + Some(result.to_string()) + } else { + None + } + } +} + impl<'le> PartialEq for GeckoElement<'le> { #[inline] fn eq(&self, other: &Self) -> bool {