aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/stylesheet_loader.rs
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2017-03-18 13:49:04 +0100
committerSimon Sapin <simon.sapin@exyr.org>2017-03-19 22:30:39 +0100
commit1e380137831eaf94a1f602c9d8dfae08f10893fa (patch)
treea3fa95714e197a277f3c06fd6df9b1d21fcacd6d /components/script/stylesheet_loader.rs
parent1bacd0eb1582f609ad9a9c9a8a33a737bf4bc6f3 (diff)
downloadservo-1e380137831eaf94a1f602c9d8dfae08f10893fa.tar.gz
servo-1e380137831eaf94a1f602c9d8dfae08f10893fa.zip
Refactor StylesheetLoader so impls do not need to acquire a shared lock.
This fixes a deadlock: https://github.com/servo/servo/pull/16014#issuecomment-287527067
Diffstat (limited to 'components/script/stylesheet_loader.rs')
-rw-r--r--components/script/stylesheet_loader.rs45
1 files changed, 20 insertions, 25 deletions
diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs
index db21ee795fd..7f544e42d08 100644
--- a/components/script/stylesheet_loader.rs
+++ b/components/script/stylesheet_loader.rs
@@ -54,32 +54,16 @@ pub trait StylesheetOwner {
pub enum StylesheetContextSource {
// NB: `media` is just an option so we avoid cloning it.
- LinkElement { media: Option<MediaList>, url: ServoUrl },
+ LinkElement { media: Option<MediaList>, },
Import(Arc<StyleLocked<ImportRule>>),
}
-impl StylesheetContextSource {
- fn url(&self, document: &Document) -> ServoUrl {
- match *self {
- StylesheetContextSource::LinkElement { ref url, .. } => url.clone(),
- StylesheetContextSource::Import(ref import) => {
- let guard = document.style_shared_lock().read();
- let import = import.read_with(&guard);
- // Look at the parser in style::stylesheets, where we don't
- // trigger a load if the url is invalid.
- import.url.url()
- .expect("Invalid urls shouldn't enter the loader")
- .clone()
- }
- }
- }
-}
-
/// The context required for asynchronously loading an external stylesheet.
pub struct StylesheetContext {
/// The element that initiated the request.
elem: Trusted<HTMLElement>,
source: StylesheetContextSource,
+ url: ServoUrl,
metadata: Option<Metadata>,
/// The response body received to date.
data: Vec<u8>,
@@ -146,7 +130,7 @@ impl FetchResponseListener for StylesheetContext {
let loader = StylesheetLoader::for_element(&elem);
match self.source {
- StylesheetContextSource::LinkElement { ref mut media, .. } => {
+ StylesheetContextSource::LinkElement { ref mut media } => {
let link = elem.downcast::<HTMLLinkElement>().unwrap();
// We must first check whether the generations of the context and the element match up,
// else we risk applying the wrong stylesheet when responses come out-of-order.
@@ -209,8 +193,7 @@ impl FetchResponseListener for StylesheetContext {
document.decrement_script_blocking_stylesheet_count();
}
- let url = self.source.url(&document);
- document.finish_load(LoadType::Stylesheet(url));
+ document.finish_load(LoadType::Stylesheet(self.url.clone()));
if let Some(any_failed) = owner.load_finished(successful) {
let event = if any_failed { atom!("error") } else { atom!("load") };
@@ -232,15 +215,16 @@ impl<'a> StylesheetLoader<'a> {
}
impl<'a> StylesheetLoader<'a> {
- pub fn load(&self, source: StylesheetContextSource, cors_setting: Option<CorsSettings>,
+ pub fn load(&self, source: StylesheetContextSource, url: ServoUrl,
+ cors_setting: Option<CorsSettings>,
integrity_metadata: String) {
let document = document_from_node(self.elem);
- let url = source.url(&document);
let gen = self.elem.downcast::<HTMLLinkElement>()
.map(HTMLLinkElement::get_request_generation_id);
let context = Arc::new(Mutex::new(StylesheetContext {
elem: Trusted::new(&*self.elem),
source: source,
+ url: url.clone(),
metadata: None,
data: vec![],
document: Trusted::new(&*document),
@@ -297,9 +281,20 @@ impl<'a> StylesheetLoader<'a> {
}
impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> {
- fn request_stylesheet(&self, import: &Arc<StyleLocked<ImportRule>>) {
+ fn request_stylesheet(
+ &self,
+ media: MediaList,
+ make_import: &mut FnMut(MediaList) -> ImportRule,
+ make_arc: &mut FnMut(ImportRule) -> Arc<StyleLocked<ImportRule>>,
+ ) -> Arc<StyleLocked<ImportRule>> {
+ let import = make_import(media);
+ let url = import.url.url().expect("Invalid urls shouldn't enter the loader").clone();
+ let arc = make_arc(import);
+
//TODO (mrnayak) : Whether we should use the original loader's CORS setting?
//Fix this when spec has more details.
- self.load(StylesheetContextSource::Import(import.clone()), None, "".to_owned())
+ self.load(StylesheetContextSource::Import(arc.clone()), url, None, "".to_owned());
+
+ arc
}
}