diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index e5fc53affe6..07dde14ebe8 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -37,7 +37,7 @@ fnv = "1.0" gfx_traits = {path = "../gfx_traits"} heapsize = "0.3.6" heapsize_derive = "0.1" -html5ever = {version = "0.10.1", features = ["heap_size", "unstable"]} +html5ever = {version = "0.10.2", features = ["heap_size", "unstable"]} html5ever-atoms = {version = "0.1", features = ["heap_size"]} hyper = "0.9.9" hyper_serde = "0.1.4" diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 11aed4be9af..528b1213ccb 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -408,6 +408,12 @@ impl MutNullableHeap> { } } + /// Gets the current value out of this object and sets it to `None`. + pub fn take(&self) -> Option> { + let value = self.get(); + self.set(None); + value + } } impl PartialEq for MutNullableHeap> { diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs index ab5af05a18d..0f806171a9b 100644 --- a/components/script/dom/servoparser/html.rs +++ b/components/script/dom/servoparser/html.rs @@ -34,22 +34,19 @@ use js::jsapi::JSTracer; use servo_url::ServoUrl; use std::borrow::Cow; use std::io::{self, Write}; -use super::{FragmentContext, Sink}; #[derive(HeapSizeOf, JSTraceable)] #[must_root] pub struct Tokenizer { #[ignore_heap_size_of = "Defined in html5ever"] inner: HtmlTokenizer, Sink>>, - #[ignore_heap_size_of = "Defined in html5ever"] - input_buffer: BufferQueue, } impl Tokenizer { pub fn new( document: &Document, url: ServoUrl, - fragment_context: Option) + fragment_context: Option) -> Self { let sink = Sink { base_url: url, @@ -80,27 +77,17 @@ impl Tokenizer { Tokenizer { inner: inner, - input_buffer: BufferQueue::new(), } } - pub fn feed(&mut self, input: String) { - self.input_buffer.push_back(input.into()); - self.run(); - } - - #[allow(unrooted_must_root)] - pub fn run(&mut self) { - while let TokenizerResult::Script(script) = self.inner.feed(&mut self.input_buffer) { - let script = Root::from_ref(script.downcast::().unwrap()); - if !script.prepare() { - break; - } + pub fn feed(&mut self, input: &mut BufferQueue) -> Result<(), Root> { + match self.inner.feed(input) { + TokenizerResult::Done => Ok(()), + TokenizerResult::Script(script) => Err(Root::from_ref(script.downcast().unwrap())), } } pub fn end(&mut self) { - assert!(self.input_buffer.is_empty()); self.inner.end(); } @@ -128,6 +115,13 @@ impl JSTraceable for HtmlTokenizer, Sink>> { } } +#[derive(JSTraceable, HeapSizeOf)] +#[must_root] +struct Sink { + base_url: ServoUrl, + document: JS, +} + impl<'a> TreeSink for Sink { type Output = Self; fn finish(self) -> Self { self } diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 31ae5d4961a..fe650477123 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -17,9 +17,11 @@ use dom::document::{Document, DocumentSource, IsHTMLDocument}; 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 encoding::all::UTF_8; use encoding::types::{DecoderTrap, Encoding}; +use html5ever::tokenizer::buffer_queue::BufferQueue; use hyper::header::ContentType; use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper_serde::Serde; @@ -31,7 +33,6 @@ use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile}; use script_thread::ScriptThread; use servo_url::ServoUrl; use std::cell::Cell; -use std::collections::VecDeque; use util::resource_files::read_resource_file; mod html; @@ -46,7 +47,8 @@ pub struct ServoParser { /// does not correspond to a page load. pipeline: Option, /// Input chunks received but not yet passed to the parser. - pending_input: DOMRefCell>, + #[ignore_heap_size_of = "Defined in html5ever"] + pending_input: DOMRefCell, /// The tokenizer of this parser. tokenizer: DOMRefCell, /// Whether to expect any further input from the associated network request. @@ -143,7 +145,7 @@ impl ServoParser { reflector: Reflector::new(), document: JS::from_ref(document), pipeline: pipeline, - pending_input: DOMRefCell::new(VecDeque::new()), + pending_input: DOMRefCell::new(BufferQueue::new()), tokenizer: DOMRefCell::new(tokenizer), last_chunk_received: Cell::new(last_chunk_state == LastChunkState::Received), suspended: Default::default(), @@ -176,16 +178,7 @@ impl ServoParser { } fn push_input_chunk(&self, chunk: String) { - self.pending_input.borrow_mut().push_back(chunk); - } - - fn take_next_input_chunk(&self) -> Option { - let mut pending_input = self.pending_input.borrow_mut(); - if pending_input.is_empty() { - None - } else { - pending_input.pop_front() - } + self.pending_input.borrow_mut().push_back(chunk.into()); } fn last_chunk_received(&self) -> bool { @@ -233,10 +226,10 @@ impl ServoParser { // the parser remains unsuspended. loop { self.document().reflow_if_reflow_timer_expired(); - if let Some(chunk) = self.take_next_input_chunk() { - self.tokenizer.borrow_mut().feed(chunk); - } else { - self.tokenizer.borrow_mut().run(); + if let Err(script) = self.tokenizer.borrow_mut().feed(&mut *self.pending_input.borrow_mut()) { + if script.prepare() { + continue; + } } // Document parsing is blocked on an external resource. @@ -284,25 +277,11 @@ enum Tokenizer { Xml(self::xml::Tokenizer), } -#[derive(JSTraceable, HeapSizeOf)] -#[must_root] -struct Sink { - pub base_url: ServoUrl, - pub document: JS, -} - impl Tokenizer { - fn feed(&mut self, input: String) { + fn feed(&mut self, input: &mut BufferQueue) -> Result<(), Root> { match *self { Tokenizer::Html(ref mut tokenizer) => tokenizer.feed(input), - Tokenizer::Xml(ref mut tokenizer) => tokenizer.feed(input.into()), - } - } - - fn run(&mut self) { - match *self { - Tokenizer::Html(ref mut tokenizer) => tokenizer.run(), - Tokenizer::Xml(ref mut tokenizer) => tokenizer.run(), + Tokenizer::Xml(ref mut tokenizer) => tokenizer.feed(input), } } diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs index 3ce3fb69ca4..4f233bd80ec 100644 --- a/components/script/dom/servoparser/xml.rs +++ b/components/script/dom/servoparser/xml.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, Root}; +use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; use dom::comment::Comment; @@ -17,11 +17,11 @@ use dom::htmlscriptelement::HTMLScriptElement; use dom::node::Node; use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; +use html5ever::tokenizer::buffer_queue::BufferQueue; use html5ever_atoms::{Prefix, QualName}; use js::jsapi::JSTracer; use servo_url::ServoUrl; use std::borrow::Cow; -use super::Sink; use xml5ever::tendril::StrTendril; use xml5ever::tokenizer::{Attribute, QName, XmlTokenizer}; use xml5ever::tree_builder::{NextParserState, NodeOrText}; @@ -39,6 +39,7 @@ impl Tokenizer { let sink = Sink { base_url: url, document: JS::from_ref(document), + script: Default::default(), }; let tb = XmlTreeBuilder::new(sink); @@ -49,12 +50,21 @@ impl Tokenizer { } } - pub fn feed(&mut self, input: String) { - self.inner.feed(input.into()) - } - - pub fn run(&mut self) { - self.inner.run() + pub fn feed(&mut self, input: &mut BufferQueue) -> Result<(), Root> { + if !input.is_empty() { + while let Some(chunk) = input.pop_front() { + self.inner.feed(chunk); + if let Some(script) = self.inner.sink().sink().script.take() { + return Err(script); + } + } + } else { + self.inner.run(); + if let Some(script) = self.inner.sink().sink().script.take() { + return Err(script); + } + } + Ok(()) } pub fn end(&mut self) { @@ -81,6 +91,14 @@ impl JSTraceable for XmlTokenizer, Sink>> { } } +#[derive(JSTraceable, HeapSizeOf)] +#[must_root] +struct Sink { + base_url: ServoUrl, + document: JS, + script: MutNullableHeap>, +} + impl<'a> TreeSink for Sink { type Handle = JS; @@ -165,13 +183,11 @@ impl<'a> TreeSink for Sink { } fn complete_script(&mut self, node: Self::Handle) -> NextParserState { - let script = node.downcast::(); - if let Some(script) = script { - return match script.prepare() { - true => NextParserState::Continue, - false => NextParserState::Suspend, - }; + if let Some(script) = node.downcast() { + self.script.set(Some(script)); + NextParserState::Suspend + } else { + NextParserState::Continue } - NextParserState::Continue } } diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 01257ed3a0a..c822e2d056a 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1990,7 +1990,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever-atoms 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3010,7 +3010,7 @@ dependencies = [ "checksum heartbeats-simple 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "78c0810722eacd0bdd3f1f691524bd9900bf8fed1947f6b883c10ddecd2560b1" "checksum heartbeats-simple-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53c4b67617665d7f4172f381f9843c1bec6a4fccc9a9226529e5b1be40dc1301" "checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" -"checksum html5ever 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e8b18bb73cb3535597d23fbd1998fb45fe88cb12b9acf183a0188331f6d915" +"checksum html5ever 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9464c43c1b84b1e31c10636e6bc85f63eb7cb435a757020a8e1d1a5502254d4c" "checksum html5ever-atoms 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "daefa106438c66af58309c84842b5db1df2733fe35849f39adde6fdf63583d40" "checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae" "checksum hyper 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "edd47c66782933e546a32ae89ca3c49263b2ba9bc29f3a0d5c52fff48e0ac67c" diff --git a/ports/servo/Cargo.lock b/ports/servo/Cargo.lock index d56d04c0039..5beb208a72d 100644 --- a/ports/servo/Cargo.lock +++ b/ports/servo/Cargo.lock @@ -1021,7 +1021,7 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2140,7 +2140,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever-atoms 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3218,7 +3218,7 @@ dependencies = [ "checksum heartbeats-simple 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "78c0810722eacd0bdd3f1f691524bd9900bf8fed1947f6b883c10ddecd2560b1" "checksum heartbeats-simple-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53c4b67617665d7f4172f381f9843c1bec6a4fccc9a9226529e5b1be40dc1301" "checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" -"checksum html5ever 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e8b18bb73cb3535597d23fbd1998fb45fe88cb12b9acf183a0188331f6d915" +"checksum html5ever 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9464c43c1b84b1e31c10636e6bc85f63eb7cb435a757020a8e1d1a5502254d4c" "checksum html5ever-atoms 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "daefa106438c66af58309c84842b5db1df2733fe35849f39adde6fdf63583d40" "checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae" "checksum hyper 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "edd47c66782933e546a32ae89ca3c49263b2ba9bc29f3a0d5c52fff48e0ac67c"