Make link elements fire a load event.

This commit is contained in:
Josh Matthews 2015-04-22 20:12:24 -04:00
parent 32a89c9455
commit f3cdba6b8b
8 changed files with 78 additions and 10 deletions

View file

@ -54,7 +54,7 @@ use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC};
use script::layout_interface::{MouseOverResponse, Msg, Reflow, ReflowGoal, ReflowQueryType}; use script::layout_interface::{MouseOverResponse, Msg, Reflow, ReflowGoal, ReflowQueryType};
use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel}; use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel};
use script_traits::ScriptControlChan; use script_traits::{ScriptControlChan, StylesheetLoadResponder};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
use std::mem::transmute; use std::mem::transmute;
@ -486,8 +486,8 @@ impl LayoutTask {
Msg::AddStylesheet(sheet, mq) => { Msg::AddStylesheet(sheet, mq) => {
self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data) self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data)
} }
Msg::LoadStylesheet(url, mq, pending) => { Msg::LoadStylesheet(url, mq, pending, link_element) => {
self.handle_load_stylesheet(url, mq, pending, possibly_locked_rw_data) self.handle_load_stylesheet(url, mq, pending, link_element, possibly_locked_rw_data)
} }
Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data), Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data),
Msg::GetRPC(response_chan) => { Msg::GetRPC(response_chan) => {
@ -593,6 +593,7 @@ impl LayoutTask {
url: Url, url: Url,
mq: MediaQueryList, mq: MediaQueryList,
pending: PendingAsyncLoad, pending: PendingAsyncLoad,
responder: Box<StylesheetLoadResponder+Send>,
possibly_locked_rw_data: possibly_locked_rw_data:
&mut Option<MutexGuard<'a, LayoutTaskData>>) { &mut Option<MutexGuard<'a, LayoutTaskData>>) {
// TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
@ -611,7 +612,7 @@ impl LayoutTask {
//TODO: mark critical subresources as blocking load as well //TODO: mark critical subresources as blocking load as well
let ScriptControlChan(ref chan) = self.script_chan; let ScriptControlChan(ref chan) = self.script_chan;
chan.send(ConstellationControlMsg::StylesheetLoadComplete(self.id, url)).unwrap(); chan.send(ConstellationControlMsg::StylesheetLoadComplete(self.id, url, responder)).unwrap();
self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data); self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data);
} }

View file

@ -8,13 +8,16 @@ use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding;
use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::HTMLLinkElementDerived; use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLLinkElementDerived};
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary}; use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary};
use dom::bindings::js::{OptionalRootable, RootedReference}; use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
use dom::element::{AttributeHandlers, Element}; use dom::element::{AttributeHandlers, Element};
use dom::event::{EventBubbles, EventCancelable, Event, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -22,6 +25,7 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers; use dom::window::WindowHelpers;
use layout_interface::{LayoutChan, Msg}; use layout_interface::{LayoutChan, Msg};
use script_traits::StylesheetLoadResponder;
use util::str::{DOMString, HTML_SPACE_CHARACTERS}; use util::str::{DOMString, HTML_SPACE_CHARACTERS};
use style::media_queries::parse_media_query_list; use style::media_queries::parse_media_query_list;
use style::node::TElement; use style::node::TElement;
@ -152,9 +156,12 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
let media = parse_media_query_list(&mut css_parser); let media = parse_media_query_list(&mut css_parser);
let doc = window.Document().root(); let doc = window.Document().root();
let link_element = Trusted::new(window.get_cx(), self, window.script_chan().clone());
let load_dispatcher = StylesheetLoadDispatcher::new(link_element);
let pending = doc.r().prep_async_load(LoadType::Stylesheet(url.clone())); let pending = doc.r().prep_async_load(LoadType::Stylesheet(url.clone()));
let LayoutChan(ref layout_chan) = window.layout_chan(); let LayoutChan(ref layout_chan) = window.layout_chan();
layout_chan.send(Msg::LoadStylesheet(url, media, pending)).unwrap(); layout_chan.send(Msg::LoadStylesheet(url, media, pending, box load_dispatcher)).unwrap();
} }
Err(e) => debug!("Parsing url {} failed: {}", href, e) Err(e) => debug!("Parsing url {} failed: {}", href, e)
} }
@ -183,3 +190,27 @@ impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> {
}) })
} }
} }
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.to_temporary().root();
let window = window_from_node(elem.r()).root();
let event = Event::new(GlobalRef::Window(window.r()), "load".to_owned(),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable).root();
let target = EventTargetCast::from_ref(elem.r());
event.r().fire(target);
}
}

