mirror of
https://github.com/servo/servo.git
synced 2025-06-16 20:34:30 +00:00
Make iframes block the enclosing document's load event. Fixes #6663.
This commit is contained in:
parent
fc3f93235e
commit
e9b98ad5fa
17 changed files with 2054 additions and 19 deletions
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue