From f3cdba6b8bbd51eedb05bdb4c21073f4fe41e9a8 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 22 Apr 2015 20:12:24 -0400 Subject: [PATCH] Make link elements fire a load event. --- components/layout/layout_task.rs | 9 ++--- components/script/dom/htmllinkelement.rs | 35 +++++++++++++++++-- components/script/layout_interface.rs | 3 +- components/script/script_task.rs | 6 ++-- components/script_traits/lib.rs | 6 +++- tests/wpt/mozilla/meta/MANIFEST.json | 6 ++++ .../mozilla/tests/mozilla/resources/style.css | 3 ++ .../tests/mozilla/stylesheet_load.html | 20 +++++++++++ 8 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 tests/wpt/mozilla/tests/mozilla/resources/style.css create mode 100644 tests/wpt/mozilla/tests/mozilla/stylesheet_load.html diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 38a2e11c3a6..c29f421f80a 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -54,7 +54,7 @@ use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC}; use script::layout_interface::{MouseOverResponse, Msg, Reflow, ReflowGoal, ReflowQueryType}; use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel}; -use script_traits::ScriptControlChan; +use script_traits::{ScriptControlChan, StylesheetLoadResponder}; use std::borrow::ToOwned; use std::cell::Cell; use std::mem::transmute; @@ -486,8 +486,8 @@ impl LayoutTask { Msg::AddStylesheet(sheet, mq) => { self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data) } - Msg::LoadStylesheet(url, mq, pending) => { - self.handle_load_stylesheet(url, mq, pending, possibly_locked_rw_data) + Msg::LoadStylesheet(url, mq, pending, link_element) => { + 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::GetRPC(response_chan) => { @@ -593,6 +593,7 @@ impl LayoutTask { url: Url, mq: MediaQueryList, pending: PendingAsyncLoad, + responder: Box, possibly_locked_rw_data: &mut Option>) { // 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 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); } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 49e9bf42b1d..fd2d3471a61 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -8,13 +8,16 @@ use dom::attr::AttrHelpers; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods; 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::global::GlobalRef; use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary}; use dom::bindings::js::{OptionalRootable, RootedReference}; +use dom::bindings::refcounted::Trusted; use dom::document::{Document, DocumentHelpers}; use dom::domtokenlist::DOMTokenList; use dom::element::{AttributeHandlers, Element}; +use dom::event::{EventBubbles, EventCancelable, Event, EventHelpers}; use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::element::ElementTypeId; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; @@ -22,6 +25,7 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom::window::WindowHelpers; use layout_interface::{LayoutChan, Msg}; +use script_traits::StylesheetLoadResponder; use util::str::{DOMString, HTML_SPACE_CHARACTERS}; use style::media_queries::parse_media_query_list; 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 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 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) } @@ -183,3 +190,27 @@ impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> { }) } } + +pub struct StylesheetLoadDispatcher { + elem: Trusted, +} + +impl StylesheetLoadDispatcher { + pub fn new(elem: Trusted) -> StylesheetLoadDispatcher { + StylesheetLoadDispatcher { + elem: elem, + } + } +} + +impl StylesheetLoadResponder for StylesheetLoadDispatcher { + fn respond(self: Box) { + 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); + } +} diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index 22f11462db1..6fde5c4312f 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -15,6 +15,7 @@ use msg::constellation_msg::{PipelineExitType, WindowSizeData}; use net_traits::PendingAsyncLoad; use profile_traits::mem::{Reporter, ReportsChan}; use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress}; +use script_traits::StylesheetLoadResponder; use std::any::Any; use std::sync::mpsc::{channel, Receiver, Sender}; use style::animation::PropertyAnimation; @@ -31,7 +32,7 @@ pub enum Msg { AddStylesheet(Stylesheet, MediaQueryList), /// Adds the given stylesheet to the document. - LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad), + LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad, Box), /// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded. SetQuirksMode, diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 3f6ce8c94fb..34faad42ec4 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -731,8 +731,10 @@ impl ScriptTask { self.handle_webdriver_msg(pipeline_id, msg), ConstellationControlMsg::TickAllAnimations(pipeline_id) => self.handle_tick_all_animations(pipeline_id), - ConstellationControlMsg::StylesheetLoadComplete(id, url) => - self.handle_resource_loaded(id, LoadType::Stylesheet(url)), + ConstellationControlMsg::StylesheetLoadComplete(id, url, responder) => { + self.handle_resource_loaded(id, LoadType::Stylesheet(url)); + responder.respond(); + } } } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index c77ebe97c72..2ed5685a00d 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -56,6 +56,10 @@ pub struct NewLayoutInfo { pub load_data: LoadData, } +pub trait StylesheetLoadResponder { + fn respond(self: Box); +} + /// Messages sent from the constellation to the script task pub enum ConstellationControlMsg { /// 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 TickAllAnimations(PipelineId), /// Notifies script that a stylesheet has finished loading. - StylesheetLoadComplete(PipelineId, Url), + StylesheetLoadComplete(PipelineId, Url, Box), } /// The mouse button involved in the event. diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 841aa8f1c5b..37b28df50ad 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -521,6 +521,12 @@ "url": "/_mozilla/mozilla/storage.html" } ], + "mozilla/stylesheet_load.html": [ + { + "path": "mozilla/stylesheet_load.html", + "url": "/_mozilla/mozilla/stylesheet_load.html" + } + ], "mozilla/textcontent.html": [ { "path": "mozilla/textcontent.html", diff --git a/tests/wpt/mozilla/tests/mozilla/resources/style.css b/tests/wpt/mozilla/tests/mozilla/resources/style.css new file mode 100644 index 00000000000..d48115e5652 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/resources/style.css @@ -0,0 +1,3 @@ +body { + background-color: white; +} \ No newline at end of file diff --git a/tests/wpt/mozilla/tests/mozilla/stylesheet_load.html b/tests/wpt/mozilla/tests/mozilla/stylesheet_load.html new file mode 100644 index 00000000000..bf095725a5c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/stylesheet_load.html @@ -0,0 +1,20 @@ + + + + + + + +