Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up the parsers into a single interface #13675

Merged
merged 9 commits into from Oct 11, 2016

Move pending input logic to ServoParser

  • Loading branch information
nox committed Oct 11, 2016
commit e1a1bf46cadd1787f543ed75d24c35bf2ae79092
@@ -107,6 +107,7 @@ impl AsyncResponseListener for ParserContext {
};

let parser = parser.r();
let servo_parser = parser.as_servo_parser();
self.parser = Some(match parser {
ParserRef::HTML(parser) => TrustedParser::HTML(
Trusted::new(parser)),
@@ -118,10 +119,10 @@ impl AsyncResponseListener for ParserContext {
Some(ContentType(Mime(TopLevel::Image, _, _))) => {
self.is_synthesized_document = true;
let page = "<html><body></body></html>".into();
parser.pending_input().borrow_mut().push(page);
servo_parser.push_input_chunk(page);
parser.parse_sync();

let doc = parser.as_servo_parser().document();
let doc = servo_parser.document();
let doc_body = Root::upcast::<Node>(doc.GetBody().unwrap());
let img = HTMLImageElement::new(atom!("img"), None, doc);
img.SetSrc(DOMString::from(self.url.to_string()));
@@ -131,7 +132,7 @@ impl AsyncResponseListener for ParserContext {
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => {
// https://html.spec.whatwg.org/multipage/#read-text
let page = "<pre>\n".into();
parser.pending_input().borrow_mut().push(page);
servo_parser.push_input_chunk(page);
parser.parse_sync();
parser.set_plaintext_state();
},
@@ -141,7 +142,7 @@ impl AsyncResponseListener for ParserContext {
let page_bytes = read_resource_file("badcert.html").unwrap();
let page = String::from_utf8(page_bytes).unwrap();
let page = page.replace("${reason}", &reason);
parser.pending_input().borrow_mut().push(page);
servo_parser.push_input_chunk(page);
parser.parse_sync();
}
},
@@ -156,7 +157,7 @@ impl AsyncResponseListener for ParserContext {
let page = format!("<html><body><p>Unknown content type ({}/{}).</p></body></html>",
toplevel.as_str(), sublevel.as_str());
self.is_synthesized_document = true;
parser.pending_input().borrow_mut().push(page);
servo_parser.push_input_chunk(page);
parser.parse_sync();
},
None => {
@@ -192,7 +193,7 @@ impl AsyncResponseListener for ParserContext {
let page_bytes = read_resource_file("neterror.html").unwrap();
let page = String::from_utf8(page_bytes).unwrap();
let page = page.replace("${reason}", reason);
parser.pending_input().borrow_mut().push(page);
parser.as_servo_parser().push_input_chunk(page);
parser.parse_sync();
} else if let Err(err) = status {
// TODO(Savago): we should send a notification to callers #5463.
@@ -217,8 +218,6 @@ pub struct ServoHTMLParser {
servoparser: ServoParser,
#[ignore_heap_size_of = "Defined in html5ever"]
tokenizer: DOMRefCell<Tokenizer>,
/// Input chunks received but not yet passed to the parser.
pending_input: DOMRefCell<Vec<String>>,
/// 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.
@@ -231,15 +230,15 @@ pub struct ServoHTMLParser {
impl<'a> Parser for &'a ServoHTMLParser {
fn parse_chunk(self, input: String) {
self.upcast().document().set_current_parser(Some(ParserRef::HTML(self)));
self.pending_input.borrow_mut().push(input);
self.upcast().push_input_chunk(input);
if !self.is_suspended() {
self.parse_sync();
}
}

fn finish(self) {
assert!(!self.suspended.get());
assert!(self.pending_input.borrow().is_empty());
assert!(!self.upcast().has_pending_input());

self.tokenizer.borrow_mut().end();
debug!("finished parsing");
@@ -271,7 +270,6 @@ impl ServoHTMLParser {
let parser = ServoHTMLParser {
servoparser: ServoParser::new_inherited(document),
tokenizer: DOMRefCell::new(tok),
pending_input: DOMRefCell::new(vec!()),
suspended: Cell::new(false),
last_chunk_received: Cell::new(false),
pipeline: pipeline,
@@ -306,7 +304,6 @@ impl ServoHTMLParser {
let parser = ServoHTMLParser {
servoparser: ServoParser::new_inherited(document),
tokenizer: DOMRefCell::new(tok),
pending_input: DOMRefCell::new(vec!()),
suspended: Cell::new(false),
last_chunk_received: Cell::new(true),
pipeline: None,
@@ -327,11 +324,6 @@ impl ServoHTMLParser {
pub fn end_tokenizer(&self) {
self.tokenizer.borrow_mut().end()
}

pub fn pending_input(&self) -> &DOMRefCell<Vec<String>> {
&self.pending_input
}

}

impl ServoHTMLParser {
@@ -352,9 +344,7 @@ impl ServoHTMLParser {
// the parser remains unsuspended.
loop {
self.upcast().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);
if let Some(chunk) = self.upcast().take_next_input_chunk() {
self.tokenizer.borrow_mut().feed(chunk.into());
} else {
self.tokenizer.borrow_mut().run();
@@ -365,7 +355,7 @@ impl ServoHTMLParser {
return;
}

if pending_input.is_empty() {
if !self.upcast().has_pending_input() {
break;
}
}
@@ -2,6 +2,7 @@
* 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::reflector::Reflector;
use dom::bindings::js::JS;
use dom::document::Document;
@@ -11,17 +12,37 @@ pub struct ServoParser {
reflector: Reflector,
/// The document associated with this parser.
document: JS<Document>,
/// Input chunks received but not yet passed to the parser.
pending_input: DOMRefCell<Vec<String>>,
}

impl ServoParser {
pub fn new_inherited(document: &Document) -> Self {
ServoParser {
reflector: Reflector::new(),
document: JS::from_ref(document),
pending_input: DOMRefCell::new(vec![]),
}
}

pub fn document(&self) -> &Document {
&self.document
}

pub fn has_pending_input(&self) -> bool {
!self.pending_input.borrow().is_empty()
}

pub fn push_input_chunk(&self, chunk: String) {
self.pending_input.borrow_mut().push(chunk);
}

pub fn take_next_input_chunk(&self) -> Option<String> {
let mut pending_input = self.pending_input.borrow_mut();
if pending_input.is_empty() {
None
} else {
Some(pending_input.remove(0))

This comment has been minimized.

@Ms2ger

Ms2ger Oct 10, 2016

Contributor

Followup: should use pop() (and probably a queue).

}
}
}
@@ -36,8 +36,6 @@ pub struct ServoXMLParser {
servoparser: ServoParser,
#[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>>,
/// 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.
@@ -50,15 +48,15 @@ pub struct ServoXMLParser {
impl<'a> Parser for &'a ServoXMLParser {
fn parse_chunk(self, input: String) {
self.upcast().document().set_current_parser(Some(ParserRef::XML(self)));
self.pending_input.borrow_mut().push(input);
self.upcast().push_input_chunk(input);
if !self.is_suspended() {
self.parse_sync();
}
}

fn finish(self) {
assert!(!self.suspended.get());
assert!(self.pending_input.borrow().is_empty());
assert!(!self.upcast().has_pending_input());

self.tokenizer.borrow_mut().end();
debug!("finished parsing");
@@ -87,7 +85,6 @@ impl ServoXMLParser {
let parser = ServoXMLParser {
servoparser: ServoParser::new_inherited(document),
tokenizer: DOMRefCell::new(tok),
pending_input: DOMRefCell::new(vec!()),
suspended: Cell::new(false),
last_chunk_received: Cell::new(false),
pipeline: pipeline,
@@ -119,10 +116,8 @@ impl ServoXMLParser {
// This parser will continue to parse while there is either pending input or
// the parser remains unsuspended.
loop {
self.upcast().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.upcast().document().reflow_if_reflow_timer_expired();
if let Some(chunk) = self.upcast().take_next_input_chunk() {
self.tokenizer.borrow_mut().feed(chunk.into());
} else {
self.tokenizer.borrow_mut().run();
@@ -133,7 +128,7 @@ impl ServoXMLParser {
return;
}

if pending_input.is_empty() {
if !self.upcast().has_pending_input() {
break;
}
}
@@ -143,10 +138,6 @@ impl ServoXMLParser {
}
}

pub fn pending_input(&self) -> &DOMRefCell<Vec<String>> {
&self.pending_input
}

pub fn set_plaintext_state(&self) {
//self.tokenizer.borrow_mut().set_plaintext_state()
}
@@ -2,7 +2,6 @@
* 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::inheritance::Castable;
use dom::bindings::js::{JS, Root};
use dom::bindings::refcounted::Trusted;
@@ -147,13 +146,6 @@ impl<'a> ParserRef<'a> {
}
}

pub fn pending_input(&self) -> &DOMRefCell<Vec<String>> {
match *self {
ParserRef::HTML(parser) => parser.pending_input(),
ParserRef::XML(parser) => parser.pending_input(),
}
}

pub fn set_plaintext_state(&self) {
match *self {
ParserRef::HTML(parser) => parser.set_plaintext_state(),
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.