diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/servohtmlparser.rs | 6 | ||||
-rw-r--r-- | components/script/dom/servoxmlparser.rs | 62 | ||||
-rw-r--r-- | components/script/parse/xml.rs | 29 | ||||
-rw-r--r-- | components/script/script_task.rs | 33 |
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(); |