Add task_source directory

Use DOMManipulationTaskSource whenever possible
This commit is contained in:
Keith Yeung 2016-01-06 11:44:54 -05:00
parent fa93d3f467
commit 3f2cbf0025
17 changed files with 261 additions and 185 deletions

View file

@ -21,8 +21,10 @@ use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use msg::constellation_msg::{ConstellationChan, PipelineId}; use msg::constellation_msg::{ConstellationChan, PipelineId};
use net_traits::ResourceThread; use net_traits::ResourceThread;
use profile_traits::mem; use profile_traits::mem;
use script_thread::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThread}; use script_thread::{CommonScriptMsg, MainThreadScriptChan, ScriptChan, ScriptPort, ScriptThread};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest}; use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest};
use task_source::TaskSource;
use task_source::dom_manipulation::DOMManipulationTask;
use timers::{OneshotTimerCallback, OneshotTimerHandle}; use timers::{OneshotTimerCallback, OneshotTimerHandle};
use url::Url; use url::Url;
@ -142,10 +144,21 @@ impl<'a> GlobalRef<'a> {
/// `ScriptChan` used to send messages to the event loop of this global's /// `ScriptChan` used to send messages to the event loop of this global's
/// thread. /// thread.
pub fn dom_manipulation_task_source(&self) -> Box<ScriptChan + Send> { pub fn script_chan(&self) -> Box<ScriptChan + Send> {
match *self {
GlobalRef::Window(ref window) => {
MainThreadScriptChan(window.main_thread_script_chan().clone()).clone()
}
GlobalRef::Worker(ref worker) => worker.script_chan(),
}
}
/// `TaskSource` used to queue DOM manipulation messages to the event loop of this global's
/// thread.
pub fn dom_manipulation_task_source(&self) -> Box<TaskSource<DOMManipulationTask> + Send> {
match *self { match *self {
GlobalRef::Window(ref window) => window.dom_manipulation_task_source(), GlobalRef::Window(ref window) => window.dom_manipulation_task_source(),
GlobalRef::Worker(ref worker) => worker.script_chan(), GlobalRef::Worker(_) => unimplemented!(),
} }
} }

View file

@ -89,7 +89,7 @@ use net_traits::CookieSource::NonHTTP;
use net_traits::response::HttpsState; use net_traits::response::HttpsState;
use net_traits::{AsyncResponseTarget, PendingAsyncLoad}; use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
use num::ToPrimitive; use num::ToPrimitive;
use script_thread::{MainThreadScriptMsg, Runnable}; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan};
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg}; use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg};
use script_traits::{TouchEventType, TouchId}; use script_traits::{TouchEventType, TouchId};
@ -108,6 +108,7 @@ use string_cache::{Atom, QualName};
use style::context::ReflowGoal; use style::context::ReflowGoal;
use style::restyle_hints::ElementSnapshot; use style::restyle_hints::ElementSnapshot;
use style::servo::Stylesheet; use style::servo::Stylesheet;
use task_source::dom_manipulation::DOMManipulationTask;
use time; use time;
use url::percent_encoding::percent_decode; use url::percent_encoding::percent_decode;
use url::{Host, Url}; use url::{Host, Url};
@ -1406,11 +1407,11 @@ impl Document {
update_with_current_time(&self.dom_content_loaded_event_start); update_with_current_time(&self.dom_content_loaded_event_start);
let doctarget = self.upcast::<EventTarget>(); let chan = MainThreadScriptChan(self.window().main_thread_script_chan().clone()).clone();
let _ = doctarget.fire_event("DOMContentLoaded", let doctarget = Trusted::new(self.upcast::<EventTarget>(), chan);
EventBubbles::Bubbles, let task_source = self.window().dom_manipulation_task_source();
EventCancelable::NotCancelable); let _ = task_source.queue(DOMManipulationTask::FireEvent(
atom!("DOMContentLoaded"), doctarget, EventBubbles::Bubbles, EventCancelable::NotCancelable));
self.window().reflow(ReflowGoal::ForDisplay, self.window().reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery, ReflowQueryType::NoQuery,
ReflowReason::DOMContentLoaded); ReflowReason::DOMContentLoaded);
@ -2590,13 +2591,13 @@ fn update_with_current_time(marker: &Cell<u64>) {
} }
pub struct DocumentProgressHandler { pub struct DocumentProgressHandler {
addr: Trusted<Document>, addr: Trusted<Document>
} }
impl DocumentProgressHandler { impl DocumentProgressHandler {
pub fn new(addr: Trusted<Document>) -> DocumentProgressHandler { pub fn new(addr: Trusted<Document>) -> DocumentProgressHandler {
DocumentProgressHandler { DocumentProgressHandler {
addr: addr, addr: addr
} }
} }

View file

@ -14,10 +14,10 @@ use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node}; use dom::node::{Node, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use script_thread::ScriptThreadEventCategory::DomEvent; use script_thread::{MainThreadScriptChan, Runnable, ScriptChan};
use script_thread::{CommonScriptMsg, Runnable};
use std::cell::Cell; use std::cell::Cell;
use string_cache::Atom; use string_cache::Atom;
use task_source::dom_manipulation::DOMManipulationTask;
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
@ -69,7 +69,17 @@ impl VirtualMethods for HTMLDetailsElement {
if attr.local_name() == &atom!("open") { if attr.local_name() == &atom!("open") {
let counter = self.toggle_counter.get() + 1; let counter = self.toggle_counter.get() + 1;
self.toggle_counter.set(counter); self.toggle_counter.set(counter);
ToggleEventRunnable::send(&self, counter);
let window = window_from_node(self);
let window = window.r();
let task_source = window.dom_manipulation_task_source();
let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone();
let details = Trusted::new(self, chan.clone());
let runnable = box ToggleEventRunnable {
element: details,
toggle_number: counter
};
let _ = task_source.queue(DOMManipulationTask::FireToggleEvent(runnable));
} }
} }
} }
@ -79,20 +89,6 @@ pub struct ToggleEventRunnable {
toggle_number: u32 toggle_number: u32
} }
impl ToggleEventRunnable {
pub fn send(node: &HTMLDetailsElement, toggle_number: u32) {
let window = window_from_node(node);
let window = window.r();
let chan = window.dom_manipulation_task_source();
let handler = Trusted::new(node, chan.clone());
let dispatcher = ToggleEventRunnable {
element: handler,
toggle_number: toggle_number,
};
let _ = chan.send(CommonScriptMsg::RunnableMsg(DomEvent, box dispatcher));
}
}
impl Runnable for ToggleEventRunnable { impl Runnable for ToggleEventRunnable {
fn handler(self: Box<ToggleEventRunnable>) { fn handler(self: Box<ToggleEventRunnable>) {
let target = self.element.root(); let target = self.element.root();

View file

@ -37,12 +37,12 @@ use hyper::header::ContentType;
use hyper::method::Method; use hyper::method::Method;
use hyper::mime; use hyper::mime;
use msg::constellation_msg::{LoadData, PipelineId}; use msg::constellation_msg::{LoadData, PipelineId};
use script_thread::ScriptThreadEventCategory::FormPlannedNavigation; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptChan};
use script_thread::{CommonScriptMsg, MainThreadScriptMsg, Runnable, ScriptChan};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use string_cache::Atom; use string_cache::Atom;
use task_source::dom_manipulation::DOMManipulationTask;
use url::form_urlencoded::serialize; use url::form_urlencoded::serialize;
use util::str::DOMString; use util::str::DOMString;
@ -76,6 +76,10 @@ impl HTMLFormElement {
let element = HTMLFormElement::new_inherited(localName, prefix, document); let element = HTMLFormElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLFormElementBinding::Wrap) Node::reflect_node(box element, document, HTMLFormElementBinding::Wrap)
} }
pub fn generation_id(&self) -> GenerationId {
self.generation_id.get()
}
} }
impl HTMLFormElementMethods for HTMLFormElement { impl HTMLFormElementMethods for HTMLFormElement {
@ -322,17 +326,20 @@ impl HTMLFormElement {
// generation ID is the same as its own generation ID. // generation ID is the same as its own generation ID.
let GenerationId(prev_id) = self.generation_id.get(); let GenerationId(prev_id) = self.generation_id.get();
self.generation_id.set(GenerationId(prev_id + 1)); self.generation_id.set(GenerationId(prev_id + 1));
// Step 2 // Step 2
let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone();
let nav = box PlannedNavigation { let nav = box PlannedNavigation {
load_data: load_data, load_data: load_data,
pipeline_id: window.pipeline(), pipeline_id: window.pipeline(),
script_chan: window.main_thread_script_chan().clone(), script_chan: window.main_thread_script_chan().clone(),
generation_id: self.generation_id.get(), generation_id: self.generation_id.get(),
form: Trusted::new(self, window.dom_manipulation_task_source()) form: Trusted::new(self, chan)
}; };
// Step 3 // Step 3
window.dom_manipulation_task_source().send( window.dom_manipulation_task_source().queue(
CommonScriptMsg::RunnableMsg(FormPlannedNavigation, nav)).unwrap(); DOMManipulationTask::PlannedNavigation(nav)).unwrap();
} }
/// Interactively validate the constraints of form elements /// Interactively validate the constraints of form elements

View file

@ -19,6 +19,7 @@ use dom::bindings::trace::JSTraceable;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeMutation, Element, ElementCreator}; use dom::element::{AttributeMutation, Element, ElementCreator};
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{ChildrenMutation, CloneChildrenFlag, Node}; use dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
use dom::node::{document_from_node, window_from_node}; use dom::node::{document_from_node, window_from_node};
@ -34,13 +35,13 @@ use js::jsapi::RootedValue;
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata}; use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata};
use network_listener::{NetworkListener, PreInvoke}; use network_listener::{NetworkListener, PreInvoke};
use script_thread::ScriptThreadEventCategory::ScriptEvent; use script_thread::{MainThreadScriptChan, ScriptChan};
use script_thread::{CommonScriptMsg, Runnable, ScriptChan};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::cell::Cell; use std::cell::Cell;
use std::mem; use std::mem;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use string_cache::Atom; use string_cache::Atom;
use task_source::dom_manipulation::DOMManipulationTask;
use url::Url; use url::Url;
use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec};
@ -442,26 +443,20 @@ impl HTMLScriptElement {
if external { if external {
self.dispatch_load_event(); self.dispatch_load_event();
} else { } else {
let chan = window.dom_manipulation_task_source(); let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone();
let handler = Trusted::new(self, chan.clone()); let script_element = Trusted::new(self.upcast::<EventTarget>(), chan);
let dispatcher = box EventDispatcher { let task_source = window.dom_manipulation_task_source();
element: handler, task_source.queue(DOMManipulationTask::FireSimpleEvent(atom!("load"), script_element)).unwrap();
is_error: false,
};
chan.send(CommonScriptMsg::RunnableMsg(ScriptEvent, dispatcher)).unwrap();
} }
} }
pub fn queue_error_event(&self) { pub fn queue_error_event(&self) {
let window = window_from_node(self); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let chan = window.dom_manipulation_task_source(); let chan = MainThreadScriptChan(window.main_thread_script_chan().clone()).clone();
let handler = Trusted::new(self, chan.clone()); let task_source = window.dom_manipulation_task_source();
let dispatcher = box EventDispatcher { let script_element = Trusted::new(self.upcast::<EventTarget>(), chan);
element: handler, task_source.queue(DOMManipulationTask::FireSimpleEvent(atom!("error"), script_element)).unwrap();
is_error: true,
};
chan.send(CommonScriptMsg::RunnableMsg(ScriptEvent, dispatcher)).unwrap();
} }
pub fn dispatch_before_script_execute_event(&self) -> bool { pub fn dispatch_before_script_execute_event(&self) -> bool {
@ -610,19 +605,3 @@ impl HTMLScriptElementMethods for HTMLScriptElement {
self.upcast::<Node>().SetTextContent(Some(value)) self.upcast::<Node>().SetTextContent(Some(value))
} }
} }
struct EventDispatcher {
element: Trusted<HTMLScriptElement>,
is_error: bool,
}
impl Runnable for EventDispatcher {
fn handler(self: Box<EventDispatcher>) {
let target = self.element.root();
if self.is_error {
target.dispatch_error_event();
} else {
target.dispatch_load_event();
}
}
}

View file

@ -16,7 +16,8 @@ use dom::urlhelper::UrlHelper;
use ipc_channel::ipc; use ipc_channel::ipc;
use net_traits::storage_thread::{StorageThread, StorageThreadMsg, StorageType}; use net_traits::storage_thread::{StorageThread, StorageThreadMsg, StorageType};
use page::IterablePage; use page::IterablePage;
use script_thread::{MainThreadRunnable, MainThreadScriptMsg, ScriptThread}; use script_thread::{MainThreadRunnable, MainThreadScriptChan, ScriptChan, ScriptThread};
use task_source::dom_manipulation::DOMManipulationTask;
use url::Url; use url::Url;
use util::str::DOMString; use util::str::DOMString;
@ -153,10 +154,10 @@ impl Storage {
new_value: Option<String>) { new_value: Option<String>) {
let global_root = self.global(); let global_root = self.global();
let global_ref = global_root.r(); let global_ref = global_root.r();
let main_script_chan = global_ref.as_window().main_thread_script_chan(); let task_source = global_ref.as_window().dom_manipulation_task_source();
let script_chan = global_ref.dom_manipulation_task_source(); let chan = MainThreadScriptChan(global_ref.as_window().main_thread_script_chan().clone()).clone();
let trusted_storage = Trusted::new(self, script_chan); let trusted_storage = Trusted::new(self, chan);
main_script_chan.send(MainThreadScriptMsg::MainThreadRunnableMsg( task_source.queue(DOMManipulationTask::SendStorageNotification(
box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap(); box StorageEventRunnable::new(trusted_storage, key, old_value, new_value))).unwrap();
} }
} }

View file

@ -14,8 +14,8 @@ interface AbstractWorker {
interface Worker : EventTarget { interface Worker : EventTarget {
//void terminate(); //void terminate();
[Throws] [Throws]
void postMessage(any message/*, optional sequence<Transferable> transfer*/); void postMessage(any message/*, optional sequence<Transferable> transfer*/);
attribute EventHandler onmessage; attribute EventHandler onmessage;
}; };
Worker implements AbstractWorker; Worker implements AbstractWorker;

View file

@ -53,9 +53,8 @@ use page::Page;
use profile_traits::mem; use profile_traits::mem;
use reporter::CSSErrorReporter; use reporter::CSSErrorReporter;
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};
use script_thread::{DOMManipulationTaskSource, UserInteractionTaskSource, NetworkingTaskSource}; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
use script_thread::{HistoryTraversalTaskSource, FileReadingTaskSource, SendableMainThreadScriptChan}; use script_thread::{SendableMainThreadScriptChan, ScriptChan, ScriptPort};
use script_thread::{ScriptChan, ScriptPort, MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
use script_traits::{ConstellationControlMsg, UntrustedNodeAddress}; use script_traits::{ConstellationControlMsg, UntrustedNodeAddress};
use script_traits::{DocumentState, MsDuration, ScriptToCompositorMsg, TimerEvent, TimerEventId}; use script_traits::{DocumentState, MsDuration, ScriptToCompositorMsg, TimerEvent, TimerEventId};
use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource}; use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource};
@ -75,6 +74,12 @@ use string_cache::Atom;
use style::context::ReflowGoal; use style::context::ReflowGoal;
use style::error_reporting::ParseErrorReporter; use style::error_reporting::ParseErrorReporter;
use style::selector_impl::PseudoElement; use style::selector_impl::PseudoElement;
use task_source::TaskSource;
use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask};
use task_source::file_reading::FileReadingTaskSource;
use task_source::history_traversal::HistoryTraversalTaskSource;
use task_source::networking::NetworkingTaskSource;
use task_source::user_interaction::UserInteractionTaskSource;
use time; use time;
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback}; use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
use url::Url; use url::Url;
@ -258,7 +263,7 @@ impl Window {
self.js_runtime.borrow().as_ref().unwrap().cx() self.js_runtime.borrow().as_ref().unwrap().cx()
} }
pub fn dom_manipulation_task_source(&self) -> Box<ScriptChan + Send> { pub fn dom_manipulation_task_source(&self) -> Box<TaskSource<DOMManipulationTask> + Send> {
self.dom_manipulation_task_source.clone() self.dom_manipulation_task_source.clone()
} }
@ -279,8 +284,7 @@ impl Window {
} }
pub fn main_thread_script_chan(&self) -> &Sender<MainThreadScriptMsg> { pub fn main_thread_script_chan(&self) -> &Sender<MainThreadScriptMsg> {
let MainThreadScriptChan(ref sender) = self.script_chan; &self.script_chan.0
sender
} }
pub fn image_cache_chan(&self) -> ImageCacheChan { pub fn image_cache_chan(&self) -> ImageCacheChan {

View file

@ -71,7 +71,7 @@ impl Worker {
let (sender, receiver) = channel(); let (sender, receiver) = channel();
let worker = Worker::new(global, sender.clone()); let worker = Worker::new(global, sender.clone());
let worker_ref = Trusted::new(worker.r(), global.dom_manipulation_task_source()); let worker_ref = Trusted::new(worker.r(), global.script_chan());
let worker_id = global.get_next_worker_id(); let worker_id = global.get_next_worker_id();
let (devtools_sender, devtools_receiver) = ipc::channel().unwrap(); let (devtools_sender, devtools_receiver) = ipc::channel().unwrap();
@ -102,7 +102,7 @@ impl Worker {
}; };
DedicatedWorkerGlobalScope::run_worker_scope( DedicatedWorkerGlobalScope::run_worker_scope(
init, worker_url, global.pipeline(), devtools_receiver, worker_ref, init, worker_url, global.pipeline(), devtools_receiver, worker_ref,
global.dom_manipulation_task_source(), sender, receiver); global.script_chan(), sender, receiver);
Ok(worker) Ok(worker)
} }
@ -138,15 +138,15 @@ impl Worker {
} }
impl WorkerMethods for Worker { impl WorkerMethods for Worker {
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage // https://html.spec.whatwg.org/multipage/#dom-worker-postmessage
fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult { fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
let data = try!(StructuredCloneData::write(cx, message)); let data = try!(StructuredCloneData::write(cx, message));
let address = Trusted::new(self, self.global().r().dom_manipulation_task_source()); let address = Trusted::new(self, self.global().r().script_chan());
self.sender.send((address, WorkerScriptMsg::DOMMessage(data))).unwrap(); self.sender.send((address, WorkerScriptMsg::DOMMessage(data))).unwrap();
Ok(()) Ok(())
} }
// https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage // https://html.spec.whatwg.org/multipage/#handler-worker-onmessage
event_handler!(message, GetOnmessage, SetOnmessage); event_handler!(message, GetOnmessage, SetOnmessage);
// https://html.spec.whatwg.org/multipage/#handler-workerglobalscope-onerror // https://html.spec.whatwg.org/multipage/#handler-workerglobalscope-onerror

View file

@ -91,6 +91,7 @@ pub mod parse;
pub mod reporter; pub mod reporter;
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub mod script_thread; pub mod script_thread;
mod task_source;
pub mod textinput; pub mod textinput;
mod timers; mod timers;
mod unpremultiplytable; mod unpremultiplytable;

View file

@ -99,6 +99,12 @@ use std::sync::atomic::{Ordering, AtomicBool};
use std::sync::mpsc::{Receiver, Select, Sender, channel}; use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use style::context::ReflowGoal; use style::context::ReflowGoal;
use task_source::TaskSource;
use task_source::dom_manipulation::{DOMManipulationTaskSource, DOMManipulationTask};
use task_source::file_reading::FileReadingTaskSource;
use task_source::history_traversal::HistoryTraversalTaskSource;
use task_source::networking::NetworkingTaskSource;
use task_source::user_interaction::UserInteractionTaskSource;
use time::{Tm, now}; use time::{Tm, now};
use url::Url; use url::Url;
use util::opts; use util::opts;
@ -251,11 +257,11 @@ pub enum MainThreadScriptMsg {
/// Notifies the script that a window associated with a particular pipeline /// Notifies the script that a window associated with a particular pipeline
/// should be closed (only dispatched to ScriptThread). /// should be closed (only dispatched to ScriptThread).
ExitWindow(PipelineId), ExitWindow(PipelineId),
/// Generic message for running threads in the ScriptThread
MainThreadRunnableMsg(Box<MainThreadRunnable + Send>),
/// Begins a content-initiated load on the specified pipeline (only /// Begins a content-initiated load on the specified pipeline (only
/// dispatched to ScriptThread). /// dispatched to ScriptThread).
Navigate(PipelineId, LoadData), Navigate(PipelineId, LoadData),
/// Tasks that originate from the DOM manipulation task source
DOMManipulation(DOMManipulationTask),
} }
/// A cloneable interface for communicating with an event loop. /// A cloneable interface for communicating with an event loop.
@ -357,102 +363,6 @@ impl MainThreadScriptChan {
} }
} }
// FIXME: Use a task source specific message instead of MainThreadScriptMsg
#[derive(JSTraceable)]
pub struct DOMManipulationTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for DOMManipulationTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let DOMManipulationTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let DOMManipulationTaskSource(ref chan) = *self;
box DOMManipulationTaskSource((*chan).clone())
}
}
// FIXME: Use a task source specific message instead of MainThreadScriptMsg
#[derive(JSTraceable)]
pub struct UserInteractionTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for UserInteractionTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let UserInteractionTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let UserInteractionTaskSource(ref chan) = *self;
box UserInteractionTaskSource((*chan).clone())
}
}
// FIXME: Use a task source specific message instead of MainThreadScriptMsg
#[derive(JSTraceable)]
pub struct NetworkingTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for NetworkingTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let NetworkingTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let NetworkingTaskSource(ref chan) = *self;
box NetworkingTaskSource((*chan).clone())
}
}
// FIXME: Use a task source specific message instead of MainThreadScriptMsg
#[derive(JSTraceable)]
pub struct HistoryTraversalTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for HistoryTraversalTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let HistoryTraversalTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let HistoryTraversalTaskSource(ref chan) = *self;
box HistoryTraversalTaskSource((*chan).clone())
}
}
// FIXME: Use a task source specific message instead of MainThreadScriptMsg
#[derive(JSTraceable)]
pub struct FileReadingTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for FileReadingTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let FileReadingTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let FileReadingTaskSource(ref chan) = *self;
box FileReadingTaskSource((*chan).clone())
}
}
// FIXME: Use a task source specific message instead of MainThreadScriptMsg
#[derive(JSTraceable)]
pub struct ProfilerThreadSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for ProfilerThreadSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let ProfilerThreadSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let ProfilerThreadSource(ref chan) = *self;
box ProfilerThreadSource((*chan).clone())
}
}
pub struct StackRootTLS<'a>(PhantomData<&'a u32>); pub struct StackRootTLS<'a>(PhantomData<&'a u32>);
impl<'a> StackRootTLS<'a> { impl<'a> StackRootTLS<'a> {
@ -494,6 +404,7 @@ pub struct ScriptThread {
/// A channel to hand out to script thread-based entities that need to be able to enqueue /// A channel to hand out to script thread-based entities that need to be able to enqueue
/// events in the event queue. /// events in the event queue.
chan: MainThreadScriptChan, chan: MainThreadScriptChan,
dom_manipulation_task_source: DOMManipulationTaskSource, dom_manipulation_task_source: DOMManipulationTaskSource,
user_interaction_task_source: UserInteractionTaskSource, user_interaction_task_source: UserInteractionTaskSource,
@ -1155,8 +1066,6 @@ impl ScriptThread {
self.handle_navigate(id, None, load_data), self.handle_navigate(id, None, load_data),
MainThreadScriptMsg::ExitWindow(id) => MainThreadScriptMsg::ExitWindow(id) =>
self.handle_exit_window_msg(id), self.handle_exit_window_msg(id),
MainThreadScriptMsg::MainThreadRunnableMsg(runnable) =>
runnable.handler(self),
MainThreadScriptMsg::DocumentLoadsComplete(id) => MainThreadScriptMsg::DocumentLoadsComplete(id) =>
self.handle_loads_complete(id), self.handle_loads_complete(id),
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => { MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
@ -1170,6 +1079,8 @@ impl ScriptThread {
LiveDOMReferences::cleanup(addr), LiveDOMReferences::cleanup(addr),
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) => MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) =>
self.collect_reports(reports_chan), self.collect_reports(reports_chan),
MainThreadScriptMsg::DOMManipulation(msg) =>
msg.handle_msg(self),
} }
} }
@ -1366,7 +1277,7 @@ impl ScriptThread {
// https://html.spec.whatwg.org/multipage/#the-end step 7 // https://html.spec.whatwg.org/multipage/#the-end step 7
let addr: Trusted<Document> = Trusted::new(doc, self.chan.clone()); let addr: Trusted<Document> = Trusted::new(doc, self.chan.clone());
let handler = box DocumentProgressHandler::new(addr.clone()); let handler = box DocumentProgressHandler::new(addr.clone());
self.chan.send(CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::DocumentEvent, handler)).unwrap(); self.dom_manipulation_task_source.queue(DOMManipulationTask::DocumentProgress(handler)).unwrap();
let ConstellationChan(ref chan) = self.constellation_chan; let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap(); chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap();

