mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Implement a DocumentLoader type that tracks pending loads and notifies the script task when the queue is empty. Dispatch the document load event based on the DocumentLoader's notification.
This commit is contained in:
parent
29a43a00b3
commit
7f0706ed42
11 changed files with 243 additions and 38 deletions
106
components/script/document_loader.rs
Normal file
106
components/script/document_loader.rs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,9 +260,22 @@ 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();
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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(..) => {
|
||||
|
|
|
@ -54,6 +54,7 @@ extern crate string_cache;
|
|||
extern crate webdriver_traits;
|
||||
|
||||
pub mod cors;
|
||||
pub mod document_loader;
|
||||
|
||||
#[macro_use]
|
||||
pub mod dom;
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue