mirror of
https://github.com/servo/servo.git
synced 2025-07-22 14:53:49 +01:00
Auto merge of #11431 - bholley:atom_traversal, r=mbrubeck
Geckolib: Add performant implementations of get_id, has_class, and each_class <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11431) <!-- Reviewable:end -->
This commit is contained in:
commit
60d78b7272
4 changed files with 62 additions and 12 deletions
|
@ -146,6 +146,10 @@ extern "C" {
|
|||
pub fn Gecko_IsRootElement(element: *mut RawGeckoElement) -> bool;
|
||||
pub fn Gecko_LocalName(element: *mut RawGeckoElement) -> *mut nsIAtom;
|
||||
pub fn Gecko_Namespace(element: *mut RawGeckoElement) -> *mut nsIAtom;
|
||||
pub fn Gecko_GetElementId(element: *mut RawGeckoElement) -> *mut nsIAtom;
|
||||
pub fn Gecko_ClassOrClassList(element: *mut RawGeckoElement,
|
||||
class_: *mut *mut nsIAtom,
|
||||
classList: *mut *mut *mut nsIAtom) -> u32;
|
||||
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
|
||||
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
|
||||
data: *mut ServoNodeData);
|
||||
|
|
|
@ -75,10 +75,16 @@ eval ./rust-bindgen/target/debug/bindgen \
|
|||
-x c++ -std=gnu++0x \
|
||||
"-I$DIST_INCLUDE" \
|
||||
"-I$DIST_INCLUDE/nspr/" \
|
||||
"-I$SRCDIR/nsprpub/pr/include/" \
|
||||
"-I$1/nsprpub/pr/include/" \
|
||||
$PLATFORM_DEPENDENT_DEFINES \
|
||||
-DMOZILLA_INTERNAL_API \
|
||||
-DMOZ_STYLO_BINDINGS=1 \
|
||||
-DJS_DEBUG=1 \
|
||||
-DDEBUG=1 -DTRACING=1 -DOS_POSIX=1 \
|
||||
-DIMPL_LIBXUL \
|
||||
-o ../bindings.rs \
|
||||
-no-type-renaming \
|
||||
-include "$1/mozilla-config.h" \
|
||||
"$DIST_INCLUDE/mozilla/ServoBindings.h" \
|
||||
-match "ServoBindings.h" \
|
||||
-match "nsStyleStructList.h" \
|
||||
|
|
|
@ -134,6 +134,10 @@ impl Atom {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub unsafe fn with<F>(ptr: *mut nsIAtom, callback: &mut F) where F: FnMut(&Atom) {
|
||||
callback(transmute(&ptr))
|
||||
}
|
||||
|
||||
// Static atoms have a dummy AddRef/Release, so we don't bother calling
|
||||
// AddRef() here. This would cause memory corruption with non-static atoms
|
||||
// both because (a) we wouldn't hold the atom alive, and (b) we can't avoid
|
||||
|
@ -226,3 +230,12 @@ impl From<String> for Atom {
|
|||
Atom::from(&*string)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<*mut nsIAtom> for Atom {
|
||||
fn from(ptr: *mut nsIAtom) -> Atom {
|
||||
unsafe {
|
||||
Gecko_AddRefAtom(ptr);
|
||||
Atom(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#![allow(unsafe_code)]
|
||||
|
||||
use gecko_bindings::bindings::{Gecko_ChildrenCount};
|
||||
use gecko_bindings::bindings::{Gecko_ClassOrClassList};
|
||||
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetAttrAsUTF8, Gecko_GetDocumentElement};
|
||||
use gecko_bindings::bindings::{Gecko_GetElementId};
|
||||
use gecko_bindings::bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement};
|
||||
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement};
|
||||
use gecko_bindings::bindings::{Gecko_GetNextSibling, Gecko_GetNextSiblingElement};
|
||||
|
@ -18,6 +20,7 @@ use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
|
|||
use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
||||
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
|
||||
use gecko_bindings::bindings::{ServoNodeData};
|
||||
use gecko_bindings::bindings::{nsIAtom};
|
||||
use libc::uintptr_t;
|
||||
use properties::GeckoComputedValues;
|
||||
use selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PrivateStyleData};
|
||||
|
@ -28,6 +31,7 @@ use smallvec::VecLike;
|
|||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::BitOr;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::str::from_utf8_unchecked;
|
||||
use std::sync::Arc;
|
||||
|
@ -447,23 +451,46 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
}
|
||||
|
||||
fn get_id(&self) -> Option<Atom> {
|
||||
// FIXME(bholley): Servo caches the id atom directly on the element to
|
||||
// make this blazing fast. Assuming that was a measured optimization, doing
|
||||
// the dumb thing like we do below will almost certainly be a bottleneck.
|
||||
self.get_attr(&ns!(), &atom!("id")).map(|s| Atom::from(s))
|
||||
unsafe {
|
||||
let ptr = Gecko_GetElementId(self.element);
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Atom::from(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_class(&self, name: &Atom) -> bool {
|
||||
// FIXME(bholley): Do this smarter.
|
||||
self.get_attr(&ns!(), &atom!("class"))
|
||||
.map_or(false, |classes| classes.split(" ").any(|n| &Atom::from(n) == name))
|
||||
unsafe {
|
||||
let mut class: *mut nsIAtom = ptr::null_mut();
|
||||
let mut list: *mut *mut nsIAtom = ptr::null_mut();
|
||||
let length = Gecko_ClassOrClassList(self.element, &mut class, &mut list);
|
||||
match length {
|
||||
0 => false,
|
||||
1 => name.as_ptr() == class,
|
||||
n => {
|
||||
let classes = slice::from_raw_parts(list, n as usize);
|
||||
classes.iter().any(|ptr| name.as_ptr() == *ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn each_class<F>(&self, mut callback: F) where F: FnMut(&Atom) {
|
||||
// FIXME(bholley): Synergize with the DOM to stop splitting strings here.
|
||||
if let Some(classes) = self.get_attr(&ns!(), &atom!("class")) {
|
||||
for c in classes.split(" ") {
|
||||
callback(&Atom::from(c));
|
||||
unsafe {
|
||||
let mut class: *mut nsIAtom = ptr::null_mut();
|
||||
let mut list: *mut *mut nsIAtom = ptr::null_mut();
|
||||
let length = Gecko_ClassOrClassList(self.element, &mut class, &mut list);
|
||||
match length {
|
||||
0 => {}
|
||||
1 => Atom::with(class, &mut callback),
|
||||
n => {
|
||||
let classes = slice::from_raw_parts(list, n as usize);
|
||||
for c in classes {
|
||||
Atom::with(*c, &mut callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue