mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Reduce the number of channels that talk to the script task to one
This commit is contained in:
parent
6365becb6b
commit
b17d9dc220
8 changed files with 160 additions and 173 deletions
|
@ -3,8 +3,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use compositing::resize_rate_limiter::ResizeRateLimiter;
|
use compositing::resize_rate_limiter::ResizeRateLimiter;
|
||||||
use dom::event::Event;
|
|
||||||
use platform::{Application, Window};
|
use platform::{Application, Window};
|
||||||
|
use scripting::script_task::{LoadMsg, ScriptMsg};
|
||||||
use windowing::{ApplicationMethods, WindowMethods};
|
use windowing::{ApplicationMethods, WindowMethods};
|
||||||
|
|
||||||
use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
||||||
|
@ -30,11 +30,11 @@ pub struct CompositorImpl {
|
||||||
|
|
||||||
impl CompositorImpl {
|
impl CompositorImpl {
|
||||||
/// Creates a new compositor instance.
|
/// Creates a new compositor instance.
|
||||||
pub fn new(dom_event_chan: SharedChan<Event>, opts: Opts) -> CompositorImpl {
|
pub fn new(script_chan: SharedChan<ScriptMsg>, opts: Opts) -> CompositorImpl {
|
||||||
let dom_event_chan = Cell(dom_event_chan);
|
let script_chan = Cell(script_chan);
|
||||||
let chan: Chan<Msg> = do on_osmain |port| {
|
let chan: Chan<Msg> = do on_osmain |port| {
|
||||||
debug!("preparing to enter main loop");
|
debug!("preparing to enter main loop");
|
||||||
mainloop(port, dom_event_chan.take(), &opts);
|
mainloop(port, script_chan.take(), &opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
CompositorImpl {
|
CompositorImpl {
|
||||||
|
@ -76,7 +76,7 @@ impl layers::layers::ImageData for AzureDrawTargetImageData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mainloop(po: Port<Msg>, dom_event_chan: SharedChan<Event>, opts: &Opts) {
|
fn mainloop(po: Port<Msg>, script_chan: SharedChan<ScriptMsg>, opts: &Opts) {
|
||||||
let key_handlers: @mut ~[Chan<()>] = @mut ~[];
|
let key_handlers: @mut ~[Chan<()>] = @mut ~[];
|
||||||
|
|
||||||
let app: Application = ApplicationMethods::new();
|
let app: Application = ApplicationMethods::new();
|
||||||
|
@ -110,7 +110,7 @@ fn mainloop(po: Port<Msg>, dom_event_chan: SharedChan<Event>, opts: &Opts) {
|
||||||
identity());
|
identity());
|
||||||
|
|
||||||
let done = @mut false;
|
let done = @mut false;
|
||||||
let resize_rate_limiter = @mut ResizeRateLimiter(dom_event_chan);
|
let resize_rate_limiter = @mut ResizeRateLimiter(script_chan.clone());
|
||||||
let check_for_messages: @fn() = || {
|
let check_for_messages: @fn() = || {
|
||||||
// Periodically check if the script task responded to our last resize event
|
// Periodically check if the script task responded to our last resize event
|
||||||
resize_rate_limiter.check_resize_response();
|
resize_rate_limiter.check_resize_response();
|
||||||
|
@ -197,6 +197,12 @@ fn mainloop(po: Port<Msg>, dom_event_chan: SharedChan<Event>, opts: &Opts) {
|
||||||
resize_rate_limiter.window_resized(width, height);
|
resize_rate_limiter.window_resized(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When the user enters a new URL, load it.
|
||||||
|
do window.set_load_url_callback |url_string| {
|
||||||
|
debug!("osmain: loading URL `%s`", url_string);
|
||||||
|
script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None)))
|
||||||
|
}
|
||||||
|
|
||||||
// Enter the main event loop.
|
// Enter the main event loop.
|
||||||
while !*done {
|
while !*done {
|
||||||
// Check for new messages coming from the rendering task.
|
// Check for new messages coming from the rendering task.
|
||||||
|
|
|
@ -2,27 +2,28 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/*!
|
//! A little class that rate limits the number of resize events sent to the script task
|
||||||
A little class that rate limits the number of resize events sent to the script task
|
/// based on how fast script dispatches those events. It waits until each event is handled
|
||||||
based on how fast script dispatches those events. It waits until each event is handled
|
/// before sending the next. If the window is resized multiple times before an event is handled
|
||||||
before sending the next. If the window is resized multiple times before an event is handled
|
/// then some events will never be sent.
|
||||||
then some events will never be sent.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use dom::event::{Event, ResizeEvent};
|
use dom::event::ResizeEvent;
|
||||||
|
use scripting::script_task::{ScriptMsg, SendEventMsg};
|
||||||
|
|
||||||
|
use core::comm::{Port, SharedChan};
|
||||||
|
|
||||||
pub struct ResizeRateLimiter {
|
pub struct ResizeRateLimiter {
|
||||||
/// The channel we send resize events on
|
/// The channel we send resize events on
|
||||||
/* priv */ dom_event_chan: comm::SharedChan<Event>,
|
priv script_chan: SharedChan<ScriptMsg>,
|
||||||
/// The port we are waiting on for a response to the last resize event
|
/// The port we are waiting on for a response to the last resize event
|
||||||
/* priv */ last_response_port: Option<comm::Port<()>>,
|
priv last_response_port: Option<Port<()>>,
|
||||||
/// The next window resize event we should fire
|
/// The next window resize event we should fire
|
||||||
/* priv */ next_resize_event: Option<(uint, uint)>
|
priv next_resize_event: Option<(uint, uint)>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ResizeRateLimiter(dom_event_chan: comm::SharedChan<Event>) -> ResizeRateLimiter {
|
pub fn ResizeRateLimiter(script_chan: SharedChan<ScriptMsg>) -> ResizeRateLimiter {
|
||||||
ResizeRateLimiter {
|
ResizeRateLimiter {
|
||||||
dom_event_chan: dom_event_chan,
|
script_chan: script_chan,
|
||||||
last_response_port: None,
|
last_response_port: None,
|
||||||
next_resize_event: None
|
next_resize_event: None
|
||||||
}
|
}
|
||||||
|
@ -64,7 +65,7 @@ pub impl ResizeRateLimiter {
|
||||||
|
|
||||||
priv fn send_event(&mut self, width: uint, height: uint) {
|
priv fn send_event(&mut self, width: uint, height: uint) {
|
||||||
let (port, chan) = comm::stream();
|
let (port, chan) = comm::stream();
|
||||||
self.dom_event_chan.send(ResizeEvent(width, height, chan));
|
self.script_chan.send(SendEventMsg(ResizeEvent(width, height, chan)));
|
||||||
self.last_response_port = Some(port);
|
self.last_response_port = Some(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use dom::event::ReflowEvent;
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use dom::node::AbstractNode;
|
use dom::node::AbstractNode;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use scripting::script_task::global_script_context;
|
use scripting::script_task::{SendEventMsg, global_script_context};
|
||||||
|
|
||||||
use js::jsapi::bindgen::{JS_AddObjectRoot, JS_RemoveObjectRoot};
|
use js::jsapi::bindgen::{JS_AddObjectRoot, JS_RemoveObjectRoot};
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
|
@ -64,9 +64,9 @@ pub impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_changed(&self) {
|
fn content_changed(&self) {
|
||||||
do self.window.map |window| {
|
for self.window.each |window| {
|
||||||
let chan = &mut window.dom_event_chan;
|
window.script_chan.send(SendEventMsg(ReflowEvent))
|
||||||
chan.send(ReflowEvent)
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
use dom::bindings::utils::WrapperCache;
|
use dom::bindings::utils::WrapperCache;
|
||||||
use dom::bindings::window;
|
use dom::bindings::window;
|
||||||
use dom::event::Event;
|
use scripting::script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext};
|
||||||
use scripting::script_task::{ControlMsg, ExitMsg, FireTimerMsg, ScriptContext};
|
|
||||||
use scripting::script_task::{global_script_context};
|
use scripting::script_task::{global_script_context};
|
||||||
use util::task::spawn_listener;
|
use util::task::spawn_listener;
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ pub enum TimerControlMsg {
|
||||||
// only used for querying layout from arbitrary script.
|
// only used for querying layout from arbitrary script.
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
timer_chan: Chan<TimerControlMsg>,
|
timer_chan: Chan<TimerControlMsg>,
|
||||||
dom_event_chan: SharedChan<Event>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
script_context: *mut ScriptContext,
|
script_context: *mut ScriptContext,
|
||||||
wrapper: WrapperCache
|
wrapper: WrapperCache
|
||||||
}
|
}
|
||||||
|
@ -82,30 +81,30 @@ pub impl Window {
|
||||||
&self.timer_chan,
|
&self.timer_chan,
|
||||||
TimerMessage_Fire(~TimerData(argc, argv)));
|
TimerMessage_Fire(~TimerData(argc, argv)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn Window(script_chan: comm::SharedChan<ControlMsg>,
|
pub fn new(script_chan: SharedChan<ScriptMsg>, script_context: *mut ScriptContext)
|
||||||
dom_event_chan: comm::SharedChan<Event>,
|
-> @mut Window {
|
||||||
script_context: *mut ScriptContext)
|
let script_chan_copy = script_chan.clone();
|
||||||
-> @mut Window {
|
let win = @mut Window {
|
||||||
let win = @mut Window {
|
wrapper: WrapperCache::new(),
|
||||||
wrapper: WrapperCache::new(),
|
script_chan: script_chan,
|
||||||
dom_event_chan: dom_event_chan,
|
timer_chan: {
|
||||||
timer_chan: {
|
do spawn_listener |timer_port: Port<TimerControlMsg>| {
|
||||||
do spawn_listener |timer_port: Port<TimerControlMsg>| {
|
loop {
|
||||||
loop {
|
match timer_port.recv() {
|
||||||
match timer_port.recv() {
|
TimerMessage_Close => break,
|
||||||
TimerMessage_Close => break,
|
TimerMessage_Fire(td) => script_chan_copy.send(FireTimerMsg(td)),
|
||||||
TimerMessage_Fire(td) => script_chan.send(FireTimerMsg(td)),
|
TimerMessage_TriggerExit => script_chan_copy.send(ExitMsg),
|
||||||
TimerMessage_TriggerExit => script_chan.send(ExitMsg),
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
script_context: script_context,
|
||||||
script_context: script_context,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let compartment = global_script_context().js_compartment;
|
let compartment = global_script_context().js_compartment;
|
||||||
window::create(compartment, win);
|
window::create(compartment, win);
|
||||||
win
|
win
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use compositing::CompositorImpl;
|
use compositing::CompositorImpl;
|
||||||
use dom::event::Event;
|
|
||||||
use layout::layout_task::LayoutTask;
|
use layout::layout_task::LayoutTask;
|
||||||
use layout::layout_task;
|
use layout::layout_task;
|
||||||
use scripting::script_task::{ExecuteMsg, LoadMsg, ScriptTask};
|
use scripting::script_task::{ExecuteMsg, LoadMsg, ScriptMsg, ScriptTask};
|
||||||
use scripting::script_task;
|
use scripting::script_task;
|
||||||
use util::task::spawn_listener;
|
use util::task::spawn_listener;
|
||||||
|
|
||||||
|
@ -40,24 +39,23 @@ pub struct Engine {
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn start(compositor: CompositorImpl,
|
pub fn start(compositor: CompositorImpl,
|
||||||
opts: &Opts,
|
opts: &Opts,
|
||||||
dom_event_port: Port<Event>,
|
script_port: Port<ScriptMsg>,
|
||||||
dom_event_chan: SharedChan<Event>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask)
|
image_cache_task: ImageCacheTask)
|
||||||
-> EngineTask {
|
-> EngineTask {
|
||||||
let dom_event_port = Cell(dom_event_port);
|
let (script_port, script_chan) = (Cell(script_port), Cell(script_chan));
|
||||||
let dom_event_chan = Cell(dom_event_chan);
|
|
||||||
|
|
||||||
let opts = Cell(copy *opts);
|
let opts = Cell(copy *opts);
|
||||||
|
|
||||||
do spawn_listener::<Msg> |request| {
|
do spawn_listener::<Msg> |request| {
|
||||||
let render_task = RenderTask(compositor.clone(), opts.with_ref(|o| copy *o));
|
let render_task = RenderTask(compositor.clone(), opts.with_ref(|o| copy *o));
|
||||||
|
|
||||||
let opts = opts.take();
|
let opts = opts.take();
|
||||||
let layout_task = LayoutTask(render_task.clone(), image_cache_task.clone(), opts);
|
let layout_task = LayoutTask(render_task.clone(), image_cache_task.clone(), opts);
|
||||||
|
|
||||||
let script_task = ScriptTask::new(layout_task.clone(),
|
let script_task = ScriptTask::new(script_port.take(),
|
||||||
dom_event_port.take(),
|
script_chan.take(),
|
||||||
dom_event_chan.take(),
|
layout_task.clone(),
|
||||||
resource_task.clone(),
|
resource_task.clone(),
|
||||||
image_cache_task.clone());
|
image_cache_task.clone());
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use css::matching::MatchMethods;
|
use css::matching::MatchMethods;
|
||||||
use css::select::new_css_select_ctx;
|
use css::select::new_css_select_ctx;
|
||||||
use dom::event::{Event, ReflowEvent};
|
use dom::event::ReflowEvent;
|
||||||
use dom::node::{AbstractNode, LayoutData};
|
use dom::node::{AbstractNode, LayoutData};
|
||||||
use layout::aux::LayoutAuxMethods;
|
use layout::aux::LayoutAuxMethods;
|
||||||
use layout::box_builder::LayoutTreeBuilder;
|
use layout::box_builder::LayoutTreeBuilder;
|
||||||
|
@ -15,6 +15,7 @@ use layout::context::LayoutContext;
|
||||||
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
||||||
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
||||||
use layout::flow::FlowContext;
|
use layout::flow::FlowContext;
|
||||||
|
use scripting::script_task::{ScriptMsg, SendEventMsg};
|
||||||
use util::task::spawn_listener;
|
use util::task::spawn_listener;
|
||||||
use util::time::time;
|
use util::time::time;
|
||||||
|
|
||||||
|
@ -79,19 +80,19 @@ impl Damage {
|
||||||
pub struct BuildData {
|
pub struct BuildData {
|
||||||
node: AbstractNode,
|
node: AbstractNode,
|
||||||
url: Url,
|
url: Url,
|
||||||
dom_event_chan: comm::SharedChan<Event>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
window_size: Size2D<uint>,
|
window_size: Size2D<uint>,
|
||||||
script_join_chan: comm::Chan<()>,
|
script_join_chan: Chan<()>,
|
||||||
damage: Damage,
|
damage: Damage,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn LayoutTask(render_task: RenderTask,
|
pub fn LayoutTask(render_task: RenderTask,
|
||||||
img_cache_task: ImageCacheTask,
|
img_cache_task: ImageCacheTask,
|
||||||
opts: Opts) -> LayoutTask {
|
opts: Opts) -> LayoutTask {
|
||||||
SharedChan::new(spawn_listener::<Msg>(|from_script| {
|
SharedChan::new(do spawn_listener::<Msg> |from_script| {
|
||||||
let mut layout = Layout(render_task.clone(), img_cache_task.clone(), from_script, &opts);
|
let mut layout = Layout(render_task.clone(), img_cache_task.clone(), from_script, &opts);
|
||||||
layout.start();
|
layout.start();
|
||||||
}))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
|
@ -170,8 +171,7 @@ impl Layout {
|
||||||
let node = &data.node;
|
let node = &data.node;
|
||||||
// FIXME: Bad copy!
|
// FIXME: Bad copy!
|
||||||
let doc_url = copy data.url;
|
let doc_url = copy data.url;
|
||||||
// FIXME: Bad clone!
|
let script_chan = data.script_chan.clone();
|
||||||
let dom_event_chan = data.dom_event_chan.clone();
|
|
||||||
|
|
||||||
debug!("layout: received layout request for: %s", doc_url.to_str());
|
debug!("layout: received layout request for: %s", doc_url.to_str());
|
||||||
debug!("layout: damage is %?", data.damage);
|
debug!("layout: damage is %?", data.damage);
|
||||||
|
@ -179,7 +179,7 @@ impl Layout {
|
||||||
debug!("%?", node.dump());
|
debug!("%?", node.dump());
|
||||||
|
|
||||||
// Reset the image cache.
|
// Reset the image cache.
|
||||||
self.local_image_cache.next_round(self.make_on_image_available_cb(dom_event_chan));
|
self.local_image_cache.next_round(self.make_on_image_available_cb(script_chan));
|
||||||
|
|
||||||
let screen_size = Size2D(Au::from_px(data.window_size.width as int),
|
let screen_size = Size2D(Au::from_px(data.window_size.width as int),
|
||||||
Au::from_px(data.window_size.height as int));
|
Au::from_px(data.window_size.height as int));
|
||||||
|
@ -315,15 +315,16 @@ impl Layout {
|
||||||
// to the script task, and ultimately cause the image to be
|
// to the script task, and ultimately cause the image to be
|
||||||
// re-requested. We probably don't need to go all the way back to
|
// re-requested. We probably don't need to go all the way back to
|
||||||
// the script task for this.
|
// the script task for this.
|
||||||
fn make_on_image_available_cb(&self, dom_event_chan: comm::SharedChan<Event>) -> @fn() -> ~fn(ImageResponseMsg) {
|
fn make_on_image_available_cb(&self, script_chan: SharedChan<ScriptMsg>)
|
||||||
|
-> @fn() -> ~fn(ImageResponseMsg) {
|
||||||
// This has a crazy signature because the image cache needs to
|
// This has a crazy signature because the image cache needs to
|
||||||
// make multiple copies of the callback, and the dom event
|
// make multiple copies of the callback, and the dom event
|
||||||
// channel is not a copyable type, so this is actually a
|
// channel is not a copyable type, so this is actually a
|
||||||
// little factory to produce callbacks
|
// little factory to produce callbacks
|
||||||
let f: @fn() -> ~fn(ImageResponseMsg) = || {
|
let f: @fn() -> ~fn(ImageResponseMsg) = || {
|
||||||
let dom_event_chan = dom_event_chan.clone();
|
let script_chan = script_chan.clone();
|
||||||
let f: ~fn(ImageResponseMsg) = |_| {
|
let f: ~fn(ImageResponseMsg) = |_| {
|
||||||
dom_event_chan.send(ReflowEvent)
|
script_chan.send(SendEventMsg(ReflowEvent))
|
||||||
};
|
};
|
||||||
f
|
f
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,6 @@ use core::cell::Cell;
|
||||||
use core::comm::{Port, SharedChan};
|
use core::comm::{Port, SharedChan};
|
||||||
use core::io::read_whole_file;
|
use core::io::read_whole_file;
|
||||||
use core::local_data;
|
use core::local_data;
|
||||||
use core::pipes::select2i;
|
|
||||||
use core::ptr::null;
|
use core::ptr::null;
|
||||||
use core::task::{SingleThreaded, task};
|
use core::task::{SingleThreaded, task};
|
||||||
use core::util::replace;
|
use core::util::replace;
|
||||||
|
@ -40,12 +39,14 @@ use servo_util::tree::TreeNodeRef;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use std::net::url;
|
use std::net::url;
|
||||||
|
|
||||||
/// Messages used to control the script task at a high level.
|
/// Messages used to control the script task.
|
||||||
pub enum ControlMsg {
|
pub enum ScriptMsg {
|
||||||
/// Loads a new URL.
|
/// Loads a new URL.
|
||||||
LoadMsg(Url),
|
LoadMsg(Url),
|
||||||
/// Executes a standalone script.
|
/// Executes a standalone script.
|
||||||
ExecuteMsg(Url),
|
ExecuteMsg(Url),
|
||||||
|
/// Sends a DOM event.
|
||||||
|
SendEventMsg(Event),
|
||||||
/// Fires a JavaScript timeout.
|
/// Fires a JavaScript timeout.
|
||||||
FireTimerMsg(~TimerData),
|
FireTimerMsg(~TimerData),
|
||||||
/// Exits the engine.
|
/// Exits the engine.
|
||||||
|
@ -54,42 +55,34 @@ pub enum ControlMsg {
|
||||||
|
|
||||||
/// Encapsulates external communication with the script task.
|
/// Encapsulates external communication with the script task.
|
||||||
pub struct ScriptTask {
|
pub struct ScriptTask {
|
||||||
/// The channel used to send control messages to the script task.
|
/// The channel used to send messages to the script task.
|
||||||
chan: SharedChan<ControlMsg>,
|
chan: SharedChan<ScriptMsg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScriptTask {
|
impl ScriptTask {
|
||||||
/// Creates a new script task.
|
/// Creates a new script task.
|
||||||
pub fn new(layout_task: LayoutTask,
|
pub fn new(script_port: Port<ScriptMsg>,
|
||||||
dom_event_port: Port<Event>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
dom_event_chan: SharedChan<Event>,
|
layout_task: LayoutTask,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask)
|
image_cache_task: ImageCacheTask)
|
||||||
-> ScriptTask {
|
-> ScriptTask {
|
||||||
let (control_port, control_chan) = comm::stream();
|
let (script_chan_copy, script_port) = (script_chan.clone(), Cell(script_port));
|
||||||
|
|
||||||
let control_chan = SharedChan::new(control_chan);
|
|
||||||
let control_chan_copy = control_chan.clone();
|
|
||||||
let control_port = Cell(control_port);
|
|
||||||
let dom_event_port = Cell(dom_event_port);
|
|
||||||
let dom_event_chan = Cell(dom_event_chan);
|
|
||||||
|
|
||||||
// FIXME: rust#6399
|
// FIXME: rust#6399
|
||||||
let mut the_task = task();
|
let mut the_task = task();
|
||||||
the_task.sched_mode(SingleThreaded);
|
the_task.sched_mode(SingleThreaded);
|
||||||
do the_task.spawn {
|
do the_task.spawn {
|
||||||
let script_context = ScriptContext::new(layout_task.clone(),
|
let script_context = ScriptContext::new(layout_task.clone(),
|
||||||
control_port.take(),
|
script_port.take(),
|
||||||
control_chan_copy.clone(),
|
script_chan_copy.clone(),
|
||||||
resource_task.clone(),
|
resource_task.clone(),
|
||||||
image_cache_task.clone(),
|
image_cache_task.clone());
|
||||||
dom_event_port.take(),
|
|
||||||
dom_event_chan.take());
|
|
||||||
script_context.start();
|
script_context.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptTask {
|
ScriptTask {
|
||||||
chan: control_chan
|
chan: script_chan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,16 +109,11 @@ pub struct ScriptContext {
|
||||||
/// The port that we will use to join layout. If this is `None`, then layout is not currently
|
/// The port that we will use to join layout. If this is `None`, then layout is not currently
|
||||||
/// running.
|
/// running.
|
||||||
layout_join_port: Option<Port<()>>,
|
layout_join_port: Option<Port<()>>,
|
||||||
/// The port on which we receive control messages (load URL, exit, etc.)
|
/// The port on which we receive messages (load URL, exit, etc.)
|
||||||
control_port: Port<ControlMsg>,
|
script_port: Port<ScriptMsg>,
|
||||||
/// A channel for us to hand out when we want some other task to be able to send us control
|
/// A channel for us to hand out when we want some other task to be able to send us script
|
||||||
/// messages.
|
/// messages.
|
||||||
control_chan: SharedChan<ControlMsg>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
/// The port on which we receive DOM events.
|
|
||||||
event_port: Port<Event>,
|
|
||||||
/// A channel for us to hand out when we want some other task to be able to send us DOM
|
|
||||||
/// events.
|
|
||||||
event_chan: SharedChan<Event>,
|
|
||||||
|
|
||||||
/// The JavaScript runtime.
|
/// The JavaScript runtime.
|
||||||
js_runtime: js::rust::rt,
|
js_runtime: js::rust::rt,
|
||||||
|
@ -173,12 +161,10 @@ impl Drop for ScriptContext {
|
||||||
impl ScriptContext {
|
impl ScriptContext {
|
||||||
/// Creates a new script context.
|
/// Creates a new script context.
|
||||||
pub fn new(layout_task: LayoutTask,
|
pub fn new(layout_task: LayoutTask,
|
||||||
control_port: Port<ControlMsg>,
|
script_port: Port<ScriptMsg>,
|
||||||
control_chan: SharedChan<ControlMsg>,
|
script_chan: SharedChan<ScriptMsg>,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
img_cache_task: ImageCacheTask,
|
img_cache_task: ImageCacheTask)
|
||||||
event_port: Port<Event>,
|
|
||||||
event_chan: SharedChan<Event>)
|
|
||||||
-> @mut ScriptContext {
|
-> @mut ScriptContext {
|
||||||
let js_runtime = js::rust::rt();
|
let js_runtime = js::rust::rt();
|
||||||
let js_context = js_runtime.cx();
|
let js_context = js_runtime.cx();
|
||||||
|
@ -197,10 +183,8 @@ impl ScriptContext {
|
||||||
resource_task: resource_task,
|
resource_task: resource_task,
|
||||||
|
|
||||||
layout_join_port: None,
|
layout_join_port: None,
|
||||||
control_port: control_port,
|
script_port: script_port,
|
||||||
control_chan: control_chan,
|
script_chan: script_chan,
|
||||||
event_port: event_port,
|
|
||||||
event_chan: event_chan,
|
|
||||||
|
|
||||||
js_runtime: js_runtime,
|
js_runtime: js_runtime,
|
||||||
js_context: js_context,
|
js_context: js_context,
|
||||||
|
@ -233,74 +217,72 @@ impl ScriptContext {
|
||||||
|
|
||||||
/// Handles an incoming control message.
|
/// Handles an incoming control message.
|
||||||
fn handle_msg(&mut self) -> bool {
|
fn handle_msg(&mut self) -> bool {
|
||||||
match select2i(&mut self.control_port, &mut self.event_port) {
|
match self.script_port.recv() {
|
||||||
Left(*) => {
|
LoadMsg(url) => {
|
||||||
let msg = self.control_port.recv();
|
self.load(url);
|
||||||
self.handle_control_msg(msg)
|
|
||||||
}
|
|
||||||
Right(*) => {
|
|
||||||
let ev = self.event_port.recv();
|
|
||||||
self.handle_event(ev);
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
ExecuteMsg(url) => {
|
||||||
|
self.handle_execute_msg(url);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
SendEventMsg(event) => {
|
||||||
|
self.handle_event(event);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
FireTimerMsg(timer_data) => {
|
||||||
|
self.handle_fire_timer_msg(timer_data);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ExitMsg => {
|
||||||
|
self.handle_exit_msg();
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a control message from the compositor/front-end. Returns true if the task is to
|
/// Handles a request to execute a script.
|
||||||
/// continue and false otherwise.
|
fn handle_execute_msg(&self, url: Url) {
|
||||||
fn handle_control_msg(&mut self, control_msg: ControlMsg) -> bool {
|
debug!("script: Received url `%s` to execute", url::to_str(&url));
|
||||||
match control_msg {
|
|
||||||
LoadMsg(url) => {
|
|
||||||
debug!("script: Received url `%s` to load", url::to_str(&url));
|
|
||||||
self.load(url);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
FireTimerMsg(timer_data) => {
|
match read_whole_file(&Path(url.path)) {
|
||||||
let this_value = if timer_data.args.len() > 0 {
|
Err(msg) => println(fmt!("Error opening %s: %s", url::to_str(&url), msg)),
|
||||||
RUST_JSVAL_TO_OBJECT(timer_data.args[0])
|
|
||||||
} else {
|
|
||||||
self.js_compartment.global_obj.ptr
|
|
||||||
};
|
|
||||||
|
|
||||||
let rval = JSVAL_NULL;
|
Ok(bytes) => {
|
||||||
// TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`.
|
self.js_compartment.define_functions(debug_fns);
|
||||||
JS_CallFunctionValue(self.js_context.ptr,
|
let _ = self.js_context.evaluate_script(self.js_compartment.global_obj,
|
||||||
this_value,
|
bytes,
|
||||||
timer_data.funval,
|
copy url.path,
|
||||||
0,
|
1);
|
||||||
null(),
|
|
||||||
&rval);
|
|
||||||
|
|
||||||
self.relayout();
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ExecuteMsg(url) => {
|
|
||||||
debug!("script: Received url `%s` to execute", url::to_str(&url));
|
|
||||||
|
|
||||||
match read_whole_file(&Path(url.path)) {
|
|
||||||
Err(msg) => println(fmt!("Error opening %s: %s", url::to_str(&url), msg)),
|
|
||||||
Ok(bytes) => {
|
|
||||||
self.js_compartment.define_functions(debug_fns);
|
|
||||||
let _ = self.js_context.evaluate_script(self.js_compartment.global_obj,
|
|
||||||
bytes,
|
|
||||||
copy url.path,
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
ExitMsg => {
|
|
||||||
self.layout_task.send(layout_task::ExitMsg);
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles a timer that fired.
|
||||||
|
fn handle_fire_timer_msg(&mut self, timer_data: ~TimerData) {
|
||||||
|
let this_value = if timer_data.args.len() > 0 {
|
||||||
|
RUST_JSVAL_TO_OBJECT(timer_data.args[0])
|
||||||
|
} else {
|
||||||
|
self.js_compartment.global_obj.ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`.
|
||||||
|
let rval = JSVAL_NULL;
|
||||||
|
JS_CallFunctionValue(self.js_context.ptr,
|
||||||
|
this_value,
|
||||||
|
timer_data.funval,
|
||||||
|
0,
|
||||||
|
null(),
|
||||||
|
&rval);
|
||||||
|
|
||||||
|
self.relayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles a request to exit the script task and shut down layout.
|
||||||
|
fn handle_exit_msg(&mut self) {
|
||||||
|
self.layout_task.send(layout_task::ExitMsg)
|
||||||
|
}
|
||||||
|
|
||||||
/// The entry point to document loading. Defines bindings, sets up the window and document
|
/// The entry point to document loading. Defines bindings, sets up the window and document
|
||||||
/// objects, parses HTML and CSS, and kicks off initial layout.
|
/// objects, parses HTML and CSS, and kicks off initial layout.
|
||||||
fn load(&mut self, url: Url) {
|
fn load(&mut self, url: Url) {
|
||||||
|
@ -332,7 +314,7 @@ impl ScriptContext {
|
||||||
debug!("js_scripts: %?", js_scripts);
|
debug!("js_scripts: %?", js_scripts);
|
||||||
|
|
||||||
// Create the window and document objects.
|
// Create the window and document objects.
|
||||||
let window = Window(self.control_chan.clone(), self.event_chan.clone(), &mut *self);
|
let window = Window::new(self.script_chan.clone(), &mut *self);
|
||||||
let document = Document(root_node, Some(window));
|
let document = Document(root_node, Some(window));
|
||||||
|
|
||||||
// Tie the root into the document.
|
// Tie the root into the document.
|
||||||
|
@ -405,7 +387,7 @@ impl ScriptContext {
|
||||||
let data = ~BuildData {
|
let data = ~BuildData {
|
||||||
node: root_frame.document.root,
|
node: root_frame.document.root,
|
||||||
url: copy root_frame.url,
|
url: copy root_frame.url,
|
||||||
dom_event_chan: self.event_chan.clone(),
|
script_chan: self.script_chan.clone(),
|
||||||
window_size: self.window_size,
|
window_size: self.window_size,
|
||||||
script_join_chan: join_chan,
|
script_join_chan: join_chan,
|
||||||
damage: replace(&mut self.damage, NoDamage),
|
damage: replace(&mut self.damage, NoDamage),
|
||||||
|
|
|
@ -133,11 +133,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(opts: &Opts) {
|
fn run(opts: &Opts) {
|
||||||
let (dom_event_port, dom_event_chan) = comm::stream();
|
let (script_port, script_chan) = comm::stream();
|
||||||
let dom_event_chan = SharedChan::new(dom_event_chan);
|
let script_chan = SharedChan::new(script_chan);
|
||||||
|
|
||||||
// The platform event handler thread
|
// The platform event handler thread
|
||||||
let compositor = CompositorImpl::new(dom_event_chan.clone(), copy *opts);
|
let compositor = CompositorImpl::new(script_chan.clone(), copy *opts);
|
||||||
|
|
||||||
// Send each file to render then wait for keypress
|
// Send each file to render then wait for keypress
|
||||||
let (keypress_from_compositor, keypress_to_engine) = comm::stream();
|
let (keypress_from_compositor, keypress_to_engine) = comm::stream();
|
||||||
|
@ -148,8 +148,8 @@ fn run(opts: &Opts) {
|
||||||
let image_cache_task = ImageCacheTask(resource_task.clone());
|
let image_cache_task = ImageCacheTask(resource_task.clone());
|
||||||
let engine_task = Engine::start(compositor.clone(),
|
let engine_task = Engine::start(compositor.clone(),
|
||||||
opts,
|
opts,
|
||||||
dom_event_port,
|
script_port,
|
||||||
dom_event_chan,
|
script_chan,
|
||||||
resource_task,
|
resource_task,
|
||||||
image_cache_task);
|
image_cache_task);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue