aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/gecko/wrapper.rs136
-rw-r--r--components/style/gecko_bindings/sugar/mod.rs1
-rw-r--r--components/style/gecko_bindings/sugar/ns_com_ptr.rs18
-rw-r--r--ports/geckolib/glue.rs1
4 files changed, 101 insertions, 55 deletions
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index e2db71fecc7..864e8fc8d22 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -17,21 +17,17 @@ use gecko_bindings::bindings;
use gecko_bindings::bindings::{Gecko_CalcStyleDifference, Gecko_StoreStyleDifference};
use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator};
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentElement};
-use gecko_bindings::bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement};
-use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement};
-use gecko_bindings::bindings::{Gecko_GetNextSibling, Gecko_GetNextSiblingElement, Gecko_GetNextStyleChild};
-use gecko_bindings::bindings::{Gecko_GetNodeFlags, Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
-use gecko_bindings::bindings::{Gecko_GetParentElement, Gecko_GetParentNode};
-use gecko_bindings::bindings::{Gecko_GetPrevSibling, Gecko_GetPrevSiblingElement};
+use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetNextStyleChild};
use gecko_bindings::bindings::{Gecko_GetServoDeclarationBlock, Gecko_IsHTMLElementInHTMLDocument};
-use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNode};
-use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
-use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement};
+use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement};
+use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink, Gecko_Namespace};
+use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
use gecko_bindings::bindings::Gecko_ClassOrClassList;
use gecko_bindings::bindings::Gecko_GetStyleContext;
+use gecko_bindings::structs;
use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
use gecko_bindings::structs::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
-use gecko_bindings::structs::{nsChangeHint, nsIAtom, nsStyleContext};
+use gecko_bindings::structs::{nsChangeHint, nsIAtom, nsIContent, nsStyleContext};
use gecko_bindings::structs::OpaqueStyleData;
use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasFFI};
use libc::uintptr_t;
@@ -96,10 +92,36 @@ fn from_opaque_style_data(d: *mut OpaqueStyleData) -> *mut NonOpaqueStyleData {
pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
impl<'ln> GeckoNode<'ln> {
+ fn from_content(content: &'ln nsIContent) -> Self {
+ use std::mem;
+ GeckoNode(&content._base)
+ }
+
+ fn node_info(&self) -> &structs::NodeInfo {
+ debug_assert!(!self.0.mNodeInfo.mRawPtr.is_null());
+ unsafe { &*self.0.mNodeInfo.mRawPtr }
+ }
+
+ fn flags(&self) -> u32 {
+ (self.0)._base._base_1.mFlags
+ }
+
+ // FIXME: We can implement this without OOL calls, but we can't easily given
+ // GeckoNode is a raw reference.
+ //
+ // We can use a Cell<T>, but that's a bit of a pain.
+ fn set_flags(&self, flags: u32) {
+ unsafe { Gecko_SetNodeFlags(self.0, flags) }
+ }
+
+ fn unset_flags(&self, flags: u32) {
+ unsafe { Gecko_UnsetNodeFlags(self.0, flags) }
+ }
+
fn get_node_data(&self) -> Option<&NonOpaqueStyleData> {
- unsafe {
- from_opaque_style_data(self.0.mServoData.get()).as_ref()
- }
+ unsafe {
+ from_opaque_style_data(self.0.mServoData.get()).as_ref()
+ }
}
pub fn initialize_data(self) {
@@ -154,15 +176,14 @@ impl BitOr for GeckoRestyleDamage {
impl<'ln> NodeInfo for GeckoNode<'ln> {
fn is_element(&self) -> bool {
- unsafe {
- Gecko_NodeIsElement(self.0)
- }
+ use gecko_bindings::structs::nsINode_BooleanFlag;
+ self.0.mBoolFlags & nsINode_BooleanFlag::NodeIsElement as u32 != 0
}
fn is_text_node(&self) -> bool {
- unsafe {
- Gecko_IsTextNode(self.0)
- }
+ // This is a DOM constant that isn't going to change.
+ const TEXT_NODE: u16 = 3;
+ self.node_info().mInner.mNodeType == TEXT_NODE
}
}
@@ -241,15 +262,14 @@ impl<'ln> TNode for GeckoNode<'ln> {
return true;
}
- let flags = unsafe { Gecko_GetNodeFlags(self.0) };
- flags & (NODE_IS_DIRTY_FOR_SERVO as u32) != 0
+ self.flags() & (NODE_IS_DIRTY_FOR_SERVO as u32) != 0
}
unsafe fn set_dirty(&self, value: bool) {
if value {
- Gecko_SetNodeFlags(self.0, NODE_IS_DIRTY_FOR_SERVO as u32)
+ self.set_flags(NODE_IS_DIRTY_FOR_SERVO as u32)
} else {
- Gecko_UnsetNodeFlags(self.0, NODE_IS_DIRTY_FOR_SERVO as u32)
+ self.unset_flags(NODE_IS_DIRTY_FOR_SERVO as u32)
}
}
@@ -259,15 +279,14 @@ impl<'ln> TNode for GeckoNode<'ln> {
if self.get_node_data().is_none() {
return true;
}
- let flags = unsafe { Gecko_GetNodeFlags(self.0) };
- flags & (NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
+ self.flags() & (NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
}
unsafe fn set_dirty_descendants(&self, value: bool) {
if value {
- Gecko_SetNodeFlags(self.0, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
+ self.set_flags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
} else {
- Gecko_UnsetNodeFlags(self.0, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
+ self.unset_flags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
}
@@ -308,33 +327,23 @@ impl<'ln> TNode for GeckoNode<'ln> {
}
fn parent_node(&self) -> Option<GeckoNode<'ln>> {
- unsafe {
- Gecko_GetParentNode(self.0).borrow_opt().map(|n| GeckoNode(n))
- }
+ unsafe { self.0.mParent.as_ref().map(GeckoNode) }
}
fn first_child(&self) -> Option<GeckoNode<'ln>> {
- unsafe {
- Gecko_GetFirstChild(self.0).borrow_opt().map(|n| GeckoNode(n))
- }
+ unsafe { self.0.mFirstChild.as_ref().map(GeckoNode::from_content) }
}
fn last_child(&self) -> Option<GeckoNode<'ln>> {
- unsafe {
- Gecko_GetLastChild(self.0).borrow_opt().map(|n| GeckoNode(n))
- }
+ unsafe { Gecko_GetLastChild(self.0).borrow_opt().map(GeckoNode) }
}
fn prev_sibling(&self) -> Option<GeckoNode<'ln>> {
- unsafe {
- Gecko_GetPrevSibling(self.0).borrow_opt().map(|n| GeckoNode(n))
- }
+ unsafe { self.0.mPreviousSibling.as_ref().map(GeckoNode::from_content) }
}
fn next_sibling(&self) -> Option<GeckoNode<'ln>> {
- unsafe {
- Gecko_GetNextSibling(self.0).borrow_opt().map(|n| GeckoNode(n))
- }
+ unsafe { self.0.mNextSibling.as_ref().map(GeckoNode::from_content) }
}
fn existing_style_for_restyle_damage<'a>(&'a self,
@@ -518,33 +527,52 @@ impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
impl<'le> ::selectors::Element for GeckoElement<'le> {
fn parent_element(&self) -> Option<Self> {
- unsafe {
- Gecko_GetParentElement(self.0).borrow_opt().map(|el| GeckoElement(el))
- }
+ let parent = self.as_node().parent_node();
+ parent.and_then(|parent| parent.as_element())
}
fn first_child_element(&self) -> Option<Self> {
- unsafe {
- Gecko_GetFirstChildElement(self.0).borrow_opt().map(|el| GeckoElement(el))
+ let mut child = self.as_node().first_child();
+ while let Some(child_node) = child {
+ if let Some(el) = child_node.as_element() {
+ return Some(el)
+ }
+ child = child_node.next_sibling();
}
+ None
}
fn last_child_element(&self) -> Option<Self> {
- unsafe {
- Gecko_GetLastChildElement(self.0).borrow_opt().map(|el| GeckoElement(el))
+ let mut child = self.as_node().last_child();
+ while let Some(child_node) = child {
+ if let Some(el) = child_node.as_element() {
+ return Some(el)
+ }
+ child = child_node.prev_sibling();
}
+ None
}
fn prev_sibling_element(&self) -> Option<Self> {
- unsafe {
- Gecko_GetPrevSiblingElement(self.0).borrow_opt().map(|el| GeckoElement(el))
+ let mut sibling = self.as_node().prev_sibling();
+ while let Some(sibling_node) = sibling {
+ if let Some(el) = sibling_node.as_element() {
+ return Some(el)
+ }
+ sibling = sibling_node.prev_sibling();
}
+ None
}
fn next_sibling_element(&self) -> Option<Self> {
- unsafe {
- Gecko_GetNextSiblingElement(self.0).borrow_opt().map(|el| GeckoElement(el))
+ let mut sibling = self.as_node().next_sibling();
+ while let Some(sibling_node) = sibling {
+ if let Some(el) = sibling_node.as_element() {
+ return Some(el)
+ }
+ sibling = sibling_node.next_sibling();
}
+ None
}
fn is_root(&self) -> bool {
@@ -560,7 +588,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
fn get_local_name(&self) -> &WeakAtom {
unsafe {
- WeakAtom::new(Gecko_LocalName(self.0))
+ WeakAtom::new(self.as_node().node_info().mInner.mName.raw())
}
}
diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs
index a451d67a06d..f8127e875d3 100644
--- a/components/style/gecko_bindings/sugar/mod.rs
+++ b/components/style/gecko_bindings/sugar/mod.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+mod ns_com_ptr;
mod ns_css_shadow_array;
mod ns_style_auto_array;
pub mod ns_style_coord;
diff --git a/components/style/gecko_bindings/sugar/ns_com_ptr.rs b/components/style/gecko_bindings/sugar/ns_com_ptr.rs
new file mode 100644
index 00000000000..a7056320a5a
--- /dev/null
+++ b/components/style/gecko_bindings/sugar/ns_com_ptr.rs
@@ -0,0 +1,18 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use gecko_bindings::structs::nsCOMPtr;
+
+impl<T> nsCOMPtr<T> {
+ #[cfg(debug_assertions)]
+ #[inline]
+ pub fn raw(&self) -> *mut T {
+ self.mRawPtr
+ }
+
+ #[cfg(not(debug_assertions))]
+ #[inline]
+ pub fn raw(&self) -> *mut T {
+ self._base.mRawPtr as *mut _
+ }
+}
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index 752ce7b61e7..b6768b6a256 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -47,7 +47,6 @@ use style::stylesheets::{Origin, Stylesheet};
use style::timer::Timer;
use url::Url;
-
/*
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
* the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against