aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Kuehn <tkuehn@cmu.edu>2013-06-26 22:42:01 -0700
committerTim Kuehn <tkuehn@cmu.edu>2013-07-01 11:03:31 -0700
commitfba7ec423c99a63bdcbe16029740e7ab4e38c088 (patch)
tree0e8a15014ee5bbf912153e8072c0a5505d3b4ecc
parentfdb0d820a49fac9ae2df623751912adcbe7a119d (diff)
downloadservo-fba7ec423c99a63bdcbe16029740e7ab4e38c088.tar.gz
servo-fba7ec423c99a63bdcbe16029740e7ab4e38c088.zip
add pipeline.rs, modularized pipelines communicating with constellation
-rw-r--r--src/components/gfx/render_task.rs143
-rw-r--r--src/components/main/compositing/mod.rs5
-rw-r--r--src/components/main/engine.rs228
-rw-r--r--src/components/main/layout/layout_task.rs65
-rw-r--r--src/components/main/macros.rs11
-rw-r--r--src/components/main/pipeline.rs105
-rwxr-xr-xsrc/components/main/servo.rc1
-rw-r--r--src/components/msg/compositor.rs31
-rw-r--r--src/components/msg/engine.rs5
-rw-r--r--src/components/script/dom/bindings/element.rs11
-rw-r--r--src/components/script/dom/bindings/proxyhandler.rs4
-rw-r--r--src/components/script/dom/bindings/utils.rs6
-rw-r--r--src/components/script/dom/element.rs45
-rw-r--r--src/components/script/dom/event.rs2
-rw-r--r--src/components/script/dom/window.rs12
-rw-r--r--src/components/script/html/hubbub_html_parser.rs8
-rw-r--r--src/components/script/layout_interface.rs23
-rw-r--r--src/components/script/script_task.rs134
m---------src/support/alert/rust-alert0
19 files changed, 525 insertions, 314 deletions
diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs
index 62d2094c1e3..68a6b3874ec 100644
--- a/src/components/gfx/render_task.rs
+++ b/src/components/gfx/render_task.rs
@@ -8,7 +8,8 @@ use azure::{AzFloat, AzGLContext};
use azure::azure_hl::{B8G8R8A8, DrawTarget};
use display_list::DisplayList;
use servo_msg::compositor::{RenderListener, IdleRenderState, RenderingRenderState, LayerBuffer};
-use servo_msg::compositor::LayerBufferSet;
+use servo_msg::compositor::{CompositorToken, LayerBufferSet};
+use servo_msg::engine::{EngineChan, TokenSurrenderMsg};
use font_context::FontContext;
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
@@ -20,6 +21,7 @@ use render_context::RenderContext;
use std::cell::Cell;
use std::comm::{Chan, Port, SharedChan};
use std::uint;
+use std::util::replace;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
@@ -29,70 +31,32 @@ pub struct RenderLayer {
size: Size2D<uint>
}
-pub enum Msg<C> {
- AttachCompositorMsg(C),
+pub enum Msg {
RenderMsg(RenderLayer),
ReRenderMsg(f32),
+ TokenBestowMsg(~CompositorToken),
+ TokenProcureMsg,
ExitMsg(Chan<()>),
}
-pub struct RenderChan<C> {
- chan: SharedChan<Msg<C>>,
+#[deriving(Clone)]
+pub struct RenderChan {
+ chan: SharedChan<Msg>,
}
-impl<C: RenderListener + Owned> Clone for RenderChan<C> {
- pub fn clone(&self) -> RenderChan<C> {
- RenderChan {
- chan: self.chan.clone(),
- }
- }
-}
-
-impl<C: RenderListener + Owned> RenderChan<C> {
- pub fn new(chan: Chan<Msg<C>>) -> RenderChan<C> {
+impl RenderChan {
+ pub fn new(chan: Chan<Msg>) -> RenderChan {
RenderChan {
chan: SharedChan::new(chan),
}
}
- pub fn send(&self, msg: Msg<C>) {
+ pub fn send(&self, msg: Msg) {
self.chan.send(msg);
}
}
-pub fn create_render_task<C: RenderListener + Owned>(port: Port<Msg<C>>,
- compositor: C,
- opts: Opts,
- profiler_chan: ProfilerChan) {
- let compositor_cell = Cell::new(compositor);
- let opts_cell = Cell::new(opts);
- let port = Cell::new(port);
-
- do spawn {
- let compositor = compositor_cell.take();
- let share_gl_context = compositor.get_gl_context();
- let opts = opts_cell.with_ref(|o| copy *o);
- let profiler_chan = profiler_chan.clone();
- let profiler_chan_copy = profiler_chan.clone();
-
- // FIXME: rust/#5967
- let mut renderer = Renderer {
- port: port.take(),
- compositor: compositor,
- font_ctx: @mut FontContext::new(opts.render_backend,
- false,
- profiler_chan),
- opts: opts_cell.take(),
- profiler_chan: profiler_chan_copy,
- share_gl_context: share_gl_context,
- render_layer: None,
- };
-
- renderer.start();
- }
-}
-
-priv struct Renderer<C> {
- port: Port<Msg<C>>,
+priv struct RenderTask<C> {
+ port: Port<Msg>,
compositor: C,
font_ctx: @mut FontContext,
opts: Opts,
@@ -104,15 +68,58 @@ priv struct Renderer<C> {
/// The layer to be rendered
render_layer: Option<RenderLayer>,
+ /// A channel to the engine task for surrendering token
+ engine_chan: EngineChan,
+ /// A token that grants permission to send paint messages to compositor
+ compositor_token: Option<~CompositorToken>,
+ /// Cached copy of last layers rendered
+ next_paint_msg: Option<(LayerBufferSet, Size2D<uint>)>,
}
-impl<C: RenderListener + Owned> Renderer<C> {
+impl<C: RenderListener + Owned> RenderTask<C> {
+ pub fn create(port: Port<Msg>,
+ compositor: C,
+ opts: Opts,
+ engine_chan: EngineChan,
+ profiler_chan: ProfilerChan) {
+ let compositor_cell = Cell::new(compositor);
+ let opts_cell = Cell::new(opts);
+ let port = Cell::new(port);
+ let engine_chan = Cell::new(engine_chan);
+
+ do spawn {
+ let compositor = compositor_cell.take();
+ let share_gl_context = compositor.get_gl_context();
+ let opts = opts_cell.with_ref(|o| copy *o);
+ let profiler_chan = profiler_chan.clone();
+ let profiler_chan_clone = profiler_chan.clone();
+
+ // FIXME: rust/#5967
+ let mut render_task = RenderTask {
+ port: port.take(),
+ compositor: compositor,
+ font_ctx: @mut FontContext::new(opts.render_backend,
+ false,
+ profiler_chan),
+ opts: opts_cell.take(),
+ profiler_chan: profiler_chan_clone,
+ share_gl_context: share_gl_context,
+ render_layer: None,
+
+ engine_chan: engine_chan.take(),
+ compositor_token: None,
+ next_paint_msg: None,
+ };
+
+ render_task.start();
+ }
+ }
+
fn start(&mut self) {
- debug!("renderer: beginning rendering loop");
+ debug!("render_task: beginning rendering loop");
loop {
match self.port.recv() {
- AttachCompositorMsg(compositor) => self.compositor = compositor,
RenderMsg(render_layer) => {
self.render_layer = Some(render_layer);
self.render(1.0);
@@ -120,6 +127,21 @@ impl<C: RenderListener + Owned> Renderer<C> {
ReRenderMsg(scale) => {
self.render(scale);
}
+ TokenBestowMsg(token) => {
+ self.compositor_token = Some(token);
+ let next_paint_msg = replace(&mut self.next_paint_msg, None);
+ match next_paint_msg {
+ Some((layer_buffer_set, layer_size)) => {
+ println("retrieving cached paint msg");
+ self.compositor.paint(layer_buffer_set, layer_size);
+ self.compositor.set_render_state(IdleRenderState);
+ }
+ None => {}
+ }
+ }
+ TokenProcureMsg => {
+ self.engine_chan.send(TokenSurrenderMsg(self.compositor_token.swap_unwrap()));
+ }
ExitMsg(response_ch) => {
response_ch.send(());
break;
@@ -129,7 +151,7 @@ impl<C: RenderListener + Owned> Renderer<C> {
}
fn render(&mut self, scale: f32) {
- debug!("renderer: rendering");
+ debug!("render_task: rendering");
let render_layer;
match (self.render_layer) {
@@ -164,7 +186,8 @@ impl<C: RenderListener + Owned> Renderer<C> {
let buffer = LayerBuffer {
draw_target: DrawTarget::new_with_fbo(self.opts.render_backend,
self.share_gl_context,
- Size2D(width as i32, height as i32),
+ Size2D(width as i32,
+ height as i32),
B8G8R8A8),
rect: tile_rect,
screen_pos: screen_rect,
@@ -210,8 +233,14 @@ impl<C: RenderListener + Owned> Renderer<C> {
buffers: new_buffers,
};
- debug!("renderer: returning surface");
- self.compositor.paint(layer_buffer_set, render_layer.size);
+ debug!("render_task: returning surface");
+ if self.compositor_token.is_some() {
+ self.compositor.paint(layer_buffer_set, render_layer.size);
+ }
+ else {
+ println("caching paint msg");
+ self.next_paint_msg = Some((layer_buffer_set, render_layer.size));
+ }
self.compositor.set_render_state(IdleRenderState);
}
}
diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs
index 9e3a2a1067e..873c46a645a 100644
--- a/src/components/main/compositing/mod.rs
+++ b/src/components/main/compositing/mod.rs
@@ -89,7 +89,7 @@ pub enum Msg {
/// Sets the channel to the current layout task
SetLayoutChan(LayoutChan),
/// Sets the channel to the current renderer
- SetRenderChan(RenderChan<CompositorChan>),
+ SetRenderChan(RenderChan),
}
/// Azure surface wrapping to work with the layers infrastructure.
@@ -176,7 +176,7 @@ impl CompositorTask {
let local_zoom = @mut 1f32;
// Channel to the current renderer.
// FIXME: This probably shouldn't be stored like this.
- let render_chan: @mut Option<RenderChan<CompositorChan>> = @mut None;
+ let render_chan: @mut Option<RenderChan> = @mut None;
let update_layout_callbacks: @fn(LayoutChan) = |layout_chan: LayoutChan| {
let layout_chan_clone = layout_chan.clone();
@@ -432,3 +432,4 @@ fn on_osmain(f: ~fn()) {
f();
}
}
+
diff --git a/src/components/main/engine.rs b/src/components/main/engine.rs
index cdabbba1ae2..41e6fafe783 100644
--- a/src/components/main/engine.rs
+++ b/src/components/main/engine.rs
@@ -10,28 +10,69 @@ use std::comm;
use std::comm::Port;
use std::task;
use gfx::opts::Opts;
-use gfx::render_task::RenderChan;
-use gfx::render_task;
-use servo_msg::compositor::{ScriptListener, ReadyState};
-use servo_msg::engine::{EngineChan, ExitMsg, LoadUrlMsg, Msg};
-use script::layout_interface::LayoutChan;
-use script::layout_interface;
-use script::script_task::{ExecuteMsg, LoadMsg, ScriptMsg, ScriptContext, ScriptChan};
-use script::script_task;
+use gfx::render_task::{TokenBestowMsg, TokenProcureMsg};
+use pipeline::Pipeline;
+use servo_msg::compositor::{CompositorToken};
+use servo_msg::engine::{EngineChan, ExitMsg, LoadUrlMsg, Msg, RendererReadyMsg, TokenSurrenderMsg};
+use script::script_task::{ExecuteMsg, LoadMsg};
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
use servo_net::resource_task::ResourceTask;
use servo_net::resource_task;
-use servo_util::time::{ProfilerChan};
+use servo_util::time::ProfilerChan;
+use std::hashmap::HashMap;
pub struct Engine {
+ chan: EngineChan,
request_port: Port<Msg>,
compositor_chan: CompositorChan,
- render_chan: RenderChan<CompositorChan>,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
- layout_chan: LayoutChan,
- script_chan: ScriptChan,
+ pipelines: HashMap<uint, Pipeline>,
+ navigation_context: NavigationContext,
+ next_id: uint,
+ current_token_holder: Option<uint>,
+ loading: Option<uint>,
profiler_chan: ProfilerChan,
+ opts: Opts,
+}
+
+pub struct NavigationContext {
+ previous: ~[uint],
+ next: ~[uint],
+ current: Option<uint>,
+}
+
+impl NavigationContext {
+ pub fn new() -> NavigationContext {
+ NavigationContext {
+ previous: ~[],
+ next: ~[],
+ current: None,
+ }
+ }
+
+ pub fn back(&mut self) -> uint {
+ do self.current.mutate |id| {
+ self.next.push(id);
+ self.previous.pop()
+ }
+ self.current.get()
+ }
+
+ pub fn forward(&mut self) -> uint {
+ do self.current.mutate |id| {
+ self.previous.push(id);
+ self.next.pop()
+ }
+ self.current.get()
+ }
+
+ pub fn navigate(&mut self, id: uint) {
+ do self.current.mutate_default(id) |cur_id| {
+ self.previous.push(cur_id);
+ id
+ }
+ }
}
impl Engine {
@@ -41,105 +82,99 @@ impl Engine {
image_cache_task: ImageCacheTask,
profiler_chan: ProfilerChan)
-> EngineChan {
- macro_rules! closure_stream(
- ($Msg:ty, $Chan:ident) => (
- {
- let (port, chan) = comm::stream::<$Msg>();
- (Cell::new(port), $Chan::new(chan))
- }
- );
- )
- // Create the script port and channel.
- let (script_port, script_chan) = closure_stream!(ScriptMsg, ScriptChan);
-
- // Create the engine port and channel.
- let (engine_port, engine_chan) = closure_stream!(Msg, EngineChan);
-
- // Create the layout port and channel.
- let (layout_port, layout_chan) = closure_stream!(layout_interface::Msg, LayoutChan);
-
- let (render_port, render_chan) = comm::stream::<render_task::Msg<CompositorChan>>();
- let (render_port, render_chan) = (Cell::new(render_port), RenderChan::new(render_chan));
-
+ let opts = Cell::new(copy *opts);
- compositor_chan.send(SetLayoutChan(layout_chan.clone()));
- compositor_chan.send(SetRenderChan(render_chan.clone()));
+ let (engine_port, engine_chan) = comm::stream();
+ let (engine_port, engine_chan) = (Cell::new(engine_port), EngineChan::new(engine_chan));
let compositor_chan = Cell::new(compositor_chan);
-
- let opts = Cell::new(copy *opts);
-
+ let engine_chan_clone = Cell::new(engine_chan.clone());
{
- let engine_chan = engine_chan.clone();
do task::spawn {
- let compositor_chan = compositor_chan.take();
- render_task::create_render_task(render_port.take(),
- compositor_chan.clone(),
- opts.with_ref(|o| copy *o),
- profiler_chan.clone());
-
- let opts = opts.take();
-
- layout_task::create_layout_task(layout_port.take(),
- script_chan.clone(),
- render_chan.clone(),
- image_cache_task.clone(),
- opts,
- profiler_chan.clone());
-
- let compositor_chan_clone = compositor_chan.clone();
- ScriptContext::create_script_context(layout_chan.clone(),
- script_port.take(),
- script_chan.clone(),
- engine_chan.clone(),
- |msg: ReadyState| {
- compositor_chan_clone.set_ready_state(msg)
- },
- resource_task.clone(),
- image_cache_task.clone());
-
- Engine {
+ let mut engine = Engine {
+ chan: engine_chan_clone.take(),
request_port: engine_port.take(),
- compositor_chan: compositor_chan.clone(),
- render_chan: render_chan.clone(),
+ compositor_chan: compositor_chan.take(),
resource_task: resource_task.clone(),
image_cache_task: image_cache_task.clone(),
- layout_chan: layout_chan.clone(),
- script_chan: script_chan.clone(),
+ pipelines: HashMap::new(),
+ navigation_context: NavigationContext::new(),
+ next_id: 0,
+ current_token_holder: None,
+ loading: None,
profiler_chan: profiler_chan.clone(),
- }.run();
+ opts: opts.take(),
+ };
+ engine.run();
}
}
engine_chan
}
- fn run(&self) {
- while self.handle_request(self.request_port.recv()) {
- // Go on...
+ fn run(&mut self) {
+ loop {
+ let request = self.request_port.recv();
+ if !self.handle_request(request) {
+ break;
+ }
}
}
- fn handle_request(&self, request: Msg) -> bool {
+ fn get_next_id(&mut self) -> uint {
+ let id = self.next_id;
+ self.next_id = id + 1;
+ id
+ }
+
+ fn handle_request(&mut self, request: Msg) -> bool {
match request {
LoadUrlMsg(url) => {
+ let pipeline_id = self.get_next_id();
+ let pipeline = Pipeline::create(pipeline_id,
+ self.chan.clone(),
+ self.compositor_chan.clone(),
+ self.image_cache_task.clone(),
+ self.resource_task.clone(),
+ self.profiler_chan.clone(),
+ copy self.opts);
if url.path.ends_with(".js") {
- self.script_chan.send(ExecuteMsg(url))
+ pipeline.script_chan.send(ExecuteMsg(url));
} else {
- self.script_chan.send(LoadMsg(url))
+ pipeline.script_chan.send(LoadMsg(url));
+ self.loading = Some(pipeline_id);
}
- return true
+ self.pipelines.insert(pipeline_id, pipeline);
}
- ExitMsg(sender) => {
- self.script_chan.send(script_task::ExitMsg);
- self.layout_chan.send(layout_interface::ExitMsg);
-
- let (response_port, response_chan) = comm::stream();
+ RendererReadyMsg(pipeline_id) => {
+ let loading = self.loading.clone();
+ do loading.map() |&id| {
+ if pipeline_id == id {
+ match self.current_token_holder {
+ Some(ref id) => {
+ let current_holder = self.pipelines.find(id).get();
+ current_holder.render_chan.send(TokenProcureMsg);
+ }
+ None => self.bestow_compositor_token(id, ~CompositorToken::new())
+ }
+ }
+ };
+ }
- self.render_chan.send(render_task::ExitMsg(response_chan));
- response_port.recv();
+ TokenSurrenderMsg(token) => {
+ self.remove_active_pipeline();
+ let loading = self.loading.clone();
+ let token = Cell::new(token);
+ do loading.map |&id| {
+ self.bestow_compositor_token(id, token.take());
+ };
+ }
+ ExitMsg(sender) => {
+ for self.pipelines.each |_, pipeline| {
+ pipeline.exit();
+ }
self.image_cache_task.exit();
self.resource_task.send(resource_task::Exit);
@@ -147,6 +182,31 @@ impl Engine {
return false
}
}
+ true
+ }
+
+ fn remove_active_pipeline(&mut self) {
+// FIXME(tkuehn): currently, pipelines are not removed at all
+// do self.current_token_holder.map |id| {
+// self.pipelines.pop(id).unwrap().exit();
+// };
+
+ self.current_token_holder = None;
+ }
+
+ fn bestow_compositor_token(&mut self, id: uint, compositor_token: ~CompositorToken) {
+ let pipeline = self.pipelines.find(&id);
+ match pipeline {
+ None => fail!("Id of pipeline that made token request does not have a \
+ corresponding struct in Engine's pipelines. This is a bug. :-("),
+ Some(pipeline) => {
+ pipeline.render_chan.send(TokenBestowMsg(compositor_token));
+ self.compositor_chan.send(SetLayoutChan(pipeline.layout_chan.clone()));
+ self.current_token_holder = Some(id);
+ self.loading = None;
+ self.navigation_context.navigate(id);
+ }
+ }
}
}
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index 7f91d3dce29..29c3d800902 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -5,7 +5,6 @@
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
/// rendered.
-use compositing::CompositorChan;
use css::matching::MatchMethods;
use css::select::new_css_select_ctx;
use layout::aux::{LayoutData, LayoutAuxMethods};
@@ -34,7 +33,7 @@ use script::dom::node::{AbstractNode, LayoutView};
use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery};
use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse};
use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitMsg, LayoutQuery};
-use script::layout_interface::{LayoutResponse, MatchSelectorsDocumentDamage, Msg};
+use script::layout_interface::{MatchSelectorsDocumentDamage, Msg};
use script::layout_interface::{QueryMsg, RouteScriptMsg, Reflow, ReflowDocumentDamage};
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
use script::script_task::{ReflowCompleteMsg, ScriptChan, ScriptMsg, SendEventMsg};
@@ -45,28 +44,10 @@ use servo_util::time::{ProfilerChan, profile, time};
use servo_util::time;
use extra::net::url::Url;
-pub fn create_layout_task(port: Port<Msg>,
- script_chan: ScriptChan,
- render_chan: RenderChan<CompositorChan>,
- img_cache_task: ImageCacheTask,
- opts: Opts,
- profiler_chan: ProfilerChan) {
- let port = Cell::new(port);
- do spawn {
- let mut layout = Layout::new(port.take(),
- script_chan.clone(),
- render_chan.clone(),
- img_cache_task.clone(),
- &opts,
- profiler_chan.clone());
- layout.start();
- };
-}
-
-struct Layout {
+struct LayoutTask {
port: Port<Msg>,
script_chan: ScriptChan,
- render_chan: RenderChan<CompositorChan>,
+ render_chan: RenderChan,
image_cache_task: ImageCacheTask,
local_image_cache: @mut LocalImageCache,
font_ctx: @mut FontContext,
@@ -80,17 +61,35 @@ struct Layout {
profiler_chan: ProfilerChan,
}
-impl Layout {
+impl LayoutTask {
+ pub fn create(port: Port<Msg>,
+ script_chan: ScriptChan,
+ render_chan: RenderChan,
+ img_cache_task: ImageCacheTask,
+ opts: Opts,
+ profiler_chan: ProfilerChan) {
+ let port = Cell::new(port);
+ do spawn {
+ let mut layout = LayoutTask::new(port.take(),
+ script_chan.clone(),
+ render_chan.clone(),
+ img_cache_task.clone(),
+ &opts,
+ profiler_chan.clone());
+ layout.start();
+ };
+ }
+
fn new(port: Port<Msg>,
script_chan: ScriptChan,
- render_chan: RenderChan<CompositorChan>,
+ render_chan: RenderChan,
image_cache_task: ImageCacheTask,
opts: &Opts,
profiler_chan: ProfilerChan)
- -> Layout {
+ -> LayoutTask {
let fctx = @mut FontContext::new(opts.render_backend, true, profiler_chan.clone());
- Layout {
+ LayoutTask {
port: port,
script_chan: script_chan,
render_chan: render_chan,
@@ -135,10 +134,10 @@ impl Layout {
self.handle_reflow(data.take());
}
}
- QueryMsg(query, chan) => {
- let chan = Cell::new(chan);
+ QueryMsg(query) => {
+ let query = Cell::new(query);
do profile(time::LayoutQueryCategory, self.profiler_chan.clone()) {
- self.handle_query(query, chan.take());
+ self.handle_query(query.take());
}
}
RouteScriptMsg(script_msg) => {
@@ -268,9 +267,9 @@ impl Layout {
/// Handles a query from the script task. This is the main routine that DOM functions like
/// `getClientRects()` or `getBoundingClientRect()` ultimately invoke.
- fn handle_query(&self, query: LayoutQuery, reply_chan: Chan<Result<LayoutResponse,()>>) {
+ fn handle_query(&self, query: LayoutQuery) {
match query {
- ContentBoxQuery(node) => {
+ ContentBoxQuery(node, reply_chan) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
@@ -302,7 +301,7 @@ impl Layout {
reply_chan.send(response)
}
- ContentBoxesQuery(node) => {
+ ContentBoxesQuery(node, reply_chan) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
@@ -322,7 +321,7 @@ impl Layout {
reply_chan.send(response)
}
- HitTestQuery(node, point) => {
+ HitTestQuery(node, point, reply_chan) => {
// FIXME: Isolate this transmutation into a single "bridge" module.
let node: AbstractNode<LayoutView> = unsafe {
transmute(node)
diff --git a/src/components/main/macros.rs b/src/components/main/macros.rs
index 8fe65bccfb6..169e0a0a201 100644
--- a/src/components/main/macros.rs
+++ b/src/components/main/macros.rs
@@ -1,7 +1,7 @@
/* 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/. */
-
+#[macro_escape];
{
macro_rules! move_ref(
{ $x:expr } => { unsafe { let y <- *ptr::to_unsafe_ptr(*$x); y } }
@@ -68,4 +68,13 @@
])+)
}
)
+
+ macro_rules! closure_stream(
+ ($Msg:ty, $Chan:ident) => (
+ {
+ let (port, chan) = comm::stream::<$Msg>();
+ (Cell(port), $Chan::new(chan))
+ }
+ );
+ )
}
diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs
new file mode 100644
index 00000000000..95a247cca3b
--- /dev/null
+++ b/src/components/main/pipeline.rs
@@ -0,0 +1,105 @@
+/* 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 compositing::CompositorChan;
+use gfx::render_task::{RenderChan, RenderTask};
+use gfx::render_task;
+use gfx::opts::Opts;
+use layout::layout_task::LayoutTask;
+use script::layout_interface::LayoutChan;
+use script::layout_interface;
+use servo_msg::engine::{EngineChan};
+use script::script_task::{ScriptTask, ScriptChan, ScriptMsg};
+use script::script_task;
+use servo_net::image_cache_task::ImageCacheTask;
+use servo_net::resource_task::ResourceTask;
+use servo_util::time::ProfilerChan;
+use std::comm;
+
+/// A uniquely-identifiable pipeline of stript task, layout task, and render task.
+pub struct Pipeline {
+ id: uint,
+ script_chan: ScriptChan,
+ layout_chan: LayoutChan,
+ render_chan: RenderChan,
+}
+
+impl Pipeline {
+ /// Starts a render task, layout task, and script task. Returns the channels wrapped in a struct.
+ pub fn create(id: uint,
+ engine_chan: EngineChan,
+ compositor_chan: CompositorChan,
+ image_cache_task: ImageCacheTask,
+ resource_task: ResourceTask,
+ profiler_chan: ProfilerChan,
+ opts: Opts) -> Pipeline {
+
+ macro_rules! closure_stream(
+ ($Msg:ty, $Chan:ident) => (
+ {
+ let (port, chan) = comm::stream::<$Msg>();
+ (port, $Chan::new(chan))
+ }
+ );
+ )
+ // Create the script port and channel.
+ let (script_port, script_chan) = closure_stream!(ScriptMsg, ScriptChan);
+
+ // Create the layout port and channel.
+ let (layout_port, layout_chan) = closure_stream!(layout_interface::Msg, LayoutChan);
+
+ let (render_port, render_chan) = comm::stream::<render_task::Msg>();
+ let render_chan = RenderChan::new(render_chan);
+
+ RenderTask::create(render_port,
+ compositor_chan.clone(),
+ copy opts,
+ engine_chan.clone(),
+ profiler_chan.clone());
+
+ LayoutTask::create(layout_port,
+ script_chan.clone(),
+ render_chan.clone(),
+ image_cache_task.clone(),
+ copy opts,
+ profiler_chan.clone());
+
+ ScriptTask::create(id,
+ compositor_chan.clone(),
+ layout_chan.clone(),
+ script_port,
+ script_chan.clone(),
+ engine_chan,
+ resource_task.clone(),
+ image_cache_task.clone());
+
+ Pipeline::new(id,
+ script_chan,
+ layout_chan,
+ render_chan)
+ }
+
+ pub fn new(id: uint,
+ script_chan: ScriptChan,
+ layout_chan: LayoutChan,
+ render_chan: RenderChan)
+ -> Pipeline {
+ Pipeline {
+ id: id,
+ script_chan: script_chan,
+ layout_chan: layout_chan,
+ render_chan: render_chan,
+ }
+ }
+
+ pub fn exit(&self) {
+ self.script_chan.send(script_task::ExitMsg);
+ self.layout_chan.send(layout_interface::ExitMsg);
+
+ let (response_port, response_chan) = comm::stream();
+ self.render_chan.send(render_task::ExitMsg(response_chan));
+ response_port.recv();
+ }
+}
+
diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc
index d2b3ae08c41..73ac4fa0a1d 100755
--- a/src/components/main/servo.rc
+++ b/src/components/main/servo.rc
@@ -63,6 +63,7 @@ pub mod css {
}
pub mod engine;
+pub mod pipeline;
pub mod layout {
pub mod block;
diff --git a/src/components/msg/compositor.rs b/src/components/msg/compositor.rs
index 6b6311fd1ba..6d8fe2ecc50 100644
--- a/src/components/msg/compositor.rs
+++ b/src/components/msg/compositor.rs
@@ -6,6 +6,7 @@ use azure::azure_hl::DrawTarget;
use azure::azure::AzGLContext;
use geom::rect::Rect;
use geom::size::Size2D;
+use std::util::NonCopyable;
pub struct LayerBuffer {
draw_target: DrawTarget,
@@ -33,14 +34,6 @@ pub enum RenderState {
RenderingRenderState,
}
-/// The interface used by the renderer to acquire draw targets for each rendered frame and
-/// submit them to be drawn to the display.
-pub trait RenderListener {
- fn get_gl_context(&self) -> AzGLContext;
- fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>);
- fn set_render_state(&self, render_state: RenderState);
-}
-
pub enum ReadyState {
/// Informs the compositor that a page is loading. Used for setting status
Loading,
@@ -50,8 +43,30 @@ pub enum ReadyState {
FinishedLoading,
}
+/// The interface used by the renderer to acquire draw targets for each render frame and
+/// submit them to be drawn to the display.
+pub trait RenderListener {
+ fn get_gl_context(&self) -> AzGLContext;
+ fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>);
+ fn set_render_state(&self, render_state: RenderState);
+}
+
/// The interface used by the script task to tell the compositor to update its ready state,
/// which is used in displaying the appropriate message in the window's title.
pub trait ScriptListener : Clone {
fn set_ready_state(&self, ReadyState);
}
+
+/// Signifies control of the compositor. Only the render task controlling
+/// the compositor token may send paint messages to the compositor
+pub struct CompositorToken {
+ construction_restrictor: NonCopyable,
+}
+
+impl CompositorToken {
+ pub fn new() -> CompositorToken {
+ CompositorToken {
+ construction_restrictor: NonCopyable::new(),
+ }
+ }
+}
diff --git a/src/components/msg/engine.rs b/src/components/msg/engine.rs
index 83e0f085ee0..b03893d14ca 100644
--- a/src/components/msg/engine.rs
+++ b/src/components/msg/engine.rs
@@ -7,6 +7,9 @@
use std::comm::{Chan, SharedChan};
use extra::net::url::Url;
+use compositor::CompositorToken;
+
+pub use compositor;
#[deriving(Clone)]
pub struct EngineChan {
@@ -27,5 +30,7 @@ impl EngineChan {
pub enum Msg {
LoadUrlMsg(Url),
ExitMsg(Chan<()>),
+ RendererReadyMsg(uint),
+ TokenSurrenderMsg(~CompositorToken),
}
diff --git a/src/components/script/dom/bindings/element.rs b/src/components/script/dom/bindings/element.rs
index 9a34f7c5dc6..b79daf75db7 100644
--- a/src/components/script/dom/bindings/element.rs
+++ b/src/components/script/dom/bindings/element.rs
@@ -16,6 +16,7 @@ use std::cast;
use std::i32;
use std::libc;
use std::libc::c_uint;
+use std::comm;
use std::ptr;
use std::ptr::null;
use std::result;
@@ -229,13 +230,9 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
let width = match node.type_id() {
ElementNodeTypeId(HTMLImageElementTypeId) => {
let script_context = task_from_context(cx);
- match (*script_context).query_layout(ContentBoxQuery(node)) {
- Ok(rect) => {
- match rect {
- ContentBoxResponse(rect) => rect.size.width.to_px(),
- _ => fail!(~"unexpected layout reply")
- }
- }
+ let (port, chan) = comm::stream();
+ match (*script_context).query_layout(ContentBoxQuery(node, chan), port) {
+ Ok(ContentBoxResponse(rect)) => rect.size.width.to_px(),
Err(()) => 0
}
// TODO: if nothing is being rendered(?), return zero dimensions
diff --git a/src/components/script/dom/bindings/proxyhandler.rs b/src/components/script/dom/bindings/proxyhandler.rs
index 2780a969eb2..cbbc4f1525d 100644
--- a/src/components/script/dom/bindings/proxyhandler.rs
+++ b/src/components/script/dom/bindings/proxyhandler.rs
@@ -71,7 +71,7 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
return ptr::null();
}
- let result = ~"[object " + name + ~"]";
+ let result = ~"[object " + name + "]";
for result.iter().enumerate().advance |(i, c)| {
*chars.offset(i) = c as jschar;
}
@@ -86,4 +86,4 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
pub fn GetExpandoObject(_proxy: *JSObject) -> *JSObject {
ptr::null()
-} \ No newline at end of file
+}
diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs
index 9d3105fefca..5a42e109268 100644
--- a/src/components/script/dom/bindings/utils.rs
+++ b/src/components/script/dom/bindings/utils.rs
@@ -21,12 +21,12 @@ use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction};
use js::jsapi::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_EncodeString, JS_free, JS_GetStringCharsAndLength};
-use js::jsapi::{JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype};
+use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype};
use js::jsapi::{JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject};
use js::jsapi::{JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject};
use js::jsapi::{JS_NewStringCopyN, JS_DefineFunctions, JS_DefineProperty};
use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot};
-use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSNative};
+use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative};
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
use js::rust::Compartment;
@@ -83,7 +83,7 @@ extern fn InterfaceObjectToString(cx: *JSContext, _argc: uint, vp: *mut JSVal) -
}
let name = jsval_to_str(cx, *v).get();
- let retval = str(~"function " + name + ~"() {\n [native code]\n}");
+ let retval = str(~"function " + name + "() {\n [native code]\n}");
*vp = domstring_to_jsval(cx, &retval);
return 1;
}
diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs
index e707a95ebb9..2595a68657d 100644
--- a/src/components/script/dom/element.rs
+++ b/src/components/script/dom/element.rs
@@ -12,6 +12,7 @@ use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
use layout_interface::{ContentBoxesResponse};
use std::cell::Cell;
+use std::comm;
use std::uint;
use std::str::eq_slice;
use extra::net::url::Url;
@@ -165,20 +166,19 @@ impl<'self> Element {
Some(win) => {
let node = self.parent.abstract.get();
assert!(node.is_element());
- let script_context = unsafe {
- &mut *win.script_context
+ let script_task = unsafe {
+ &mut *win.script_task
};
- match script_context.query_layout(ContentBoxesQuery(node)) {
- Ok(rects) => match rects {
- ContentBoxesResponse(rects) =>
- do rects.map |r| {
- ClientRect::new(
- r.origin.y.to_f32(),
- (r.origin.y + r.size.height).to_f32(),
- r.origin.x.to_f32(),
- (r.origin.x + r.size.width).to_f32())
- },
- _ => fail!(~"unexpected layout reply")
+ let (port, chan) = comm::stream();
+ match script_task.query_layout(ContentBoxesQuery(node, chan), port) {
+ Ok(ContentBoxesResponse(rects)) => {
+ do rects.map |r| {
+ ClientRect::new(
+ r.origin.y.to_f32(),
+ (r.origin.y + r.size.height).to_f32(),
+ r.origin.x.to_f32(),
+ (r.origin.x + r.size.width).to_f32())
+ }
},
Err(()) => {
debug!("layout query error");
@@ -207,16 +207,15 @@ impl<'self> Element {
Some(win) => {
let node = self.parent.abstract.get();
assert!(node.is_element());
- let script_context = unsafe { &mut *win.script_context };
- match script_context.query_layout(ContentBoxQuery(node)) {
- Ok(rect) => match rect {
- ContentBoxResponse(rect) =>
- Some(ClientRect::new(
- rect.origin.y.to_f32(),
- (rect.origin.y + rect.size.height).to_f32(),
- rect.origin.x.to_f32(),
- (rect.origin.x + rect.size.width).to_f32())),
- _ => fail!(~"unexpected layout result")
+ let script_task = unsafe { &mut *win.script_task };
+ let (port, chan) = comm::stream();
+ match script_task.query_layout(ContentBoxQuery(node, chan), port) {
+ Ok(ContentBoxResponse(rect)) => {
+ Some(ClientRect::new(
+ rect.origin.y.to_f32(),
+ (rect.origin.y + rect.size.height).to_f32(),
+ rect.origin.x.to_f32(),
+ (rect.origin.x + rect.size.width).to_f32()))
},
Err(()) => {
debug!("error querying layout");
diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs
index 047b734e6b4..6b4be15b701 100644
--- a/src/components/script/dom/event.rs
+++ b/src/components/script/dom/event.rs
@@ -9,8 +9,6 @@ use dom::bindings::utils::{DOMString, ErrorResult, WrapperCache};
use geom::point::Point2D;
-use std::comm;
-
pub enum Event {
ResizeEvent(uint, uint),
ReflowEvent,
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs
index 5fb07c66f07..41f99eaa9e9 100644
--- a/src/components/script/dom/window.rs
+++ b/src/components/script/dom/window.rs
@@ -6,7 +6,7 @@ use dom::bindings::utils::WrapperCache;
use dom::bindings::window;
use layout_interface::ReflowForScriptQuery;
-use script_task::{ExitMsg, FireTimerMsg, ScriptChan, ScriptContext};
+use script_task::{ExitMsg, FireTimerMsg, ScriptChan, ScriptTask};
use std::comm;
use std::comm::Chan;
@@ -29,7 +29,7 @@ pub enum TimerControlMsg {
pub struct Window {
timer_chan: Chan<TimerControlMsg>,
script_chan: ScriptChan,
- script_context: *mut ScriptContext,
+ script_task: *mut ScriptTask,
wrapper: WrapperCache
}
@@ -89,11 +89,11 @@ impl Window {
pub fn content_changed(&self) {
unsafe {
- (*self.script_context).reflow_all(ReflowForScriptQuery)
+ (*self.script_task).reflow_all(ReflowForScriptQuery)
}
}
- pub fn new(script_chan: ScriptChan, script_context: *mut ScriptContext)
+ pub fn new(script_chan: ScriptChan, script_task: *mut ScriptTask)
-> @mut Window {
let script_chan_clone = script_chan.clone();
let win = @mut Window {
@@ -112,11 +112,11 @@ impl Window {
}
timer_chan
},
- script_context: script_context,
+ script_task: script_task,
};
unsafe {
- let compartment = (*script_context).js_compartment;
+ let compartment = (*script_task).js_compartment;
window::create(compartment, win);
}
win
diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs
index 6309e488d7e..9540fcc87d4 100644
--- a/src/components/script/html/hubbub_html_parser.rs
+++ b/src/components/script/html/hubbub_html_parser.rs
@@ -303,9 +303,9 @@ pub fn parse_html(url: Url,
// Handle CSS style sheets from <link> elements
ElementNodeTypeId(HTMLLinkElementTypeId) => {
do node.with_imm_element |element| {
- match (element.get_attr(~"rel"), element.get_attr(~"href")) {
+ match (element.get_attr("rel"), element.get_attr("href")) {
(Some(rel), Some(href)) => {
- if rel == ~"stylesheet" {
+ if rel == "stylesheet" {
debug!("found CSS stylesheet: %s", href);
let url = make_url(href.to_str(), Some(url2.clone()));
css_chan2.send(CSSTaskNewFile(UrlProvenance(url)));
@@ -317,7 +317,7 @@ pub fn parse_html(url: Url,
},
ElementNodeTypeId(HTMLImageElementTypeId) => {
do node.with_mut_image_element |image_element| {
- let src_opt = image_element.parent.get_attr(~"src").map(|x| x.to_str());
+ let src_opt = image_element.parent.get_attr("src").map(|x| x.to_str());
match src_opt {
None => {}
Some(src) => {
@@ -401,7 +401,7 @@ pub fn parse_html(url: Url,
unsafe {
let script: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(script);
do script.with_imm_element |script| {
- match script.get_attr(~"src") {
+ match script.get_attr("src") {
Some(src) => {
debug!("found script: %s", src);
let new_url = make_url(src.to_str(), Some(url.clone()));
diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs
index 3a1531b83e6..766c728067b 100644
--- a/src/components/script/layout_interface.rs
+++ b/src/components/script/layout_interface.rs
@@ -30,7 +30,7 @@ pub enum Msg {
/// Performs a synchronous layout request.
///
/// FIXME(pcwalton): As noted below, this isn't very type safe.
- QueryMsg(LayoutQuery, Chan<Result<LayoutResponse,()>>),
+ QueryMsg(LayoutQuery),
/// Routes a message (usually from the compositor) to the appropriate script task
RouteScriptMsg(ScriptMsg),
@@ -42,25 +42,16 @@ pub enum Msg {
/// Synchronous messages that script can send to layout.
pub enum LayoutQuery {
/// Requests the dimensions of the content box, as in the `getBoundingClientRect()` call.
- ContentBoxQuery(AbstractNode<ScriptView>),
+ ContentBoxQuery(AbstractNode<ScriptView>, Chan<Result<ContentBoxResponse, ()>>),
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
- ContentBoxesQuery(AbstractNode<ScriptView>),
+ ContentBoxesQuery(AbstractNode<ScriptView>, Chan<Result<ContentBoxesResponse, ()>>),
/// Requests the node containing the point of interest
- HitTestQuery(AbstractNode<ScriptView>, Point2D<f32>),
+ HitTestQuery(AbstractNode<ScriptView>, Point2D<f32>, Chan<Result<HitTestResponse, ()>>),
}
-/// The reply of a synchronous message from script to layout.
-///
-/// FIXME(pcwalton): This isn't very type safe. Maybe `LayoutQuery` objects should include
-/// response channels?
-pub enum LayoutResponse {
- /// A response to the `ContentBoxQuery` message.
- ContentBoxResponse(Rect<Au>),
- /// A response to the `ContentBoxesQuery` message.
- ContentBoxesResponse(~[Rect<Au>]),
- /// A response to the `HitTestQuery` message.
- HitTestResponse(AbstractNode<LayoutView>),
-}
+pub struct ContentBoxResponse(Rect<Au>);
+pub struct ContentBoxesResponse(~[Rect<Au>]);
+pub struct HitTestResponse(AbstractNode<LayoutView>);
/// Determines which part of the
pub enum DocumentDamageLevel {
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index 7ef0b0035e1..ce89ef5efd7 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -5,19 +5,21 @@
/// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing
/// and layout tasks.
-use servo_msg::compositor::{ReadyState, Loading, PerformingLayout, FinishedLoading};
+use servo_msg::compositor::{ScriptListener, Loading, PerformingLayout};
+use servo_msg::compositor::FinishedLoading;
use dom::bindings::utils::GlobalStaticData;
use dom::document::Document;
use dom::element::Element;
use dom::event::{Event, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseUpEvent};
use dom::node::{AbstractNode, ScriptView, define_bindings};
use dom::window::Window;
-use layout_interface::{AddStylesheetMsg, DocumentDamage, DocumentDamageLevel, HitTestQuery};
-use layout_interface::{HitTestResponse, LayoutQuery, LayoutResponse, LayoutChan};
-use layout_interface::{MatchSelectorsDocumentDamage, QueryMsg, Reflow, ReflowDocumentDamage};
-use layout_interface::{ReflowForDisplay, ReflowForScriptQuery, ReflowGoal, ReflowMsg};
+use layout_interface::{AddStylesheetMsg, DocumentDamage};
+use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery};
+use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg, Reflow};
+use layout_interface::{ReflowDocumentDamage, ReflowForDisplay, ReflowForScriptQuery, ReflowGoal};
+use layout_interface::ReflowMsg;
use layout_interface;
-use servo_msg::engine::{EngineChan, LoadUrlMsg};
+use servo_msg::engine::{EngineChan, LoadUrlMsg, RendererReadyMsg};
use std::cast::transmute;
use std::cell::Cell;
@@ -91,7 +93,9 @@ pub struct Frame {
/// frames.
///
/// FIXME: Rename to `Page`, following WebKit?
-pub struct ScriptContext {
+pub struct ScriptTask {
+ /// A unique identifier to the script's pipeline
+ id: uint,
/// A handle to the layout task.
layout_chan: LayoutChan,
/// A handle to the image cache task.
@@ -110,8 +114,8 @@ pub struct ScriptContext {
/// For communicating load url messages to the engine
engine_chan: EngineChan,
- /// For communicating loading messages to the compositor
- compositor_task: ~fn(ReadyState),
+ /// For permission to communicate ready state messages to the compositor
+ compositor: @ScriptListener,
/// The JavaScript runtime.
js_runtime: js::rust::rt,
@@ -134,26 +138,26 @@ pub struct ScriptContext {
damage: Option<DocumentDamage>,
}
-fn global_script_context_key(_: @ScriptContext) {}
+fn global_script_context_key(_: @ScriptTask) {}
/// Returns this task's script context singleton.
-pub fn global_script_context() -> @ScriptContext {
+pub fn global_script_context() -> @ScriptTask {
unsafe {
local_data::local_data_get(global_script_context_key).get()
}
}
-/// Returns the script context from the JS Context.
+/// Returns the script task from the JS Context.
///
/// FIXME: Rename to `script_context_from_js_context`.
-pub fn task_from_context(js_context: *JSContext) -> *mut ScriptContext {
+pub fn task_from_context(js_context: *JSContext) -> *mut ScriptTask {
unsafe {
- JS_GetContextPrivate(js_context) as *mut ScriptContext
+ JS_GetContextPrivate(js_context) as *mut ScriptTask
}
}
#[unsafe_destructor]
-impl Drop for ScriptContext {
+impl Drop for ScriptTask {
fn finalize(&self) {
unsafe {
let _ = local_data::local_data_pop(global_script_context_key);
@@ -161,16 +165,17 @@ impl Drop for ScriptContext {
}
}
-impl ScriptContext {
- /// Creates a new script context.
- pub fn new(layout_chan: LayoutChan,
+impl ScriptTask {
+ /// Creates a new script task.
+ pub fn new(id: uint,
+ compositor: @ScriptListener,
+ layout_chan: LayoutChan,
script_port: Port<ScriptMsg>,
script_chan: ScriptChan,
engine_chan: EngineChan,
- compositor_task: ~fn(ReadyState),
resource_task: ResourceTask,
img_cache_task: ImageCacheTask)
- -> @mut ScriptContext {
+ -> @mut ScriptTask {
let js_runtime = js::rust::rt();
let js_context = js_runtime.cx();
@@ -182,7 +187,10 @@ impl ScriptContext {
Err(()) => fail!("Failed to create a compartment"),
};
- let script_context = @mut ScriptContext {
+ let script_task = @mut ScriptTask {
+ id: id,
+ compositor: compositor,
+
layout_chan: layout_chan,
image_cache_task: img_cache_task,
resource_task: resource_task,
@@ -192,7 +200,6 @@ impl ScriptContext {
script_chan: script_chan,
engine_chan: engine_chan,
- compositor_task: compositor_task,
js_runtime: js_runtime,
js_context: js_context,
@@ -207,17 +214,17 @@ impl ScriptContext {
damage: None,
};
// Indirection for Rust Issue #6248, dynamic freeze scope artifically extended
- let script_context_ptr = {
- let borrowed_ctx= &mut *script_context;
- borrowed_ctx as *mut ScriptContext
+ let script_task_ptr = {
+ let borrowed_ctx= &mut *script_task;
+ borrowed_ctx as *mut ScriptTask
};
unsafe {
- js_context.set_cx_private(script_context_ptr as *());
- local_data::local_data_set(global_script_context_key, transmute(script_context))
+ js_context.set_cx_private(script_task_ptr as *());
+ local_data::local_data_set(global_script_context_key, transmute(script_task))
}
- script_context
+ script_task
}
/// Starts the script task. After calling this method, the script task will loop receiving
@@ -228,27 +235,29 @@ impl ScriptContext {
}
}
- pub fn create_script_context(layout_chan: LayoutChan,
- script_port: Port<ScriptMsg>,
- script_chan: ScriptChan,
- engine_chan: EngineChan,
- compositor_task: ~fn(ReadyState),
- resource_task: ResourceTask,
- image_cache_task: ImageCacheTask) {
+ pub fn create<C: ScriptListener + Owned>(id: uint,
+ compositor: C,
+ layout_chan: LayoutChan,
+ script_port: Port<ScriptMsg>,
+ script_chan: ScriptChan,
+ engine_chan: EngineChan,
+ resource_task: ResourceTask,
+ image_cache_task: ImageCacheTask) {
+ let compositor = Cell::new(compositor);
let script_port = Cell::new(script_port);
- let compositor_task = Cell::new(compositor_task);
// FIXME: rust#6399
let mut the_task = task();
the_task.sched_mode(SingleThreaded);
- do the_task.spawn {
- let script_context = ScriptContext::new(layout_chan.clone(),
- script_port.take(),
- script_chan.clone(),
- engine_chan.clone(),
- compositor_task.take(),
- resource_task.clone(),
- image_cache_task.clone());
- script_context.start();
+ do spawn {
+ let script_task = ScriptTask::new(id,
+ @compositor.take() as @ScriptListener,
+ layout_chan.clone(),
+ script_port.take(),
+ script_chan.clone(),
+ engine_chan.clone(),
+ resource_task.clone(),
+ image_cache_task.clone());
+ script_task.start();
}
}
@@ -324,7 +333,8 @@ impl ScriptContext {
/// Handles a notification that reflow completed.
fn handle_reflow_complete_msg(&mut self) {
self.layout_join_port = None;
- self.set_ready_state(FinishedLoading)
+ self.engine_chan.send(RendererReadyMsg(self.id));
+ self.compositor.set_ready_state(FinishedLoading);
}
/// Handles a request to exit the script task and shut down layout.
@@ -337,12 +347,6 @@ impl ScriptContext {
self.layout_chan.send(layout_interface::ExitMsg)
}
- // tells the compositor when loading starts and finishes
- // FIXME ~compositor_interface doesn't work right now, which is why this is necessary
- fn set_ready_state(&self, msg: ReadyState) {
- (self.compositor_task)(msg);
- }
-
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
fn load(&mut self, url: Url) {
@@ -354,7 +358,7 @@ impl ScriptContext {
self.bindings_initialized = true
}
- self.set_ready_state(Loading);
+ self.compositor.set_ready_state(Loading);
// Parse HTML.
//
// Note: We can parse the next document in parallel with any previous documents.
@@ -446,7 +450,7 @@ impl ScriptContext {
self.join_layout();
// Tell the user that we're performing layout.
- self.set_ready_state(PerformingLayout);
+ self.compositor.set_ready_state(PerformingLayout);
// Layout will let us know when it's done.
let (join_port, join_chan) = comm::stream();
@@ -478,7 +482,7 @@ impl ScriptContext {
/// FIXME: This should basically never be used.
pub fn reflow_all(&mut self, goal: ReflowGoal) {
for self.root_frame.iter().advance |root_frame| {
- ScriptContext::damage(&mut self.damage,
+ ScriptTask::damage(&mut self.damage,
root_frame.document.root,
MatchSelectorsDocumentDamage)
}
@@ -487,12 +491,10 @@ impl ScriptContext {
}
/// Sends the given query to layout.
- pub fn query_layout(&mut self, query: LayoutQuery) -> Result<LayoutResponse,()> {
- self.join_layout();
-
- let (response_port, response_chan) = comm::stream();
- self.layout_chan.send(QueryMsg(query, response_chan));
- response_port.recv()
+ pub fn query_layout<T: Owned>(&mut self, query: LayoutQuery, response_port: Port<Result<T, ()>>) -> Result<T,()> {
+ self.join_layout();
+ self.layout_chan.send(QueryMsg(query));
+ response_port.recv()
}
/// Adds the given damage.
@@ -526,7 +528,7 @@ impl ScriptContext {
self.window_size = Size2D(new_width, new_height);
for self.root_frame.iter().advance |root_frame| {
- ScriptContext::damage(&mut self.damage,
+ ScriptTask::damage(&mut self.damage,
root_frame.document.root,
ReflowDocumentDamage);
}
@@ -541,7 +543,7 @@ impl ScriptContext {
debug!("script got reflow event");
for self.root_frame.iter().advance |root_frame| {
- ScriptContext::damage(&mut self.damage,
+ ScriptTask::damage(&mut self.damage,
root_frame.document.root,
MatchSelectorsDocumentDamage);
}
@@ -557,7 +559,8 @@ impl ScriptContext {
Some(ref frame) => frame.document.root,
None => fail!("root frame is None")
};
- match self.query_layout(HitTestQuery(root, point)) {
+ let (port, chan) = comm::stream();
+ match self.query_layout(HitTestQuery(root, point, chan), port) {
Ok(node) => match node {
HitTestResponse(node) => {
debug!("clicked on %?", node.debug_str());
@@ -580,7 +583,6 @@ impl ScriptContext {
}
}
}
- _ => fail!(~"unexpected layout reply")
},
Err(()) => {
debug!(fmt!("layout query error"));
@@ -594,7 +596,7 @@ impl ScriptContext {
priv fn load_url_from_element(&self, element: &Element) {
// if the node's element is "a," load url from href attr
- for element.attrs.each |attr| {
+ for element.attrs.iter().advance |attr| {
if attr.name == ~"href" {
debug!("clicked on link to %?", attr.value);
let current_url = match self.root_frame {
diff --git a/src/support/alert/rust-alert b/src/support/alert/rust-alert
-Subproject 68875af396cb583e670dd5caad99431dac62f8d
+Subproject 502ec156da38860a4dff911cf8f33f388a0a188