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

Implement async fetching of extenal script sources via interruptible parsing. #5197

Closed
wants to merge 14 commits into from

Implement sync XHR by creating and spinning on-demand event loops.

  • Loading branch information
jdm committed Mar 5, 2015
commit c87b7b87d7b00ef23298cadc564274ec703837ee
@@ -51,12 +51,6 @@ pub fn global_init() {
}
}

#[must_use]
pub enum AsyncResponseResult {
ContinueNormalResponse,
AbortResponse,
}

pub struct ListenerWrapper(pub Box<for<'r> Invoke<(&'r (AsyncResponseListener+'r))> + Send>);

impl ListenerWrapper {
@@ -71,7 +65,7 @@ impl ListenerWrapper {
}

pub trait AsyncResponseListener {
fn headers_available(&self, metadata: Metadata) -> AsyncResponseResult;
fn headers_available(&self, metadata: Metadata);
fn data_available(&self, payload: Vec<u8>);
fn response_complete(&self, status: Result<(), String>);
}
@@ -12,7 +12,7 @@ use dom::bindings::js::{JS, JSRef, Root, Unrooted};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use dom::window::{self, WindowHelpers};
use script_task::ScriptChan;
use script_task::{ScriptChan, ScriptPort, ScriptMsg, ScriptTask};

use net::resource_task::ResourceTask;

@@ -105,6 +105,24 @@ impl<'a> GlobalRef<'a> {
GlobalRef::Worker(ref worker) => worker.script_chan(),
}
}

/// `ScriptChan` used to send messages to the event loop of this global's
/// thread.
pub fn new_script_pair(&self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
match *self {
GlobalRef::Window(ref window) => window.new_script_pair(),
GlobalRef::Worker(ref worker) => worker.new_script_pair(),
}
}

/// Process a single event as if it were the next event in the task queue for
/// this global.
pub fn process_event(&self, msg: ScriptMsg) {
match *self {
GlobalRef::Window(_) => ScriptTask::process_event(msg),
GlobalRef::Worker(ref worker) => worker.process_event(msg),
}
}
}

impl<'a> Reflectable for GlobalRef<'a> {
@@ -21,7 +21,7 @@ use dom::messageevent::MessageEvent;
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler, Worker};
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use dom::workerglobalscope::WorkerGlobalScopeTypeId;
use script_task::{ScriptTask, ScriptChan, ScriptMsg, TimerSource};
use script_task::{ScriptTask, ScriptChan, ScriptMsg, TimerSource, ScriptPort};
use script_task::ScriptMsg::WorkerDispatchErrorEvent;
use script_task::StackRootTLS;

@@ -35,7 +35,7 @@ use js::jsval::JSVal;
use js::rust::Cx;

use std::rc::Rc;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc::{Sender, Receiver, channel};
use url::Url;

/// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with
@@ -185,6 +185,8 @@ impl DedicatedWorkerGlobalScope {

pub trait DedicatedWorkerGlobalScopeHelpers {
fn script_chan(self) -> Box<ScriptChan+Send>;
fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
fn process_event(self, msg: ScriptMsg);
}

impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> {
@@ -194,6 +196,19 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalSc
worker: self.worker.borrow().as_ref().unwrap().clone(),
}
}

fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
let (tx, rx) = channel();
let chan = box SendableWorkerScriptChan {
sender: tx,
worker: self.worker.borrow().as_ref().unwrap().clone(),
};
(chan, box rx)
}

fn process_event(self, msg: ScriptMsg) {
self.handle_event(msg);
}
}

trait PrivateDedicatedWorkerGlobalScopeHelpers {
@@ -29,7 +29,7 @@ use dom::storage::Storage;
use layout_interface::{ReflowGoal, ReflowQueryType, LayoutRPC, LayoutChan, Reflow, Msg};
use layout_interface::{ContentBoxResponse, ContentBoxesResponse};
use page::Page;
use script_task::{TimerSource, ScriptChan};
use script_task::{TimerSource, ScriptChan, ScriptPort, NonWorkerScriptChan};
use script_task::ScriptMsg;
use script_traits::ScriptControlChan;
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
@@ -154,6 +154,11 @@ impl Window {
self.subpage_id.clone()
}

pub fn new_script_pair(&self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
let (tx, rx) = channel();
(box NonWorkerScriptChan(tx), box rx)
}

pub fn control_chan<'a>(&'a self) -> &'a ScriptControlChan {
&self.control_chan
}
@@ -16,7 +16,7 @@ use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use dom::window::{base64_atob, base64_btoa};
use script_task::{ScriptChan, TimerSource};
use script_task::{ScriptChan, TimerSource, ScriptPort, ScriptMsg};
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};

use net::resource_task::{ResourceTask, load_whole_resource};
@@ -190,6 +190,8 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
pub trait WorkerGlobalScopeHelpers {
fn handle_fire_timer(self, timer_id: TimerId);
fn script_chan(self) -> Box<ScriptChan+Send>;
fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
fn process_event(self, msg: ScriptMsg);
fn get_cx(self) -> *mut JSContext;
}

@@ -203,6 +205,24 @@ impl<'a> WorkerGlobalScopeHelpers for JSRef<'a, WorkerGlobalScope> {
}
}

fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) {
let dedicated: Option<JSRef<DedicatedWorkerGlobalScope>> =
DedicatedWorkerGlobalScopeCast::to_ref(self);
match dedicated {
Some(dedicated) => dedicated.new_script_pair(),
None => panic!("need to implement creating isolated event loops for SharedWorker"),
}
}

fn process_event(self, msg: ScriptMsg) {
let dedicated: Option<JSRef<DedicatedWorkerGlobalScope>> =
DedicatedWorkerGlobalScopeCast::to_ref(self);
match dedicated {
Some(dedicated) => dedicated.process_event(msg),
None => panic!("need to implement processing single events for SharedWorker"),
}
}

fn handle_fire_timer(self, timer_id: TimerId) {
self.timers.fire_timer(timer_id, self);
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.