diff options
Diffstat (limited to 'src/components/net')
-rw-r--r-- | src/components/net/data_loader.rs | 9 | ||||
-rw-r--r-- | src/components/net/file_loader.rs | 29 | ||||
-rw-r--r-- | src/components/net/http_loader.rs | 13 | ||||
-rw-r--r-- | src/components/net/image/holder.rs | 4 | ||||
-rw-r--r-- | src/components/net/image_cache_task.rs | 500 | ||||
-rw-r--r-- | src/components/net/local_image_cache.rs | 15 | ||||
-rw-r--r-- | src/components/net/net.rc | 7 | ||||
-rw-r--r-- | src/components/net/resource_task.rs | 25 | ||||
-rw-r--r-- | src/components/net/util.rs | 7 |
9 files changed, 237 insertions, 372 deletions
diff --git a/src/components/net/data_loader.rs b/src/components/net/data_loader.rs index 09b1accd6e5..881b6b28bf6 100644 --- a/src/components/net/data_loader.rs +++ b/src/components/net/data_loader.rs @@ -11,7 +11,7 @@ use http::headers::test_utils::from_stream_with_str; use http::headers::content_type::MediaType; pub fn factory() -> LoaderTask { - |url, start_chan| { + proc(url, start_chan) { // NB: we don't spawn a new task. // Hypothesis: data URLs are too small for parallel base64 etc. to be worth it. // Should be tested at some point. @@ -25,7 +25,7 @@ fn load(url: Url, start_chan: Chan<LoadResponse>) { let mut metadata = Metadata::default(url.clone()); // Split out content type and data. - let parts: ~[&str] = url.path.splitn_iter(',', 1).to_owned_vec(); + let parts: ~[&str] = url.path.splitn(',', 1).to_owned_vec(); if parts.len() != 2 { start_sending(start_chan, metadata).send(Done(Err(()))); return; @@ -49,7 +49,7 @@ fn load(url: Url, start_chan: Chan<LoadResponse>) { if is_base64 { match parts[1].from_base64() { - Err(*) => { + Err(..) => { progress_chan.send(Done(Err(()))); } Ok(data) => { @@ -71,9 +71,8 @@ fn assert_parse(url: &'static str, charset: Option<~str>, data: Option<~[u8]>) { use std::from_str::FromStr; - use std::comm; - let (start_port, start_chan) = comm::stream(); + let (start_port, start_chan) = Chan::new(); load(FromStr::from_str(url).unwrap(), start_chan); let response = start_port.recv(); diff --git a/src/components/net/file_loader.rs b/src/components/net/file_loader.rs index 7225fe8606f..67690b6547a 100644 --- a/src/components/net/file_loader.rs +++ b/src/components/net/file_loader.rs @@ -5,45 +5,44 @@ use resource_task::{ProgressMsg, Metadata, Payload, Done, LoaderTask, start_sending}; use servo_util::io::result; -use std::comm::Chan; -use std::rt::io::file; -use std::rt::io::{FileStream, Reader, EndOfFile, Open, Read, ignore_io_error}; -use std::task; +use std::io; +use std::io::File; static READ_SIZE: uint = 1024; -fn read_all(reader: &mut FileStream, progress_chan: &Chan<ProgressMsg>) +fn read_all(reader: &mut io::Stream, progress_chan: &SharedChan<ProgressMsg>) -> Result<(), ()> { loop { - match (do result { + match (result(|| { let data = reader.read_bytes(READ_SIZE); progress_chan.send(Payload(data)); - }) { + })) { Ok(()) => (), Err(e) => match e.kind { - EndOfFile => return Ok(()), - _ => return Err(()), + io::EndOfFile => return Ok(()), + _ => return Err(()), } } } } pub fn factory() -> LoaderTask { - let f: LoaderTask = |url, start_chan| { + let f: LoaderTask = proc(url, start_chan) { assert!("file" == url.scheme); let progress_chan = start_sending(start_chan, Metadata::default(url.clone())); - do task::spawn { + spawn(proc() { // ignore_io_error causes us to get None instead of a task failure. - match ignore_io_error(|| file::open(&url.path.as_slice(), Open, Read)) { + let _guard = io::ignore_io_error(); + match File::open_mode(&Path::new(url.path), io::Open, io::Read) { Some(ref mut reader) => { - let res = read_all(reader, &progress_chan); + let res = read_all(reader as &mut io::Stream, &progress_chan); progress_chan.send(Done(res)); } None => { progress_chan.send(Done(Err(()))); } - } - } + }; + }); }; f } diff --git a/src/components/net/http_loader.rs b/src/components/net/http_loader.rs index 87c8cf369f1..79b34778245 100644 --- a/src/components/net/http_loader.rs +++ b/src/components/net/http_loader.rs @@ -4,19 +4,16 @@ use resource_task::{Metadata, Payload, Done, LoadResponse, LoaderTask, start_sending}; -use std::cell::Cell; use std::vec; use extra::url::Url; use http::client::RequestWriter; use http::method::Get; use http::headers::HeaderEnum; -use std::rt::io::Reader; +use std::io::Reader; pub fn factory() -> LoaderTask { - let f: LoaderTask = |url, start_chan| { - let url = Cell::new(url); - let start_chan = Cell::new(start_chan); - spawn(|| load(url.take(), start_chan.take())) + let f: LoaderTask = proc(url, start_chan) { + spawn(proc() load(url, start_chan)) }; f } @@ -63,10 +60,10 @@ fn load(mut url: Url, start_chan: Chan<LoadResponse>) { loop { let mut buf = vec::with_capacity(1024); - unsafe { vec::raw::set_len(&mut buf, 1024) }; + unsafe { buf.set_len(1024); } match response.read(buf) { Some(len) => { - unsafe { vec::raw::set_len(&mut buf, len) }; + unsafe { buf.set_len(len); } progress_chan.send(Payload(buf)); } None => { diff --git a/src/components/net/image/holder.rs b/src/components/net/image/holder.rs index 5b312fffe4f..7213644551d 100644 --- a/src/components/net/image/holder.rs +++ b/src/components/net/image/holder.rs @@ -64,12 +64,12 @@ impl ImageHolder { /// Query and update the current image size. pub fn get_size(&mut self) -> Option<Size2D<int>> { debug!("get_size() {}", self.url.to_str()); - do self.get_image().map |img| { + self.get_image().map(|img| { let img_ref = img.get(); self.cached_size = Size2D(img_ref.width as int, img_ref.height as int); self.cached_size.clone() - } + }) } pub fn get_image(&mut self) -> Option<Arc<~Image>> { diff --git a/src/components/net/image_cache_task.rs b/src/components/net/image_cache_task.rs index 7669f09f4d7..8a99ccf4a2c 100644 --- a/src/components/net/image_cache_task.rs +++ b/src/components/net/image_cache_task.rs @@ -7,8 +7,7 @@ use resource_task; use resource_task::ResourceTask; use servo_util::url::{UrlMap, url_map}; -use std::cell::Cell; -use std::comm::{Chan, Port, SharedChan, stream}; +use std::comm::{Chan, Port, SharedChan}; use std::task::spawn; use std::to_str::ToStr; use std::util::replace; @@ -24,7 +23,7 @@ pub enum Msg { // FIXME: We can probably get rid of this Cell now // FIXME: make this priv after visibility rules change /// Used be the prefetch tasks to post back image binaries - StorePrefetchedImageData(Url, Result<Cell<~[u8]>, ()>), + StorePrefetchedImageData(Url, Result<~[u8], ()>), /// Tell the cache to decode an image. Must be posted before GetImage/WaitForImage Decode(Url), @@ -40,12 +39,16 @@ pub enum Msg { /// Wait for an image to become available (or fail to load). WaitForImage(Url, Chan<ImageResponseMsg>), + /// Clients must wait for a response before shutting down the ResourceTask + Exit(Chan<()>), + /// For testing // FIXME: make this priv after visibility rules change - OnMsg(~fn(msg: &Msg)), + WaitForStore(Chan<()>), - /// Clients must wait for a response before shutting down the ResourceTask - Exit(Chan<()>), + /// For testing + // FIXME: make this priv after visibility rules change + WaitForStorePrefetched(Chan<()>), } #[deriving(Clone)] @@ -59,11 +62,11 @@ impl Eq for ImageResponseMsg { fn eq(&self, other: &ImageResponseMsg) -> bool { // FIXME: Bad copies match (self.clone(), other.clone()) { - (ImageReady(*), ImageReady(*)) => fail!(~"unimplemented comparison"), + (ImageReady(..), ImageReady(..)) => fail!(~"unimplemented comparison"), (ImageNotReady, ImageNotReady) => true, (ImageFailed, ImageFailed) => true, - (ImageReady(*), _) | (ImageNotReady, _) | (ImageFailed, _) => false + (ImageReady(..), _) | (ImageNotReady, _) | (ImageFailed, _) => false } } @@ -72,49 +75,39 @@ impl Eq for ImageResponseMsg { } } -pub type ImageCacheTask = SharedChan<Msg>; - -type DecoderFactory = ~fn() -> ~fn(&[u8]) -> Option<Image>; - -pub fn ImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask { - ImageCacheTask_(resource_task, default_decoder_factory) +#[deriving(Clone)] +pub struct ImageCacheTask { + chan: SharedChan<Msg>, } -pub fn ImageCacheTask_(resource_task: ResourceTask, decoder_factory: DecoderFactory) - -> ImageCacheTask { - // FIXME: Doing some dancing to avoid copying decoder_factory, our test - // version of which contains an uncopyable type which rust will currently - // copy unsoundly - let decoder_factory_cell = Cell::new(decoder_factory); +type DecoderFactory = fn() -> proc(&[u8]) -> Option<Image>; - let (port, chan) = stream(); - let chan = SharedChan::new(chan); - let port_cell = Cell::new(port); - let chan_cell = Cell::new(chan.clone()); +pub fn ImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask { + let (port, chan) = SharedChan::new(); + let chan_clone = chan.clone(); - do spawn { + spawn(proc() { let mut cache = ImageCache { resource_task: resource_task.clone(), - decoder_factory: decoder_factory_cell.take(), - port: port_cell.take(), - chan: chan_cell.take(), + port: port, + chan: chan_clone, state_map: url_map(), wait_map: url_map(), need_exit: None }; cache.run(); - } + }); - chan + ImageCacheTask { + chan: chan, + } } // FIXME: make this priv after visibility rules change pub fn SyncImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask { - let (port, chan) = stream(); - let port_cell = Cell::new(port); + let (port, chan) = SharedChan::new(); - do spawn { - let port = port_cell.take(); + spawn(proc() { let inner_cache = ImageCacheTask(resource_task.clone()); loop { @@ -131,16 +124,16 @@ pub fn SyncImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask { msg => inner_cache.send(msg) } } - } + }); - SharedChan::new(chan) + ImageCacheTask { + chan: chan, + } } struct ImageCache { /// A handle to the resource task for fetching the image binaries resource_task: ResourceTask, - /// Creates image decoders - decoder_factory: DecoderFactory, /// The port on which we'll receive client requests port: Port<Msg>, /// A copy of the shared chan to give to child tasks @@ -156,7 +149,7 @@ struct ImageCache { enum ImageState { Init, Prefetching(AfterPrefetch), - Prefetched(Cell<~[u8]>), + Prefetched(~[u8]), Decoding, Decoded(Arc<~Image>), Failed @@ -170,29 +163,39 @@ enum AfterPrefetch { impl ImageCache { pub fn run(&mut self) { - let mut msg_handlers: ~[~fn(msg: &Msg)] = ~[]; + let mut store_chan: Option<Chan<()>> = None; + let mut store_prefetched_chan: Option<Chan<()>> = None; loop { let msg = self.port.recv(); - for handler in msg_handlers.iter() { - (*handler)(&msg) - } - debug!("image_cache_task: received: {:?}", msg); match msg { Prefetch(url) => self.prefetch(url), StorePrefetchedImageData(url, data) => { + store_prefetched_chan.map(|chan| { + chan.send(()); + }); + store_prefetched_chan = None; + self.store_prefetched_image_data(url, data); } Decode(url) => self.decode(url), - StoreImage(url, image) => self.store_image(url, image), + StoreImage(url, image) => { + store_chan.map(|chan| { + chan.send(()); + }); + store_chan = None; + + self.store_image(url, image) + } GetImage(url, response) => self.get_image(url, response), WaitForImage(url, response) => { self.wait_for_image(url, response) } - OnMsg(handler) => msg_handlers.push(handler), + WaitForStore(chan) => store_chan = Some(chan), + WaitForStorePrefetched(chan) => store_prefetched_chan = Some(chan), Exit(response) => { assert!(self.need_exit.is_none()); self.need_exit = Some(response); @@ -208,10 +211,10 @@ impl ImageCache { let mut can_exit = true; for (_, state) in self.state_map.iter() { match *state { - Prefetching(*) => can_exit = false, + Prefetching(..) => can_exit = false, Decoding => can_exit = false, - Init | Prefetched(*) | Decoded(*) | Failed => () + Init | Prefetched(..) | Decoded(..) | Failed => () } } @@ -243,45 +246,44 @@ impl ImageCache { Init => { let to_cache = self.chan.clone(); let resource_task = self.resource_task.clone(); - let url_cell = Cell::new(url.clone()); + let url_clone = url.clone(); - do spawn { - let url = url_cell.take(); + spawn(proc() { + let url = url_clone; debug!("image_cache_task: started fetch for {:s}", url.to_str()); let image = load_image_data(url.clone(), resource_task.clone()); let result = if image.is_ok() { - Ok(Cell::new(image.unwrap())) + Ok(image.unwrap()) } else { Err(()) }; to_cache.send(StorePrefetchedImageData(url.clone(), result)); debug!("image_cache_task: ended fetch for {:s}", (url.clone()).to_str()); - } + }); self.set_state(url, Prefetching(DoNotDecode)); } - Prefetching(*) | Prefetched(*) | Decoding | Decoded(*) | Failed => { + Prefetching(..) | Prefetched(..) | Decoding | Decoded(..) | Failed => { // We've already begun working on this image } } } - fn store_prefetched_image_data(&mut self, url: Url, data: Result<Cell<~[u8]>, ()>) { + fn store_prefetched_image_data(&mut self, url: Url, data: Result<~[u8], ()>) { match self.get_state(url.clone()) { Prefetching(next_step) => { match data { - Ok(data_cell) => { - let data = data_cell.take(); - self.set_state(url.clone(), Prefetched(Cell::new(data))); + Ok(data) => { + self.set_state(url.clone(), Prefetched(data)); match next_step { DoDecode => self.decode(url), _ => () } } - Err(*) => { + Err(..) => { self.set_state(url.clone(), Failed); self.purge_waiters(url, || ImageFailed); } @@ -289,9 +291,9 @@ impl ImageCache { } Init - | Prefetched(*) + | Prefetched(..) | Decoding - | Decoded(*) + | Decoded(..) | Failed => { fail!(~"wrong state for storing prefetched image") } @@ -311,18 +313,14 @@ impl ImageCache { // We don't have the data yet, but the decode request is queued up } - Prefetched(data_cell) => { - assert!(!data_cell.is_empty()); - - let data = data_cell.take(); + Prefetched(data) => { let to_cache = self.chan.clone(); - let url_cell = Cell::new(url.clone()); - let decode = (self.decoder_factory)(); + let url_clone = url.clone(); - do spawn { - let url = url_cell.take(); + spawn(proc() { + let url = url_clone; debug!("image_cache_task: started image decode for {:s}", url.to_str()); - let image = decode(data); + let image = load_from_memory(data); let image = if image.is_some() { Some(Arc::new(~image.unwrap())) } else { @@ -330,12 +328,12 @@ impl ImageCache { }; to_cache.send(StoreImage(url.clone(), image)); debug!("image_cache_task: ended image decode for {:s}", url.to_str()); - } + }); self.set_state(url, Decoding); } - Decoding | Decoded(*) | Failed => { + Decoding | Decoded(..) | Failed => { // We've already begun decoding } } @@ -358,9 +356,9 @@ impl ImageCache { } Init - | Prefetching(*) - | Prefetched(*) - | Decoded(*) + | Prefetching(..) + | Prefetched(..) + | Decoded(..) | Failed => { fail!(~"incorrect state in store_image") } @@ -368,7 +366,7 @@ impl ImageCache { } - fn purge_waiters(&mut self, url: Url, f: &fn() -> ImageResponseMsg) { + fn purge_waiters(&mut self, url: Url, f: || -> ImageResponseMsg) { match self.wait_map.pop(&url) { Some(waiters) => { unsafe { @@ -387,7 +385,7 @@ impl ImageCache { match self.get_state(url.clone()) { Init => fail!(~"request for image before prefetch"), Prefetching(DoDecode) => response.send(ImageNotReady), - Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"), + Prefetching(DoNotDecode) | Prefetched(..) => fail!(~"request for image before decode"), Decoding => response.send(ImageNotReady), Decoded(image) => response.send(ImageReady(image.clone())), Failed => response.send(ImageFailed), @@ -398,16 +396,16 @@ impl ImageCache { match self.get_state(url.clone()) { Init => fail!(~"request for image before prefetch"), - Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"), + Prefetching(DoNotDecode) | Prefetched(..) => fail!(~"request for image before decode"), Prefetching(DoDecode) | Decoding => { // We don't have this image yet if self.wait_map.contains_key(&url) { let waiters = self.wait_map.find_mut(&url).unwrap(); + let mut response = Some(response); unsafe { - let res = Cell::new(response); - waiters.unsafe_access( |waiters| { - waiters.push(res.take()); + waiters.unsafe_access(|waiters| { + waiters.push(response.take().unwrap()); }); } } else { @@ -434,14 +432,34 @@ trait ImageCacheTaskClient { impl ImageCacheTaskClient for ImageCacheTask { fn exit(&self) { - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); self.send(Exit(response_chan)); response_port.recv(); } } +impl ImageCacheTask { + pub fn send(&self, msg: Msg) { + self.chan.send(msg); + } + + #[cfg(test)] + fn wait_for_store(&self) -> Port<()> { + let (port, chan) = Chan::new(); + self.send(WaitForStore(chan)); + port + } + + #[cfg(test)] + fn wait_for_store_prefetched(&self) -> Port<()> { + let (port, chan) = Chan::new(); + self.send(WaitForStorePrefetched(chan)); + port + } +} + fn load_image_data(url: Url, resource_task: ResourceTask) -> Result<~[u8], ()> { - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); resource_task.send(resource_task::Load(url, response_chan)); let mut image_data = ~[]; @@ -452,38 +470,29 @@ fn load_image_data(url: Url, resource_task: ResourceTask) -> Result<~[u8], ()> { resource_task::Payload(data) => { image_data.push_all(data); } - resource_task::Done(result::Ok(*)) => { + resource_task::Done(result::Ok(..)) => { return Ok(image_data); } - resource_task::Done(result::Err(*)) => { + resource_task::Done(result::Err(..)) => { return Err(()); } } } } -fn default_decoder_factory() -> ~fn(&[u8]) -> Option<Image> { - let foo: ~fn(&[u8]) -> Option<Image> = |data: &[u8]| { load_from_memory(data) }; - foo -} #[cfg(test)] mod tests { use super::*; - use std::comm; - use std::comm::{Port, SharedChan}; - use std::result; - use std::cell::Cell; - use resource_task; use resource_task::{ResourceTask, Metadata, start_sending}; - use image::base::{Image, test_image_bin, load_from_memory}; + use image::base::test_image_bin; use util::spawn_listener; use servo_util::url::make_url; - fn mock_resource_task(on_load: ~fn(resource: Chan<resource_task::ProgressMsg>)) -> ResourceTask { - let chan = do spawn_listener |port: Port<resource_task::ControlMsg>| { + fn mock_resource_task(on_load: proc(resource: SharedChan<resource_task::ProgressMsg>)) -> ResourceTask { + spawn_listener(proc(port: Port<resource_task::ControlMsg>) { loop { match port.recv() { resource_task::Load(_, response) => { @@ -493,13 +502,12 @@ mod tests { resource_task::Exit => break } } - }; - SharedChan::new(chan) + }) } #[test] fn should_exit_on_request() { - let mock_resource_task = mock_resource_task(|_response| () ); + let mock_resource_task = mock_resource_task(proc(_response) {}); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let _url = make_url(~"file", None); @@ -511,24 +519,24 @@ mod tests { #[test] #[should_fail] fn should_fail_if_unprefetched_image_is_requested() { - let mock_resource_task = mock_resource_task(|_response| () ); + let mock_resource_task = mock_resource_task(proc(_response) {}); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (port, chan) = stream(); + let (port, chan) = Chan::new(); image_cache_task.send(GetImage(url, chan)); port.recv(); } #[test] fn should_request_url_from_resource_task_on_prefetch() { - let (url_requested, url_requested_chan) = comm::stream(); + let (url_requested, url_requested_chan) = Chan::new(); - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { url_requested_chan.send(()); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -539,47 +547,14 @@ mod tests { mock_resource_task.send(resource_task::Exit); } - - #[test] - #[should_fail] - fn should_fail_if_requesting_decode_of_an_unprefetched_image() { - let mock_resource_task = mock_resource_task(|_response| () ); - - let image_cache_task = ImageCacheTask(mock_resource_task.clone()); - let url = make_url(~"file", None); - - image_cache_task.send(Decode(url)); - image_cache_task.exit(); - } - - #[test] - #[should_fail] - fn should_fail_if_requesting_image_before_requesting_decode() { - let mock_resource_task = do mock_resource_task |response| { - response.send(resource_task::Done(result::Ok(()))); - }; - - let image_cache_task = ImageCacheTask(mock_resource_task.clone()); - let url = make_url(~"file", None); - - image_cache_task.send(Prefetch(url.clone())); - // no decode message - - let (_port, chan) = stream(); - image_cache_task.send(GetImage(url, chan)); - - image_cache_task.exit(); - mock_resource_task.send(resource_task::Exit); - } - #[test] fn should_not_request_url_from_resource_task_on_multiple_prefetches() { - let (url_requested, url_requested_chan) = comm::stream(); + let (url_requested, url_requested_chan) = Chan::new(); - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { url_requested_chan.send(()); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -589,27 +564,27 @@ mod tests { url_requested.recv(); image_cache_task.exit(); mock_resource_task.send(resource_task::Exit); - assert!(!url_requested.peek()) + assert!(url_requested.try_recv().is_none()) } #[test] fn should_return_image_not_ready_if_data_has_not_arrived() { - let (wait_port, wait_chan) = comm::stream(); + let (wait_port, wait_chan) = Chan::new(); - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { // Don't send the data until after the client requests // the image wait_port.recv(); response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url, response_chan)); assert!(response_port.recv() == ImageNotReady); wait_chan.send(()); @@ -619,30 +594,23 @@ mod tests { #[test] fn should_return_decoded_image_data_if_data_has_arrived() { - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (wait_for_image, wait_for_image_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StoreImage(*) => wait_for_image_chan.send(()), - _ => () - } - })); + let join_port = image_cache_task.wait_for_store(); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); // Wait until our mock resource task has sent the image to the image cache - wait_for_image.recv(); + join_port.recv(); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url, response_chan)); match response_port.recv() { ImageReady(_) => (), @@ -655,31 +623,24 @@ mod tests { #[test] fn should_return_decoded_image_data_for_multiple_requests() { - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (wait_for_image, wait_for_image_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StoreImage(*) => wait_for_image_chan.send(()), - _ => () - } - })); + let join_port = image_cache_task.wait_for_store(); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); // Wait until our mock resource task has sent the image to the image cache - wait_for_image.recv(); + join_port.recv(); for _ in range(0,2) { - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url.clone(), response_chan)); match response_port.recv() { ImageReady(_) => (), @@ -693,17 +654,17 @@ mod tests { #[test] fn should_not_request_image_from_resource_task_if_image_is_already_available() { - let (image_bin_sent, image_bin_sent_chan) = comm::stream(); + let (image_bin_sent, image_bin_sent_chan) = Chan::new(); - let (resource_task_exited, resource_task_exited_chan) = comm::stream(); + let (resource_task_exited, resource_task_exited_chan) = Chan::new(); - let mock_resource_task = do spawn_listener |port: comm::Port<resource_task::ControlMsg>| { + let mock_resource_task = spawn_listener(proc(port: Port<resource_task::ControlMsg>) { loop { match port.recv() { resource_task::Load(_, response) => { let chan = start_sending(response, Metadata::default(make_url(~"file:///fake", None))); chan.send(resource_task::Payload(test_image_bin())); - chan.send(resource_task::Done(result::Ok(()))); + chan.send(resource_task::Done(Ok(()))); image_bin_sent_chan.send(()); } resource_task::Exit => { @@ -712,8 +673,7 @@ mod tests { } } } - }; - let mock_resource_task = SharedChan::new(mock_resource_task); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -732,22 +692,22 @@ mod tests { // Our resource task should not have received another request for the image // because it's already cached - assert!(!image_bin_sent.peek()); + assert!(image_bin_sent.try_recv().is_none()); } #[test] fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() { - let (image_bin_sent, image_bin_sent_chan) = comm::stream(); + let (image_bin_sent, image_bin_sent_chan) = Chan::new(); - let (resource_task_exited, resource_task_exited_chan) = comm::stream(); + let (resource_task_exited, resource_task_exited_chan) = Chan::new(); - let mock_resource_task = do spawn_listener |port: comm::Port<resource_task::ControlMsg>| { + let mock_resource_task = spawn_listener(proc(port: Port<resource_task::ControlMsg>) { loop { match port.recv() { resource_task::Load(_, response) => { let chan = start_sending(response, Metadata::default(make_url(~"file:///fake", None))); chan.send(resource_task::Payload(test_image_bin())); - chan.send(resource_task::Done(result::Err(()))); + chan.send(resource_task::Done(Err(()))); image_bin_sent_chan.send(()); } resource_task::Exit => { @@ -756,8 +716,7 @@ mod tests { } } } - }; - let mock_resource_task = SharedChan::new(mock_resource_task); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -778,36 +737,29 @@ mod tests { // Our resource task should not have received another request for the image // because it's already cached - assert!(!image_bin_sent.peek()); + assert!(image_bin_sent.try_recv().is_none()); } #[test] fn should_return_failed_if_image_bin_cannot_be_fetched() { - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { response.send(resource_task::Payload(test_image_bin())); // ERROR fetching image - response.send(resource_task::Done(result::Err(()))); - }; + response.send(resource_task::Done(Err(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (wait_for_prefetech, wait_for_prefetech_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StorePrefetchedImageData(*) => wait_for_prefetech_chan.send(()), - _ => () - } - })); + let join_port = image_cache_task.wait_for_store_prefetched(); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); // Wait until our mock resource task has sent the image to the image cache - wait_for_prefetech.recv(); + join_port.recv(); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url, response_chan)); match response_port.recv() { ImageFailed => (), @@ -820,31 +772,24 @@ mod tests { #[test] fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() { - let mock_resource_task = do mock_resource_task |response | { + let mock_resource_task = mock_resource_task(proc(response) { response.send(resource_task::Payload(test_image_bin())); // ERROR fetching image - response.send(resource_task::Done(result::Err(()))); - }; + response.send(resource_task::Done(Err(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (wait_for_prefetech, wait_for_prefetech_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StorePrefetchedImageData(*) => wait_for_prefetech_chan.send(()), - _ => () - } - })); + let join_port = image_cache_task.wait_for_store_prefetched(); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); // Wait until our mock resource task has sent the image to the image cache - wait_for_prefetech.recv(); + join_port.recv(); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url.clone(), response_chan)); match response_port.recv() { ImageFailed => (), @@ -852,7 +797,7 @@ mod tests { } // And ask again, we should get the same response - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url, response_chan)); match response_port.recv() { ImageFailed => (), @@ -864,86 +809,26 @@ mod tests { } #[test] - fn should_return_not_ready_if_image_is_still_decoding() { - let (wait_to_decode_port, wait_to_decode_chan) = comm::stream(); - - let mock_resource_task = do mock_resource_task |response| { - response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; - - let wait_to_decode_port_cell = Cell::new(wait_to_decode_port); - let decoder_factory: ~fn:Send() -> ~fn:Send(&[u8]) -> Option<Image> = || { - let wait_to_decode_port = wait_to_decode_port_cell.take(); - |data: &[u8]| { - // Don't decode until after the client requests the image - wait_to_decode_port.recv(); - load_from_memory(data) - } - }; - - let image_cache_task = ImageCacheTask_(mock_resource_task.clone(), decoder_factory); - let url = make_url(~"file", None); - - let (wait_for_prefetech, wait_for_prefetech_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StorePrefetchedImageData(*) => wait_for_prefetech_chan.send(()), - _ => () - } - })); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - wait_for_prefetech.recv(); - - // Make the request - let (response_port, response_chan) = stream(); - image_cache_task.send(GetImage(url, response_chan)); - - match response_port.recv() { - ImageNotReady => (), - _ => fail!("bleh") - } - - // Now decode - wait_to_decode_chan.send(()); - - image_cache_task.exit(); - mock_resource_task.send(resource_task::Exit); - } - - #[test] fn should_return_failed_if_image_decode_fails() { - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { // Bogus data response.send(resource_task::Payload(~[])); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (wait_for_decode, wait_for_decode_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StoreImage(*) => wait_for_decode_chan.send(()), - _ => () - } - })); + let join_port = image_cache_task.wait_for_store(); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); // Wait until our mock resource task has sent the image to the image cache - wait_for_decode.recv(); + join_port.recv(); // Make the request - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url, response_chan)); match response_port.recv() { @@ -957,33 +842,26 @@ mod tests { #[test] fn should_return_image_on_wait_if_image_is_already_loaded() { - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); - let (wait_for_decode, wait_for_decode_chan) = comm::stream(); - - image_cache_task.send(OnMsg(|msg| { - match *msg { - StoreImage(*) => wait_for_decode_chan.send(()), - _ => () - } - })); + let join_port = image_cache_task.wait_for_store(); image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); // Wait until our mock resource task has sent the image to the image cache - wait_for_decode.recv(); + join_port.recv(); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(WaitForImage(url, response_chan)); match response_port.recv() { - ImageReady(*) => (), + ImageReady(..) => (), _ => fail!("bleh") } @@ -993,13 +871,13 @@ mod tests { #[test] fn should_return_image_on_wait_if_image_is_not_yet_loaded() { - let (wait_port, wait_chan) = comm::stream(); + let (wait_port, wait_chan) = Chan::new(); - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { wait_port.recv(); response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -1007,13 +885,13 @@ mod tests { image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(WaitForImage(url, response_chan)); wait_chan.send(()); match response_port.recv() { - ImageReady(*) => (), + ImageReady(..) => (), _ => fail!("bleh") } @@ -1023,13 +901,13 @@ mod tests { #[test] fn should_return_image_failed_on_wait_if_image_fails_to_load() { - let (wait_port, wait_chan) = comm::stream(); + let (wait_port, wait_chan) = Chan::new(); - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { wait_port.recv(); response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Err(()))); - }; + response.send(resource_task::Done(Err(()))); + }); let image_cache_task = ImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -1037,7 +915,7 @@ mod tests { image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(WaitForImage(url, response_chan)); wait_chan.send(()); @@ -1053,10 +931,10 @@ mod tests { #[test] fn sync_cache_should_wait_for_images() { - let mock_resource_task = do mock_resource_task |response| { + let mock_resource_task = mock_resource_task(proc(response) { response.send(resource_task::Payload(test_image_bin())); - response.send(resource_task::Done(result::Ok(()))); - }; + response.send(resource_task::Done(Ok(()))); + }); let image_cache_task = SyncImageCacheTask(mock_resource_task.clone()); let url = make_url(~"file", None); @@ -1064,7 +942,7 @@ mod tests { image_cache_task.send(Prefetch(url.clone())); image_cache_task.send(Decode(url.clone())); - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(GetImage(url, response_chan)); match response_port.recv() { ImageReady(_) => (), diff --git a/src/components/net/local_image_cache.rs b/src/components/net/local_image_cache.rs index f1889ff306b..f6dd537e47f 100644 --- a/src/components/net/local_image_cache.rs +++ b/src/components/net/local_image_cache.rs @@ -11,14 +11,13 @@ multiple times and thus triggering reflows multiple times. use image_cache_task::{Decode, GetImage, ImageCacheTask, ImageFailed, ImageNotReady, ImageReady}; use image_cache_task::{ImageResponseMsg, Prefetch, WaitForImage}; -use std::comm; use std::comm::Port; use std::task; use servo_util::url::{UrlMap, url_map}; use extra::url::Url; pub trait ImageResponder { - fn respond(&self) -> ~fn(ImageResponseMsg); + fn respond(&self) -> proc(ImageResponseMsg); } pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache { @@ -90,13 +89,13 @@ impl LocalImageCache { match state.last_response { ImageReady(ref image) => { - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); chan.send(ImageReady(image.clone())); return port; } ImageNotReady => { if last_round == self.round_number { - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); chan.send(ImageNotReady); return port; } else { @@ -105,14 +104,14 @@ impl LocalImageCache { } } ImageFailed => { - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); chan.send(ImageFailed); return port; } } } - let (response_port, response_chan) = comm::stream(); + let (response_port, response_chan) = Chan::new(); self.image_cache_task.send(GetImage((*url).clone(), response_chan)); let response = response_port.recv(); @@ -128,7 +127,7 @@ impl LocalImageCache { let on_image_available = self.on_image_available.as_ref().unwrap().respond(); let url = (*url).clone(); do task::spawn { - let (response_port, response_chan) = comm::stream(); + let (response_port, response_chan) = Chan::new(); image_cache_task.send(WaitForImage(url.clone(), response_chan)); on_image_available(response_port.recv()); } @@ -144,7 +143,7 @@ impl LocalImageCache { }; self.get_state(url).last_response = response_copy; - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); chan.send(response); return port; } diff --git a/src/components/net/net.rc b/src/components/net/net.rc index da445e1e964..7378c7c059b 100644 --- a/src/components/net/net.rc +++ b/src/components/net/net.rc @@ -2,17 +2,14 @@ * 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/. */ -#[link(name = "net", - vers = "0.1", - uuid = "69c2b7b7-0d7d-4514-a48a-0eed61476039", - url = "http://servo.org/")]; +#[crate_id = "github.com/mozilla/servo#net:0.1"]; #[crate_type = "lib"]; #[feature(globs, managed_boxes)]; extern mod geom; extern mod http; -extern mod servo_util (name = "util"); +extern mod servo_util = "util"; extern mod stb_image; extern mod extra; extern mod png; diff --git a/src/components/net/resource_task.rs b/src/components/net/resource_task.rs index 94d074e91b7..53d5c3ea5ba 100644 --- a/src/components/net/resource_task.rs +++ b/src/components/net/resource_task.rs @@ -8,9 +8,7 @@ use file_loader; use http_loader; use data_loader; -use std::cell::Cell; use std::comm::{Chan, Port, SharedChan}; -use std::comm; use extra::url::Url; use util::spawn_listener; use http::headers::content_type::MediaType; @@ -87,8 +85,8 @@ pub enum ProgressMsg { /// For use by loaders in responding to a Load message. pub fn start_sending(start_chan: Chan<LoadResponse>, - metadata: Metadata) -> Chan<ProgressMsg> { - let (progress_port, progress_chan) = comm::stream(); + metadata: Metadata) -> SharedChan<ProgressMsg> { + let (progress_port, progress_chan) = SharedChan::new(); start_chan.send(LoadResponse { metadata: metadata, progress_port: progress_port, @@ -99,7 +97,7 @@ pub fn start_sending(start_chan: Chan<LoadResponse>, /// Convenience function for synchronously loading a whole resource. pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) -> Result<(Metadata, ~[u8]), ()> { - let (start_port, start_chan) = comm::stream(); + let (start_port, start_chan) = Chan::new(); resource_task.send(Load(url, start_chan)); let response = start_port.recv(); @@ -116,7 +114,7 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) /// Handle to a resource task pub type ResourceTask = SharedChan<ControlMsg>; -pub type LoaderTask = ~fn(url: Url, Chan<LoadResponse>); +pub type LoaderTask = proc(url: Url, Chan<LoadResponse>); /** Creates a task to load a specific resource @@ -137,12 +135,11 @@ pub fn ResourceTask() -> ResourceTask { } fn create_resource_task_with_loaders(loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask { - let loaders_cell = Cell::new(loaders); - let chan = do spawn_listener |from_client| { + let chan = spawn_listener(proc(from_client) { // TODO: change copy to move once we can move out of closures - ResourceManager(from_client, loaders_cell.take()).start() - }; - SharedChan::new(chan) + ResourceManager(from_client, loaders).start() + }); + chan } pub struct ResourceManager { @@ -211,7 +208,7 @@ fn test_exit() { #[test] fn test_bad_scheme() { let resource_task = ResourceTask(); - let (start, start_chan) = comm::stream(); + let (start, start_chan) = Chan::new(); resource_task.send(Load(FromStr::from_str("bogus://whatever").unwrap(), start_chan)); let response = start.recv(); match response.progress_port.recv() { @@ -226,7 +223,7 @@ static snicklefritz_payload: [u8, ..3] = [1, 2, 3]; #[cfg(test)] fn snicklefritz_loader_factory() -> LoaderTask { - let f: LoaderTask = |url: Url, start_chan: Chan<LoadResponse>| { + let f: LoaderTask = proc(url: Url, start_chan: Chan<LoadResponse>) { let progress_chan = start_sending(start_chan, Metadata::default(url)); progress_chan.send(Payload(snicklefritz_payload.into_owned())); progress_chan.send(Done(Ok(()))); @@ -238,7 +235,7 @@ fn snicklefritz_loader_factory() -> LoaderTask { fn should_delegate_to_scheme_loader() { let loader_factories = ~[(~"snicklefritz", snicklefritz_loader_factory)]; let resource_task = create_resource_task_with_loaders(loader_factories); - let (start, start_chan) = comm::stream(); + let (start, start_chan) = Chan::new(); resource_task.send(Load(FromStr::from_str("snicklefritz://heya").unwrap(), start_chan)); let response = start.recv(); diff --git a/src/components/net/util.rs b/src/components/net/util.rs index 342f7df5d4e..2fc4a940881 100644 --- a/src/components/net/util.rs +++ b/src/components/net/util.rs @@ -2,14 +2,13 @@ * 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 std::comm; use std::comm::{Chan, Port}; use std::task; -pub fn spawn_listener<A: Send>(f: ~fn(Port<A>)) -> Chan<A> { - let (setup_port, setup_chan) = comm::stream(); +pub fn spawn_listener<A: Send>(f: proc(Port<A>)) -> SharedChan<A> { + let (setup_port, setup_chan) = Chan::new(); do task::spawn { - let (port, chan) = comm::stream(); + let (port, chan) = SharedChan::new(); setup_chan.send(chan); f(port); } |