script: Add infrastructure to track subresource loads in <link> and <style> elements.

This commit is contained in:
Emilio Cobos Álvarez 2016-12-16 12:16:41 +01:00
parent b86aa41568
commit 21bf91c386
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
3 changed files with 86 additions and 6 deletions

View file

@ -244,7 +244,7 @@ fn create_html_element(name: QualName,
local_name!("span") => make!(HTMLSpanElement), local_name!("span") => make!(HTMLSpanElement),
local_name!("strike") => make!(HTMLElement), local_name!("strike") => make!(HTMLElement),
local_name!("strong") => make!(HTMLElement), local_name!("strong") => make!(HTMLElement),
local_name!("style") => make!(HTMLStyleElement), local_name!("style") => make!(HTMLStyleElement, creator),
local_name!("sub") => make!(HTMLElement), local_name!("sub") => make!(HTMLElement),
local_name!("summary") => make!(HTMLElement), local_name!("summary") => make!(HTMLElement),
local_name!("sup") => make!(HTMLElement), local_name!("sup") => make!(HTMLElement),

View file

@ -62,6 +62,11 @@ pub struct HTMLLinkElement {
/// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts
parser_inserted: Cell<bool>, parser_inserted: Cell<bool>,
/// The number of loads that this link element has triggered (could be more
/// than one because of imports), and how many of them have finished.
pending_loads: Cell<u32>,
/// Whether any of the loads have failed.
any_failed_load: Cell<bool>,
} }
impl HTMLLinkElement { impl HTMLLinkElement {
@ -73,6 +78,8 @@ impl HTMLLinkElement {
parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), parser_inserted: Cell::new(creator == ElementCreator::ParserCreated),
stylesheet: DOMRefCell::new(None), stylesheet: DOMRefCell::new(None),
cssom_stylesheet: MutNullableJS::new(None), cssom_stylesheet: MutNullableJS::new(None),
pending_loads: Cell::new(0),
any_failed_load: Cell::new(false),
} }
} }
@ -86,6 +93,16 @@ impl HTMLLinkElement {
HTMLLinkElementBinding::Wrap) HTMLLinkElementBinding::Wrap)
} }
pub fn parser_inserted(&self) -> bool {
self.parser_inserted.get()
}
pub fn set_stylesheet(&self, s: Arc<Stylesheet>) {
assert!(self.stylesheet.borrow().is_none());
*self.stylesheet.borrow_mut() = Some(s);
}
pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> { pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
self.stylesheet.borrow().clone() self.stylesheet.borrow().clone()
} }
@ -217,6 +234,28 @@ impl VirtualMethods for HTMLLinkElement {
impl HTMLLinkElement { impl HTMLLinkElement {
pub fn increment_pending_loads_count(&self) {
self.pending_loads.set(self.pending_loads.get() + 1)
}
/// Returns None if there are still pending loads, or whether any load has
/// failed since the loads started.
pub fn load_finished(&self, succeeded: bool) -> Option<bool> {
assert!(self.pending_loads.get() > 0, "What finished?");
if !succeeded {
self.any_failed_load.set(true);
}
self.pending_loads.set(self.pending_loads.get() - 1);
if self.pending_loads.get() != 0 {
return None;
}
let any_failed = self.any_failed_load.get();
self.any_failed_load.set(false);
Some(any_failed)
}
/// https://html.spec.whatwg.org/multipage/#concept-link-obtain /// https://html.spec.whatwg.org/multipage/#concept-link-obtain
fn handle_stylesheet_url(&self, href: &str) { fn handle_stylesheet_url(&self, href: &str) {
let document = document_from_node(self); let document = document_from_node(self);
@ -231,8 +270,11 @@ impl HTMLLinkElement {
// Step 2. // Step 2.
let url = match document.base_url().join(href) { let url = match document.base_url().join(href) {
Err(e) => return debug!("Parsing url {} failed: {}", href, e),
Ok(url) => url, Ok(url) => url,
Err(e) => {
debug!("Parsing url {} failed: {}", href, e);
return;
}
}; };
let element = self.upcast::<Element>(); let element = self.upcast::<Element>();

View file

@ -12,17 +12,20 @@ use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::str::DOMString; use dom::bindings::str::DOMString;
use dom::cssstylesheet::CSSStyleSheet; use dom::cssstylesheet::CSSStyleSheet;
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::{Element, ElementCreator};
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node}; use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node};
use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::stylesheet::StyleSheet as DOMStyleSheet;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use html5ever_atoms::LocalName; use html5ever_atoms::LocalName;
use script_layout_interface::message::Msg; use script_layout_interface::message::Msg;
use std::cell::Cell;
use std::sync::Arc; use std::sync::Arc;
use style::media_queries::parse_media_query_list; use style::media_queries::parse_media_query_list;
use style::parser::ParserContextExtraData; use style::parser::ParserContextExtraData;
use style::stylesheets::{Stylesheet, Origin}; use style::stylesheets::{Stylesheet, Origin};
use stylesheet_loader::StylesheetLoader;
#[dom_struct] #[dom_struct]
pub struct HTMLStyleElement { pub struct HTMLStyleElement {
@ -30,28 +33,59 @@ pub struct HTMLStyleElement {
#[ignore_heap_size_of = "Arc"] #[ignore_heap_size_of = "Arc"]
stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
cssom_stylesheet: MutNullableJS<CSSStyleSheet>, cssom_stylesheet: MutNullableJS<CSSStyleSheet>,
/// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts
parser_inserted: Cell<bool>,
pending_loads: Cell<u32>,
any_failed_load: Cell<bool>,
} }
impl HTMLStyleElement { impl HTMLStyleElement {
fn new_inherited(local_name: LocalName, fn new_inherited(local_name: LocalName,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: &Document) -> HTMLStyleElement { document: &Document,
creator: ElementCreator) -> HTMLStyleElement {
HTMLStyleElement { HTMLStyleElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document), htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
stylesheet: DOMRefCell::new(None), stylesheet: DOMRefCell::new(None),
cssom_stylesheet: MutNullableJS::new(None), cssom_stylesheet: MutNullableJS::new(None),
parser_inserted: Cell::new(creator == ElementCreator::ParserCreated),
pending_loads: Cell::new(0),
any_failed_load: Cell::new(false),
} }
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(local_name: LocalName, pub fn new(local_name: LocalName,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: &Document) -> Root<HTMLStyleElement> { document: &Document,
Node::reflect_node(box HTMLStyleElement::new_inherited(local_name, prefix, document), creator: ElementCreator) -> Root<HTMLStyleElement> {
Node::reflect_node(box HTMLStyleElement::new_inherited(local_name, prefix, document, creator),
document, document,
HTMLStyleElementBinding::Wrap) HTMLStyleElementBinding::Wrap)
} }
pub fn increment_pending_loads_count(&self) {
self.pending_loads.set(self.pending_loads.get() + 1)
}
/// Returns None if there are still pending loads, or whether any load has
/// failed since the loads started.
pub fn load_finished(&self, succeeded: bool) -> Option<bool> {
assert!(self.pending_loads.get() > 0, "What finished?");
if !succeeded {
self.any_failed_load.set(true);
}
self.pending_loads.set(self.pending_loads.get() - 1);
if self.pending_loads.get() != 0 {
return None;
}
let any_failed = self.any_failed_load.get();
self.any_failed_load.set(false);
Some(any_failed)
}
pub fn parse_own_css(&self) { pub fn parse_own_css(&self) {
let node = self.upcast::<Node>(); let node = self.upcast::<Node>();
let element = self.upcast::<Element>(); let element = self.upcast::<Element>();
@ -94,6 +128,10 @@ impl HTMLStyleElement {
}) })
}) })
} }
pub fn parser_inserted(&self) -> bool {
self.parser_inserted.get()
}
} }
impl VirtualMethods for HTMLStyleElement { impl VirtualMethods for HTMLStyleElement {