aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/blob.rs3
-rw-r--r--components/script/dom/comment.rs3
-rw-r--r--components/script/dom/element.rs2
-rw-r--r--components/script/dom/htmliframeelement.rs57
-rw-r--r--components/script/dom/htmllinkelement.rs66
-rw-r--r--components/script/dom/htmlstyleelement.rs4
-rw-r--r--components/script/dom/node.rs10
-rw-r--r--components/script/dom/window.rs25
-rw-r--r--components/script/html/cssparse.rs72
-rw-r--r--components/script/html/hubbub_html_parser.rs220
-rw-r--r--components/script/layout_interface.rs3
-rw-r--r--components/script/lib.rs1
-rw-r--r--components/script/script_task.rs54
13 files changed, 247 insertions, 273 deletions
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index 0bbdca9f93d..1266cce96b9 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -41,9 +41,6 @@ impl Blob {
}
}
-pub trait BlobMethods {
-}
-
impl Reflectable for Blob {
fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_
diff --git a/components/script/dom/comment.rs b/components/script/dom/comment.rs
index dd070df87ac..5e82dae3716 100644
--- a/components/script/dom/comment.rs
+++ b/components/script/dom/comment.rs
@@ -46,9 +46,6 @@ impl Comment {
}
}
-pub trait CommentMethods {
-}
-
impl Reflectable for Comment {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.characterdata.reflector()
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index ff7e4e1e925..953036788f4 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -806,7 +806,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
Err(()) => Err(Syntax),
Ok(ref selectors) => {
let root: &JSRef<Node> = NodeCast::from_ref(self);
- Ok(matches(selectors, root))
+ Ok(matches(selectors, root, &mut None))
}
}
}
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index a731d0820b6..a5c83002327 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -76,36 +76,41 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
fn get_url(&self) -> Option<Url> {
let element: &JSRef<Element> = ElementCast::from_ref(self);
element.get_attribute(Null, "src").root().and_then(|src| {
- let window = window_from_node(self).root();
- UrlParser::new().base_url(&window.deref().page().get_url())
- .parse(src.deref().value().as_slice()).ok()
+ let url = src.deref().value();
+ if url.as_slice().is_empty() {
+ None
+ } else {
+ let window = window_from_node(self).root();
+ UrlParser::new().base_url(&window.deref().page().get_url())
+ .parse(url.as_slice()).ok()
+ }
})
}
fn process_the_iframe_attributes(&self) {
- match self.get_url() {
- Some(url) => {
- let sandboxed = if self.is_sandboxed() {
- IFrameSandboxed
- } else {
- IFrameUnsandboxed
- };
-
- // Subpage Id
- let window = window_from_node(self).root();
- let page = window.deref().page();
- let subpage_id = page.get_next_subpage_id();
-
- self.deref().size.deref().set(Some(IFrameSize {
- pipeline_id: page.id,
- subpage_id: subpage_id,
- }));
-
- let ConstellationChan(ref chan) = *page.constellation_chan.deref();
- chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
- }
- _ => ()
- }
+ let url = match self.get_url() {
+ Some(url) => url.clone(),
+ None => Url::parse("about:blank").unwrap(),
+ };
+
+ let sandboxed = if self.is_sandboxed() {
+ IFrameSandboxed
+ } else {
+ IFrameUnsandboxed
+ };
+
+ // Subpage Id
+ let window = window_from_node(self).root();
+ let page = window.deref().page();
+ let subpage_id = page.get_next_subpage_id();
+
+ self.deref().size.deref().set(Some(IFrameSize {
+ pipeline_id: page.id,
+ subpage_id: subpage_id,
+ }));
+
+ let ConstellationChan(ref chan) = *page.constellation_chan.deref();
+ chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
}
}
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index d8389033bd1..3c44a9cba8b 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -2,20 +2,25 @@
* 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::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived;
-use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
-use dom::bindings::js::{JSRef, Temporary};
+use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
+use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::Document;
-use dom::element::HTMLLinkElementTypeId;
+use dom::element::{AttributeHandlers, Element, HTMLLinkElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
-use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
+use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
-
+use layout_interface::{LayoutChan, LoadStylesheetMsg};
use servo_util::atom::Atom;
-use servo_util::str::DOMString;
+use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
+use servo_util::namespace::Null;
+
+use std::ascii::StrAsciiExt;
+use url::UrlParser;
#[deriving(Encodable)]
#[must_root]
@@ -74,6 +79,55 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
_ => ()
}
}
+
+ fn bind_to_tree(&self, tree_in_doc: bool) {
+ match self.super_type() {
+ Some(ref s) => s.bind_to_tree(tree_in_doc),
+ _ => ()
+ }
+
+ if tree_in_doc {
+ let element: &JSRef<Element> = ElementCast::from_ref(self);
+
+ // 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.get_attribute(Null, "rel").root();
+ rel.map(|rel| rel.deref().value().as_slice().to_string())
+ };
+ let href = {
+ let href = element.get_attribute(Null, "href").root();
+ href.map(|href| href.deref().value().as_slice().to_string())
+ };
+
+ 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")) {
+ self.handle_stylesheet_url(href.as_slice());
+ }
+ }
+ _ => {}
+ }
+ }
+ }
+}
+
+trait PrivateHTMLLinkElementHelpers {
+ fn handle_stylesheet_url(&self, href: &str);
+}
+
+impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
+ fn handle_stylesheet_url(&self, href: &str) {
+ let window = window_from_node(self).root();
+ match UrlParser::new().base_url(&window.deref().page().get_url()).parse(href) {
+ Ok(url) => {
+ let LayoutChan(ref layout_chan) = *window.deref().page().layout_chan;
+ layout_chan.send(LoadStylesheetMsg(url));
+ }
+ Err(e) => debug!("Parsing url {:s} failed: {:?}", href, e)
+ }
+ }
}
impl Reflectable for HTMLLinkElement {
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index 30aa81f15f1..d968c3bc6ee 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -13,9 +13,9 @@ use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
-use html::cssparse::parse_inline_css;
use layout_interface::{AddStylesheetMsg, LayoutChan};
use servo_util::str::DOMString;
+use style::Stylesheet;
#[deriving(Encodable)]
#[must_root]
@@ -56,7 +56,7 @@ impl<'a> StyleElementHelpers for JSRef<'a, HTMLStyleElement> {
let url = win.deref().page().get_url();
let data = node.GetTextContent().expect("Element.textContent must be a string");
- let sheet = parse_inline_css(url, data);
+ let sheet = Stylesheet::from_str(data.as_slice(), url);
let LayoutChan(ref layout_chan) = *win.deref().page().layout_chan;
layout_chan.send(AddStylesheetMsg(sheet));
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index b46adc488fd..9e1b73feb12 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -611,7 +611,7 @@ impl<'m, 'n> NodeHelpers<'m, 'n> for JSRef<'n, Node> {
Ok(ref selectors) => {
let root = self.ancestors().last().unwrap_or(self.clone());
for node in root.traverse_preorder() {
- if node.is_element() && matches(selectors, &node) {
+ if node.is_element() && matches(selectors, &node, &mut None) {
let elem: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
return Ok(Some(Temporary::from_rooted(elem)));
}
@@ -632,7 +632,9 @@ impl<'m, 'n> NodeHelpers<'m, 'n> for JSRef<'n, Node> {
// Step 3.
Ok(ref selectors) => {
nodes = root.traverse_preorder().filter(
- |node| node.is_element() && matches(selectors, node)).collect()
+ // TODO(cgaebel): Is it worth it to build a bloom filter here
+ // (instead of passing `None`)? Probably.
+ |node| node.is_element() && matches(selectors, node, &mut None)).collect()
}
}
let window = window_from_node(self).root();
@@ -1990,6 +1992,10 @@ impl<'a> style::TNode<JSRef<'a, Element>> for JSRef<'a, Node> {
(self as &NodeHelpers).parent_node().map(|node| *node.root())
}
+ fn tnode_first_child(&self) -> Option<JSRef<'a, Node>> {
+ (self as &NodeHelpers).first_child().map(|node| *node.root())
+ }
+
fn prev_sibling(&self) -> Option<JSRef<'a, Node>> {
(self as &NodeHelpers).prev_sibling().map(|node| *node.root())
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index d9c9cd5c6c6..75f1aaea79b 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -29,14 +29,15 @@ use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::{DOMString,HTML_SPACE_CHARACTERS};
use servo_util::task::{spawn_named};
-use js::jsapi::JS_CallFunctionValue;
+use js::jsapi::{JS_CallFunctionValue, JS_EvaluateUCScript};
use js::jsapi::JSContext;
use js::jsapi::{JS_GC, JS_GetRuntime};
use js::jsval::JSVal;
-use js::jsval::NullValue;
+use js::jsval::{UndefinedValue, NullValue};
use js::rust::with_compartment;
use url::{Url, UrlParser};
+use libc;
use serialize::base64::{FromBase64, ToBase64, STANDARD};
use std::collections::hashmap::HashMap;
use std::cell::{Cell, RefCell};
@@ -359,6 +360,7 @@ pub trait WindowHelpers {
fn init_browser_context(&self, doc: &JSRef<Document>);
fn load_url(&self, href: DOMString);
fn handle_fire_timer(&self, timer_id: TimerId, cx: *mut JSContext);
+ fn evaluate_js_with_result(&self, code: &str) -> JSVal;
}
trait PrivateWindowHelpers {
@@ -366,6 +368,25 @@ trait PrivateWindowHelpers {
}
impl<'a> WindowHelpers for JSRef<'a, Window> {
+ fn evaluate_js_with_result(&self, code: &str) -> JSVal {
+ let global = self.reflector().get_jsobject();
+ let code: Vec<u16> = code.as_slice().utf16_units().collect();
+ let mut rval = UndefinedValue();
+ let filename = "".to_c_str();
+ let cx = self.get_cx();
+
+ with_compartment(cx, global, || {
+ unsafe {
+ if JS_EvaluateUCScript(cx, global, code.as_ptr(),
+ code.len() as libc::c_uint,
+ filename.as_ptr(), 1, &mut rval) == 0 {
+ debug!("error evaluating JS string");
+ }
+ rval
+ }
+ })
+ }
+
fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
// FIXME This should probably be ReflowForQuery, not Display. All queries currently
// currently rely on the display list, which means we can't destroy it by
diff --git a/components/script/html/cssparse.rs b/components/script/html/cssparse.rs
deleted file mode 100644
index 473b64c7d76..00000000000
--- a/components/script/html/cssparse.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-/// Some little helpers for hooking up the HTML parser with the CSS parser.
-
-use std::comm::{channel, Receiver};
-use encoding::EncodingRef;
-use encoding::all::UTF_8;
-use style::Stylesheet;
-use servo_net::resource_task::{Load, LoadData, LoadResponse, ProgressMsg, Payload, Done, ResourceTask};
-use servo_util::task::spawn_named;
-use url::Url;
-
-/// Where a style sheet comes from.
-pub enum StylesheetProvenance {
- UrlProvenance(Url, ResourceTask),
- InlineProvenance(Url, String),
-}
-
-// Parses the style data and returns the stylesheet
-pub fn parse_inline_css(url: Url, data: String) -> Stylesheet {
- parse_css(InlineProvenance(url, data))
-}
-
-fn parse_css(provenance: StylesheetProvenance) -> Stylesheet {
- // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
- let environment_encoding = UTF_8 as EncodingRef;
-
- match provenance {
- UrlProvenance(url, resource_task) => {
- debug!("cssparse: loading style sheet at {:s}", url.serialize());
- let (input_chan, input_port) = channel();
- resource_task.send(Load(LoadData::new(url), input_chan));
- let LoadResponse { metadata: metadata, progress_port: progress_port , ..}
- = input_port.recv();
- let final_url = &metadata.final_url;
- let protocol_encoding_label = metadata.charset.as_ref().map(|s| s.as_slice());
- let iter = ProgressMsgPortIterator { progress_port: progress_port };
- Stylesheet::from_bytes_iter(
- iter, final_url.clone(),
- protocol_encoding_label, Some(environment_encoding))
- }
- InlineProvenance(base_url, data) => {
- debug!("cssparse: loading inline stylesheet {:s}", data);
- Stylesheet::from_str(data.as_slice(), base_url)
- }
- }
-}
-
-pub fn spawn_css_parser(provenance: StylesheetProvenance) -> Receiver<Stylesheet> {
- let (result_chan, result_port) = channel();
-
- spawn_named("cssparser", proc() {
- result_chan.send(parse_css(provenance));
- });
-
- return result_port;
-}
-
-struct ProgressMsgPortIterator {
- progress_port: Receiver<ProgressMsg>
-}
-
-impl Iterator<Vec<u8>> for ProgressMsgPortIterator {
- fn next(&mut self) -> Option<Vec<u8>> {
- match self.progress_port.recv() {
- Payload(data) => Some(data),
- Done(..) => None
- }
- }
-}
diff --git a/components/script/html/hubbub_html_parser.rs b/components/script/html/hubbub_html_parser.rs
index 89d817b9380..74dd6ca933b 100644
--- a/components/script/html/hubbub_html_parser.rs
+++ b/components/script/html/hubbub_html_parser.rs
@@ -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;
@@ -55,25 +53,24 @@ macro_rules! handle_element(
pub struct JSFile {
pub data: String,
- pub url: Url
+ pub url: Option<Url>,
}
pub type JSResult = Vec<JSFile>;
-enum CSSMessage {
- CSSTaskNewFile(StylesheetProvenance),
- CSSTaskExit
+pub enum HTMLInput {
+ InputString(String),
+ InputUrl(Url),
}
enum JSMessage {
JSTaskNewFile(Url),
- JSTaskNewInlineScript(String, Url),
+ JSTaskNewInlineScript(String, Option<Url>),
JSTaskExit
}
/// Messages generated by the HTML parser upon discovery of additional resources
pub enum HtmlDiscoveryMessage {
- HtmlDiscoveredStyle(Stylesheet),
HtmlDiscoveredScript(JSResult)
}
@@ -95,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) {
@@ -148,7 +108,7 @@ fn js_script_listener(to_parent: Sender<HtmlDiscoveryMessage>,
let decoded = UTF_8.decode(bytes.as_slice(), DecodeReplace).unwrap();
result_vec.push(JSFile {
data: decoded.to_string(),
- url: metadata.final_url,
+ url: Some(metadata.final_url),
});
}
}
@@ -326,20 +286,13 @@ pub fn build_element_from_tag(tag: DOMString, ns: Namespace, document: &JSRef<Do
pub fn parse_html(page: &Page,
document: &JSRef<Document>,
- url: Url,
+ input: HTMLInput,
resource_task: ResourceTask)
-> HtmlParserResult {
- debug!("Hubbub: parsing {:?}", url);
- // 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);
- });
+ debug!("Hubbub: parsing {:?}", input);
// 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();
@@ -347,38 +300,50 @@ pub fn parse_html(page: &Page,
js_script_listener(js_result_chan, js_msg_port, resource_task2.clone());
});
- // Wait for the LoadResponse so that the parser knows the final URL.
- let (input_chan, input_port) = channel();
- resource_task.send(Load(LoadData::new(url.clone()), input_chan));
- let load_response = input_port.recv();
+ let (base_url, load_response) = match input {
+ InputUrl(ref url) => {
+ // Wait for the LoadResponse so that the parser knows the final URL.
+ let (input_chan, input_port) = channel();
+ resource_task.send(Load(LoadData::new(url.clone()), input_chan));
+ let load_response = input_port.recv();
- debug!("Fetched page; metadata is {:?}", load_response.metadata);
+ debug!("Fetched page; metadata is {:?}", load_response.metadata);
- load_response.metadata.headers.map(|headers| {
- let header = headers.iter().find(|h|
- h.header_name().as_slice().to_ascii_lower() == "last-modified".to_string()
- );
+ load_response.metadata.headers.as_ref().map(|headers| {
+ let header = headers.iter().find(|h|
+ h.header_name().as_slice().to_ascii_lower() == "last-modified".to_string()
+ );
- match header {
- Some(h) => document.set_last_modified(
- parse_last_modified(h.header_value().as_slice())),
- None => {},
- };
- });
+ match header {
+ Some(h) => document.set_last_modified(
+ parse_last_modified(h.header_value().as_slice())),
+ None => {},
+ };
+ });
- let base_url = &load_response.metadata.final_url;
+ let base_url = load_response.metadata.final_url.clone();
- {
- // Store the final URL before we start parsing, so that DOM routines
- // (e.g. HTMLImageElement::update_image) can resolve relative URLs
- // correctly.
- *page.mut_url() = Some((base_url.clone(), true));
- }
+ {
+ // Store the final URL before we start parsing, so that DOM routines
+ // (e.g. HTMLImageElement::update_image) can resolve relative URLs
+ // correctly.
+ *page.mut_url() = Some((base_url.clone(), true));
+ }
+
+ (Some(base_url), Some(load_response))
+ },
+ InputString(_) => {
+ match *page.url() {
+ Some((ref page_url, _)) => (Some(page_url.clone()), None),
+ None => (None, None),
+ }
+ },
+ };
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);
@@ -430,46 +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);
- match UrlParser::new().base_url(base_url).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| {
@@ -550,8 +475,14 @@ pub fn parse_html(page: &Page,
match script_element.get_attribute(Null, "src").root() {
Some(src) => {
debug!("found script: {:s}", src.deref().Value());
- match UrlParser::new().base_url(base_url)
- .parse(src.deref().value().as_slice()) {
+ let mut url_parser = UrlParser::new();
+ match 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) => js_chan2.send(JSTaskNewFile(new_url)),
Err(e) => debug!("Parsing url {:s} failed: {:?}", src.deref().Value(), e)
};
@@ -580,29 +511,36 @@ pub fn parse_html(page: &Page,
parser.set_tree_handler(&mut tree_handler);
debug!("set tree handler");
debug!("loaded page");
- match load_response.metadata.content_type {
- Some((ref t, _)) if t.as_slice().eq_ignore_ascii_case("image") => {
- let page = format!("<html><body><img src='{:s}' /></body></html>", base_url.serialize());
- parser.parse_chunk(page.into_bytes().as_slice());
+ match input {
+ InputString(s) => {
+ parser.parse_chunk(s.into_bytes().as_slice());
},
- _ => loop {
- match load_response.progress_port.recv() {
- Payload(data) => {
- debug!("received data");
- parser.parse_chunk(data.as_slice());
- }
- Done(Err(err)) => {
- fail!("Failed to load page URL {:s}, error: {:s}", url.serialize(), err);
- }
- Done(..) => {
- break;
+ InputUrl(url) => {
+ let load_response = load_response.unwrap();
+ match load_response.metadata.content_type {
+ Some((ref t, _)) if t.as_slice().eq_ignore_ascii_case("image") => {
+ let page = format!("<html><body><img src='{:s}' /></body></html>", base_url.get_ref().serialize());
+ parser.parse_chunk(page.into_bytes().as_slice());
+ },
+ _ => loop {
+ match load_response.progress_port.recv() {
+ Payload(data) => {
+ debug!("received data");
+ parser.parse_chunk(data.as_slice());
+ }
+ Done(Err(err)) => {
+ fail!("Failed to load page URL {:s}, error: {:s}", url.serialize(), err);
+ }
+ Done(..) => {
+ break;
+ }
+ }
}
}
- }
+ },
}
debug!("finished parsing");
- css_chan.send(CSSTaskExit);
js_chan.send(JSTaskExit);
HtmlParserResult {
diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs
index 1e5e23f9c9a..0c82c61447d 100644
--- a/components/script/layout_interface.rs
+++ b/components/script/layout_interface.rs
@@ -29,6 +29,9 @@ pub enum Msg {
/// Adds the given stylesheet to the document.
AddStylesheetMsg(Stylesheet),
+ /// Adds the given stylesheet to the document.
+ LoadStylesheetMsg(Url),
+
/// Requests a reflow.
ReflowMsg(Box<Reflow>),
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 939238df1a4..9f3effaa368 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -200,7 +200,6 @@ pub mod dom {
/// Parsers for HTML and CSS.
pub mod html {
- pub mod cssparse;
pub mod hubbub_html_parser;
}
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 88e2f42415a..8dc4578abb8 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -6,6 +6,7 @@
//! and layout tasks.
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, EventCast};
+use dom::bindings::conversions::{FromJSValConvertible, Empty};
use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, RootCollection, Temporary, OptionalSettable};
use dom::bindings::js::OptionalRootable;
@@ -22,10 +23,8 @@ use dom::node::{ElementNodeTypeId, Node, NodeHelpers};
use dom::window::{TimerId, Window, WindowHelpers};
use dom::worker::{Worker, TrustedWorkerAddress};
use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress};
-use html::hubbub_html_parser::HtmlParserResult;
-use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredScript};
+use html::hubbub_html_parser::{InputString, InputUrl, HtmlParserResult, HtmlDiscoveredScript};
use html::hubbub_html_parser;
-use layout_interface::AddStylesheetMsg;
use layout_interface::{ScriptLayoutChan, LayoutChan, MatchSelectorsDocumentDamage};
use layout_interface::{ReflowDocumentDamage, ReflowForDisplay};
use layout_interface::ContentChangedDocumentDamage;
@@ -590,7 +589,7 @@ impl ScriptTask {
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
fn load(&self, pipeline_id: PipelineId, url: Url) {
- debug!("ScriptTask: loading {:?} on page {:?}", url, pipeline_id);
+ debug!("ScriptTask: loading {} on page {:?}", url, pipeline_id);
let mut page = self.page.borrow_mut();
let page = page.find(pipeline_id).expect("ScriptTask: received a load
@@ -610,6 +609,9 @@ impl ScriptTask {
_ => (),
}
+ let is_javascript = url.scheme.as_slice() == "javascript";
+ let last_url = last_loaded_url.map(|(ref loaded, _)| loaded.clone());
+
let cx = self.js_context.borrow();
let cx = cx.get_ref();
// Create the window and document objects.
@@ -619,17 +621,39 @@ impl ScriptTask {
self.control_chan.clone(),
self.compositor.dup(),
self.image_cache_task.clone()).root();
- let document = Document::new(&*window, Some(url.clone()), HTMLDocument, None).root();
+ let doc_url = if is_javascript {
+ let doc_url = match last_url {
+ Some(url) => Some(url.clone()),
+ None => Url::parse("about:blank").ok(),
+ };
+ *page.mut_url() = Some((doc_url.get_ref().clone(), true));
+ doc_url
+ } else {
+ Some(url.clone())
+ };
+ let document = Document::new(&*window, doc_url, HTMLDocument, None).root();
+
window.deref().init_browser_context(&*document);
self.compositor.set_ready_state(pipeline_id, Loading);
+
+ let parser_input = if !is_javascript {
+ InputUrl(url.clone())
+ } else {
+ let evalstr = url.non_relative_scheme_data().unwrap();
+ let jsval = window.evaluate_js_with_result(evalstr);
+ let strval = FromJSValConvertible::from_jsval(self.get_cx(), jsval, Empty);
+ InputString(strval.unwrap_or("".to_string()))
+ };
+
// Parse HTML.
//
// Note: We can parse the next document in parallel with any previous documents.
- let html_parsing_result = hubbub_html_parser::parse_html(&*page,
- &*document,
- url.clone(),
- self.resource_task.clone());
+ let html_parsing_result =
+ hubbub_html_parser::parse_html(&*page,
+ &*document,
+ parser_input,
+ self.resource_task.clone());
let HtmlParserResult {
discovery_port
@@ -656,15 +680,12 @@ impl ScriptTask {
assert!(js_scripts.is_none());
js_scripts = Some(scripts);
}
- Ok(HtmlDiscoveredStyle(sheet)) => {
- let LayoutChan(ref chan) = *page.layout_chan;
- chan.send(AddStylesheetMsg(sheet));
- }
Err(()) => break
}
}
// Kick off the initial reflow of the page.
+ debug!("kicking off initial reflow of {}", url);
document.deref().content_changed();
let fragment = url.fragment.as_ref().map(|ref fragment| fragment.to_string());
@@ -684,9 +705,14 @@ impl ScriptTask {
// Evaluate every script in the document.
for file in js_scripts.iter() {
let global_obj = window.reflector().get_jsobject();
+ let filename = match file.url {
+ None => String::new(),
+ Some(ref url) => url.serialize(),
+ };
+
//FIXME: this should have some kind of error handling, or explicitly
// drop an exception on the floor.
- match cx.evaluate_script(global_obj, file.data.clone(), file.url.serialize(), 1) {
+ match cx.evaluate_script(global_obj, file.data.clone(), filename, 1) {
Ok(_) => (),
Err(_) => println!("evaluate_script failed")
}