mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +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
|
@ -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(..) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue