mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 13:25:37 +00:00
Bug 1483964: Manually inline class and ID getters. r=xidorn
Somewhat ugly but hopefully not too much. Somehow it ends up removing more lines than adding. Differential Revision: https://phabricator.services.mozilla.com/D3536
This commit is contained in:
parent
557d043591
commit
5a92426ddb
@ -949,23 +949,12 @@ public:
|
||||
* class attribute). This may be null if there are no classes, but that's not
|
||||
* guaranteed (e.g. we could have class="").
|
||||
*/
|
||||
const nsAttrValue* GetClasses() const {
|
||||
if (MayHaveClass()) {
|
||||
return DoGetClasses();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for implementing GetClasses. This should only be called if the
|
||||
* ElementMayHaveClass flag is set.
|
||||
*
|
||||
* Public only because Servo needs to call it too, and it ensures the
|
||||
* precondition before calling this.
|
||||
*/
|
||||
const nsAttrValue* DoGetClasses() const
|
||||
const nsAttrValue* GetClasses() const
|
||||
{
|
||||
MOZ_ASSERT(MayHaveClass(), "Unexpected call");
|
||||
if (!MayHaveClass()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsSVGElement()) {
|
||||
if (const nsAttrValue* value = GetSVGAnimatedClass()) {
|
||||
return value;
|
||||
@ -1967,7 +1956,7 @@ protected:
|
||||
|
||||
private:
|
||||
/**
|
||||
* Slow path for DoGetClasses, this should only be called for SVG elements.
|
||||
* Slow path for GetClasses, this should only be called for SVG elements.
|
||||
*/
|
||||
const nsAttrValue* GetSVGAnimatedClass() const;
|
||||
|
||||
|
@ -41,7 +41,7 @@ class DeclarationBlock;
|
||||
|
||||
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
|
||||
|
||||
#define NS_ATTRVALUE_BASETYPE_MASK (uintptr_t(3))
|
||||
const uintptr_t NS_ATTRVALUE_BASETYPE_MASK = 3;
|
||||
#define NS_ATTRVALUE_POINTERVALUE_MASK (~NS_ATTRVALUE_BASETYPE_MASK)
|
||||
|
||||
#define NS_ATTRVALUE_INTEGERTYPE_BITS 4
|
||||
|
@ -916,14 +916,6 @@ Gecko_IsBrowserFrame(RawGeckoElementBorrowed aElement)
|
||||
return browserFrame && browserFrame->GetReallyIsBrowser();
|
||||
}
|
||||
|
||||
template <typename Implementor>
|
||||
static nsAtom*
|
||||
AtomAttrValue(Implementor* aElement, nsAtom* aName)
|
||||
{
|
||||
const nsAttrValue* attr = aElement->GetParsedAttr(aName);
|
||||
return attr ? attr->GetAtomValue() : nullptr;
|
||||
}
|
||||
|
||||
template <typename Implementor>
|
||||
static nsAtom*
|
||||
LangValue(Implementor* aElement)
|
||||
@ -1074,94 +1066,7 @@ AttrHasSuffix(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an element contains a class in its class list or not.
|
||||
*/
|
||||
template <typename Implementor>
|
||||
static bool
|
||||
HasClass(Implementor* aElement, nsAtom* aClass, bool aIgnoreCase)
|
||||
{
|
||||
const nsAttrValue* attr = aElement->DoGetClasses();
|
||||
if (!attr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return attr->Contains(aClass, aIgnoreCase ? eIgnoreCase : eCaseMatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class or class list (if any) of the implementor. The calling
|
||||
* convention here is rather hairy, and is optimized for getting Servo the
|
||||
* information it needs for hot calls.
|
||||
*
|
||||
* The return value indicates the number of classes. If zero, neither outparam
|
||||
* is valid. If one, the class_ outparam is filled with the atom of the class.
|
||||
* If two or more, the classList outparam is set to point to an array of atoms
|
||||
* representing the class list.
|
||||
*
|
||||
* The array is borrowed and the atoms are not addrefed. These values can be
|
||||
* invalidated by any DOM mutation. Use them in a tight scope.
|
||||
*/
|
||||
template <typename Implementor>
|
||||
static uint32_t
|
||||
ClassOrClassList(Implementor* aElement, nsAtom** aClass, nsAtom*** aClassList)
|
||||
{
|
||||
const nsAttrValue* attr = aElement->DoGetClasses();
|
||||
if (!attr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For class values with only whitespace, Gecko just stores a string. For the
|
||||
// purposes of the style system, there is no class in this case.
|
||||
nsAttrValue::ValueType type = attr->Type();
|
||||
if (MOZ_UNLIKELY(type == nsAttrValue::eString)) {
|
||||
MOZ_ASSERT(nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
|
||||
attr->GetStringValue()).IsEmpty());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Single tokens are generally stored as an atom. Check that case.
|
||||
if (type == nsAttrValue::eAtom) {
|
||||
*aClass = attr->GetAtomValue();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// At this point we should have an atom array. It is likely, but not
|
||||
// guaranteed, that we have two or more elements in the array.
|
||||
MOZ_ASSERT(type == nsAttrValue::eAtomArray);
|
||||
nsTArray<RefPtr<nsAtom>>* atomArray = attr->GetAtomArrayValue();
|
||||
uint32_t length = atomArray->Length();
|
||||
|
||||
// Special case: zero elements.
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Special case: one element.
|
||||
if (length == 1) {
|
||||
*aClass = atomArray->ElementAt(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// General case: Two or more elements.
|
||||
//
|
||||
// Note: We could also expose this array as an array of nsCOMPtrs, since
|
||||
// bindgen knows what those look like, and eliminate the reinterpret_cast.
|
||||
// But it's not obvious that that would be preferable.
|
||||
static_assert(sizeof(RefPtr<nsAtom>) == sizeof(nsAtom*), "Bad simplification");
|
||||
static_assert(alignof(RefPtr<nsAtom>) == alignof(nsAtom*), "Bad simplification");
|
||||
|
||||
RefPtr<nsAtom>* elements = atomArray->Elements();
|
||||
nsAtom** rawElements = reinterpret_cast<nsAtom**>(elements);
|
||||
*aClassList = rawElements;
|
||||
return atomArray->Length();
|
||||
}
|
||||
|
||||
#define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
|
||||
nsAtom* prefix_##AtomAttrValue(implementor_ aElement, nsAtom* aName) \
|
||||
{ \
|
||||
return AtomAttrValue(aElement, aName); \
|
||||
} \
|
||||
nsAtom* prefix_##LangValue(implementor_ aElement) \
|
||||
{ \
|
||||
return LangValue(aElement); \
|
||||
@ -1199,16 +1104,7 @@ ClassOrClassList(Implementor* aElement, nsAtom** aClass, nsAtom*** aClassList)
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrHasSuffix(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsAtom** aClass, \
|
||||
nsAtom*** aClassList) \
|
||||
{ \
|
||||
return ClassOrClassList(aElement, aClass, aClassList); \
|
||||
} \
|
||||
bool prefix_##HasClass(implementor_ aElement, nsAtom* aClass, bool aIgnoreCase)\
|
||||
{ \
|
||||
return HasClass(aElement, aClass, aIgnoreCase); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
|
||||
@ -2969,3 +2865,22 @@ Gecko_IsMainThread()
|
||||
{
|
||||
return NS_IsMainThread();
|
||||
}
|
||||
|
||||
const nsAttrValue*
|
||||
Gecko_GetSVGAnimatedClass(RawGeckoElementBorrowed aElement)
|
||||
{
|
||||
MOZ_ASSERT(aElement->IsSVGElement());
|
||||
return static_cast<const nsSVGElement*>(aElement)->GetAnimatedClassName();
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AssertClassAttrValueIsSane(const nsAttrValue* aValue)
|
||||
{
|
||||
MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom ||
|
||||
aValue->Type() == nsAttrValue::eString ||
|
||||
aValue->Type() == nsAttrValue::eAtomArray);
|
||||
MOZ_ASSERT_IF(aValue->Type() == nsAttrValue::eString,
|
||||
nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
|
||||
aValue->GetStringValue()).IsEmpty());
|
||||
return true;
|
||||
}
|
||||
|
@ -200,7 +200,6 @@ bool Gecko_IsBrowserFrame(RawGeckoElementBorrowed element);
|
||||
|
||||
// Attributes.
|
||||
#define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
|
||||
nsAtom* prefix_##AtomAttrValue(implementor_ element, nsAtom* attribute); \
|
||||
nsAtom* prefix_##LangValue(implementor_ element); \
|
||||
bool prefix_##HasAttr(implementor_ element, nsAtom* ns, nsAtom* name); \
|
||||
bool prefix_##AttrEquals(implementor_ element, nsAtom* ns, nsAtom* name, \
|
||||
@ -215,11 +214,11 @@ bool Gecko_IsBrowserFrame(RawGeckoElementBorrowed element);
|
||||
bool prefix_##AttrHasPrefix(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
bool prefix_##AttrHasSuffix(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
uint32_t prefix_##ClassOrClassList(implementor_ element, nsAtom** class_, \
|
||||
nsAtom*** classList); \
|
||||
bool prefix_##HasClass(implementor_ element, nsAtom* class_, \
|
||||
bool ignore_case);
|
||||
nsAtom* name, nsAtom* str, bool ignore_case);
|
||||
|
||||
bool Gecko_AssertClassAttrValueIsSane(const nsAttrValue*);
|
||||
const nsAttrValue* Gecko_GetSVGAnimatedClass(RawGeckoElementBorrowed);
|
||||
|
||||
|
||||
SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
|
||||
SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,
|
||||
@ -653,7 +652,6 @@ nsCSSKeyword Gecko_LookupCSSKeyword(const uint8_t* string, uint32_t len);
|
||||
const char* Gecko_CSSKeywordString(nsCSSKeyword keyword, uint32_t* len);
|
||||
|
||||
bool Gecko_IsDocumentBody(RawGeckoElementBorrowed element);
|
||||
|
||||
// We use an int32_t here instead of a LookAndFeel::ColorID
|
||||
// because forward-declaring a nested enum/struct is impossible
|
||||
nscolor Gecko_GetLookAndFeelSystemColor(int32_t color_id,
|
||||
|
@ -197,6 +197,7 @@ rusty-enums = [
|
||||
whitelist-vars = [
|
||||
"NS_AUTHOR_SPECIFIED_.*",
|
||||
"NS_THEME_.*",
|
||||
"NS_ATTRVALUE_.*",
|
||||
"NODE_.*",
|
||||
"ELEMENT_.*",
|
||||
"NS_FONT_.*",
|
||||
@ -476,6 +477,7 @@ structs-types = [
|
||||
"mozilla::StyleDisplayMode",
|
||||
"ServoRawOffsetArc",
|
||||
"DeclarationBlockMutationClosure",
|
||||
"nsAttrValue",
|
||||
"nsIContent",
|
||||
"nsINode",
|
||||
"nsIDocument",
|
||||
|
@ -134,12 +134,6 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const nsAttrValue* DoGetClasses() const
|
||||
{
|
||||
MOZ_ASSERT(HasAttrs());
|
||||
return &mClass;
|
||||
}
|
||||
|
||||
bool IsInChromeDocument() const { return mIsInChromeDocument; }
|
||||
bool SupportsLangAttr() const { return mSupportsLangAttr; }
|
||||
|
||||
|
@ -51,10 +51,6 @@ impl GeckoElementSnapshot {
|
||||
(self.mContains as u8 & flags as u8) != 0
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const Self {
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns true if the snapshot has stored state for pseudo-classes
|
||||
/// that depend on things other than `ElementState`.
|
||||
#[inline]
|
||||
@ -184,14 +180,7 @@ impl ElementSnapshot for GeckoElementSnapshot {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ptr = unsafe { bindings::Gecko_SnapshotAtomAttrValue(self, atom!("id").as_ptr()) };
|
||||
|
||||
// FIXME(emilio): This should assert, since this flag is exact.
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { WeakAtom::new(ptr) })
|
||||
}
|
||||
snapshot_helpers::get_id(&*self.mAttrs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -200,12 +189,7 @@ impl ElementSnapshot for GeckoElementSnapshot {
|
||||
return false;
|
||||
}
|
||||
|
||||
snapshot_helpers::has_class(
|
||||
self.as_ptr(),
|
||||
name,
|
||||
case_sensitivity,
|
||||
bindings::Gecko_SnapshotHasClass,
|
||||
)
|
||||
snapshot_helpers::has_class(name, case_sensitivity, &self.mClass)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -217,11 +201,7 @@ impl ElementSnapshot for GeckoElementSnapshot {
|
||||
return;
|
||||
}
|
||||
|
||||
snapshot_helpers::each_class(
|
||||
self.as_ptr(),
|
||||
callback,
|
||||
bindings::Gecko_SnapshotClassOrClassList,
|
||||
)
|
||||
snapshot_helpers::each_class(&self.mClass, callback)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -4,58 +4,114 @@
|
||||
|
||||
//! Element an snapshot common logic.
|
||||
|
||||
use gecko_bindings::structs::nsAtom;
|
||||
use CaseSensitivityExt;
|
||||
use gecko_bindings::bindings;
|
||||
use gecko_bindings::structs::{self, nsAtom};
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use std::{ptr, slice};
|
||||
use string_cache::Atom;
|
||||
use string_cache::{Atom, WeakAtom};
|
||||
|
||||
/// A function that, given an element of type `T`, allows you to get a single
|
||||
/// class or a class list.
|
||||
pub type ClassOrClassList<T> =
|
||||
unsafe extern "C" fn(T, *mut *mut nsAtom, *mut *mut *mut nsAtom) -> u32;
|
||||
enum Class<'a> {
|
||||
None,
|
||||
One(*const nsAtom),
|
||||
More(&'a [structs::RefPtr<nsAtom>]),
|
||||
}
|
||||
|
||||
/// A function to return whether an element of type `T` has a given class.
|
||||
///
|
||||
/// The `bool` argument represents whether it should compare case-insensitively
|
||||
/// or not.
|
||||
pub type HasClass<T> = unsafe extern "C" fn(T, *mut nsAtom, bool) -> bool;
|
||||
|
||||
/// Given an item `T`, a class name, and a getter function, return whether that
|
||||
/// element has the class that `name` represents.
|
||||
#[inline(always)]
|
||||
pub fn has_class<T>(
|
||||
item: T,
|
||||
fn base_type(attr: &structs::nsAttrValue) -> structs::nsAttrValue_ValueBaseType {
|
||||
(attr.mBits & structs::NS_ATTRVALUE_BASETYPE_MASK) as structs::nsAttrValue_ValueBaseType
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn ptr<T>(attr: &structs::nsAttrValue) -> *const T {
|
||||
(attr.mBits & !structs::NS_ATTRVALUE_BASETYPE_MASK) as *const T
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn get_class_from_attr(attr: &structs::nsAttrValue) -> Class {
|
||||
debug_assert!(bindings::Gecko_AssertClassAttrValueIsSane(attr));
|
||||
let base_type = base_type(attr);
|
||||
if base_type == structs::nsAttrValue_ValueBaseType_eStringBase {
|
||||
return Class::None;
|
||||
}
|
||||
if base_type == structs::nsAttrValue_ValueBaseType_eAtomBase {
|
||||
return Class::One(ptr::<nsAtom>(attr));
|
||||
}
|
||||
debug_assert_eq!(base_type, structs::nsAttrValue_ValueBaseType_eOtherBase);
|
||||
|
||||
let container = ptr::<structs::MiscContainer>(attr);
|
||||
debug_assert_eq!((*container).mType, structs::nsAttrValue_ValueType_eAtomArray);
|
||||
let array =
|
||||
(*container).__bindgen_anon_1.mValue.as_ref().__bindgen_anon_1.mAtomArray.as_ref();
|
||||
Class::More(&***array)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn get_id_from_attr(attr: &structs::nsAttrValue) -> &WeakAtom {
|
||||
debug_assert_eq!(base_type(attr), structs::nsAttrValue_ValueBaseType_eAtomBase);
|
||||
WeakAtom::new(ptr::<nsAtom>(attr))
|
||||
}
|
||||
|
||||
/// Find an attribute value with a given name and no namespace.
|
||||
#[inline(always)]
|
||||
pub fn find_attr<'a>(
|
||||
attrs: &'a [structs::AttrArray_InternalAttr],
|
||||
name: &Atom,
|
||||
) -> Option<&'a structs::nsAttrValue> {
|
||||
attrs.iter()
|
||||
.find(|attr| attr.mName.mBits == name.as_ptr() as usize)
|
||||
.map(|attr| &attr.mValue)
|
||||
}
|
||||
|
||||
/// Finds the id attribute from a list of attributes.
|
||||
#[inline(always)]
|
||||
pub fn get_id(attrs: &[structs::AttrArray_InternalAttr]) -> Option<&WeakAtom> {
|
||||
Some(unsafe { get_id_from_attr(find_attr(attrs, &atom!("id"))?) })
|
||||
}
|
||||
|
||||
/// Given a class name, a case sensitivity, and an array of attributes, returns
|
||||
/// whether the class has the attribute that name represents.
|
||||
#[inline(always)]
|
||||
pub fn has_class(
|
||||
name: &Atom,
|
||||
case_sensitivity: CaseSensitivity,
|
||||
getter: HasClass<T>,
|
||||
attr: &structs::nsAttrValue,
|
||||
) -> bool {
|
||||
let ignore_case = match case_sensitivity {
|
||||
CaseSensitivity::CaseSensitive => false,
|
||||
CaseSensitivity::AsciiCaseInsensitive => true,
|
||||
};
|
||||
|
||||
unsafe { getter(item, name.as_ptr(), ignore_case) }
|
||||
match unsafe { get_class_from_attr(attr) } {
|
||||
Class::None => false,
|
||||
Class::One(atom) => unsafe {
|
||||
case_sensitivity.eq_atom(name, WeakAtom::new(atom))
|
||||
},
|
||||
Class::More(atoms) => {
|
||||
match case_sensitivity {
|
||||
CaseSensitivity::CaseSensitive => {
|
||||
atoms.iter().any(|atom| atom.mRawPtr == name.as_ptr())
|
||||
}
|
||||
CaseSensitivity::AsciiCaseInsensitive => unsafe {
|
||||
atoms.iter().any(|atom| WeakAtom::new(atom.mRawPtr).eq_ignore_ascii_case(name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an item, a callback, and a getter, execute `callback` for each class
|
||||
/// this `item` has.
|
||||
pub fn each_class<F, T>(item: T, mut callback: F, getter: ClassOrClassList<T>)
|
||||
#[inline(always)]
|
||||
pub fn each_class<F>(attr: &structs::nsAttrValue, mut callback: F)
|
||||
where
|
||||
F: FnMut(&Atom),
|
||||
{
|
||||
unsafe {
|
||||
let mut class: *mut nsAtom = ptr::null_mut();
|
||||
let mut list: *mut *mut nsAtom = ptr::null_mut();
|
||||
let length = getter(item, &mut class, &mut list);
|
||||
match length {
|
||||
0 => {},
|
||||
1 => Atom::with(class, callback),
|
||||
n => {
|
||||
let classes = slice::from_raw_parts(list, n as usize);
|
||||
for c in classes {
|
||||
Atom::with(*c, &mut callback)
|
||||
match get_class_from_attr(attr) {
|
||||
Class::None => {},
|
||||
Class::One(atom) => Atom::with(atom, callback),
|
||||
Class::More(atoms) => {
|
||||
for atom in atoms {
|
||||
Atom::with(atom.mRawPtr, &mut callback)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ use gecko_bindings::bindings;
|
||||
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme};
|
||||
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetPreviousSibling, Gecko_GetNextStyleChild};
|
||||
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
|
||||
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
||||
use gecko_bindings::bindings::Gecko_ElementHasAnimations;
|
||||
use gecko_bindings::bindings::Gecko_ElementHasCSSAnimations;
|
||||
use gecko_bindings::bindings::Gecko_ElementHasCSSTransitions;
|
||||
@ -581,6 +580,34 @@ impl<'le> fmt::Debug for GeckoElement<'le> {
|
||||
}
|
||||
|
||||
impl<'le> GeckoElement<'le> {
|
||||
#[inline(always)]
|
||||
fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
|
||||
unsafe {
|
||||
let attrs = match self.0._base.mAttrs.mImpl.mPtr.as_ref() {
|
||||
Some(attrs) => attrs,
|
||||
None => return &[],
|
||||
};
|
||||
|
||||
attrs.mBuffer.as_slice(attrs.mAttrCount as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_class_attr(&self) -> Option<&structs::nsAttrValue> {
|
||||
if !self.may_have_class() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if self.is_svg_element() {
|
||||
let svg_class = unsafe { bindings::Gecko_GetSVGAnimatedClass(self.0).as_ref() };
|
||||
if let Some(c) = svg_class {
|
||||
return Some(c)
|
||||
}
|
||||
}
|
||||
|
||||
snapshot_helpers::find_attr(self.attrs(), &atom!("class"))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn closest_anon_subtree_root_parent(&self) -> Option<Self> {
|
||||
debug_assert!(self.is_in_native_anonymous_subtree());
|
||||
@ -1281,26 +1308,19 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ptr = unsafe { bindings::Gecko_AtomAttrValue(self.0, atom!("id").as_ptr()) };
|
||||
|
||||
// FIXME(emilio): Pretty sure the has_id flag is exact and we could
|
||||
// assert here.
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { WeakAtom::new(ptr) })
|
||||
}
|
||||
snapshot_helpers::get_id(self.attrs())
|
||||
}
|
||||
|
||||
fn each_class<F>(&self, callback: F)
|
||||
where
|
||||
F: FnMut(&Atom),
|
||||
{
|
||||
if !self.may_have_class() {
|
||||
return;
|
||||
}
|
||||
let attr = match self.get_class_attr() {
|
||||
Some(c) => c,
|
||||
None => return,
|
||||
};
|
||||
|
||||
snapshot_helpers::each_class(self.0, callback, Gecko_ClassOrClassList)
|
||||
snapshot_helpers::each_class(attr, callback)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -2265,24 +2285,22 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let ptr = bindings::Gecko_AtomAttrValue(self.0, atom!("id").as_ptr());
|
||||
let element_id = match snapshot_helpers::get_id(self.attrs()) {
|
||||
Some(id) => id,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
if ptr.is_null() {
|
||||
false
|
||||
} else {
|
||||
case_sensitivity.eq_atom(WeakAtom::new(ptr), id)
|
||||
}
|
||||
}
|
||||
case_sensitivity.eq_atom(element_id, id)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {
|
||||
if !self.may_have_class() {
|
||||
return false;
|
||||
}
|
||||
let attr = match self.get_class_attr() {
|
||||
Some(c) => c,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
snapshot_helpers::has_class(self.0, name, case_sensitivity, bindings::Gecko_HasClass)
|
||||
snapshot_helpers::has_class(name, case_sensitivity, attr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -263,7 +263,7 @@ impl fmt::Display for WeakAtom {
|
||||
|
||||
impl Atom {
|
||||
/// Execute a callback with the atom represented by `ptr`.
|
||||
pub unsafe fn with<F, R>(ptr: *mut nsAtom, callback: F) -> R
|
||||
pub unsafe fn with<F, R>(ptr: *const nsAtom, callback: F) -> R
|
||||
where
|
||||
F: FnOnce(&Atom) -> R,
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user