diff options
Diffstat (limited to 'components/script/document_loader.rs')
-rw-r--r-- | components/script/document_loader.rs | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index e0da74ae706..c6c33fc1a5d 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -5,10 +5,13 @@ //! Tracking of pending loads in a document. //! https://html.spec.whatwg.org/multipage/#the-end +use dom::bindings::js::JS; +use dom::document::Document; use msg::constellation_msg::PipelineId; use net_traits::AsyncResponseTarget; use net_traits::{PendingAsyncLoad, ResourceThread, LoadContext}; use std::sync::Arc; +use std::thread; use url::Url; #[derive(JSTraceable, PartialEq, Clone, Debug, HeapSizeOf)] @@ -41,6 +44,50 @@ impl LoadType { } } +/// Canary value ensuring that manually added blocking loads (ie. ones that weren't +/// created via DocumentLoader::prepare_async_load) are always removed by the time +/// that the owner is destroyed. +#[derive(JSTraceable, HeapSizeOf)] +#[must_root] +pub struct LoadBlocker { + /// The document whose load event is blocked by this object existing. + doc: JS<Document>, + /// The load that is blocking the document's load event. + load: Option<LoadType>, +} + +impl LoadBlocker { + /// Mark the document's load event as blocked on this new load. + pub fn new(doc: &Document, load: LoadType) -> LoadBlocker { + doc.add_blocking_load(load.clone()); + LoadBlocker { + doc: JS::from_ref(doc), + load: Some(load), + } + } + + /// Remove this load from the associated document's list of blocking loads. + pub fn terminate(blocker: &mut Option<LoadBlocker>) { + if let Some(this) = blocker.as_mut() { + this.doc.finish_load(this.load.take().unwrap()); + } + *blocker = None; + } + + /// Return the url associated with this load. + pub fn url(&self) -> Option<&Url> { + self.load.as_ref().map(LoadType::url) + } +} + +impl Drop for LoadBlocker { + fn drop(&mut self) { + if !thread::panicking() { + assert!(self.load.is_none()); + } + } +} + #[derive(JSTraceable, HeapSizeOf)] pub struct DocumentLoader { /// We use an `Arc<ResourceThread>` here in order to avoid file descriptor exhaustion when there @@ -73,12 +120,16 @@ impl DocumentLoader { } } + pub fn add_blocking_load(&mut self, load: LoadType) { + self.blocking_loads.push(load); + } + /// Create a new pending network request, which can be initiated at some point in /// the future. pub fn prepare_async_load(&mut self, load: LoadType) -> PendingAsyncLoad { let context = load.to_load_context(); let url = load.url().clone(); - self.blocking_loads.push(load); + self.add_blocking_load(load); PendingAsyncLoad::new(context, (*self.resource_thread).clone(), url, self.pipeline) } |