mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
Rewrite NodeChildrenIterator to return Temporary.
This commit is contained in:
parent
bc8ed81dc1
commit
c8106da277
11 changed files with 208 additions and 129 deletions
|
@ -79,7 +79,10 @@ fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String
|
||||||
|
|
||||||
pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
|
pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
|
||||||
let parent = find_node_by_unique_id(&*page, pipeline, node_id).root();
|
let parent = find_node_by_unique_id(&*page, pipeline, node_id).root();
|
||||||
let children = parent.r().children().map(|child| child.summarize()).collect();
|
let children = parent.r().children().map(|child| {
|
||||||
|
let child = child.root();
|
||||||
|
child.r().summarize()
|
||||||
|
}).collect();
|
||||||
reply.send(children).unwrap();
|
reply.send(children).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -901,9 +901,9 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
fn GetDoctype(self) -> Option<Temporary<DocumentType>> {
|
fn GetDoctype(self) -> Option<Temporary<DocumentType>> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.children()
|
node.children()
|
||||||
.filter_map(DocumentTypeCast::to_ref)
|
.map(|c| c.root())
|
||||||
|
.filter_map(|c| DocumentTypeCast::to_ref(c.r()).map(Temporary::from_rooted))
|
||||||
.next()
|
.next()
|
||||||
.map(Temporary::from_rooted)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-document-documentelement
|
// http://dom.spec.whatwg.org/#dom-document-documentelement
|
||||||
|
@ -1127,7 +1127,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
let mut title = String::new();
|
let mut title = String::new();
|
||||||
if let Some(title_element) = title_element {
|
if let Some(title_element) = title_element {
|
||||||
for child in title_element.children() {
|
for child in title_element.children() {
|
||||||
if let Some(text) = TextCast::to_ref(child) {
|
let child = child.root();
|
||||||
|
if let Some(text) = TextCast::to_ref(child.r()) {
|
||||||
title.push_str(&text.characterdata().data());
|
title.push_str(&text.characterdata().data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1146,18 +1147,19 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
child.type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement))
|
child.type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement))
|
||||||
});
|
});
|
||||||
head_node.map(|head| {
|
head_node.map(|head| {
|
||||||
let title_node = head.children().find(|child| {
|
let title_node = head.children().map(|c| c.root()).find(|child| {
|
||||||
child.type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement))
|
child.r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement))
|
||||||
});
|
});
|
||||||
|
|
||||||
match title_node {
|
match title_node {
|
||||||
Some(ref title_node) => {
|
Some(ref title_node) => {
|
||||||
for title_child in title_node.children() {
|
for title_child in title_node.r().children() {
|
||||||
assert!(title_node.RemoveChild(title_child).is_ok());
|
let title_child = title_child.root();
|
||||||
|
assert!(title_node.r().RemoveChild(title_child.r()).is_ok());
|
||||||
}
|
}
|
||||||
if !title.is_empty() {
|
if !title.is_empty() {
|
||||||
let new_text = self.CreateTextNode(title.clone()).root();
|
let new_text = self.CreateTextNode(title.clone()).root();
|
||||||
assert!(title_node.AppendChild(NodeCast::from_ref(new_text.r())).is_ok());
|
assert!(title_node.r().AppendChild(NodeCast::from_ref(new_text.r())).is_ok());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -1181,7 +1183,10 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
self.get_html_element().and_then(|root| {
|
self.get_html_element().and_then(|root| {
|
||||||
let root = root.root();
|
let root = root.root();
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(root.r());
|
let node: JSRef<Node> = NodeCast::from_ref(root.r());
|
||||||
node.children().filter_map(HTMLHeadElementCast::to_ref).next().map(Temporary::from_rooted)
|
node.children()
|
||||||
|
.map(|c| c.root())
|
||||||
|
.filter_map(|c| HTMLHeadElementCast::to_ref(c.r()).map(Temporary::from_rooted))
|
||||||
|
.next()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1195,14 +1200,14 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
||||||
self.get_html_element().and_then(|root| {
|
self.get_html_element().and_then(|root| {
|
||||||
let root = root.root();
|
let root = root.root();
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(root.r());
|
let node: JSRef<Node> = NodeCast::from_ref(root.r());
|
||||||
node.children().find(|child| {
|
node.children().map(|c| c.root()).find(|child| {
|
||||||
match child.type_id() {
|
match child.r().type_id() {
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)) |
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)) |
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFrameSetElement)) => true,
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFrameSetElement)) => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}).map(|node| {
|
}).map(|node| {
|
||||||
Temporary::from_rooted(HTMLElementCast::to_ref(node).unwrap())
|
Temporary::from_rooted(HTMLElementCast::to_ref(node.r()).unwrap())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
|
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
|
||||||
use dom::bindings::js::{JSRef, Temporary};
|
use dom::bindings::js::{JSRef, Temporary, RootedReference};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeHandlers, Element, ElementHelpers};
|
use dom::element::{AttributeHandlers, Element, ElementHelpers};
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
|
@ -93,11 +93,17 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||||
node.set_disabled_state(true);
|
node.set_disabled_state(true);
|
||||||
node.set_enabled_state(false);
|
node.set_enabled_state(false);
|
||||||
let maybe_legend = node.children().find(|node| node.is_htmllegendelement());
|
let maybe_legend = node.children()
|
||||||
let filtered: Vec<JSRef<Node>> = node.children().filter(|child| {
|
.map(|node| node.root())
|
||||||
maybe_legend.map_or(true, |legend| legend != *child)
|
.find(|node| node.r().is_htmllegendelement());
|
||||||
}).collect();
|
|
||||||
for descendant in filtered.iter().flat_map(|child| child.traverse_preorder()) {
|
for child in node.children() {
|
||||||
|
let child = child.root();
|
||||||
|
if Some(child.r()) == maybe_legend.r() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for descendant in child.r().traverse_preorder() {
|
||||||
match descendant.type_id() {
|
match descendant.type_id() {
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
|
||||||
|
@ -109,6 +115,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
@ -124,11 +131,17 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||||
node.set_disabled_state(false);
|
node.set_disabled_state(false);
|
||||||
node.set_enabled_state(true);
|
node.set_enabled_state(true);
|
||||||
let maybe_legend = node.children().find(|node| node.is_htmllegendelement());
|
let maybe_legend = node.children()
|
||||||
let filtered: Vec<JSRef<Node>> = node.children().filter(|child| {
|
.map(|node| node.root())
|
||||||
maybe_legend.map_or(true, |legend| legend != *child)
|
.find(|node| node.r().is_htmllegendelement());
|
||||||
}).collect();
|
|
||||||
for descendant in filtered.iter().flat_map(|child| child.traverse_preorder()) {
|
for child in node.children() {
|
||||||
|
let child = child.root();
|
||||||
|
if Some(child.r()) == maybe_legend.r() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for descendant in child.r().traverse_preorder() {
|
||||||
match descendant.type_id() {
|
match descendant.type_id() {
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
|
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
|
||||||
|
@ -140,6 +153,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,12 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLOptGroupElement> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||||
node.set_disabled_state(true);
|
node.set_disabled_state(true);
|
||||||
node.set_enabled_state(false);
|
node.set_enabled_state(false);
|
||||||
for child in node.children().filter(|child| child.is_htmloptionelement()) {
|
for child in node.children() {
|
||||||
child.set_disabled_state(true);
|
let child = child.root();
|
||||||
child.set_enabled_state(false);
|
if child.r().is_htmloptionelement() {
|
||||||
|
child.r().set_disabled_state(true);
|
||||||
|
child.r().set_enabled_state(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -88,8 +91,11 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLOptGroupElement> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||||
node.set_disabled_state(false);
|
node.set_disabled_state(false);
|
||||||
node.set_enabled_state(true);
|
node.set_enabled_state(true);
|
||||||
for child in node.children().filter(|child| child.is_htmloptionelement()) {
|
for child in node.children() {
|
||||||
child.check_disabled_attribute();
|
let child = child.root();
|
||||||
|
if child.r().is_htmloptionelement() {
|
||||||
|
child.r().check_disabled_attribute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => ()
|
_ => ()
|
||||||
|
|
|
@ -57,11 +57,12 @@ fn collect_text(node: &JSRef<Node>, value: &mut DOMString) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
if child.is_text() {
|
let child = child.root();
|
||||||
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(child).unwrap();
|
if child.r().is_text() {
|
||||||
|
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(child.r()).unwrap();
|
||||||
value.push_str(characterdata.Data().as_slice());
|
value.push_str(characterdata.Data().as_slice());
|
||||||
} else {
|
} else {
|
||||||
collect_text(&child, value);
|
collect_text(&child.r(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -525,7 +525,7 @@ impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
|
||||||
// http://www.whatwg.org/html/#dom-script-text
|
// http://www.whatwg.org/html/#dom-script-text
|
||||||
fn Text(self) -> DOMString {
|
fn Text(self) -> DOMString {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
Node::collect_text_contents(node.children())
|
Node::collect_text_contents(node.children().map(|c| c.root()).map(|c| c.get_unsound_ref_forever()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://www.whatwg.org/html/#dom-script-text
|
// http://www.whatwg.org/html/#dom-script-text
|
||||||
|
|
|
@ -64,12 +64,11 @@ impl<'a> HTMLTableElementMethods for JSRef<'a, HTMLTableElement> {
|
||||||
fn GetCaption(self) -> Option<Temporary<HTMLTableCaptionElement>> {
|
fn GetCaption(self) -> Option<Temporary<HTMLTableCaptionElement>> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
node.children()
|
node.children()
|
||||||
.filter_map(|n| {
|
.map(|c| c.root())
|
||||||
let t: Option<JSRef<HTMLTableCaptionElement>> = HTMLTableCaptionElementCast::to_ref(n);
|
.filter_map(|c| {
|
||||||
t
|
HTMLTableCaptionElementCast::to_ref(c.r()).map(Temporary::from_rooted)
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
.map(Temporary::from_rooted)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://www.whatwg.org/html/#dom-table-caption
|
// http://www.whatwg.org/html/#dom-table-caption
|
||||||
|
|
|
@ -48,7 +48,8 @@ impl<'a> HTMLTitleElementMethods for JSRef<'a, HTMLTitleElement> {
|
||||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
let text: Option<JSRef<Text>> = TextCast::to_ref(child);
|
let child = child.root();
|
||||||
|
let text: Option<JSRef<Text>> = TextCast::to_ref(child.r());
|
||||||
match text {
|
match text {
|
||||||
Some(text) => content.push_str(text.characterdata().data().as_slice()),
|
Some(text) => content.push_str(text.characterdata().data().as_slice()),
|
||||||
None => (),
|
None => (),
|
||||||
|
|
|
@ -27,6 +27,7 @@ use dom::bindings::js::{JS, JSRef, LayoutJS, RootedReference, Temporary, Root, U
|
||||||
use dom::bindings::js::{TemporaryPushable, OptionalRootedRootable};
|
use dom::bindings::js::{TemporaryPushable, OptionalRootedRootable};
|
||||||
use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS};
|
use dom::bindings::js::{ResultRootable, OptionalRootable, MutNullableJS};
|
||||||
use dom::bindings::trace::JSTraceable;
|
use dom::bindings::trace::JSTraceable;
|
||||||
|
use dom::bindings::trace::RootedVec;
|
||||||
use dom::bindings::utils::{Reflectable, reflect_dom_object};
|
use dom::bindings::utils::{Reflectable, reflect_dom_object};
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
|
@ -407,10 +408,10 @@ impl<'a> Iterator for QuerySelectorIterator<'a> {
|
||||||
pub trait NodeHelpers<'a> {
|
pub trait NodeHelpers<'a> {
|
||||||
fn ancestors(self) -> AncestorIterator<'a>;
|
fn ancestors(self) -> AncestorIterator<'a>;
|
||||||
fn inclusive_ancestors(self) -> AncestorIterator<'a>;
|
fn inclusive_ancestors(self) -> AncestorIterator<'a>;
|
||||||
fn children(self) -> NodeChildrenIterator<'a>;
|
fn children(self) -> NodeChildrenIterator;
|
||||||
fn rev_children(self) -> ReverseChildrenIterator;
|
fn rev_children(self) -> ReverseChildrenIterator;
|
||||||
fn child_elements(self) -> ChildElementIterator<'a>;
|
fn child_elements(self) -> ChildElementIterator<'a>;
|
||||||
fn following_siblings(self) -> NodeChildrenIterator<'a>;
|
fn following_siblings(self) -> NodeChildrenIterator;
|
||||||
fn is_in_doc(self) -> bool;
|
fn is_in_doc(self) -> bool;
|
||||||
fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool;
|
fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool;
|
||||||
fn is_parent_of(self, child: JSRef<Node>) -> bool;
|
fn is_parent_of(self, child: JSRef<Node>) -> bool;
|
||||||
|
@ -478,7 +479,7 @@ pub trait NodeHelpers<'a> {
|
||||||
fn debug_str(self) -> String;
|
fn debug_str(self) -> String;
|
||||||
|
|
||||||
fn traverse_preorder(self) -> TreeIterator<'a>;
|
fn traverse_preorder(self) -> TreeIterator<'a>;
|
||||||
fn inclusively_following_siblings(self) -> NodeChildrenIterator<'a>;
|
fn inclusively_following_siblings(self) -> NodeChildrenIterator;
|
||||||
|
|
||||||
fn to_trusted_node_address(self) -> TrustedNodeAddress;
|
fn to_trusted_node_address(self) -> TrustedNodeAddress;
|
||||||
|
|
||||||
|
@ -502,7 +503,8 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
fn teardown(self) {
|
fn teardown(self) {
|
||||||
self.layout_data.dispose();
|
self.layout_data.dispose();
|
||||||
for kid in self.children() {
|
for kid in self.children() {
|
||||||
kid.teardown();
|
let kid = kid.root();
|
||||||
|
kid.r().teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +525,8 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
|
|
||||||
// FIXME: this should have a pure version?
|
// FIXME: this should have a pure version?
|
||||||
for kid in self.children() {
|
for kid in self.children() {
|
||||||
kid.dump_indent(indent + 1u)
|
let kid = kid.root();
|
||||||
|
kid.r().dump_indent(indent + 1u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,7 +693,8 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
node.set_flag(IS_DIRTY | HAS_DIRTY_SIBLINGS | HAS_DIRTY_DESCENDANTS, true);
|
node.set_flag(IS_DIRTY | HAS_DIRTY_SIBLINGS | HAS_DIRTY_DESCENDANTS, true);
|
||||||
|
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
dirty_subtree(kid);
|
let kid = kid.root();
|
||||||
|
dirty_subtree(kid.r());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +712,8 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for sibling in parent.root().r().children() {
|
for sibling in parent.root().r().children() {
|
||||||
sibling.set_has_dirty_siblings(true);
|
let sibling = sibling.root();
|
||||||
|
sibling.r().set_has_dirty_siblings(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,9 +729,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
TreeIterator::new(self)
|
TreeIterator::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inclusively_following_siblings(self) -> NodeChildrenIterator<'a> {
|
fn inclusively_following_siblings(self) -> NodeChildrenIterator {
|
||||||
NodeChildrenIterator {
|
NodeChildrenIterator {
|
||||||
current: Some(self.clone()),
|
current: Some(Temporary::from_rooted(self)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,9 +739,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
self == parent || parent.ancestors().any(|ancestor| ancestor == self)
|
self == parent || parent.ancestors().any(|ancestor| ancestor == self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn following_siblings(self) -> NodeChildrenIterator<'a> {
|
fn following_siblings(self) -> NodeChildrenIterator {
|
||||||
NodeChildrenIterator {
|
NodeChildrenIterator {
|
||||||
current: self.next_sibling().root().map(|next| next.get_unsound_ref_forever()),
|
current: self.next_sibling(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,9 +838,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
self.owner_doc().root().r().is_html_document()
|
self.owner_doc().root().r().is_html_document()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn children(self) -> NodeChildrenIterator<'a> {
|
fn children(self) -> NodeChildrenIterator {
|
||||||
NodeChildrenIterator {
|
NodeChildrenIterator {
|
||||||
current: self.first_child.get().map(|node| node.root().get_unsound_ref_forever()),
|
current: self.first_child.get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,12 +851,13 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_elements(self) -> ChildElementIterator<'a> {
|
fn child_elements(self) -> ChildElementIterator<'a> {
|
||||||
fn cast(n: JSRef<Node>) -> Option<JSRef<Element>> {
|
fn cast<'a>(n: Temporary<Node>) -> Option<JSRef<'a, Element>> {
|
||||||
ElementCast::to_ref(n)
|
let n = n.root();
|
||||||
|
ElementCast::to_ref(n.get_unsound_ref_forever())
|
||||||
}
|
}
|
||||||
|
|
||||||
self.children()
|
self.children()
|
||||||
.filter_map(cast as fn(JSRef<Node>) -> Option<JSRef<Element>>)
|
.filter_map(cast as fn(_) -> _)
|
||||||
.peekable()
|
.peekable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,20 +1070,23 @@ impl RawLayoutNodeHelpers for Node {
|
||||||
//
|
//
|
||||||
|
|
||||||
pub type ChildElementIterator<'a> =
|
pub type ChildElementIterator<'a> =
|
||||||
Peekable<FilterMap<NodeChildrenIterator<'a>,
|
Peekable<FilterMap<NodeChildrenIterator,
|
||||||
fn(JSRef<Node>) -> Option<JSRef<Element>>>>;
|
fn(Temporary<Node>) -> Option<JSRef<'a, Element>>>>;
|
||||||
|
|
||||||
pub struct NodeChildrenIterator<'a> {
|
pub struct NodeChildrenIterator {
|
||||||
current: Option<JSRef<'a, Node>>,
|
current: Option<Temporary<Node>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for NodeChildrenIterator<'a> {
|
impl Iterator for NodeChildrenIterator {
|
||||||
type Item = JSRef<'a, Node>;
|
type Item = Temporary<Node>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<JSRef<'a, Node>> {
|
fn next(&mut self) -> Option<Temporary<Node>> {
|
||||||
let node = self.current;
|
let current = match self.current.take() {
|
||||||
self.current = node.and_then(|node| node.next_sibling().map(|node| node.root().get_unsound_ref_forever()));
|
None => return None,
|
||||||
node
|
Some(current) => current,
|
||||||
|
}.root();
|
||||||
|
self.current = current.r().next_sibling();
|
||||||
|
Some(Temporary::from_rooted(current.r()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,7 +1280,10 @@ impl Node {
|
||||||
// Step 6.1
|
// Step 6.1
|
||||||
NodeTypeId::DocumentFragment => {
|
NodeTypeId::DocumentFragment => {
|
||||||
// Step 6.1.1(b)
|
// Step 6.1.1(b)
|
||||||
if node.children().any(|c| c.is_text()) {
|
if node.children()
|
||||||
|
.map(|c| c.root())
|
||||||
|
.any(|c| c.r().is_text())
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
match node.child_elements().count() {
|
match node.child_elements().count() {
|
||||||
|
@ -1283,7 +1295,8 @@ impl Node {
|
||||||
}
|
}
|
||||||
if let Some(child) = child {
|
if let Some(child) = child {
|
||||||
if child.inclusively_following_siblings()
|
if child.inclusively_following_siblings()
|
||||||
.any(|child| child.is_doctype()) {
|
.map(|c| c.root())
|
||||||
|
.any(|child| child.r().is_doctype()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1299,21 +1312,27 @@ impl Node {
|
||||||
}
|
}
|
||||||
if let Some(ref child) = child {
|
if let Some(ref child) = child {
|
||||||
if child.inclusively_following_siblings()
|
if child.inclusively_following_siblings()
|
||||||
.any(|child| child.is_doctype()) {
|
.map(|c| c.root())
|
||||||
|
.any(|child| child.r().is_doctype()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Step 6.3
|
// Step 6.3
|
||||||
NodeTypeId::DocumentType => {
|
NodeTypeId::DocumentType => {
|
||||||
if parent.children().any(|c| c.is_doctype()) {
|
if parent.children()
|
||||||
|
.map(|c| c.root())
|
||||||
|
.any(|c| c.r().is_doctype())
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
match child {
|
match child {
|
||||||
Some(ref child) => {
|
Some(child) => {
|
||||||
if parent.children()
|
if parent.children()
|
||||||
.take_while(|c| c != child)
|
.map(|c| c.root())
|
||||||
.any(|c| c.is_element()) {
|
.take_while(|c| c.r() != child)
|
||||||
|
.any(|c| c.r().is_element())
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1386,18 +1405,21 @@ impl Node {
|
||||||
// Step 6: DocumentFragment.
|
// Step 6: DocumentFragment.
|
||||||
let mut kids = Vec::new();
|
let mut kids = Vec::new();
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
kids.push(kid.clone());
|
let kid = kid.root();
|
||||||
Node::remove(kid, node, SuppressObserver::Suppressed);
|
kids.push(Temporary::from_rooted(kid.r()));
|
||||||
|
Node::remove(kid.r(), node, SuppressObserver::Suppressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7: mutation records.
|
// Step 7: mutation records.
|
||||||
// Step 8.
|
// Step 8.
|
||||||
for kid in kids.iter() {
|
for kid in kids.clone().into_iter() {
|
||||||
do_insert((*kid).clone(), parent, child);
|
let kid = kid.root();
|
||||||
|
do_insert(kid.r(), parent, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
for kid in kids.into_iter() {
|
for kid in kids.into_iter() {
|
||||||
fire_observer_if_necessary(kid, suppress_observers);
|
let kid = kid.root();
|
||||||
|
fire_observer_if_necessary(kid.r(), suppress_observers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1425,20 +1447,24 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let removed_nodes: Vec<JSRef<Node>> = parent.children().collect();
|
let mut removed_nodes: RootedVec<JS<Node>> = RootedVec::new();
|
||||||
|
for child in parent.children() {
|
||||||
|
removed_nodes.push(JS::from_rooted(child));
|
||||||
|
}
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
let added_nodes = match node {
|
let added_nodes = match node {
|
||||||
None => vec!(),
|
None => vec!(),
|
||||||
Some(node) => match node.type_id() {
|
Some(node) => match node.type_id() {
|
||||||
NodeTypeId::DocumentFragment => node.children().collect(),
|
NodeTypeId::DocumentFragment => node.children().collect(),
|
||||||
_ => vec!(node.clone()),
|
_ => vec!(Temporary::from_rooted(node)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
for child in parent.children() {
|
for child in parent.children() {
|
||||||
Node::remove(child, parent, SuppressObserver::Suppressed);
|
let child = child.root();
|
||||||
|
Node::remove(child.r(), parent, SuppressObserver::Suppressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5.
|
// Step 5.
|
||||||
|
@ -1452,10 +1478,12 @@ impl Node {
|
||||||
// Step 7.
|
// Step 7.
|
||||||
let parent_in_doc = parent.is_in_doc();
|
let parent_in_doc = parent.is_in_doc();
|
||||||
for removed_node in removed_nodes.iter() {
|
for removed_node in removed_nodes.iter() {
|
||||||
removed_node.node_removed(parent_in_doc);
|
let removed_node = removed_node.root();
|
||||||
|
removed_node.r().node_removed(parent_in_doc);
|
||||||
}
|
}
|
||||||
for added_node in added_nodes.iter() {
|
for added_node in added_nodes {
|
||||||
added_node.node_inserted();
|
let added_node = added_node.root();
|
||||||
|
added_node.r().node_inserted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1596,7 +1624,9 @@ impl Node {
|
||||||
// Step 6.
|
// Step 6.
|
||||||
if clone_children == CloneChildrenFlag::CloneChildren {
|
if clone_children == CloneChildrenFlag::CloneChildren {
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
let child_copy = Node::clone(child, Some(document), clone_children).root();
|
let child = child.root();
|
||||||
|
let child_copy = Node::clone(child.r(), Some(document),
|
||||||
|
clone_children).root();
|
||||||
let _inserted_node = Node::pre_insert(child_copy.r(), copy.r(), None);
|
let _inserted_node = Node::pre_insert(child_copy.r(), copy.r(), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1855,7 +1885,10 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
// Step 6.1
|
// Step 6.1
|
||||||
NodeTypeId::DocumentFragment => {
|
NodeTypeId::DocumentFragment => {
|
||||||
// Step 6.1.1(b)
|
// Step 6.1.1(b)
|
||||||
if node.children().any(|c| c.is_text()) {
|
if node.children()
|
||||||
|
.map(|c| c.root())
|
||||||
|
.any(|c| c.r().is_text())
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
match node.child_elements().count() {
|
match node.child_elements().count() {
|
||||||
|
@ -1866,7 +1899,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
if child.following_siblings()
|
if child.following_siblings()
|
||||||
.any(|child| child.is_doctype()) {
|
.map(|c| c.root())
|
||||||
|
.any(|child| child.r().is_doctype()) {
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1876,22 +1910,31 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
},
|
},
|
||||||
// Step 6.2
|
// Step 6.2
|
||||||
NodeTypeId::Element(..) => {
|
NodeTypeId::Element(..) => {
|
||||||
if self.child_elements().any(|c| NodeCast::from_ref(c) != child) {
|
if self.child_elements()
|
||||||
|
.any(|c| NodeCast::from_ref(c) != child)
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
if child.following_siblings()
|
if child.following_siblings()
|
||||||
.any(|child| child.is_doctype()) {
|
.map(|c| c.root())
|
||||||
|
.any(|child| child.r().is_doctype())
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Step 6.3
|
// Step 6.3
|
||||||
NodeTypeId::DocumentType => {
|
NodeTypeId::DocumentType => {
|
||||||
if self.children().any(|c| c.is_doctype() && c != child) {
|
if self.children()
|
||||||
|
.map(|c| c.root())
|
||||||
|
.any(|c| c.r().is_doctype() && c.r() != child)
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
if self.children()
|
if self.children()
|
||||||
.take_while(|c| *c != child)
|
.map(|c| c.root())
|
||||||
.any(|c| c.is_element()) {
|
.take_while(|c| c.r() != child)
|
||||||
|
.any(|c| c.r().is_element())
|
||||||
|
{
|
||||||
return Err(HierarchyRequest);
|
return Err(HierarchyRequest);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1921,7 +1964,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
Node::adopt(node, document.r());
|
Node::adopt(node, document.r());
|
||||||
|
|
||||||
// Step 12.
|
// Step 12.
|
||||||
let mut nodes: Vec<JSRef<Node>> = vec!();
|
let mut nodes: RootedVec<JS<Node>> = RootedVec::new();
|
||||||
if node.type_id() == NodeTypeId::DocumentFragment {
|
if node.type_id() == NodeTypeId::DocumentFragment {
|
||||||
// Collect fragment children before Step 11,
|
// Collect fragment children before Step 11,
|
||||||
// because Node::insert removes a DocumentFragment's children,
|
// because Node::insert removes a DocumentFragment's children,
|
||||||
|
@ -1929,10 +1972,11 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
// Issue filed against the spec:
|
// Issue filed against the spec:
|
||||||
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=28330
|
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=28330
|
||||||
for child_node in node.children() {
|
for child_node in node.children() {
|
||||||
nodes.push(child_node);
|
let child_node = child_node.root();
|
||||||
|
nodes.push(JS::from_rooted(child_node.r()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodes.push(node);
|
nodes.push(JS::from_rooted(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1945,8 +1989,9 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
|
|
||||||
// Step 13: mutation records.
|
// Step 13: mutation records.
|
||||||
child.node_removed(self.is_in_doc());
|
child.node_removed(self.is_in_doc());
|
||||||
for child_node in nodes {
|
for child_node in &*nodes {
|
||||||
child_node.node_inserted();
|
let child_node = child_node.root();
|
||||||
|
child_node.r().node_inserted();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 14.
|
// Step 14.
|
||||||
|
@ -1961,27 +2006,28 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-node-normalize
|
// http://dom.spec.whatwg.org/#dom-node-normalize
|
||||||
fn Normalize(self) {
|
fn Normalize(self) {
|
||||||
let mut prev_text = None;
|
let mut prev_text: Option<Temporary<Text>> = None;
|
||||||
for child in self.children() {
|
for child in self.children() {
|
||||||
let t: Option<JSRef<Text>> = TextCast::to_ref(child);
|
let child = child.root();
|
||||||
match t {
|
match TextCast::to_ref(child.r()) {
|
||||||
Some(text) => {
|
Some(text) => {
|
||||||
let characterdata: JSRef<CharacterData> = CharacterDataCast::from_ref(text);
|
let characterdata: JSRef<CharacterData> = CharacterDataCast::from_ref(text);
|
||||||
if characterdata.Length() == 0 {
|
if characterdata.Length() == 0 {
|
||||||
self.remove_child(child);
|
self.remove_child(child.r());
|
||||||
} else {
|
} else {
|
||||||
match prev_text {
|
match prev_text {
|
||||||
Some(text_node) => {
|
Some(ref text_node) => {
|
||||||
let prev_characterdata: JSRef<CharacterData> = CharacterDataCast::from_ref(text_node);
|
let text_node = text_node.clone().root();
|
||||||
|
let prev_characterdata: JSRef<CharacterData> = CharacterDataCast::from_ref(text_node.r());
|
||||||
let _ = prev_characterdata.AppendData(characterdata.Data());
|
let _ = prev_characterdata.AppendData(characterdata.Data());
|
||||||
self.remove_child(child);
|
self.remove_child(child.r());
|
||||||
},
|
},
|
||||||
None => prev_text = Some(text)
|
None => prev_text = Some(Temporary::from_rooted(text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
child.Normalize();
|
child.r().Normalize();
|
||||||
prev_text = None;
|
prev_text = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2066,8 +2112,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
this.children().zip(node.children()).all(|(ref child, ref other_child)| {
|
this.children().zip(node.children()).all(|(child, other_child)| {
|
||||||
is_equal_node(*child, *other_child)
|
is_equal_node(child.root().r(), other_child.root().r())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
match maybe_node {
|
match maybe_node {
|
||||||
|
@ -2335,10 +2381,13 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
|
||||||
self.set_enabled_state(false);
|
self.set_enabled_state(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match ancestor.children().find(|child| child.is_htmllegendelement()) {
|
match ancestor.children()
|
||||||
|
.map(|child| child.root())
|
||||||
|
.find(|child| child.r().is_htmllegendelement())
|
||||||
|
{
|
||||||
Some(legend) => {
|
Some(legend) => {
|
||||||
// XXXabinader: should we save previous ancestor to avoid this iteration?
|
// XXXabinader: should we save previous ancestor to avoid this iteration?
|
||||||
if self.ancestors().any(|ancestor| ancestor == legend) { continue; }
|
if self.ancestors().any(|ancestor| ancestor == legend.r()) { continue; }
|
||||||
},
|
},
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,6 @@ impl<'a> NodeListMethods for JSRef<'a, NodeList> {
|
||||||
NodeListType::Children(ref node) => {
|
NodeListType::Children(ref node) => {
|
||||||
let node = node.root();
|
let node = node.root();
|
||||||
node.r().children().nth(index as usize)
|
node.r().children().nth(index as usize)
|
||||||
.map(|child| Temporary::from_rooted(child))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,8 @@ impl<'a> Serializable for JSRef<'a, Node> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for handle in node.children() {
|
for handle in node.children() {
|
||||||
try!(handle.serialize(serializer, IncludeNode));
|
let handle = handle.root();
|
||||||
|
try!(handle.r().serialize(serializer, IncludeNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
if traversal_scope == IncludeNode {
|
if traversal_scope == IncludeNode {
|
||||||
|
@ -212,7 +213,8 @@ impl<'a> Serializable for JSRef<'a, Node> {
|
||||||
|
|
||||||
(ChildrenOnly, NodeTypeId::Document) => {
|
(ChildrenOnly, NodeTypeId::Document) => {
|
||||||
for handle in node.children() {
|
for handle in node.children() {
|
||||||
try!(handle.serialize(serializer, IncludeNode));
|
let handle = handle.root();
|
||||||
|
try!(handle.r().serialize(serializer, IncludeNode));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue