Auto merge of #5541 - nox:node-iterators-temporary, r=jdm

This commit is contained in:
bors-servo 2015-04-07 10:22:10 -05:00
commit e57630711f
11 changed files with 120 additions and 82 deletions

View file

@ -5408,6 +5408,16 @@ impl ${name}Cast {
} }
} }
#[inline(always)]
pub fn to_temporary<T: ${toBound}+Reflectable>(base: Temporary<T>) -> Option<Temporary<${name}>> {
let base = base.root();
let base = base.r();
match base.${checkFn}() {
true => Some(Temporary::from_rooted(unsafe { base.transmute() })),
false => None
}
}
#[inline(always)] #[inline(always)]
pub fn from_ref<'a, T: ${fromBound}+Reflectable>(derived: JSRef<'a, T>) -> JSRef<'a, ${name}> { pub fn from_ref<'a, T: ${fromBound}+Reflectable>(derived: JSRef<'a, T>) -> JSRef<'a, ${name}> {
unsafe { derived.transmute() } unsafe { derived.transmute() }

View file

@ -506,20 +506,17 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
}.root(); }.root();
let el = match ElementCast::to_ref(node.r()) { let el = match ElementCast::to_ref(node.r()) {
Some(el) => el, Some(el) => Temporary::from_rooted(el),
None => { None => {
let ancestor = node.r() let parent = node.r().parent_node();
.ancestors() match parent.and_then(ElementCast::to_temporary) {
.filter_map(ElementCast::to_ref) Some(parent) => parent,
.next();
match ancestor {
Some(ancestor) => ancestor,
None => return, None => return,
} }
}, },
}; }.root();
let node: JSRef<Node> = NodeCast::from_ref(el); let node: JSRef<Node> = NodeCast::from_ref(el.r());
debug!("clicked on {:?}", node.debug_str()); debug!("clicked on {:?}", node.debug_str());
// Prevent click event if form control element is disabled. // Prevent click event if form control element is disabled.
if node.click_event_filter_by_disabled_state() { if node.click_event_filter_by_disabled_state() {
@ -548,7 +545,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events
event.set_trusted(true); event.set_trusted(true);
// https://html.spec.whatwg.org/multipage/interaction.html#run-authentic-click-activation-steps // https://html.spec.whatwg.org/multipage/interaction.html#run-authentic-click-activation-steps
el.authentic_click_activation(event); el.r().authentic_click_activation(event);
self.commit_focus_transaction(); self.commit_focus_transaction();
window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent); window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent);
@ -563,7 +560,10 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let mouse_over_targets: Vec<JS<Node>> = mouse_over_addresses.iter() let mouse_over_targets: Vec<JS<Node>> = mouse_over_addresses.iter()
.filter_map(|node_address| { .filter_map(|node_address| {
let node = node::from_untrusted_node_address(js_runtime, *node_address); let node = node::from_untrusted_node_address(js_runtime, *node_address);
node.root().r().inclusive_ancestors().find(|node| node.is_element()).map(JS::from_rooted) node.root().r().inclusive_ancestors()
.map(|node| node.root())
.find(|node| node.r().is_element())
.map(|node| JS::from_rooted(node.r()))
}).collect(); }).collect();
// Remove hover from any elements in the previous list that are no longer // Remove hover from any elements in the previous list that are no longer
@ -927,7 +927,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
// http://dom.spec.whatwg.org/#dom-document-documentelement // http://dom.spec.whatwg.org/#dom-document-documentelement
fn GetDocumentElement(self) -> Option<Temporary<Element>> { fn GetDocumentElement(self) -> Option<Temporary<Element>> {
let node: JSRef<Node> = NodeCast::from_ref(self); let node: JSRef<Node> = NodeCast::from_ref(self);
node.child_elements().next().map(Temporary::from_rooted) node.child_elements().next()
} }
// http://dom.spec.whatwg.org/#dom-document-getelementsbytagname // http://dom.spec.whatwg.org/#dom-document-getelementsbytagname

View file

