compositing: Move messages that go over the ScriptListener to go over

an IPC channel instead.

Because this used a boxed trait object to invoke messages across a
process boundary, and boxed trait objects are not supported across IPC,
we spawn a helper thread inside the compositor to perform the marshaling
for us.
This commit is contained in:
Patrick Walton 2015-07-10 18:08:03 -07:00
parent 2947d78e4e
commit e841065351
14 changed files with 211 additions and 82 deletions

View file

@ -52,6 +52,9 @@ git = "https://github.com/servo/rust-png"
[dependencies.clipboard] [dependencies.clipboard]
git = "https://github.com/aweinstock314/rust-clipboard" git = "https://github.com/aweinstock314/rust-clipboard"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies] [dependencies]
log = "*" log = "*"
num = "0.1.24" num = "0.1.24"

View file

@ -13,10 +13,11 @@ use windowing::{WindowEvent, WindowMethods};
use euclid::point::Point2D; use euclid::point::Point2D;
use euclid::rect::Rect; use euclid::rect::Rect;
use ipc_channel::ipc::IpcReceiver;
use layers::platform::surface::NativeDisplay; use layers::platform::surface::NativeDisplay;
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
use msg::compositor_msg::{Epoch, LayerId, LayerProperties, FrameTreeId}; use msg::compositor_msg::{Epoch, LayerId, LayerProperties, FrameTreeId};
use msg::compositor_msg::{PaintListener, ScriptListener}; use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg};
use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId}; use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId};
use msg::constellation_msg::{Key, KeyState, KeyModifiers}; use msg::constellation_msg::{Key, KeyState, KeyModifiers};
use profile_traits::mem; use profile_traits::mem;
@ -61,31 +62,28 @@ impl CompositorReceiver for Receiver<Msg> {
} }
} }
/// Implementation of the abstract `ScriptListener` interface. pub fn run_script_listener_thread(mut compositor_proxy: Box<CompositorProxy + 'static + Send>,
impl ScriptListener for Box<CompositorProxy+'static+Send> { receiver: IpcReceiver<ScriptToCompositorMsg>) {
fn scroll_fragment_point(&mut self, while let Ok(msg) = receiver.recv() {
pipeline_id: PipelineId, match msg {
layer_id: LayerId, ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point) => {
point: Point2D<f32>) { compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point));
self.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point)); }
}
fn close(&mut self) { ScriptToCompositorMsg::Exit => {
let (chan, port) = channel(); let (chan, port) = channel();
self.send(Msg::Exit(chan)); compositor_proxy.send(Msg::Exit(chan));
port.recv().unwrap(); port.recv().unwrap();
} }
fn dup(&mut self) -> Box<ScriptListener+'static> { ScriptToCompositorMsg::SetTitle(pipeline_id, title) => {
box self.clone_compositor_proxy() as Box<ScriptListener+'static> compositor_proxy.send(Msg::ChangePageTitle(pipeline_id, title))
} }
fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) { ScriptToCompositorMsg::SendKeyEvent(key, key_state, key_modifiers) => {
self.send(Msg::ChangePageTitle(pipeline_id, title)) compositor_proxy.send(Msg::KeyEvent(key, key_state, key_modifiers))
} }
}
fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers) {
self.send(Msg::KeyEvent(key, state, modifiers));
} }
} }

View file

@ -14,6 +14,7 @@ extern crate azure;
extern crate devtools_traits; extern crate devtools_traits;
extern crate euclid; extern crate euclid;
extern crate gfx; extern crate gfx;
extern crate ipc_channel;
extern crate layers; extern crate layers;
extern crate layout_traits; extern crate layout_traits;
extern crate png; extern crate png;

View file

