aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/create.rs2
-rw-r--r--components/script/dom/document.rs58
-rw-r--r--components/script/dom/htmllinkelement.rs163
-rw-r--r--components/script/dom/htmlmetaelement.rs29
-rw-r--r--components/script/dom/htmlstyleelement.rs24
-rw-r--r--components/script/dom/window.rs7
6 files changed, 224 insertions, 59 deletions
diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs
index 4e2b07399b1..2f1d35d3b59 100644
--- a/components/script/dom/create.rs
+++ b/components/script/dom/create.rs
@@ -174,7 +174,7 @@ pub fn create_element(name: QualName, prefix: Option<Atom>,
atom!("label") => make!(HTMLLabelElement),
atom!("legend") => make!(HTMLLegendElement),
atom!("li") => make!(HTMLLIElement),
- atom!("link") => make!(HTMLLinkElement),
+ atom!("link") => make!(HTMLLinkElement, creator),
// https://html.spec.whatwg.org/multipage/#other-elements,-attributes-and-apis:listing
atom!("listing") => make!(HTMLPreElement),
atom!("main") => make!(HTMLElement),
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index b39adbc53fc..4d5fb5e2ccd 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -48,7 +48,10 @@ use dom::htmlheadelement::HTMLHeadElement;
use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmliframeelement::{self, HTMLIFrameElement};
use dom::htmlimageelement::HTMLImageElement;
+use dom::htmllinkelement::HTMLLinkElement;
+use dom::htmlmetaelement::HTMLMetaElement;
use dom::htmlscriptelement::HTMLScriptElement;
+use dom::htmlstyleelement::HTMLStyleElement;
use dom::htmltitleelement::HTMLTitleElement;
use dom::keyboardevent::KeyboardEvent;
use dom::location::Location;
@@ -96,8 +99,10 @@ use std::default::Default;
use std::iter::FromIterator;
use std::ptr;
use std::rc::Rc;
+use std::sync::Arc;
use std::sync::mpsc::channel;
use string_cache::{Atom, QualName};
+use style::stylesheets::Stylesheet;
use time;
use url::Url;
use util::str::{DOMString, split_html_space_chars, str_join};
@@ -135,6 +140,10 @@ pub struct Document {
scripts: MutNullableHeap<JS<HTMLCollection>>,
anchors: MutNullableHeap<JS<HTMLCollection>>,
applets: MutNullableHeap<JS<HTMLCollection>>,
+ /// List of stylesheets associated with nodes in this document. |None| if the list needs to be refreshed.
+ stylesheets: DOMRefCell<Option<Vec<Arc<Stylesheet>>>>,
+ /// Whether the list of stylesheets has changed since the last reflow was triggered.
+ stylesheets_changed_since_reflow: Cell<bool>,
ready_state: Cell<DocumentReadyState>,
/// Whether the DOMContentLoaded event has already been dispatched.
domcontentloaded_dispatched: Cell<bool>,
@@ -983,6 +992,21 @@ impl Document {
count_cell.set(count_cell.get() - 1);
}
+ pub fn invalidate_stylesheets(&self) {
+ self.stylesheets_changed_since_reflow.set(true);
+ *self.stylesheets.borrow_mut() = None;
+ // Mark the document element dirty so a reflow will be performed.
+ self.get_html_element().map(|root| {
+ root.upcast::<Node>().dirty(NodeDamage::NodeStyleDamaged);
+ });
+ }
+
+ pub fn get_and_reset_stylesheets_changed_since_reflow(&self) -> bool {
+ let changed = self.stylesheets_changed_since_reflow.get();
+ self.stylesheets_changed_since_reflow.set(false);
+ changed
+ }
+
pub fn set_pending_parsing_blocking_script(&self, script: Option<&HTMLScriptElement>) {
assert!(self.get_pending_parsing_blocking_script().is_none() || script.is_none());
self.pending_parsing_blocking_script.set(script);
@@ -1100,6 +1124,13 @@ impl Document {
if parser.is_suspended() {
parser.resume();
}
+ } else if self.reflow_timeout.get().is_none() {
+ // If we don't have a parser, and the reflow timer has been reset, explicitly
+ // trigger a reflow.
+ if let LoadType::Stylesheet(_) = load {
+ self.window().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery,
+ ReflowReason::StylesheetLoaded);
+ }
}
let loader = self.loader.borrow();
@@ -1304,6 +1335,8 @@ impl Document {
scripts: Default::default(),
anchors: Default::default(),
applets: Default::default(),
+ stylesheets: DOMRefCell::new(None),
+ stylesheets_changed_since_reflow: Cell::new(false),
ready_state: Cell::new(ready_state),
domcontentloaded_dispatched: Cell::new(domcontentloaded_dispatched),
possibly_focused: Default::default(),
@@ -1369,6 +1402,31 @@ impl Document {
self.GetDocumentElement().and_then(Root::downcast)
}
+ /// Returns the list of stylesheets associated with nodes in the document.
+ pub fn stylesheets(&self) -> Ref<Vec<Arc<Stylesheet>>> {
+ {
+ let mut stylesheets = self.stylesheets.borrow_mut();
+ if stylesheets.is_none() {
+ let new_stylesheets: Vec<Arc<Stylesheet>> = self.upcast::<Node>()
+ .traverse_preorder()
+ .filter_map(|node| {
+ if let Some(node) = node.downcast::<HTMLStyleElement>() {
+ node.get_stylesheet()
+ } else if let Some(node) = node.downcast::<HTMLLinkElement>() {
+ node.get_stylesheet()
+ } else if let Some(node) = node.downcast::<HTMLMetaElement>() {
+ node.get_stylesheet()
+ } else {
+ None
+ }
+ })
+ .collect();
+ *stylesheets = Some(new_stylesheets);
+ };
+ }
+ Ref::map(self.stylesheets.borrow(), |t| t.as_ref().unwrap())
+ }
+
/// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document
pub fn appropriate_template_contents_owner_document(&self) -> Root<Document> {
self.appropriate_template_contents_owner_document.or_init(|| {
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 6fd36f60074..2860c98dd5c 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -5,55 +5,76 @@
use cssparser::Parser as CssParser;
use document_loader::LoadType;
use dom::attr::{Attr, AttrValue};
+use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::js::{RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::document::Document;
use dom::domtokenlist::DOMTokenList;
-use dom::element::{AttributeMutation, Element};
-use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::eventtarget::EventTarget;
+use dom::element::{AttributeMutation, Element, ElementCreator};
use dom::htmlelement::HTMLElement;
-use dom::node::{Node, window_from_node};
+use dom::node::{Node, document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods;
+use encoding::EncodingRef;
+use encoding::all::UTF_8;
+use ipc_channel::ipc;
+use ipc_channel::router::ROUTER;
use layout_interface::{LayoutChan, Msg};
use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg;
-use script_traits::StylesheetLoadResponder;
+use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata};
+use network_listener::{NetworkListener, PreInvoke};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
+use std::cell::Cell;
use std::default::Default;
+use std::mem;
+use std::sync::{Arc, Mutex};
use string_cache::Atom;
-use style::media_queries::parse_media_query_list;
-use url::UrlParser;
+use style::media_queries::{MediaQueryList, parse_media_query_list};
+use style::stylesheets::{Origin, Stylesheet};
+use url::{Url, UrlParser};
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
+no_jsmanaged_fields!(Stylesheet);
+
#[dom_struct]
pub struct HTMLLinkElement {
htmlelement: HTMLElement,
rel_list: MutNullableHeap<JS<DOMTokenList>>,
+ stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
+
+ /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts
+ parser_inserted: Cell<bool>,
}
impl HTMLLinkElement {
- fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLLinkElement {
+ fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document,
+ creator: ElementCreator) -> HTMLLinkElement {
HTMLLinkElement {
htmlelement: HTMLElement::new_inherited(localName, prefix, document),
rel_list: Default::default(),
+ parser_inserted: Cell::new(creator == ElementCreator::ParserCreated),
+ stylesheet: DOMRefCell::new(None),
}
}
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
- document: &Document) -> Root<HTMLLinkElement> {
- let element = HTMLLinkElement::new_inherited(localName, prefix, document);
+ document: &Document,
+ creator: ElementCreator) -> Root<HTMLLinkElement> {
+ let element = HTMLLinkElement::new_inherited(localName, prefix, document, creator);
Node::reflect_node(box element, document, HTMLLinkElementBinding::Wrap)
}
+
+ pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
+ self.stylesheet.borrow().clone()
+ }
}
fn get_attr(element: &Element, local_name: &Atom) -> Option<String> {
@@ -64,7 +85,7 @@ fn get_attr(element: &Element, local_name: &Atom) -> Option<String> {
})
}
-fn is_stylesheet(value: &Option<String>) -> bool {
+fn string_is_stylesheet(value: &Option<String>) -> bool {
match *value {
Some(ref value) => {
value.split(HTML_SPACE_CHARACTERS)
@@ -100,14 +121,14 @@ impl VirtualMethods for HTMLLinkElement {
let rel = get_attr(self.upcast(), &atom!(rel));
match attr.local_name() {
&atom!(href) => {
- if is_stylesheet(&rel) {
+ if string_is_stylesheet(&rel) {
self.handle_stylesheet_url(&attr.value());
} else if is_favicon(&rel) {
self.handle_favicon_url(&attr.value());
}
},
&atom!(media) => {
- if is_stylesheet(&rel) {
+ if string_is_stylesheet(&rel) {
self.handle_stylesheet_url(&attr.value());
}
},
@@ -134,7 +155,7 @@ impl VirtualMethods for HTMLLinkElement {
let href = get_attr(element, &atom!("href"));
match (rel, href) {
- (ref rel, Some(ref href)) if is_stylesheet(rel) => {
+ (ref rel, Some(ref href)) if string_is_stylesheet(rel) => {
self.handle_stylesheet_url(href);
}
(ref rel, Some(ref href)) if is_favicon(rel) => {
@@ -164,13 +185,35 @@ impl HTMLLinkElement {
let mut css_parser = CssParser::new(&mq_str);
let media = parse_media_query_list(&mut css_parser);
+ // TODO: #8085 - Don't load external stylesheets if the node's mq doesn't match.
let doc = window.Document();
- let link_element = Trusted::new(window.get_cx(), self, window.script_chan().clone());
- let load_dispatcher = StylesheetLoadDispatcher::new(link_element);
+ let script_chan = window.script_chan();
+ let elem = Trusted::new(window.get_cx(), self, script_chan.clone());
+
+ let context = Arc::new(Mutex::new(StylesheetContext {
+ elem: elem,
+ media: Some(media),
+ data: vec!(),
+ metadata: None,
+ url: url.clone(),
+ }));
+
+ let (action_sender, action_receiver) = ipc::channel().unwrap();
+ let listener = NetworkListener {
+ context: context,
+ script_chan: script_chan,
+ };
+ let response_target = AsyncResponseTarget {
+ sender: action_sender,
+ };
+ ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
+ listener.notify(message.to().unwrap());
+ });
- let pending = doc.prepare_async_load(LoadType::Stylesheet(url.clone()));
- let LayoutChan(ref layout_chan) = window.layout_chan();
- layout_chan.send(Msg::LoadStylesheet(url, media, pending, box load_dispatcher)).unwrap();
+ if self.parser_inserted.get() {
+ doc.increment_script_blocking_stylesheet_count();
+ }
+ doc.load_async(LoadType::Stylesheet(url), response_target);
}
Err(e) => debug!("Parsing url {} failed: {}", href, e)
}
@@ -190,6 +233,62 @@ impl HTMLLinkElement {
}
}
+/// The context required for asynchronously loading an external stylesheet.
+struct StylesheetContext {
+ /// The element that initiated the request.
+ elem: Trusted<HTMLLinkElement>,
+ media: Option<MediaQueryList>,
+ /// The response body received to date.
+ data: Vec<u8>,
+ /// The response metadata received to date.
+ metadata: Option<Metadata>,
+ /// The initial URL requested.
+ url: Url,
+}
+
+impl PreInvoke for StylesheetContext {}
+
+impl AsyncResponseListener for StylesheetContext {
+ fn headers_available(&mut self, metadata: Metadata) {
+ self.metadata = Some(metadata);
+ }
+
+ fn data_available(&mut self, payload: Vec<u8>) {
+ let mut payload = payload;
+ self.data.append(&mut payload);
+ }
+
+ fn response_complete(&mut self, _status: Result<(), String>) {
+ let data = mem::replace(&mut self.data, vec!());
+ let metadata = self.metadata.take().unwrap();
+ // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
+ let environment_encoding = UTF_8 as EncodingRef;
+ let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s);
+ let final_url = metadata.final_url;
+ let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label,
+ Some(environment_encoding), Origin::Author);
+ let media = self.media.take().unwrap();
+ sheet.set_media(Some(media));
+ let sheet = Arc::new(sheet);
+
+ let elem = self.elem.root();
+ let elem = elem.r();
+ let document = document_from_node(elem);
+ let document = document.r();
+
+ let win = window_from_node(elem);
+ let LayoutChan(ref layout_chan) = win.r().layout_chan();
+ layout_chan.send(Msg::AddStylesheet(sheet.clone())).unwrap();
+
+ *elem.stylesheet.borrow_mut() = Some(sheet);
+ document.invalidate_stylesheets();
+ if elem.parser_inserted.get() {
+ document.decrement_script_blocking_stylesheet_count();
+ }
+ document.finish_load(LoadType::Stylesheet(self.url.clone()));
+ }
+}
+
impl HTMLLinkElementMethods for HTMLLinkElement {
// https://html.spec.whatwg.org/multipage/#dom-link-href
make_url_getter!(Href);
@@ -244,27 +343,3 @@ impl HTMLLinkElementMethods for HTMLLinkElement {
// https://html.spec.whatwg.org/multipage/#dom-link-target
make_setter!(SetTarget, "target");
}
-
-pub struct StylesheetLoadDispatcher {
- elem: Trusted<HTMLLinkElement>,
-}
-
-impl StylesheetLoadDispatcher {
- pub fn new(elem: Trusted<HTMLLinkElement>) -> StylesheetLoadDispatcher {
- StylesheetLoadDispatcher {
- elem: elem,
- }
- }
-}
-
-impl StylesheetLoadResponder for StylesheetLoadDispatcher {
- fn respond(self: Box<StylesheetLoadDispatcher>) {
- let elem = self.elem.root();
- let window = window_from_node(elem.r());
- let event = Event::new(GlobalRef::Window(window.r()),
- DOMString("load".to_owned()),
- EventBubbles::DoesNotBubble,
- EventCancelable::NotCancelable);
- event.fire(elem.upcast::<EventTarget>());
- }
-}
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index e615a0efbf7..dd0245104cb 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -2,6 +2,7 @@
* 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::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLMetaElementBinding;
use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods;
use dom::bindings::inheritance::Castable;
@@ -9,16 +10,18 @@ use dom::bindings::js::{Root, RootedReference};
use dom::document::Document;
use dom::element::Element;
use dom::htmlelement::HTMLElement;
-use dom::node::{Node, window_from_node};
+use dom::node::{Node, document_from_node};
use dom::virtualmethods::VirtualMethods;
-use layout_interface::{LayoutChan, Msg};
use std::ascii::AsciiExt;
+use std::sync::Arc;
+use style::stylesheets::{CSSRule, Origin, Stylesheet};
use style::viewport::ViewportRule;
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
#[dom_struct]
pub struct HTMLMetaElement {
htmlelement: HTMLElement,
+ stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
}
impl HTMLMetaElement {
@@ -26,7 +29,8 @@ impl HTMLMetaElement {
prefix: Option<DOMString>,
document: &Document) -> HTMLMetaElement {
HTMLMetaElement {
- htmlelement: HTMLElement::new_inherited(localName, prefix, document)
+ htmlelement: HTMLElement::new_inherited(localName, prefix, document),
+ stylesheet: DOMRefCell::new(None),
}
}
@@ -38,6 +42,10 @@ impl HTMLMetaElement {
Node::reflect_node(box element, document, HTMLMetaElementBinding::Wrap)
}
+ pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
+ self.stylesheet.borrow().clone()
+ }
+
fn process_attributes(&self) {
let element = self.upcast::<Element>();
if let Some(name) = element.get_attribute(&ns!(""), &atom!("name")).r() {
@@ -45,22 +53,25 @@ impl HTMLMetaElement {
let name = name.trim_matches(HTML_SPACE_CHARACTERS);
match name {
- "viewport" => self.translate_viewport(),
+ "viewport" => self.apply_viewport(),
_ => {}
}
}
}
- fn translate_viewport(&self) {
+ fn apply_viewport(&self) {
let element = self.upcast::<Element>();
if let Some(content) = element.get_attribute(&ns!(""), &atom!("content")).r() {
let content = content.value();
if !content.is_empty() {
if let Some(translated_rule) = ViewportRule::from_meta(&**content) {
- let win = window_from_node(self);
- let LayoutChan(ref layout_chan) = win.layout_chan();
-
- layout_chan.send(Msg::AddMetaViewport(translated_rule)).unwrap();
+ *self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet {
+ rules: vec![CSSRule::Viewport(translated_rule)],
+ origin: Origin::Author,
+ media: None,
+ }));
+ let doc = document_from_node(self);
+ doc.invalidate_stylesheets();
}
}
}
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index d1ac6dcc37b..e225ec33981 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::Parser as CssParser;
+use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
@@ -10,9 +11,10 @@ use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::Element;
use dom::htmlelement::HTMLElement;
-use dom::node::{ChildrenMutation, Node, window_from_node};
+use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use layout_interface::{LayoutChan, Msg};
+use std::sync::Arc;
use style::media_queries::parse_media_query_list;
use style::stylesheets::{Origin, Stylesheet};
use util::str::DOMString;
@@ -20,6 +22,7 @@ use util::str::DOMString;
#[dom_struct]
pub struct HTMLStyleElement {
htmlelement: HTMLElement,
+ stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
}
impl HTMLStyleElement {
@@ -27,7 +30,8 @@ impl HTMLStyleElement {
prefix: Option<DOMString>,
document: &Document) -> HTMLStyleElement {
HTMLStyleElement {
- htmlelement: HTMLElement::new_inherited(localName, prefix, document)
+ htmlelement: HTMLElement::new_inherited(localName, prefix, document),
+ stylesheet: DOMRefCell::new(None),
}
}
@@ -52,13 +56,23 @@ impl HTMLStyleElement {
Some(a) => String::from(&**a.value()),
None => String::new(),
};
+
+ let data = node.GetTextContent().expect("Element.textContent must be a string");
+ let mut sheet = Stylesheet::from_str(&data, url, Origin::Author);
let mut css_parser = CssParser::new(&mq_str);
let media = parse_media_query_list(&mut css_parser);
+ sheet.set_media(Some(media));
+ let sheet = Arc::new(sheet);
- let data = node.GetTextContent().expect("Element.textContent must be a string");
- let sheet = Stylesheet::from_str(&data, url, Origin::Author);
let LayoutChan(ref layout_chan) = win.layout_chan();
- layout_chan.send(Msg::AddStylesheet(sheet, media)).unwrap();
+ layout_chan.send(Msg::AddStylesheet(sheet.clone())).unwrap();
+ *self.stylesheet.borrow_mut() = Some(sheet);
+ let doc = document_from_node(self);
+ doc.r().invalidate_stylesheets();
+ }
+
+ pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> {
+ self.stylesheet.borrow().clone()
}
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index e296cea77d5..e50674c222c 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -99,6 +99,7 @@ pub enum ReflowReason {
WindowResize,
DOMContentLoaded,
DocumentLoaded,
+ StylesheetLoaded,
ImageLoaded,
RequestAnimationFrame,
WebFontLoaded,
@@ -915,6 +916,9 @@ impl Window {
debug_reflow_events(&goal, &query_type, &reason);
}
+ let document = self.Document();
+ let stylesheets_changed = document.get_and_reset_stylesheets_changed_since_reflow();
+
// Send new document and relevant styles to layout.
let reflow = ScriptReflow {
reflow_info: Reflow {
@@ -922,6 +926,8 @@ impl Window {
page_clip_rect: self.page_clip_rect.get(),
},
document: self.Document().upcast::<Node>().to_trusted_node_address(),
+ document_stylesheets: document.stylesheets().clone(),
+ stylesheets_changed: stylesheets_changed,
window_size: window_size,
script_join_chan: join_chan,
query_type: query_type,
@@ -1325,6 +1331,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
ReflowReason::WindowResize => "\tWindowResize",
ReflowReason::DOMContentLoaded => "\tDOMContentLoaded",
ReflowReason::DocumentLoaded => "\tDocumentLoaded",
+ ReflowReason::StylesheetLoaded => "\tStylesheetLoaded",
ReflowReason::ImageLoaded => "\tImageLoaded",
ReflowReason::RequestAnimationFrame => "\tRequestAnimationFrame",
ReflowReason::WebFontLoaded => "\tWebFontLoaded",