@ -28,7 +28,7 @@ use dom::bindings::error::Error;
use dom::bindings::error::Error::{InvalidCharacter, Syntax}; use dom::bindings::error::Error::{InvalidCharacter, Syntax};
use dom::bindings::error::Error::NoModificationAllowed; use dom::bindings::error::Error::NoModificationAllowed;
use dom::bindings::js::{MutNullableJS, JS, JSRef, LayoutJS, Temporary, TemporaryPushable}; use dom::bindings::js::{MutNullableJS, JS, JSRef, LayoutJS, Temporary, TemporaryPushable};
use dom::bindings::js::OptionalRootable; use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::bindings::trace::RootedVec; use dom::bindings::trace::RootedVec;
use dom::bindings::utils::xml_name_type; use dom::bindings::utils::xml_name_type;
use dom::bindings::utils::XMLName::{QName, Name, InvalidXMLName}; use dom::bindings::utils::XMLName::{QName, Name, InvalidXMLName};
@ -595,8 +595,8 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
// https://html.spec.whatwg.org/multipage/infrastructure.html#root-element // https://html.spec.whatwg.org/multipage/infrastructure.html#root-element
fn get_root_element(self) -> Option<Temporary<Element>> { fn get_root_element(self) -> Option<Temporary<Element>> {
let node: JSRef<Node> = NodeCast::from_ref(self); let node: JSRef<Node> = NodeCast::from_ref(self);
match node.ancestors().last().map(ElementCast::to_ref) { match node.ancestors().last().map(ElementCast::to_temporary) {
Some(n) => n.map(Temporary::from_rooted), Some(n) => n,
None => Some(self).map(Temporary::from_rooted), None => Some(self).map(Temporary::from_rooted),
} }
} }
@ -1258,10 +1258,15 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
Err(()) => Err(Syntax), Err(()) => Err(Syntax),
Ok(ref selectors) => { Ok(ref selectors) => {
let root: JSRef<Node> = NodeCast::from_ref(self); let root: JSRef<Node> = NodeCast::from_ref(self);
Ok(root.inclusive_ancestors() for element in root.inclusive_ancestors() {
.filter_map(ElementCast::to_ref) let element = element.root();
.find(|element| matches(selectors, &NodeCast::from_ref(*element), &mut None)) if let Some(element) = ElementCast::to_ref(element.r()) {
.map(Temporary::from_rooted)) if matches(selectors, &NodeCast::from_ref(element), &mut None) {
return Ok(Some(Temporary::from_rooted(element)));
}
}
}
Ok(None)
} }
} }
} }
@ -1599,13 +1604,15 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> {
Some(el) => Some(Temporary::from_rooted(el.as_element().root().r())), Some(el) => Some(Temporary::from_rooted(el.as_element().root().r())),
None => { None => {
let node: JSRef<Node> = NodeCast::from_ref(self); let node: JSRef<Node> = NodeCast::from_ref(self);
node.ancestors() for node in node.ancestors() {
.filter_map(|node| { let node = node.root();
let e: Option<JSRef<Element>> = ElementCast::to_ref(node); if let Some(node) = ElementCast::to_ref(node.r()) {
e if node.as_maybe_activatable().is_some() {
}) return Some(Temporary::from_rooted(node))
.filter(|e| e.as_maybe_activatable().is_some()).next() }
.map(|r| Temporary::from_rooted(r)) }
}
None
} }
} }
} }

View file

@ -31,7 +31,8 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new(); let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new();
if let Some(target_node) = NodeCast::to_ref(target) { if let Some(target_node) = NodeCast::to_ref(target) {
for ancestor in target_node.ancestors() { for ancestor in target_node.ancestors() {
let ancestor_target: JSRef<EventTarget> = EventTargetCast::from_ref(ancestor); let ancestor = ancestor.root();
let ancestor_target = EventTargetCast::from_ref(ancestor.r());
chain.push(JS::from_rooted(ancestor_target)) chain.push(JS::from_rooted(ancestor_target))
} }
} }

View file

@ -161,7 +161,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node: JSRef<Node> = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
node.check_disabled_attribute(); node.check_disabled_attribute();

View file