@ -7,13 +7,16 @@ use layout_traits::{LayoutControlMsg, LayoutTaskFactory, LayoutControlChan};
use script_traits::{ScriptControlChan, ScriptTaskFactory}; use script_traits::{ScriptControlChan, ScriptTaskFactory};
use script_traits::{NewLayoutInfo, ConstellationControlMsg}; use script_traits::{NewLayoutInfo, ConstellationControlMsg};
use compositor_task;
use devtools_traits::DevtoolsControlChan; use devtools_traits::DevtoolsControlChan;
use euclid::rect::{TypedRect}; use euclid::rect::{TypedRect};
use euclid::scale_factor::ScaleFactor; use euclid::scale_factor::ScaleFactor;
use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::{PaintChan, PaintTask}; use gfx::paint_task::{PaintChan, PaintTask};
use gfx::font_cache_task::FontCacheTask; use gfx::font_cache_task::FontCacheTask;
use ipc_channel::ipc;
use layers::geometry::DevicePixel; use layers::geometry::DevicePixel;
use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId}; use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId};
use msg::constellation_msg::{LoadData, WindowSizeData, PipelineExitType, MozBrowserEvent}; use msg::constellation_msg::{LoadData, WindowSizeData, PipelineExitType, MozBrowserEvent};
use profile_traits::mem; use profile_traits::mem;
@ -22,6 +25,7 @@ use net_traits::ResourceTask;
use net_traits::image_cache_task::ImageCacheTask; use net_traits::image_cache_task::ImageCacheTask;
use net_traits::storage_task::StorageTask; use net_traits::storage_task::StorageTask;
use std::sync::mpsc::{Receiver, channel}; use std::sync::mpsc::{Receiver, channel};
use std::thread;
use url::Url; use url::Url;
use util::geometry::{PagePx, ViewportPx}; use util::geometry::{PagePx, ViewportPx};
use util::opts; use util::opts;
@ -91,6 +95,8 @@ impl Pipeline {
let script_chan = match script_chan { let script_chan = match script_chan {
None => { None => {
let (script_chan, script_port) = channel(); let (script_chan, script_port) = channel();
let (script_to_compositor_chan, script_to_compositor_port) =
ipc::channel().unwrap();
let window_size = window_rect.map(|rect| { let window_size = window_rect.map(|rect| {
WindowSizeData { WindowSizeData {
@ -100,10 +106,18 @@ impl Pipeline {
} }
}); });
let compositor_proxy_for_script_listener_thread =
compositor_proxy.clone_compositor_proxy();
thread::spawn(move || {
compositor_task::run_script_listener_thread(
compositor_proxy_for_script_listener_thread,
script_to_compositor_port)
});
ScriptTaskFactory::create(None::<&mut STF>, ScriptTaskFactory::create(None::<&mut STF>,
id, id,
parent_info, parent_info,
compositor_proxy.clone_compositor_proxy(), ScriptListener::new(script_to_compositor_chan),
&layout_pair, &layout_pair,
ScriptControlChan(script_chan.clone()), ScriptControlChan(script_chan.clone()),
script_port, script_port,

View file

@ -22,12 +22,17 @@ git = "https://github.com/servo/rust-layers"
[dependencies.png] [dependencies.png]
git = "https://github.com/servo/rust-png" git = "https://github.com/servo/rust-png"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies] [dependencies]
url = "0.2.35" url = "0.2.35"
bitflags = "*" bitflags = "*"
hyper = "0.5" hyper = "0.5"
rustc-serialize = "0.3.4" rustc-serialize = "0.3.4"
euclid = "0.1" euclid = "0.1"
serde = "*"
serde_macros = "*"
[target.x86_64-apple-darwin.dependencies] [target.x86_64-apple-darwin.dependencies]
core-foundation = "*" core-foundation = "*"

View file

@ -7,6 +7,7 @@ use constellation_msg::{Key, KeyState, KeyModifiers};
use euclid::point::Point2D; use euclid::point::Point2D;
use euclid::rect::Rect; use euclid::rect::Rect;
use euclid::Matrix4; use euclid::Matrix4;
use ipc_channel::ipc::IpcSender;
use layers::platform::surface::NativeDisplay; use layers::platform::surface::NativeDisplay;
use layers::layers::{BufferRequest, LayerBufferSet}; use layers::layers::{BufferRequest, LayerBufferSet};
use std::fmt::{Formatter, Debug}; use std::fmt::{Formatter, Debug};
@ -35,7 +36,7 @@ impl FrameTreeId {
} }
} }
#[derive(Clone, PartialEq, Eq, Copy, Hash)] #[derive(Clone, PartialEq, Eq, Copy, Hash, Deserialize, Serialize)]
pub struct LayerId(pub usize, pub u32); pub struct LayerId(pub usize, pub u32);
impl Debug for LayerId { impl Debug for LayerId {
@ -115,16 +116,47 @@ pub trait PaintListener {
fn notify_paint_task_exiting(&mut self, pipeline_id: PipelineId); fn notify_paint_task_exiting(&mut self, pipeline_id: PipelineId);
} }
#[derive(Deserialize, Serialize)]
pub enum ScriptToCompositorMsg {
ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>),
SetTitle(PipelineId, Option<String>),
SendKeyEvent(Key, KeyState, KeyModifiers),
Exit,
}
/// The interface used by the script task to tell the compositor to update its ready state, /// 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. /// which is used in displaying the appropriate message in the window's title.
pub trait ScriptListener { #[derive(Clone)]
fn scroll_fragment_point(&mut self, pub struct ScriptListener(IpcSender<ScriptToCompositorMsg>);
pipeline_id: PipelineId,
layer_id: LayerId, impl ScriptListener {
point: Point2D<f32>); pub fn new(sender: IpcSender<ScriptToCompositorMsg>) -> ScriptListener {
/// Informs the compositor that the title of the page with the given pipeline ID has changed. ScriptListener(sender)
fn set_title(&mut self, pipeline_id: PipelineId, new_title: Option<String>); }
fn close(&mut self);
fn dup(&mut self) -> Box<ScriptListener+'static>; pub fn scroll_fragment_point(&mut self,
fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers); pipeline_id: PipelineId,
layer_id: LayerId,
point: Point2D<f32>) {
self.0
.send(ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point))
.unwrap()
}
pub fn close(&mut self) {
self.0.send(ScriptToCompositorMsg::Exit).unwrap()
}
pub fn dup(&mut self) -> ScriptListener {
self.clone()
}
pub fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
self.0.send(ScriptToCompositorMsg::SetTitle(pipeline_id, title)).unwrap()
}
pub fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers) {
self.0.send(ScriptToCompositorMsg::SendKeyEvent(key, state, modifiers)).unwrap()
}
} }

