aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/servohtmlparser.rs6
-rw-r--r--components/script/dom/servoxmlparser.rs62
-rw-r--r--components/script/parse/xml.rs29
-rw-r--r--components/script/script_task.rs33
4 files changed, 95 insertions, 35 deletions
diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs
index 500fd46d6e6..6584dbe5cb5 100644
--- a/components/script/dom/servohtmlparser.rs
+++ b/components/script/dom/servohtmlparser.rs
@@ -268,7 +268,10 @@ impl AsyncResponseListener for ParserContext {
let parser = parser.r();
let win = parser.window();
self.parser = Some(match parser {
- ParserRef::HTML(parser) => TrustedParser::HTML(Trusted::new(win.get_cx(), parser, self.script_chan.clone())),
+ ParserRef::HTML(parser) => TrustedParser::HTML(
+ Trusted::new(win.get_cx(),
+ parser,
+ self.script_chan.clone())),
ParserRef::XML(parser) => TrustedParser::XML(Trusted::new(win.get_cx(), parser, self.script_chan.clone())),
});
@@ -288,6 +291,7 @@ impl AsyncResponseListener for ParserContext {
parser.set_plaintext_state();
},
Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, _))) => {}, // Handle text/html
+ Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) => {}, // Handle text/xml
Some(ContentType(Mime(toplevel, sublevel, _))) => {
if toplevel.as_str() == "application" && sublevel.as_str() == "xhtml+xml" {
// Handle xhtml (application/xhtml+xml).
diff --git a/components/script/dom/servoxmlparser.rs b/components/script/dom/servoxmlparser.rs
index 9075dd5f2eb..4f4b4be7d3e 100644
--- a/components/script/dom/servoxmlparser.rs
+++ b/components/script/dom/servoxmlparser.rs
@@ -3,8 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell;
+use dom::bindings::codegen::Bindings::ServoXMLParserBinding;
+use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
-use dom::bindings::reflector::Reflector;
+use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::trace::JSTraceable;
use dom::document::Document;
use dom::node::Node;
@@ -87,7 +89,30 @@ impl<'a> Parser for &'a ServoXMLParser {
}
impl ServoXMLParser {
- pub fn new() {
+ #[allow(unrooted_must_root)]
+ pub fn new(base_url: Option<Url>, document: &Document, pipeline: Option<PipelineId>)
+ -> Root<ServoXMLParser> {
+ let sink = Sink {
+ base_url: base_url,
+ document: JS::from_ref(document),
+ };
+
+ let tb = XmlTreeBuilder::new(sink);
+
+ let tok = tokenizer::XmlTokenizer::new(tb, Default::default());
+
+ let parser = ServoXMLParser {
+ reflector_: Reflector::new(),
+ tokenizer: DOMRefCell::new(tok),
+ pending_input: DOMRefCell::new(vec!()),
+ document: JS::from_ref(document),
+ suspended: Cell::new(false),
+ last_chunk_received: Cell::new(false),
+ pipeline: pipeline,
+ };
+
+ reflect_dom_object(box parser, GlobalRef::Window(document.window()),
+ ServoXMLParserBinding::Wrap)
}
pub fn window(&self) -> &Window {
@@ -95,19 +120,44 @@ impl ServoXMLParser {
}
pub fn resume(&self) {
- panic!()
+ assert!(self.suspended.get());
+ self.suspended.set(false);
+ self.parse_sync();
}
pub fn suspend(&self) {
- panic!()
+ assert!(!self.suspended.get());
+ self.suspended.set(true);
}
pub fn is_suspended(&self) -> bool {
- panic!()
+ self.suspended.get()
}
pub fn parse_sync(&self) {
- panic!()
+ // This parser will continue to parse while there is either pending input or
+ // the parser remains unsuspended.
+ loop {
+ self.document.reflow_if_reflow_timer_expired();
+ let mut pending_input = self.pending_input.borrow_mut();
+ if !pending_input.is_empty() {
+ let chunk = pending_input.remove(0);
+ self.tokenizer.borrow_mut().feed(chunk.into());
+ }
+
+ // Document parsing is blocked on an external resource.
+ if self.suspended.get() {
+ return;
+ }
+
+ if pending_input.is_empty() {
+ break;
+ }
+ }
+
+ if self.last_chunk_received.get() {
+ self.finish();
+ }
}
pub fn pending_input(&self) -> &DOMRefCell<Vec<String>> {
diff --git a/components/script/parse/xml.rs b/components/script/parse/xml.rs
index 2c2f97d3a78..30cd5138348 100644
--- a/components/script/parse/xml.rs
+++ b/components/script/parse/xml.rs
@@ -6,7 +6,7 @@
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{JS, RootedReference};
+use dom::bindings::js::{JS, Root, RootedReference};
use dom::comment::Comment;
use dom::document::Document;
use dom::documenttype::DocumentType;
@@ -14,7 +14,10 @@ use dom::element::{Element, ElementCreator};
use dom::node::Node;
use dom::processinginstruction::ProcessingInstruction;
use dom::servoxmlparser;
+use dom::servoxmlparser::ServoXMLParser;
+use dom::text::Text;
use msg::constellation_msg::PipelineId;
+use parse::Parser;
use std::borrow::Cow;
use string_cache::QualName;
use tendril::StrTendril;
@@ -61,8 +64,14 @@ impl<'a> TreeSink for servoxmlparser::Sink {
}
fn append(&mut self, parent: JS<Node>, child: NodeOrText<JS<Node>>) {
- let child = self.get_or_create(child);
-
+ 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());
}
@@ -90,8 +99,14 @@ pub enum ParseContext {
}
-pub fn parse_xml(_document: &Document,
- _input: DOMString,
- _url: Url,
- _context: ParseContext) {
+pub fn parse_xml(document: &Document,
+ input: DOMString,
+ url: Url,
+ context: ParseContext) {
+ let parser = match context {
+ ParseContext::Owner(owner) =>
+ ServoXMLParser::new(Some(url), document, owner),
+ };
+ parser.parse_chunk(String::from(input));
}
+
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index c7078d0db75..5563a0a2ca9 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -1660,7 +1660,6 @@ impl ScriptTask {
});
let content_type = match metadata.content_type {
-
Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) => {
Some(DOMString::from("text/xml"))
}
@@ -1675,28 +1674,20 @@ impl ScriptTask {
let loader = DocumentLoader::new_with_task(self.resource_task.clone(),
Some(page.pipeline()),
Some(incomplete.url.clone()));
- let document;
- match metadata.content_type {
- Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) => {
- document = Document::new(window.r(),
- Some(final_url.clone()),
- IsHTMLDocument::NonHTMLDocument,
- content_type,
- last_modified,
- DocumentSource::NotFromParser,
- loader);
- }
- _ => {
- document = Document::new(window.r(),
+ let is_html_document = match metadata.content_type {
+ Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) =>
+ IsHTMLDocument::NonHTMLDocument,
+ _ => IsHTMLDocument::HTMLDocument,
+ };
+
+ let document = Document::new(window.r(),
Some(final_url.clone()),
- IsHTMLDocument::HTMLDocument,
+ is_html_document,
content_type,
last_modified,
DocumentSource::FromParser,
loader);
- }
- }
let frame_element = frame_element.r().map(Castable::upcast);
window.init_browsing_context(document.r(), frame_element);
@@ -1738,7 +1729,8 @@ impl ScriptTask {
unsafe {
let mut jsval = RootedValue::new(self.get_cx(), UndefinedValue());
window.evaluate_js_on_global_with_result(&script_source, jsval.handle_mut());
- let strval = DOMString::from_jsval(self.get_cx(), jsval.handle(),
+ let strval = DOMString::from_jsval(self.get_cx(),
+ jsval.handle(),
StringificationBehavior::Empty);
strval.unwrap_or(DOMString::new())
}
@@ -1746,8 +1738,7 @@ impl ScriptTask {
DOMString::new()
};
- match metadata.content_type {
-
+ match metadata.content_type {
Some(ContentType(Mime(TopLevel::Text, SubLevel::Xml, _))) => {
parse_xml(document.r(),
parse_input,
@@ -1760,7 +1751,7 @@ impl ScriptTask {
final_url,
ParseContext::Owner(Some(incomplete.pipeline_id)));
}
- }
+ }
page_remover.neuter();