@ -258,7 +258,7 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
if child.get_disabled_state() { if child.get_disabled_state() {
return None; return None;
} }
if child.ancestors().any(|a| a.type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDataListElement))) { if child.ancestors().any(|a| a.root().r().type_id() == NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDataListElement))) {
return None; return None;
} }
// XXXManishearth don't include it if it is a button but not the submitter // XXXManishearth don't include it if it is a button but not the submitter
@ -531,8 +531,13 @@ pub trait FormControl<'a> : Copy + Sized {
} }
} }
let node: JSRef<Node> = NodeCast::from_ref(elem); let node: JSRef<Node> = NodeCast::from_ref(elem);
node.ancestors().filter_map(|a| HTMLFormElementCast::to_ref(a)).next() for ancestor in node.ancestors() {
.map(Temporary::from_rooted) let ancestor = ancestor.root();
if let Some(ancestor) = HTMLFormElementCast::to_ref(ancestor.r()) {
return Some(Temporary::from_rooted(ancestor))
}
}
None
} }
fn get_form_attribute<InputFn, OwnerFn>(self, fn get_form_attribute<InputFn, OwnerFn>(self,

View file

@ -583,7 +583,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node: JSRef<Node> = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
node.check_disabled_attribute(); node.check_disabled_attribute();

View file

@ -129,7 +129,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLSelectElement> {
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node: JSRef<Node> = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
node.check_disabled_attribute(); node.check_disabled_attribute();

View file

@ -319,7 +319,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTextAreaElement> {
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node: JSRef<Node> = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
node.check_disabled_attribute(); node.check_disabled_attribute();

View file

@ -409,11 +409,11 @@ impl<'a> Iterator for QuerySelectorIterator<'a> {
} }
pub trait NodeHelpers<'a> { pub trait NodeHelpers<'a> {
fn ancestors(self) -> AncestorIterator<'a>; fn ancestors(self) -> AncestorIterator;
fn inclusive_ancestors(self) -> AncestorIterator<'a>; fn inclusive_ancestors(self) -> AncestorIterator;
fn children(self) -> NodeChildrenIterator; 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;
fn following_siblings(self) -> NodeChildrenIterator; 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;
@ -735,8 +735,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
// 4. Dirty ancestors. // 4. Dirty ancestors.
for ancestor in self.ancestors() { for ancestor in self.ancestors() {
if !force_ancestors && ancestor.get_has_dirty_descendants() { break } let ancestor = ancestor.root();
ancestor.set_has_dirty_descendants(true); if !force_ancestors && ancestor.r().get_has_dirty_descendants() { break }
ancestor.r().set_has_dirty_descendants(true);
} }
} }
@ -752,7 +753,7 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
} }
fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool { fn is_inclusive_ancestor_of(self, parent: JSRef<Node>) -> bool {
self == parent || parent.ancestors().any(|ancestor| ancestor == self) self == parent || parent.ancestors().any(|ancestor| ancestor.root().r() == self)
} }
fn following_siblings(self) -> NodeChildrenIterator { fn following_siblings(self) -> NodeChildrenIterator {
@ -788,7 +789,8 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
Err(()) => return Err(Syntax), Err(()) => return Err(Syntax),
// Step 3. // Step 3.
Ok(ref selectors) => { Ok(ref selectors) => {
let root = self.ancestors().last().unwrap_or(self.clone()); let root = self.ancestors().last().root();
let root = root.r().unwrap_or(self.clone());
Ok(root.traverse_preorder() Ok(root.traverse_preorder()
.filter_map(ElementCast::to_ref) .filter_map(ElementCast::to_ref)
.find(|element| matches(selectors, &NodeCast::from_ref(*element), &mut None)) .find(|element| matches(selectors, &NodeCast::from_ref(*element), &mut None))
@ -805,7 +807,9 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
-> Fallible<QuerySelectorIterator<'a>> { -> Fallible<QuerySelectorIterator<'a>> {
// Step 1. // Step 1.
let nodes; let nodes;
let root = self.ancestors().last().unwrap_or(self.clone()); let root = self.ancestors().last().root()
.map(|node| node.get_unsound_ref_forever())
.unwrap_or(self.clone());
match parse_author_origin_selector_list_from_str(selectors.as_slice()) { match parse_author_origin_selector_list_from_str(selectors.as_slice()) {
// Step 2. // Step 2.
Err(()) => return Err(Syntax), Err(()) => return Err(Syntax),
@ -830,15 +834,15 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
} }
fn ancestors(self) -> AncestorIterator<'a> { fn ancestors(self) -> AncestorIterator {
AncestorIterator { AncestorIterator {
current: self.parent_node.get().map(|node| node.root().get_unsound_ref_forever()), current: self.parent_node()
} }
} }
fn inclusive_ancestors(self) -> AncestorIterator<'a> { fn inclusive_ancestors(self) -> AncestorIterator {
AncestorIterator { AncestorIterator {
current: Some(self.clone()) current: Some(Temporary::from_rooted(self))
} }
} }
@ -862,18 +866,13 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
fn rev_children(self) -> ReverseChildrenIterator { fn rev_children(self) -> ReverseChildrenIterator {
ReverseChildrenIterator { ReverseChildrenIterator {
current: self.last_child.get().root(), current: self.last_child(),
} }
} }
fn child_elements(self) -> ChildElementIterator<'a> { fn child_elements(self) -> ChildElementIterator {
fn cast<'a>(n: Temporary<Node>) -> Option<JSRef<'a, Element>> {
let n = n.root();
ElementCast::to_ref(n.get_unsound_ref_forever())
}
self.children() self.children()
.filter_map(cast as fn(_) -> _) .filter_map(ElementCast::to_temporary as fn(_) -> _)
.peekable() .peekable()
} }
@ -1110,9 +1109,9 @@ impl RawLayoutNodeHelpers for Node {
// Iteration and traversal // Iteration and traversal
// //
pub type ChildElementIterator<'a> = pub type ChildElementIterator =
Peekable<FilterMap<NodeChildrenIterator, Peekable<FilterMap<NodeChildrenIterator,
fn(Temporary<Node>) -> Option<JSRef<'a, Element>>>>; fn(Temporary<Node>) -> Option<Temporary<Element>>>>;
pub struct NodeChildrenIterator { pub struct NodeChildrenIterator {
current: Option<Temporary<Node>>, current: Option<Temporary<Node>>,
@ -1132,30 +1131,36 @@ impl Iterator for NodeChildrenIterator {
} }
pub struct ReverseChildrenIterator { pub struct ReverseChildrenIterator {
current: Option<Root<Node>>, current: Option<Temporary<Node>>,
} }
impl Iterator for ReverseChildrenIterator { impl Iterator for ReverseChildrenIterator {
type Item = Temporary<Node>; type Item = Temporary<Node>;
fn next(&mut self) -> Option<Temporary<Node>> { fn next(&mut self) -> Option<Temporary<Node>> {
let node = self.current.r().map(Temporary::from_rooted); let current = match self.current.take() {
self.current = self.current.take().and_then(|node| node.r().prev_sibling()).root(); None => return None,
node Some(current) => current,
}.root();
self.current = current.r().prev_sibling();
Some(Temporary::from_rooted(current.r()))
} }
} }
pub struct AncestorIterator<'a> { pub struct AncestorIterator {
current: Option<JSRef<'a, Node>>, current: Option<Temporary<Node>>,
} }
impl<'a> Iterator for AncestorIterator<'a> { impl Iterator for AncestorIterator {
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.parent_node().map(|node| node.root().get_unsound_ref_forever())); None => return None,
node Some(current) => current,
}.root();
self.current = current.r().parent_node();
Some(Temporary::from_rooted(current.r()))
} }
} }
@ -1936,7 +1941,9 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
0 => (), 0 => (),
// Step 6.1.2 // Step 6.1.2
1 => { 1 => {
if self.child_elements().any(|c| NodeCast::from_ref(c) != child) { if self.child_elements()
.map(|c| c.root())
.any(|c| NodeCast::from_ref(c.r()) != child) {
return Err(HierarchyRequest); return Err(HierarchyRequest);
} }
if child.following_siblings() if child.following_siblings()
@ -1952,8 +1959,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// Step 6.2 // Step 6.2
NodeTypeId::Element(..) => { NodeTypeId::Element(..) => {
if self.child_elements() if self.child_elements()
.any(|c| NodeCast::from_ref(c) != child) .map(|c| c.root())
{ .any(|c| NodeCast::from_ref(c.r()) != child) {
return Err(HierarchyRequest); return Err(HierarchyRequest);
} }
if child.following_siblings() if child.following_siblings()
@ -2171,23 +2178,25 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
// step 2. // step 2.
0 0
} else { } else {
let mut lastself = self.clone(); let mut lastself = Temporary::from_rooted(self.clone());
let mut lastother = other.clone(); let mut lastother = Temporary::from_rooted(other.clone());
for ancestor in self.ancestors() { for ancestor in self.ancestors() {
if ancestor == other { let ancestor = ancestor.root();
if ancestor.r() == other {
// step 4. // step 4.
return NodeConstants::DOCUMENT_POSITION_CONTAINS + return NodeConstants::DOCUMENT_POSITION_CONTAINS +
NodeConstants::DOCUMENT_POSITION_PRECEDING; NodeConstants::DOCUMENT_POSITION_PRECEDING;
} }
lastself = ancestor.clone(); lastself = Temporary::from_rooted(ancestor.r());
} }
for ancestor in other.ancestors() { for ancestor in other.ancestors() {
if ancestor == self { let ancestor = ancestor.root();
if ancestor.r() == self {
// step 5. // step 5.
return NodeConstants::DOCUMENT_POSITION_CONTAINED_BY + return NodeConstants::DOCUMENT_POSITION_CONTAINED_BY +
NodeConstants::DOCUMENT_POSITION_FOLLOWING; NodeConstants::DOCUMENT_POSITION_FOLLOWING;
} }
lastother = ancestor.clone(); lastother = Temporary::from_rooted(ancestor.r());
} }
if lastself != lastother { if lastself != lastother {
@ -2205,7 +2214,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; NodeConstants::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
} }
for child in lastself.traverse_preorder() { let lastself = lastself.root();
for child in lastself.r().traverse_preorder() {
if child == other { if child == other {
// step 6. // step 6.
return NodeConstants::DOCUMENT_POSITION_PRECEDING; return NodeConstants::DOCUMENT_POSITION_PRECEDING;
@ -2415,7 +2425,10 @@ pub trait DisabledStateHelpers {
impl<'a> DisabledStateHelpers for JSRef<'a, Node> { impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
fn check_ancestors_disabled_state_for_form_control(self) { fn check_ancestors_disabled_state_for_form_control(self) {
if self.get_disabled_state() { return; } if self.get_disabled_state() { return; }
for ancestor in self.ancestors().filter(|ancestor| ancestor.is_htmlfieldsetelement()) { for ancestor in self.ancestors() {
let ancestor = ancestor.root();
let ancestor = ancestor.r();
if !ancestor.is_htmlfieldsetelement() { continue; }
if !ancestor.get_disabled_state() { continue; } if !ancestor.get_disabled_state() { continue; }
if ancestor.is_parent_of(self) { if ancestor.is_parent_of(self) {
self.set_disabled_state(true); self.set_disabled_state(true);
@ -2428,7 +2441,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
{ {
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.r()) { continue; } if self.ancestors().any(|ancestor| ancestor.root().r() == legend.r()) { continue; }
}, },
None => () None => ()
} }

View file

@ -12,6 +12,7 @@ use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, TextCast, CommentCa
use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast; use dom::bindings::codegen::InheritTypes::ProcessingInstructionCast;
use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived; use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
use dom::bindings::js::RootedReference;
use dom::bindings::trace::RootedVec; use dom::bindings::trace::RootedVec;
use dom::comment::Comment; use dom::comment::Comment;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
@ -350,10 +351,11 @@ pub fn parse_html_fragment(context_node: JSRef<Node>,
// Step 11. // Step 11.
let form = context_node.inclusive_ancestors() let form = context_node.inclusive_ancestors()
.find(|element| element.is_htmlformelement()); .map(|element| element.root())
.find(|element| element.r().is_htmlformelement());
let fragment_context = FragmentContext { let fragment_context = FragmentContext {
context_elem: context_node, context_elem: context_node,
form_elem: form, form_elem: form.r(),
}; };
parse_html(document.r(), HTMLInput::InputString(input), &url, Some(fragment_context)); parse_html(document.r(), HTMLInput::InputString(input), &url, Some(fragment_context));