View file

@ -0,0 +1,63 @@
/* 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/. */
use dom::bindings::refcounted::Trusted;
use dom::event::{EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use script_thread::{MainThreadRunnable, MainThreadScriptMsg, Runnable, ScriptThread};
use std::result::Result;
use std::sync::mpsc::Sender;
use string_cache::Atom;
use task_source::TaskSource;
#[derive(JSTraceable)]
pub struct DOMManipulationTaskSource(pub Sender<MainThreadScriptMsg>);
impl TaskSource<DOMManipulationTask> for DOMManipulationTaskSource {
fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> {
let DOMManipulationTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<TaskSource<DOMManipulationTask> + Send> {
let DOMManipulationTaskSource(ref chan) = *self;
box DOMManipulationTaskSource((*chan).clone())
}
}
pub enum DOMManipulationTask {
// https://html.spec.whatwg.org/multipage/#the-end step 7
DocumentProgress(Box<Runnable + Send>),
// https://dom.spec.whatwg.org/#concept-event-fire
FireEvent(Atom, Trusted<EventTarget>, EventBubbles, EventCancelable),
// https://html.spec.whatwg.org/multipage/#fire-a-simple-event
FireSimpleEvent(Atom, Trusted<EventTarget>),
// https://html.spec.whatwg.org/multipage/#details-notification-task-steps
FireToggleEvent(Box<Runnable + Send>),
// https://html.spec.whatwg.org/multipage/#planned-navigation
PlannedNavigation(Box<Runnable + Send>),
// https://html.spec.whatwg.org/multipage/#send-a-storage-notification
SendStorageNotification(Box<MainThreadRunnable + Send>)
}
impl DOMManipulationTask {
pub fn handle_msg(self, script_thread: &ScriptThread) {
use self::DOMManipulationTask::*;
match self {
DocumentProgress(runnable) => runnable.handler(),
FireEvent(name, element, bubbles, cancelable) => {
let target = element.root();
target.fire_event(&*name, bubbles, cancelable);
}
FireSimpleEvent(name, element) => {
let target = element.root();
target.fire_simple_event(&*name);
}
FireToggleEvent(runnable) => runnable.handler(),
PlannedNavigation(runnable) => runnable.handler(),
SendStorageNotification(runnable) => runnable.handler(script_thread)
}
}
}

View file

@ -0,0 +1,21 @@
/* 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/. */
use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan};
use std::sync::mpsc::Sender;
#[derive(JSTraceable)]
pub struct FileReadingTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for FileReadingTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let FileReadingTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let FileReadingTaskSource(ref chan) = *self;
box FileReadingTaskSource((*chan).clone())
}
}

View file

@ -0,0 +1,21 @@
/* 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/. */
use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan};
use std::sync::mpsc::Sender;
#[derive(JSTraceable)]
pub struct HistoryTraversalTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for HistoryTraversalTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let HistoryTraversalTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let HistoryTraversalTaskSource(ref chan) = *self;
box HistoryTraversalTaskSource((*chan).clone())
}
}

View file

@ -0,0 +1,16 @@
/* 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/. */
pub mod dom_manipulation;
pub mod file_reading;
pub mod history_traversal;
pub mod networking;
pub mod user_interaction;
use std::result::Result;
pub trait TaskSource<T> {
fn queue(&self, msg: T) -> Result<(), ()>;
fn clone(&self) -> Box<TaskSource<T> + Send>;
}

View file

@ -0,0 +1,21 @@
/* 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/. */
use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan};
use std::sync::mpsc::Sender;
#[derive(JSTraceable)]
pub struct NetworkingTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for NetworkingTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let NetworkingTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let NetworkingTaskSource(ref chan) = *self;
box NetworkingTaskSource((*chan).clone())
}
}

View file

@ -0,0 +1,21 @@
/* 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/. */
use script_thread::{CommonScriptMsg, MainThreadScriptMsg, ScriptChan};
use std::sync::mpsc::Sender;
#[derive(JSTraceable)]
pub struct UserInteractionTaskSource(pub Sender<MainThreadScriptMsg>);
impl ScriptChan for UserInteractionTaskSource {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
let UserInteractionTaskSource(ref chan) = *self;
chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ())
}
fn clone(&self) -> Box<ScriptChan + Send> {
let UserInteractionTaskSource(ref chan) = *self;
box UserInteractionTaskSource((*chan).clone())
}
}