aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-04-13 04:52:32 -0500
committerbors-servo <metajack+bors@gmail.com>2015-04-13 04:52:32 -0500
commit1e45d025b381390f346e8f24db615cb698033844 (patch)
treea8d976b5919028dc894fda2807b2987548eeba06
parent9d027bab0a9601437842acb738b326c7e5547844 (diff)
parente20d997b37d93d35d2a80761d8e125351d9165bc (diff)
downloadservo-1e45d025b381390f346e8f24db615cb698033844.tar.gz
servo-1e45d025b381390f346e8f24db615cb698033844.zip
Auto merge of #5645 - nox:treeiterator-temporary, r=Ms2ger
-rw-r--r--components/script/devtools.rs4
-rw-r--r--components/script/dom/document.rs51
-rw-r--r--components/script/dom/htmlbuttonelement.rs10
-rw-r--r--components/script/dom/htmlcollection.rs24
-rw-r--r--components/script/dom/htmlfieldsetelement.rs14
-rw-r--r--components/script/dom/htmlformelement.rs21
-rw-r--r--components/script/dom/htmlinputelement.rs31
-rw-r--r--components/script/dom/node.rs135
-rw-r--r--components/script/dom/nodelist.rs5
-rw-r--r--components/script/script_task.rs24
10 files changed, 172 insertions, 147 deletions
diff --git a/components/script/devtools.rs b/components/script/devtools.rs
index 56588941667..8b9bb84e830 100644
--- a/components/script/devtools.rs
+++ b/components/script/devtools.rs
@@ -69,8 +69,8 @@ fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String
let node: JSRef<Node> = NodeCast::from_ref(document.r());
for candidate in node.traverse_preorder() {
- if candidate.get_unique_id() == node_id {
- return Temporary::from_rooted(candidate);
+ if candidate.root().r().get_unique_id() == node_id {
+ return candidate;
}
}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 57cee418838..f001f0268f3 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -26,6 +26,7 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{MutNullableJS, JS, JSRef, LayoutJS, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::bindings::refcounted::Trusted;
+use dom::bindings::trace::RootedVec;
use dom::bindings::utils::reflect_dom_object;
use dom::bindings::utils::{xml_name_type, validate_and_extract};
use dom::bindings::utils::XMLName::InvalidXMLName;
@@ -343,12 +344,12 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let mut head: usize = 0;
let root: JSRef<Node> = NodeCast::from_ref(root.r());
for node in root.traverse_preorder() {
- let elem: Option<JSRef<Element>> = ElementCast::to_ref(node);
- if let Some(elem) = elem {
+ let node = node.root();
+ if let Some(elem) = ElementCast::to_ref(node.r()) {
if (*elements)[head].root().r() == elem {
head += 1;
}
- if new_node == node || head == elements.len() {
+ if new_node == node.r() || head == elements.len() {
break;
}
}
@@ -379,9 +380,9 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
};
let doc_node: JSRef<Node> = NodeCast::from_ref(self);
doc_node.traverse_preorder()
- .filter_map(HTMLAnchorElementCast::to_ref)
- .find(check_anchor)
- .map(|node| Temporary::from_rooted(ElementCast::from_ref(node)))
+ .filter_map(HTMLAnchorElementCast::to_temporary)
+ .find(|node| check_anchor(&node.root().r()))
+ .map(ElementCast::from_temporary)
})
}
@@ -493,7 +494,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
fn dirty_all_nodes(self) {
let root: JSRef<Node> = NodeCast::from_ref(self);
for node in root.traverse_preorder() {
- node.dirty(NodeDamage::OtherNodeDamage)
+ node.root().r().dirty(NodeDamage::OtherNodeDamage)
}
}
@@ -817,22 +818,24 @@ impl Document {
}
trait PrivateDocumentHelpers {
- fn createNodeList<F: Fn(JSRef<Node>) -> bool>(self, callback: F) -> Temporary<NodeList>;
+ fn create_node_list<F: Fn(JSRef<Node>) -> bool>(self, callback: F) -> Temporary<NodeList>;
fn get_html_element(self) -> Option<Temporary<HTMLHtmlElement>>;
}
impl<'a> PrivateDocumentHelpers for JSRef<'a, Document> {
- fn createNodeList<F: Fn(JSRef<Node>) -> bool>(self, callback: F) -> Temporary<NodeList> {
+ fn create_node_list<F: Fn(JSRef<Node>) -> bool>(self, callback: F) -> Temporary<NodeList> {
let window = self.window.root();
let document_element = self.GetDocumentElement().root();
- let nodes = match document_element {
- None => vec!(),
- Some(ref root) => {
- let root: JSRef<Node> = NodeCast::from_ref(root.r());
- root.traverse_preorder().filter(|&node| callback(node)).collect()
+ let mut nodes = RootedVec::new();
+ if let Some(ref root) = document_element {
+ for node in NodeCast::from_ref(root.r()).traverse_preorder() {
+ let node = node.root();
+ if callback(node.r()) {
+ nodes.push(node.r().unrooted());
+ }
}
};
- NodeList::new_simple_list(window.r(), nodes)
+ NodeList::new_simple_list(window.r(), &nodes)
}
fn get_html_element(self) -> Option<Temporary<HTMLHtmlElement>> {
@@ -1118,14 +1121,14 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://www.whatwg.org/specs/web-apps/current-work/#document.title
fn Title(self) -> DOMString {
let title_element = self.GetDocumentElement().root().and_then(|root| {
- NodeCast::from_ref(root.get_unsound_ref_forever())
- .traverse_preorder()
- .find(|node| node.type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement)))
- });
+ NodeCast::from_ref(root.r()).traverse_preorder().find(|node| {
+ node.root().r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement))
+ })
+ }).root();
let mut title = String::new();
if let Some(title_element) = title_element {
- for child in title_element.children() {
+ for child in title_element.r().children() {
let child = child.root();
if let Some(text) = TextCast::to_ref(child.r()) {
title.push_str(&CharacterDataCast::from_ref(text).data());
@@ -1142,9 +1145,9 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
self.GetDocumentElement().root().map(|root| {
let root: JSRef<Node> = NodeCast::from_ref(root.r());
let head_node = root.traverse_preorder().find(|child| {
- child.type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement))
- });
- head_node.map(|head| {
+ child.root().r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement))
+ }).root();
+ head_node.r().map(|head| {
let title_node = head.children().map(|c| c.root()).find(|child| {
child.r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement))
});
@@ -1255,7 +1258,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-getelementsbyname
fn GetElementsByName(self, name: DOMString) -> Temporary<NodeList> {
- self.createNodeList(|node| {
+ self.create_node_list(|node| {
let element: JSRef<Element> = match ElementCast::to_ref(node) {
Some(element) => element,
None => return false,
diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs
index aaf725d1d9e..a4877e72aa4 100644
--- a/components/script/dom/htmlbuttonelement.rs
+++ b/components/script/dom/htmlbuttonelement.rs
@@ -224,12 +224,10 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
// and only then performing actions which may modify the DOM tree
unsafe {
node.query_selector_iter("button[type=submit]".to_owned()).unwrap()
- .filter_map(|t| {
- let h: Option<JSRef<HTMLButtonElement>> = HTMLButtonElementCast::to_ref(t);
- h
- })
- .find(|r| r.form_owner() == owner)
- .map(|s| s.synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
+ .filter_map(HTMLButtonElementCast::to_temporary)
+ .map(|t| t.root())
+ .find(|r| r.r().form_owner() == owner)
+ .map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
}
}
}
diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs
index a6e216cffdb..a2cf605bc7e 100644
--- a/components/script/dom/htmlcollection.rs
+++ b/components/script/dom/htmlcollection.rs
@@ -164,12 +164,13 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box ElementChildFilter)
}
- fn traverse<'a>(root: JSRef<'a, Node>)
- -> FilterMap<Skip<TreeIterator<'a>>,
- fn(JSRef<Node>) -> Option<JSRef<Element>>> {
+ fn traverse(root: JSRef<Node>)
+ -> FilterMap<Skip<TreeIterator>,
+ fn(Temporary<Node>) -> Option<Temporary<Element>>> {
root.traverse_preorder()
.skip(1)
- .filter_map(ElementCast::to_ref as fn(JSRef<Node>) -> Option<JSRef<Element>>)
+ .filter_map(ElementCast::to_temporary as
+ fn(Temporary<Node>) -> Option<Temporary<Element>>)
}
}
@@ -181,7 +182,7 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root();
HTMLCollection::traverse(root.r())
- .filter(|element| filter.filter(*element, root.r()))
+ .filter(|element| filter.filter(element.root().r(), root.r()))
.count() as u32
}
}
@@ -198,10 +199,8 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root();
HTMLCollection::traverse(root.r())
- .filter(|element| filter.filter(*element, root.r()))
+ .filter(|element| filter.filter(element.root().r(), root.r()))
.nth(index)
- .clone()
- .map(Temporary::from_rooted)
}
}
}
@@ -224,11 +223,12 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root();
HTMLCollection::traverse(root.r())
- .filter(|element| filter.filter(*element, root.r()))
+ .map(|element| element.root())
+ .filter(|element| filter.filter(element.r(), root.r()))
.find(|elem| {
- elem.get_string_attribute(&atom!("name")) == key ||
- elem.get_string_attribute(&atom!("id")) == key })
- .map(Temporary::from_rooted)
+ elem.r().get_string_attribute(&atom!("name")) == key ||
+ elem.r().get_string_attribute(&atom!("id")) == key })
+ .map(|elem| Temporary::from_rooted(elem.r()))
}
}
}
diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs
index 39088810eab..e3b8397e4bc 100644
--- a/components/script/dom/htmlfieldsetelement.rs
+++ b/components/script/dom/htmlfieldsetelement.rs
@@ -104,13 +104,14 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
}
for descendant in child.r().traverse_preorder() {
- match descendant.type_id() {
+ let descendant = descendant.root();
+ match descendant.r().type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
- descendant.set_disabled_state(true);
- descendant.set_enabled_state(false);
+ descendant.r().set_disabled_state(true);
+ descendant.r().set_enabled_state(false);
},
_ => ()
}
@@ -142,13 +143,14 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
}
for descendant in child.r().traverse_preorder() {
- match descendant.type_id() {
+ let descendant = descendant.root();
+ match descendant.r().type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
- descendant.check_disabled_attribute();
- descendant.check_ancestors_disabled_state_for_form_control();
+ descendant.r().check_disabled_attribute();
+ descendant.r().check_ancestors_disabled_state_for_form_control();
},
_ => ()
}
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 395a9ab8522..7bd9925ffd2 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -20,7 +20,7 @@ use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlinputelement::{HTMLInputElement, HTMLInputElementHelpers};
use dom::htmlbuttonelement::{HTMLButtonElement};
-use dom::htmltextareaelement::{HTMLTextAreaElement, HTMLTextAreaElementHelpers};
+use dom::htmltextareaelement::HTMLTextAreaElementHelpers;
use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node};
use hyper::method::Method;
use hyper::header::ContentType;
@@ -255,16 +255,18 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
// TODO: This is an incorrect way of getting controls owned
// by the form, but good enough until html5ever lands
let data_set = node.traverse_preorder().filter_map(|child| {
- if child.get_disabled_state() {
+ let child = child.root();
+ if child.r().get_disabled_state() {
return None;
}
- if child.ancestors().any(|a| a.root().r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDataListElement))) {
+ if child.r().ancestors()
+ .any(|a| a.root().r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDataListElement))) {
return None;
}
// XXXManishearth don't include it if it is a button but not the submitter
- match child.type_id() {
+ match child.r().type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
- let input: JSRef<HTMLInputElement> = HTMLInputElementCast::to_ref(child).unwrap();
+ let input = HTMLInputElementCast::to_ref(child.r()).unwrap();
let ty = input.Type();
let name = input.Name();
match ty.as_slice() {
@@ -368,10 +370,10 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
// TODO: This is an incorrect way of getting controls owned
// by the form, but good enough until html5ever lands
for child in node.traverse_preorder() {
- match child.type_id() {
+ let child = child.root();
+ match child.r().type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
- let input: JSRef<HTMLInputElement> = HTMLInputElementCast::to_ref(child)
- .unwrap();
+ let input = HTMLInputElementCast::to_ref(child.r()).unwrap();
input.reset()
}
// TODO HTMLKeygenElement unimplemented
@@ -384,8 +386,7 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
{}
}
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
- let textarea: JSRef<HTMLTextAreaElement> = HTMLTextAreaElementCast::to_ref(child)
- .unwrap();
+ let textarea = HTMLTextAreaElementCast::to_ref(child.r()).unwrap();
textarea.reset()
}
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index cb3eff8c59b..30cd0676eb1 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -346,12 +346,13 @@ fn broadcast_radio_checked(broadcaster: JSRef<HTMLInputElement>, group: Option<&
// There is no DOM tree manipulation here, so this is safe
let iter = unsafe {
doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
- .filter_map(|t| HTMLInputElementCast::to_ref(t))
- .filter(|&r| in_same_group(r, owner, group) && broadcaster != r)
+ .filter_map(HTMLInputElementCast::to_temporary)
+ .map(|t| t.root())
+ .filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r())
};
for r in iter {
- if r.Checked() {
- r.SetChecked(false);
+ if r.r().Checked() {
+ r.r().SetChecked(false);
}
}
}
@@ -684,12 +685,14 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// Safe since we only manipulate the DOM tree after finding an element
let checked_member = unsafe {
doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
- .filter_map(|t| HTMLInputElementCast::to_ref(t))
- .filter(|&r| in_same_group(r, owner.r(),
- group.as_ref().map(|gr| gr.as_slice())))
- .find(|r| r.Checked())
+ .filter_map(HTMLInputElementCast::to_temporary)
+ .map(|t| t.root())
+ .find(|r| {
+ in_same_group(r.r(), owner.r(), group.as_ref().map(|gr| gr.as_slice())) &&
+ r.r().Checked()
+ })
};
- cache.checked_radio.assign(checked_member);
+ cache.checked_radio.assign(checked_member.r());
cache.checked_changed = self.checked_changed.get();
self.SetChecked(true);
}
@@ -815,12 +818,10 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// and only then performing actions which may modify the DOM tree
unsafe {
node.query_selector_iter("input[type=submit]".to_owned()).unwrap()
- .filter_map(|t| {
- let h: Option<JSRef<HTMLInputElement>> = HTMLInputElementCast::to_ref(t);
- h
- })
- .find(|r| r.form_owner() == owner)
- .map(|s| s.synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
+ .filter_map(HTMLInputElementCast::to_temporary)
+ .map(|t| t.root())
+ .find(|r| r.r().form_owner() == owner)
+ .map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
}
}
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index e628ee4b2d9..6e96e560101 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -290,7 +290,8 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
let is_in_doc = self.is_in_doc();
for node in self.traverse_preorder() {
- vtable_for(&node).bind_to_tree(is_in_doc);
+ let node = node.root();
+ vtable_for(&node.r()).bind_to_tree(is_in_doc);
}
let parent = self.parent_node().root();
@@ -302,7 +303,8 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
fn node_removed(self, parent_in_doc: bool) {
assert!(self.parent_node().is_none());
for node in self.traverse_preorder() {
- vtable_for(&node).unbind_from_tree(parent_in_doc);
+ let node = node.root();
+ vtable_for(&node.r()).unbind_from_tree(parent_in_doc);
}
self.layout_data.dispose();
}
@@ -381,14 +383,15 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
}
}
-pub struct QuerySelectorIterator<'a> {
+pub struct QuerySelectorIterator {
selectors: Vec<Selector>,
- iterator: TreeIterator<'a>,
+ iterator: TreeIterator,
}
-impl<'a> QuerySelectorIterator<'a> {
+impl<'a> QuerySelectorIterator {
#[allow(unsafe_code)]
- unsafe fn new(iter: TreeIterator<'a>, selectors: Vec<Selector>) -> QuerySelectorIterator<'a> {
+ unsafe fn new(iter: TreeIterator, selectors: Vec<Selector>)
+ -> QuerySelectorIterator {
QuerySelectorIterator {
selectors: selectors,
iterator: iter,
@@ -396,18 +399,21 @@ impl<'a> QuerySelectorIterator<'a> {
}
}
-impl<'a> Iterator for QuerySelectorIterator<'a> {
- type Item = JSRef<'a, Node>;
+impl<'a> Iterator for QuerySelectorIterator {
+ type Item = Temporary<Node>;
- fn next(&mut self) -> Option<JSRef<'a, Node>> {
+ fn next(&mut self) -> Option<Temporary<Node>> {
let selectors = &self.selectors;
// TODO(cgaebel): Is it worth it to build a bloom filter here
// (instead of passing `None`)? Probably.
- self.iterator.find(|node| node.is_element() && matches(selectors, node, &mut None))
+ self.iterator.find(|node| {
+ let node = node.root();
+ node.r().is_element() && matches(selectors, &node.r(), &mut None)
+ })
}
}
-pub trait NodeHelpers<'a> {
+pub trait NodeHelpers {
fn ancestors(self) -> AncestorIterator;
fn inclusive_ancestors(self) -> AncestorIterator;
fn children(self) -> NodeSiblingIterator;
@@ -484,7 +490,7 @@ pub trait NodeHelpers<'a> {
fn dump_indent(self, indent: u32);
fn debug_str(self) -> String;
- fn traverse_preorder(self) -> TreeIterator<'a>;
+ fn traverse_preorder(self) -> TreeIterator;
fn inclusively_following_siblings(self) -> NodeSiblingIterator;
fn inclusively_preceding_siblings(self) -> ReverseSiblingIterator;
@@ -495,7 +501,7 @@ pub trait NodeHelpers<'a> {
fn query_selector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
#[allow(unsafe_code)]
- unsafe fn query_selector_iter(self, selectors: DOMString) -> Fallible<QuerySelectorIterator<'a>>;
+ unsafe fn query_selector_iter(self, selectors: DOMString) -> Fallible<QuerySelectorIterator>;
fn query_selector_all(self, selectors: DOMString) -> Fallible<Temporary<NodeList>>;
fn remove_self(self);
@@ -508,7 +514,7 @@ pub trait NodeHelpers<'a> {
fn parse_fragment(self, markup: DOMString) -> Fallible<Temporary<DocumentFragment>>;
}
-impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
+impl<'a> NodeHelpers for JSRef<'a, Node> {
fn teardown(self) {
self.layout_data.dispose();
for kid in self.children() {
@@ -745,7 +751,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
}
/// Iterates over this node and all its descendants, in preorder.
- fn traverse_preorder(self) -> TreeIterator<'a> {
+ fn traverse_preorder(self) -> TreeIterator {
TreeIterator::new(self)
}
@@ -806,10 +812,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
Ok(ref selectors) => {
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))
- .map(Temporary::from_rooted))
+ Ok(root.traverse_preorder().filter_map(ElementCast::to_temporary).find(|element| {
+ matches(selectors, &NodeCast::from_ref(element.root().r()), &mut None)
+ }))
}
}
}
@@ -819,7 +824,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
/// the iterator may be invalidated
#[allow(unsafe_code)]
unsafe fn query_selector_iter(self, selectors: DOMString)
- -> Fallible<QuerySelectorIterator<'a>> {
+ -> Fallible<QuerySelectorIterator> {
// Step 1.
let nodes;
let root = self.ancestors().last().root()
@@ -839,13 +844,12 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
// http://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
#[allow(unsafe_code)]
fn query_selector_all(self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
- // Step 1.
- unsafe {
- self.query_selector_iter(selectors).map(|iter| {
- let window = window_from_node(self).root();
- NodeList::new_simple_list(window.r(), iter.collect())
- })
+ let mut nodes = RootedVec::new();
+ for node in try!(unsafe { self.query_selector_iter(selectors) }) {
+ nodes.push(JS::from_rooted(node));
}
+ let window = window_from_node(self).root();
+ Ok(NodeList::new_simple_list(window.r(), &nodes))
}
@@ -1179,30 +1183,48 @@ impl Iterator for AncestorIterator {
}
}
-pub struct TreeIterator<'a> {
- stack: Vec<JSRef<'a, Node>>,
+pub struct TreeIterator {
+ current: Option<Temporary<Node>>,
+ depth: usize,
}
-impl<'a> TreeIterator<'a> {
- fn new(root: JSRef<'a, Node>) -> TreeIterator<'a> {
- let mut stack = vec!();
- stack.push(root);
-
+impl<'a> TreeIterator {
+ fn new(root: JSRef<'a, Node>) -> TreeIterator {
TreeIterator {
- stack: stack,
+ current: Some(Temporary::from_rooted(root)),
+ depth: 0,
}
}
}
-impl<'a> Iterator for TreeIterator<'a> {
- type Item = JSRef<'a, Node>;
+impl Iterator for TreeIterator {
+ type Item = Temporary<Node>;
- fn next(&mut self) -> Option<JSRef<'a, Node>> {
- let ret = self.stack.pop();
- ret.map(|node| {
- self.stack.extend(node.rev_children().map(|c| c.root().get_unsound_ref_forever()))
- });
- ret
+ // https://dom.spec.whatwg.org/#concept-tree-order
+ fn next(&mut self) -> Option<Temporary<Node>> {
+ let current = match self.current.take() {
+ None => return None,
+ Some(current) => current,
+ };
+ let node = current.root();
+ if let Some(first_child) = node.r().first_child() {
+ self.current = Some(first_child);
+ self.depth += 1;
+ return Some(current);
+ };
+ for ancestor in node.r().inclusive_ancestors() {
+ if self.depth == 0 {
+ break;
+ }
+ if let Some(next_sibling) = ancestor.root().r().next_sibling() {
+ self.current = Some(next_sibling);
+ return Some(current);
+ }
+ self.depth -= 1;
+ }
+ debug_assert!(self.depth == 0);
+ self.current = None;
+ Some(current)
}
}
@@ -1284,7 +1306,7 @@ impl Node {
let node_doc = document_from_node(node).root();
if node_doc.r() != document {
for descendant in node.traverse_preorder() {
- descendant.set_owner_doc(document);
+ descendant.root().r().set_owner_doc(document);
}
}
@@ -1439,13 +1461,14 @@ impl Node {
parent.add_child(node, child);
let is_in_doc = parent.is_in_doc();
for kid in node.traverse_preorder() {
- let mut flags = kid.flags.get();
+ let kid = kid.root();
+ let mut flags = kid.r().flags.get();
if is_in_doc {
flags.insert(IS_IN_DOC);
} else {
flags.remove(IS_IN_DOC);
}
- kid.flags.set(flags);
+ kid.r().flags.set(flags);
}
}
@@ -1848,8 +1871,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
match self.type_id {
NodeTypeId::DocumentFragment |
NodeTypeId::Element(..) => {
- let content = Node::collect_text_contents(
- self.traverse_preorder().map(Temporary::from_rooted));
+ let content = Node::collect_text_contents(self.traverse_preorder());
Some(content)
}
NodeTypeId::Comment |
@@ -2233,11 +2255,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
let lastself = lastself.root();
for child in lastself.r().traverse_preorder() {
- if child == other {
+ let child = child.root();
+ if child.r() == other {
// step 6.
return NodeConstants::DOCUMENT_POSITION_PRECEDING;
}
- if child == self {
+ if child.r() == self {
// step 7.
return NodeConstants::DOCUMENT_POSITION_FOLLOWING;
}
@@ -2308,7 +2331,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn parent_node(self) -> Option<JSRef<'a, Node>> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn parent_node<'a, T: NodeHelpers<'a>>(this: T) -> Option<Temporary<Node>> {
+ fn parent_node<'a, T: NodeHelpers>(this: T) -> Option<Temporary<Node>> {
this.parent_node()
}
@@ -2318,7 +2341,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn first_child(self) -> Option<JSRef<'a, Node>> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn first_child<'a, T: NodeHelpers<'a>>(this: T) -> Option<Temporary<Node>> {
+ fn first_child<'a, T: NodeHelpers>(this: T) -> Option<Temporary<Node>> {
this.first_child()
}
@@ -2328,7 +2351,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn last_child(self) -> Option<JSRef<'a, Node>> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn last_child<'a, T: NodeHelpers<'a>>(this: T) -> Option<Temporary<Node>> {
+ fn last_child<'a, T: NodeHelpers>(this: T) -> Option<Temporary<Node>> {
this.last_child()
}
@@ -2338,7 +2361,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn prev_sibling(self) -> Option<JSRef<'a, Node>> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn prev_sibling<'a, T: NodeHelpers<'a>>(this: T) -> Option<Temporary<Node>> {
+ fn prev_sibling<'a, T: NodeHelpers>(this: T) -> Option<Temporary<Node>> {
this.prev_sibling()
}
@@ -2348,7 +2371,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn next_sibling(self) -> Option<JSRef<'a, Node>> {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn next_sibling<'a, T: NodeHelpers<'a>>(this: T) -> Option<Temporary<Node>> {
+ fn next_sibling<'a, T: NodeHelpers>(this: T) -> Option<Temporary<Node>> {
this.next_sibling()
}
@@ -2358,7 +2381,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn is_document(self) -> bool {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn is_document<'a, T: NodeHelpers<'a>>(this: T) -> bool {
+ fn is_document<'a, T: NodeHelpers>(this: T) -> bool {
this.is_document()
}
@@ -2368,7 +2391,7 @@ impl<'a> style::node::TNode<'a> for JSRef<'a, Node> {
fn is_element(self) -> bool {
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
// of disambiguating methods.
- fn is_element<'a, T: NodeHelpers<'a>>(this: T) -> bool {
+ fn is_element<'a, T: NodeHelpers>(this: T) -> bool {
this.is_element()
}
diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs
index 84aa5d6e2ea..8826733cfa6 100644
--- a/components/script/dom/nodelist.rs
+++ b/components/script/dom/nodelist.rs
@@ -6,6 +6,7 @@ use dom::bindings::codegen::Bindings::NodeListBinding;
use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary};
+use dom::bindings::trace::RootedVec;
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::node::{Node, NodeHelpers};
use dom::window::Window;
@@ -38,8 +39,8 @@ impl NodeList {
GlobalRef::Window(window), NodeListBinding::Wrap)
}
- pub fn new_simple_list(window: JSRef<Window>, elements: Vec<JSRef<Node>>) -> Temporary<NodeList> {
- NodeList::new(window, NodeListType::Simple(elements.iter().map(|element| JS::from_rooted(*element)).collect()))
+ pub fn new_simple_list(window: JSRef<Window>, elements: &RootedVec<JS<Node>>) -> Temporary<NodeList> {
+ NodeList::new(window, NodeListType::Simple((**elements).clone()))
}
pub fn new_child_list(window: JSRef<Window>, node: JSRef<Node>) -> Temporary<NodeList> {
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 93d176e3b18..40eae7e0f74 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -24,7 +24,7 @@ use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, Documen
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
-use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, RootedReference};
+use dom::bindings::js::{JS, JSRef, OptionalRootable, RootedReference};
use dom::bindings::js::{RootCollection, RootCollectionPtr};
use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference};
use dom::bindings::structuredclone::StructuredCloneData;
@@ -811,9 +811,8 @@ impl ScriptTask {
let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
doc.traverse_preorder()
- .filter_map(HTMLIFrameElementCast::to_ref)
- .find(|node| node.subpage_id() == Some(subpage_id))
- .map(Temporary::from_rooted)
+ .filter_map(HTMLIFrameElementCast::to_temporary)
+ .find(|node| node.root().r().subpage_id() == Some(subpage_id))
}).root();
if let Some(frame_element) = frame_element {
@@ -832,9 +831,8 @@ impl ScriptTask {
let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
doc.traverse_preorder()
- .filter_map(HTMLIFrameElementCast::to_ref)
- .find(|node| node.subpage_id() == Some(old_subpage_id))
- .map(Temporary::from_rooted)
+ .filter_map(HTMLIFrameElementCast::to_temporary)
+ .find(|node| node.root().r().subpage_id() == Some(old_subpage_id))
}).root();
frame_element.unwrap().r().update_subpage_id(new_subpage_id);
@@ -952,10 +950,9 @@ impl ScriptTask {
let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
doc.traverse_preorder()
- .filter_map(HTMLIFrameElementCast::to_ref)
- .find(|node| node.subpage_id() == Some(subpage_id))
- .map(ElementCast::from_ref)
- .map(Temporary::from_rooted)
+ .filter_map(HTMLIFrameElementCast::to_temporary)
+ .find(|node| node.root().r().subpage_id() == Some(subpage_id))
+ .map(ElementCast::from_temporary)
})
})
}).root();
@@ -1218,9 +1215,8 @@ impl ScriptTask {
let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
doc.traverse_preorder()
- .filter_map(HTMLIFrameElementCast::to_ref)
- .find(|node| node.subpage_id() == Some(subpage_id))
- .map(Temporary::from_rooted)
+ .filter_map(HTMLIFrameElementCast::to_temporary)
+ .find(|node| node.root().r().subpage_id() == Some(subpage_id))
}).root();
if let Some(iframe) = iframe.r() {
iframe.navigate_child_browsing_context(load_data.url);