Introduce abstraction over HTML and XML parsers for parser network listener.

This commit is contained in:
Josh Matthews 2015-12-02 02:45:52 -05:00
parent a840a23990
commit 9d3b915cac
5 changed files with 328 additions and 33 deletions

View file

@ -2,15 +2,26 @@
* 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/. */
use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::Reflector;
use dom::bindings::trace::JSTraceable;
use dom::document::Document;
use dom::node::Node;
use dom::servohtmlparser::ParserRef;
use dom::text::Text;
use dom::window::Window;
use js::jsapi::JSTracer;
use msg::constellation_msg::PipelineId;
use parse::Parser;
use script_task::ScriptTask;
use std::cell::Cell;
use url::Url;
use util::str::DOMString;
use xml5ever::tree_builder::{NodeOrText, TreeSink};
use xml5ever::tokenizer;
use xml5ever::tree_builder::{self, NodeOrText, XmlTreeBuilder};
pub type Tokenizer = tokenizer::XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>>;
#[must_root]
#[derive(JSTraceable, HeapSizeOf)]
@ -36,9 +47,115 @@ impl Sink {
#[dom_struct]
pub struct ServoXMLParser {
reflector_: Reflector,
#[ignore_heap_size_of = "Defined in xml5ever"]
tokenizer: DOMRefCell<Tokenizer>,
/// Input chunks received but not yet passed to the parser.
pending_input: DOMRefCell<Vec<String>>,
/// The document associated with this parser.
document: JS<Document>,
/// True if this parser should avoid passing any further data to the tokenizer.
suspended: Cell<bool>,
/// Whether to expect any further input from the associated network request.
last_chunk_received: Cell<bool>,
/// The pipeline associated with this parse, unavailable if this parse does not
/// correspond to a page load.
pipeline: Option<PipelineId>,
}
impl<'a> Parser for &'a ServoXMLParser {
fn parse_chunk(self, input: String) {
self.document.set_current_parser(Some(ParserRef::XML(self)));
self.pending_input.borrow_mut().push(input);
if !self.is_suspended() {
self.parse_sync();
}
}
fn finish(self) {
assert!(!self.suspended.get());
assert!(self.pending_input.borrow().is_empty());
self.tokenizer.borrow_mut().end();
debug!("finished parsing");
self.document.set_current_parser(None);
if let Some(pipeline) = self.pipeline {
ScriptTask::parsing_complete(pipeline);
}
}
}
impl ServoXMLParser {
pub fn new() {
}
pub fn window(&self) -> &Window {
self.document.window()
}
pub fn resume(&self) {
panic!()
}
pub fn suspend(&self) {
panic!()
}
pub fn is_suspended(&self) -> bool {
panic!()
}
pub fn parse_sync(&self) {
panic!()
}
pub fn pending_input(&self) -> &DOMRefCell<Vec<String>> {
&self.pending_input
}
pub fn set_plaintext_state(&self) {
//self.tokenizer.borrow_mut().set_plaintext_state()
}
pub fn end_tokenizer(&self) {
self.tokenizer.borrow_mut().end()
}
pub fn document(&self) -> &Document {
&self.document
}
pub fn last_chunk_received(&self) -> &Cell<bool> {
&self.last_chunk_received
}
pub fn tokenizer(&self) -> &DOMRefCell<Tokenizer> {
&self.tokenizer
}
}
struct Tracer {
trc: *mut JSTracer,
}
impl tree_builder::Tracer for Tracer {
type Handle = JS<Node>;
#[allow(unrooted_must_root)]
fn trace_handle(&self, node: JS<Node>) {
node.trace(self.trc);
}
}
impl JSTraceable for Tokenizer {
fn trace(&self, trc: *mut JSTracer) {
let tracer = Tracer {
trc: trc,
};
let tracer = &tracer as &tree_builder::Tracer<Handle=JS<Node>>;
let tree_builder = self.sink();
tree_builder.trace_handles(tracer);
tree_builder.sink().trace(trc);
}
}