aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2016-11-30 01:23:58 +0100
committerAnthony Ramine <n.oxyde@gmail.com>2016-12-01 11:55:06 +0100
commit03e04179ae3907afa2036f1bb02ded79156d12ca (patch)
tree01ec7dca6d43ec6d879536432a45f0ab7ecd03e4 /components/script/dom
parentea4fbbc63a8b499683d874633f246b191520f1e2 (diff)
downloadservo-03e04179ae3907afa2036f1bb02ded79156d12ca.tar.gz
servo-03e04179ae3907afa2036f1bb02ded79156d12ca.zip
Refactor fragment parsing
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/element.rs51
-rw-r--r--components/script/dom/node.rs14
-rw-r--r--components/script/dom/range.rs12
-rw-r--r--components/script/dom/servoparser/mod.rs36
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 {