Hold a Temporary in AncestorIterator

This commit is contained in:
Anthony Ramine 2015-04-05 04:38:25 +02:00
parent 6a6ecb9afa
commit bf7c791e3a
10 changed files with 91 additions and 63 deletions

View file

@ -409,8 +409,8 @@ impl<'a> Iterator for QuerySelectorIterator<'a> {
}
pub trait NodeHelpers<'a> {
fn ancestors(self) -> AncestorIterator<'a>;
fn inclusive_ancestors(self) -> AncestorIterator<'a>;
fn ancestors(self) -> AncestorIterator;
fn inclusive_ancestors(self) -> AncestorIterator;
fn children(self) -> NodeChildrenIterator;
fn rev_children(self) -> ReverseChildrenIterator;
fn child_elements(self) -> ChildElementIterator<'a>;
@ -735,8 +735,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
// 4. Dirty ancestors.
for ancestor in self.ancestors() {
if !force_ancestors && ancestor.get_has_dirty_descendants() { break }
ancestor.set_has_dirty_descendants(true);
let ancestor = ancestor.root();
if !force_ancestors && ancestor.r().get_has_dirty_descendants() { break }
ancestor.r().set_has_dirty_descendants(true);
}
}
@ -752,7 +753,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool {
self == parent || parent.ancestors().any(|ancestor| ancestor == self)
self == parent || parent.ancestors().any(|ancestor| ancestor.root().r() == self)
}
fn following_siblings(self) -> NodeChildrenIterator {
@ -788,7 +789,8 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
Err(()) => return Err(Syntax),
// Step 3.
Ok(ref selectors) => {
let root = self.ancestors().last().unwrap_or(self.clone());
let root = self.ancestors().last().root();
let root = root.r().unwrap_or(self.clone());
Ok(root.traverse_preorder()
.filter_map(ElementCast::to_ref)
.find(|element| matches(selectors, &NodeCast::from_ref(*element), &mut None))
@ -805,7 +807,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
-> Fallible<QuerySelectorIterator<'a>> {
// Step 1.
let nodes;
let root = self.ancestors().last().unwrap_or(self.clone());
let root = self.ancestors().last().root()
.map(|node| node.get_unsound_ref_forever())
.unwrap_or(self.clone());
match parse_author_origin_selector_list_from_str(selectors.as_slice()) {
// Step 2.
Err(()) => return Err(Syntax),
@ -830,15 +834,15 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
fn ancestors(self) -> AncestorIterator<'a> {
fn ancestors(self) -> AncestorIterator {
AncestorIterator {
current: self.parent_node.get().map(|node| node.root().get_unsound_ref_forever()),
current: self.parent_node()
}
}
fn inclusive_ancestors(self) -> AncestorIterator<'a> {
fn inclusive_ancestors(self) -> AncestorIterator {
AncestorIterator {
current: Some(self.clone())
current: Some(Temporary::from_rooted(self))
}
}
@ -1148,17 +1152,20 @@ impl Iterator for ReverseChildrenIterator {
}
}
pub struct AncestorIterator<'a> {
current: Option<JSRef<'a, Node>>,
pub struct AncestorIterator {
current: Option<Temporary<Node>>,
}
impl<'a> Iterator for AncestorIterator<'a> {
type Item = JSRef<'a, Node>;
impl Iterator for AncestorIterator {
type Item = Temporary<Node>;
fn next(&mut self) -> Option<JSRef<'a, Node>> {
let node = self.current;
self.current = node.and_then(|node| node.parent_node().map(|node| node.root().get_unsound_ref_forever()));
node
fn next(&mut self) -> Option<Temporary<Node>> {
let current = match self.current.take() {
None => return None,
Some(current) => current,
}.root();
self.current = current.r().parent_node();
Some(Temporary::from_rooted(current.r()))
}
}
@ -2174,23 +2181,25 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// step 2.
0
} else {
let mut lastself = self.clone();
let mut lastother = other.clone();
let mut lastself = Temporary::from_rooted(self.clone());
let mut lastother = Temporary::from_rooted(other.clone());
for ancestor in self.ancestors() {
if ancestor == other {
let ancestor = ancestor.root();
if ancestor.r() == other {
// step 4.
return NodeConstants::DOCUMENT_POSITION_CONTAINS +
NodeConstants::DOCUMENT_POSITION_PRECEDING;
}
lastself = ancestor.clone();
lastself = Temporary::from_rooted(ancestor.r());
}
for ancestor in other.ancestors() {
if ancestor == self {
let ancestor = ancestor.root();
if ancestor.r() == self {
// step 5.
return NodeConstants::DOCUMENT_POSITION_CONTAINED_BY +
NodeConstants::DOCUMENT_POSITION_FOLLOWING;
}
lastother = ancestor.clone();
lastother = Temporary::from_rooted(ancestor.r());
}
if lastself != lastother {
@ -2208,7 +2217,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
}
for child in lastself.traverse_preorder() {
let lastself = lastself.root();
for child in lastself.r().traverse_preorder() {
if child == other {
// step 6.
return NodeConstants::DOCUMENT_POSITION_PRECEDING;
@ -2418,7 +2428,10 @@ pub trait DisabledStateHelpers {
impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
fn check_ancestors_disabled_state_for_form_control(self) {
if self.get_disabled_state() { return; }
for ancestor in self.ancestors().filter(|ancestor| ancestor.is_htmlfieldsetelement()) {
for ancestor in self.ancestors() {
let ancestor = ancestor.root();
let ancestor = ancestor.r();
if !ancestor.is_htmlfieldsetelement() { continue; }
if !ancestor.get_disabled_state() { continue; }
if ancestor.is_parent_of(self) {
self.set_disabled_state(true);
@ -2431,7 +2444,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
{
Some(legend) => {
// XXXabinader: should we save previous ancestor to avoid this iteration?
if self.ancestors().any(|ancestor| ancestor == legend.r()) { continue; }
if self.ancestors().any(|ancestor| ancestor.root().r() == legend.r()) { continue; }
},
None => ()
}