aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/document_loader.rs106
-rw-r--r--components/script/dom/bindings/global.rs9
-rw-r--r--components/script/dom/document.rs55
-rw-r--r--components/script/dom/domimplementation.rs13
-rw-r--r--components/script/dom/domparser.rs11
-rw-r--r--components/script/dom/htmlscriptelement.rs7
-rw-r--r--components/script/dom/node.rs4
-rw-r--r--components/script/lib.rs1
-rw-r--r--components/script/page.rs4
-rw-r--r--components/script/parse/html.rs22
-rw-r--r--components/script/script_task.rs49
11 files changed, 243 insertions, 38 deletions
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs
new file mode 100644
index 00000000000..bf759788c57
--- /dev/null
+++ b/components/script/document_loader.rs
@@ -0,0 +1,106 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Tracking of pending loads in a document.
+//! https://html.spec.whatwg.org/multipage/#the-end
+
+use script_task::{ScriptMsg, ScriptChan};
+use msg::constellation_msg::{PipelineId};
+use net_traits::{LoadResponse, Metadata, load_whole_resource, ResourceTask};
+use net_traits::{ControlMsg, LoadData, LoadConsumer};
+use url::Url;
+
+use std::sync::mpsc::{Receiver, channel};
+
+#[jstraceable]
+#[derive(PartialEq, Clone)]
+pub enum LoadType {
+ Image(Url),
+ Script(Url),
+ Subframe(Url),
+ Stylesheet(Url),
+ PageSource(Url),
+}
+
+impl LoadType {
+ fn url(&self) -> &Url {
+ match *self {
+ LoadType::Image(ref url) |
+ LoadType::Script(ref url) |
+ LoadType::Subframe(ref url) |
+ LoadType::Stylesheet(ref url) |
+ LoadType::PageSource(ref url) => url,
+ }
+ }
+}
+
+#[jstraceable]
+pub struct DocumentLoader {
+ pub resource_task: ResourceTask,
+ notifier_data: Option<NotifierData>,
+ blocking_loads: Vec<LoadType>,
+}
+
+#[jstraceable]
+pub struct NotifierData {
+ pub script_chan: Box<ScriptChan + Send>,
+ pub pipeline: PipelineId,
+}
+
+impl DocumentLoader {
+ pub fn new(existing: &DocumentLoader) -> DocumentLoader {
+ DocumentLoader::new_with_task(existing.resource_task.clone(), None, None)
+ }
+
+ pub fn new_with_task(resource_task: ResourceTask,
+ data: Option<NotifierData>,
+ initial_load: Option<Url>,)
+ -> DocumentLoader {
+ let mut initial_loads = vec!();
+ if let Some(load) = initial_load {
+ initial_loads.push(LoadType::PageSource(load));
+ }
+
+ DocumentLoader {
+ resource_task: resource_task,
+ notifier_data: data,
+ blocking_loads: initial_loads,
+ }
+ }
+
+ pub fn load_async(&mut self, load: LoadType) -> Receiver<LoadResponse> {
+ let (tx, rx) = channel();
+ self.blocking_loads.push(load.clone());
+ let pipeline = self.notifier_data.as_ref().map(|data| data.pipeline);
+ let load_data = LoadData::new(load.url().clone(), pipeline);
+ self.resource_task.send(ControlMsg::Load(load_data, LoadConsumer::Channel(tx))).unwrap();
+ rx
+ }
+
+ pub fn load_sync(&mut self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> {
+ self.blocking_loads.push(load.clone());
+ let result = load_whole_resource(&self.resource_task, load.url().clone());
+ self.finish_load(load);
+ result
+ }
+
+ pub fn finish_load(&mut self, load: LoadType) {
+ let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == load);
+ self.blocking_loads.remove(idx.expect("unknown completed load"));
+
+ if let Some(NotifierData { ref script_chan, pipeline }) = self.notifier_data {
+ if !self.is_blocked() {
+ script_chan.send(ScriptMsg::DocumentLoadsComplete(pipeline)).unwrap();
+ }
+ }
+ }
+
+ pub fn is_blocked(&self) -> bool {
+ !self.blocking_loads.is_empty()
+ }
+
+ pub fn inhibit_events(&mut self) {
+ self.notifier_data = None;
+ }
+}
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs
index 1b34844fa53..d1294173dd1 100644
--- a/components/script/dom/bindings/global.rs
+++ b/components/script/dom/bindings/global.rs
@@ -7,9 +7,11 @@
//! This module contains smart pointers to global scopes, to simplify writing
//! code that works in workers as well as window scopes.
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::native_from_reflector_jsmanaged;
use dom::bindings::js::{JS, JSRef, Rootable, Root, Unrooted};
use dom::bindings::utils::{Reflectable, Reflector};
+use dom::document::DocumentHelpers;
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use dom::window::{self, WindowHelpers};
use devtools_traits::DevtoolsControlChan;
@@ -101,7 +103,12 @@ impl<'a> GlobalRef<'a> {
/// Get the `ResourceTask` for this global scope.
pub fn resource_task(&self) -> ResourceTask {
match *self {
- GlobalRef::Window(ref window) => window.resource_task().clone(),
+ GlobalRef::Window(ref window) => {
+ let doc = window.Document().root();
+ let doc = doc.r();
+ let loader = doc.loader();
+ loader.resource_task.clone()
+ }
GlobalRef::Worker(ref worker) => worker.resource_task().clone(),
}
}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 9c3b0b00511..411cd1fefe7 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use document_loader::{DocumentLoader, LoadType};
use dom::attr::{Attr, AttrHelpers, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding;
@@ -71,6 +72,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyMod
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
use net_traits::CookieSource::NonHTTP;
use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
+use net_traits::{Metadata, LoadResponse};
use script_task::Runnable;
use script_traits::{MouseButton, UntrustedNodeAddress};
use util::opts;
@@ -90,9 +92,9 @@ use std::borrow::ToOwned;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::ascii::AsciiExt;
-use std::cell::{Cell, Ref, RefCell};
+use std::cell::{Cell, Ref, RefMut, RefCell};
use std::default::Default;
-use std::sync::mpsc::channel;
+use std::sync::mpsc::{Receiver, channel};
use time;
#[derive(PartialEq)]
@@ -139,6 +141,8 @@ pub struct Document {
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
/// List of animation frame callbacks
animation_frame_list: RefCell<HashMap<i32, Box<Fn(f64)>>>,
+ /// Tracks all outstanding loads related to this document.
+ loader: DOMRefCell<DocumentLoader>,
}
impl DocumentDerived for EventTarget {
@@ -205,6 +209,8 @@ impl CollectionFilter for AppletsFilter {
}
pub trait DocumentHelpers<'a> {
+ fn loader(&self) -> Ref<DocumentLoader>;
+ fn mut_loader(&self) -> RefMut<DocumentLoader>;
fn window(self) -> Temporary<Window>;
fn encoding_name(self) -> Ref<'a, DOMString>;
fn is_html_document(self) -> bool;
@@ -254,10 +260,23 @@ pub trait DocumentHelpers<'a> {
fn cancel_animation_frame(self, ident: i32);
/// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
fn invoke_animation_callbacks(self);
+ fn load_async(self, load: LoadType) -> Receiver<LoadResponse>;
+ fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String>;
+ fn finish_load(self, load: LoadType);
}
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
#[inline]
+ fn loader(&self) -> Ref<DocumentLoader> {
+ self.loader.borrow()
+ }
+
+ #[inline]
+ fn mut_loader(&self) -> RefMut<DocumentLoader> {
+ self.loader.borrow_mut()
+ }
+
+ #[inline]
fn window(self) -> Temporary<Window> {
Temporary::from_rooted(self.window)
}
@@ -864,6 +883,21 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
callback(*performance.Now());
}
}
+
+ fn load_async(self, load: LoadType) -> Receiver<LoadResponse> {
+ let mut loader = self.loader.borrow_mut();
+ loader.load_async(load)
+ }
+
+ fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> {
+ let mut loader = self.loader.borrow_mut();
+ loader.load_sync(load)
+ }
+
+ fn finish_load(self, load: LoadType) {
+ let mut loader = self.loader.borrow_mut();
+ loader.finish_load(load);
+ }
}
pub enum MouseEventType {
@@ -898,7 +932,8 @@ impl Document {
is_html_document: IsHTMLDocument,
content_type: Option<DOMString>,
last_modified: Option<DOMString>,
- source: DocumentSource) -> Document {
+ source: DocumentSource,
+ doc_loader: DocumentLoader) -> Document {
let url = url.unwrap_or_else(|| Url::parse("about:blank").unwrap());
let ready_state = if source == DocumentSource::FromParser {
@@ -943,14 +978,19 @@ impl Document {
scripting_enabled: Cell::new(true),
animation_frame_ident: Cell::new(0),
animation_frame_list: RefCell::new(HashMap::new()),
+ loader: DOMRefCell::new(doc_loader),
}
}
// https://dom.spec.whatwg.org/#dom-document
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<Document>> {
- Ok(Document::new(global.as_window(), None,
+ let win = global.as_window();
+ let doc = win.Document().root();
+ let doc = doc.r();
+ let docloader = DocumentLoader::new(&*doc.loader());
+ Ok(Document::new(win, None,
IsHTMLDocument::NonHTMLDocument, None,
- None, DocumentSource::NotFromParser))
+ None, DocumentSource::NotFromParser, docloader))
}
pub fn new(window: JSRef<Window>,
@@ -958,10 +998,11 @@ impl Document {
doctype: IsHTMLDocument,
content_type: Option<DOMString>,
last_modified: Option<DOMString>,
- source: DocumentSource) -> Temporary<Document> {
+ source: DocumentSource,
+ doc_loader: DocumentLoader) -> Temporary<Document> {
let document = reflect_dom_object(box Document::new_inherited(window, url, doctype,
content_type, last_modified,
- source),
+ source, doc_loader),
GlobalRef::Window(window),
DocumentBinding::Wrap).root();
diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs
index 3400c1d3ea3..d64ad103aa1 100644
--- a/components/script/dom/domimplementation.rs
+++ b/components/script/dom/domimplementation.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use document_loader::DocumentLoader;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMImplementationBinding;
use dom::bindings::codegen::Bindings::DOMImplementationBinding::DOMImplementationMethods;
@@ -63,11 +64,13 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
fn CreateDocument(self, namespace: Option<DOMString>, qname: DOMString,
maybe_doctype: Option<JSRef<DocumentType>>) -> Fallible<Temporary<Document>> {
let doc = self.document.root();
- let win = doc.r().window().root();
+ let doc = doc.r();
+ let win = doc.window().root();
+ let loader = DocumentLoader::new(&*doc.loader());
// Step 1.
let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument,
- None, None, DocumentSource::NotFromParser).root();
+ None, None, DocumentSource::NotFromParser, loader).root();
// Step 2-3.
let maybe_elem = if qname.is_empty() {
None
@@ -109,11 +112,13 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
fn CreateHTMLDocument(self, title: Option<DOMString>) -> Temporary<Document> {
let document = self.document.root();
- let win = document.r().window().root();
+ let document = document.r();
+ let win = document.window().root();
+ let loader = DocumentLoader::new(&*document.loader());
// Step 1-2.
let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None,
- DocumentSource::NotFromParser).root();
+ DocumentSource::NotFromParser, loader).root();
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
{
diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs
index 65afb15e5fa..5685c3f324f 100644
--- a/components/script/dom/domparser.rs
+++ b/components/script/dom/domparser.rs
@@ -2,10 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use document_loader::DocumentLoader;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentReadyState;
use dom::bindings::codegen::Bindings::DOMParserBinding;
use dom::bindings::codegen::Bindings::DOMParserBinding::DOMParserMethods;
use dom::bindings::codegen::Bindings::DOMParserBinding::SupportedType::{Text_html, Text_xml};
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Rootable, Temporary};
@@ -51,13 +53,17 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
let window = self.window.root();
let url = window.r().get_url();
let content_type = DOMParserBinding::SupportedTypeValues::strings[ty as usize].to_owned();
+ let doc = window.r().Document().root();
+ let doc = doc.r();
+ let loader = DocumentLoader::new(&*doc.loader());
match ty {
Text_html => {
let document = Document::new(window.r(), Some(url.clone()),
IsHTMLDocument::HTMLDocument,
Some(content_type),
None,
- DocumentSource::FromParser).root();
+ DocumentSource::FromParser,
+ loader).root();
parse_html(document.r(), HTMLInput::InputString(s), &url, None);
document.r().set_ready_state(DocumentReadyState::Complete);
Ok(Temporary::from_rooted(document.r()))
@@ -68,7 +74,8 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
IsHTMLDocument::NonHTMLDocument,
Some(content_type),
None,
- DocumentSource::NotFromParser))
+ DocumentSource::NotFromParser,
+ loader))
}
}
}
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index aaf36f95cb4..2f7a52ec272 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -4,6 +4,7 @@
use std::ascii::AsciiExt;
+use document_loader::LoadType;
use dom::attr::Attr;
use dom::attr::AttrHelpers;
use dom::bindings::cell::DOMRefCell;
@@ -34,7 +35,7 @@ use script_task::{ScriptMsg, Runnable};
use encoding::all::UTF_8;
use encoding::label::encoding_from_whatwg_label;
use encoding::types::{Encoding, EncodingRef, DecoderTrap};
-use net_traits::{load_whole_resource, Metadata};
+use net_traits::Metadata;
use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec};
use std::borrow::ToOwned;
use std::cell::Cell;
@@ -261,7 +262,9 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
// state of the element's `crossorigin` content attribute, the origin being
// the origin of the script element's node document, and the default origin
// behaviour set to taint.
- ScriptOrigin::External(load_whole_resource(&window.resource_task(), url))
+ let doc = document_from_node(self).root();
+ let contents = doc.r().load_sync(LoadType::Script(url));
+ ScriptOrigin::External(contents)
}
}
},
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 048ee28b3a9..170ff22e5a1 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -4,6 +4,7 @@
//! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements.
+use document_loader::DocumentLoader;
use dom::attr::{Attr, AttrHelpers};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
@@ -1711,9 +1712,10 @@ impl Node {
false => IsHTMLDocument::NonHTMLDocument,
};
let window = document.window().root();
+ let loader = DocumentLoader::new(&*document.loader());
let document = Document::new(window.r(), Some(document.url()),
is_html_doc, None,
- None, DocumentSource::NotFromParser);
+ None, DocumentSource::NotFromParser, loader);
NodeCast::from_temporary(document)
},
NodeTypeId::Element(..) => {
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 09340e7446e..403d53fccbe 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -54,6 +54,7 @@ extern crate string_cache;
extern crate webdriver_traits;
pub mod cors;
+pub mod document_loader;
#[macro_use]
pub mod dom;
diff --git a/components/script/page.rs b/components/script/page.rs
index 67da1a9fc61..404cf20de6b 100644
--- a/components/script/page.rs
+++ b/components/script/page.rs
@@ -71,6 +71,10 @@ impl Page {
}
}
+ pub fn pipeline(&self) -> PipelineId {
+ self.id
+ }
+
pub fn window(&self) -> Temporary<Window> {
Temporary::from_rooted(self.frame.borrow().as_ref().unwrap().window.clone())
}
diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs
index c870fe8c616..80885acf300 100644
--- a/components/script/parse/html.rs
+++ b/components/script/parse/html.rs
@@ -4,6 +4,7 @@
#![allow(unsafe_code, unrooted_must_root)]
+use document_loader::{DocumentLoader, LoadType};
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
@@ -286,7 +287,7 @@ pub fn parse_html(document: JSRef<Document>,
task_state::enter(IN_HTML_PARSER);
}
- fn parse_progress(parser: JSRef<ServoHTMLParser>, url: &Url, load_response: &LoadResponse) {
+ fn parse_progress(document: JSRef<Document>, parser: JSRef<ServoHTMLParser>, url: &Url, load_response: &LoadResponse) {
for msg in load_response.progress_port.iter() {
match msg {
ProgressMsg::Payload(data) => {
@@ -299,7 +300,10 @@ pub fn parse_html(document: JSRef<Document>,
// TODO(Savago): we should send a notification to callers #5463.
break;
}
- ProgressMsg::Done(Ok(())) => break,
+ ProgressMsg::Done(Ok(())) => {
+ document.finish_load(LoadType::PageSource(url.clone()));
+ break;
+ }
}
}
};
@@ -313,6 +317,7 @@ pub fn parse_html(document: JSRef<Document>,
Some(ContentType(Mime(TopLevel::Image, _, _))) => {
let page = format!("<html><body><img src='{}' /></body></html>", url.serialize());
parser.parse_chunk(page);
+ document.finish_load(LoadType::PageSource(url.clone()));
},
Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, _))) => {
// FIXME: When servo/html5ever#109 is fixed remove <plaintext> usage and
@@ -325,10 +330,10 @@ pub fn parse_html(document: JSRef<Document>,
// https://html.spec.whatwg.org/multipage/#read-text
let page = format!("<pre>\u{000A}<plaintext>");
parser.parse_chunk(page);
- parse_progress(parser, url, &load_response);
+ parse_progress(document, parser, url, &load_response);
},
_ => {
- parse_progress(parser, url, &load_response);
+ parse_progress(document, parser, url, &load_response);
}
}
}
@@ -349,16 +354,19 @@ pub fn parse_html_fragment(context_node: JSRef<Node>,
output: &mut RootedVec<JS<Node>>) {
let window = window_from_node(context_node).root();
let context_document = document_from_node(context_node).root();
- let url = context_document.r().url();
+ let context_document = context_document.r();
+ let url = context_document.url();
// Step 1.
+ let loader = DocumentLoader::new(&*context_document.loader());
let document = Document::new(window.r(), Some(url.clone()),
IsHTMLDocument::HTMLDocument,
None, None,
- DocumentSource::FromParser).root();
+ DocumentSource::FromParser,
+ loader).root();
// Step 2.
- document.r().set_quirks_mode(context_document.r().quirks_mode());
+ document.r().set_quirks_mode(context_document.quirks_mode());
// Step 11.
let form = context_node.inclusive_ancestors()
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index b7fc3198511..93b3c794234 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -19,6 +19,7 @@
#![allow(unsafe_code)]
+use document_loader::{DocumentLoader, NotifierData};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
@@ -65,7 +66,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType};
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId};
use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType};
use msg::constellation_msg::Msg as ConstellationMsg;
-use net_traits::{ResourceTask, ControlMsg, LoadResponse, LoadConsumer};
+use net_traits::{ResourceTask, LoadResponse, LoadConsumer, ControlMsg};
use net_traits::LoadData as NetLoadData;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
use net_traits::storage_task::StorageTask;
@@ -190,6 +191,8 @@ pub enum ScriptMsg {
RefcountCleanup(TrustedReference),
/// The final network response for a page has arrived.
PageFetchComplete(PipelineId, Option<SubpageId>, LoadResponse),
+ /// Notify a document that all pending loads are complete.
+ DocumentLoadsComplete(PipelineId),
}
/// A cloneable interface for communicating with an event loop.
@@ -753,6 +756,8 @@ impl ScriptTask {
LiveDOMReferences::cleanup(self.get_cx(), addr),
ScriptMsg::PageFetchComplete(id, subpage, response) =>
self.handle_page_fetch_complete(id, subpage, response),
+ ScriptMsg::DocumentLoadsComplete(id) =>
+ self.handle_loads_complete(id),
}
}
@@ -858,6 +863,25 @@ impl ScriptTask {
self.start_page_load(new_load, load_data);
}
+ fn handle_loads_complete(&self, pipeline: PipelineId) {
+ let page = get_page(&self.root_page(), pipeline);
+ let doc = page.document().root();
+ let doc = doc.r();
+ if doc.loader().is_blocked() {
+ return;
+ }
+
+ doc.mut_loader().inhibit_events();
+
+ // https://html.spec.whatwg.org/multipage/#the-end step 7
+ let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone());
+ let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load);
+ self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
+
+ let ConstellationChan(ref chan) = self.constellation_chan;
+ chan.send(ConstellationMsg::LoadComplete).unwrap();
+ }
+
/// Handles a timer that fired.
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
let page = self.root_page();
@@ -1142,12 +1166,20 @@ impl ScriptTask {
_ => None
};
+ let notifier_data = NotifierData {
+ script_chan: self.chan.clone(),
+ pipeline: page.pipeline(),
+ };
+ let loader = DocumentLoader::new_with_task(self.resource_task.clone(),
+ Some(notifier_data),
+ Some(final_url.clone()));
let document = Document::new(window.r(),
Some(final_url.clone()),
IsHTMLDocument::HTMLDocument,
content_type,
last_modified,
- DocumentSource::FromParser).root();
+ DocumentSource::FromParser,
+ loader).root();
let frame_element = frame_element.r().map(|elem| ElementCast::from_ref(elem));
window.r().init_browser_context(document.r(), frame_element);
@@ -1422,22 +1454,11 @@ impl ScriptTask {
// https://html.spec.whatwg.org/multipage/#the-end step 4
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
- let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::DOMContentLoaded);
- self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
-
- // We have no concept of a document loader right now, so just dispatch the
- // "load" event as soon as we've finished executing all scripts parsed during
- // the initial load.
-
- // https://html.spec.whatwg.org/multipage/#the-end step 7
- let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::Load);
+ let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded);
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
window.r().set_fragment_name(final_url.fragment.clone());
- let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(ConstellationMsg::LoadComplete).unwrap();
-
// Notify devtools that a new script global exists.
self.notify_devtools(document.r().Title(), final_url, (id, None));
}