aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/servoparser/xml.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2016-10-10 17:07:08 +0200
committerAnthony Ramine <n.oxyde@gmail.com>2016-10-11 16:42:01 +0200
commit4b813e0bdc4c7e908a9ce3f145cf453c4778e2b9 (patch)
tree7e832207a3a3a3be65fb89d8ab62f80912c09a36 /components/script/dom/servoparser/xml.rs
parent1405be691776e48836f651c3c616dc12322a0932 (diff)
downloadservo-4b813e0bdc4c7e908a9ce3f145cf453c4778e2b9.tar.gz
servo-4b813e0bdc4c7e908a9ce3f145cf453c4778e2b9.zip
Merge script::parse and script::dom::servoparser
Diffstat (limited to 'components/script/dom/servoparser/xml.rs')
-rw-r--r--components/script/dom/servoparser/xml.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs
new file mode 100644
index 00000000000..0713fa5c58a
--- /dev/null
+++ b/components/script/dom/servoparser/xml.rs
@@ -0,0 +1,147 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#![allow(unrooted_must_root)]
+
+use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{JS, Root};
+use dom::bindings::str::DOMString;
+use dom::comment::Comment;
+use dom::document::Document;
+use dom::documenttype::DocumentType;
+use dom::element::{Element, ElementCreator};
+use dom::htmlscriptelement::HTMLScriptElement;
+use dom::node::Node;
+use dom::processinginstruction::ProcessingInstruction;
+use dom::text::Text;
+use html5ever;
+use msg::constellation_msg::PipelineId;
+use std::borrow::Cow;
+use string_cache::{Atom, QualName, Namespace};
+use super::{LastChunkState, ServoParser, Sink, Tokenizer};
+use url::Url;
+use xml5ever::tendril::StrTendril;
+use xml5ever::tokenizer::{Attribute, QName, XmlTokenizer};
+use xml5ever::tree_builder::{NextParserState, NodeOrText, TreeSink, XmlTreeBuilder};
+
+impl<'a> TreeSink for Sink {
+ type Handle = JS<Node>;
+
+ fn parse_error(&mut self, msg: Cow<'static, str>) {
+ debug!("Parse error: {}", msg);
+ }
+
+ fn get_document(&mut self) -> JS<Node> {
+ JS::from_ref(self.document.upcast())
+ }
+
+ fn elem_name(&self, target: &JS<Node>) -> QName {
+ let elem = target.downcast::<Element>()
+ .expect("tried to get name of non-Element in XML parsing");
+ QName {
+ prefix: elem.prefix().as_ref().map_or(atom!(""), |p| Atom::from(&**p)),
+ namespace_url: elem.namespace().0.clone(),
+ local: elem.local_name().clone(),
+ }
+ }
+
+ fn create_element(&mut self, name: QName, attrs: Vec<Attribute>)
+ -> JS<Node> {
+ let prefix = if name.prefix == atom!("") { None } else { Some(name.prefix) };
+ let name = QualName {
+ ns: Namespace(name.namespace_url),
+ local: name.local,
+ };
+ let elem = Element::create(name, prefix, &*self.document,
+ ElementCreator::ParserCreated);
+
+ for attr in attrs {
+ let name = QualName {
+ ns: Namespace(attr.name.namespace_url),
+ local: attr.name.local,
+ };
+ elem.set_attribute_from_parser(name, DOMString::from(String::from(attr.value)), None);
+ }
+
+ JS::from_ref(elem.upcast())
+ }
+
+ fn create_comment(&mut self, text: StrTendril) -> JS<Node> {
+ let comment = Comment::new(DOMString::from(String::from(text)), &*self.document);
+ JS::from_ref(comment.upcast())
+ }
+
+ fn append(&mut self, parent: JS<Node>, child: NodeOrText<JS<Node>>) {
+ let child = match child {
+ NodeOrText::AppendNode(n) => Root::from_ref(&*n),
+ NodeOrText::AppendText(t) => {
+ let s: String = t.into();
+ let text = Text::new(DOMString::from(s), &self.document);
+ Root::upcast(text)
+ }
+ };
+ assert!(parent.AppendChild(child.r()).is_ok());
+ }
+
+ fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril,
+ system_id: StrTendril) {
+ let doc = &*self.document;
+ let doctype = DocumentType::new(
+ DOMString::from(String::from(name)), Some(DOMString::from(String::from(public_id))),
+ Some(DOMString::from(String::from(system_id))), doc);
+ doc.upcast::<Node>().AppendChild(doctype.upcast()).expect("Appending failed");
+ }
+
+ fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> JS<Node> {
+ let doc = &*self.document;
+ let pi = ProcessingInstruction::new(
+ DOMString::from(String::from(target)), DOMString::from(String::from(data)),
+ doc);
+ JS::from_ref(pi.upcast())
+ }
+
+ fn mark_script_already_started(&mut self, node: Self::Handle) {
+ let script = node.downcast::<HTMLScriptElement>();
+ if let Some(script) = script {
+ script.set_already_started(true);
+ }
+ }
+
+ fn complete_script(&mut self, node: Self::Handle) -> NextParserState {
+ let script = node.downcast::<HTMLScriptElement>();
+ if let Some(script) = script {
+ return match script.prepare() {
+ html5ever::tree_builder::NextParserState::Continue => NextParserState::Continue,
+ html5ever::tree_builder::NextParserState::Suspend => NextParserState::Suspend
+ };
+ }
+ NextParserState::Continue
+ }
+}
+
+
+pub enum ParseContext {
+ Owner(Option<PipelineId>)
+}
+
+
+pub fn parse_xml(document: &Document,
+ input: DOMString,
+ url: Url,
+ context: ParseContext) {
+ let parser = match context {
+ ParseContext::Owner(owner) => {
+ let tb = XmlTreeBuilder::new(Sink {
+ base_url: url,
+ document: JS::from_ref(document),
+ });
+ let tok = XmlTokenizer::new(tb, Default::default());
+
+ ServoParser::new(
+ document, owner, Tokenizer::XML(tok), LastChunkState::NotReceived)
+ }
+ };
+ parser.parse_chunk(String::from(input));
+}