Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make external script sources load asynchronously, yet still block furthe... #5727

Merged
merged 3 commits into from May 21, 2015
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -132,8 +132,6 @@ pub struct PendingAsyncLoad {
resource_task: ResourceTask,
url: Url,
pipeline: Option<PipelineId>,
input_sender: Sender<LoadResponse>,
input_receiver: Receiver<LoadResponse>,
guard: PendingLoadGuard,
}

@@ -156,13 +154,10 @@ impl Drop for PendingLoadGuard {
impl PendingAsyncLoad {
pub fn new(resource_task: ResourceTask, url: Url, pipeline: Option<PipelineId>)
-> PendingAsyncLoad {
let (sender, receiver) = channel();
PendingAsyncLoad {
resource_task: resource_task,
url: url,
pipeline: pipeline,
input_sender: sender,
input_receiver: receiver,
guard: PendingLoadGuard { loaded: false, },
}
}
@@ -171,9 +166,18 @@ impl PendingAsyncLoad {
pub fn load(mut self) -> Receiver<LoadResponse> {
self.guard.neuter();
let load_data = LoadData::new(self.url, self.pipeline);
let consumer = LoadConsumer::Channel(self.input_sender);
let (sender, receiver) = channel();
let consumer = LoadConsumer::Channel(sender);
self.resource_task.send(ControlMsg::Load(load_data, consumer)).unwrap();
receiver
}

/// Initiate the network request associated with this pending load, using the provided target.
pub fn load_async(mut self, listener: Box<AsyncResponseTarget + Send>) {
self.guard.neuter();
let load_data = LoadData::new(self.url, self.pipeline);
let consumer = LoadConsumer::Listener(listener);
self.resource_task.send(ControlMsg::Load(load_data, consumer)).unwrap();
self.input_receiver
}
}

@@ -7,13 +7,12 @@

use script_task::{ScriptMsg, ScriptChan};
use msg::constellation_msg::{PipelineId};
use net_traits::{LoadResponse, Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad};
use net_traits::{Metadata, load_whole_resource, ResourceTask, PendingAsyncLoad};
use net_traits::AsyncResponseTarget;
use url::Url;

use std::sync::mpsc::Receiver;

#[jstraceable]
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub enum LoadType {
Image(Url),
Script(Url),
@@ -75,9 +74,9 @@ impl DocumentLoader {
}

/// Create and initiate a new network request.
pub fn load_async(&mut self, load: LoadType) -> Receiver<LoadResponse> {
pub fn load_async(&mut self, load: LoadType, listener: Box<AsyncResponseTarget + Send>) {
let pending = self.prepare_async_load(load);
pending.load()
pending.load_async(listener)
}

/// Create, initiate, and await the response for a new network request.
@@ -91,7 +90,7 @@ impl DocumentLoader {
/// Mark an in-progress network request complete.
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"));
self.blocking_loads.remove(idx.expect(&format!("unknown completed load {:?}", load)));

if let Some(NotifierData { ref script_chan, pipeline }) = self.notifier_data {
if !self.is_blocked() {
@@ -101,6 +100,7 @@ impl DocumentLoader {
}

pub fn is_blocked(&self) -> bool {
//TODO: Ensure that we report blocked if parsing is still ongoing.
!self.blocking_loads.is_empty()
}

@@ -61,6 +61,7 @@ use dom::nodelist::NodeList;
use dom::text::Text;
use dom::processinginstruction::ProcessingInstruction;
use dom::range::Range;
use dom::servohtmlparser::ServoHTMLParser;
use dom::treewalker::TreeWalker;
use dom::uievent::UIEvent;
use dom::window::{Window, WindowHelpers, ReflowReason};
@@ -73,7 +74,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, PendingAsyncLoad};
use net_traits::{Metadata, PendingAsyncLoad, AsyncResponseTarget};
use script_task::Runnable;
use script_traits::{MouseButton, UntrustedNodeAddress};
use util::opts;
@@ -96,7 +97,7 @@ use std::ascii::AsciiExt;
use std::cell::{Cell, Ref, RefMut, RefCell};
use std::default::Default;
use std::ptr;
use std::sync::mpsc::{Receiver, channel};
use std::sync::mpsc::channel;
use time;

#[derive(PartialEq)]
@@ -145,6 +146,8 @@ pub struct Document {
animation_frame_list: RefCell<HashMap<i32, Box<Fn(f64)>>>,
/// Tracks all outstanding loads related to this document.
loader: DOMRefCell<DocumentLoader>,
/// The current active HTML parser, to allow resuming after interruptions.
current_parser: MutNullableHeap<JS<ServoHTMLParser>>,
}

impl DocumentDerived for EventTarget {
@@ -263,9 +266,11 @@ pub trait DocumentHelpers<'a> {
/// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
fn invoke_animation_callbacks(self);
fn prepare_async_load(self, load: LoadType) -> PendingAsyncLoad;
fn load_async(self, load: LoadType) -> Receiver<LoadResponse>;
fn load_async(self, load: LoadType, listener: Box<AsyncResponseTarget + Send>);
fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String>;
fn finish_load(self, load: LoadType);
fn set_current_parser(self, script: Option<JSRef<ServoHTMLParser>>);
fn get_current_parser(self) -> Option<Temporary<ServoHTMLParser>>;
}

impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
@@ -892,9 +897,9 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
loader.prepare_async_load(load)
}

fn load_async(self, load: LoadType) -> Receiver<LoadResponse> {
fn load_async(self, load: LoadType, listener: Box<AsyncResponseTarget + Send>) {
let mut loader = self.loader.borrow_mut();
loader.load_async(load)
loader.load_async(load, listener)
}

fn load_sync(self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> {
@@ -906,6 +911,14 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let mut loader = self.loader.borrow_mut();
loader.finish_load(load);
}

fn set_current_parser(self, script: Option<JSRef<ServoHTMLParser>>) {
self.current_parser.set(script.map(JS::from_rooted));
}

fn get_current_parser(self) -> Option<Temporary<ServoHTMLParser>> {
self.current_parser.get().map(Temporary::from_rooted)
}
}

pub enum MouseEventType {
@@ -914,6 +927,7 @@ pub enum MouseEventType {
MouseUp,
}


#[derive(PartialEq)]
pub enum DocumentSource {
FromParser,
@@ -987,6 +1001,7 @@ impl Document {
animation_frame_ident: Cell::new(0),
animation_frame_list: RefCell::new(HashMap::new()),
loader: DOMRefCell::new(doc_loader),
current_parser: Default::default(),
}
}

@@ -15,7 +15,7 @@ use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
use dom::document::DocumentSource;
use dom::window::{Window, WindowHelpers};
use parse::html::{HTMLInput, parse_html};
use parse::html::{ParseContext, parse_html};
use util::str::DOMString;

use std::borrow::ToOwned;
@@ -64,7 +64,7 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
None,
DocumentSource::FromParser,
loader).root();
parse_html(document.r(), HTMLInput::InputString(s), &url, None);
parse_html(document.r(), s, &url, ParseContext::Owner(None));
document.r().set_ready_state(DocumentReadyState::Complete);
Ok(Temporary::from_rooted(document.r()))
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.