New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stylo: Traverse anonymous children when styling #12911
Changes from all commits
470368e
b56297f
1799b0a
122df8c
File filter...
Jump to…
| @@ -5,16 +5,16 @@ | ||
| #![allow(unsafe_code)] | ||
|
|
||
| use gecko_bindings::bindings; | ||
| use gecko_bindings::bindings::Gecko_ChildrenCount; | ||
| use gecko_bindings::bindings::Gecko_ClassOrClassList; | ||
| use gecko_bindings::bindings::Gecko_GetNodeData; | ||
| use gecko_bindings::bindings::Gecko_GetStyleContext; | ||
| use gecko_bindings::bindings::ServoNodeData; | ||
| 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}; | ||
| 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}; | ||
| @@ -134,6 +134,7 @@ impl<'ln> TNode for GeckoNode<'ln> { | ||
| type ConcreteDocument = GeckoDocument<'ln>; | ||
| type ConcreteElement = GeckoElement<'ln>; | ||
| type ConcreteRestyleDamage = GeckoRestyleDamage; | ||
| type ConcreteChildrenIterator = GeckoChildrenIterator<'ln>; | ||
|
|
||
| fn to_unsafe(&self) -> UnsafeNode { | ||
| (self.node as usize, 0) | ||
| @@ -163,6 +164,15 @@ impl<'ln> TNode for GeckoNode<'ln> { | ||
| unimplemented!() | ||
| } | ||
|
|
||
| fn children(self) -> GeckoChildrenIterator<'ln> { | ||
| let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.node) }; | ||
| if !maybe_iter.is_null() { | ||
| GeckoChildrenIterator::GeckoIterator(maybe_iter) | ||
| } else { | ||
| GeckoChildrenIterator::Current(self.first_child()) | ||
| } | ||
| } | ||
|
|
||
| fn opaque(&self) -> OpaqueNode { | ||
| let ptr: uintptr_t = self.node as uintptr_t; | ||
| OpaqueNode(ptr) | ||
| @@ -180,12 +190,6 @@ impl<'ln> TNode for GeckoNode<'ln> { | ||
| unimplemented!() | ||
| } | ||
|
|
||
| fn children_count(&self) -> u32 { | ||
| unsafe { | ||
| Gecko_ChildrenCount(self.node) | ||
| } | ||
| } | ||
|
|
||
| fn as_element(&self) -> Option<GeckoElement<'ln>> { | ||
| if self.is_element() { | ||
| unsafe { Some(GeckoElement::from_raw(self.node as *mut RawGeckoElement)) } | ||
| @@ -341,6 +345,40 @@ impl<'ln> TNode for GeckoNode<'ln> { | ||
| unsafe fn set_dirty_on_viewport_size_changed(&self) {} | ||
| } | ||
|
|
||
| // We generally iterate children by traversing the siblings of the first child | ||
| // like Servo does. However, for nodes with anonymous children, we use a custom | ||
| // (heavier-weight) Gecko-implemented iterator. | ||
| pub enum GeckoChildrenIterator<'a> { | ||
| Current(Option<GeckoNode<'a>>), | ||
| GeckoIterator(*mut bindings::StyleChildrenIterator), | ||
| } | ||
|
|
||
| impl<'a> Drop for GeckoChildrenIterator<'a> { | ||
| fn drop(&mut self) { | ||
| if let GeckoChildrenIterator::GeckoIterator(it) = *self { | ||
| unsafe { | ||
| Gecko_DropStyleChildrenIterator(it); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<'a> Iterator for GeckoChildrenIterator<'a> { | ||
| type Item = GeckoNode<'a>; | ||
| fn next(&mut self) -> Option<GeckoNode<'a>> { | ||
| match *self { | ||
| GeckoChildrenIterator::Current(curr) => { | ||
| let next = curr.and_then(|node| node.next_sibling()); | ||
| *self = GeckoChildrenIterator::Current(next); | ||
| curr | ||
| }, | ||
| GeckoChildrenIterator::GeckoIterator(it) => unsafe { | ||
| Gecko_GetNextStyleChild(it).as_ref().map(|n| GeckoNode::from_ref(n)) | ||
bholley
Author
Contributor
|
||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[derive(Clone, Copy)] | ||
| pub struct GeckoDocument<'ld> { | ||
| document: *mut RawGeckoDocument, | ||
You can eta-reduce this closure ;-)