aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/servoparser/mod.rs
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2017-01-26 12:42:38 +0100
committerAnthony Ramine <n.oxyde@gmail.com>2017-02-03 16:50:12 +0100
commitac254046e448e4edde86f2d68f27330fbd9ec1e6 (patch)
tree323d38fdd2d1fe80765e7f0f3ed287d7f3a49bb4 /components/script/dom/servoparser/mod.rs
parent8c3abd6c79d2be83e1e088b18ab3b8bbc0cca201 (diff)
downloadservo-ac254046e448e4edde86f2d68f27330fbd9ec1e6.tar.gz
servo-ac254046e448e4edde86f2d68f27330fbd9ec1e6.zip
Implement document.open and document.close (fixes #14591)
Diffstat (limited to 'components/script/dom/servoparser/mod.rs')
-rw-r--r--components/script/dom/servoparser/mod.rs115
1 files changed, 100 insertions, 15 deletions
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index 0d8e02d273e..67f1b23e583 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -38,6 +38,7 @@ use script_thread::ScriptThread;
use script_traits::DocumentActivity;
use servo_config::resource_files::read_resource_file;
use servo_url::ServoUrl;
+use std::ascii::AsciiExt;
use std::cell::Cell;
use std::mem;
@@ -75,6 +76,10 @@ pub struct ServoParser {
suspended: Cell<bool>,
/// https://html.spec.whatwg.org/multipage/#script-nesting-level
script_nesting_level: Cell<usize>,
+ /// https://html.spec.whatwg.org/multipage/#abort-a-parser
+ aborted: Cell<bool>,
+ /// https://html.spec.whatwg.org/multipage/#script-created-parser
+ script_created_parser: bool,
}
#[derive(PartialEq)]
@@ -87,7 +92,8 @@ impl ServoParser {
pub fn parse_html_document(document: &Document, input: DOMString, url: ServoUrl) {
let parser = ServoParser::new(document,
Tokenizer::Html(self::html::Tokenizer::new(document, url, None)),
- LastChunkState::NotReceived);
+ LastChunkState::NotReceived,
+ ParserKind::Normal);
parser.parse_chunk(String::from(input));
}
@@ -129,7 +135,8 @@ impl ServoParser {
Tokenizer::Html(self::html::Tokenizer::new(&document,
url.clone(),
Some(fragment_context))),
- LastChunkState::Received);
+ LastChunkState::Received,
+ ParserKind::Normal);
parser.parse_chunk(String::from(input));
// Step 14.
@@ -139,10 +146,23 @@ impl ServoParser {
}
}
+ pub fn parse_html_script_input(document: &Document, url: ServoUrl, type_: &str) {
+ let parser = ServoParser::new(document,
+ Tokenizer::Html(self::html::Tokenizer::new(document, url, None)),
+ LastChunkState::NotReceived,
+ ParserKind::ScriptCreated);
+ document.set_current_parser(Some(&parser));
+ if !type_.eq_ignore_ascii_case("text/html") {
+ parser.parse_chunk("<pre>\n".to_owned());
+ parser.tokenizer.borrow_mut().set_plaintext_state();
+ }
+ }
+
pub fn parse_xml_document(document: &Document, input: DOMString, url: ServoUrl) {
let parser = ServoParser::new(document,
Tokenizer::Xml(self::xml::Tokenizer::new(document, url)),
- LastChunkState::NotReceived);
+ LastChunkState::NotReceived,
+ ParserKind::Normal);
parser.parse_chunk(String::from(input));
}
@@ -150,6 +170,10 @@ impl ServoParser {
self.script_nesting_level.get()
}
+ pub fn is_script_created(&self) -> bool {
+ self.script_created_parser
+ }
+
/// Corresponds to the latter part of the "Otherwise" branch of the 'An end
/// tag whose tag name is "script"' of
/// https://html.spec.whatwg.org/multipage/#parsing-main-incdata
@@ -186,9 +210,13 @@ impl ServoParser {
}
}
+ pub fn can_write(&self) -> bool {
+ self.script_created_parser || self.script_nesting_level.get() > 0
+ }
+
/// Steps 6-8 of https://html.spec.whatwg.org/multipage/#document.write()
pub fn write(&self, text: Vec<DOMString>) {
- assert!(self.script_nesting_level.get() > 0);
+ assert!(self.can_write());
if self.document.has_pending_parsing_blocking_script() {
// There is already a pending parsing blocking script so the
@@ -225,10 +253,47 @@ impl ServoParser {
assert!(input.is_empty());
}
+ // Steps 4-6 of https://html.spec.whatwg.org/multipage/#dom-document-close
+ pub fn close(&self) {
+ assert!(self.script_created_parser);
+
+ // Step 4.
+ self.last_chunk_received.set(true);
+
+ if self.suspended.get() {
+ // Step 5.
+ return;
+ }
+
+ // Step 6.
+ self.parse_sync();
+ }
+
+ // https://html.spec.whatwg.org/multipage/#abort-a-parser
+ pub fn abort(&self) {
+ assert!(!self.aborted.get());
+ self.aborted.set(true);
+
+ // Step 1.
+ *self.script_input.borrow_mut() = BufferQueue::new();
+ *self.network_input.borrow_mut() = BufferQueue::new();
+
+ // Step 2.
+ self.document.set_ready_state(DocumentReadyState::Interactive);
+
+ // Step 3.
+ self.tokenizer.borrow_mut().end();
+ self.document.set_current_parser(None);
+
+ // Step 4.
+ self.document.set_ready_state(DocumentReadyState::Interactive);
+ }
+
#[allow(unrooted_must_root)]
fn new_inherited(document: &Document,
tokenizer: Tokenizer,
- last_chunk_state: LastChunkState)
+ last_chunk_state: LastChunkState,
+ kind: ParserKind)
-> Self {
ServoParser {
reflector: Reflector::new(),
@@ -239,15 +304,18 @@ impl ServoParser {
last_chunk_received: Cell::new(last_chunk_state == LastChunkState::Received),
suspended: Default::default(),
script_nesting_level: Default::default(),
+ aborted: Default::default(),
+ script_created_parser: kind == ParserKind::ScriptCreated,
}
}
#[allow(unrooted_must_root)]
fn new(document: &Document,
tokenizer: Tokenizer,
- last_chunk_state: LastChunkState)
+ last_chunk_state: LastChunkState,
+ kind: ParserKind)
-> Root<Self> {
- reflect_dom_object(box ServoParser::new_inherited(document, tokenizer, last_chunk_state),
+ reflect_dom_object(box ServoParser::new_inherited(document, tokenizer, last_chunk_state, kind),
document.window(),
ServoParserBinding::Wrap)
}
@@ -301,6 +369,7 @@ impl ServoParser {
{
loop {
assert!(!self.suspended.get());
+ assert!(!self.aborted.get());
self.document.reflow_if_reflow_timer_expired();
let script = match feed(&mut *self.tokenizer.borrow_mut()) {
@@ -358,6 +427,12 @@ impl Iterator for FragmentParsingResult {
}
}
+#[derive(HeapSizeOf, JSTraceable, PartialEq)]
+enum ParserKind {
+ Normal,
+ ScriptCreated,
+}
+
#[derive(HeapSizeOf, JSTraceable)]
#[must_root]
enum Tokenizer {
@@ -454,6 +529,9 @@ impl FetchResponseListener for ParserContext {
Some(parser) => parser,
None => return,
};
+ if parser.aborted.get() {
+ return;
+ }
self.parser = Some(Trusted::new(&*parser));
@@ -512,15 +590,19 @@ impl FetchResponseListener for ParserContext {
}
fn process_response_chunk(&mut self, payload: Vec<u8>) {
- if !self.is_synthesized_document {
- // FIXME: use Vec<u8> (html5ever #34)
- let data = UTF_8.decode(&payload, DecoderTrap::Replace).unwrap();
- let parser = match self.parser.as_ref() {
- Some(parser) => parser.root(),
- None => return,
- };
- parser.parse_chunk(data);
+ if self.is_synthesized_document {
+ return;
+ }
+ // FIXME: use Vec<u8> (html5ever #34)
+ let data = UTF_8.decode(&payload, DecoderTrap::Replace).unwrap();
+ let parser = match self.parser.as_ref() {
+ Some(parser) => parser.root(),
+ None => return,
+ };
+ if parser.aborted.get() {
+ return;
}
+ parser.parse_chunk(data);
}
fn process_response_eof(&mut self, status: Result<(), NetworkError>) {
@@ -528,6 +610,9 @@ impl FetchResponseListener for ParserContext {
Some(parser) => parser.root(),
None => return,
};
+ if parser.aborted.get() {
+ return;
+ }
if let Err(NetworkError::Internal(ref reason)) = status {
// Show an error page for network errors,