style: Add a Document::elements_with_id API.
draft
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -2866,8 +2866,17 @@ Gecko_ContentList_AppendAll(
MOZ_ASSERT(aList);
aList->SetCapacity(aLength);
for (size_t i = 0; i < aLength; ++i) {
aList->AppendElement(const_cast<Element*>(aElements[i]));
}
}
+
+const nsTArray<Element*>*
+Gecko_GetElementsWithId(const nsIDocument* aDocument, nsAtom* aId)
+{
+ MOZ_ASSERT(aDocument);
+ MOZ_ASSERT(aId);
+
+ return aDocument->GetAllElementsForId(nsDependentAtomString(aId));
+}
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -712,11 +712,15 @@ void Gecko_ReportUnexpectedCSSError(mozi
uint32_t lineNumber,
uint32_t colNumber);
// DOM APIs.
void Gecko_ContentList_AppendAll(nsSimpleContentList* aContentList,
const RawGeckoElement** aElements,
size_t aLength);
+const nsTArray<mozilla::dom::Element*>* Gecko_GetElementsWithId(
+ const nsIDocument* aDocument,
+ nsAtom* aId);
+
} // extern "C"
#endif // mozilla_ServoBindings_h
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -470,16 +470,17 @@ structs-types = [
"nsIDocument",
"nsIDocument_DocumentTheme",
"nsSimpleContentList",
"RawGeckoAnimationPropertySegment",
"RawGeckoComputedTiming",
"RawGeckoCSSPropertyIDList",
"RawGeckoDocument",
"RawGeckoElement",
+ "Element",
"RawGeckoKeyframeList",
"RawGeckoPropertyValuePairList",
"RawGeckoComputedKeyframeValuesList",
"RawGeckoFontFaceRuleList",
"RawGeckoNode",
"RawServoAnimationValue",
"RawGeckoServoAnimationValueList",
"RawServoMediaList",
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -141,16 +141,27 @@ pub trait TDocument : Sized + Copy + Clo
/// Get this document as a `TNode`.
fn as_node(&self) -> Self::ConcreteNode;
/// Returns whether this document is an HTML document.
fn is_html_document(&self) -> bool;
/// Returns the quirks mode of this document.
fn quirks_mode(&self) -> QuirksMode;
+
+ /// Get a list of elements with a given ID in this document.
+ ///
+ /// Can return an error to signal that this list is not available, or also
+ /// return an empty slice.
+ fn elements_with_id(
+ &self,
+ _id: &Atom,
+ ) -> Result<&[<Self::ConcreteNode as TNode>::ConcreteElement], ()> {
+ Err(())
+ }
}
/// The `TNode` trait. This is the main generic trait over which the style
/// system can be implemented.
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
/// The concrete `TElement` type.
type ConcreteElement: TElement<ConcreteNode = Self>;
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -105,16 +105,31 @@ impl<'ld> TDocument for GeckoDocument<'l
fn is_html_document(&self) -> bool {
self.0.mType == structs::root::nsIDocument_Type::eHTML
}
fn quirks_mode(&self) -> QuirksMode {
self.0.mCompatMode.into()
}
+
+ fn elements_with_id(&self, id: &Atom) -> Result<&[GeckoElement<'ld>], ()> {
+ unsafe {
+ let array = bindings::Gecko_GetElementsWithId(self.0, id.as_ptr());
+ if array.is_null() {
+ return Ok(&[]);
+ }
+
+ let elements: &[*mut RawGeckoElement] = &**array;
+
+ // NOTE(emilio): We rely on the in-memory representation of
+ // GeckoElement<'ld> and *mut RawGeckoElement being the same.
+ Ok(mem::transmute(elements))
+ }
+ }
}
/// A simple wrapper over a non-null Gecko node (`nsINode`) pointer.
///
/// Important: We don't currently refcount the DOM, because the wrapper lifetime
/// magic guarantees that our LayoutFoo references won't outlive the root, and
/// we don't mutate any of the references on the Gecko side during restyle.
///