diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/devtools.rs | 4 | ||||
-rw-r--r-- | components/script/dom/document.rs | 51 | ||||
-rw-r--r-- | components/script/dom/htmlbuttonelement.rs | 10 | ||||
-rw-r--r-- | components/script/dom/htmlcollection.rs | 24 | ||||
-rw-r--r-- | components/script/dom/htmlfieldsetelement.rs | 14 | ||||
-rw-r--r-- | components/script/dom/htmlformelement.rs | 21 | ||||
-rw-r--r-- | components/script/dom/htmlinputelement.rs | 31 | ||||
-rw-r--r-- | components/script/dom/node.rs | 135 | ||||
-rw-r--r-- | components/script/dom/nodelist.rs | 5 | ||||
-rw-r--r-- | components/script/script_task.rs | 24 |
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); |