diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2016-11-30 01:23:58 +0100 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2016-12-01 11:55:06 +0100 |
commit | 03e04179ae3907afa2036f1bb02ded79156d12ca (patch) | |
tree | 01ec7dca6d43ec6d879536432a45f0ab7ecd03e4 /components/script/dom | |
parent | ea4fbbc63a8b499683d874633f246b191520f1e2 (diff) | |
download | servo-03e04179ae3907afa2036f1bb02ded79156d12ca.tar.gz servo-03e04179ae3907afa2036f1bb02ded79156d12ca.zip |
Refactor fragment parsing
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/element.rs | 51 | ||||
-rw-r--r-- | components/script/dom/node.rs | 14 | ||||
-rw-r--r-- | components/script/dom/range.rs | 12 | ||||
-rw-r--r-- | components/script/dom/servoparser/mod.rs | 36 |
4 files changed, 67 insertions, 46 deletions
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d8f0dd601a7..4eb53998809 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -30,6 +30,7 @@ use dom::bindings::xmlname::XMLName::InvalidXMLName; use dom::characterdata::CharacterData; use dom::create::create_element; use dom::document::{Document, LayoutDocumentHelpers}; +use dom::documentfragment::DocumentFragment; use dom::domrect::DOMRect; use dom::domrectlist::DOMRectList; use dom::domtokenlist::DOMTokenList; @@ -61,6 +62,7 @@ use dom::node::{CLICK_IN_PROGRESS, ChildrenMutation, LayoutNodeHelpers, Node}; use dom::node::{NodeDamage, SEQUENTIALLY_FOCUSABLE, UnbindContext}; use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; +use dom::servoparser::ServoParser; use dom::text::Text; use dom::validation::Validatable; use dom::virtualmethods::{VirtualMethods, vtable_for}; @@ -1230,6 +1232,37 @@ impl Element { // Step 11 win.scroll_node(node.to_trusted_node_address(), x, y, behavior); } + + // https://w3c.github.io/DOM-Parsing/#parsing + pub fn parse_fragment(&self, markup: DOMString) -> Fallible<Root<DocumentFragment>> { + // Steps 1-2. + let context_document = document_from_node(self); + let new_children = if context_document.is_html_document() { + ServoParser::parse_html_fragment(self, markup) + } else { + // FIXME: XML case + unimplemented!() + }; + // Step 3. + let fragment = DocumentFragment::new(&context_document); + // Step 4. + for child in new_children { + fragment.upcast::<Node>().AppendChild(&child).unwrap(); + } + // Step 5. + Ok(fragment) + } + + pub fn fragment_parsing_context(owner_doc: &Document, element: Option<&Self>) -> Root<Self> { + match element { + Some(elem) if elem.local_name() != &local_name!("html") || !elem.html_element_in_html_document() => { + Root::from_ref(elem) + }, + _ => { + Root::upcast(HTMLBodyElement::new(local_name!("body"), None, owner_doc)) + } + } + } } impl ElementMethods for Element { @@ -1757,15 +1790,14 @@ impl ElementMethods for Element { /// https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML fn SetInnerHTML(&self, value: DOMString) -> ErrorResult { - let context_node = self.upcast::<Node>(); // Step 1. - let frag = try!(context_node.parse_fragment(value)); + let frag = try!(self.parse_fragment(value)); // Step 2. // https://github.com/w3c/DOM-Parsing/issues/1 let target = if let Some(template) = self.downcast::<HTMLTemplateElement>() { Root::upcast(template.Content()) } else { - Root::from_ref(context_node) + Root::from_ref(self.upcast()) }; Node::replace_all(Some(frag.upcast()), &target); Ok(()) @@ -1776,7 +1808,7 @@ impl ElementMethods for Element { self.serialize(IncludeNode) } - // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML + // https://w3c.github.io/DOM-Parsing/#dom-element-outerhtml fn SetOuterHTML(&self, value: DOMString) -> ErrorResult { let context_document = document_from_node(self); let context_node = self.upcast::<Node>(); @@ -1800,7 +1832,7 @@ impl ElementMethods for Element { ElementCreator::ScriptCreated); Root::upcast(body_elem) }, - _ => context_node.GetParentNode().unwrap() + _ => context_node.GetParentElement().unwrap() }; // Step 5. @@ -1957,14 +1989,11 @@ impl ElementMethods for Element { }; // Step 2. - let context = match context.downcast::<Element>() { - Some(elem) if elem.local_name() != &local_name!("html") || - !elem.html_element_in_html_document() => Root::from_ref(elem), - _ => Root::upcast(HTMLBodyElement::new(local_name!("body"), None, &*context.owner_doc())), - }; + let context = Element::fragment_parsing_context( + &context.owner_doc(), context.downcast::<Element>()); // Step 3. - let fragment = try!(context.upcast::<Node>().parse_fragment(text)); + let fragment = try!(context.parse_fragment(text)); // Step 4. self.insert_adjacent(position, fragment.upcast()).map(|_| ()) diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 983e2e8d403..2985ad80cb3 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -51,7 +51,6 @@ use dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHel use dom::nodelist::NodeList; use dom::processinginstruction::ProcessingInstruction; use dom::range::WeakRangeVec; -use dom::servoparser::ServoParser; use dom::svgsvgelement::{SVGSVGElement, LayoutSVGSVGElementHelpers}; use dom::text::Text; use dom::virtualmethods::{VirtualMethods, vtable_for}; @@ -799,19 +798,6 @@ impl Node { } } - // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#dfn-concept-parse-fragment - pub fn parse_fragment(&self, markup: DOMString) -> Fallible<Root<DocumentFragment>> { - let context_document = document_from_node(self); - let fragment = DocumentFragment::new(&context_document); - if context_document.is_html_document() { - ServoParser::parse_html_fragment(self.upcast(), markup, fragment.upcast()); - } else { - // FIXME: XML case - unimplemented!(); - } - Ok(fragment) - } - /// Used by `HTMLTableSectionElement::InsertRow` and `HTMLTableRowElement::InsertCell` pub fn insert_cell_or_row<F, G, I>(&self, index: i32, get_items: F, new_child: G) -> Fallible<Root<HTMLElement>> where F: Fn() -> Root<HTMLCollection>, diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index 0a5ab7a66df..b2507aeab3b 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -22,7 +22,6 @@ use dom::characterdata::CharacterData; use dom::document::Document; use dom::documentfragment::DocumentFragment; use dom::element::Element; -use dom::htmlbodyelement::HTMLBodyElement; use dom::htmlscriptelement::HTMLScriptElement; use dom::node::{Node, UnbindContext}; use dom::text::Text; @@ -901,6 +900,7 @@ impl RangeMethods for Range { fn CreateContextualFragment(&self, fragment: DOMString) -> Fallible<Root<DocumentFragment>> { // Step 1. let node = self.StartContainer(); + let owner_doc = node.owner_doc(); let element = match node.type_id() { NodeTypeId::Document(_) | NodeTypeId::DocumentFragment => None, NodeTypeId::Element(_) => Some(Root::downcast::<Element>(node).unwrap()), @@ -911,15 +911,7 @@ impl RangeMethods for Range { }; // Step 2. - let should_create_body = element.as_ref().map_or(true, |elem| { - let elem = elem.downcast::<Element>().unwrap(); - elem.local_name() == &local_name!("html") && elem.html_element_in_html_document() - }); - let element: Root<Node> = if should_create_body { - Root::upcast(HTMLBodyElement::new(local_name!("body"), None, &self.StartContainer().owner_doc())) - } else { - Root::upcast(element.unwrap()) - }; + let element = Element::fragment_parsing_context(&owner_doc, element.r()); // Step 3. let fragment_node = try!(element.parse_fragment(fragment)); diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index ff90674c1d2..c6f4364925b 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -14,11 +14,12 @@ use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::document::{Document, DocumentSource, IsHTMLDocument}; +use dom::element::Element; use dom::globalscope::GlobalScope; use dom::htmlformelement::HTMLFormElement; use dom::htmlimageelement::HTMLImageElement; use dom::htmlscriptelement::HTMLScriptElement; -use dom::node::{Node, document_from_node, window_from_node}; +use dom::node::{Node, NodeSiblingIterator}; use encoding::all::UTF_8; use encoding::types::{DecoderTrap, Encoding}; use html5ever::tokenizer::buffer_queue::BufferQueue; @@ -96,17 +97,15 @@ impl ServoParser { } // https://html.spec.whatwg.org/multipage/#parsing-html-fragments - pub fn parse_html_fragment( - context_node: &Node, - input: DOMString, - output: &Node) { - let window = window_from_node(context_node); - let context_document = document_from_node(context_node); + pub fn parse_html_fragment(context: &Element, input: DOMString) -> FragmentParsingResult { + let context_node = context.upcast::<Node>(); + let context_document = context_node.owner_doc(); + let window = context_document.window(); let url = context_document.url(); // Step 1. let loader = DocumentLoader::new(&*context_document.loader()); - let document = Document::new(&window, None, Some(url.clone()), + let document = Document::new(window, None, Some(url.clone()), IsHTMLDocument::HTMLDocument, None, None, DocumentSource::FromParser, @@ -134,9 +133,7 @@ impl ServoParser { // Step 14. let root_element = document.GetDocumentElement().expect("no document element"); - for child in root_element.upcast::<Node>().children() { - output.AppendChild(&child).unwrap(); - } + FragmentParsingResult { inner: root_element.upcast::<Node>().children() } } pub fn parse_xml_document( @@ -349,6 +346,23 @@ impl ServoParser { } } +pub struct FragmentParsingResult { + inner: NodeSiblingIterator, +} + +impl Iterator for FragmentParsingResult { + type Item = Root<Node>; + + fn next(&mut self) -> Option<Root<Node>> { + let next = match self.inner.next() { + Some(next) => next, + None => return None, + }; + next.remove_self(); + Some(next) + } +} + #[derive(HeapSizeOf, JSTraceable)] #[must_root] enum Tokenizer { |