View file

@ -57,7 +57,7 @@ pub struct WindowSizeData {
pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>, pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
} }
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum KeyState { pub enum KeyState {
Pressed, Pressed,
Released, Released,
@ -65,7 +65,7 @@ pub enum KeyState {
} }
//N.B. Based on the glutin key enum //N.B. Based on the glutin key enum
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum Key { pub enum Key {
Space, Space,
Apostrophe, Apostrophe,
@ -191,6 +191,7 @@ pub enum Key {
} }
bitflags! { bitflags! {
#[derive(Deserialize, Serialize)]
flags KeyModifiers: u8 { flags KeyModifiers: u8 {
const NONE = 0x00, const NONE = 0x00,
const SHIFT = 0x01, const SHIFT = 0x01,
@ -368,10 +369,10 @@ pub struct FrameId(pub u32);
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct WorkerId(pub u32); pub struct WorkerId(pub u32);
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)]
pub struct PipelineId(pub u32); pub struct PipelineId(pub u32);
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)]
pub struct SubpageId(pub u32); pub struct SubpageId(pub u32);
// The type of pipeline exit. During complete shutdowns, pipelines do not have to // The type of pipeline exit. During complete shutdowns, pipelines do not have to

View file

@ -2,13 +2,18 @@
* 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/. */
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate azure; extern crate azure;
#[macro_use] extern crate bitflags; #[macro_use] extern crate bitflags;
extern crate euclid; extern crate euclid;
extern crate hyper; extern crate hyper;
extern crate ipc_channel;
extern crate layers; extern crate layers;
extern crate png; extern crate png;
extern crate rustc_serialize; extern crate rustc_serialize;
extern crate serde;
extern crate util; extern crate util;
extern crate url; extern crate url;
extern crate style; extern crate style;

View file

@ -328,7 +328,7 @@ impl<A,B> JSTraceable for fn(A) -> B {
} }
} }
impl JSTraceable for Box<ScriptListener+'static> { impl JSTraceable for ScriptListener {
#[inline] #[inline]
fn trace(&self, _: *mut JSTracer) { fn trace(&self, _: *mut JSTracer) {
// Do nothing // Do nothing

View file

@ -251,8 +251,11 @@ pub trait DocumentHelpers<'a> {
fn title_changed(self); fn title_changed(self);
fn send_title_to_compositor(self); fn send_title_to_compositor(self);
fn dirty_all_nodes(self); fn dirty_all_nodes(self);
fn dispatch_key_event(self, key: Key, state: KeyState, fn dispatch_key_event(self,
modifiers: KeyModifiers, compositor: &mut Box<ScriptListener+'static>); key: Key,
state: KeyState,
modifiers: KeyModifiers,
compositor: &mut ScriptListener);
fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>) fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>)
-> Fallible<Root<Node>>; -> Fallible<Root<Node>>;
fn get_body_attribute(self, local_name: &Atom) -> DOMString; fn get_body_attribute(self, local_name: &Atom) -> DOMString;
@ -763,10 +766,11 @@ impl<'a> DocumentHelpers<'a> for &'a Document {
} }
/// The entry point for all key processing for web content /// The entry point for all key processing for web content
fn dispatch_key_event(self, key: Key, fn dispatch_key_event(self,
key: Key,
state: KeyState, state: KeyState,
modifiers: KeyModifiers, modifiers: KeyModifiers,
compositor: &mut Box<ScriptListener+'static>) { compositor: &mut ScriptListener) {
let window = self.window.root(); let window = self.window.root();
let focused = self.get_focused_element(); let focused = self.get_focused_element();
let body = self.GetBody(); let body = self.GetBody();

View file

@ -105,7 +105,7 @@ pub struct Window {
navigator: MutNullableHeap<JS<Navigator>>, navigator: MutNullableHeap<JS<Navigator>>,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
image_cache_chan: ImageCacheChan, image_cache_chan: ImageCacheChan,
compositor: DOMRefCell<Box<ScriptListener+'static>>, compositor: DOMRefCell<ScriptListener>,
browser_context: DOMRefCell<Option<BrowserContext>>, browser_context: DOMRefCell<Option<BrowserContext>>,
page: Rc<Page>, page: Rc<Page>,
performance: MutNullableHeap<JS<Performance>>, performance: MutNullableHeap<JS<Performance>>,
@ -241,7 +241,7 @@ impl Window {
&self.image_cache_task &self.image_cache_task
} }
pub fn compositor<'a>(&'a self) -> RefMut<'a, Box<ScriptListener+'static>> { pub fn compositor<'a>(&'a self) -> RefMut<'a, ScriptListener> {
self.compositor.borrow_mut() self.compositor.borrow_mut()
} }
@ -964,7 +964,7 @@ impl Window {
script_chan: Box<ScriptChan+Send>, script_chan: Box<ScriptChan+Send>,
image_cache_chan: ImageCacheChan, image_cache_chan: ImageCacheChan,
control_chan: ScriptControlChan, control_chan: ScriptControlChan,
compositor: Box<ScriptListener+'static>, compositor: ScriptListener,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
resource_task: ResourceTask, resource_task: ResourceTask,
storage_task: StorageTask, storage_task: StorageTask,

View file

@ -297,8 +297,9 @@ pub struct ScriptTask {
/// For communicating load url messages to the constellation /// For communicating load url messages to the constellation
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
/// A handle to the compositor for communicating ready state messages. /// A handle to the compositor for communicating ready state messages.
compositor: DOMRefCell<Box<ScriptListener+'static>>, compositor: DOMRefCell<ScriptListener>,
/// The port on which we receive messages from the image cache /// The port on which we receive messages from the image cache
image_cache_port: Receiver<ImageCacheResult>, image_cache_port: Receiver<ImageCacheResult>,
@ -374,29 +375,28 @@ impl ScriptTaskFactory for ScriptTask {
box pair.sender() as Box<Any+Send> box pair.sender() as Box<Any+Send>
} }
fn create<C>(_phantom: Option<&mut ScriptTask>, fn create(_phantom: Option<&mut ScriptTask>,
id: PipelineId, id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>, parent_info: Option<(PipelineId, SubpageId)>,
compositor: C, compositor: ScriptListener,
layout_chan: &OpaqueScriptLayoutChannel, layout_chan: &OpaqueScriptLayoutChannel,
control_chan: ScriptControlChan, control_chan: ScriptControlChan,
control_port: Receiver<ConstellationControlMsg>, control_port: Receiver<ConstellationControlMsg>,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
failure_msg: Failure, failure_msg: Failure,
resource_task: ResourceTask, resource_task: ResourceTask,
storage_task: StorageTask, storage_task: StorageTask,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
devtools_chan: Option<DevtoolsControlChan>, devtools_chan: Option<DevtoolsControlChan>,
window_size: Option<WindowSizeData>, window_size: Option<WindowSizeData>,
load_data: LoadData) load_data: LoadData) {
where C: ScriptListener + Send + 'static {
let ConstellationChan(const_chan) = constellation_chan.clone(); let ConstellationChan(const_chan) = constellation_chan.clone();
let (script_chan, script_port) = channel(); let (script_chan, script_port) = channel();
let layout_chan = LayoutChan(layout_chan.sender()); let layout_chan = LayoutChan(layout_chan.sender());
spawn_named_with_send_on_failure(format!("ScriptTask {:?}", id), task_state::SCRIPT, move || { spawn_named_with_send_on_failure(format!("ScriptTask {:?}", id), task_state::SCRIPT, move || {
let roots = RootCollection::new(); let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots); let _stack_roots_tls = StackRootTLS::new(&roots);
let script_task = ScriptTask::new(box compositor as Box<ScriptListener>, let script_task = ScriptTask::new(compositor,
script_port, script_port,
NonWorkerScriptChan(script_chan), NonWorkerScriptChan(script_chan),
control_chan, control_chan,
@ -464,7 +464,7 @@ impl ScriptTask {
} }
/// Creates a new script task. /// Creates a new script task.
pub fn new(compositor: Box<ScriptListener+'static>, pub fn new(compositor: ScriptListener,
port: Receiver<ScriptMsg>, port: Receiver<ScriptMsg>,
chan: NonWorkerScriptChan, chan: NonWorkerScriptChan,
control_chan: ScriptControlChan, control_chan: ScriptControlChan,

View file

@ -150,22 +150,21 @@ pub struct ScriptControlChan(pub Sender<ConstellationControlMsg>);
/// crate. /// crate.
pub trait ScriptTaskFactory { pub trait ScriptTaskFactory {
/// Create a `ScriptTask`. /// Create a `ScriptTask`.
fn create<C>(_phantom: Option<&mut Self>, fn create(_phantom: Option<&mut Self>,
id: PipelineId, id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>, parent_info: Option<(PipelineId, SubpageId)>,
compositor: C, compositor: ScriptListener,
layout_chan: &OpaqueScriptLayoutChannel, layout_chan: &OpaqueScriptLayoutChannel,
control_chan: ScriptControlChan, control_chan: ScriptControlChan,
control_port: Receiver<ConstellationControlMsg>, control_port: Receiver<ConstellationControlMsg>,
constellation_msg: ConstellationChan, constellation_msg: ConstellationChan,
failure_msg: Failure, failure_msg: Failure,
resource_task: ResourceTask, resource_task: ResourceTask,
storage_task: StorageTask, storage_task: StorageTask,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
devtools_chan: Option<DevtoolsControlChan>, devtools_chan: Option<DevtoolsControlChan>,
window_size: Option<WindowSizeData>, window_size: Option<WindowSizeData>,
load_data: LoadData) load_data: LoadData);
where C: ScriptListener + Send;
/// Create a script -> layout channel (`Sender`, `Receiver` pair). /// Create a script -> layout channel (`Sender`, `Receiver` pair).
fn create_layout_channel(_phantom: Option<&mut Self>) -> OpaqueScriptLayoutChannel; fn create_layout_channel(_phantom: Option<&mut Self>) -> OpaqueScriptLayoutChannel;
/// Clone the `Sender` in `pair`. /// Clone the `Sender` in `pair`.

View file

@ -47,6 +47,11 @@ name = "android_glue"
version = "0.0.2" version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aster"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "azure" name = "azure"
version = "0.1.0" version = "0.1.0"
@ -157,6 +162,7 @@ dependencies = [
"gfx 0.0.1", "gfx 0.0.1",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout_traits 0.0.1", "layout_traits 0.0.1",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -612,6 +618,17 @@ dependencies = [
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "ipc-channel"
version = "0.1.0"
source = "git+https://github.com/pcwalton/ipc-channel#aa2eab807ba1e7e287d283c2788c317c53d26970"
dependencies = [
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "js" name = "js"
version = "0.1.0" version = "0.1.0"
@ -789,9 +806,12 @@ dependencies = [
"euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"png 0.1.0 (git+https://github.com/servo/rust-png)", "png 0.1.0 (git+https://github.com/servo/rust-png)",
"rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1", "style 0.0.1",
"url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1", "util 0.0.1",
@ -1007,6 +1027,27 @@ dependencies = [
"url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "quasi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quasi_codegen"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aster 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quasi_macros"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quasi_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "quicksort" name = "quicksort"
version = "1.0.0" version = "1.0.0"
@ -1124,6 +1165,32 @@ dependencies = [
"string_cache_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "serde"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_codegen"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aster 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quasi 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"quasi_macros 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_macros"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "shared_library" name = "shared_library"
version = "0.1.0" version = "0.1.0"