Reduce the number of channels that talk to the script task to one

This commit is contained in:
Patrick Walton 2013-05-16 18:15:37 -07:00
parent 6365becb6b
commit b17d9dc220
8 changed files with 160 additions and 173 deletions

View file

@ -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.

View file

@ -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);
} }
} }

View file

@ -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) }
};
} }
} }

View file

@ -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
}
} }

View file

@ -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());

View file

@ -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
}; };

View file

@ -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),

View file

@ -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);