Skip to content
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

Merged
merged 4 commits into from Aug 26, 2016
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

Implement GeckoChildrenIterator to traverse anonymous children.

  • Loading branch information
bholley committed Aug 26, 2016
commit 122df8ca6052c356fca901d8043d29e358a1a0fb
@@ -168,6 +168,7 @@ pub enum RawServoStyleSheet { }
pub enum RawServoStyleSet { }
pub enum nsHTMLCSSStyleSheet { }
pub enum ServoDeclarationBlock { }
pub enum StyleChildrenIterator { }
pub type ThreadSafePrincipalHolder = nsMainThreadPtrHolder<nsIPrincipal>;
pub type ThreadSafeURIHolder = nsMainThreadPtrHolder<nsIURI>;
extern "C" {
@@ -190,6 +191,11 @@ extern "C" {
-> *mut RawGeckoElement;
pub fn Gecko_GetDocumentElement(document: *mut RawGeckoDocument)
-> *mut RawGeckoElement;
pub fn Gecko_MaybeCreateStyleChildrenIterator(node: *mut RawGeckoNode)
-> *mut StyleChildrenIterator;
pub fn Gecko_DropStyleChildrenIterator(it: *mut StyleChildrenIterator);
pub fn Gecko_GetNextStyleChild(it: *mut StyleChildrenIterator)
-> *mut RawGeckoNode;
pub fn Gecko_ElementState(element: *mut RawGeckoElement) -> u8;
pub fn Gecko_IsHTMLElementInHTMLDocument(element: *mut RawGeckoElement)
-> bool;
@@ -10,10 +10,11 @@ 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};
@@ -164,8 +165,11 @@ impl<'ln> TNode for GeckoNode<'ln> {
}

fn children(self) -> GeckoChildrenIterator<'ln> {
GeckoChildrenIterator {
current: self.first_child(),
let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.node) };
if !maybe_iter.is_null() {
GeckoChildrenIterator::GeckoIterator(maybe_iter)
} else {
GeckoChildrenIterator::Current(self.first_child())
}
}

@@ -341,16 +345,37 @@ impl<'ln> TNode for GeckoNode<'ln> {
unsafe fn set_dirty_on_viewport_size_changed(&self) {}
}

pub struct GeckoChildrenIterator<'a> {
current: Option<GeckoNode<'a>>,
// 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>> {
let node = self.current;
self.current = node.and_then(|node| node.next_sibling());
node
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))

This comment has been minimized.

@emilio

emilio Aug 18, 2016

Member

You can eta-reduce this closure ;-)

This comment has been minimized.

@bholley

bholley Aug 26, 2016

Author Contributor

I can't:

Compiling geckoservo v0.0.1 (file:///files/mozilla/stylo/bb/servo/ports/geckolib)
wrapper.rs:376:54: 376:57 error: the trait bound unsafe fn(&gecko_bindings::bindings::nsINode) -> wrapper::GeckoNode<'_> {wrapper::GeckoNode<'_>::from_ref}: std::ops::FnOnce<(&gecko_bindings::bindings::nsINode,)> is not satisfied [E0277]
wrapper.rs:376 Gecko_GetNextStyleChild(it).as_ref().map(GeckoNode::from_ref)
^~~
wrapper.rs:376:54: 376:57 help: run rustc --explain E0277 to see a detailed explanation
error: aborting due to previous error
error: Could not compile geckoservo.

To learn more, run the command again with --verbose.

}
}
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.