View file

@ -15,6 +15,7 @@ use msg::constellation_msg::{PipelineExitType, WindowSizeData};
use net_traits::PendingAsyncLoad; use net_traits::PendingAsyncLoad;
use profile_traits::mem::{Reporter, ReportsChan}; use profile_traits::mem::{Reporter, ReportsChan};
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress}; use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress};
use script_traits::StylesheetLoadResponder;
use std::any::Any; use std::any::Any;
use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::mpsc::{channel, Receiver, Sender};
use style::animation::PropertyAnimation; use style::animation::PropertyAnimation;
@ -31,7 +32,7 @@ pub enum Msg {
AddStylesheet(Stylesheet, MediaQueryList), AddStylesheet(Stylesheet, MediaQueryList),
/// Adds the given stylesheet to the document. /// Adds the given stylesheet to the document.
LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad), LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad, Box<StylesheetLoadResponder+Send>),
/// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded. /// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded.
SetQuirksMode, SetQuirksMode,

View file

@ -731,8 +731,10 @@ impl ScriptTask {
self.handle_webdriver_msg(pipeline_id, msg), self.handle_webdriver_msg(pipeline_id, msg),
ConstellationControlMsg::TickAllAnimations(pipeline_id) => ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
self.handle_tick_all_animations(pipeline_id), self.handle_tick_all_animations(pipeline_id),
ConstellationControlMsg::StylesheetLoadComplete(id, url) => ConstellationControlMsg::StylesheetLoadComplete(id, url, responder) => {
self.handle_resource_loaded(id, LoadType::Stylesheet(url)), self.handle_resource_loaded(id, LoadType::Stylesheet(url));
responder.respond();
}
} }
} }

View file

@ -56,6 +56,10 @@ pub struct NewLayoutInfo {
pub load_data: LoadData, pub load_data: LoadData,
} }
pub trait StylesheetLoadResponder {
fn respond(self: Box<Self>);
}
/// Messages sent from the constellation to the script task /// Messages sent from the constellation to the script task
pub enum ConstellationControlMsg { pub enum ConstellationControlMsg {
/// Gives a channel and ID to a layout task, as well as the ID of that layout's parent /// Gives a channel and ID to a layout task, as well as the ID of that layout's parent
@ -91,7 +95,7 @@ pub enum ConstellationControlMsg {
/// Notifies script task that all animations are done /// Notifies script task that all animations are done
TickAllAnimations(PipelineId), TickAllAnimations(PipelineId),
/// Notifies script that a stylesheet has finished loading. /// Notifies script that a stylesheet has finished loading.
StylesheetLoadComplete(PipelineId, Url), StylesheetLoadComplete(PipelineId, Url, Box<StylesheetLoadResponder+Send>),
} }
/// The mouse button involved in the event. /// The mouse button involved in the event.

View file

@ -521,6 +521,12 @@
"url": "/_mozilla/mozilla/storage.html" "url": "/_mozilla/mozilla/storage.html"
} }
], ],
"mozilla/stylesheet_load.html": [
{
"path": "mozilla/stylesheet_load.html",
"url": "/_mozilla/mozilla/stylesheet_load.html"
}
],
"mozilla/textcontent.html": [ "mozilla/textcontent.html": [
{ {
"path": "mozilla/textcontent.html", "path": "mozilla/textcontent.html",

View file

@ -0,0 +1,3 @@
body {
background-color: white;
}

View file

@ -0,0 +1,20 @@
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link href="resources/style.css" rel="stylesheet" id="style_test"></link>
<script>
var saw_link_onload = false;
var t = async_test();
document.getElementById('style_test').onload = t.step_func(function() {
saw_link_onload = true;
});
window.addEventListener('load', function() {
t.step_func(function() {
assert_true(saw_link_onload);
});
t.done();
}, false);
</script>
</head>
</html>