aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/parse/html.rs
diff options
context:
space:
mode:
authorMatt Brubeck <mbrubeck@limpet.net>2014-10-17 09:48:31 -0700
committerMatt Brubeck <mbrubeck@limpet.net>2014-10-29 14:31:47 -0700
commitfe123ad07ce048c11c2820481c9fd54ce296202d (patch)
tree920d2a5cf4ca502aa1e6a2b761528c4080af9b84 /components/script/parse/html.rs
parent65a0d1fe9a14e09b675cc24cb59c9aebf1615020 (diff)
downloadservo-fe123ad07ce048c11c2820481c9fd54ce296202d.tar.gz
servo-fe123ad07ce048c11c2820481c9fd54ce296202d.zip
Switch to synchronous script loading
This removes the old code for asyncronously loading scripts during HTML parsing and then executing them afterward. Fixes #3356.
Diffstat (limited to 'components/script/parse/html.rs')
-rw-r--r--components/script/parse/html.rs133
1 files changed, 21 insertions, 112 deletions
diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs
index 39001fe8f7f..c802e6de9aa 100644
--- a/components/script/parse/html.rs
+++ b/components/script/parse/html.rs
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::AttrHelpers;
-use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast};
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
@@ -23,82 +22,26 @@ use parse::Parser;
use encoding::all::UTF_8;
use encoding::types::{Encoding, DecodeReplace};
-use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask, load_whole_resource};
+use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask};
use servo_msg::constellation_msg::LoadData as MsgLoadData;
-use servo_util::task::spawn_named;
use servo_util::task_state;
use servo_util::task_state::InHTMLParser;
use servo_util::str::DOMString;
use std::ascii::StrAsciiExt;
-use std::comm::{channel, Sender, Receiver};
+use std::comm::channel;
use std::str::MaybeOwned;
-use url::{Url, UrlParser};
+use url::Url;
use http::headers::HeaderEnum;
use time;
use html5ever::Attribute;
use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText};
use string_cache::QualName;
-pub struct JSFile {
- pub data: String,
- pub url: Option<Url>,
-}
-
-pub type JSResult = Vec<JSFile>;
-
pub enum HTMLInput {
InputString(String),
InputUrl(Url),
}
-pub enum JSMessage {
- JSTaskNewFile(Url),
- JSTaskNewInlineScript(String, Option<Url>),
- JSTaskExit
-}
-
-/// Messages generated by the HTML parser upon discovery of additional resources
-pub enum HtmlDiscoveryMessage {
- HtmlDiscoveredScript(JSResult)
-}
-
-pub struct HtmlParserResult {
- pub discovery_port: Receiver<HtmlDiscoveryMessage>,
-}
-
-fn js_script_listener(to_parent: Sender<HtmlDiscoveryMessage>,
- from_parent: Receiver<JSMessage>,
- resource_task: ResourceTask) {
- let mut result_vec = vec!();
-
- loop {
- match from_parent.recv_opt() {
- Ok(JSTaskNewFile(url)) => {
- match load_whole_resource(&resource_task, url.clone()) {
- Err(_) => {
- error!("error loading script {:s}", url.serialize());
- }
- Ok((metadata, bytes)) => {
- let decoded = UTF_8.decode(bytes.as_slice(), DecodeReplace).unwrap();
- result_vec.push(JSFile {
- data: decoded.to_string(),
- url: Some(metadata.final_url),
- });
- }
- }
- }
- Ok(JSTaskNewInlineScript(data, url)) => {
- result_vec.push(JSFile { data: data, url: url });
- }
- Ok(JSTaskExit) | Err(()) => {
- break;
- }
- }
- }
-
- assert!(to_parent.send_opt(HtmlDiscoveredScript(result_vec)).is_ok());
-}
-
// Parses an RFC 2616 compliant date/time string, and returns a localized
// date/time string in a format suitable for document.lastModified.
fn parse_last_modified(timestamp: &str) -> String {
@@ -123,9 +66,16 @@ fn parse_last_modified(timestamp: &str) -> String {
}
}
+#[deriving(PartialEq)]
+pub enum ElementCreator {
+ ParserCreated,
+ ScriptCreated,
+}
+
pub fn build_element_from_tag(name: QualName,
prefix: Option<DOMString>,
- document: JSRef<Document>) -> Temporary<Element> {
+ document: JSRef<Document>,
+ creator: ElementCreator) -> Temporary<Element> {
if name.ns != ns!(HTML) {
return Element::new(name.local.as_slice().to_string(), name.ns, None, document);
}
@@ -233,7 +183,7 @@ pub fn build_element_from_tag(name: QualName,
atom!("ruby") => make!(HTMLElement),
atom!("s") => make!(HTMLElement),
atom!("samp") => make!(HTMLElement),
- atom!("script") => make!(HTMLScriptElement, true),
+ atom!("script") => make!(HTMLScriptElement, creator),
atom!("section") => make!(HTMLElement),
atom!("select") => make!(HTMLSelectElement),
atom!("small") => make!(HTMLElement),
@@ -307,7 +257,7 @@ impl<'a> TreeSink<TrustedNodeAddress> for servohtmlparser::Sink {
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>)
-> TrustedNodeAddress {
let doc = self.document.root();
- let elem = build_element_from_tag(name, None, *doc).root();
+ let elem = build_element_from_tag(name, None, *doc, ParserCreated).root();
for attr in attrs.into_iter() {
elem.set_attribute_from_parser(attr.name, attr.value, None);
@@ -378,42 +328,16 @@ impl<'a> TreeSink<TrustedNodeAddress> for servohtmlparser::Sink {
error!("remove_from_parent not implemented!");
}
- fn mark_script_already_started(&mut self, _node: TrustedNodeAddress) {
- error!("mark_script_already_started not implemented!");
+ fn mark_script_already_started(&mut self, node: TrustedNodeAddress) {
+ let node: Root<Node> = unsafe { JS::from_trusted_node_address(node).root() };
+ let script: Option<JSRef<HTMLScriptElement>> = HTMLScriptElementCast::to_ref(*node);
+ script.map(|script| script.mark_already_started());
}
fn complete_script(&mut self, node: TrustedNodeAddress) {
let node: Root<Node> = unsafe { JS::from_trusted_node_address(node).root() };
- let script: Option<JSRef<HTMLScriptElement>> =
- HTMLScriptElementCast::to_ref(*node);
- let script = match script {
- Some(script) if script.is_javascript() => script,
- _ => return,
- };
-
- let script_element: JSRef<Element> = ElementCast::from_ref(script);
- match script_element.get_attribute(ns!(""), &atom!("src")).root() {
- Some(src) => {
- debug!("found script: {:s}", src.deref().Value());
- let mut url_parser = UrlParser::new();
- match self.base_url {
- None => (),
- Some(ref base_url) => {
- url_parser.base_url(base_url);
- }
- };
- match url_parser.parse(src.deref().value().as_slice()) {
- Ok(new_url) => self.js_chan.send(JSTaskNewFile(new_url)),
- Err(e) => debug!("Parsing url {:s} failed: {:?}", src.deref().Value(), e)
- };
- }
- None => {
- let scriptnode: JSRef<Node> = NodeCast::from_ref(script);
- let data = Node::collect_text_contents(scriptnode.children());
- debug!("script data = {:?}", data);
- self.js_chan.send(JSTaskNewInlineScript(data, self.base_url.clone()));
- }
- }
+ let script: Option<JSRef<HTMLScriptElement>> = HTMLScriptElementCast::to_ref(*node);
+ script.map(|script| script.prepare());
}
}
@@ -422,17 +346,7 @@ pub fn parse_html(page: &Page,
document: JSRef<Document>,
input: HTMLInput,
resource_task: ResourceTask,
- msg_load_data: Option<MsgLoadData>)
- -> HtmlParserResult {
- // Spawn a JS parser to receive JavaScript.
- let (discovery_chan, discovery_port) = channel();
- let resource_task2 = resource_task.clone();
- let js_result_chan = discovery_chan.clone();
- let (js_chan, js_msg_port) = channel();
- spawn_named("parse_html:js", proc() {
- js_script_listener(js_result_chan, js_msg_port, resource_task2.clone());
- });
-
+ msg_load_data: Option<MsgLoadData>) {
let (base_url, load_response) = match input {
InputUrl(ref url) => {
// Wait for the LoadResponse so that the parser knows the final URL.
@@ -480,7 +394,7 @@ pub fn parse_html(page: &Page,
},
};
- let parser = ServoHTMLParser::new(js_chan.clone(), base_url.clone(), document).root();
+ let parser = ServoHTMLParser::new(base_url.clone(), document).root();
let parser: JSRef<ServoHTMLParser> = *parser;
task_state::enter(InHTMLParser);
@@ -520,9 +434,4 @@ pub fn parse_html(page: &Page,
task_state::exit(InHTMLParser);
debug!("finished parsing");
- js_chan.send(JSTaskExit);
-
- HtmlParserResult {
- discovery_port: discovery_port,
- }
}