Move link rel=stylesheet fetching to layout task

Fixes #3346.
This commit is contained in:
Matt Brubeck 2014-09-15 12:39:18 -07:00
parent 7a5f15f137
commit 1ae3bda172
17 changed files with 154 additions and 196 deletions

View file

@ -10,14 +10,13 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLScriptElementCast};
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
use dom::bindings::utils::Reflectable;
use dom::document::{Document, DocumentHelpers};
use dom::element::{AttributeHandlers, HTMLLinkElementTypeId};
use dom::element::AttributeHandlers;
use dom::htmlelement::HTMLElement;
use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6};
use dom::htmlformelement::HTMLFormElement;
use dom::htmlscriptelement::HTMLScriptElementHelpers;
use dom::node::{ElementNodeTypeId, NodeHelpers};
use dom::node::NodeHelpers;
use dom::types::*;
use html::cssparse::{StylesheetProvenance, UrlProvenance, spawn_css_parser};
use page::Page;
use encoding::all::UTF_8;
@ -29,13 +28,12 @@ use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask, load
use servo_util::atom::Atom;
use servo_util::namespace;
use servo_util::namespace::{Namespace, Null};
use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
use servo_util::str::DOMString;
use servo_util::task::spawn_named;
use std::ascii::StrAsciiExt;
use std::mem;
use std::cell::RefCell;
use std::comm::{channel, Sender, Receiver};
use style::Stylesheet;
use url::{Url, UrlParser};
use http::headers::HeaderEnum;
use time;
@ -65,11 +63,6 @@ pub enum HTMLInput {
InputUrl(Url),
}
enum CSSMessage {
CSSTaskNewFile(StylesheetProvenance),
CSSTaskExit
}
enum JSMessage {
JSTaskNewFile(Url),
JSTaskNewInlineScript(String, Option<Url>),
@ -78,7 +71,6 @@ enum JSMessage {
/// Messages generated by the HTML parser upon discovery of additional resources
pub enum HtmlDiscoveryMessage {
HtmlDiscoveredStyle(Stylesheet),
HtmlDiscoveredScript(JSResult)
}
@ -100,43 +92,6 @@ unsafe fn from_hubbub_node<T: Reflectable>(n: hubbub::NodeDataPtr) -> Temporary<
Temporary::new(JS::from_raw(mem::transmute(n)))
}
/**
Runs a task that coordinates parsing links to css stylesheets.
This function should be spawned in a separate task and spins waiting
for the html builder to find links to css stylesheets and sends off
tasks to parse each link. When the html process finishes, it notifies
the listener, who then collects the css rules from each task it
spawned, collates them, and sends them to the given result channel.
# Arguments
* `to_parent` - A channel on which to send back the full set of rules.
* `from_parent` - A port on which to receive new links.
*/
fn css_link_listener(to_parent: Sender<HtmlDiscoveryMessage>,
from_parent: Receiver<CSSMessage>) {
let mut result_vec = vec!();
loop {
match from_parent.recv_opt() {
Ok(CSSTaskNewFile(provenance)) => {
result_vec.push(spawn_css_parser(provenance));
}
Ok(CSSTaskExit) | Err(()) => {
break;
}
}
}
// Send the sheets back in order
// FIXME: Shouldn't wait until after we've recieved CSSTaskExit to start sending these
for port in result_vec.iter() {
assert!(to_parent.send_opt(HtmlDiscoveredStyle(port.recv())).is_ok());
}
}
fn js_script_listener(to_parent: Sender<HtmlDiscoveryMessage>,
from_parent: Receiver<JSMessage>,
resource_task: ResourceTask) {
@ -335,16 +290,9 @@ pub fn parse_html(page: &Page,
resource_task: ResourceTask)
-> HtmlParserResult {
debug!("Hubbub: parsing {:?}", input);
// Spawn a CSS parser to receive links to CSS style sheets.
let (discovery_chan, discovery_port) = channel();
let stylesheet_chan = discovery_chan.clone();
let (css_chan, css_msg_port) = channel();
spawn_named("parse_html:css", proc() {
css_link_listener(stylesheet_chan, css_msg_port);
});
// 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();
@ -395,7 +343,7 @@ pub fn parse_html(page: &Page,
let mut parser = build_parser(unsafe { document.to_hubbub_node() });
debug!("created parser");
let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone());
let js_chan2 = js_chan.clone();
let doc_cell = RefCell::new(document);
@ -447,54 +395,6 @@ pub fn parse_html(page: &Page,
prefix.map(|p| p.to_string()));
}
//FIXME: workaround for https://github.com/mozilla/rust/issues/13246;
// we get unrooting order failures if these are inside the match.
let rel = {
let rel = element.deref().get_attribute(Null, "rel").root();
rel.map(|a| a.deref().Value())
};
let href = {
let href= element.deref().get_attribute(Null, "href").root();
href.map(|a| a.deref().Value())
};
// Spawn additional parsing, network loads, etc. from tag and attrs
let type_id = {
let node: &JSRef<Node> = NodeCast::from_ref(&*element);
node.type_id()
};
match type_id {
// Handle CSS style sheets from <link> elements
ElementNodeTypeId(HTMLLinkElementTypeId) => {
match (rel, href) {
(Some(ref rel), Some(ref href)) => {
if rel.as_slice()
.split(HTML_SPACE_CHARACTERS.as_slice())
.any(|s| {
s.as_slice().eq_ignore_ascii_case("stylesheet")
}) {
debug!("found CSS stylesheet: {:s}", *href);
let mut url_parser = UrlParser::new();
match base_url {
None => (),
Some(ref base_url) => {
url_parser.base_url(base_url);
}
}
match url_parser.parse(href.as_slice()) {
Ok(url) => css_chan2.send(CSSTaskNewFile(
UrlProvenance(url, resource_task.clone()))),
Err(e) => debug!("Parsing url {:s} failed: {:?}", *href, e)
};
}
}
_ => {}
}
}
_ => {}
}
unsafe { element.deref().to_hubbub_node() }
},
create_text: |data: String| {
@ -641,7 +541,6 @@ pub fn parse_html(page: &Page,
}
debug!("finished parsing");
css_chan.send(CSSTaskExit);
js_chan.send(JSTaskExit);
HtmlParserResult {