diff options
author | bors-servo <release+servo@mozilla.com> | 2014-01-12 19:16:21 -0800 |
---|---|---|
committer | bors-servo <release+servo@mozilla.com> | 2014-01-12 19:16:21 -0800 |
commit | 943ab4a4f0e3074e78d96ad94b7e96a46edacf79 (patch) | |
tree | 0a086f0bf0f5f1f0b9fde7c9e971c096cb1708cb /src | |
parent | e8b0eae09e531674fb6cd7ea0b341f77ae551aa2 (diff) | |
parent | a7ef1cd35e9347a285f245041db4eb94047f4ab0 (diff) | |
download | servo-943ab4a4f0e3074e78d96ad94b7e96a46edacf79.tar.gz servo-943ab4a4f0e3074e78d96ad94b7e96a46edacf79.zip |
auto merge of #1473 : metajack/servo/rustup-20131219, r=jdm
Diffstat (limited to 'src')
125 files changed, 1864 insertions, 2473 deletions
diff --git a/src/compiler/rust b/src/compiler/rust -Subproject f6b236b9d2780edc1336ea5f62c2ba0fed6e34c +Subproject d3b3c66a3a54a0455b068ede8fe2f48ed99ca90 diff --git a/src/compiler/rust-auto-clean-trigger b/src/compiler/rust-auto-clean-trigger index 6474e73f600..da7e8de4e9a 100644 --- a/src/compiler/rust-auto-clean-trigger +++ b/src/compiler/rust-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then rust will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2014-01-02 +2014-01-08 diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs index 5a5300aabf3..7a5004c0325 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list.rs @@ -150,14 +150,14 @@ pub struct ClipDisplayItem<E> { need_clip: bool } -pub enum DisplayItemIterator<'self,E> { +pub enum DisplayItemIterator<'a,E> { EmptyDisplayItemIterator, - ParentDisplayItemIterator(VecIterator<'self,DisplayItem<E>>), + ParentDisplayItemIterator(VecIterator<'a,DisplayItem<E>>), } -impl<'self,E> Iterator<&'self DisplayItem<E>> for DisplayItemIterator<'self,E> { +impl<'a,E> Iterator<&'a DisplayItem<E>> for DisplayItemIterator<'a,E> { #[inline] - fn next(&mut self) -> Option<&'self DisplayItem<E>> { + fn next(&mut self) -> Option<&'a DisplayItem<E>> { match *self { EmptyDisplayItemIterator => None, ParentDisplayItemIterator(ref mut subiterator) => subiterator.next(), @@ -192,12 +192,12 @@ impl<E> DisplayItem<E> { let text_run = text.text_run.get(); let font = render_context.font_ctx.get_font_by_descriptor(&text_run.font_descriptor).unwrap(); - let font_metrics = font.with_borrow( |font| { + let font_metrics = font.borrow().with(|font| { font.metrics.clone() }); let origin = text.base.bounds.origin; let baseline_origin = Point2D(origin.x, origin.y + font_metrics.ascent); - font.with_mut_borrow( |font| { + font.borrow().with_mut(|font| { font.draw_text_into_context(render_context, text.text_run.get(), &text.range, @@ -264,10 +264,10 @@ impl<E> DisplayItem<E> { pub fn children<'a>(&'a self) -> DisplayItemIterator<'a,E> { match *self { ClipDisplayItemClass(ref clip) => ParentDisplayItemIterator(clip.child_list.iter()), - SolidColorDisplayItemClass(*) | - TextDisplayItemClass(*) | - ImageDisplayItemClass(*) | - BorderDisplayItemClass(*) => EmptyDisplayItemIterator, + SolidColorDisplayItemClass(..) | + TextDisplayItemClass(..) | + ImageDisplayItemClass(..) | + BorderDisplayItemClass(..) => EmptyDisplayItemIterator, } } diff --git a/src/components/gfx/font.rs b/src/components/gfx/font.rs index ac2d45b6f2b..9c1e729bc12 100644 --- a/src/components/gfx/font.rs +++ b/src/components/gfx/font.rs @@ -10,13 +10,11 @@ use geom::{Point2D, Rect, Size2D}; use std::cast; use std::ptr; use std::str; -use std::vec; -use std::rc::RcMut; +use std::rc::Rc; +use std::cell::RefCell; use servo_util::cache::{Cache, HashCache}; use servo_util::range::Range; -use servo_util::time::ProfilerChan; use style::computed_values::{text_decoration, font_weight, font_style}; - use color::Color; use font_context::FontContext; use servo_util::geometry::Au; @@ -73,7 +71,7 @@ impl FontTableTagConversions for FontTableTag { } pub trait FontTableMethods { - fn with_buffer(&self, &fn(*u8, uint)); + fn with_buffer(&self, |*u8, uint|); } #[deriving(Clone)] @@ -108,12 +106,6 @@ pub struct FontStyle { pub type SpecifiedFontStyle = FontStyle; pub type UsedFontStyle = FontStyle; -// FIXME: move me to layout -struct ResolvedFont { - group: @FontGroup, - style: SpecifiedFontStyle, -} - // FontDescriptor serializes a specific font and used font style // options, such as point size. @@ -153,11 +145,11 @@ pub struct FontGroup { // style of the first western font in group, which is // used for purposes of calculating text run metrics. style: UsedFontStyle, - fonts: ~[RcMut<Font>] + fonts: ~[Rc<RefCell<Font>>] } impl FontGroup { - pub fn new(families: ~[~str], style: &UsedFontStyle, fonts: ~[RcMut<Font>]) -> FontGroup { + pub fn new(families: ~[~str], style: &UsedFontStyle, fonts: ~[Rc<RefCell<Font>>]) -> FontGroup { FontGroup { families: families, style: (*style).clone(), @@ -173,7 +165,7 @@ impl FontGroup { assert!(self.fonts.len() > 0); // TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable. - self.fonts[0].with_mut_borrow(|font| { + self.fonts[0].borrow().with_mut(|font| { TextRun::new(font, text.clone(), decoration) }) } @@ -218,18 +210,16 @@ pub struct Font { style: UsedFontStyle, metrics: FontMetrics, backend: BackendType, - profiler_chan: ProfilerChan, shape_cache: HashCache<~str, Arc<GlyphStore>>, glyph_advance_cache: HashCache<u32, FractionalPixel>, } -impl<'self> Font { +impl<'a> Font { pub fn new_from_buffer(ctx: &FontContext, buffer: ~[u8], style: &SpecifiedFontStyle, - backend: BackendType, - profiler_chan: ProfilerChan) - -> Result<RcMut<Font>, ()> { + backend: BackendType) + -> Result<Rc<RefCell<Font>>, ()> { let handle = FontHandleMethods::new_from_buffer(&ctx.handle, buffer, style); let handle: FontHandle = if handle.is_ok() { handle.unwrap() @@ -240,22 +230,21 @@ impl<'self> Font { let metrics = handle.get_metrics(); // TODO(Issue #179): convert between specified and used font style here? - return Ok(RcMut::new(Font { + return Ok(Rc::from_mut(RefCell::new(Font { handle: handle, azure_font: None, shaper: None, style: (*style).clone(), metrics: metrics, backend: backend, - profiler_chan: profiler_chan, shape_cache: HashCache::new(), glyph_advance_cache: HashCache::new(), - })); + }))); } pub fn new_from_adopted_handle(_fctx: &FontContext, handle: FontHandle, - style: &SpecifiedFontStyle, backend: BackendType, - profiler_chan: ProfilerChan) -> Font { + style: &SpecifiedFontStyle, backend: BackendType) + -> Font { let metrics = handle.get_metrics(); Font { @@ -265,15 +254,14 @@ impl<'self> Font { style: (*style).clone(), metrics: metrics, backend: backend, - profiler_chan: profiler_chan, shape_cache: HashCache::new(), glyph_advance_cache: HashCache::new(), } } pub fn new_from_existing_handle(fctx: &FontContext, handle: &FontHandle, - style: &SpecifiedFontStyle, backend: BackendType, - profiler_chan: ProfilerChan) -> Result<RcMut<Font>,()> { + style: &SpecifiedFontStyle, backend: BackendType) + -> Result<Rc<RefCell<Font>>,()> { // TODO(Issue #179): convert between specified and used font style here? let styled_handle = match handle.clone_with_style(&fctx.handle, style) { @@ -281,15 +269,15 @@ impl<'self> Font { Err(()) => return Err(()) }; - return Ok(RcMut::new(Font::new_from_adopted_handle(fctx, styled_handle, style, backend, profiler_chan))); + return Ok(Rc::from_mut(RefCell::new(Font::new_from_adopted_handle(fctx, styled_handle, style, backend)))); } - fn make_shaper(&'self mut self) -> &'self Shaper { + fn make_shaper(&'a mut self) -> &'a Shaper { // fast path: already created a shaper match self.shaper { - Some(ref shaper) => { - let s: &'self Shaper = shaper; - return s; + Some(ref shaper) => { + let s: &'a Shaper = shaper; + return s; }, None => {} } @@ -349,7 +337,6 @@ impl<'self> Font { impl Font { - #[fixed_stack_segment] pub fn draw_text_into_context(&mut self, rctx: &RenderContext, run: &~TextRun, @@ -399,8 +386,8 @@ impl Font { if azglyph_buf_len == 0 { return; } // Otherwise the Quartz backend will assert. let glyphbuf = struct__AzGlyphBuffer { - mGlyphs: vec::raw::to_ptr(azglyphs), - mNumGlyphs: azglyph_buf_len as uint32_t + mGlyphs: azglyphs.as_ptr(), + mNumGlyphs: azglyph_buf_len as uint32_t }; unsafe { @@ -441,11 +428,11 @@ impl Font { //FIXME (ksh8281) self.make_shaper(); - do self.shape_cache.find_or_create(&text) |txt| { + self.shape_cache.find_or_create(&text, |txt| { let mut glyphs = GlyphStore::new(text.char_len(), is_whitespace); self.shaper.get_ref().shape_text(*txt, &mut glyphs); Arc::new(glyphs) - } + }) } pub fn get_descriptor(&self) -> FontDescriptor { @@ -457,12 +444,12 @@ impl Font { } pub fn glyph_h_advance(&mut self, glyph: GlyphIndex) -> FractionalPixel { - do self.glyph_advance_cache.find_or_create(&glyph) |glyph| { + self.glyph_advance_cache.find_or_create(&glyph, |glyph| { match self.handle.glyph_h_advance(*glyph) { Some(adv) => adv, None => /* FIXME: Need fallback strategy */ 10f64 as FractionalPixel } - } + }) } } diff --git a/src/components/gfx/font_context.rs b/src/components/gfx/font_context.rs index 2ed981994da..a465df11ffd 100644 --- a/src/components/gfx/font_context.rs +++ b/src/components/gfx/font_context.rs @@ -15,7 +15,8 @@ use platform::font_context::FontContextHandle; use azure::azure_hl::BackendType; use std::hashmap::HashMap; -use std::rc::RcMut; +use std::rc::Rc; +use std::cell::RefCell; pub trait FontContextHandleMethods { @@ -23,16 +24,16 @@ pub trait FontContextHandleMethods { } pub struct FontContext { - instance_cache: LRUCache<FontDescriptor, RcMut<Font>>, + instance_cache: LRUCache<FontDescriptor, Rc<RefCell<Font>>>, font_list: Option<FontList>, // only needed by layout - group_cache: LRUCache<SpecifiedFontStyle, RcMut<FontGroup>>, + group_cache: LRUCache<SpecifiedFontStyle, Rc<RefCell<FontGroup>>>, handle: FontContextHandle, backend: BackendType, generic_fonts: HashMap<~str,~str>, profiler_chan: ProfilerChan, } -impl<'self> FontContext { +impl FontContext { pub fn new(backend: BackendType, needs_font_list: bool, profiler_chan: ProfilerChan) @@ -61,11 +62,8 @@ impl<'self> FontContext { } } - fn get_font_list(&'self self) -> &'self FontList { - self.font_list.get_ref() - } - - pub fn get_resolved_font_for_style(&mut self, style: &SpecifiedFontStyle) -> RcMut<FontGroup> { + pub fn get_resolved_font_for_style(&mut self, style: &SpecifiedFontStyle) + -> Rc<RefCell<FontGroup>> { match self.group_cache.find(style) { Some(fg) => { debug!("font group cache hit"); @@ -80,7 +78,8 @@ impl<'self> FontContext { } } - pub fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) -> Result<RcMut<Font>, ()> { + pub fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) + -> Result<Rc<RefCell<Font>>, ()> { match self.instance_cache.find(desc) { Some(f) => { debug!("font cache hit"); @@ -107,7 +106,7 @@ impl<'self> FontContext { } } - fn create_font_group(&mut self, style: &SpecifiedFontStyle) -> RcMut<FontGroup> { + fn create_font_group(&mut self, style: &SpecifiedFontStyle) -> Rc<RefCell<FontGroup>> { let mut fonts = ~[]; debug!("(create font group) --- starting ---"); @@ -140,8 +139,7 @@ impl<'self> FontContext { Some(ref result) => { found = true; let instance = self.get_font_by_descriptor(result); - - for font in instance.iter() { fonts.push(font.clone()); } + instance.map(|font| fonts.push(font.clone())); }, _ => {} } @@ -179,10 +177,7 @@ impl<'self> FontContext { match font_desc { Some(ref fd) => { let instance = self.get_font_by_descriptor(fd); - - for font in instance.iter() { - fonts.push(font.clone()); - } + instance.map(|font| fonts.push(font.clone())); }, None => { } }; @@ -194,22 +189,28 @@ impl<'self> FontContext { debug!("(create font group) --- finished ---"); - unsafe { RcMut::new_unchecked(FontGroup::new(style.families.clone(), &used_style, fonts)) } + unsafe { + Rc::new_unchecked( + RefCell::new( + FontGroup::new(style.families.to_owned(), &used_style, fonts))) + } } - fn create_font_instance(&self, desc: &FontDescriptor) -> Result<RcMut<Font>, ()> { + fn create_font_instance(&self, desc: &FontDescriptor) -> Result<Rc<RefCell<Font>>, ()> { return match &desc.selector { // TODO(Issue #174): implement by-platform-name font selectors. &SelectorPlatformIdentifier(ref identifier) => { let result_handle = self.handle.create_font_from_identifier((*identifier).clone(), desc.style.clone()); - do result_handle.and_then |handle| { - Ok(RcMut::new(Font::new_from_adopted_handle(self, - handle, - &desc.style, - self.backend, - self.profiler_chan.clone()))) - } + result_handle.and_then(|handle| { + Ok( + Rc::from_mut( + RefCell::new( + Font::new_from_adopted_handle(self, + handle, + &desc.style, + self.backend)))) + }) } }; } diff --git a/src/components/gfx/font_list.rs b/src/components/gfx/font_list.rs index f4aba05c140..cb49d90f148 100644 --- a/src/components/gfx/font_list.rs +++ b/src/components/gfx/font_list.rs @@ -29,7 +29,7 @@ pub struct FontList { prof_chan: ProfilerChan, } -impl<'self> FontList { +impl FontList { pub fn new(fctx: &FontContextHandle, prof_chan: ProfilerChan) -> FontList { @@ -48,20 +48,20 @@ impl<'self> FontList { // changed. Does OSX have a notification for this event? // // Should font families with entries be invalidated/refreshed too? - do profile(time::GfxRegenAvailableFontsCategory, self.prof_chan.clone()) { + profile(time::GfxRegenAvailableFontsCategory, self.prof_chan.clone(), || { self.family_map = self.handle.get_available_families(); - } + }); } - pub fn find_font_in_family(&'self mut self, - family_name: &~str, - style: &SpecifiedFontStyle) -> Option<&'self FontEntry> { + pub fn find_font_in_family<'a>(&'a mut self, + family_name: &~str, + style: &SpecifiedFontStyle) -> Option<&'a FontEntry> { // TODO(Issue #188): look up localized font family names if canonical name not found // look up canonical name if self.family_map.contains_key(family_name) { //FIXME call twice!(ksh8281) debug!("FontList: Found font family with name={:s}", family_name.to_str()); - let s: &'self mut FontFamily = self.family_map.get_mut(family_name); + let s: &'a mut FontFamily = self.family_map.get_mut(family_name); // TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'. // if such family exists, try to match style to a font let result = s.find_font_for_style(&mut self.handle, style); @@ -82,13 +82,13 @@ impl<'self> FontList { } } -// Holds a specific font family, and the various -pub struct FontFamily<'self> { +// Holds a specific font family, and the various +pub struct FontFamily { family_name: ~str, entries: ~[FontEntry], } -impl<'self> FontFamily { +impl FontFamily { pub fn new(family_name: &str) -> FontFamily { FontFamily { family_name: family_name.to_str(), @@ -104,8 +104,8 @@ impl<'self> FontFamily { assert!(self.entries.len() > 0) } - pub fn find_font_for_style(&'self mut self, list: &FontListHandle, style: &SpecifiedFontStyle) - -> Option<&'self FontEntry> { + pub fn find_font_for_style<'a>(&'a mut self, list: &FontListHandle, style: &SpecifiedFontStyle) + -> Option<&'a FontEntry> { self.load_family_variations(list); // TODO(Issue #189): optimize lookup for diff --git a/src/components/gfx/gfx.rc b/src/components/gfx/gfx.rc index 0eb60d63fb5..5f30e60b4aa 100644 --- a/src/components/gfx/gfx.rc +++ b/src/components/gfx/gfx.rc @@ -2,10 +2,7 @@ * 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 = "gfx", - vers = "0.1", - uuid = "0106bb54-6ea9-45bf-a39e-a738621f15e5", - url = "http://servo.org/")]; +#[crate_id = "github.com/mozilla/servo#gfx:0.1"]; #[crate_type = "lib"]; #[feature(globs, managed_boxes, macro_rules)]; @@ -16,10 +13,10 @@ extern mod geom; extern mod layers; extern mod stb_image; extern mod png; -extern mod servo_net (name = "net"); -extern mod servo_util (name = "util"); +extern mod servo_net = "net"; +extern mod servo_util = "util"; extern mod style; -extern mod servo_msg (name = "msg"); +extern mod servo_msg = "msg"; // Eventually we would like the shaper to be pluggable, as many operating systems have their own // shapers. For now, however, this is a hard dependency. diff --git a/src/components/gfx/opts.rs b/src/components/gfx/opts.rs index ca9c9cc815b..a58b6ed4291 100644 --- a/src/components/gfx/opts.rs +++ b/src/components/gfx/opts.rs @@ -113,9 +113,9 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts { }; // if only flag is present, default to 5 second period - let profiler_period = do opt_match.opt_default("p", "5").map |period| { + let profiler_period = opt_match.opt_default("p", "5").map(|period| { from_str(period).unwrap() - }; + }); let cpu_painting = opt_match.opt_present("c"); diff --git a/src/components/gfx/platform/android/font.rs b/src/components/gfx/platform/android/font.rs index f8f11eb251d..6df0b9c13c1 100644 --- a/src/components/gfx/platform/android/font.rs +++ b/src/components/gfx/platform/android/font.rs @@ -41,7 +41,7 @@ pub struct FontTable { } impl FontTableMethods for FontTable { - fn with_buffer(&self, _blk: &fn(*u8, uint)) { + fn with_buffer(&self, _blk: |*u8, uint|) { fail!() } } @@ -61,7 +61,6 @@ pub struct FontHandle { #[unsafe_destructor] impl Drop for FontHandle { - #[fixed_stack_segment] fn drop(&mut self) { assert!(self.face.is_not_null()); unsafe { @@ -80,9 +79,7 @@ impl FontHandleMethods for FontHandle { let ft_ctx: FT_Library = fctx.ctx.borrow().ctx; if ft_ctx.is_null() { return Err(()); } - let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| { - create_face_from_buffer(ft_ctx, bytes, len, style.pt_size) - }; + let face_result = create_face_from_buffer(ft_ctx, buf.as_ptr(), buf.len(), style.pt_size); // TODO: this could be more simply written as result::chain // and moving buf into the struct ctor, but cant' move out of @@ -99,7 +96,6 @@ impl FontHandleMethods for FontHandle { Err(()) => Err(()) }; - #[fixed_stack_segment] fn create_face_from_buffer(lib: FT_Library, cbuf: *u8, cbuflen: uint, pt_size: f64) -> Result<FT_Face, ()> { unsafe { @@ -129,14 +125,12 @@ impl FontHandleMethods for FontHandle { fn family_name(&self) -> ~str { unsafe { str::raw::from_c_str((*self.face).family_name) } } - #[fixed_stack_segment] fn face_name(&self) -> ~str { unsafe { str::raw::from_c_str(FT_Get_Postscript_Name(self.face)) } } fn is_italic(&self) -> bool { unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC != 0 } } - #[fixed_stack_segment] fn boldness(&self) -> font_weight::T { let default_weight = font_weight::Weight400; if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD == 0 } { @@ -179,7 +173,6 @@ impl FontHandleMethods for FontHandle { } } - #[fixed_stack_segment] fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> { assert!(self.face.is_not_null()); @@ -194,7 +187,6 @@ impl FontHandleMethods for FontHandle { } } - #[fixed_stack_segment] fn glyph_h_advance(&self, glyph: GlyphIndex) -> Option<FractionalPixel> { assert!(self.face.is_not_null()); @@ -216,7 +208,6 @@ impl FontHandleMethods for FontHandle { } } - #[fixed_stack_segment] fn get_metrics(&self) -> FontMetrics { /* TODO(Issue #76): complete me */ let face = self.get_face_rec(); @@ -272,8 +263,7 @@ impl FontHandleMethods for FontHandle { } } -impl<'self> FontHandle { - #[fixed_stack_segment] +impl<'a> FontHandle { fn set_char_size(face: FT_Face, pt_size: f64) -> Result<(), ()>{ let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6; let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6; @@ -286,7 +276,6 @@ impl<'self> FontHandle { } } - #[fixed_stack_segment] pub fn new_from_file(fctx: &FontContextHandle, file: &str, style: &SpecifiedFontStyle) -> Result<FontHandle, ()> { unsafe { @@ -295,10 +284,10 @@ impl<'self> FontHandle { let mut face: FT_Face = ptr::null(); let face_index = 0 as FT_Long; - do file.to_c_str().with_ref |file_str| { + file.to_c_str().with_ref(|file_str| { FT_New_Face(ft_ctx, file_str, face_index, ptr::to_mut_unsafe_ptr(&mut face)); - } + }); if face.is_null() { return Err(()); } @@ -314,7 +303,6 @@ impl<'self> FontHandle { } } - #[fixed_stack_segment] pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str) -> Result<FontHandle, ()> { unsafe { @@ -323,10 +311,10 @@ impl<'self> FontHandle { let mut face: FT_Face = ptr::null(); let face_index = 0 as FT_Long; - do file.to_c_str().with_ref |file_str| { + file.to_c_str().with_ref(|file_str| { FT_New_Face(ft_ctx, file_str, face_index, ptr::to_mut_unsafe_ptr(&mut face)); - } + }); if face.is_null() { return Err(()); } @@ -339,7 +327,7 @@ impl<'self> FontHandle { } } - fn get_face_rec(&'self self) -> &'self FT_FaceRec { + fn get_face_rec(&'a self) -> &'a FT_FaceRec { unsafe { &(*self.face) } diff --git a/src/components/gfx/platform/android/font_context.rs b/src/components/gfx/platform/android/font_context.rs index 4b6c74d95c2..3aa9e064281 100644 --- a/src/components/gfx/platform/android/font_context.rs +++ b/src/components/gfx/platform/android/font_context.rs @@ -24,7 +24,6 @@ pub struct FontContextHandle { } impl Drop for FreeTypeLibraryHandle { - #[fixed_stack_segment] fn drop(&mut self) { assert!(self.ctx.is_not_null()); unsafe { FT_Done_FreeType(self.ctx) }; @@ -32,7 +31,6 @@ impl Drop for FreeTypeLibraryHandle { } impl FontContextHandle { - #[fixed_stack_segment] pub fn new() -> FontContextHandle { unsafe { let ctx: FT_Library = ptr::null(); @@ -49,10 +47,10 @@ impl FontContextHandleMethods for FontContextHandle { fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle) -> Result<FontHandle, ()> { debug!("Creating font handle for {:s}", name); - do path_from_identifier(name, &style).and_then |file_name| { + path_from_identifier(name, &style).and_then(|file_name| { debug!("Opening font face {:s}", file_name); FontHandle::new_from_file(self, file_name.to_owned(), &style) - } + }) } } diff --git a/src/components/gfx/platform/android/font_list.rs b/src/components/gfx/platform/android/font_list.rs index b547fb7ca83..132f98c4641 100644 --- a/src/components/gfx/platform/android/font_list.rs +++ b/src/components/gfx/platform/android/font_list.rs @@ -40,7 +40,6 @@ impl FontListHandle { FontListHandle { fctx: fctx.clone() } } - #[fixed_stack_segment] pub fn get_available_families(&self) -> FontFamilyMap { let mut family_map : FontFamilyMap = HashMap::new(); unsafe { @@ -50,7 +49,7 @@ impl FontListHandle { let font = (*fontSet).fonts.offset(i); let family: *FcChar8 = ptr::null(); let mut v: c_int = 0; - do "family".to_c_str().with_ref |FC_FAMILY| { + "family".to_c_str().with_ref(|FC_FAMILY| { while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch { let family_name = str::raw::from_c_str(family as *c_char); debug!("Creating new FontFamily for family: {:s}", family_name); @@ -58,13 +57,12 @@ impl FontListHandle { family_map.insert(family_name, new_family); v += 1; } - } + }); } } return family_map; } - #[fixed_stack_segment] pub fn load_variations_for_family(&self, family: &mut FontFamily) { debug!("getting variations for {:?}", family); unsafe { @@ -73,22 +71,22 @@ impl FontListHandle { let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set); let pattern = FcPatternCreate(); assert!(pattern.is_not_null()); - do "family".to_c_str().with_ref |FC_FAMILY| { - do family.family_name.to_c_str().with_ref |family_name| { + "family".to_c_str().with_ref(|FC_FAMILY| { + family.family_name.to_c_str().with_ref(|family_name| { let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8); assert!(ok != 0); - } - } + }); + }); let object_set = FcObjectSetCreate(); assert!(object_set.is_not_null()); - do "file".to_c_str().with_ref |FC_FILE| { + "file".to_c_str().with_ref(|FC_FILE| { FcObjectSetAdd(object_set, FC_FILE); - } - do "index".to_c_str().with_ref |FC_INDEX| { + }); + "index".to_c_str().with_ref(|FC_INDEX| { FcObjectSetAdd(object_set, FC_INDEX); - } + }); let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); @@ -96,22 +94,22 @@ impl FontListHandle { for i in range(0, (*matches).nfont as int) { let font = (*matches).fonts.offset(i); - let file = do "file".to_c_str().with_ref |FC_FILE| { + let file = "file".to_c_str().with_ref(|FC_FILE| { let file: *FcChar8 = ptr::null(); if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch { str::raw::from_c_str(file as *libc::c_char) } else { fail!(); } - }; - let index = do "index".to_c_str().with_ref |FC_INDEX| { + }); + let index = "index".to_c_str().with_ref(|FC_INDEX| { let index: libc::c_int = 0; if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch { index } else { fail!(); } - }; + }); debug!("variation file: {}", file); debug!("variation index: {}", index); @@ -141,7 +139,6 @@ struct AutoPattern { } impl Drop for AutoPattern { - #[fixed_stack_segment] fn drop(&mut self) { unsafe { FcPatternDestroy(self.pattern); @@ -149,17 +146,16 @@ impl Drop for AutoPattern { } } -#[fixed_stack_segment] pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ()> { unsafe { let config = FcConfigGetCurrent(); let wrapper = AutoPattern { pattern: FcPatternCreate() }; let pattern = wrapper.pattern; - let res = do "family".to_c_str().with_ref |FC_FAMILY| { - do name.to_c_str().with_ref |family| { + let res = "family".to_c_str().with_ref(|FC_FAMILY| { + name.to_c_str().with_ref(|family| { FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8) - } - }; + }) + }); if res != 1 { debug!("adding family to pattern failed"); return Err(()); @@ -168,18 +164,18 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ( match style.style { font_style::normal => (), font_style::italic => { - let res = do "slant".to_c_str().with_ref |FC_SLANT| { + let res = "slant".to_c_str().with_ref(|FC_SLANT| { FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC) - }; + }); if res != 1 { debug!("adding slant to pattern failed"); return Err(()); } }, font_style::oblique => { - let res = do "slant".to_c_str().with_ref |FC_SLANT| { + let res = "slant".to_c_str().with_ref(|FC_SLANT| { FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_OBLIQUE) - }; + }); if res != 1 { debug!("adding slant(oblique) to pattern failed"); return Err(()); @@ -188,9 +184,9 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ( } if style.weight.is_bold() { - let res = do "weight".to_c_str().with_ref |FC_WEIGHT| { + let res = "weight".to_c_str().with_ref(|FC_WEIGHT| { FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD) - }; + }); if res != 1 { debug!("adding weight to pattern failed"); return Err(()); @@ -211,9 +207,9 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ( } let file: *FcChar8 = ptr::null(); - let res = do "file".to_c_str().with_ref |FC_FILE| { + let res = "file".to_c_str().with_ref(|FC_FILE| { FcPatternGetString(result_pattern, FC_FILE, 0, &file) - }; + }); if res != FcResultMatch { debug!("getting filename for font failed"); return Err(()); diff --git a/src/components/gfx/platform/linux/font.rs b/src/components/gfx/platform/linux/font.rs index f8f11eb251d..6df0b9c13c1 100644 --- a/src/components/gfx/platform/linux/font.rs +++ b/src/components/gfx/platform/linux/font.rs @@ -41,7 +41,7 @@ pub struct FontTable { } impl FontTableMethods for FontTable { - fn with_buffer(&self, _blk: &fn(*u8, uint)) { + fn with_buffer(&self, _blk: |*u8, uint|) { fail!() } } @@ -61,7 +61,6 @@ pub struct FontHandle { #[unsafe_destructor] impl Drop for FontHandle { - #[fixed_stack_segment] fn drop(&mut self) { assert!(self.face.is_not_null()); unsafe { @@ -80,9 +79,7 @@ impl FontHandleMethods for FontHandle { let ft_ctx: FT_Library = fctx.ctx.borrow().ctx; if ft_ctx.is_null() { return Err(()); } - let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| { - create_face_from_buffer(ft_ctx, bytes, len, style.pt_size) - }; + let face_result = create_face_from_buffer(ft_ctx, buf.as_ptr(), buf.len(), style.pt_size); // TODO: this could be more simply written as result::chain // and moving buf into the struct ctor, but cant' move out of @@ -99,7 +96,6 @@ impl FontHandleMethods for FontHandle { Err(()) => Err(()) }; - #[fixed_stack_segment] fn create_face_from_buffer(lib: FT_Library, cbuf: *u8, cbuflen: uint, pt_size: f64) -> Result<FT_Face, ()> { unsafe { @@ -129,14 +125,12 @@ impl FontHandleMethods for FontHandle { fn family_name(&self) -> ~str { unsafe { str::raw::from_c_str((*self.face).family_name) } } - #[fixed_stack_segment] fn face_name(&self) -> ~str { unsafe { str::raw::from_c_str(FT_Get_Postscript_Name(self.face)) } } fn is_italic(&self) -> bool { unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC != 0 } } - #[fixed_stack_segment] fn boldness(&self) -> font_weight::T { let default_weight = font_weight::Weight400; if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD == 0 } { @@ -179,7 +173,6 @@ impl FontHandleMethods for FontHandle { } } - #[fixed_stack_segment] fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> { assert!(self.face.is_not_null()); @@ -194,7 +187,6 @@ impl FontHandleMethods for FontHandle { } } - #[fixed_stack_segment] fn glyph_h_advance(&self, glyph: GlyphIndex) -> Option<FractionalPixel> { assert!(self.face.is_not_null()); @@ -216,7 +208,6 @@ impl FontHandleMethods for FontHandle { } } - #[fixed_stack_segment] fn get_metrics(&self) -> FontMetrics { /* TODO(Issue #76): complete me */ let face = self.get_face_rec(); @@ -272,8 +263,7 @@ impl FontHandleMethods for FontHandle { } } -impl<'self> FontHandle { - #[fixed_stack_segment] +impl<'a> FontHandle { fn set_char_size(face: FT_Face, pt_size: f64) -> Result<(), ()>{ let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6; let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6; @@ -286,7 +276,6 @@ impl<'self> FontHandle { } } - #[fixed_stack_segment] pub fn new_from_file(fctx: &FontContextHandle, file: &str, style: &SpecifiedFontStyle) -> Result<FontHandle, ()> { unsafe { @@ -295,10 +284,10 @@ impl<'self> FontHandle { let mut face: FT_Face = ptr::null(); let face_index = 0 as FT_Long; - do file.to_c_str().with_ref |file_str| { + file.to_c_str().with_ref(|file_str| { FT_New_Face(ft_ctx, file_str, face_index, ptr::to_mut_unsafe_ptr(&mut face)); - } + }); if face.is_null() { return Err(()); } @@ -314,7 +303,6 @@ impl<'self> FontHandle { } } - #[fixed_stack_segment] pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str) -> Result<FontHandle, ()> { unsafe { @@ -323,10 +311,10 @@ impl<'self> FontHandle { let mut face: FT_Face = ptr::null(); let face_index = 0 as FT_Long; - do file.to_c_str().with_ref |file_str| { + file.to_c_str().with_ref(|file_str| { FT_New_Face(ft_ctx, file_str, face_index, ptr::to_mut_unsafe_ptr(&mut face)); - } + }); if face.is_null() { return Err(()); } @@ -339,7 +327,7 @@ impl<'self> FontHandle { } } - fn get_face_rec(&'self self) -> &'self FT_FaceRec { + fn get_face_rec(&'a self) -> &'a FT_FaceRec { unsafe { &(*self.face) } diff --git a/src/components/gfx/platform/linux/font_context.rs b/src/components/gfx/platform/linux/font_context.rs index 4b6c74d95c2..3aa9e064281 100644 --- a/src/components/gfx/platform/linux/font_context.rs +++ b/src/components/gfx/platform/linux/font_context.rs @@ -24,7 +24,6 @@ pub struct FontContextHandle { } impl Drop for FreeTypeLibraryHandle { - #[fixed_stack_segment] fn drop(&mut self) { assert!(self.ctx.is_not_null()); unsafe { FT_Done_FreeType(self.ctx) }; @@ -32,7 +31,6 @@ impl Drop for FreeTypeLibraryHandle { } impl FontContextHandle { - #[fixed_stack_segment] pub fn new() -> FontContextHandle { unsafe { let ctx: FT_Library = ptr::null(); @@ -49,10 +47,10 @@ impl FontContextHandleMethods for FontContextHandle { fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle) -> Result<FontHandle, ()> { debug!("Creating font handle for {:s}", name); - do path_from_identifier(name, &style).and_then |file_name| { + path_from_identifier(name, &style).and_then(|file_name| { debug!("Opening font face {:s}", file_name); FontHandle::new_from_file(self, file_name.to_owned(), &style) - } + }) } } diff --git a/src/components/gfx/platform/linux/font_list.rs b/src/components/gfx/platform/linux/font_list.rs index 61838a44683..7fbc7323f68 100644 --- a/src/components/gfx/platform/linux/font_list.rs +++ b/src/components/gfx/platform/linux/font_list.rs @@ -40,7 +40,6 @@ impl FontListHandle { FontListHandle { fctx: fctx.clone() } } - #[fixed_stack_segment] pub fn get_available_families(&self) -> FontFamilyMap { let mut family_map : FontFamilyMap = HashMap::new(); unsafe { @@ -50,7 +49,7 @@ impl FontListHandle { let font = (*fontSet).fonts.offset(i); let family: *FcChar8 = ptr::null(); let mut v: c_int = 0; - do "family".to_c_str().with_ref |FC_FAMILY| { + "family".to_c_str().with_ref(|FC_FAMILY| { while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch { let family_name = str::raw::from_c_str(family as *c_char); debug!("Creating new FontFamily for family: {:s}", family_name); @@ -58,13 +57,12 @@ impl FontListHandle { family_map.insert(family_name, new_family); v += 1; } - } + }); } } return family_map; } - #[fixed_stack_segment] pub fn load_variations_for_family(&self, family: &mut FontFamily) { debug!("getting variations for {:?}", family); unsafe { @@ -73,22 +71,22 @@ impl FontListHandle { let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set); let pattern = FcPatternCreate(); assert!(pattern.is_not_null()); - do "family".to_c_str().with_ref |FC_FAMILY| { - do family.family_name.to_c_str().with_ref |family_name| { + "family".to_c_str().with_ref(|FC_FAMILY| { + family.family_name.to_c_str().with_ref(|family_name| { let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8); assert!(ok != 0); - } - } + }); + }); let object_set = FcObjectSetCreate(); assert!(object_set.is_not_null()); - do "file".to_c_str().with_ref |FC_FILE| { + "file".to_c_str().with_ref(|FC_FILE| { FcObjectSetAdd(object_set, FC_FILE); - } - do "index".to_c_str().with_ref |FC_INDEX| { + }); + "index".to_c_str().with_ref(|FC_INDEX| { FcObjectSetAdd(object_set, FC_INDEX); - } + }); let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set); @@ -96,22 +94,22 @@ impl FontListHandle { for i in range(0, (*matches).nfont as int) { let font = (*matches).fonts.offset(i); - let file = do "file".to_c_str().with_ref |FC_FILE| { + let file = "file".to_c_str().with_ref(|FC_FILE| { let file: *FcChar8 = ptr::null(); if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch { str::raw::from_c_str(file as *libc::c_char) } else { fail!(); } - }; - let index = do "index".to_c_str().with_ref |FC_INDEX| { + }); + let index = "index".to_c_str().with_ref(|FC_INDEX| { let index: libc::c_int = 0; if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch { index } else { fail!(); } - }; + }); debug!("variation file: {}", file); debug!("variation index: {}", index); @@ -141,7 +139,6 @@ struct AutoPattern { } impl Drop for AutoPattern { - #[fixed_stack_segment] fn drop(&mut self) { unsafe { FcPatternDestroy(self.pattern); @@ -149,17 +146,16 @@ impl Drop for AutoPattern { } } -#[fixed_stack_segment] pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ()> { unsafe { let config = FcConfigGetCurrent(); let wrapper = AutoPattern { pattern: FcPatternCreate() }; let pattern = wrapper.pattern; - let res = do "family".to_c_str().with_ref |FC_FAMILY| { - do name.to_c_str().with_ref |family| { + let res = "family".to_c_str().with_ref(|FC_FAMILY| { + name.to_c_str().with_ref(|family| { FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8) - } - }; + }) + }); if res != 1 { debug!("adding family to pattern failed"); return Err(()); @@ -168,18 +164,18 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ( match style.style { font_style::normal => (), font_style::italic => { - let res = do "slant".to_c_str().with_ref |FC_SLANT| { + let res = "slant".to_c_str().with_ref(|FC_SLANT| { FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC) - }; + }); if res != 1 { debug!("adding slant to pattern failed"); return Err(()); } }, font_style::oblique => { - let res = do "slant".to_c_str().with_ref |FC_SLANT| { + let res = "slant".to_c_str().with_ref(|FC_SLANT| { FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_OBLIQUE) - }; + }); if res != 1 { debug!("adding slant(oblique) to pattern failed"); return Err(()); @@ -188,9 +184,9 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ( } if style.weight.is_bold() { - let res = do "weight".to_c_str().with_ref |FC_WEIGHT| { + let res = "weight".to_c_str().with_ref(|FC_WEIGHT| { FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD) - }; + }); if res != 1 { debug!("adding weight to pattern failed"); return Err(()); @@ -211,9 +207,9 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ( } let file: *FcChar8 = ptr::null(); - let res = do "file".to_c_str().with_ref |FC_FILE| { + let res = "file".to_c_str().with_ref(|FC_FILE| { FcPatternGetString(result_pattern, FC_FILE, 0, &file) - }; + }); if res != FcResultMatch { debug!("getting filename for font failed"); return Err(()); diff --git a/src/components/gfx/platform/macos/font.rs b/src/components/gfx/platform/macos/font.rs index 3b6b60e9235..e3b292b2a63 100644 --- a/src/components/gfx/platform/macos/font.rs +++ b/src/components/gfx/platform/macos/font.rs @@ -29,7 +29,6 @@ use core_text::font_descriptor::{kCTFontDefaultOrientation}; use core_text; use std::ptr; -use std::vec; pub struct FontTable { data: CFData, @@ -47,8 +46,8 @@ impl FontTable { } impl FontTableMethods for FontTable { - fn with_buffer(&self, blk: &fn(*u8, uint)) { - blk(vec::raw::to_ptr(self.data.bytes()), self.data.len() as uint); + fn with_buffer(&self, blk: |*u8, uint|) { + blk(self.data.bytes().as_ptr(), self.data.len() as uint); } } @@ -185,9 +184,9 @@ impl FontHandleMethods for FontHandle { fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> { let result: Option<CFData> = self.ctfont.get_font_table(tag); - do result.and_then |data| { + result.and_then(|data| { Some(FontTable::wrap(data)) - } + }) } fn face_identifier(&self) -> ~str { diff --git a/src/components/gfx/platform/macos/font_context.rs b/src/components/gfx/platform/macos/font_context.rs index 4a4afe6cefb..ef9ea06c447 100644 --- a/src/components/gfx/platform/macos/font_context.rs +++ b/src/components/gfx/platform/macos/font_context.rs @@ -27,8 +27,8 @@ impl FontContextHandleMethods for FontContextHandle { style: UsedFontStyle) -> Result<FontHandle, ()> { let ctfont_result = core_text::font::new_from_name(name, style.pt_size); - do ctfont_result.and_then |ctfont| { + ctfont_result.and_then(|ctfont| { FontHandle::new_from_CTFont(self, ctfont) - } + }) } } diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index d13d709acce..fc12c1133fc 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -18,14 +18,13 @@ use geom::side_offsets::SideOffsets2D; use servo_net::image::base::Image; use png::{RGBA8, K8, KA8}; use servo_util::geometry::Au; -use std::vec; use std::libc::types::common::c99::uint16_t; use std::libc::size_t; -pub struct RenderContext<'self> { - draw_target: &'self DrawTarget, - font_ctx: &'self mut ~FontContext, - opts: &'self Opts, +pub struct RenderContext<'a> { + draw_target: &'a DrawTarget, + font_ctx: &'a mut ~FontContext, + opts: &'a Opts, /// The rectangle that this context encompasses in page coordinates. page_rect: Rect<f32>, /// The rectangle that this context encompasses in screen coordinates (pixels). @@ -39,8 +38,8 @@ enum Direction { Bottom } -impl<'self> RenderContext<'self> { - pub fn get_draw_target(&self) -> &'self DrawTarget { +impl<'a> RenderContext<'a> { + pub fn get_draw_target(&self) -> &'a DrawTarget { self.draw_target } @@ -167,7 +166,7 @@ impl<'self> RenderContext<'self> { stroke_opts.line_width = border_width; dash[0] = border_width * 3 as AzFloat; dash[1] = border_width * 3 as AzFloat; - stroke_opts.mDashPattern = vec::raw::to_ptr(dash); + stroke_opts.mDashPattern = dash.as_ptr(); stroke_opts.mDashLength = dash.len() as size_t; let (start, end) = match direction { diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index 88da24cc396..0f1dd7913c9 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -20,7 +20,6 @@ use servo_util::time::{ProfilerChan, profile}; use servo_util::time; use std::comm::{Chan, Port, SharedChan}; -use std::task::spawn_with; use extra::arc::Arc; use buffer_map::BufferMap; @@ -63,24 +62,32 @@ pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferReq // FIXME(rust#9155): this should be a newtype struct, but // generic newtypes ICE when compiled cross-crate -#[deriving(Clone)] pub struct RenderChan<T> { chan: SharedChan<Msg<T>>, } -impl<T: Send> RenderChan<T> { - pub fn new(chan: Chan<Msg<T>>) -> RenderChan<T> { + +impl<T: Send> Clone for RenderChan<T> { + fn clone(&self) -> RenderChan<T> { RenderChan { - chan: SharedChan::new(chan), + chan: self.chan.clone(), } } } -impl<T: Send> GenericChan<Msg<T>> for RenderChan<T> { - fn send(&self, msg: Msg<T>) { + +impl<T: Send> RenderChan<T> { + pub fn new() -> (Port<Msg<T>>, RenderChan<T>) { + let (port, chan) = SharedChan::new(); + let render_chan = RenderChan { + chan: chan, + }; + (port, render_chan) + } + + pub fn send(&self, msg: Msg<T>) { assert!(self.try_send(msg), "RenderChan.send: render port closed") } -} -impl<T: Send> GenericSmartChan<Msg<T>> for RenderChan<T> { - fn try_send(&self, msg: Msg<T>) -> bool { + + pub fn try_send(&self, msg: Msg<T>) -> bool { self.chan.try_send(msg) } } @@ -138,9 +145,7 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { opts: Opts, profiler_chan: ProfilerChan, shutdown_chan: Chan<()>) { - do spawn_with((port, compositor, constellation_chan, opts, profiler_chan, shutdown_chan)) - |(port, compositor, constellation_chan, opts, profiler_chan, shutdown_chan)| { - + spawn(proc() { { // Ensures RenderTask and graphics context are destroyed before shutdown msg let native_graphics_context = compositor.get_graphics_metadata().map( |md| NativePaintingGraphicsContext::from_metadata(&md)); @@ -153,8 +158,8 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { compositor: compositor, constellation_chan: constellation_chan, font_ctx: ~FontContext::new(opts.render_backend.clone(), - false, - profiler_chan.clone()), + false, + profiler_chan.clone()), opts: opts, profiler_chan: profiler_chan, @@ -176,13 +181,12 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { render_task.start(); // Destroy all the buffers. - render_task.native_graphics_context.as_ref().map(|ctx| - render_task.buffer_map.clear(ctx) - ); + render_task.native_graphics_context.as_ref().map( + |ctx| render_task.buffer_map.clear(ctx)); } shutdown_chan.send(()); - } + }); } fn start(&mut self) { @@ -243,12 +247,12 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { } self.compositor.set_render_state(RenderingRenderState); - do time::profile(time::RenderingCategory, self.profiler_chan.clone()) { + time::profile(time::RenderingCategory, self.profiler_chan.clone(), || { // FIXME: Try not to create a new array here. let mut new_buffers = ~[]; // Divide up the layer into tiles. - do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) { + time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone(), || { for tile in tiles.iter() { let width = tile.screen_rect.size.width; let height = tile.screen_rect.size.height; @@ -293,10 +297,10 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { ctx.clear(); // Draw the display list. - do profile(time::RenderingDrawingCategory, self.profiler_chan.clone()) { + profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || { render_layer.display_list.get().draw_into_context(&mut ctx); ctx.draw_target.flush(); - } + }); } // Extract the texture from the draw target and place it into its slot in the @@ -335,11 +339,11 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { } }; - do draw_target.snapshot().get_data_surface().with_data |data| { + draw_target.snapshot().get_data_surface().with_data(|data| { buffer.native_surface.upload(native_graphics_context!(self), data); debug!("RENDERER uploading to native surface {:d}", buffer.native_surface.get_id() as int); - } + }); buffer } @@ -367,7 +371,7 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { new_buffers.push(buffer); } - } + }); let layer_buffer_set = ~LayerBufferSet { buffers: new_buffers, @@ -380,7 +384,7 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> { self.constellation_chan.send(RendererReadyMsg(self.id)); } self.compositor.set_render_state(IdleRenderState); - } + }) } } diff --git a/src/components/gfx/text/glyph.rs b/src/components/gfx/text/glyph.rs index 6a72582c4d1..541ae815e85 100644 --- a/src/components/gfx/text/glyph.rs +++ b/src/components/gfx/text/glyph.rs @@ -14,7 +14,6 @@ use std::vec; use std::util; use std::iter; use geom::point::Point2D; -use extra::sort; /// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly. /// @@ -149,8 +148,8 @@ static FLAG_NOT_LIGATURE_GROUP_START: u32 = 0x00000004; static FLAG_CHAR_IS_TAB: u32 = 0x00000008; static FLAG_CHAR_IS_NEWLINE: u32 = 0x00000010; -static FLAG_CHAR_IS_LOW_SURROGATE: u32 = 0x00000020; -static CHAR_IDENTITY_FLAGS_MASK: u32 = 0x00000038; +//static FLAG_CHAR_IS_LOW_SURROGATE: u32 = 0x00000020; +//static CHAR_IDENTITY_FLAGS_MASK: u32 = 0x00000038; fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool { ((glyphId as u32) & GLYPH_ID_MASK) == glyphId @@ -176,10 +175,6 @@ impl GlyphEntry { self.value & GLYPH_ID_MASK } - fn offset(&self) -> Point2D<Au> { - Point2D(Au(0), Au(0)) - } - fn is_ligature_start(&self) -> bool { self.has_flag(!FLAG_NOT_LIGATURE_GROUP_START) } @@ -312,7 +307,7 @@ struct DetailedGlyphStore { lookup_is_sorted: bool, } -impl<'self> DetailedGlyphStore { +impl<'a> DetailedGlyphStore { fn new() -> DetailedGlyphStore { DetailedGlyphStore { detail_buffer: ~[], // TODO: default size? @@ -345,8 +340,8 @@ impl<'self> DetailedGlyphStore { self.lookup_is_sorted = false; } - fn get_detailed_glyphs_for_entry(&'self self, entry_offset: uint, count: u16) - -> &'self [DetailedGlyph] { + fn get_detailed_glyphs_for_entry(&'a self, entry_offset: uint, count: u16) + -> &'a [DetailedGlyph] { debug!("Requesting detailed glyphs[n={:u}] for entry[off={:u}]", count as uint, entry_offset); // FIXME: Is this right? --pcwalton @@ -375,10 +370,10 @@ impl<'self> DetailedGlyphStore { } } - fn get_detailed_glyph_with_index(&'self self, + fn get_detailed_glyph_with_index(&'a self, entry_offset: uint, detail_offset: u16) - -> &'self DetailedGlyph { + -> &'a DetailedGlyph { assert!((detail_offset as uint) <= self.detail_buffer.len()); assert!(self.lookup_is_sorted); @@ -411,7 +406,13 @@ impl<'self> DetailedGlyphStore { let mut unsorted_records: ~[DetailedGlyphRecord] = ~[]; util::swap(&mut self.detail_lookup, &mut unsorted_records); let mut mut_records : ~[DetailedGlyphRecord] = unsorted_records; - sort::quick_sort3(mut_records); + mut_records.sort_by(|a, b| { + if a < b { + Less + } else { + Greater + } + }); let mut sorted_records = mut_records; util::swap(&mut self.detail_lookup, &mut sorted_records); @@ -458,12 +459,12 @@ impl GlyphData { // through glyphs (either for a particular TextRun offset, or all glyphs). // Rather than eagerly assembling and copying glyph data, it only retrieves // values as they are needed from the GlyphStore, using provided offsets. -enum GlyphInfo<'self> { - SimpleGlyphInfo(&'self GlyphStore, uint), - DetailGlyphInfo(&'self GlyphStore, uint, u16) +enum GlyphInfo<'a> { + SimpleGlyphInfo(&'a GlyphStore, uint), + DetailGlyphInfo(&'a GlyphStore, uint, u16) } -impl<'self> GlyphInfo<'self> { +impl<'a> GlyphInfo<'a> { pub fn index(self) -> GlyphIndex { match self { SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].index(), @@ -492,20 +493,6 @@ impl<'self> GlyphInfo<'self> { } } } - - pub fn is_ligature_start(self) -> bool { - match self { - SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].is_ligature_start(), - DetailGlyphInfo(store, entry_i, _) => store.entry_buffer[entry_i].is_ligature_start() - } - } - - pub fn is_cluster_start(self) -> bool { - match self { - SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].is_cluster_start(), - DetailGlyphInfo(store, entry_i, _) => store.entry_buffer[entry_i].is_cluster_start() - } - } } // Public data structure and API for storing and retrieving glyph data @@ -519,7 +506,7 @@ pub struct GlyphStore { is_whitespace: bool, } -impl<'self> GlyphStore { +impl<'a> GlyphStore { // Initializes the glyph store, but doesn't actually shape anything. // Use the set_glyph, set_glyphs() methods to store glyph data. pub fn new(length: uint, is_whitespace: bool) -> GlyphStore { @@ -606,12 +593,12 @@ impl<'self> GlyphStore { self.entry_buffer[i] = entry; } - pub fn iter_glyphs_for_char_index(&'self self, i: uint) -> GlyphIterator<'self> { + pub fn iter_glyphs_for_char_index(&'a self, i: uint) -> GlyphIterator<'a> { self.iter_glyphs_for_char_range(&Range::new(i, 1)) } #[inline] - pub fn iter_glyphs_for_char_range(&'self self, rang: &Range) -> GlyphIterator<'self> { + pub fn iter_glyphs_for_char_range(&'a self, rang: &Range) -> GlyphIterator<'a> { if rang.begin() >= self.entry_buffer.len() { fail!("iter_glyphs_for_range: range.begin beyond length!"); } @@ -684,17 +671,17 @@ impl<'self> GlyphStore { } } -pub struct GlyphIterator<'self> { - priv store: &'self GlyphStore, +pub struct GlyphIterator<'a> { + priv store: &'a GlyphStore, priv char_index: uint, priv char_range: iter::Range<uint>, priv glyph_range: Option<iter::Range<uint>>, } -impl<'self> GlyphIterator<'self> { +impl<'a> GlyphIterator<'a> { // Slow path when there is a glyph range. #[inline(never)] - fn next_glyph_range(&mut self) -> Option<(uint, GlyphInfo<'self>)> { + fn next_glyph_range(&mut self) -> Option<(uint, GlyphInfo<'a>)> { match self.glyph_range.get_mut_ref().next() { Some(j) => Some((self.char_index, DetailGlyphInfo(self.store, self.char_index, j as u16))), @@ -709,14 +696,14 @@ impl<'self> GlyphIterator<'self> { // Slow path when there is a complex glyph. #[inline(never)] fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: uint) - -> Option<(uint, GlyphInfo<'self>)> { + -> Option<(uint, GlyphInfo<'a>)> { let glyphs = self.store.detail_store.get_detailed_glyphs_for_entry(i, entry.glyph_count()); self.glyph_range = Some(range(0, glyphs.len())); self.next() } } -impl<'self> Iterator<(uint, GlyphInfo<'self>)> for GlyphIterator<'self> { +impl<'a> Iterator<(uint, GlyphInfo<'a>)> for GlyphIterator<'a> { // I tried to start with something simpler and apply FlatMap, but the // inability to store free variables in the FlatMap struct was problematic. // @@ -724,7 +711,7 @@ impl<'self> Iterator<(uint, GlyphInfo<'self>)> for GlyphIterator<'self> { // slow paths, which should not be inlined, are `next_glyph_range()` and // `next_complex_glyph()`. #[inline(always)] - fn next(&mut self) -> Option<(uint, GlyphInfo<'self>)> { + fn next(&mut self) -> Option<(uint, GlyphInfo<'a>)> { // Would use 'match' here but it borrows contents in a way that // interferes with mutation. if self.glyph_range.is_some() { diff --git a/src/components/gfx/text/shaping/harfbuzz.rs b/src/components/gfx/text/shaping/harfbuzz.rs index d8dc5fd14ae..93d590fba9a 100644 --- a/src/components/gfx/text/shaping/harfbuzz.rs +++ b/src/components/gfx/text/shaping/harfbuzz.rs @@ -10,15 +10,14 @@ use platform::font::FontTable; use text::glyph::{GlyphStore, GlyphIndex, GlyphData}; use text::shaping::ShaperMethods; use servo_util::range::Range; -use text::util::{float_to_fixed, fixed_to_float, fixed_to_rounded_int}; +use text::util::{float_to_fixed, fixed_to_float}; use std::cast::transmute; use std::char; use std::libc::{c_uint, c_int, c_void, c_char}; use std::ptr; use std::ptr::null; -use std::uint; -use std::util::ignore; +use std::num; use std::vec; use geom::Point2D; use harfbuzz::{hb_blob_create, hb_face_create_for_tables}; @@ -63,7 +62,6 @@ pub struct ShapedGlyphEntry { } impl ShapedGlyphData { - #[fixed_stack_segment] pub fn new(buffer: *hb_buffer_t) -> ShapedGlyphData { unsafe { let glyph_count = 0; @@ -143,7 +141,6 @@ pub struct Shaper { #[unsafe_destructor] impl Drop for Shaper { - #[fixed_stack_segment] fn drop(&mut self) { unsafe { assert!(self.hb_face.is_not_null()); @@ -159,7 +156,6 @@ impl Drop for Shaper { } impl Shaper { - #[fixed_stack_segment] pub fn new(font: &mut Font) -> Shaper { unsafe { // Indirection for Rust Issue #6248, dynamic freeze scope artifically extended @@ -200,29 +196,22 @@ impl Shaper { fn fixed_to_float(i: hb_position_t) -> f64 { fixed_to_float(16, i) } - - fn fixed_to_rounded_int(f: hb_position_t) -> int { - fixed_to_rounded_int(16, f) - } } impl ShaperMethods for Shaper { /// Calculate the layout metrics associated with the given text when rendered in a specific /// font. - #[fixed_stack_segment] fn shape_text(&self, text: &str, glyphs: &mut GlyphStore) { unsafe { let hb_buffer: *hb_buffer_t = hb_buffer_create(); hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR); // Using as_imm_buf because it never does a copy - we don't need the trailing null - do text.as_imm_buf |ctext: *u8, _: uint| { - hb_buffer_add_utf8(hb_buffer, - ctext as *c_char, - text.len() as c_int, - 0, - text.len() as c_int); - } + hb_buffer_add_utf8(hb_buffer, + text.as_ptr() as *c_char, + text.len() as c_int, + 0, + text.len() as c_int); hb_shape(self.hb_font, hb_buffer, null(), 0); self.save_glyph_results(text, glyphs, hb_buffer); @@ -261,7 +250,7 @@ impl Shaper { byteToGlyph = vec::from_elem(byte_max, NO_GLYPH); } else { byteToGlyph = vec::from_elem(byte_max, CONTINUATION_BYTE); - for (i, _) in text.char_offset_iter() { + for (i, _) in text.char_indices() { byteToGlyph[i] = NO_GLYPH; } } @@ -283,7 +272,7 @@ impl Shaper { debug!("text: {:s}", text); debug!("(char idx): char->(glyph index):"); - for (i, ch) in text.char_offset_iter() { + for (i, ch) in text.char_indices() { debug!("{:u}: {} --> {:d}", i, ch, byteToGlyph[i] as int); } @@ -309,7 +298,7 @@ impl Shaper { // any trailing chars that do not have associated glyphs. while char_byte_span.end() < byte_max { let range = text.char_range_at(char_byte_span.end()); - ignore(range.ch); + drop(range.ch); char_byte_span.extend_to(range.next); debug!("Processing char byte span: off={:u}, len={:u} for glyph idx={:u}", @@ -320,7 +309,7 @@ impl Shaper { debug!("Extending char byte span to include byte offset={:u} with no associated \ glyph", char_byte_span.end()); let range = text.char_range_at(char_byte_span.end()); - ignore(range.ch); + drop(range.ch); char_byte_span.extend_to(range.next); } @@ -329,7 +318,7 @@ impl Shaper { let mut max_glyph_idx = glyph_span.end(); for i in char_byte_span.eachi() { if byteToGlyph[i] > NO_GLYPH { - max_glyph_idx = uint::max(byteToGlyph[i] as uint + 1, max_glyph_idx); + max_glyph_idx = num::max(byteToGlyph[i] as uint + 1, max_glyph_idx); } } @@ -390,7 +379,7 @@ impl Shaper { while covered_byte_span.end() < byte_max && byteToGlyph[covered_byte_span.end()] == NO_GLYPH { let range = text.char_range_at(covered_byte_span.end()); - ignore(range.ch); + drop(range.ch); covered_byte_span.extend_to(range.next); } @@ -404,7 +393,7 @@ impl Shaper { // clamp to end of text. (I don't think this will be necessary, but..) let end = covered_byte_span.end(); // FIXME: borrow checker workaround - covered_byte_span.extend_to(uint::min(end, byte_max)); + covered_byte_span.extend_to(num::min(end, byte_max)); // fast path: 1-to-1 mapping of single char and single glyph. if glyph_span.length() == 1 { @@ -443,7 +432,7 @@ impl Shaper { let mut i = covered_byte_span.begin(); loop { let range = text.char_range_at(i); - ignore(range.ch); + drop(range.ch); i = range.next; if i >= covered_byte_span.end() { break; } char_idx += 1; @@ -514,14 +503,14 @@ extern fn get_font_table_func(_: *hb_face_t, tag: hb_tag_t, user_data: *c_void) let skinny_font_table_ptr: *FontTable = font_table; // private context let mut blob: *hb_blob_t = null(); - do (*skinny_font_table_ptr).with_buffer |buf: *u8, len: uint| { + (*skinny_font_table_ptr).with_buffer(|buf: *u8, len: uint| { // HarfBuzz calls `destroy_blob_func` when the buffer is no longer needed. blob = hb_blob_create(buf as *c_char, len as c_uint, HB_MEMORY_MODE_READONLY, transmute(skinny_font_table_ptr), destroy_blob_func); - } + }); assert!(blob.is_not_null()); blob diff --git a/src/components/gfx/text/text_run.rs b/src/components/gfx/text/text_run.rs index 2e5a06e5079..0bde3607d3f 100644 --- a/src/components/gfx/text/text_run.rs +++ b/src/components/gfx/text/text_run.rs @@ -22,16 +22,16 @@ pub struct TextRun { glyphs: Arc<~[Arc<GlyphStore>]>, } -pub struct SliceIterator<'self> { - priv glyph_iter: VecIterator<'self, Arc<GlyphStore>>, +pub struct SliceIterator<'a> { + priv glyph_iter: VecIterator<'a, Arc<GlyphStore>>, priv range: Range, priv offset: uint, } -impl<'self> Iterator<(&'self GlyphStore, uint, Range)> for SliceIterator<'self> { +impl<'a> Iterator<(&'a GlyphStore, uint, Range)> for SliceIterator<'a> { // inline(always) due to the inefficient rt failures messing up inline heuristics, I think. #[inline(always)] - fn next(&mut self) -> Option<(&'self GlyphStore, uint, Range)> { + fn next(&mut self) -> Option<(&'a GlyphStore, uint, Range)> { loop { let slice_glyphs = self.glyph_iter.next(); if slice_glyphs.is_none() { @@ -52,13 +52,13 @@ impl<'self> Iterator<(&'self GlyphStore, uint, Range)> for SliceIterator<'self> } } -pub struct LineIterator<'self> { +pub struct LineIterator<'a> { priv range: Range, priv clump: Option<Range>, - priv slices: SliceIterator<'self>, + priv slices: SliceIterator<'a>, } -impl<'self> Iterator<Range> for LineIterator<'self> { +impl<'a> Iterator<Range> for LineIterator<'a> { fn next(&mut self) -> Option<Range> { // Loop until we hit whitespace and are in a clump. loop { @@ -96,7 +96,7 @@ impl<'self> Iterator<Range> for LineIterator<'self> { } } -impl<'self> TextRun { +impl<'a> TextRun { pub fn new(font: &mut Font, text: ~str, decoration: text_decoration::T) -> TextRun { let glyphs = TextRun::break_and_shape(font, text); @@ -170,12 +170,12 @@ impl<'self> TextRun { } pub fn char_len(&self) -> uint { - do self.glyphs.get().iter().fold(0u) |len, slice_glyphs| { + self.glyphs.get().iter().fold(0u, |len, slice_glyphs| { len + slice_glyphs.get().char_len() - } + }) } - pub fn glyphs(&'self self) -> &'self ~[Arc<GlyphStore>] { + pub fn glyphs(&'a self) -> &'a ~[Arc<GlyphStore>] { self.glyphs.get() } @@ -216,7 +216,7 @@ impl<'self> TextRun { max_piece_width } - pub fn iter_slices_for_range(&'self self, range: &Range) -> SliceIterator<'self> { + pub fn iter_slices_for_range(&'a self, range: &Range) -> SliceIterator<'a> { SliceIterator { glyph_iter: self.glyphs.get().iter(), range: *range, @@ -224,7 +224,7 @@ impl<'self> TextRun { } } - pub fn iter_natural_lines_for_range(&'self self, range: &Range) -> LineIterator<'self> { + pub fn iter_natural_lines_for_range(&'a self, range: &Range) -> LineIterator<'a> { LineIterator { range: *range, clump: None, diff --git a/src/components/gfx/text/util.rs b/src/components/gfx/text/util.rs index 7b741e11a6f..924d6273ea0 100644 --- a/src/components/gfx/text/util.rs +++ b/src/components/gfx/text/util.rs @@ -24,7 +24,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo let mut out_str: ~str = ~""; let out_whitespace = match mode { CompressNone | DiscardNewline => { - for ch in text.iter() { + for ch in text.chars() { if is_discardable_char(ch, mode) { // TODO: record skipped char } else { @@ -40,7 +40,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo CompressWhitespace | CompressWhitespaceNewline => { let mut in_whitespace: bool = incoming_whitespace; - for ch in text.iter() { + for ch in text.chars() { // TODO: discard newlines between CJK chars let mut next_in_whitespace: bool = is_in_whitespace(ch, mode); diff --git a/src/components/main/compositing/compositor.rs b/src/components/main/compositing/compositor.rs index f2a86e9ad81..3790664b73f 100644 --- a/src/components/main/compositing/compositor.rs +++ b/src/components/main/compositing/compositor.rs @@ -34,13 +34,11 @@ use png; use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBufferSet, RenderState}; use servo_msg::constellation_msg::{ConstellationChan, NavigateMsg, ResizedWindowMsg, LoadUrlMsg, PipelineId}; use servo_msg::constellation_msg; -use servo_util::time::{profile, ProfilerChan}; +use servo_util::time::{profile, ProfilerChan, Timer}; use servo_util::{time, url}; use std::comm::Port; use std::num::Orderable; use std::path::Path; -use std::rt::io::timer::Timer; -use std::vec; pub struct IOCompositor { @@ -157,11 +155,17 @@ impl IOCompositor { self.constellation_chan.send(ResizedWindowMsg(self.window_size)); // Enter the main event loop. - let mut tm = Timer::new().unwrap(); while !self.done { // Check for new messages coming from the rendering task. self.handle_message(); + if (self.done) { + // We have exited the compositor and passing window + // messages to script may crash. + debug!("Exiting the compositor due to a request from script."); + break; + } + // Check for messages coming from the windowing system. self.handle_window_message(self.window.recv()); @@ -171,7 +175,7 @@ impl IOCompositor { self.composite(); } - tm.sleep(10); + Timer::sleep(10); // If a pinch-zoom happened recently, ask for tiles at the new resolution if self.zoom_action && precise_time_s() - self.zoom_time > 0.3 { @@ -189,62 +193,65 @@ impl IOCompositor { // Drain compositor port, sometimes messages contain channels that are blocking // another task from finishing (i.e. SetIds) - while self.port.peek() { self.port.recv(); } + while self.port.try_recv().is_some() {} } fn handle_message(&mut self) { - while self.port.peek() { - match self.port.recv() { - Exit => { - self.done = true - }, + loop { + match self.port.try_recv() { + None => break, - ChangeReadyState(ready_state) => { + Some(Exit(chan)) => { + self.done = true; + chan.send(()); + } + + Some(ChangeReadyState(ready_state)) => { self.window.set_ready_state(ready_state); } - ChangeRenderState(render_state) => { + Some(ChangeRenderState(render_state)) => { self.change_render_state(render_state); } - SetUnRenderedColor(_id, color) => { + Some(SetUnRenderedColor(_id, color)) => { self.set_unrendered_color(_id, color); } - SetIds(frame_tree, response_chan, new_constellation_chan) => { + Some(SetIds(frame_tree, response_chan, new_constellation_chan)) => { self.set_ids(frame_tree, response_chan, new_constellation_chan); } - GetGraphicsMetadata(chan) => { + Some(GetGraphicsMetadata(chan)) => { chan.send(Some(azure_hl::current_graphics_metadata())); } - NewLayer(_id, new_size) => { + Some(NewLayer(_id, new_size)) => { self.create_new_layer(_id, new_size); } - SetLayerPageSize(id, new_size, epoch) => { + Some(SetLayerPageSize(id, new_size, epoch)) => { self.set_layer_page_size(id, new_size, epoch); } - SetLayerClipRect(id, new_rect) => { + Some(SetLayerClipRect(id, new_rect)) => { self.set_layer_clip_rect(id, new_rect); } - DeleteLayer(id) => { + Some(DeleteLayer(id)) => { self.delete_layer(id); } - Paint(id, new_layer_buffer_set, epoch) => { + Some(Paint(id, new_layer_buffer_set, epoch)) => { self.paint(id, new_layer_buffer_set, epoch); } - InvalidateRect(id, rect) => { + Some(InvalidateRect(id, rect)) => { self.invalidate_rect(id, rect); } - ScrollFragmentPoint(id, point) => { + Some(ScrollFragmentPoint(id, point)) => { self.scroll_fragment_to_point(id, point); } } @@ -601,7 +608,7 @@ impl IOCompositor { } fn composite(&mut self) { - do profile(time::CompositingCategory, self.profiler_chan.clone()) { + profile(time::CompositingCategory, self.profiler_chan.clone(), || { debug!("compositor: compositing"); // Adjust the layer dimensions as necessary to correspond to the size of the window. self.scene.size = self.window.size(); @@ -616,7 +623,7 @@ impl IOCompositor { None => {} } rendergl::render_scene(self.context, &self.scene); - } + }); // Render to PNG. We must read from the back buffer (ie, before // self.window.present()) as OpenGL ES 2 does not have glReadBuffer(). @@ -634,9 +641,10 @@ impl IOCompositor { for y in range(0, height) { let dst_start = y * stride; let src_start = (height - y - 1) * stride; - vec::bytes::copy_memory(pixels.mut_slice(dst_start, dst_start + stride), - orig_pixels.slice(src_start, src_start + stride), - stride); + unsafe { + pixels.mut_slice(dst_start, dst_start + stride) + .copy_memory(orig_pixels.slice(src_start, src_start + stride).slice_to(stride)); + } } let img = png::Image { width: width as u32, diff --git a/src/components/main/compositing/compositor_layer.rs b/src/components/main/compositing/compositor_layer.rs index 9e1784bba8d..a04638dd09e 100644 --- a/src/components/main/compositing/compositor_layer.rs +++ b/src/components/main/compositing/compositor_layer.rs @@ -22,7 +22,6 @@ use script::dom::event::{ClickEvent, MouseDownEvent, MouseUpEvent}; use script::script_task::SendEventMsg; use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile}; use servo_msg::constellation_msg::PipelineId; -use std::cell::Cell; use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent}; use windowing::{MouseWindowMouseUpEvent}; use azure::azure_hl::Color; @@ -141,7 +140,7 @@ impl CompositorLayer { -> CompositorLayer { let SendableFrameTree { pipeline, children } = frame_tree; let mut layer = CompositorLayer::new(pipeline, None, tile_size, max_mem, cpu_painting); - layer.children = (do children.move_iter().map |child| { + layer.children = (children.move_iter().map(|child| { let SendableChildFrameTree { frame_tree, rect } = child; let container = @mut ContainerLayer(); match rect { @@ -165,7 +164,7 @@ impl CompositorLayer { child: child_layer, container: container, } - }).collect(); + })).collect(); layer.set_occlusions(); layer } @@ -267,7 +266,7 @@ impl CompositorLayer { let mut redisplay: bool; { // block here to prevent double mutable borrow of self let quadtree = match self.quadtree { - NoTree(*) => fail!("CompositorLayer: cannot get buffer request for {:?}, + NoTree(..) => fail!("CompositorLayer: cannot get buffer request for {:?}, no quadtree initialized", self.pipeline.id), Tree(ref mut quadtree) => quadtree, }; @@ -327,7 +326,7 @@ impl CompositorLayer { let old_rect = con.scissor; con.scissor = Some(new_rect); match self.quadtree { - NoTree(*) => {} // Nothing to do + NoTree(..) => {} // Nothing to do Tree(ref mut quadtree) => { match old_rect { Some(old_rect) => { @@ -494,15 +493,15 @@ impl CompositorLayer { // Delete old layer. while current_layer_child.is_some() { let trash = current_layer_child.unwrap(); - do current_layer_child.unwrap().with_common |common| { + current_layer_child.unwrap().with_common(|common| { current_layer_child = common.next_sibling; - } + }); self.root_layer.remove_child(trash); } // Add new tiles. let quadtree = match self.quadtree { - NoTree(*) => fail!("CompositorLayer: cannot build layer tree for {:?}, + NoTree(..) => fail!("CompositorLayer: cannot build layer tree for {:?}, no quadtree initialized", self.pipeline.id), Tree(ref mut quadtree) => quadtree, }; @@ -544,9 +543,9 @@ impl CompositorLayer { buffer.native_surface.bind_to_texture(graphics_context, texture, size); // Move on to the next sibling. - do current_layer_child.unwrap().with_common |common| { + current_layer_child.unwrap().with_common(|common| { common.next_sibling - } + }) } Some(_) => fail!(~"found unexpected layer kind"), }; @@ -584,29 +583,29 @@ impl CompositorLayer { pub fn add_buffers(&mut self, graphics_context: &NativeCompositingGraphicsContext, pipeline_id: PipelineId, - new_buffers: ~LayerBufferSet, + mut new_buffers: ~LayerBufferSet, epoch: Epoch) -> Option<~LayerBufferSet> { - let cell = Cell::new(new_buffers); if self.pipeline.id == pipeline_id { if self.epoch != epoch { debug!("compositor epoch mismatch: {:?} != {:?}, id: {:?}", self.epoch, epoch, self.pipeline.id); - self.pipeline.render_chan.send(UnusedBufferMsg(cell.take().buffers)); + self.pipeline.render_chan.send(UnusedBufferMsg(new_buffers.buffers)); return None; } + { // Block here to prevent double mutable borrow of self. let quadtree = match self.quadtree { - NoTree(*) => fail!("CompositorLayer: cannot add buffers, no quadtree initialized"), + NoTree(..) => fail!("CompositorLayer: cannot add buffers, no quadtree initialized"), Tree(ref mut quadtree) => quadtree, }; let mut unused_tiles = ~[]; // move_rev_iter is more efficient - for buffer in cell.take().buffers.move_rev_iter() { + for buffer in new_buffers.buffers.move_rev_iter() { unused_tiles.push_all_move(quadtree.add_tile_pixel(buffer.screen_pos.origin.x, buffer.screen_pos.origin.y, buffer.resolution, buffer)); @@ -623,15 +622,15 @@ impl CompositorLayer { for child_layer in self.children.mut_iter() { match child_layer.child.add_buffers(graphics_context, pipeline_id, - cell.take(), + new_buffers, epoch) { None => return None, - Some(buffers) => cell.put_back(buffers), + Some(buffers) => new_buffers = buffers, } } // Not found. Give the caller the buffers back. - Some(cell.take()) + Some(new_buffers) } // Deletes a specified sublayer, including hidden children. Returns false if the layer is not found. @@ -643,7 +642,7 @@ impl CompositorLayer { Some(i) => { let mut child = self.children.remove(i); match self.quadtree { - NoTree(*) => {} // Nothing to do + NoTree(..) => {} // Nothing to do Tree(ref mut quadtree) => { match child.container.scissor { Some(rect) => { @@ -670,7 +669,7 @@ impl CompositorLayer { pub fn invalidate_rect(&mut self, pipeline_id: PipelineId, rect: Rect<f32>) -> bool { if self.pipeline.id == pipeline_id { let quadtree = match self.quadtree { - NoTree(*) => return true, // Nothing to do + NoTree(..) => return true, // Nothing to do Tree(ref mut quadtree) => quadtree, }; quadtree.set_status_page(rect, Invalid, true); @@ -681,32 +680,11 @@ impl CompositorLayer { } } - // Adds a child. - pub fn add_child(&mut self, pipeline: CompositionPipeline, page_size: Option<Size2D<f32>>, tile_size: uint, - max_mem: Option<uint>, clipping_rect: Rect<f32>) { - let container = @mut ContainerLayer(); - container.scissor = Some(clipping_rect); - container.common.set_transform(identity().translate(clipping_rect.origin.x, - clipping_rect.origin.y, - 0.0)); - let child = ~CompositorLayer::new(pipeline, - page_size, - tile_size, - max_mem, - self.cpu_painting); - container.add_child_start(ContainerLayerKind(child.root_layer)); - self.children.push(CompositorLayerChild { - child: child, - container: container, - }); - self.set_occlusions(); - } - // Recursively sets occluded portions of quadtrees to Hidden, so that they do not ask for // tile requests. If layers are moved, resized, or deleted, these portions may be updated. fn set_occlusions(&mut self) { let quadtree = match self.quadtree { - NoTree(*) => return, // Cannot calculate occlusions + NoTree(..) => return, // Cannot calculate occlusions Tree(ref mut quadtree) => quadtree, }; for child in self.children.iter().filter(|x| !x.child.hidden) { @@ -726,7 +704,7 @@ impl CompositorLayer { /// reused. fn clear(&mut self) { match self.quadtree { - NoTree(*) => {} + NoTree(..) => {} Tree(ref mut quadtree) => { let mut tiles = quadtree.collect_tiles(); @@ -759,7 +737,7 @@ impl CompositorLayer { /// This is used during shutdown, when we know the render task is going away. pub fn forget_all_tiles(&mut self) { match self.quadtree { - NoTree(*) => {} + NoTree(..) => {} Tree(ref mut quadtree) => { let tiles = quadtree.collect_tiles(); for tile in tiles.move_iter() { diff --git a/src/components/main/compositing/compositor_task.rs b/src/components/main/compositing/compositor_task.rs index 5cdf310ce59..6e01b3d64e3 100644 --- a/src/components/main/compositing/compositor_task.rs +++ b/src/components/main/compositing/compositor_task.rs @@ -19,7 +19,6 @@ use servo_msg::compositor_msg::{ScriptListener, Tile}; use servo_msg::constellation_msg::{ConstellationChan, PipelineId, ExitMsg}; use servo_util::time::ProfilerChan; use std::comm::{Chan, SharedChan, Port}; -use std::comm; use std::num::Orderable; #[cfg(target_os="linux")] @@ -54,7 +53,9 @@ impl ScriptListener for CompositorChan { } fn close(&self) { - self.chan.send(Exit); + let (port, chan) = Chan::new(); + self.chan.send(Exit(chan)); + port.recv(); } } @@ -62,7 +63,7 @@ impl ScriptListener for CompositorChan { /// Implementation of the abstract `RenderListener` interface. impl RenderListener for CompositorChan { fn get_graphics_metadata(&self) -> Option<NativeGraphicsMetadata> { - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); self.chan.send(GetGraphicsMetadata(chan)); port.recv() } @@ -99,10 +100,12 @@ impl RenderListener for CompositorChan { } impl CompositorChan { - pub fn new(chan: Chan<Msg>) -> CompositorChan { - CompositorChan { - chan: SharedChan::new(chan), - } + pub fn new() -> (Port<Msg>, CompositorChan) { + let (port, chan) = SharedChan::new(); + let compositor_chan = CompositorChan { + chan: chan, + }; + (port, compositor_chan) } pub fn send(&self, msg: Msg) { @@ -113,7 +116,7 @@ impl CompositorChan { /// Messages from the painting task and the constellation task to the compositor task. pub enum Msg { /// Requests that the compositor shut down. - Exit, + Exit(Chan<()>), /// Requests the compositor's graphics metadata. Graphics metadata is what the renderer needs /// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this /// is the pixel format. diff --git a/src/components/main/compositing/headless.rs b/src/components/main/compositing/headless.rs index 4ec179c7e05..07a2e973868 100644 --- a/src/components/main/compositing/headless.rs +++ b/src/components/main/compositing/headless.rs @@ -38,7 +38,10 @@ impl NullCompositor { fn handle_message(&self) { loop { match self.port.recv() { - Exit => break, + Exit(chan) => { + chan.send(()); + break + } GetGraphicsMetadata(chan) => { chan.send(None); @@ -52,9 +55,9 @@ impl NullCompositor { // we'll notice and think about whether it needs a response, like // SetIds. - NewLayer(*) | SetLayerPageSize(*) | SetLayerClipRect(*) | DeleteLayer(*) | - Paint(*) | InvalidateRect(*) | ChangeReadyState(*) | ChangeRenderState(*)| - ScrollFragmentPoint(*) | SetUnRenderedColor(*) + NewLayer(..) | SetLayerPageSize(..) | SetLayerClipRect(..) | DeleteLayer(..) | + Paint(..) | InvalidateRect(..) | ChangeReadyState(..) | ChangeRenderState(..)| + ScrollFragmentPoint(..) | SetUnRenderedColor(..) => () } } diff --git a/src/components/main/compositing/quadtree.rs b/src/components/main/compositing/quadtree.rs index 5ad48c1988e..b874335db2b 100644 --- a/src/components/main/compositing/quadtree.rs +++ b/src/components/main/compositing/quadtree.rs @@ -18,8 +18,6 @@ use servo_msg::compositor_msg::Tile; #[cfg(test)] use layers::platform::surface::NativePaintingGraphicsContext; -static HEADER: &'static str = "<!DOCTYPE html><html>"; - /// Parent to all quadtree nodes. Stores variables needed at all levels. All method calls /// at this level are in pixel coordinates. pub struct Quadtree<T> { @@ -101,20 +99,6 @@ impl<T: Tile> Quadtree<T> { } } - /// Return the maximum allowed tile size - pub fn get_tile_size(&self) -> uint { - self.max_tile_size - } - /// Get a tile at a given pixel position and scale. - pub fn get_tile_pixel<'r>(&'r self, x: uint, y: uint, scale: f32) -> &'r Option<T> { - self.root.get_tile(x as f32 / scale, y as f32 / scale) - } - - /// Get a tile at a given page position. - pub fn get_tile_page<'r>(&'r self, x: f32, y: f32) -> &'r Option<T> { - self.root.get_tile(x, y) - } - /// Add a tile associated with a given pixel position and scale. /// If the tile pushes the total memory over its maximum, tiles will be removed /// until total memory is below the maximum again. These tiles are returned. @@ -137,73 +121,17 @@ impl<T: Tile> Quadtree<T> { tiles } - /// Add a tile associated with a given page position. - /// If the tile pushes the total memory over its maximum, tiles will be removed - /// until total memory is below the maximum again. These tiles are returned. - pub fn add_tile_page(&mut self, x: f32, y: f32, scale: f32, tile: T) -> ~[T] { - let (_, tiles) = self.root.add_tile(x, y, tile, self.max_tile_size as f32 / scale); - let mut tiles = tiles; - match self.max_mem { - Some(max) => { - while self.root.tile_mem > max { - let r = self.root.remove_tile(x, y); - match r { - (Some(tile), _, _) => tiles.push(tile), - _ => fail!("Quadtree: No valid tiles to remove"), - } - } - } - None => {} // Nothing to do - } - tiles - } - - /// Get the tile rect in screen and page coordinates for a given pixel position. - pub fn get_tile_rect_pixel(&mut self, x: uint, y: uint, scale: f32) -> BufferRequest { - self.root.get_tile_rect(x as f32 / scale, y as f32 / scale, - self.clip_size.width as f32, - self.clip_size.height as f32, - scale, self.max_tile_size as f32 / scale) - } - - /// Get the tile rect in screen and page coordinates for a given page position. - pub fn get_tile_rect_page(&mut self, x: f32, y: f32, scale: f32) -> BufferRequest { - self.root.get_tile_rect(x, y, - self.clip_size.width as f32, - self.clip_size.height as f32, - scale, self.max_tile_size as f32 / scale) - } - /// Get all the tiles in the tree. pub fn get_all_tiles<'r>(&'r self) -> ~[&'r T] { self.root.get_all_tiles() } - /// Ask a tile to be deleted from the quadtree. This tries to delete a tile that is far from the - /// given point in pixel coordinates. - pub fn remove_tile_pixel(&mut self, x: uint, y: uint, scale: f32) -> T { - let r = self.root.remove_tile(x as f32 / scale, y as f32 / scale); - match r { - (Some(tile), _, _) => tile, - _ => fail!("Quadtree: No valid tiles to remove"), - } - } - - /// Ask a tile to be deleted from the quadtree. This tries to delete a tile that is far from the - /// given point in page coordinates. - pub fn remove_tile_page(&mut self, x: f32, y: f32) -> T { - let r = self.root.remove_tile(x, y); - match r { - (Some(tile), _, _) => tile, - _ => fail!("Quadtree: No valid tiles to remove"), - } - } - /// Given a window rect in pixel coordinates, this function returns a list of BufferRequests for tiles that /// need to be rendered. It also returns a vector of tiles if the window needs to be redisplayed, i.e. if /// no tiles need to be rendered, but the display tree needs to be rebuilt. This can occur when the /// user zooms out and cached tiles need to be displayed on top of higher resolution tiles. /// When this happens, higher resolution tiles will be removed from the quadtree. + #[cfg(test)] pub fn get_tile_rects_pixel(&mut self, window: Rect<int>, scale: f32) -> (~[BufferRequest], ~[T]) { let (ret, unused, _) = self.root.get_tile_rects( Rect(Point2D(window.origin.x as f32 / scale, window.origin.y as f32 / scale), @@ -245,6 +173,7 @@ impl<T: Tile> Quadtree<T> { /// Resize the underlying quadtree without removing tiles already in place. /// Might be useful later on, but resize() should be used for now. /// TODO: return tiles after shrinking + #[cfg(test)] pub fn bad_resize(&mut self, width: uint, height: uint) { self.clip_size = Size2D(width, height); let longer = width.max(&height); @@ -301,11 +230,6 @@ impl<T: Tile> Quadtree<T> { pub fn collect_tiles(&mut self) -> ~[T] { self.root.collect_tiles() } - - /// Generate html to visualize the tree. For debugging purposes only. - pub fn get_html(&self) -> ~str { - format!("{:s}<body>{:s}</body></html>", HEADER, self.root.get_html()) - } } impl<T: Tile> QuadtreeNode<T> { @@ -336,20 +260,6 @@ impl<T: Tile> QuadtreeNode<T> { } } - /// Get the lowest-level (highest resolution) tile associated with a given position in page coords. - fn get_tile<'r> (&'r self, x: f32, y: f32) -> &'r Option<T> { - if x >= self.origin.x + self.size || x < self.origin.x - || y >= self.origin.y + self.size || y < self.origin.y { - fail!("Quadtree: Tried to get a tile outside of range"); - } - - let index = self.get_quadrant(x, y) as int; - match self.quadrants[index] { - None => &'r self.tile, - Some(ref child) => child.get_tile(x, y), - } - } - /// Get all tiles in the tree, parents first. fn get_all_tiles<'r>(&'r self) -> ~[&'r T] { let mut ret = ~[]; @@ -602,7 +512,7 @@ impl<T: Tile> QuadtreeNode<T> { let w_br_quad = self.get_quadrant(w_x + w_width, w_y + w_height); // Figure out which quadrants the window is in - let builder = |push: &fn(Quadrant)| { + let builder = |push: |Quadrant|| { match (w_tl_quad, w_br_quad) { (tl, br) if tl as int == br as int => { push(tl); @@ -734,44 +644,6 @@ impl<T: Tile> QuadtreeNode<T> { } } } - - /// Generate html to visualize the tree. - /// This is really inefficient, but it's for testing only. - fn get_html(&self) -> ~str { - let mut ret = ~""; - match self.tile { - Some(ref tile) => { - ret = format!("{:s}{:?}", ret, tile); - } - None => { - ret = format!("{:s}NO TILE", ret); - } - } - match self.quadrants { - [None, None, None, None] => {} - _ => { - ret = format!("{:s}<table border=1><tr>", ret); - // FIXME: This should be inline, but currently won't compile - let quads = [TL, TR, BL, BR]; - for quad in quads.iter() { - match self.quadrants[*quad as int] { - Some(ref child) => { - ret = format!("{:s}<td>{:s}</td>", ret, child.get_html()); - } - None => { - ret = format!("{:s}<td>EMPTY CHILD</td>", ret); - } - } - match *quad { - TR => ret = format!("{:s}</tr><tr>", ret), - _ => {} - } - } - ret = format!("{:s}</table>\n", ret); - } - } - return ret; - } } #[test] diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs index 8408063890e..66303f41545 100644 --- a/src/components/main/constellation.rs +++ b/src/components/main/constellation.rs @@ -20,10 +20,7 @@ use servo_net::resource_task::ResourceTask; use servo_net::resource_task; use servo_util::time::ProfilerChan; use servo_util::url::make_url; -use std::comm::Port; -use std::comm; use std::hashmap::{HashMap, HashSet}; -use std::task::spawn_with; use std::util::replace; /// Maintains the pipelines and navigation context and grants permission to composite @@ -53,9 +50,9 @@ struct FrameTree { // Need to clone the FrameTrees, but _not_ the Pipelines impl Clone for FrameTree { fn clone(&self) -> FrameTree { - let mut children = do self.children.iter().map |child_frame_tree| { + let mut children = self.children.iter().map(|child_frame_tree| { child_frame_tree.clone() - }; + }); FrameTree { pipeline: self.pipeline, parent: self.parent.clone(), @@ -90,41 +87,46 @@ pub struct SendableChildFrameTree { rect: Option<Rect<f32>>, } -impl SendableFrameTree { - fn contains(&self, id: PipelineId) -> bool { - self.pipeline.id == id || - do self.children.iter().any |&SendableChildFrameTree { frame_tree: ref frame_tree, _ }| { - frame_tree.contains(id) - } - } +// impl SendableFrameTree { +// fn contains(&self, id: PipelineId) -> bool { +// self.pipeline.id == id || +// self.children.iter().any(|&SendableChildFrameTree { frame_tree: ref frame_tree, .. }| { +// frame_tree.contains(id) +// }) +// } +// } + +enum ReplaceResult { + ReplacedNode(@mut FrameTree), + OriginalNode(@mut FrameTree), } impl FrameTree { fn contains(@mut self, id: PipelineId) -> bool { - do self.iter().any |frame_tree| { + self.iter().any(|frame_tree| { id == frame_tree.pipeline.id - } + }) } /// Returns the frame tree whose key is id fn find(@mut self, id: PipelineId) -> Option<@mut FrameTree> { - do self.iter().find |frame_tree| { + self.iter().find(|frame_tree| { id == frame_tree.pipeline.id - } + }) } /// Replaces a node of the frame tree in place. Returns the node that was removed or the original node /// if the node to replace could not be found. - fn replace_child(@mut self, id: PipelineId, new_child: @mut FrameTree) -> Either<@mut FrameTree, @mut FrameTree> { + fn replace_child(@mut self, id: PipelineId, new_child: @mut FrameTree) -> ReplaceResult { for frame_tree in self.iter() { let mut child = frame_tree.children.mut_iter() .find(|child| child.frame_tree.pipeline.id == id); for child in child.mut_iter() { new_child.parent = child.frame_tree.parent; - return Left(replace(&mut child.frame_tree, new_child)); + return ReplacedNode(replace(&mut child.frame_tree, new_child)); } } - Right(new_child) + OriginalNode(new_child) } fn to_sendable(&self) -> SendableFrameTree { @@ -162,7 +164,7 @@ impl Iterator<@mut FrameTree> for FrameTreeIterator { fn next(&mut self) -> Option<@mut FrameTree> { if !self.stack.is_empty() { let next = self.stack.pop(); - for &ChildFrameTree { frame_tree, _ } in next.children.rev_iter() { + for &ChildFrameTree { frame_tree, .. } in next.children.rev_iter() { self.stack.push(frame_tree); } Some(next) @@ -223,15 +225,15 @@ impl NavigationContext { /// Returns the frame trees whose keys are pipeline_id. pub fn find_all(&mut self, pipeline_id: PipelineId) -> ~[@mut FrameTree] { - let from_current = do self.current.iter().filter_map |frame_tree| { + let from_current = self.current.iter().filter_map(|frame_tree| { frame_tree.find(pipeline_id) - }; - let from_next = do self.next.iter().filter_map |frame_tree| { + }); + let from_next = self.next.iter().filter_map(|frame_tree| { frame_tree.find(pipeline_id) - }; - let from_prev = do self.previous.iter().filter_map |frame_tree| { + }); + let from_prev = self.previous.iter().filter_map(|frame_tree| { frame_tree.find(pipeline_id) - }; + }); from_prev.chain(from_current).chain(from_next).collect() } @@ -241,36 +243,25 @@ impl NavigationContext { let from_prev = self.previous.iter(); let mut all_contained = from_prev.chain(from_current).chain(from_next); - do all_contained.any |frame_tree| { + all_contained.any(|frame_tree| { frame_tree.contains(pipeline_id) - } + }) } } impl Constellation { - pub fn start(constellation_port: Port<Msg>, - constellation_chan: ConstellationChan, - compositor_chan: CompositorChan, + pub fn start(compositor_chan: CompositorChan, opts: &Opts, resource_task: ResourceTask, image_cache_task: ImageCacheTask, - profiler_chan: ProfilerChan) { - do spawn_with((constellation_port, - constellation_chan.clone(), - compositor_chan, - resource_task, - image_cache_task, - profiler_chan, - opts.clone())) - |(constellation_port, - constellation_chan, - compositor_chan, - resource_task, - image_cache_task, - profiler_chan, - opts)| { + profiler_chan: ProfilerChan) + -> ConstellationChan { + let (constellation_port, constellation_chan) = ConstellationChan::new(); + let constellation_chan_clone = constellation_chan.clone(); + let opts_clone = opts.clone(); + spawn(proc() { let mut constellation = Constellation { - chan: constellation_chan, + chan: constellation_chan_clone, request_port: constellation_port, compositor_chan: compositor_chan, resource_task: resource_task, @@ -282,10 +273,11 @@ impl Constellation { pending_sizes: HashMap::new(), profiler_chan: profiler_chan, window_size: Size2D(500u, 500u), - opts: opts + opts: opts_clone, }; constellation.run(); - } + }); + constellation_chan } fn run(&mut self) { @@ -313,9 +305,9 @@ impl Constellation { /// Returns both the navigation context and pending frame trees whose keys are pipeline_id. pub fn find_all(&mut self, pipeline_id: PipelineId) -> ~[@mut FrameTree] { let matching_navi_frames = self.navigation_context.find_all(pipeline_id); - let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| { + let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| { frame_change.after.find(pipeline_id) - }; + }); matching_navi_frames.move_iter().chain(matching_pending_frames).collect() } @@ -323,6 +315,7 @@ impl Constellation { fn handle_request(&mut self, request: Msg) -> bool { match request { ExitMsg(sender) => { + debug!("constellation exiting"); self.handle_exit(sender); return false; } @@ -499,9 +492,9 @@ impl Constellation { // and add the new pipeline to their sub frames. let frame_trees: ~[@mut FrameTree] = { let matching_navi_frames = self.navigation_context.find_all(source_pipeline_id); - let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| { + let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| { frame_change.after.find(source_pipeline_id) - }; + }); matching_navi_frames.move_iter().chain(matching_pending_frames).collect() }; @@ -681,9 +674,9 @@ impl Constellation { // Find the pending frame change whose new pipeline id is pipeline_id. // If it is not found, it simply means that this pipeline will not receive // permission to paint. - let pending_index = do self.pending_frames.iter().rposition |frame_change| { + let pending_index = self.pending_frames.iter().rposition(|frame_change| { frame_change.after.pipeline.id == pipeline_id - }; + }); for &pending_index in pending_index.iter() { let frame_change = self.pending_frames.swap_remove(pending_index); let to_add = frame_change.after; @@ -742,9 +735,9 @@ impl Constellation { /// Called when the window is resized. fn handle_resized_window_msg(&mut self, new_size: Size2D<uint>) { let mut already_seen = HashSet::new(); - for &@FrameTree { pipeline: pipeline, _ } in self.current_frame().iter() { + for &@FrameTree { pipeline: pipeline, .. } in self.current_frame().iter() { debug!("constellation sending resize message to active frame"); - pipeline.script_chan.send(ResizeMsg(pipeline.id, new_size)); + pipeline.script_chan.try_send(ResizeMsg(pipeline.id, new_size)); already_seen.insert(pipeline.id); } for frame_tree in self.navigation_context.previous.iter() @@ -752,7 +745,7 @@ impl Constellation { let pipeline = &frame_tree.pipeline; if !already_seen.contains(&pipeline.id) { debug!("constellation sending resize message to inactive frame"); - pipeline.script_chan.send(ResizeInactiveMsg(pipeline.id, new_size)); + pipeline.script_chan.try_send(ResizeInactiveMsg(pipeline.id, new_size)); already_seen.insert(pipeline.id); } } @@ -774,7 +767,7 @@ impl Constellation { fn close_pipelines(&mut self, frame_tree: @mut FrameTree) { // TODO(tkuehn): should only exit once per unique script task, // and then that script task will handle sub-exits - for @FrameTree { pipeline, _ } in frame_tree.iter() { + for @FrameTree { pipeline, .. } in frame_tree.iter() { pipeline.exit(); self.pipelines.remove(&pipeline.id); } @@ -809,9 +802,9 @@ impl Constellation { } fn set_ids(&self, frame_tree: @mut FrameTree) { - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); self.compositor_chan.send(SetIds(frame_tree.to_sendable(), chan, self.chan.clone())); - match port.try_recv() { + match port.recv_opt() { Some(()) => { for frame in frame_tree.iter() { frame.pipeline.grant_paint_permission(); diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs index cace6ffd5f1..f25f92874c1 100644 --- a/src/components/main/css/matching.rs +++ b/src/components/main/css/matching.rs @@ -11,11 +11,8 @@ use layout::wrapper::LayoutNode; use extra::arc::{Arc, RWArc}; use std::cast; -use std::cell::Cell; -use std::comm; use std::libc::uintptr_t; use std::rt; -use std::task; use std::vec; use style::{TNode, Stylist, cascade}; use style::{Before, After}; @@ -27,22 +24,23 @@ pub trait MatchMethods { fn cascade_subtree(&self, parent: Option<LayoutNode>); } -impl<'self> MatchMethods for LayoutNode<'self> { +impl<'ln> MatchMethods for LayoutNode<'ln> { fn match_node(&self, stylist: &Stylist) { - let style_attribute = do self.with_element |element| { + let style_attribute = self.with_element(|element| { match *element.style_attribute() { None => None, Some(ref style_attribute) => Some(style_attribute) } - }; + }); - match *self.mutate_layout_data().ptr { + let mut layout_data_ref = self.mutate_layout_data(); + match *layout_data_ref.get() { Some(ref mut layout_data) => { - layout_data.applicable_declarations = stylist.get_applicable_declarations( + layout_data.data.applicable_declarations = stylist.get_applicable_declarations( self, style_attribute, None); - layout_data.before_applicable_declarations = stylist.get_applicable_declarations( + layout_data.data.before_applicable_declarations = stylist.get_applicable_declarations( self, None, Some(Before)); - layout_data.after_applicable_declarations = stylist.get_applicable_declarations( + layout_data.data.after_applicable_declarations = stylist.get_applicable_declarations( self, None, Some(After)); } None => fail!("no layout data") @@ -60,8 +58,7 @@ impl<'self> MatchMethods for LayoutNode<'self> { } } - let (port, chan) = comm::stream(); - let chan = comm::SharedChan::new(chan); + let (port, chan) = SharedChan::new(); let mut num_spawned = 0; for nodes in nodes_per_task.move_iter() { @@ -77,20 +74,20 @@ impl<'self> MatchMethods for LayoutNode<'self> { cast::transmute(nodes) }; - do task::spawn_with((evil, stylist)) |(evil, stylist)| { + let evil = Some(evil); + spawn(proc() { + let mut evil = evil; let nodes: ~[LayoutNode] = unsafe { - cast::transmute(evil) + cast::transmute(evil.take_unwrap()) }; - let nodes = Cell::new(nodes); - do stylist.read |stylist| { - let nodes = nodes.take(); + stylist.read(|stylist| { for node in nodes.iter() { node.match_node(stylist); } - } + }); chan.send(()); - } + }); num_spawned += 1; } } @@ -100,9 +97,6 @@ impl<'self> MatchMethods for LayoutNode<'self> { } fn cascade_subtree(&self, parent: Option<LayoutNode>) { - let layout_data = unsafe { - self.borrow_layout_data_unchecked().as_ref().unwrap() - }; macro_rules! cascade_node( ($applicable_declarations: ident, $style: ident) => {{ let parent_style = match parent { @@ -110,18 +104,21 @@ impl<'self> MatchMethods for LayoutNode<'self> { None => None }; - let computed_values = Arc::new(cascade( - layout_data.$applicable_declarations, - parent_style.map(|parent_style| parent_style.get()))); + let computed_values = { + let layout_data_ref = self.borrow_layout_data(); + let layout_data = layout_data_ref.get().as_ref().unwrap(); + Arc::new(cascade(layout_data.data.$applicable_declarations, parent_style.map(|parent_style| parent_style.get()))) + }; - match *self.mutate_layout_data().ptr { + let mut layout_data_ref = self.mutate_layout_data(); + match *layout_data_ref.get() { None => fail!("no layout data"), Some(ref mut layout_data) => { - let style = &mut layout_data.$style; + let style = &mut layout_data.data.$style; match *style { None => (), Some(ref previous_style) => { - layout_data.restyle_damage = Some(incremental::compute_damage( + layout_data.data.restyle_damage = Some(incremental::compute_damage( previous_style.get(), computed_values.get()).to_int()) } } @@ -131,14 +128,22 @@ impl<'self> MatchMethods for LayoutNode<'self> { }} ); - unsafe { - if self.borrow_layout_data_unchecked().as_ref().unwrap().before_applicable_declarations.len() > 0 { + { + let before_len = { + let layout_data_ref = self.borrow_layout_data(); + layout_data_ref.get().as_ref().unwrap().data.before_applicable_declarations.len() + }; + if before_len > 0 { cascade_node!(before_applicable_declarations, before_style); } } cascade_node!(applicable_declarations, style); - unsafe { - if self.borrow_layout_data_unchecked().as_ref().unwrap().after_applicable_declarations.len() > 0 { + { + let after_len = { + let layout_data_ref = self.borrow_layout_data(); + layout_data_ref.get().as_ref().unwrap().data.after_applicable_declarations.len() + }; + if after_len > 0 { cascade_node!(after_applicable_declarations, after_style); } } diff --git a/src/components/main/css/node_style.rs b/src/components/main/css/node_style.rs index 6810d9187ea..f9b561425bb 100644 --- a/src/components/main/css/node_style.rs +++ b/src/components/main/css/node_style.rs @@ -17,7 +17,7 @@ pub trait StyledNode { fn restyle_damage(&self) -> RestyleDamage; } -impl<'self> StyledNode for LayoutNode<'self> { +impl<'ln> StyledNode for LayoutNode<'ln> { #[inline] fn style<'a>(&'a self) -> &'a Arc<ComputedValues> { self.get_css_select_results() diff --git a/src/components/main/css/node_util.rs b/src/components/main/css/node_util.rs index a84fb5cc061..3a2b83ccab3 100644 --- a/src/components/main/css/node_util.rs +++ b/src/components/main/css/node_util.rs @@ -18,7 +18,7 @@ pub trait NodeUtil { fn set_restyle_damage(self, damage: RestyleDamage); } -impl<'self> NodeUtil for LayoutNode<'self> { +impl<'ln> NodeUtil for LayoutNode<'ln> { /** * Provides the computed style for the given node. If CSS selector * Returns the style results for the given node. If CSS selector @@ -27,18 +27,15 @@ impl<'self> NodeUtil for LayoutNode<'self> { #[inline] fn get_css_select_results<'a>(&'a self) -> &'a Arc<ComputedValues> { unsafe { - cast::transmute_region(self.borrow_layout_data_unchecked() - .as_ref() - .unwrap() - .style - .as_ref() - .unwrap()) + let layout_data_ref = self.borrow_layout_data(); + cast::transmute_region(layout_data_ref.get().as_ref().unwrap().data.style.as_ref().unwrap()) } } /// Does this node have a computed style yet? fn have_css_select_results(self) -> bool { - self.borrow_layout_data().ptr.as_ref().unwrap().style.is_some() + let layout_data_ref = self.borrow_layout_data(); + layout_data_ref.get().get_ref().data.style.is_some() } /// Get the description of how to account for recent style changes. @@ -52,10 +49,11 @@ impl<'self> NodeUtil for LayoutNode<'self> { RestyleDamage::none() }; - self.borrow_layout_data() - .ptr - .as_ref() - .unwrap() + let layout_data_ref = self.borrow_layout_data(); + layout_data_ref + .get() + .get_ref() + .data .restyle_damage .map(|x| RestyleDamage::from_int(x)) .unwrap_or(default) @@ -63,10 +61,10 @@ impl<'self> NodeUtil for LayoutNode<'self> { /// Set the restyle damage field. fn set_restyle_damage(self, damage: RestyleDamage) { - match *self.mutate_layout_data().ptr { - Some(ref mut data) => data.restyle_damage = Some(damage.to_int()), + let mut layout_data_ref = self.mutate_layout_data(); + match *layout_data_ref.get() { + Some(ref mut layout_data) => layout_data.data.restyle_damage = Some(damage.to_int()), _ => fail!("no layout data for this node"), } } } - diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index ff85f4e14ad..276e6a38e1d 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -4,7 +4,7 @@ //! CSS block formatting contexts. -use layout::box::Box; +use layout::box_::Box; use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::flow::{BlockFlowClass, FlowClass, Flow, FlowData, ImmutableFlowUtils}; @@ -12,7 +12,7 @@ use layout::flow; use layout::model::{MaybeAuto, Specified, Auto, specified_or_none, specified}; use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType}; -use std::cell::Cell; +use std::cell::RefCell; use geom::{Point2D, Rect, SideOffsets2D}; use gfx::display_list::DisplayList; use servo_util::geometry::Au; @@ -53,7 +53,7 @@ pub struct BlockFlow { base: FlowData, /// The associated box. - box: Option<Box>, + box_: Option<Box>, /// Whether this block flow is the root flow. is_root: bool, @@ -66,25 +66,25 @@ impl BlockFlow { pub fn new(base: FlowData) -> BlockFlow { BlockFlow { base: base, - box: None, + box_: None, is_root: false, float: None } } - pub fn from_box(base: FlowData, box: Box) -> BlockFlow { + pub fn from_box(base: FlowData, box_: Box) -> BlockFlow { BlockFlow { base: base, - box: Some(box), + box_: Some(box_), is_root: false, float: None } } - pub fn float_from_box(base: FlowData, float_type: FloatType, box: Box) -> BlockFlow { + pub fn float_from_box(base: FlowData, float_type: FloatType, box_: Box) -> BlockFlow { BlockFlow { base: base, - box: Some(box), + box_: Some(box_), is_root: false, float: Some(~FloatedBlockInfo::new(float_type)) } @@ -93,7 +93,7 @@ impl BlockFlow { pub fn new_root(base: FlowData) -> BlockFlow { BlockFlow { base: base, - box: None, + box_: None, is_root: true, float: None } @@ -102,7 +102,7 @@ impl BlockFlow { pub fn new_float(base: FlowData, float_type: FloatType) -> BlockFlow { BlockFlow { base: base, - box: None, + box_: None, is_root: false, float: Some(~FloatedBlockInfo::new(float_type)) } @@ -113,10 +113,10 @@ impl BlockFlow { } pub fn teardown(&mut self) { - for box in self.box.iter() { - box.teardown(); + for box_ in self.box_.iter() { + box_.teardown(); } - self.box = None; + self.box_ = None; self.float = None; } @@ -172,9 +172,9 @@ impl BlockFlow { (width_Au, left_margin_Au, right_margin_Au) } - fn compute_block_margins(&self, box: &Box, remaining_width: Au, available_width: Au) + fn compute_block_margins(&self, box_: &Box, remaining_width: Au, available_width: Au) -> (Au, Au, Au) { - let style = box.style(); + let style = box_.style(); let (width, maybe_margin_left, maybe_margin_right) = (MaybeAuto::from_style(style.Box.width, remaining_width), @@ -215,8 +215,8 @@ impl BlockFlow { return (width, margin_left, margin_right); } - fn compute_float_margins(&self, box: &Box, remaining_width: Au) -> (Au, Au, Au) { - let style = box.style(); + fn compute_float_margins(&self, box_: &Box, remaining_width: Au) -> (Au, Au, Au) { + let style = box_.style(); let margin_left = MaybeAuto::from_style(style.Margin.margin_left, remaining_width).specified_or_zero(); let margin_right = MaybeAuto::from_style(style.Margin.margin_right, @@ -240,20 +240,20 @@ impl BlockFlow { let mut left_offset = Au::new(0); let mut float_ctx = Invalid; - for box in self.box.iter() { - clearance = match box.clear() { + for box_ in self.box_.iter() { + clearance = match box_.clear() { None => Au::new(0), Some(clear) => { self.base.floats_in.clearance(clear) } }; - top_offset = clearance + box.margin.get().top + box.border.get().top + - box.padding.get().top; + top_offset = clearance + box_.margin.get().top + box_.border.get().top + + box_.padding.get().top; cur_y = cur_y + top_offset; - bottom_offset = box.margin.get().bottom + box.border.get().bottom + - box.padding.get().bottom; - left_offset = box.offset(); + bottom_offset = box_.margin.get().bottom + box_.border.get().bottom + + box_.padding.get().bottom; + left_offset = box_.offset(); } if inorder { @@ -279,17 +279,17 @@ impl BlockFlow { let mut top_margin_collapsible = false; let mut bottom_margin_collapsible = false; let mut first_in_flow = true; - for box in self.box.iter() { - if !self.is_root && box.border.get().top == Au(0) && box.padding.get().top == Au(0) { - collapsible = box.margin.get().top; + for box_ in self.box_.iter() { + if !self.is_root && box_.border.get().top == Au(0) && box_.padding.get().top == Au(0) { + collapsible = box_.margin.get().top; top_margin_collapsible = true; } - if !self.is_root && box.border.get().bottom == Au(0) && - box.padding.get().bottom == Au(0) { + if !self.is_root && box_.border.get().bottom == Au(0) && + box_.padding.get().bottom == Au(0) { bottom_margin_collapsible = true; } - margin_top = box.margin.get().top; - margin_bottom = box.margin.get().bottom; + margin_top = box_.margin.get().top; + margin_bottom = box_.margin.get().bottom; } for kid in self.base.child_iter() { @@ -332,8 +332,8 @@ impl BlockFlow { cur_y - top_offset - collapsing }; - for box in self.box.iter() { - let style = box.style(); + for box_ in self.box_.iter() { + let style = box_.style(); // At this point, `height` is the height of the containing block, so passing `height` // as the second argument here effectively makes percentages relative to the containing @@ -345,9 +345,9 @@ impl BlockFlow { } let mut noncontent_height = Au::new(0); - for box in self.box.iter() { - let mut position = box.position.get(); - let mut margin = box.margin.get(); + for box_ in self.box_.iter() { + let mut position = box_.position.get(); + let mut margin = box_.margin.get(); // The associated box is the border box of this flow. margin.top = margin_top; @@ -355,14 +355,14 @@ impl BlockFlow { position.origin.y = clearance + margin.top; - noncontent_height = box.padding.get().top + box.padding.get().bottom + - box.border.get().top + box.border.get().bottom; + noncontent_height = box_.padding.get().top + box_.padding.get().bottom + + box_.border.get().top + box_.border.get().bottom; position.size.height = height + noncontent_height; noncontent_height = noncontent_height + clearance + margin.top + margin.bottom; - box.position.set(position); - box.margin.set(margin); + box_.position.set(position); + box_.margin.set(margin); } self.base.position.size.height = height + noncontent_height; @@ -384,19 +384,19 @@ impl BlockFlow { let mut full_noncontent_width = Au(0); let mut margin_height = Au(0); - for box in self.box.iter() { - height = box.position.get().size.height; - clearance = match box.clear() { + for box_ in self.box_.iter() { + height = box_.position.get().size.height; + clearance = match box_.clear() { None => Au(0), Some(clear) => self.base.floats_in.clearance(clear), }; - let noncontent_width = box.padding.get().left + box.padding.get().right + - box.border.get().left + box.border.get().right; + let noncontent_width = box_.padding.get().left + box_.padding.get().right + + box_.border.get().left + box_.border.get().right; - full_noncontent_width = noncontent_width + box.margin.get().left + - box.margin.get().right; - margin_height = box.margin.get().top + box.margin.get().bottom; + full_noncontent_width = noncontent_width + box_.margin.get().left + + box_.margin.get().right; + margin_height = box_.margin.get().top + box_.margin.get().bottom; } let info = PlacementInfo { @@ -427,8 +427,8 @@ impl BlockFlow { let mut cur_y = Au(0); let mut top_offset = Au(0); - for box in self.box.iter() { - top_offset = box.margin.get().top + box.border.get().top + box.padding.get().top; + for box_ in self.box_.iter() { + top_offset = box_.margin.get().top + box_.border.get().top + box_.padding.get().top; cur_y = cur_y + top_offset; } @@ -441,31 +441,31 @@ impl BlockFlow { let mut height = cur_y - top_offset; let mut noncontent_height; - let box = self.box.as_ref().unwrap(); - let mut position = box.position.get(); + let box_ = self.box_.as_ref().unwrap(); + let mut position = box_.position.get(); // The associated box is the border box of this flow. - position.origin.y = box.margin.get().top; + position.origin.y = box_.margin.get().top; - noncontent_height = box.padding.get().top + box.padding.get().bottom + - box.border.get().top + box.border.get().bottom; + noncontent_height = box_.padding.get().top + box_.padding.get().bottom + + box_.border.get().top + box_.border.get().bottom; //TODO(eatkinson): compute heights properly using the 'height' property. - let height_prop = MaybeAuto::from_style(box.style().Box.height, + let height_prop = MaybeAuto::from_style(box_.style().Box.height, Au::new(0)).specified_or_zero(); height = geometry::max(height, height_prop) + noncontent_height; debug!("assign_height_float -- height: {}", height); position.size.height = height; - box.position.set(position); + box_.position.set(position); } pub fn build_display_list_block<E:ExtraDisplayListData>( &mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + list: &RefCell<DisplayList<E>>) -> bool { if self.is_float() { return self.build_display_list_float(builder, dirty, list); @@ -479,8 +479,8 @@ impl BlockFlow { debug!("build_display_list_block: adding display element"); // add box that starts block context - for box in self.box.iter() { - box.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list) + for box_ in self.box_.iter() { + box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list) } // TODO: handle any out-of-flow elements @@ -497,7 +497,7 @@ impl BlockFlow { &mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + list: &RefCell<DisplayList<E>>) -> bool { let abs_rect = Rect(self.base.abs_position, self.base.position.size); if !abs_rect.intersects(dirty) { @@ -506,8 +506,8 @@ impl BlockFlow { let offset = self.base.abs_position + self.float.get_ref().rel_pos; // add box that starts block context - for box in self.box.iter() { - box.build_display_list(builder, dirty, offset, (&*self) as &Flow, list) + for box_ in self.box_.iter() { + box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, list) } @@ -564,13 +564,13 @@ impl Flow for BlockFlow { /* if not an anonymous block context, add in block box's widths. these widths will not include child elements, just padding etc. */ - for box in self.box.iter() { + for box_ in self.box_.iter() { { // Can compute border width here since it doesn't depend on anything. - box.compute_borders(box.style()) + box_.compute_borders(box_.style()) } - let (this_minimum_width, this_preferred_width) = box.minimum_and_preferred_widths(); + let (this_minimum_width, this_preferred_width) = box_.minimum_and_preferred_widths(); min_width = min_width + this_minimum_width; pref_width = pref_width + this_preferred_width; } @@ -612,17 +612,17 @@ impl Flow for BlockFlow { self.base.flags.set_inorder(false); } - for box in self.box.iter() { - let style = box.style(); + for box_ in self.box_.iter() { + let style = box_.style(); // The text alignment of a block flow is the text alignment of its box's style. self.base.flags.set_text_align(style.Text.text_align); // Can compute padding here since we know containing block width. - box.compute_padding(style, remaining_width); + box_.compute_padding(style, remaining_width); // Margins are 0 right now so base.noncontent_width() is just borders + padding. - let available_width = remaining_width - box.noncontent_width(); + let available_width = remaining_width - box_.noncontent_width(); // Top and bottom margins for blocks are 0 if auto. let margin_top = MaybeAuto::from_style(style.Margin.margin_top, @@ -631,25 +631,25 @@ impl Flow for BlockFlow { remaining_width).specified_or_zero(); let (width, margin_left, margin_right) = if self.is_float() { - self.compute_float_margins(box, remaining_width) + self.compute_float_margins(box_, remaining_width) } else { - self.compute_block_margins(box, remaining_width, available_width) + self.compute_block_margins(box_, remaining_width, available_width) }; - box.margin.set(SideOffsets2D::new(margin_top, + box_.margin.set(SideOffsets2D::new(margin_top, margin_right, margin_bottom, margin_left)); - x_offset = box.offset(); + x_offset = box_.offset(); remaining_width = width; // The associated box is the border box of this flow. - let position_ref = box.position.mutate(); - position_ref.ptr.origin.x = box.margin.get().left; - let padding_and_borders = box.padding.get().left + box.padding.get().right + - box.border.get().left + box.border.get().right; - position_ref.ptr.size.width = remaining_width + padding_and_borders; + let mut position_ref = box_.position.borrow_mut(); + position_ref.get().origin.x = box_.margin.get().left; + let padding_and_borders = box_.padding.get().left + box_.padding.get().right + + box_.border.get().left + box_.border.get().right; + position_ref.get().size.width = remaining_width + padding_and_borders; } if self.is_float() { @@ -722,24 +722,24 @@ impl Flow for BlockFlow { return; } - for box in self.box.iter() { + for box_ in self.box_.iter() { // The top margin collapses with its first in-flow block-level child's // top margin if the parent has no top border, no top padding. if *first_in_flow && top_margin_collapsible { // If top-margin of parent is less than top-margin of its first child, // the parent box goes down until its top is aligned with the child. - if *margin_top < box.margin.get().top { + if *margin_top < box_.margin.get().top { // TODO: The position of child floats should be updated and this // would influence clearance as well. See #725 - let extra_margin = box.margin.get().top - *margin_top; + let extra_margin = box_.margin.get().top - *margin_top; *top_offset = *top_offset + extra_margin; - *margin_top = box.margin.get().top; + *margin_top = box_.margin.get().top; } } // The bottom margin of an in-flow block-level element collapses // with the top margin of its next in-flow block-level sibling. - *collapsing = geometry::min(box.margin.get().top, *collapsible); - *collapsible = box.margin.get().bottom; + *collapsing = geometry::min(box_.margin.get().top, *collapsible); + *collapsible = box_.margin.get().bottom; } *first_in_flow = false; @@ -757,7 +757,7 @@ impl Flow for BlockFlow { } else { ~"BlockFlow: " }; - txt.append(match self.box { + txt.append(match self.box_ { Some(ref rb) => rb.debug_str(), None => ~"", }) diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box_.rs index d1ed277a95b..57eed410b6a 100644 --- a/src/components/main/layout/box.rs +++ b/src/components/main/layout/box_.rs @@ -22,9 +22,8 @@ use servo_net::local_image_cache::LocalImageCache; use servo_util::geometry::Au; use servo_util::geometry; use servo_util::range::*; -use servo_util::slot::Slot; use std::cast; -use std::cell::Cell; +use std::cell::RefCell; use std::cmp::ApproxEq; use std::num::Zero; use style::{ComputedValues, TElement, TNode, cascade}; @@ -71,24 +70,24 @@ pub struct Box { style: Arc<ComputedValues>, /// The position of this box relative to its owning flow. - position: Slot<Rect<Au>>, + position: RefCell<Rect<Au>>, /// The border of the content box. /// /// FIXME(pcwalton): This need not be stored in the box. - border: Slot<SideOffsets2D<Au>>, + border: RefCell<SideOffsets2D<Au>>, /// The padding of the content box. - padding: Slot<SideOffsets2D<Au>>, + padding: RefCell<SideOffsets2D<Au>>, /// The margin of the content box. - margin: Slot<SideOffsets2D<Au>>, + margin: RefCell<SideOffsets2D<Au>>, /// Info specific to the kind of box. Keep this enum small. specific: SpecificBoxInfo, /// positioned box offsets - position_offsets: Slot<SideOffsets2D<Au>>, + position_offsets: RefCell<SideOffsets2D<Au>>, } /// Info specific to the kind of box. Keep this enum small. @@ -105,7 +104,7 @@ pub enum SpecificBoxInfo { #[deriving(Clone)] pub struct ImageBoxInfo { /// The image held within this box. - image: Slot<ImageHolder>, + image: RefCell<ImageHolder>, /// The width attribute supplied by the DOM, if any. dom_width: Option<Au>, /// The height attribute supplied by the DOM, if any. @@ -129,7 +128,7 @@ impl ImageBoxInfo { } ImageBoxInfo { - image: Slot::init(ImageHolder::new(image_url, local_image_cache)), + image: RefCell::new(ImageHolder::new(image_url, local_image_cache)), dom_width: convert_length(node, "width"), dom_height: convert_length(node, "height"), } @@ -139,7 +138,8 @@ impl ImageBoxInfo { fn image_width(&self) -> Au { // TODO(brson): Consult margins and borders? self.dom_width.unwrap_or_else(|| { - Au::from_px(self.image.mutate().ptr.get_size().unwrap_or(Size2D(0, 0)).width) + let mut image_ref = self.image.borrow_mut(); + Au::from_px(image_ref.get().get_size().unwrap_or(Size2D(0, 0)).width) }) } @@ -147,7 +147,8 @@ impl ImageBoxInfo { pub fn image_height(&self) -> Au { // TODO(brson): Consult margins and borders? self.dom_height.unwrap_or_else(|| { - Au::from_px(self.image.mutate().ptr.get_size().unwrap_or(Size2D(0, 0)).height) + let mut image_ref = self.image.borrow_mut(); + Au::from_px(image_ref.get().get_size().unwrap_or(Size2D(0, 0)).height) }) } } @@ -256,12 +257,12 @@ impl Box { Box { node: OpaqueNode::from_layout_node(&node), style: node_style, - position: Slot::init(Au::zero_rect()), - border: Slot::init(Zero::zero()), - padding: Slot::init(Zero::zero()), - margin: Slot::init(Zero::zero()), + position: RefCell::new(Au::zero_rect()), + border: RefCell::new(Zero::zero()), + padding: RefCell::new(Zero::zero()), + margin: RefCell::new(Zero::zero()), specific: specific, - position_offsets: Slot::init(Zero::zero()), + position_offsets: RefCell::new(Zero::zero()), } } @@ -279,12 +280,12 @@ impl Box { Box { node: self.node, style: self.style.clone(), - position: Slot::init(Rect(self.position.get().origin, size)), - border: Slot::init(self.border.get()), - padding: Slot::init(self.padding.get()), - margin: Slot::init(self.margin.get()), + position: RefCell::new(Rect(self.position.get().origin, size)), + border: RefCell::new(self.border.get()), + padding: RefCell::new(self.padding.get()), + margin: RefCell::new(self.margin.get()), specific: specific, - position_offsets: Slot::init(Zero::zero()) + position_offsets: RefCell::new(Zero::zero()) } } @@ -310,11 +311,6 @@ impl Box { self.border.get().left + self.border.get().right } - /// Sets the size of this box. - fn set_size(&self, new_size: Size2D<Au>) { - self.position.set(Rect(self.position.get().origin, new_size)) - } - pub fn calculate_line_height(&self, font_size: Au) -> Au { match self.line_height() { line_height::Normal => font_size.scale_by(1.14), @@ -408,11 +404,11 @@ impl Box { debug!("(font style) start"); // FIXME: Too much allocation here. - let font_families = do my_style.Font.font_family.map |family| { + let font_families = my_style.Font.font_family.map(|family| { match *family { font_family::FamilyName(ref name) => (*name).clone(), } - }; + }); debug!("(font style) font families: `{:?}`", font_families); let font_size = my_style.Font.font_size.to_f64().unwrap() / 60.0; @@ -465,7 +461,7 @@ impl Box { /// and so on. pub fn is_replaced(&self) -> bool { match self.specific { - ImageBox(*) => true, + ImageBox(..) => true, _ => false, } } @@ -473,7 +469,7 @@ impl Box { /// Returns true if this element can be split. This is true for text boxes. pub fn can_split(&self) -> bool { match self.specific { - ScannedTextBox(*) => true, + ScannedTextBox(..) => true, _ => false, } } @@ -496,7 +492,7 @@ impl Box { /// necessary. pub fn paint_background_if_applicable<E:ExtraDisplayListData>( &self, - list: &Cell<DisplayList<E>>, + list: &RefCell<DisplayList<E>>, absolute_bounds: &Rect<Au>) { // FIXME: This causes a lot of background colors to be displayed when they are clearly not // needed. We could use display list optimization to clean this up, but it still seems @@ -505,7 +501,7 @@ impl Box { let style = self.style(); let background_color = style.resolve_color(style.Background.background_color); if !background_color.alpha.approx_eq(&0.0) { - list.with_mut_ref(|list| { + list.with_mut(|list| { let solid_color_display_item = ~SolidColorDisplayItem { base: BaseDisplayItem { bounds: *absolute_bounds, @@ -523,7 +519,7 @@ impl Box { /// necessary. pub fn paint_borders_if_applicable<E:ExtraDisplayListData>( &self, - list: &Cell<DisplayList<E>>, + list: &RefCell<DisplayList<E>>, abs_bounds: &Rect<Au>) { // Fast path. let border = self.border.get(); @@ -542,7 +538,7 @@ impl Box { let left_style = style.Border.border_left_style; // Append the border to the display list. - do list.with_mut_ref |list| { + list.with_mut(|list| { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: *abs_bounds, @@ -560,7 +556,7 @@ impl Box { }; list.append_item(BorderDisplayItemClass(border_display_item)) - } + }); } /// Adds the display items for this box to the given display list. @@ -583,7 +579,7 @@ impl Box { dirty: &Rect<Au>, offset: Point2D<Au>, flow: &Flow, - list: &Cell<DisplayList<E>>) { + list: &RefCell<DisplayList<E>>) { let box_bounds = self.position.get(); let absolute_box_bounds = box_bounds.translate(&offset); debug!("Box::build_display_list at rel={}, abs={}: {:s}", @@ -607,7 +603,7 @@ impl Box { match self.specific { UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."), ScannedTextBox(ref text_box) => { - do list.with_mut_ref |list| { + list.with_mut(|list| { let item = ~ClipDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -617,7 +613,7 @@ impl Box { need_clip: false }; list.append_item(ClipDisplayItemClass(item)); - } + }); let color = self.style().Color.color.to_gfx_color(); @@ -629,7 +625,7 @@ impl Box { text_flags.set_override_line_through(flow_flags.override_line_through()); // Create the text box. - do list.with_mut_ref |list| { + list.with_mut(|list| { let text_display_item = ~TextDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -642,7 +638,7 @@ impl Box { }; list.append_item(TextDisplayItemClass(text_display_item)) - } + }); // Draw debug frames for text bounds. // @@ -652,7 +648,7 @@ impl Box { // Compute the text box bounds and draw a border surrounding them. let debug_border = SideOffsets2D::new_all_same(Au::from_px(1)); - do list.with_mut_ref |list| { + list.with_mut(|list| { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -664,7 +660,7 @@ impl Box { }; list.append_item(BorderDisplayItemClass(border_display_item)) - } + }); // Draw a rectangle representing the baselines. // @@ -674,7 +670,7 @@ impl Box { let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent), Size2D(absolute_box_bounds.size.width, Au(0))); - do list.with_mut_ref |list| { + list.with_mut(|list| { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: baseline, @@ -686,13 +682,11 @@ impl Box { }; list.append_item(BorderDisplayItemClass(border_display_item)) - } - - () + }); }); }, - GenericBox | IframeBox(_) => { - do list.with_mut_ref |list| { + GenericBox | IframeBox(..) => { + list.with_mut(|list| { let item = ~ClipDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -702,14 +696,14 @@ impl Box { need_clip: self.needs_clip() }; list.append_item(ClipDisplayItemClass(item)); - } + }); // FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We // should have a real `SERVO_DEBUG` system. debug!("{:?}", { let debug_border = SideOffsets2D::new_all_same(Au::from_px(1)); - do list.with_mut_ref |list| { + list.with_mut(|list| { let border_display_item = ~BorderDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -721,13 +715,11 @@ impl Box { }; list.append_item(BorderDisplayItemClass(border_display_item)) - } - - () + }); }); }, ImageBox(ref image_box) => { - do list.with_mut_ref |list| { + list.with_mut(|list| { let item = ~ClipDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -737,14 +729,15 @@ impl Box { need_clip: false }; list.append_item(ClipDisplayItemClass(item)); - } + }); - match image_box.image.mutate().ptr.get_image() { + let mut image_ref = image_box.image.borrow_mut(); + match image_ref.get().get_image() { Some(image) => { debug!("(building display list) building image box"); // Place the image into the display list. - do list.with_mut_ref |list| { + list.with_mut(|list| { let image_display_item = ~ImageDisplayItem { base: BaseDisplayItem { bounds: absolute_box_bounds, @@ -752,8 +745,8 @@ impl Box { }, image: image.clone(), }; - list.append_item(ImageDisplayItemClass(image_display_item)) - } + list.append_item(ImageDisplayItemClass(image_display_item)); + }); } None => { // No image data at all? Do nothing. @@ -809,7 +802,7 @@ impl Box { (min_line_width, max_line_width) } - UnscannedTextBox(*) => fail!("Unscanned text boxes should have been scanned by now!"), + UnscannedTextBox(..) => fail!("Unscanned text boxes should have been scanned by now!"), }; (guessed_width + additional_minimum, guessed_width + additional_preferred) } @@ -822,11 +815,12 @@ impl Box { match self.specific { GenericBox | IframeBox(_) => Au(0), ImageBox(ref image_box_info) => { - let size = image_box_info.image.mutate().ptr.get_size(); + let mut image_ref = image_box_info.image.borrow_mut(); + let size = image_ref.get().get_size(); let height = Au::from_px(size.unwrap_or(Size2D(0, 0)).height); // Eww. Refactor this. - self.position.mutate().ptr.size.height = height; + self.position.borrow_mut().get().size.height = height; debug!("box_height: found image height: {}", height); height @@ -955,11 +949,11 @@ impl Box { match self.specific { GenericBox | IframeBox(_) => { // FIXME(pcwalton): This seems clownshoes; can we remove? - self.position.mutate().ptr.size.width = Au::from_px(45) + self.position.borrow_mut().get().size.width = Au::from_px(45) } ImageBox(ref image_box_info) => { let image_width = image_box_info.image_width(); - self.position.mutate().ptr.size.width = image_width + self.position.borrow_mut().get().size.width = image_width } ScannedTextBox(_) => { // Scanned text boxes will have already had their widths assigned by this point. diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs index 80a8ffb8a1b..a0866cf934c 100644 --- a/src/components/main/layout/construct.rs +++ b/src/components/main/layout/construct.rs @@ -22,8 +22,8 @@ use css::node_style::StyledNode; use layout::block::BlockFlow; -use layout::box::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo}; -use layout::box::{UnscannedTextBox, UnscannedTextBoxInfo}; +use layout::box_::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo}; +use layout::box_::{UnscannedTextBox, UnscannedTextBoxInfo}; use layout::context::LayoutContext; use layout::float_context::FloatType; use layout::flow::{Flow, FlowData, MutableFlowUtils}; @@ -35,10 +35,11 @@ use layout::wrapper::{LayoutNode, PostorderNodeMutTraversal}; use script::dom::element::{HTMLIframeElementTypeId, HTMLImageElementTypeId}; use script::dom::node::{CommentNodeTypeId, DoctypeNodeTypeId, DocumentFragmentNodeTypeId}; use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, TextNodeTypeId}; -use servo_util::slot::Slot; -use std::util; use style::computed_values::{display, float}; +use std::cell::RefCell; +use std::util; + /// The results of flow construction for a DOM node. pub enum ConstructionResult { /// This node contributes nothing at all (`display: none`). Alternately, this is what newly @@ -47,7 +48,7 @@ pub enum ConstructionResult { /// This node contributed a flow at the proper position in the tree. Nothing more needs to be /// done for this node. - FlowConstructionResult(~Flow:), + FlowConstructionResult(~Flow), /// This node contributed some object or objects that will be needed to construct a proper flow /// later up the tree, but these objects have not yet found their home. @@ -102,7 +103,7 @@ struct InlineBlockSplit { predecessor_boxes: ~[Box], /// The flow that caused this {ib} split. - flow: ~Flow:, + flow: ~Flow, } /// Methods on optional vectors. @@ -169,24 +170,24 @@ impl<T> OptVector<T> for Option<~[T]> { } /// An object that knows how to create flows. -pub struct FlowConstructor<'self> { +pub struct FlowConstructor<'a> { /// The layout context. /// /// FIXME(pcwalton): Why does this contain `@`??? That destroys parallelism!!! - layout_context: &'self mut LayoutContext, + layout_context: &'a mut LayoutContext, /// The next flow ID to assign. /// /// FIXME(pcwalton): This is going to have to be atomic; can't we do something better? - next_flow_id: Slot<int>, + next_flow_id: RefCell<int>, } -impl<'self> FlowConstructor<'self> { +impl<'fc> FlowConstructor<'fc> { /// Creates a new flow constructor. pub fn init<'a>(layout_context: &'a mut LayoutContext) -> FlowConstructor<'a> { FlowConstructor { layout_context: layout_context, - next_flow_id: Slot::init(0), + next_flow_id: RefCell::new(0), } } @@ -231,10 +232,10 @@ impl<'self> FlowConstructor<'self> { /// `#[inline(always)]` because this is performance critical and LLVM will not inline it /// otherwise. #[inline(always)] - fn flush_inline_boxes_to_flow(&mut self, boxes: ~[Box], flow: &mut ~Flow:, node: LayoutNode) { + fn flush_inline_boxes_to_flow(&mut self, boxes: ~[Box], flow: &mut ~Flow, node: LayoutNode) { if boxes.len() > 0 { let inline_base = FlowData::new(self.next_flow_id(), node); - let mut inline_flow = ~InlineFlow::from_boxes(inline_base, boxes) as ~Flow:; + let mut inline_flow = ~InlineFlow::from_boxes(inline_base, boxes) as ~Flow; TextRunScanner::new().scan_for_runs(self.layout_context, inline_flow); flow.add_new_child(inline_flow) } @@ -244,7 +245,7 @@ impl<'self> FlowConstructor<'self> { /// the given flow. fn flush_inline_boxes_to_flow_if_necessary(&mut self, opt_boxes: &mut Option<~[Box]>, - flow: &mut ~Flow:, + flow: &mut ~Flow, node: LayoutNode) { let opt_boxes = util::replace(opt_boxes, None); if opt_boxes.len() > 0 { @@ -256,7 +257,7 @@ impl<'self> FlowConstructor<'self> { /// other `BlockFlow`s or `InlineFlow`s will be populated underneath this node, depending on /// whether {ib} splits needed to happen. fn build_children_of_block_flow(&mut self, - flow: &mut ~Flow:, + flow: &mut ~Flow, node: LayoutNode) { // Gather up boxes for the inline flows we might need to create. let mut opt_boxes_for_inline_flow = None; @@ -342,10 +343,10 @@ impl<'self> FlowConstructor<'self> { /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly /// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed /// to happen. - fn build_flow_for_block(&mut self, node: LayoutNode) -> ~Flow: { + fn build_flow_for_block(&mut self, node: LayoutNode) -> ~Flow { let base = FlowData::new(self.next_flow_id(), node); - let box = self.build_box_for_node(node); - let mut flow = ~BlockFlow::from_box(base, box) as ~Flow:; + let box_ = self.build_box_for_node(node); + let mut flow = ~BlockFlow::from_box(base, box_) as ~Flow; self.build_children_of_block_flow(&mut flow, node); flow } @@ -353,10 +354,10 @@ impl<'self> FlowConstructor<'self> { /// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with /// a `BlockFlow` underneath it. fn build_flow_for_floated_block(&mut self, node: LayoutNode, float_type: FloatType) - -> ~Flow: { + -> ~Flow { let base = FlowData::new(self.next_flow_id(), node); - let box = self.build_box_for_node(node); - let mut flow = ~BlockFlow::float_from_box(base, float_type, box) as ~Flow:; + let box_ = self.build_box_for_node(node); + let mut flow = ~BlockFlow::float_from_box(base, float_type, box_) as ~Flow; self.build_children_of_block_flow(&mut flow, node); flow } @@ -458,7 +459,7 @@ impl<'self> FlowConstructor<'self> { } } -impl<'self> PostorderNodeMutTraversal for FlowConstructor<'self> { +impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { // `#[inline(always)]` because this is always called from the traversal function and for some // reason LLVM's inlining heuristics go awry here. #[inline(always)] @@ -528,7 +529,7 @@ trait NodeUtils { fn swap_out_construction_result(self) -> ConstructionResult; } -impl<'self> NodeUtils for LayoutNode<'self> { +impl<'ln> NodeUtils for LayoutNode<'ln> { fn is_replaced_content(self) -> bool { match self.type_id() { TextNodeTypeId | @@ -543,17 +544,19 @@ impl<'self> NodeUtils for LayoutNode<'self> { #[inline(always)] fn set_flow_construction_result(self, result: ConstructionResult) { - match *self.mutate_layout_data().ptr { - Some(ref mut layout_data) => layout_data.flow_construction_result = result, + let mut layout_data_ref = self.mutate_layout_data(); + match *layout_data_ref.get() { + Some(ref mut layout_data) => layout_data.data.flow_construction_result = result, None => fail!("no layout data"), } } #[inline(always)] fn swap_out_construction_result(self) -> ConstructionResult { - match *self.mutate_layout_data().ptr { + let mut layout_data_ref = self.mutate_layout_data(); + match *layout_data_ref.get() { Some(ref mut layout_data) => { - util::replace(&mut layout_data.flow_construction_result, NoConstructionResult) + util::replace(&mut layout_data.data.flow_construction_result, NoConstructionResult) } None => fail!("no layout data"), } @@ -568,14 +571,14 @@ fn strip_ignorable_whitespace_from_start(opt_boxes: &mut Option<~[Box]>) { // FIXME(pcwalton): This is slow because vector shift is broken. :( let mut found_nonwhitespace = false; let mut result = ~[]; - for box in boxes.move_iter() { - if !found_nonwhitespace && box.is_whitespace_only() { + for box_ in boxes.move_iter() { + if !found_nonwhitespace && box_.is_whitespace_only() { debug!("stripping ignorable whitespace from start"); continue } found_nonwhitespace = true; - result.push(box) + result.push(box_) } *opt_boxes = Some(result) diff --git a/src/components/main/layout/display_list_builder.rs b/src/components/main/layout/display_list_builder.rs index 7dd538d493d..dc20f784667 100644 --- a/src/components/main/layout/display_list_builder.rs +++ b/src/components/main/layout/display_list_builder.rs @@ -4,7 +4,7 @@ //! Constructs display lists from boxes. -use layout::box::Box; +use layout::box_::Box; use layout::context::LayoutContext; use layout::util::OpaqueNode; @@ -12,14 +12,14 @@ use gfx; use style; pub trait ExtraDisplayListData { - fn new(box: &Box) -> Self; + fn new(box_: &Box) -> Self; } pub type Nothing = (); impl ExtraDisplayListData for OpaqueNode { - fn new(box: &Box) -> OpaqueNode { - box.node + fn new(box_: &Box) -> OpaqueNode { + box_.node } } @@ -35,8 +35,8 @@ impl ExtraDisplayListData for Nothing { /// /// Right now, the builder isn't used for much, but it establishes the pattern we'll need once we /// support display-list-based hit testing and so forth. -pub struct DisplayListBuilder<'self> { - ctx: &'self LayoutContext, +pub struct DisplayListBuilder<'a> { + ctx: &'a LayoutContext, } // diff --git a/src/components/main/layout/extra.rs b/src/components/main/layout/extra.rs index c17bfc4e0e4..ba7cf8a2595 100644 --- a/src/components/main/layout/extra.rs +++ b/src/components/main/layout/extra.rs @@ -4,33 +4,39 @@ //! Code for managing the layout data in the DOM. -use layout::util::{LayoutData, LayoutDataAccess}; +use layout::util::{PrivateLayoutData, LayoutDataAccess, LayoutDataWrapper}; use layout::wrapper::LayoutNode; +use script::layout_interface::LayoutChan; /// Functionality useful for querying the layout-specific data on DOM nodes. pub trait LayoutAuxMethods { - fn initialize_layout_data(self); - fn initialize_style_for_subtree(self); + fn initialize_layout_data(self, chan: LayoutChan); + fn initialize_style_for_subtree(self, chan: LayoutChan); } -impl<'self> LayoutAuxMethods for LayoutNode<'self> { +impl<'ln> LayoutAuxMethods for LayoutNode<'ln> { /// Resets layout data and styles for the node. /// /// FIXME(pcwalton): Do this as part of box building instead of in a traversal. - fn initialize_layout_data(self) { - let layout_data_handle = self.mutate_layout_data(); - match *layout_data_handle.ptr { - None => *layout_data_handle.ptr = Some(~LayoutData::new()), + fn initialize_layout_data(self, chan: LayoutChan) { + let mut layout_data_ref = self.mutate_layout_data(); + match *layout_data_ref.get() { + None => { + *layout_data_ref.get() = Some(LayoutDataWrapper { + chan: Some(chan), + data: ~PrivateLayoutData::new(), + }); + } Some(_) => {} } } /// Resets layout data and styles for a Node tree. - /// + /// /// FIXME(pcwalton): Do this as part of box building instead of in a traversal. - fn initialize_style_for_subtree(self) { + fn initialize_style_for_subtree(self, chan: LayoutChan) { for n in self.traverse_preorder() { - n.initialize_layout_data(); + n.initialize_layout_data(chan.clone()); } } } diff --git a/src/components/main/layout/float_context.rs b/src/components/main/layout/float_context.rs index 7a92554401c..e61d3eb11c7 100644 --- a/src/components/main/layout/float_context.rs +++ b/src/components/main/layout/float_context.rs @@ -77,7 +77,7 @@ impl FloatContext { } #[inline(always)] - fn with_mut_base<R>(&mut self, callback: &fn(&mut FloatContextBase) -> R) -> R { + fn with_mut_base<R>(&mut self, callback: |&mut FloatContextBase| -> R) -> R { match *self { Invalid => fail!("Float context no longer available"), Valid(ref mut base) => callback(&mut *base) @@ -85,7 +85,7 @@ impl FloatContext { } #[inline(always)] - pub fn with_base<R>(&self, callback: &fn(&FloatContextBase) -> R) -> R { + pub fn with_base<R>(&self, callback: |&FloatContextBase| -> R) -> R { match *self { Invalid => fail!("Float context no longer available"), Valid(ref base) => callback(&*base) @@ -94,46 +94,46 @@ impl FloatContext { #[inline(always)] pub fn translate(&mut self, trans: Point2D<Au>) -> FloatContext { - do self.with_mut_base |base| { + self.with_mut_base(|base| { base.translate(trans); - } + }); replace(self, Invalid) } #[inline(always)] pub fn available_rect(&mut self, top: Au, height: Au, max_x: Au) -> Option<Rect<Au>> { - do self.with_base |base| { + self.with_base(|base| { base.available_rect(top, height, max_x) - } + }) } #[inline(always)] pub fn add_float(&mut self, info: &PlacementInfo) -> FloatContext{ - do self.with_mut_base |base| { + self.with_mut_base(|base| { base.add_float(info); - } + }); replace(self, Invalid) } #[inline(always)] pub fn place_between_floats(&self, info: &PlacementInfo) -> Rect<Au> { - do self.with_base |base| { + self.with_base(|base| { base.place_between_floats(info) - } + }) } #[inline(always)] pub fn last_float_pos(&mut self) -> Point2D<Au> { - do self.with_base |base| { + self.with_base(|base| { base.last_float_pos() - } + }) } #[inline(always)] pub fn clearance(&self, clear: ClearType) -> Au { - do self.with_base |base| { + self.with_base(|base| { base.clearance(clear) - } + }) } } @@ -288,24 +288,6 @@ impl FloatContextBase { self.floats_used += 1; } - /// Returns true if the given rect overlaps with any floats. - fn collides_with_float(&self, bounds: &Rect<Au>) -> bool { - for floats in self.float_data.iter() { - for float in floats.iter() { - match *float { - None => (), - Some(data) => { - if data.bounds.translate(&self.offset).intersects(bounds) { - return true; - } - } - }; - } - } - - return false; - } - /// Given the top 3 sides of the rectange, finds the largest height that /// will result in the rectange not colliding with any floats. Returns /// None if that height is infinite. diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index d7d1f602f29..d6b377d92bc 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -27,7 +27,7 @@ use css::node_style::StyledNode; use layout::block::BlockFlow; -use layout::box::Box; +use layout::box_::Box; use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::float_context::{FloatContext, Invalid}; @@ -42,7 +42,7 @@ use geom::rect::Rect; use gfx::display_list::{ClipDisplayItemClass, DisplayList}; use servo_util::geometry::Au; use std::cast; -use std::cell::Cell; +use std::cell::RefCell; use style::ComputedValues; use style::computed_values::text_align; @@ -127,7 +127,7 @@ pub fn base<'a>(this: &'a Flow) -> &'a FlowData { } /// Iterates over the children of this immutable flow. -pub fn imm_child_iter<'a>(flow: &'a Flow) -> DListIterator<'a,~Flow:> { +pub fn imm_child_iter<'a>(flow: &'a Flow) -> DListIterator<'a,~Flow> { base(flow).children.iter() } @@ -140,12 +140,12 @@ pub fn mut_base<'a>(this: &'a mut Flow) -> &'a mut FlowData { } /// Returns the last child of this flow. -pub fn last_child<'a>(flow: &'a mut Flow) -> Option<&'a mut ~Flow:> { +pub fn last_child<'a>(flow: &'a mut Flow) -> Option<&'a mut ~Flow> { mut_base(flow).children.back_mut() } /// Iterates over the children of this flow. -pub fn child_iter<'a>(flow: &'a mut Flow) -> MutDListIterator<'a,~Flow:> { +pub fn child_iter<'a>(flow: &'a mut Flow) -> MutDListIterator<'a,~Flow> { mut_base(flow).children.mut_iter() } @@ -183,13 +183,13 @@ pub trait MutableFlowUtils { // Mutators /// Adds a new flow as a child of this flow. - fn add_new_child(self, new_child: ~Flow:); + fn add_new_child(self, new_child: ~Flow); /// Invokes a closure with the first child of this flow. - fn with_first_child<R>(self, f: &fn(Option<&mut ~Flow:>) -> R) -> R; + fn with_first_child<R>(self, f: |Option<&mut ~Flow>| -> R) -> R; /// Invokes a closure with the last child of this flow. - fn with_last_child<R>(self, f: &fn(Option<&mut ~Flow:>) -> R) -> R; + fn with_last_child<R>(self, f: |Option<&mut ~Flow>| -> R) -> R; /// Removes the first child of this flow and destroys it. fn remove_first(self); @@ -205,7 +205,7 @@ pub trait MutableFlowUtils { self, builder: &DisplayListBuilder, dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + list: &RefCell<DisplayList<E>>) -> bool; } @@ -385,7 +385,7 @@ pub struct FlowData { restyle_damage: RestyleDamage, /// The children of this flow. - children: DList<~Flow:>, + children: DList<~Flow>, /* TODO (Issue #87): debug only */ id: int, @@ -454,12 +454,12 @@ impl FlowData { } } - pub fn child_iter<'a>(&'a mut self) -> MutDListIterator<'a,~Flow:> { + pub fn child_iter<'a>(&'a mut self) -> MutDListIterator<'a,~Flow> { self.children.mut_iter() } } -impl<'self> ImmutableFlowUtils for &'self Flow { +impl<'a> ImmutableFlowUtils for &'a Flow { /// Returns true if this flow is a block or a float flow. fn is_block_like(self) -> bool { match self.class() { @@ -508,7 +508,7 @@ impl<'self> ImmutableFlowUtils for &'self Flow { } } -impl<'self> MutableFlowUtils for &'self mut Flow { +impl<'a> MutableFlowUtils for &'a mut Flow { /// Traverses the tree in preorder. fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &mut T) -> bool { if traversal.should_prune(self) { @@ -548,17 +548,17 @@ impl<'self> MutableFlowUtils for &'self mut Flow { } /// Adds a new flow as a child of this flow. - fn add_new_child(self, new_child: ~Flow:) { + fn add_new_child(self, new_child: ~Flow) { mut_base(self).children.push_back(new_child) } /// Invokes a closure with the first child of this flow. - fn with_first_child<R>(self, f: &fn(Option<&mut ~Flow:>) -> R) -> R { + fn with_first_child<R>(self, f: |Option<&mut ~Flow>| -> R) -> R { f(mut_base(self).children.front_mut()) } /// Invokes a closure with the last child of this flow. - fn with_last_child<R>(self, f: &fn(Option<&mut ~Flow:>) -> R) -> R { + fn with_last_child<R>(self, f: |Option<&mut ~Flow>| -> R) -> R { f(mut_base(self).children.back_mut()) } @@ -587,7 +587,7 @@ impl<'self> MutableFlowUtils for &'self mut Flow { self, builder: &DisplayListBuilder, dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + list: &RefCell<DisplayList<E>>) -> bool { debug!("Flow: building display list for f{}", base(self).id); match self.class() { @@ -596,20 +596,21 @@ impl<'self> MutableFlowUtils for &'self mut Flow { _ => fail!("Tried to build_display_list_recurse of flow: {:?}", self), }; - if list.with_mut_ref(|list| list.list.len() == 0) { + if list.with_mut(|list| list.list.len() == 0) { return true; } - let child_list = ~Cell::new(DisplayList::new()); + let child_list = ~RefCell::new(DisplayList::new()); for kid in child_iter(self) { kid.build_display_list(builder,dirty,child_list); } - do list.with_mut_ref |list| { + let mut child_list = Some(child_list.unwrap()); + list.with_mut(|list| { let result = list.list.mut_rev_iter().position(|item| { match *item { ClipDisplayItemClass(ref mut item) => { - item.child_list.push_all_move(child_list.take().list); + item.child_list.push_all_move(child_list.take_unwrap().list); true }, _ => false, @@ -620,7 +621,7 @@ impl<'self> MutableFlowUtils for &'self mut Flow { fail!("fail to find parent item"); } - } + }); true } } diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 455f05a9249..42af73fab6c 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -3,14 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use css::node_style::StyledNode; -use layout::box::{Box, CannotSplit, GenericBox, IframeBox, ImageBox, ScannedTextBox, SplitDidFit}; -use layout::box::{SplitDidNotFit, UnscannedTextBox}; +use layout::box_::{Box, CannotSplit, GenericBox, IframeBox, ImageBox, ScannedTextBox, SplitDidFit}; +use layout::box_::{SplitDidNotFit, UnscannedTextBox}; use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::flow::{FlowClass, Flow, FlowData, InlineFlowClass}; use layout::flow; use layout::float_context::FloatContext; -use layout::util::{ElementMapping}; +use layout::util::ElementMapping; use layout::float_context::{PlacementInfo, FloatLeft}; use extra::container::Deque; @@ -19,7 +19,7 @@ use geom::{Point2D, Rect, Size2D}; use gfx::display_list::DisplayList; use servo_util::geometry::Au; use servo_util::range::Range; -use std::cell::Cell; +use std::cell::RefCell; use std::u16; use std::util; use style::computed_values::{text_align, vertical_align}; @@ -80,18 +80,6 @@ impl LineboxScanner { } } - fn reinitialize(&mut self, float_ctx: FloatContext) { - self.floats = float_ctx; - self.new_boxes.truncate(0); - self.work_list.clear(); - self.pending_line.range = Range::empty(); - self.pending_line.bounds = Rect(Point2D(Au::new(0), Au::new(0)), - Size2D(Au::new(0), Au::new(0))); - self.pending_line.green_zone = Size2D(Au::new(0), Au::new(0)); - self.lines.truncate(0); - self.cur_y = Au::new(0); - } - pub fn floats_out(&mut self) -> FloatContext { self.floats.clone() } @@ -119,13 +107,13 @@ impl LineboxScanner { if flow.boxes.is_empty() { break; } - let box = flow.boxes.remove(0); // FIXME: use a linkedlist - debug!("LineboxScanner: Working with box from box list: b{}", box.debug_id()); - box + let box_ = flow.boxes.remove(0); // FIXME: use a linkedlist + debug!("LineboxScanner: Working with box from box list: b{}", box_.debug_id()); + box_ } else { - let box = self.work_list.pop_front().unwrap(); - debug!("LineboxScanner: Working with box from work list: b{}", box.debug_id()); - box + let box_ = self.work_list.pop_front().unwrap(); + debug!("LineboxScanner: Working with box from work list: b{}", box_.debug_id()); + box_ }; let box_was_appended = self.try_append_to_line(cur_box, flow); @@ -413,8 +401,8 @@ impl LineboxScanner { } // An unconditional push - fn push_box_to_line(&mut self, box: Box) { - debug!("LineboxScanner: Pushing box {} to line {:u}", box.debug_id(), self.lines.len()); + fn push_box_to_line(&mut self, box_: Box) { + debug!("LineboxScanner: Pushing box {} to line {:u}", box_.debug_id(), self.lines.len()); if self.pending_line.range.length() == 0 { assert!(self.new_boxes.len() <= (u16::max_value as uint)); @@ -422,10 +410,10 @@ impl LineboxScanner { } self.pending_line.range.extend_by(1); self.pending_line.bounds.size.width = self.pending_line.bounds.size.width + - box.position.get().size.width; + box_.position.get().size.width; self.pending_line.bounds.size.height = Au::max(self.pending_line.bounds.size.height, - box.position.get().size.height); - self.new_boxes.push(box); + box_.position.get().size.height); + self.new_boxes.push(box_); } } @@ -467,8 +455,8 @@ impl InlineFlow { } pub fn teardown(&mut self) { - for box in self.boxes.iter() { - box.teardown(); + for box_ in self.boxes.iter() { + box_.teardown(); } self.boxes = ~[]; } @@ -477,7 +465,7 @@ impl InlineFlow { &self, builder: &DisplayListBuilder, dirty: &Rect<Au>, - list: &Cell<DisplayList<E>>) + list: &RefCell<DisplayList<E>>) -> bool { let abs_rect = Rect(self.base.abs_position, self.base.position.size); if !abs_rect.intersects(dirty) { @@ -490,8 +478,8 @@ impl InlineFlow { self.base.id, self.boxes.len()); - for box in self.boxes.iter() { - box.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list) + for box_ in self.boxes.iter() { + box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list) } // TODO(#225): Should `inline-block` elements have flows as children of the inline flow or @@ -590,9 +578,9 @@ impl InlineFlow { }; for i in line.range.eachi() { - let box = &boxes[i]; - let size = box.position.get().size; - box.position.set(Rect(Point2D(offset_x, box.position.get().origin.y), size)); + let box_ = &boxes[i]; + let size = box_.position.get().size; + box_.position.set(Rect(Point2D(offset_x, box_.position.get().origin.y), size)); offset_x = offset_x + size.width; } } @@ -623,10 +611,10 @@ impl Flow for InlineFlow { let mut min_width = Au::new(0); let mut pref_width = Au::new(0); - for box in self.boxes.iter() { - debug!("Flow[{:d}]: measuring {:s}", self.base.id, box.debug_str()); + for box_ in self.boxes.iter() { + debug!("Flow[{:d}]: measuring {:s}", self.base.id, box_.debug_str()); let (this_minimum_width, this_preferred_width) = - box.minimum_and_preferred_widths(); + box_.minimum_and_preferred_widths(); min_width = Au::max(min_width, this_minimum_width); pref_width = Au::max(pref_width, this_preferred_width); } @@ -647,8 +635,8 @@ impl Flow for InlineFlow { { let this = &mut *self; - for box in this.boxes.iter() { - box.assign_width(); + for box_ in this.boxes.iter() { + box_.assign_width(); } } @@ -736,9 +724,9 @@ impl Flow for InlineFlow { let noncontent_height = top + bottom; height = height + noncontent_height; - let position_ref = cur_box.position.mutate(); - position_ref.ptr.size.height = height; - position_ref.ptr.translate(&Point2D(Au::new(0), -height)); + let mut position_ref = cur_box.position.borrow_mut(); + position_ref.get().size.height = height; + position_ref.get().translate(&Point2D(Au::new(0), -height)); let ascent = height + bottom; (height, Au::new(0), ascent) @@ -818,7 +806,7 @@ impl Flow for InlineFlow { bottommost = bottom_from_base; } - cur_box.position.mutate().ptr.origin.y = line.bounds.origin.y + offset; + cur_box.position.borrow_mut().get().origin.y = line.bounds.origin.y + offset; } // Calculate the distance from baseline to the top of the biggest box with 'bottom' @@ -847,7 +835,7 @@ impl Flow for InlineFlow { _ => baseline_offset, }; - cur_box.position.mutate().ptr.origin.y = cur_box.position.get().origin.y + + cur_box.position.borrow_mut().get().origin.y = cur_box.position.get().origin.y + adjust_offset; } diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 2224401188a..740576617fd 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -16,7 +16,7 @@ use layout::flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTrave use layout::flow::{PostorderFlowTraversal}; use layout::flow; use layout::incremental::{RestyleDamage}; -use layout::util::{LayoutData, LayoutDataAccess, OpaqueNode}; +use layout::util::{LayoutDataAccess, OpaqueNode, LayoutDataWrapper}; use layout::wrapper::LayoutNode; use extra::arc::{Arc, RWArc, MutexArc}; @@ -34,7 +34,7 @@ use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId}; use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery}; use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitNowMsg, LayoutQuery}; use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse}; -use script::layout_interface::{ContentChangedDocumentDamage, Msg, PrepareToExitMsg}; +use script::layout_interface::{ContentChangedDocumentDamage, LayoutChan, Msg, PrepareToExitMsg}; use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, ReflowDocumentDamage}; use script::layout_interface::{ReflowForDisplay, ReflowMsg}; use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg}; @@ -46,20 +46,22 @@ use servo_util::time::{ProfilerChan, profile}; use servo_util::time; use std::cast::transmute; use std::cast; -use std::cell::Cell; +use std::cell::RefCell; use std::comm::Port; -use std::task; use std::util; use style::{AuthorOrigin, Stylesheet, Stylist}; /// Information needed by the layout task. -struct LayoutTask { +pub struct LayoutTask { /// The ID of the pipeline that we belong to. id: PipelineId, /// The port on which we receive messages. port: Port<Msg>, + //// The channel to send messages to ourself. + chan: LayoutChan, + /// The channel on which messages can be sent to the constellation. constellation_chan: ConstellationChan, @@ -132,9 +134,9 @@ impl PreorderFlowTraversal for PropagateDamageTraversal { /// The bubble-widths traversal, the first part of layout computation. This computes preferred /// and intrinsic widths and bubbles them up the tree. -struct BubbleWidthsTraversal<'self>(&'self mut LayoutContext); +struct BubbleWidthsTraversal<'a>(&'a mut LayoutContext); -impl<'self> PostorderFlowTraversal for BubbleWidthsTraversal<'self> { +impl<'a> PostorderFlowTraversal for BubbleWidthsTraversal<'a> { #[inline] fn process(&mut self, flow: &mut Flow) -> bool { flow.bubble_widths(**self); @@ -151,9 +153,9 @@ impl<'self> PostorderFlowTraversal for BubbleWidthsTraversal<'self> { } /// The assign-widths traversal. In Gecko this corresponds to `Reflow`. -struct AssignWidthsTraversal<'self>(&'self mut LayoutContext); +struct AssignWidthsTraversal<'a>(&'a mut LayoutContext); -impl<'self> PreorderFlowTraversal for AssignWidthsTraversal<'self> { +impl<'a> PreorderFlowTraversal for AssignWidthsTraversal<'a> { #[inline] fn process(&mut self, flow: &mut Flow) -> bool { flow.assign_widths(**self); @@ -164,9 +166,9 @@ impl<'self> PreorderFlowTraversal for AssignWidthsTraversal<'self> { /// The assign-heights-and-store-overflow traversal, the last (and most expensive) part of layout /// computation. Determines the final heights for all layout objects, computes positions, and /// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`. -struct AssignHeightsAndStoreOverflowTraversal<'self>(&'self mut LayoutContext); +struct AssignHeightsAndStoreOverflowTraversal<'a>(&'a mut LayoutContext); -impl<'self> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'self> { +impl<'a> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'a> { #[inline] fn process(&mut self, flow: &mut Flow) -> bool { flow.assign_height(**self); @@ -186,10 +188,10 @@ struct LayoutImageResponder { } impl ImageResponder for LayoutImageResponder { - fn respond(&self) -> ~fn(ImageResponseMsg) { + fn respond(&self) -> proc(ImageResponseMsg) { let id = self.id.clone(); let script_chan = self.script_chan.clone(); - let f: ~fn(ImageResponseMsg) = |_| { + let f: proc(ImageResponseMsg) = proc(_) { script_chan.send(SendEventMsg(id.clone(), ReflowEvent)) }; f @@ -200,6 +202,7 @@ impl LayoutTask { /// Spawns a new layout task. pub fn create(id: PipelineId, port: Port<Msg>, + chan: LayoutChan, constellation_chan: ConstellationChan, script_chan: ScriptChan, render_chan: RenderChan<OpaqueNode>, @@ -207,11 +210,11 @@ impl LayoutTask { opts: Opts, profiler_chan: ProfilerChan, shutdown_chan: Chan<()>) { - spawn_with!(task::task(), [port, constellation_chan, script_chan, - render_chan, img_cache_task, profiler_chan, shutdown_chan], { - { // Ensures LayoutTask gets destroyed before we send the shutdown message + spawn(proc() { + { // Ensures layout task is destroyed before we send shutdown message let mut layout = LayoutTask::new(id, port, + chan, constellation_chan, script_chan, render_chan, @@ -220,7 +223,6 @@ impl LayoutTask { profiler_chan); layout.start(); } - shutdown_chan.send(()); }); } @@ -228,6 +230,7 @@ impl LayoutTask { /// Creates a new `LayoutTask` structure. fn new(id: PipelineId, port: Port<Msg>, + chan: LayoutChan, constellation_chan: ConstellationChan, script_chan: ScriptChan, render_chan: RenderChan<OpaqueNode>, @@ -239,6 +242,7 @@ impl LayoutTask { LayoutTask { id: id, port: port, + chan: chan, constellation_chan: constellation_chan, script_chan: script_chan, render_chan: render_chan, @@ -281,17 +285,15 @@ impl LayoutTask { match self.port.recv() { AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet), ReflowMsg(data) => { - let data = Cell::new(data); - - do profile(time::LayoutPerformCategory, self.profiler_chan.clone()) { - self.handle_reflow(data.take()); - } + profile(time::LayoutPerformCategory, self.profiler_chan.clone(), || { + self.handle_reflow(data); + }); } QueryMsg(query) => { - let query = Cell::new(query); - do profile(time::LayoutQueryCategory, self.profiler_chan.clone()) { - self.handle_query(query.take()); - } + let mut query = Some(query); + profile(time::LayoutQueryCategory, self.profiler_chan.clone(), || { + self.handle_query(query.take_unwrap()); + }); } ReapLayoutDataMsg(dead_layout_data) => { unsafe { @@ -340,16 +342,16 @@ impl LayoutTask { /// Shuts down the layout task now. If there are any DOM nodes left, layout will now (safely) /// crash. fn exit_now(&mut self) { - let (response_port, response_chan) = stream(); + let (response_port, response_chan) = Chan::new(); self.render_chan.send(render_task::ExitMsg(response_chan)); response_port.recv() } fn handle_add_stylesheet(&mut self, sheet: Stylesheet) { - let sheet = Cell::new(sheet); - do self.stylist.write |stylist| { - stylist.add_stylesheet(sheet.take(), AuthorOrigin); - } + let mut sheet = Some(sheet); + self.stylist.write(|stylist| { + stylist.add_stylesheet(sheet.take_unwrap(), AuthorOrigin); + }); } /// Builds the flow tree. @@ -359,12 +361,13 @@ impl LayoutTask { /// is intertwined with selector matching, making it difficult to compare directly. It is /// marked `#[inline(never)]` to aid benchmarking in sampling profilers. #[inline(never)] - fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: LayoutNode) -> ~Flow: { + fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: LayoutNode) -> ~Flow { node.traverse_postorder_mut(&mut FlowConstructor::init(layout_context)); - let result = match *node.mutate_layout_data().ptr { + let mut layout_data_ref = node.mutate_layout_data(); + let result = match *layout_data_ref.get() { Some(ref mut layout_data) => { - util::replace(&mut layout_data.flow_construction_result, NoConstructionResult) + util::replace(&mut layout_data.data.flow_construction_result, NoConstructionResult) } None => fail!("no layout data for root node"), }; @@ -436,18 +439,18 @@ impl LayoutTask { // Initialize layout data for each node. // // FIXME: This is inefficient. We don't need an entire traversal to do this! - do profile(time::LayoutAuxInitCategory, self.profiler_chan.clone()) { - node.initialize_style_for_subtree(); - } + profile(time::LayoutAuxInitCategory, self.profiler_chan.clone(), || { + node.initialize_style_for_subtree(self.chan.clone()); + }); // Perform CSS selector matching if necessary. match data.damage.level { ReflowDocumentDamage => {} _ => { - do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) { + profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone(), || { node.match_subtree(self.stylist.clone()); node.cascade_subtree(None); - } + }); } } @@ -464,25 +467,25 @@ impl LayoutTask { // Perform the primary layout passes over the flow tree to compute the locations of all // the boxes. - do profile(time::LayoutMainCategory, self.profiler_chan.clone()) { + profile(time::LayoutMainCategory, self.profiler_chan.clone(), || { self.solve_constraints(layout_root, &mut layout_ctx) - } + }); debug!("layout: constraint solving done:"); debug!("{:?}", layout_root.dump()); // Build the display list if necessary, and send it to the renderer. if data.goal == ReflowForDisplay { - do profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone()) { + profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || { let root_size = flow::base(layout_root).position.size; - let display_list = ~Cell::new(DisplayList::<OpaqueNode>::new()); + let display_list = ~RefCell::new(DisplayList::<OpaqueNode>::new()); let dirty = flow::base(layout_root).position.clone(); let display_list_builder = DisplayListBuilder { ctx: &layout_ctx, }; layout_root.build_display_list(&display_list_builder, &dirty, display_list); - let display_list = Arc::new(display_list.take()); + let display_list = Arc::new(display_list.unwrap()); let mut color = color::rgba(255.0, 255.0, 255.0, 255.0); @@ -516,7 +519,7 @@ impl LayoutTask { self.display_list = Some(display_list.clone()); self.render_chan.send(RenderMsg(render_layer)); - } // time(layout: display list building) + }); } // Tell script that we're done. @@ -663,8 +666,9 @@ impl LayoutTask { /// Handles a message to destroy layout data. Layout data must be destroyed on *this* task /// because it contains local managed pointers. unsafe fn handle_reap_layout_data(&self, layout_data: LayoutDataRef) { - let ptr: &mut Option<~LayoutData> = cast::transmute(layout_data.borrow_unchecked()); - *ptr = None + let mut layout_data_ref = layout_data.borrow_mut(); + let _: Option<LayoutDataWrapper> = cast::transmute( + util::replace(layout_data_ref.get(), None)); } } diff --git a/src/components/main/layout/text.rs b/src/components/main/layout/text.rs index bc3059695d6..72695c691b2 100644 --- a/src/components/main/layout/text.rs +++ b/src/components/main/layout/text.rs @@ -4,7 +4,7 @@ //! Text layout. -use layout::box::{Box, ScannedTextBox, ScannedTextBoxInfo, UnscannedTextBox}; +use layout::box_::{Box, ScannedTextBox, ScannedTextBoxInfo, UnscannedTextBox}; use layout::context::LayoutContext; use layout::flow::Flow; @@ -15,7 +15,7 @@ use servo_util::range::Range; use std::vec; /// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es. -struct TextRunScanner { +pub struct TextRunScanner { clump: Range, } @@ -123,7 +123,7 @@ impl TextRunScanner { // font group fonts. This is probably achieved by creating the font group above // and then letting `FontGroup` decide which `Font` to stick into the text run. let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); - let run = ~fontgroup.with_borrow(|fg| fg.create_textrun(transformed_text.clone(), decoration)); + let run = ~fontgroup.borrow().with(|fg| fg.create_textrun(transformed_text.clone(), decoration)); debug!("TextRunScanner: pushing single text box in range: {} ({})", self.clump, @@ -142,7 +142,7 @@ impl TextRunScanner { // First, transform/compress text of all the nodes. let mut last_whitespace_in_clump = new_whitespace; - let transformed_strs: ~[~str] = do vec::from_fn(self.clump.length()) |i| { + let transformed_strs: ~[~str] = vec::from_fn(self.clump.length(), |i| { // TODO(#113): We should be passing the compression context between calls to // `transform_text`, so that boxes starting and/or ending with whitespace can // be compressed correctly with respect to the text run. @@ -157,7 +157,7 @@ impl TextRunScanner { last_whitespace_in_clump); last_whitespace_in_clump = new_whitespace; new_str - }; + }); new_whitespace = last_whitespace_in_clump; // Next, concatenate all of the transformed strings together, saving the new @@ -186,8 +186,8 @@ impl TextRunScanner { // sequence. If no clump takes ownership, however, it will leak. let clump = self.clump; let run = if clump.length() != 0 && run_str.len() > 0 { - fontgroup.with_borrow( |fg| { - fg.fonts[0].with_mut_borrow( |font| { + fontgroup.borrow().with(|fg| { + fg.fonts[0].borrow().with_mut(|font| { Some(Arc::new(~TextRun::new(font, run_str.clone(), decoration))) }) }) @@ -216,14 +216,14 @@ impl TextRunScanner { } // End of match. debug!("--- In boxes: ---"); - for (i, box) in in_boxes.iter().enumerate() { - debug!("{:u} --> {:s}", i, box.debug_str()); + for (i, box_) in in_boxes.iter().enumerate() { + debug!("{:u} --> {:s}", i, box_.debug_str()); } debug!("------------------"); debug!("--- Out boxes: ---"); - for (i, box) in out_boxes.iter().enumerate() { - debug!("{:u} --> {:s}", i, box.debug_str()); + for (i, box_) in out_boxes.iter().enumerate() { + debug!("{:u} --> {:s}", i, box_.debug_str()); } debug!("------------------"); diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs index a5dc5047968..65cf0b6b676 100644 --- a/src/components/main/layout/util.rs +++ b/src/components/main/layout/util.rs @@ -2,15 +2,16 @@ * 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 layout::box::Box; +use layout::box_::Box; use layout::construct::{ConstructionResult, NoConstructionResult}; use layout::wrapper::LayoutNode; use extra::arc::Arc; use script::dom::node::AbstractNode; +use script::layout_interface::LayoutChan; use servo_util::range::Range; -use servo_util::slot::{MutSlotRef, SlotRef}; use std::cast; +use std::cell::{Ref, RefMut}; use std::iter::Enumerate; use std::libc::uintptr_t; use std::vec::VecIterator; @@ -31,7 +32,7 @@ impl NodeRange { } } -struct ElementMapping { +pub struct ElementMapping { priv entries: ~[NodeRange], } @@ -46,7 +47,7 @@ impl ElementMapping { self.entries.push(NodeRange::new(node, range)) } - pub fn each(&self, callback: &fn(nr: &NodeRange) -> bool) -> bool { + pub fn each(&self, callback: |nr: &NodeRange| -> bool) -> bool { for nr in self.entries.iter() { if !callback(nr) { break @@ -63,14 +64,14 @@ impl ElementMapping { let entries = &mut self.entries; debug!("--- Old boxes: ---"); - for (i, box) in old_boxes.iter().enumerate() { - debug!("{:u} --> {:s}", i, box.debug_str()); + for (i, box_) in old_boxes.iter().enumerate() { + debug!("{:u} --> {:s}", i, box_.debug_str()); } debug!("------------------"); debug!("--- New boxes: ---"); - for (i, box) in new_boxes.iter().enumerate() { - debug!("{:u} --> {:s}", i, box.debug_str()); + for (i, box_) in new_boxes.iter().enumerate() { + debug!("{:u} --> {:s}", i, box_.debug_str()); } debug!("------------------"); @@ -125,7 +126,7 @@ impl ElementMapping { } /// Data that layout associates with a node. -pub struct LayoutData { +pub struct PrivateLayoutData { /// The results of CSS matching for this node. before_applicable_declarations: ~[Arc<~[PropertyDeclaration]>], @@ -148,10 +149,10 @@ pub struct LayoutData { flow_construction_result: ConstructionResult, } -impl LayoutData { +impl PrivateLayoutData { /// Creates new layout data. - pub fn new() -> LayoutData { - LayoutData { + pub fn new() -> PrivateLayoutData { + PrivateLayoutData { applicable_declarations: ~[], before_applicable_declarations: ~[], after_applicable_declarations: ~[], @@ -164,35 +165,35 @@ impl LayoutData { } } +pub struct LayoutDataWrapper { + chan: Option<LayoutChan>, + data: ~PrivateLayoutData, +} + /// A trait that allows access to the layout data of a DOM node. pub trait LayoutDataAccess { /// Borrows the layout data without checks. /// /// FIXME(pcwalton): Make safe. - unsafe fn borrow_layout_data_unchecked<'a>(&'a self) -> &'a Option<~LayoutData>; + // unsafe fn borrow_layout_data_unchecked<'a>(&'a self) -> &'a Option<~LayoutData>; /// Borrows the layout data immutably. Fails on a conflicting borrow. - fn borrow_layout_data<'a>(&'a self) -> SlotRef<'a,Option<~LayoutData>>; + fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>>; /// Borrows the layout data mutably. Fails on a conflicting borrow. - fn mutate_layout_data<'a>(&'a self) -> MutSlotRef<'a,Option<~LayoutData>>; + fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>>; } -impl<'self> LayoutDataAccess for LayoutNode<'self> { - #[inline(always)] - unsafe fn borrow_layout_data_unchecked<'a>(&'a self) -> &'a Option<~LayoutData> { - cast::transmute(self.get().layout_data.borrow_unchecked()) - } - +impl<'ln> LayoutDataAccess for LayoutNode<'ln> { #[inline(always)] - fn borrow_layout_data<'a>(&'a self) -> SlotRef<'a,Option<~LayoutData>> { + fn borrow_layout_data<'a>(&'a self) -> Ref<'a,Option<LayoutDataWrapper>> { unsafe { cast::transmute(self.get().layout_data.borrow()) } } #[inline(always)] - fn mutate_layout_data<'a>(&'a self) -> MutSlotRef<'a,Option<~LayoutData>> { + fn mutate_layout_data<'a>(&'a self) -> RefMut<'a,Option<LayoutDataWrapper>> { unsafe { - cast::transmute(self.get().layout_data.mutate()) + cast::transmute(self.get().layout_data.borrow_mut()) } } } diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index 619c711329a..f41fdb67d26 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -29,17 +29,17 @@ use style::{PropertyDeclarationBlock, TElement, TNode}; /// A wrapper so that layout can access only the methods that it should have access to. Layout must /// only ever see these and must never see instances of `AbstractNode`. #[deriving(Clone, Eq)] -pub struct LayoutNode<'self> { +pub struct LayoutNode<'a> { /// The wrapped node. priv node: AbstractNode, /// Being chained to a value prevents `LayoutNode`s from escaping. - priv chain: &'self (), + priv chain: &'a (), } -impl<'self> LayoutNode<'self> { +impl<'ln> LayoutNode<'ln> { /// Creates a new layout node, scoped to the given closure. - pub unsafe fn with_layout_node<R>(node: AbstractNode, f: &fn<'a>(LayoutNode<'a>) -> R) -> R { + pub unsafe fn with_layout_node<R>(node: AbstractNode, f: <'a> |LayoutNode<'a>| -> R) -> R { let heavy_iron_ball = (); f(LayoutNode { node: node, @@ -48,7 +48,7 @@ impl<'self> LayoutNode<'self> { } /// Creates a new layout node with the same lifetime as this layout node. - unsafe fn new_with_this_lifetime(&self, node: AbstractNode) -> LayoutNode<'self> { + unsafe fn new_with_this_lifetime(&self, node: AbstractNode) -> LayoutNode<'ln> { LayoutNode { node: node, chain: self.chain, @@ -62,14 +62,14 @@ impl<'self> LayoutNode<'self> { } /// Returns the first child of this node. - pub fn first_child(&self) -> Option<LayoutNode<'self>> { + pub fn first_child(&self) -> Option<LayoutNode<'ln>> { unsafe { self.node.first_child().map(|node| self.new_with_this_lifetime(node)) } } /// Returns the first child of this node. - pub fn last_child(&self) -> Option<LayoutNode<'self>> { + pub fn last_child(&self) -> Option<LayoutNode<'ln>> { unsafe { self.node.last_child().map(|node| self.new_with_this_lifetime(node)) } @@ -78,14 +78,14 @@ impl<'self> LayoutNode<'self> { /// Iterates over this node and all its descendants, in preorder. /// /// FIXME(pcwalton): Terribly inefficient. We should use parallelism. - pub fn traverse_preorder(&self) -> LayoutTreeIterator<'self> { + pub fn traverse_preorder(&self) -> LayoutTreeIterator<'ln> { let mut nodes = ~[]; gather_layout_nodes(self, &mut nodes, false); LayoutTreeIterator::new(nodes) } /// Returns an iterator over this node's children. - pub fn children(&self) -> LayoutNodeChildrenIterator<'self> { + pub fn children(&self) -> LayoutNodeChildrenIterator<'ln> { LayoutNodeChildrenIterator { current_node: self.first_child(), } @@ -110,7 +110,7 @@ impl<'self> LayoutNode<'self> { /// Downcasts this node to an image element and calls the given closure. /// /// FIXME(pcwalton): RAII. - unsafe fn with_image_element<R>(self, f: &fn(&HTMLImageElement) -> R) -> R { + unsafe fn with_image_element<R>(self, f: |&HTMLImageElement| -> R) -> R { if !self.node.is_image_element() { fail!(~"node is not an image element"); } @@ -131,7 +131,7 @@ impl<'self> LayoutNode<'self> { /// Downcasts this node to an iframe element and calls the given closure. /// /// FIXME(pcwalton): RAII. - unsafe fn with_iframe_element<R>(self, f: &fn(&HTMLIFrameElement) -> R) -> R { + unsafe fn with_iframe_element<R>(self, f: |&HTMLIFrameElement| -> R) -> R { if !self.node.is_iframe_element() { fail!(~"node is not an iframe element"); } @@ -164,7 +164,7 @@ impl<'self> LayoutNode<'self> { /// Downcasts this node to a text node and calls the given closure. /// /// FIXME(pcwalton): RAII. - unsafe fn with_text<R>(self, f: &fn(&Text) -> R) -> R { + unsafe fn with_text<R>(self, f: |&Text| -> R) -> R { self.node.with_imm_text(f) } @@ -228,20 +228,20 @@ impl<'self> LayoutNode<'self> { } } -impl<'self> TNode<LayoutElement<'self>> for LayoutNode<'self> { - fn parent_node(&self) -> Option<LayoutNode<'self>> { +impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> { + fn parent_node(&self) -> Option<LayoutNode<'ln>> { unsafe { self.node.node().parent_node.map(|node| self.new_with_this_lifetime(node)) } } - fn prev_sibling(&self) -> Option<LayoutNode<'self>> { + fn prev_sibling(&self) -> Option<LayoutNode<'ln>> { unsafe { self.node.node().prev_sibling.map(|node| self.new_with_this_lifetime(node)) } } - fn next_sibling(&self) -> Option<LayoutNode<'self>> { + fn next_sibling(&self) -> Option<LayoutNode<'ln>> { unsafe { self.node.node().next_sibling.map(|node| self.new_with_this_lifetime(node)) } @@ -249,21 +249,21 @@ impl<'self> TNode<LayoutElement<'self>> for LayoutNode<'self> { fn is_element(&self) -> bool { match self.node.type_id() { - ElementNodeTypeId(*) => true, + ElementNodeTypeId(..) => true, _ => false } } fn is_document(&self) -> bool { match self.node.type_id() { - DocumentNodeTypeId(*) => true, + DocumentNodeTypeId(..) => true, _ => false } } /// If this is an element, accesses the element data. Fails if this is not an element node. #[inline] - fn with_element<R>(&self, f: &fn(&LayoutElement<'self>) -> R) -> R { + fn with_element<R>(&self, f: |&LayoutElement<'ln>| -> R) -> R { self.node.with_imm_element(|element| { // FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on // implementations. @@ -276,16 +276,16 @@ impl<'self> TNode<LayoutElement<'self>> for LayoutNode<'self> { } } -pub struct LayoutNodeChildrenIterator<'self> { - priv current_node: Option<LayoutNode<'self>>, +pub struct LayoutNodeChildrenIterator<'a> { + priv current_node: Option<LayoutNode<'a>>, } -impl<'self> Iterator<LayoutNode<'self>> for LayoutNodeChildrenIterator<'self> { - fn next(&mut self) -> Option<LayoutNode<'self>> { +impl<'a> Iterator<LayoutNode<'a>> for LayoutNodeChildrenIterator<'a> { + fn next(&mut self) -> Option<LayoutNode<'a>> { let node = self.current_node; - self.current_node = do self.current_node.and_then |node| { + self.current_node = self.current_node.and_then(|node| { node.next_sibling() - }; + }); node } } @@ -294,13 +294,13 @@ impl<'self> Iterator<LayoutNode<'self>> for LayoutNodeChildrenIterator<'self> { // Easy for preorder; harder for postorder. // // FIXME(pcwalton): Parallelism! Eventually this should just be nuked. -pub struct LayoutTreeIterator<'self> { - priv nodes: ~[LayoutNode<'self>], +pub struct LayoutTreeIterator<'a> { + priv nodes: ~[LayoutNode<'a>], priv index: uint, } -impl<'self> LayoutTreeIterator<'self> { - fn new(nodes: ~[LayoutNode<'self>]) -> LayoutTreeIterator<'self> { +impl<'a> LayoutTreeIterator<'a> { + fn new(nodes: ~[LayoutNode<'a>]) -> LayoutTreeIterator<'a> { LayoutTreeIterator { nodes: nodes, index: 0, @@ -308,8 +308,8 @@ impl<'self> LayoutTreeIterator<'self> { } } -impl<'self> Iterator<LayoutNode<'self>> for LayoutTreeIterator<'self> { - fn next(&mut self) -> Option<LayoutNode<'self>> { +impl<'a> Iterator<LayoutNode<'a>> for LayoutTreeIterator<'a> { + fn next(&mut self) -> Option<LayoutNode<'a>> { if self.index >= self.nodes.len() { None } else { @@ -360,17 +360,17 @@ pub trait PostorderNodeMutTraversal { } /// A wrapper around elements that ensures layout can only ever access safe properties. -pub struct LayoutElement<'self> { - priv element: &'self Element, +pub struct LayoutElement<'le> { + priv element: &'le Element, } -impl<'self> LayoutElement<'self> { - pub fn style_attribute(&self) -> &'self Option<PropertyDeclarationBlock> { +impl<'le> LayoutElement<'le> { + pub fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> { &self.element.style_attribute } } -impl<'self> TElement for LayoutElement<'self> { +impl<'le> TElement for LayoutElement<'le> { fn get_local_name<'a>(&'a self) -> &'a str { self.element.tag_name.as_slice() } diff --git a/src/components/main/macros.rs b/src/components/main/macros.rs index 34b0d2ac869..4feab0d94bc 100644 --- a/src/components/main/macros.rs +++ b/src/components/main/macros.rs @@ -2,26 +2,10 @@ * 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! special_stream( - ($Chan:ident) => ( - { - let (port, chan) = stream::(); - (port, $Chan::new(chan)) - } - ); -) // Spawn a task, capturing the listed variables in a way that avoids the // move-from-closure error. This is sugar around the function spawn_with, // taking care of building a tuple and a lambda. -// -// FIXME: Once cross-crate macros work, there are a few places outside of -// the main crate which could benefit from this macro. -macro_rules! spawn_with( - ($task:expr, [ $($var:ident),+ ], $body:block) => ( - do ($task).spawn_with(( $($var),+ , () )) |( $($var),+ , () )| $body - ) -) macro_rules! bitfield( ($bitfieldname:ident, $getter:ident, $setter:ident, $value:expr) => ( diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs index 9fe5094bcbc..8f5aaef929d 100644 --- a/src/components/main/pipeline.rs +++ b/src/components/main/pipeline.rs @@ -15,12 +15,10 @@ use script::layout_interface::LayoutChan; use script::script_task::LoadMsg; use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan}; use script::script_task; -use servo_msg::constellation_msg::{ConstellationChan, FailureMsg, PipelineId, SubpageId}; +use servo_msg::constellation_msg::{ConstellationChan, PipelineId, SubpageId}; use servo_net::image_cache_task::ImageCacheTask; use servo_net::resource_task::ResourceTask; use servo_util::time::ProfilerChan; -use std::task; -use std::comm; /// A uniquely-identifiable pipeline of script task, layout task, and render task. pub struct Pipeline { @@ -55,10 +53,10 @@ impl Pipeline { opts: Opts, script_pipeline: &Pipeline) -> Pipeline { - let (layout_port, layout_chan) = special_stream!(LayoutChan); - let (render_port, render_chan) = special_stream!(RenderChan); - let (render_shutdown_port, render_shutdown_chan) = comm::stream(); - let (layout_shutdown_port, layout_shutdown_chan) = comm::stream(); + let (layout_port, layout_chan) = LayoutChan::new(); + let (render_port, render_chan) = RenderChan::new(); + let (render_shutdown_port, render_shutdown_chan) = Chan::new(); + let (layout_shutdown_port, layout_shutdown_chan) = Chan::new(); RenderTask::create(id, render_port, @@ -70,6 +68,7 @@ impl Pipeline { LayoutTask::create(id, layout_port, + layout_chan.clone(), constellation_chan, script_pipeline.script_chan.clone(), render_chan.clone(), @@ -105,11 +104,11 @@ impl Pipeline { window_size: Size2D<uint>, opts: Opts) -> Pipeline { - let (script_port, script_chan) = special_stream!(ScriptChan); - let (layout_port, layout_chan) = special_stream!(LayoutChan); - let (render_port, render_chan) = special_stream!(RenderChan); - let (render_shutdown_port, render_shutdown_chan) = comm::stream(); - let (layout_shutdown_port, layout_shutdown_chan) = comm::stream(); + let (script_port, script_chan) = ScriptChan::new(); + let (layout_port, layout_chan) = LayoutChan::new(); + let (render_port, render_chan) = RenderChan::new(); + let (render_shutdown_port, render_shutdown_chan) = Chan::new(); + let (layout_shutdown_port, layout_shutdown_chan) = Chan::new(); let pipeline = Pipeline::new(id, subpage_id, script_chan.clone(), @@ -118,65 +117,36 @@ impl Pipeline { layout_shutdown_port, render_shutdown_port); - // Wrap task creation within a supervised task so that failure will - // only tear down those tasks instead of ours. - let hard_fail = opts.hard_fail; - let failure_chan = constellation_chan.clone(); - let mut supervised_task = task::task(); - let task_port = supervised_task.future_result(); - supervised_task.supervised(); - - spawn_with!(supervised_task, [ - script_port, - resource_task, - render_port, - layout_port, - constellation_chan, - image_cache_task, - profiler_chan, - layout_shutdown_chan, - render_shutdown_chan - ], { - ScriptTask::create(id, - compositor_chan.clone(), - layout_chan.clone(), - script_port, - script_chan.clone(), - constellation_chan.clone(), - resource_task, - image_cache_task.clone(), - window_size); - - RenderTask::create(id, - render_port, - compositor_chan.clone(), - constellation_chan.clone(), - opts.clone(), - profiler_chan.clone(), - render_shutdown_chan); - - LayoutTask::create(id, - layout_port, - constellation_chan, - script_chan.clone(), - render_chan.clone(), - image_cache_task, - opts.clone(), - profiler_chan, - layout_shutdown_chan); - }); + // FIXME(#1434): add back failure supervision - spawn_with!(task::task(), [failure_chan], { - match task_port.recv() { - Ok(*) => (), - Err(*) => { - if hard_fail { - fail!("Pipeline failed in hard-fail mode"); - } - failure_chan.send(FailureMsg(id, subpage_id)); - } - } - }); + ScriptTask::create(id, + compositor_chan.clone(), + layout_chan.clone(), + script_port, + script_chan.clone(), + constellation_chan.clone(), + resource_task, + image_cache_task.clone(), + window_size); + + RenderTask::create(id, + render_port, + compositor_chan.clone(), + constellation_chan.clone(), + opts.clone(), + profiler_chan.clone(), + render_shutdown_chan); + + LayoutTask::create(id, + layout_port, + layout_chan.clone(), + constellation_chan, + script_chan.clone(), + render_chan.clone(), + image_cache_task, + opts.clone(), + profiler_chan, + layout_shutdown_chan); pipeline } @@ -215,9 +185,9 @@ impl Pipeline { } pub fn reload(&mut self) { - do self.url.clone().map() |url| { + self.url.clone().map(|url| { self.load(url); - }; + }); } pub fn exit(&self) { @@ -226,8 +196,8 @@ impl Pipeline { // Wait until all slave tasks have terminated and run destructors // NOTE: We don't wait for script task as we don't always own it - self.render_shutdown_port.try_recv(); - self.layout_shutdown_port.try_recv(); + self.render_shutdown_port.recv_opt(); + self.layout_shutdown_port.recv_opt(); } pub fn to_sendable(&self) -> CompositionPipeline { diff --git a/src/components/main/platform/common/glfw_windowing.rs b/src/components/main/platform/common/glfw_windowing.rs index 5b99f5c243b..9c4c8b12f91 100644 --- a/src/components/main/platform/common/glfw_windowing.rs +++ b/src/components/main/platform/common/glfw_windowing.rs @@ -30,9 +30,7 @@ impl ApplicationMethods for Application { fn new() -> Application { // Per GLFW docs it's safe to set the error callback before calling // glfwInit(), and this way we notice errors from init too. - do glfw::set_error_callback |_error_code, description| { - error!("GLFW error: {:s}", description); - }; + glfw::set_error_callback(~glfw::LogErrorHandler); glfw::init(); Application } @@ -45,6 +43,38 @@ impl Drop for Application { } } +macro_rules! glfw_callback( + ( + $callback:path ($($arg:ident: $arg_ty:ty),*) $block:expr + ) => ({ + struct GlfwCallback; + impl $callback for GlfwCallback { + fn call(&self $(, $arg: $arg_ty)*) { + $block + } + } + ~GlfwCallback + }); + + ( + [$($state:ident: $state_ty:ty),*], + $callback:path ($($arg:ident: $arg_ty:ty),*) $block:expr + ) => ({ + struct GlfwCallback { + $($state: $state_ty,)* + } + impl $callback for GlfwCallback { + fn call(&self $(, $arg: $arg_ty)*) { + $block + } + } + ~GlfwCallback { + $($state: $state,)* + } + }); +) + + /// The type of a window. pub struct Window { glfw_window: glfw::Window, @@ -90,43 +120,50 @@ impl WindowMethods<Application> for Window { install_local_window(window); // Register event handlers. - do window.glfw_window.set_framebuffer_size_callback |_win, width, height| { - local_window().event_queue.push(ResizeWindowEvent(width as uint, height as uint)) - } - do window.glfw_window.set_refresh_callback |_win| { - local_window().event_queue.push(RefreshWindowEvent) - } - do window.glfw_window.set_key_callback |_win, key, _scancode, action, mods| { - if action == glfw::Press { - local_window().handle_key(key, mods) - } - } - do window.glfw_window.set_mouse_button_callback |win, button, action, _mods| { - let (x, y) = win.get_cursor_pos(); - //handle hidpi displays, since GLFW returns non-hi-def coordinates. - let (backing_size, _) = win.get_framebuffer_size(); - let (window_size, _) = win.get_size(); - let hidpi = (backing_size as f32) / (window_size as f32); - let x = x as f32 * hidpi; - let y = y as f32 * hidpi; - if button == glfw::MouseButtonLeft || button == glfw::MouseButtonRight { - local_window().handle_mouse(button, action, x as i32, y as i32); - } - } - do window.glfw_window.set_scroll_callback |win, x_offset, y_offset| { - let dx = (x_offset as f32) * 30.0; - let dy = (y_offset as f32) * 30.0; + window.glfw_window.set_framebuffer_size_callback( + glfw_callback!(glfw::FramebufferSizeCallback(_win: &glfw::Window, width: i32, height: i32) { + local_window().event_queue.push(ResizeWindowEvent(width as uint, height as uint)); + })); + window.glfw_window.set_refresh_callback( + glfw_callback!(glfw::WindowRefreshCallback(_win: &glfw::Window) { + local_window().event_queue.push(RefreshWindowEvent); + })); + window.glfw_window.set_key_callback( + glfw_callback!(glfw::KeyCallback(_win: &glfw::Window, key: glfw::Key, _scancode: c_int, + action: glfw::Action, mods: glfw::Modifiers) { + if action == glfw::Press { + local_window().handle_key(key, mods) + } + })); + window.glfw_window.set_mouse_button_callback( + glfw_callback!(glfw::MouseButtonCallback(win: &glfw::Window, button: glfw::MouseButton, + action: glfw::Action, _mods: glfw::Modifiers) { + let (x, y) = win.get_cursor_pos(); + //handle hidpi displays, since GLFW returns non-hi-def coordinates. + let (backing_size, _) = win.get_framebuffer_size(); + let (window_size, _) = win.get_size(); + let hidpi = (backing_size as f32) / (window_size as f32); + let x = x as f32 * hidpi; + let y = y as f32 * hidpi; + if button == glfw::MouseButtonLeft || button == glfw::MouseButtonRight { + local_window().handle_mouse(button, action, x as i32, y as i32); + } + })); + window.glfw_window.set_scroll_callback( + glfw_callback!(glfw::ScrollCallback(win: &glfw::Window, xpos: f64, ypos: f64) { + let dx = (xpos as f32) * 30.0; + let dy = (ypos as f32) * 30.0; - let (x, y) = win.get_cursor_pos(); - //handle hidpi displays, since GLFW returns non-hi-def coordinates. - let (backing_size, _) = win.get_framebuffer_size(); - let (window_size, _) = win.get_size(); - let hidpi = (backing_size as f32) / (window_size as f32); - let x = x as f32 * hidpi; - let y = y as f32 * hidpi; - - local_window().event_queue.push(ScrollWindowEvent(Point2D(dx, dy), Point2D(x as i32, y as i32))); - } + let (x, y) = win.get_cursor_pos(); + //handle hidpi displays, since GLFW returns non-hi-def coordinates. + let (backing_size, _) = win.get_framebuffer_size(); + let (window_size, _) = win.get_size(); + let hidpi = (backing_size as f32) / (window_size as f32); + let x = x as f32 * hidpi; + let y = y as f32 * hidpi; + + local_window().event_queue.push(ScrollWindowEvent(Point2D(dx, dy), Point2D(x as i32, y as i32))); + })); window } diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs index b781d562a5c..38457aed4e5 100644 --- a/src/components/main/platform/common/glut_windowing.rs +++ b/src/components/main/platform/common/glut_windowing.rs @@ -7,22 +7,22 @@ use windowing::{ApplicationMethods, WindowEvent, WindowMethods}; use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass}; use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent}; -use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent}; +use windowing::{MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent}; use windowing::{Forward, Back}; use alert::{Alert, AlertMethods}; -use std::libc::c_int; +use std::libc::{c_int, c_uchar}; use std::local_data; use geom::point::Point2D; use geom::size::Size2D; use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState}; -use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState}; +use servo_msg::compositor_msg::{FinishedLoading, Blank, ReadyState}; -use glut::glut::{ACTIVE_CTRL, ACTIVE_SHIFT, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight}; +use glut::glut::{ACTIVE_SHIFT, DOUBLE, WindowHeight}; use glut::glut::WindowWidth; use glut::glut; -static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ]; +// static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ]; /// A structure responsible for setting up and tearing down the entire windowing system. pub struct Application; @@ -85,31 +85,47 @@ impl WindowMethods<Application> for Window { // Register event handlers. //Added dummy display callback to freeglut. According to freeglut ref, we should register some kind of display callback after freeglut 3.0. - do glut::display_func || { - debug!("GLUT display func registered"); - } - do glut::reshape_func(window.glut_window) |width, height| { - local_window().event_queue.push(ResizeWindowEvent(width as uint, height as uint)) + + struct DisplayCallbackState; + impl glut::DisplayCallback for DisplayCallbackState { + fn call(&self) { + debug!("GLUT display func registgered"); + } } - do glut::keyboard_func |key, _, _| { - local_window().handle_key(key) + glut::display_func(~DisplayCallbackState); + struct ReshapeCallbackState; + impl glut::ReshapeCallback for ReshapeCallbackState { + fn call(&self, width: c_int, height: c_int) { + local_window().event_queue.push(ResizeWindowEvent(width as uint, height as uint)) + } } - do glut::mouse_func |button, state, x, y| { - if button < 3 { - local_window().handle_mouse(button, state, x, y); + glut::reshape_func(glut_window, ~ReshapeCallbackState); + struct KeyboardCallbackState; + impl glut::KeyboardCallback for KeyboardCallbackState { + fn call(&self, key: c_uchar, _x: c_int, _y: c_int) { + local_window().handle_key(key) } - else { - match button { - 3 => { - local_window().event_queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))); - }, - 4 => { - local_window().event_queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))); - }, - _ => {} + } + glut::keyboard_func(~KeyboardCallbackState); + struct MouseCallbackState; + impl glut::MouseCallback for MouseCallbackState { + fn call(&self, button: c_int, state: c_int, x: c_int, y: c_int) { + if button < 3 { + local_window().handle_mouse(button, state, x, y); + } else { + match button { + 3 => { + local_window().event_queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))); + }, + 4 => { + local_window().event_queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))); + }, + _ => {} + } } } } + glut::mouse_func(~MouseCallbackState); window } @@ -165,28 +181,28 @@ impl WindowMethods<Application> for Window { impl Window { /// Helper function to set the window title in accordance with the ready state. - fn update_window_title(&self) { - let throbber = THROBBER[self.throbber_frame]; - match self.ready_state { - Blank => { - glut::set_window_title(self.glut_window, "Blank") - } - Loading => { - glut::set_window_title(self.glut_window, format!("{:c} Loading . Servo", throbber)) - } - PerformingLayout => { - glut::set_window_title(self.glut_window, format!("{:c} Performing Layout . Servo", throbber)) - } - FinishedLoading => { - match self.render_state { - RenderingRenderState => { - glut::set_window_title(self.glut_window, format!("{:c} Rendering . Servo", throbber)) - } - IdleRenderState => glut::set_window_title(self.glut_window, "Servo"), - } - } - } - } + // fn update_window_title(&self) { + // let throbber = THROBBER[self.throbber_frame]; + // match self.ready_state { + // Blank => { + // glut::set_window_title(self.glut_window, "Blank") + // } + // Loading => { + // glut::set_window_title(self.glut_window, format!("{:c} Loading . Servo", throbber)) + // } + // PerformingLayout => { + // glut::set_window_title(self.glut_window, format!("{:c} Performing Layout . Servo", throbber)) + // } + // FinishedLoading => { + // match self.render_state { + // RenderingRenderState => { + // glut::set_window_title(self.glut_window, format!("{:c} Rendering . Servo", throbber)) + // } + // IdleRenderState => glut::set_window_title(self.glut_window, "Servo"), + // } + // } + // } + // } /// Helper function to handle keyboard events. fn handle_key(&self, key: u8) { diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc index 5dc43a3bb4e..6b1bbe37302 100755 --- a/src/components/main/servo.rc +++ b/src/components/main/servo.rc @@ -2,21 +2,16 @@ * 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 = "servo", - vers = "0.1", - uuid = "637ffc98-9058-471d-9de7-abfc49ef0549", - url = "http://servo.org/")]; - +#[crate_id = "github.com/mozilla/servo"]; #[comment = "The Servo Parallel Browser Project"]; #[license = "MPL"]; -#[crate_type = "lib"]; #[feature(globs, macro_rules, managed_boxes)]; extern mod alert; extern mod azure; extern mod geom; -extern mod gfx (name = "gfx"); +extern mod gfx; #[cfg(not(target_os="android"))] extern mod glfw; #[cfg(target_os="android")] @@ -26,39 +21,50 @@ extern mod layers; extern mod opengles; extern mod png; extern mod script; -extern mod servo_net (name = "net"); -extern mod servo_msg (name = "msg"); -extern mod servo_util (name = "util"); +extern mod servo_net = "net"; +extern mod servo_msg = "msg"; +extern mod servo_util = "util"; extern mod style; extern mod sharegl; extern mod stb_image; + extern mod extra; +extern mod green; +extern mod native; #[cfg(target_os="macos")] extern mod core_graphics; #[cfg(target_os="macos")] extern mod core_text; +#[cfg(not(test))] use compositing::{CompositorChan, CompositorTask}; +#[cfg(not(test))] use constellation::Constellation; -use servo_msg::constellation_msg::{ConstellationChan, InitLoadUrlMsg}; +#[cfg(not(test))] +use servo_msg::constellation_msg::InitLoadUrlMsg; #[cfg(not(test))] use gfx::opts; +#[cfg(not(test))] use servo_net::image_cache_task::ImageCacheTask; +#[cfg(not(test))] use servo_net::resource_task::ResourceTask; -use servo_util::time::{Profiler, ProfilerChan}; +#[cfg(not(test))] +use servo_util::time::Profiler; pub use gfx::opts::Opts; pub use gfx::text; pub use servo_util::url::make_url; -use std::comm; + #[cfg(not(test))] use std::os; #[cfg(not(test), target_os="android")] use std::str; -use std::task::spawn_with; +#[cfg(not(test))] +use std::task::TaskOpts; + #[path="compositing/compositor_task.rs"] pub mod compositing; @@ -78,7 +84,7 @@ pub mod pipeline; pub mod layout { pub mod block; - pub mod box; + pub mod box_; pub mod construct; pub mod context; pub mod display_list_builder; @@ -106,15 +112,15 @@ pub mod util; #[cfg(not(test), target_os="macos")] #[start] fn start(argc: int, argv: **u8) -> int { - do std::rt::start_on_main_thread(argc, argv) { + native::start(argc, argv, proc() { run(opts::from_cmdline_args(os::args())) - } + }) } #[cfg(not(test), target_os="android")] #[no_mangle] pub extern "C" fn android_start(argc: int, argv: **u8) -> int { - do std::rt::start_on_main_thread(argc, argv) { + native::start(argc, argv, proc() { let mut args:~[~str] = ~[]; for i in range(0u, argc as uint) { unsafe { @@ -122,53 +128,51 @@ pub extern "C" fn android_start(argc: int, argv: **u8) -> int { } } run(opts::from_cmdline_args(args)) - } + }) } +#[cfg(not(test))] fn run(opts: Opts) { - let (exit_response_from_constellation, exit_chan) = comm::stream(); - let (profiler_port, profiler_chan) = special_stream!(ProfilerChan); - let (compositor_port, compositor_chan) = special_stream!(CompositorChan); - let (constellation_port, constellation_chan) = special_stream!(ConstellationChan); - - Profiler::create(profiler_port, profiler_chan.clone(), opts.profiler_period); - - do spawn_with((constellation_port, - constellation_chan.clone(), - profiler_chan.clone(), - compositor_chan, - opts.clone())) - |(constellation_port, - constellation_chan, - profiler_chan, - compositor_chan, - opts)| { - let opts = &opts; + let mut pool = green::SchedPool::new(green::PoolConfig::new()); + let (exit_response_from_constellation, exit_chan) = Chan::new(); + let (compositor_port, compositor_chan) = CompositorChan::new(); + let profiler_chan = Profiler::create(opts.profiler_period); + + let opts_clone = opts.clone(); + let profiler_chan_clone = profiler_chan.clone(); + + let (result_port, result_chan) = Chan::new(); + pool.spawn(TaskOpts::new(), proc() { + let opts = &opts_clone; // Create a Servo instance. let resource_task = ResourceTask(); let image_cache_task = ImageCacheTask(resource_task.clone()); - Constellation::start(constellation_port, - constellation_chan.clone(), - compositor_chan, - opts, - resource_task, - image_cache_task, - profiler_chan.clone()); + let constellation_chan = Constellation::start(compositor_chan, + opts, + resource_task, + image_cache_task, + profiler_chan_clone); + + // Send the constallation Chan as the result + result_chan.send(constellation_chan.clone()); // Send the URL command to the constellation. for filename in opts.urls.iter() { constellation_chan.send(InitLoadUrlMsg(make_url(filename.clone(), None))) } - } + }); + let constellation_chan = result_port.recv(); debug!("preparing to enter main loop"); CompositorTask::create(opts, compositor_port, - constellation_chan.clone(), + constellation_chan, profiler_chan, exit_chan, exit_response_from_constellation); + + pool.shutdown(); } diff --git a/src/components/main/util/task.rs b/src/components/main/util/task.rs index 0300fa59200..f85688f7d2f 100644 --- a/src/components/main/util/task.rs +++ b/src/components/main/util/task.rs @@ -2,26 +2,20 @@ * 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::cell::Cell; -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_po, setup_ch) = comm::stream(); - do task::spawn { - let (po, ch) = comm::stream(); +pub fn spawn_listener<A: Send>(f: proc(Port<A>)) -> Chan<A> { + let (setup_po, setup_ch) = Chan::new(); + spawn(proc() { + let (po, ch) = Chan::new(); setup_ch.send(ch); f(po); - } + }); setup_po.recv() } -pub fn spawn_conversation<A: Send, B: Send>(f: ~fn(Port<A>, Chan<B>)) -> (Port<B>, Chan<A>) { - let (from_child, to_parent) = comm::stream(); - let to_parent = Cell::new(to_parent); +pub fn spawn_conversation<A: Send, B: Send>(f: proc(Port<A>, Chan<B>)) -> (Port<B>, Chan<A>) { + let (from_child, to_parent) = Chan::new(); let to_child = do spawn_listener |from_parent| { - f(from_parent, to_parent.take()) + f(from_parent, to_parent) }; (from_child, to_child) } diff --git a/src/components/msg/constellation_msg.rs b/src/components/msg/constellation_msg.rs index 5c91b329379..ee8f2914785 100644 --- a/src/components/msg/constellation_msg.rs +++ b/src/components/msg/constellation_msg.rs @@ -14,8 +14,9 @@ use std::comm::{Chan, SharedChan}; pub struct ConstellationChan(SharedChan<Msg>); impl ConstellationChan { - pub fn new(chan: Chan<Msg>) -> ConstellationChan { - ConstellationChan(SharedChan::new(chan)) + pub fn new() -> (Port<Msg>, ConstellationChan) { + let (port, chan) = SharedChan::new(); + (port, ConstellationChan(chan)) } } @@ -53,5 +54,6 @@ pub enum NavigationDirection { #[deriving(Clone, Eq, IterBytes)] pub struct PipelineId(uint); + #[deriving(Clone, Eq, IterBytes)] pub struct SubpageId(uint); diff --git a/src/components/msg/msg.rc b/src/components/msg/msg.rc index 35c364f6331..e27148b09d7 100644 --- a/src/components/msg/msg.rc +++ b/src/components/msg/msg.rc @@ -2,10 +2,7 @@ * 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 = "msg", - vers = "0.1", - uuid = "4c6054e4-2a7b-4fae-b0c8-6d04416b2bf2", - url = "http://servo.org/")]; +#[crate_id = "github.com/mozilla/servo#msg:0.1"]; #[crate_type = "lib"]; extern mod azure; 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); } diff --git a/src/components/script/dom/bindings/callback.rs b/src/components/script/dom/bindings/callback.rs index f7f519012ea..40b3bd7b5fa 100644 --- a/src/components/script/dom/bindings/callback.rs +++ b/src/components/script/dom/bindings/callback.rs @@ -43,7 +43,6 @@ impl CallbackInterface { } } - #[fixed_stack_segment] pub fn GetCallableProperty(&self, cx: *JSContext, name: *libc::c_char, callable: &mut JSVal) -> bool { unsafe { if JS_GetProperty(cx, self.callback, name, &*callable) == 0 { @@ -65,7 +64,6 @@ pub fn GetJSObjectFromCallback<T: CallbackContainer>(callback: &T) -> *JSObject callback.callback() } -#[fixed_stack_segment] pub fn WrapCallThisObject<T: 'static + CallbackContainer + Reflectable>(cx: *JSContext, _scope: *JSObject, p: @mut T) -> *JSObject { diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index b426c2989ed..b1ba6b9dac4 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1091,7 +1091,7 @@ for (uint32_t i = 0; i < length; ++i) { return handleDefault( conversionCode, ("static data: [u8, ..%s] = [ %s ];\n" - "%s = str::from_utf8(data)" % + "%s = str::from_utf8(data).to_owned()" % (len(defaultValue.value) + 1, ", ".join(["'" + char + "' as u8" for char in defaultValue.value] + ["0"]), varName))) @@ -2173,7 +2173,7 @@ class CGImports(CGWrapper): # Allow unreachable_code because we use 'break' in a way that sometimes produces # two 'break's in a row. See for example CallbackMember.getArgConversions. return '\n'.join([ - '#[allow(unreachable_code,non_uppercase_statics,unused_imports,unused_variable,unused_unsafe,unused_mut,dead_assignment)];', + '#[allow(unreachable_code,non_uppercase_statics,unused_imports,unused_variable,unused_unsafe,unused_mut,dead_assignment,dead_code)];', ''.join('use %s;\n' % i for i in imports), '']) CGWrapper.__init__(self, child, @@ -2454,16 +2454,14 @@ class CGAbstractMethod(CGThing): def _decorators(self): decorators = [] if self.alwaysInline: - # FIXME Rust #8801 #[inline(always)] and #[fixed_stack_segment] not compatible - # decorators.append('#[inline(always)]') - pass + decorators.append('#[inline(always)]') elif self.inline: #decorators.append('inline') pass if self.extern: decorators.append('extern') if not self.extern: - decorators.append('#[fixed_stack_segment]') + pass if self.static: #decorators.append('static') pass @@ -3522,6 +3520,7 @@ class CGEnum(CGThing): def define(self): return """ + #[repr(uint)] pub enum valuelist { %s } @@ -3576,7 +3575,7 @@ class ClassMethod(ClassItem): ClassItem.__init__(self, name, visibility) def getDecorators(self, declaring): - decorators = ['#[fixed_stack_segment]'] + decorators = [] if self.inline: decorators.append('inline') if declaring: @@ -4150,8 +4149,8 @@ class CGProxyUnwrap(CGAbstractMethod): obj = js::UnwrapObject(obj); }*/ //MOZ_ASSERT(IsProxy(obj)); - let box: *Box<%s> = cast::transmute(RUST_JSVAL_TO_PRIVATE(GetProxyPrivate(obj))); - return ptr::to_unsafe_ptr(&(*box).data);""" % (self.descriptor.concreteType) + let box_: *Box<%s> = cast::transmute(RUST_JSVAL_TO_PRIVATE(GetProxyPrivate(obj))); + return ptr::to_unsafe_ptr(&(*box_).data);""" % (self.descriptor.concreteType) class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod): def __init__(self, descriptor): @@ -4443,9 +4442,9 @@ class CGDOMJSProxyHandler_obj_toString(CGAbstractExternMethod): JSString* jsresult; return xpc_qsStringToJsstring(cx, result, &jsresult) ? jsresult : NULL;""" - return """ do "%s".to_c_str().with_ref |s| { + return """ "%s".to_c_str().with_ref(|s| { _obj_toString(cx, s) - }""" % self.descriptor.name + })""" % self.descriptor.name def definition_body(self): return self.getBody() @@ -4907,7 +4906,6 @@ class CGDictionary(CGThing): " return true;\n" " }\n" "\n" if not self.workers else "") + - " #[fixed_stack_segment]\n" + " pub fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool {\n" " unsafe {\n" + # NOTE: jsids are per-runtime, so don't use them in workers diff --git a/src/components/script/dom/bindings/conversions.rs b/src/components/script/dom/bindings/conversions.rs index 22bad8cff16..06745217365 100644 --- a/src/components/script/dom/bindings/conversions.rs +++ b/src/components/script/dom/bindings/conversions.rs @@ -13,14 +13,12 @@ pub trait JSValConvertible { impl JSValConvertible for i64 { - #[fixed_stack_segment] fn to_jsval(&self) -> JSVal { unsafe { RUST_DOUBLE_TO_JSVAL(*self as f64) } } - #[fixed_stack_segment] fn from_jsval(val: JSVal) -> Option<i64> { unsafe { Some(RUST_JSVAL_TO_DOUBLE(val) as i64) @@ -29,14 +27,12 @@ impl JSValConvertible for i64 { } impl JSValConvertible for u32 { - #[fixed_stack_segment] fn to_jsval(&self) -> JSVal { unsafe { RUST_UINT_TO_JSVAL(*self) } } - #[fixed_stack_segment] fn from_jsval(val: JSVal) -> Option<u32> { unsafe { Some(RUST_JSVAL_TO_INT(val) as u32) @@ -45,14 +41,12 @@ impl JSValConvertible for u32 { } impl JSValConvertible for i32 { - #[fixed_stack_segment] fn to_jsval(&self) -> JSVal { unsafe { RUST_UINT_TO_JSVAL(*self as u32) } } - #[fixed_stack_segment] fn from_jsval(val: JSVal) -> Option<i32> { unsafe { Some(RUST_JSVAL_TO_INT(val) as i32) @@ -61,14 +55,12 @@ impl JSValConvertible for i32 { } impl JSValConvertible for u16 { - #[fixed_stack_segment] fn to_jsval(&self) -> JSVal { unsafe { RUST_UINT_TO_JSVAL(*self as u32) } } - #[fixed_stack_segment] fn from_jsval(val: JSVal) -> Option<u16> { unsafe { Some(RUST_JSVAL_TO_INT(val) as u16) @@ -97,14 +89,12 @@ impl JSValConvertible for bool { } impl JSValConvertible for f32 { - #[fixed_stack_segment] fn to_jsval(&self) -> JSVal { unsafe { RUST_DOUBLE_TO_JSVAL(*self as f64) } } - #[fixed_stack_segment] fn from_jsval(val: JSVal) -> Option<f32> { unsafe { Some(RUST_JSVAL_TO_DOUBLE(val) as f32) @@ -113,14 +103,12 @@ impl JSValConvertible for f32 { } impl JSValConvertible for f64 { - #[fixed_stack_segment] fn to_jsval(&self) -> JSVal { unsafe { RUST_DOUBLE_TO_JSVAL(*self as f64) } } - #[fixed_stack_segment] fn from_jsval(val: JSVal) -> Option<f64> { unsafe { Some(RUST_JSVAL_TO_DOUBLE(val) as f64) diff --git a/src/components/script/dom/bindings/node.rs b/src/components/script/dom/bindings/node.rs index cdc4c58bce0..8bf2ab8a565 100644 --- a/src/components/script/dom/bindings/node.rs +++ b/src/components/script/dom/bindings/node.rs @@ -2,7 +2,7 @@ * 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 dom::bindings::utils::{Reflectable, Reflector, Traceable}; +use dom::bindings::utils::{Reflectable, Reflector, Traceable, trace_reflector}; use dom::types::*; use dom::node::AbstractNode; @@ -23,7 +23,6 @@ impl Reflectable for AbstractNode { impl Traceable for Node { fn trace(&self, tracer: *mut JSTracer) { - #[fixed_stack_segment] fn trace_node(tracer: *mut JSTracer, node: Option<AbstractNode>, name: &str) { if node.is_none() { return; @@ -35,10 +34,10 @@ impl Traceable for Node { unsafe { (*tracer).debugPrinter = ptr::null(); (*tracer).debugPrintIndex = -1; - do name.to_c_str().with_ref |name| { + name.to_c_str().with_ref(|name| { (*tracer).debugPrintArg = name as *libc::c_void; JS_CallTracer(cast::transmute(tracer), obj, JSTRACE_OBJECT as u32); - } + }); } } debug!("tracing {:p}?:", self.reflector().get_jsobject()); @@ -47,5 +46,7 @@ impl Traceable for Node { trace_node(tracer, self.last_child, "last child"); trace_node(tracer, self.next_sibling, "next sibling"); trace_node(tracer, self.prev_sibling, "prev sibling"); + let owner_doc = self.owner_doc(); + trace_reflector(tracer, "document", owner_doc.reflector()); } } diff --git a/src/components/script/dom/bindings/proxyhandler.rs b/src/components/script/dom/bindings/proxyhandler.rs index 5201b724070..2f8267d4f29 100644 --- a/src/components/script/dom/bindings/proxyhandler.rs +++ b/src/components/script/dom/bindings/proxyhandler.rs @@ -44,7 +44,6 @@ pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid, } } -#[fixed_stack_segment] pub fn defineProperty_(cx: *JSContext, proxy: *JSObject, id: jsid, desc: *JSPropertyDescriptor) -> JSBool { unsafe { @@ -72,7 +71,6 @@ pub extern fn defineProperty(cx: *JSContext, proxy: *JSObject, id: jsid, defineProperty_(cx, proxy, id, desc) } -#[fixed_stack_segment] pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString { unsafe { let name = str::raw::from_c_str(className); @@ -83,7 +81,7 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString { } let result = ~"[object " + name + "]"; - for (i, c) in result.iter().enumerate() { + for (i, c) in result.chars().enumerate() { *chars.offset(i as int) = c as jschar; } *chars.offset(nchars as int) = 0; @@ -95,7 +93,6 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString { } } -#[fixed_stack_segment] pub fn GetExpandoObject(obj: *JSObject) -> *JSObject { unsafe { assert!(is_dom_proxy(obj)); @@ -108,7 +105,6 @@ pub fn GetExpandoObject(obj: *JSObject) -> *JSObject { } } -#[fixed_stack_segment] pub fn EnsureExpandoObject(cx: *JSContext, obj: *JSObject) -> *JSObject { unsafe { assert!(is_dom_proxy(obj)); diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 99f0d9f4fa9..f1e69e32021 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -29,7 +29,7 @@ use js::jsapi::{JS_NewUCStringCopyN, JS_DefineFunctions, JS_DefineProperty}; use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot}; use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass, JSNative, JSTracer}; use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor}; -use js::jsapi::{JSPropertyOp, JSStrictPropertyOp, JS_NewGlobalObject, JS_InitStandardClasses}; +use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses}; use js::jsapi::{JSString, JS_CallTracer, JSTRACE_OBJECT}; use js::jsapi::{JS_IsExceptionPending}; use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; @@ -47,22 +47,18 @@ mod jsval { use js::glue::{RUST_JSVAL_IS_STRING, RUST_JSVAL_TO_STRING}; use js::jsapi::{JSVal, JSString}; - #[fixed_stack_segment] pub fn is_null(v: JSVal) -> bool { unsafe { RUST_JSVAL_IS_NULL(v) == 1 } } - #[fixed_stack_segment] pub fn is_undefined(v: JSVal) -> bool { unsafe { RUST_JSVAL_IS_VOID(v) == 1 } } - #[fixed_stack_segment] pub fn is_string(v: JSVal) -> bool { unsafe { RUST_JSVAL_IS_STRING(v) == 1 } } - #[fixed_stack_segment] pub unsafe fn to_string(v: JSVal) -> *JSString { RUST_JSVAL_TO_STRING(v) } @@ -149,7 +145,6 @@ fn is_dom_class(clasp: *JSClass) -> bool { } } -#[fixed_stack_segment] pub fn is_dom_proxy(obj: *JSObject) -> bool { unsafe { (js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) && @@ -157,7 +152,6 @@ pub fn is_dom_proxy(obj: *JSObject) -> bool { } } -#[fixed_stack_segment] pub unsafe fn dom_object_slot(obj: *JSObject) -> u32 { let clasp = JS_GetClass(obj); if is_dom_class(clasp) { @@ -168,14 +162,12 @@ pub unsafe fn dom_object_slot(obj: *JSObject) -> u32 { } } -#[fixed_stack_segment] pub unsafe fn unwrap<T>(obj: *JSObject) -> T { let slot = dom_object_slot(obj); let val = JS_GetReservedSlot(obj, slot); cast::transmute(RUST_JSVAL_TO_PRIVATE(val)) } -#[fixed_stack_segment] pub unsafe fn get_dom_class(obj: *JSObject) -> Result<DOMClass, ()> { let clasp = JS_GetClass(obj); if is_dom_class(clasp) { @@ -194,7 +186,7 @@ pub unsafe fn get_dom_class(obj: *JSObject) -> Result<DOMClass, ()> { pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<T, ()> { unsafe { - do get_dom_class(obj).and_then |dom_class| { + get_dom_class(obj).and_then(|dom_class| { if dom_class.interface_chain[proto_depth] == proto_id { debug!("good prototype"); Ok(unwrap(obj)) @@ -202,11 +194,10 @@ pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_d debug!("bad prototype"); Err(()) } - } + }) } } -#[fixed_stack_segment] pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<T, ()> { unsafe { let obj = RUST_JSVAL_TO_OBJECT(*val); @@ -216,22 +207,19 @@ pub fn unwrap_value<T>(val: *JSVal, proto_id: PrototypeList::id::ID, proto_depth pub unsafe fn squirrel_away<T>(x: @mut T) -> *Box<T> { let y: *Box<T> = cast::transmute(x); - cast::forget(x); y } -#[fixed_stack_segment] pub fn jsstring_to_str(cx: *JSContext, s: *JSString) -> ~str { unsafe { let length = 0; let chars = JS_GetStringCharsAndLength(cx, s, &length); - do vec::raw::buf_as_slice(chars, length as uint) |char_vec| { + vec::raw::buf_as_slice(chars, length as uint, |char_vec| { str::from_utf16(char_vec) - } + }) } } -#[fixed_stack_segment] pub fn jsid_to_str(cx: *JSContext, id: jsid) -> ~str { unsafe { assert!(RUST_JSID_IS_STRING(id) != 0); @@ -245,7 +233,6 @@ pub enum StringificationBehavior { Empty, } -#[fixed_stack_segment] pub fn jsval_to_str(cx: *JSContext, v: JSVal, nullBehavior: StringificationBehavior) -> Result<~str, ()> { if jsval::is_null(v) && nullBehavior == Empty { @@ -261,7 +248,6 @@ pub fn jsval_to_str(cx: *JSContext, v: JSVal, } } -#[fixed_stack_segment] pub fn jsval_to_domstring(cx: *JSContext, v: JSVal) -> Result<Option<DOMString>, ()> { if jsval::is_null(v) || jsval::is_undefined(v) { Ok(None) @@ -276,20 +262,17 @@ pub fn jsval_to_domstring(cx: *JSContext, v: JSVal) -> Result<Option<DOMString>, } } -#[fixed_stack_segment] pub unsafe fn str_to_jsval(cx: *JSContext, string: DOMString) -> JSVal { - do string.to_utf16().as_imm_buf |buf, len| { - let jsstr = JS_NewUCStringCopyN(cx, buf, len as libc::size_t); - if jsstr.is_null() { - // FIXME: is there something else we should do on failure? - JSVAL_NULL - } else { - RUST_STRING_TO_JSVAL(jsstr) - } + let string_utf16 = string.to_utf16(); + let jsstr = JS_NewUCStringCopyN(cx, string_utf16.as_ptr(), string_utf16.len() as libc::size_t); + if jsstr.is_null() { + // FIXME: is there something else we should do on failure? + JSVAL_NULL + } else { + RUST_STRING_TO_JSVAL(jsstr) } } -#[fixed_stack_segment] pub unsafe fn domstring_to_jsval(cx: *JSContext, string: Option<DOMString>) -> JSVal { match string { None => JSVAL_NULL, @@ -313,7 +296,7 @@ pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT; // NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and // LSetDOMProperty. Those constants need to be changed accordingly if this value // changes. -static JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1; +pub static JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1; pub struct NativeProperties { staticMethods: *JSFunctionSpec, @@ -379,7 +362,6 @@ pub struct DOMJSClass { dom_class: DOMClass } -#[fixed_stack_segment] pub fn GetProtoOrIfaceArray(global: *JSObject) -> **JSObject { unsafe { /*assert ((*JS_GetClass(global)).flags & JSCLASS_DOM_GLOBAL) != 0;*/ @@ -387,7 +369,6 @@ pub fn GetProtoOrIfaceArray(global: *JSObject) -> **JSObject { } } -#[fixed_stack_segment] pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSObject, protoProto: *JSObject, protoClass: *JSClass, constructorClass: *JSClass, constructor: Option<JSNative>, @@ -415,11 +396,11 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO let mut interface = ptr::null(); if constructorClass.is_not_null() || constructor.is_some() { - interface = do name.to_c_str().with_ref |s| { + interface = name.to_c_str().with_ref(|s| { CreateInterfaceObject(cx, global, receiver, constructorClass, constructor, ctorNargs, proto, staticMethods, constants, s) - }; + }); if interface.is_null() { return ptr::null(); } @@ -432,7 +413,6 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO } } -#[fixed_stack_segment] fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject, constructorClass: *JSClass, constructorNative: Option<JSNative>, ctorNargs: u32, proto: *JSObject, @@ -467,11 +447,11 @@ fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject, } if constructorClass.is_not_null() { - let toString = do "toString".to_c_str().with_ref |s| { + let toString = "toString".to_c_str().with_ref(|s| { DefineFunctionWithReserved(cx, constructor, s, InterfaceObjectToString, 0, 0) - }; + }); if toString.is_null() { return ptr::null(); } @@ -511,7 +491,6 @@ fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject, } } -#[fixed_stack_segment] fn DefineConstants(cx: *JSContext, obj: *JSObject, constants: *ConstantSpec) -> bool { let mut i = 0; loop { @@ -541,21 +520,18 @@ fn DefineConstants(cx: *JSContext, obj: *JSObject, constants: *ConstantSpec) -> } } -#[fixed_stack_segment] fn DefineMethods(cx: *JSContext, obj: *JSObject, methods: *JSFunctionSpec) -> bool { unsafe { JS_DefineFunctions(cx, obj, methods) != 0 } } -#[fixed_stack_segment] fn DefineProperties(cx: *JSContext, obj: *JSObject, properties: *JSPropertySpec) -> bool { unsafe { JS_DefineProperties(cx, obj, properties) != 0 } } -#[fixed_stack_segment] fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject, parentProto: *JSObject, protoClass: *JSClass, methods: *JSFunctionSpec, @@ -592,17 +568,16 @@ pub trait Traceable { fn trace(&self, trc: *mut JSTracer); } -#[fixed_stack_segment] pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) { unsafe { - do description.to_c_str().with_ref |name| { + description.to_c_str().with_ref(|name| { (*tracer).debugPrinter = ptr::null(); (*tracer).debugPrintIndex = -1; (*tracer).debugPrintArg = name as *libc::c_void; debug!("tracing {:s}", description); JS_CallTracer(tracer as *JSTracer, reflector.get_jsobject(), JSTRACE_OBJECT as u32); - } + }); } } @@ -610,13 +585,12 @@ pub fn trace_option<T: Reflectable>(tracer: *mut JSTracer, description: &str, op option.map(|some| trace_reflector(tracer, description, some.reflector())); } -#[fixed_stack_segment] pub fn initialize_global(global: *JSObject) { let protoArray = @mut ([0 as *JSObject, ..PrototypeList::id::_ID_Count as uint]); unsafe { //XXXjdm we should be storing the box pointer instead of the inner - let box = squirrel_away(protoArray); - let inner = ptr::to_unsafe_ptr(&(*box).data); + let box_ = squirrel_away(protoArray); + let inner = ptr::to_unsafe_ptr(&(*box_).data); JS_SetReservedSlot(global, DOM_PROTOTYPE_SLOT, RUST_PRIVATE_TO_JSVAL(inner as *libc::c_void)); @@ -668,7 +642,6 @@ impl Reflector { } } -#[fixed_stack_segment] pub fn GetReflector(cx: *JSContext, reflector: &Reflector, vp: *mut JSVal) -> JSBool { let obj = reflector.get_jsobject(); @@ -679,7 +652,6 @@ pub fn GetReflector(cx: *JSContext, reflector: &Reflector, } } -#[fixed_stack_segment] pub fn GetPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid, found: *mut bool, vp: *JSVal) -> bool { unsafe { @@ -703,7 +675,6 @@ pub fn GetPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid, found: } } -#[fixed_stack_segment] pub fn GetArrayIndexFromId(_cx: *JSContext, id: jsid) -> Option<u32> { unsafe { if RUST_JSID_IS_INT(id) != 0 { @@ -727,7 +698,6 @@ pub fn GetArrayIndexFromId(_cx: *JSContext, id: jsid) -> Option<u32> { }*/ } -#[fixed_stack_segment] pub fn XrayResolveProperty(cx: *JSContext, wrapper: *JSObject, id: jsid, @@ -754,7 +724,7 @@ pub fn XrayResolveProperty(cx: *JSContext, RUST_SET_JITINFO(fun, attr.getter.info); let funobj = JS_GetFunctionObject(fun); - (*desc).getter = Some(funobj as JSPropertyOp); + (*desc).getter = Some(cast::transmute(funobj)); (*desc).attrs |= JSPROP_GETTER; if attr.setter.op.is_some() { let fun = JS_NewFunction(cx, attr.setter.op, 1, 0, global, ptr::null()); @@ -764,7 +734,7 @@ pub fn XrayResolveProperty(cx: *JSContext, RUST_SET_JITINFO(fun, attr.setter.info); let funobj = JS_GetFunctionObject(fun); - (*desc).setter = Some(funobj as JSStrictPropertyOp); + (*desc).setter = Some(cast::transmute(funobj)); (*desc).attrs |= JSPROP_SETTER; } else { (*desc).setter = None; @@ -777,7 +747,6 @@ pub fn XrayResolveProperty(cx: *JSContext, } } -#[fixed_stack_segment] fn InternJSString(cx: *JSContext, chars: *libc::c_char) -> Option<jsid> { unsafe { let s = JS_InternString(cx, chars); @@ -824,7 +793,6 @@ pub struct EnumEntry { length: uint } -#[fixed_stack_segment] pub fn FindEnumStringIndex(cx: *JSContext, v: JSVal, values: &[EnumEntry]) -> Result<uint, ()> { @@ -865,14 +833,12 @@ pub fn HasPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid) -> boo return !GetPropertyOnPrototype(cx, proxy, id, &mut found, ptr::null()) || found; } -#[fixed_stack_segment] pub fn IsConvertibleToCallbackInterface(cx: *JSContext, obj: *JSObject) -> bool { unsafe { JS_ObjectIsDate(cx, obj) == 0 && JS_ObjectIsRegExp(cx, obj) == 0 } } -#[fixed_stack_segment] pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject { unsafe { let obj = JS_NewGlobalObject(cx, class, ptr::null()); @@ -886,7 +852,6 @@ pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject { } /// Returns the global object of the realm that the given JS object was created in. -#[fixed_stack_segment] fn global_object_for_js_object(obj: *JSObject) -> *Box<window::Window> { unsafe { let global = GetGlobalForObjectCrossCompartment(obj); @@ -900,7 +865,6 @@ fn global_object_for_js_object(obj: *JSObject) -> *Box<window::Window> { } } -#[fixed_stack_segment] fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext { unsafe { let win = global_object_for_js_object(obj); @@ -912,7 +876,6 @@ fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext { } /// Returns the global object of the realm that the given DOM object was created in. -#[fixed_stack_segment] pub fn global_object_for_dom_object<T: Reflectable>(obj: &mut T) -> *Box<window::Window> { global_object_for_js_object(obj.reflector().get_jsobject()) } @@ -921,7 +884,6 @@ pub fn cx_for_dom_object<T: Reflectable>(obj: &mut T) -> *JSContext { cx_for_dom_reflector(obj.reflector().get_jsobject()) } -#[fixed_stack_segment] pub fn throw_method_failed_with_details<T>(cx: *JSContext, result: Result<T, Error>, interface: &'static str, @@ -929,9 +891,9 @@ pub fn throw_method_failed_with_details<T>(cx: *JSContext, assert!(result.is_err()); assert!(unsafe { JS_IsExceptionPending(cx) } == 0); let message = format!("Method failed: {}.{}", interface, member); - do message.with_c_str |string| { + message.with_c_str(|string| { unsafe { ReportError(cx, string) }; - } + }); return 0; } @@ -979,7 +941,7 @@ pub fn xml_name_type(name: &str) -> XMLName { } } - let mut iter = name.iter(); + let mut iter = name.chars(); let mut non_qname_colons = false; let mut seen_colon = false; match iter.next() { @@ -994,7 +956,7 @@ pub fn xml_name_type(name: &str) -> XMLName { } } - for c in name.iter() { + for c in name.chars() { if !is_valid_continuation(c) { return InvalidXMLName; } diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index be4a8f06330..15a952cd418 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -55,17 +55,12 @@ impl AbstractDocument { } } - unsafe fn transmute<T, R>(&self, f: &fn(&T) -> R) -> R { - let box: *Box<T> = cast::transmute(self.document); - f(&(*box).data) + unsafe fn transmute<T, R>(&self, f: |&T| -> R) -> R { + let box_: *Box<T> = cast::transmute(self.document); + f(&(*box_).data) } - unsafe fn transmute_mut<T, R>(&self, f: &fn(&mut T) -> R) -> R { - let box: *mut Box<T> = cast::transmute(self.document); - f(&mut (*box).data) - } - - pub fn with_html<R>(&self, callback: &fn(&HTMLDocument) -> R) -> R { + pub fn with_html<R>(&self, callback: |&HTMLDocument| -> R) -> R { match self.document().doctype { HTML => unsafe { self.transmute(callback) }, _ => fail!("attempt to downcast a non-HTMLDocument to HTMLDocument") @@ -105,9 +100,9 @@ impl Document { let document = reflect_dom_object(document, window, wrap_fn); assert!(document.reflector().get_jsobject().is_not_null()); - // This surrenders memory management of the document! + // JS object now owns the Document, so transmute_copy is needed let abstract = AbstractDocument { - document: unsafe { cast::transmute(document) } + document: unsafe { cast::transmute_copy(&document) } }; abstract.mut_document().node.set_owner_doc(abstract); abstract @@ -165,10 +160,6 @@ impl Document { self.node.child_elements().next() } - fn get_cx(&self) -> *JSContext { - self.window.get_cx() - } - pub fn GetElementsByTagName(&self, tag: DOMString) -> @mut HTMLCollection { self.createHTMLCollection(|elem| eq_slice(elem.tag_name, tag)) } @@ -238,9 +229,9 @@ impl Document { } for child in node.children() { if child.is_text() { - do child.with_imm_text() |text| { + child.with_imm_text(|text| { title = title + text.element.Data(); - } + }); } } break; @@ -249,7 +240,7 @@ impl Document { } } } - let v: ~[&str] = title.word_iter().collect(); + let v: ~[&str] = title.words().collect(); title = v.connect(" "); title = title.trim().to_owned(); title @@ -295,12 +286,12 @@ impl Document { } fn get_html_element(&self) -> Option<AbstractNode> { - do self.GetDocumentElement().filtered |root| { + self.GetDocumentElement().filtered(|root| { match root.type_id() { ElementNodeTypeId(HTMLHtmlElementTypeId) => true, _ => false } - } + }) } // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-head @@ -317,13 +308,13 @@ impl Document { match self.get_html_element() { None => None, Some(root) => { - do root.children().find |child| { + root.children().find(|child| { match child.type_id() { ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => true, _ => false } - } + }) } } } @@ -366,18 +357,18 @@ impl Document { elem.get_attr(Null, "name").is_some() && eq_slice(elem.get_attr(Null, "name").unwrap(), name)) } - pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection { + pub fn createHTMLCollection(&self, callback: |elem: &Element| -> bool) -> @mut HTMLCollection { let mut elements = ~[]; match self.GetDocumentElement() { None => {}, Some(root) => { for child in root.traverse_preorder() { if child.is_element() { - do child.with_imm_element |elem| { + child.with_imm_element(|elem| { if callback(elem) { elements.push(child); } - } + }); } } } @@ -436,25 +427,24 @@ impl Document { } #[inline(always)] -fn foreach_ided_elements(root: &AbstractNode, callback: &fn(&DOMString, &AbstractNode)) { +fn foreach_ided_elements(root: &AbstractNode, callback: |&DOMString, &AbstractNode|) { for node in root.traverse_preorder() { if !node.is_element() { continue; } - do node.with_imm_element |element| { + node.with_imm_element(|element| { match element.get_attr(Null, "id") { Some(id) => { callback(&id.to_str(), &node); } None => () } - } + }); } } impl Traceable for Document { - #[fixed_stack_segment] fn trace(&self, tracer: *mut JSTracer) { self.node.trace(tracer); } diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 8e5294d2663..df5e76d2168 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -22,7 +22,6 @@ use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage}; use layout_interface::{MatchSelectorsDocumentDamage}; use style; -use std::comm; use std::str::eq; use std::ascii::StrAsciiExt; @@ -123,7 +122,7 @@ pub enum ElementTypeId { // -impl<'self> Element { +impl Element { pub fn new_inherited(type_id: ElementTypeId, tag_name: ~str, namespace: Namespace, document: AbstractDocument) -> Element { Element { node: Node::new_inherited(ElementNodeTypeId(type_id), document), @@ -175,7 +174,7 @@ impl<'self> Element { //FIXME: Throw for XML-invalid names //FIXME: Throw for XMLNS-invalid names let (prefix, local_name) = if name.contains(":") { - let parts: ~[&str] = name.splitn_iter(':', 1).collect(); + let parts: ~[&str] = name.splitn(':', 1).collect(); (Some(parts[0].to_owned()), parts[1].to_owned()) } else { (None, name.clone()) @@ -238,14 +237,14 @@ impl<'self> Element { // This hardcoding is awful. match abstract_self.type_id() { ElementNodeTypeId(HTMLImageElementTypeId) => { - do abstract_self.with_mut_image_element |image| { + abstract_self.with_mut_image_element(|image| { image.AfterSetAttr(local_name.clone(), value.clone()); - } + }); } ElementNodeTypeId(HTMLIframeElementTypeId) => { - do abstract_self.with_mut_iframe_element |iframe| { + abstract_self.with_mut_iframe_element(|iframe| { iframe.AfterSetAttr(local_name.clone(), value.clone()); - } + }); } _ => () } @@ -390,18 +389,18 @@ impl Element { let win = self.node.owner_doc().document().window; let node = abstract_self; assert!(node.is_element()); - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); let rects = match win.page.query_layout(ContentBoxesQuery(node, chan), port) { ContentBoxesResponse(rects) => { - do rects.map |r| { + rects.map(|r| { ClientRect::new( win, r.origin.y, r.origin.y + r.size.height, r.origin.x, r.origin.x + r.size.width) - } + }) }, }; @@ -412,7 +411,7 @@ impl Element { let win = self.node.owner_doc().document().window; let node = abstract_self; assert!(node.is_element()); - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); match win.page.query_layout(ContentBoxQuery(node, chan), port) { ContentBoxResponse(rect) => { ClientRect::new( diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs index 69b96be8660..f2124ea37d9 100644 --- a/src/components/script/dom/event.rs +++ b/src/components/script/dom/event.rs @@ -35,9 +35,9 @@ pub enum EventPhase { } impl AbstractEvent { - pub fn from_box(box: *mut Box<Event>) -> AbstractEvent { + pub fn from_box(box_: *mut Box<Event>) -> AbstractEvent { AbstractEvent { - event: box + event: box_ } } @@ -47,15 +47,15 @@ impl AbstractEvent { fn transmute<'a, T>(&'a self) -> &'a T { unsafe { - let box: *Box<T> = self.event as *Box<T>; - &(*box).data + let box_: *Box<T> = self.event as *Box<T>; + &(*box_).data } } fn transmute_mut<'a, T>(&'a self) -> &'a mut T { unsafe { - let box: *mut Box<T> = self.event as *mut Box<T>; - &mut (*box).data + let box_: *mut Box<T> = self.event as *mut Box<T>; + &mut (*box_).data } } diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index d3768ed656e..9ee4c123870 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -44,9 +44,9 @@ pub struct AbstractEventTarget { } impl AbstractEventTarget { - pub fn from_box<T>(box: *mut Box<T>) -> AbstractEventTarget { + pub fn from_box<T>(box_: *mut Box<T>) -> AbstractEventTarget { AbstractEventTarget { - eventtarget: box as *mut Box<EventTarget> + eventtarget: box_ as *mut Box<EventTarget> } } @@ -86,15 +86,15 @@ impl AbstractEventTarget { fn transmute<'a, T>(&'a self) -> &'a T { unsafe { - let box: *Box<T> = self.eventtarget as *Box<T>; - &(*box).data + let box_: *Box<T> = self.eventtarget as *Box<T>; + &(*box_).data } } fn transmute_mut<'a, T>(&'a mut self) -> &'a mut T { unsafe { - let box: *mut Box<T> = self.eventtarget as *mut Box<T>; - &mut (*box).data + let box_: *mut Box<T> = self.eventtarget as *mut Box<T>; + &mut (*box_).data } } @@ -127,17 +127,17 @@ impl EventTarget { } pub fn get_listeners(&self, type_: &str) -> Option<~[EventListener]> { - do self.handlers.find_equiv(&type_).map |listeners| { + self.handlers.find_equiv(&type_).map(|listeners| { listeners.iter().map(|entry| entry.listener).collect() - } + }) } pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase) -> Option<~[EventListener]> { - do self.handlers.find_equiv(&type_).map |listeners| { + self.handlers.find_equiv(&type_).map(|listeners| { let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase); filtered.map(|entry| entry.listener).collect() - } + }) } pub fn AddEventListener(&mut self, diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index f263444a335..5157ab03be7 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -95,7 +95,7 @@ impl HTMLIFrameElement { pub fn AfterSetAttr(&mut self, name: DOMString, value: DOMString) { if "sandbox" == name { let mut modes = AllowNothing as u8; - for word in value.split_iter(' ') { + for word in value.split(' ') { // FIXME: Workaround for https://github.com/mozilla/rust/issues/10683 let word_lower = word.to_ascii_lower(); modes |= match word_lower.as_slice() { diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index aa1a02d7ecb..53686661c10 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -112,7 +112,7 @@ impl HTMLImageElement { pub fn Width(&self, abstract_self: AbstractNode) -> u32 { let node = &self.htmlelement.element.node; let page = node.owner_doc().document().window.page; - let (port, chan) = stream(); + let (port, chan) = Chan::new(); match page.query_layout(ContentBoxQuery(abstract_self, chan), port) { ContentBoxResponse(rect) => { to_px(rect.size.width) as u32 @@ -129,7 +129,7 @@ impl HTMLImageElement { pub fn Height(&self, abstract_self: AbstractNode) -> u32 { let node = &self.htmlelement.element.node; let page = node.owner_doc().document().window.page; - let (port, chan) = stream(); + let (port, chan) = Chan::new(); match page.query_layout(ContentBoxQuery(abstract_self, chan), port) { ContentBoxResponse(rect) => { to_px(rect.size.height) as u32 diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index b002715eb1c..a98f89b4817 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -7,7 +7,6 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{DOMString, null_str_as_empty}; use dom::bindings::utils::{ErrorResult, Fallible, NotFound, HierarchyRequest}; -use dom::bindings::utils; use dom::characterdata::CharacterData; use dom::document::{AbstractDocument, DocumentTypeId}; use dom::documenttype::DocumentType; @@ -20,12 +19,15 @@ use dom::nodelist::{NodeList}; use dom::text::Text; use js::jsapi::{JSObject, JSContext}; -use servo_util::slot::{MutSlotRef, Slot, SlotRef}; -use std::cast::transmute; + +use layout_interface::{LayoutChan, ReapLayoutDataMsg}; + use std::cast; -use std::unstable::raw::Box; -use std::util; +use std::cast::transmute; +use std::cell::{RefCell, Ref, RefMut}; use std::iter::Filter; +use std::util; +use std::unstable::raw::Box; // // The basic Node structure @@ -37,7 +39,7 @@ use std::iter::Filter; /// FIXME: This should be replaced with a trait once they can inherit from structs. #[deriving(Eq)] pub struct AbstractNode { - priv obj: *mut Box<Node>, + priv obj: *mut (), } /// An HTML node. @@ -109,30 +111,43 @@ impl Drop for Node { } /// Encapsulates the abstract layout data. +pub struct LayoutData { + priv chan: Option<LayoutChan>, + priv data: *(), +} + pub struct LayoutDataRef { - priv data: Slot<Option<*()>>, + data_cell: RefCell<Option<LayoutData>>, } impl LayoutDataRef { - #[inline] - pub fn init() -> LayoutDataRef { + pub fn new() -> LayoutDataRef { LayoutDataRef { - data: Slot::init(None), + data_cell: RefCell::new(None), } } - /// Creates a new piece of layout data from a value. - #[inline] pub unsafe fn from_data<T>(data: ~T) -> LayoutDataRef { LayoutDataRef { - data: Slot::init(Some(cast::transmute(data))), + data_cell: RefCell::new(Some(cast::transmute(data))), } } - /// Returns true if this layout data is present or false otherwise. + /// Returns true if there is layout data present. #[inline] pub fn is_present(&self) -> bool { - self.data.get().is_some() + let data_ref = self.data_cell.borrow(); + data_ref.get().is_some() + } + + /// Take the chan out of the layout data if it is present. + pub fn take_chan(&self) -> Option<LayoutChan> { + let mut data_ref = self.data_cell.borrow_mut(); + let layout_data = data_ref.get(); + match *layout_data { + None => None, + Some(..) => Some(layout_data.get_mut_ref().chan.take_unwrap()), + } } /// Borrows the layout data immutably, *asserting that there are no mutators*. Bad things will @@ -141,17 +156,15 @@ impl LayoutDataRef { /// /// FIXME(pcwalton): Enforce this invariant via the type system. Will require traversal /// functions to be trusted, but c'est la vie. - #[inline] - pub unsafe fn borrow_unchecked<'a>(&'a self) -> &'a () { - cast::transmute(self.data.borrow_unchecked()) - } + // #[inline] + // pub unsafe fn borrow_unchecked<'a>(&'a self) -> &'a () { + // self.data.borrow_unchecked() + // } /// Borrows the layout data immutably. This function is *not* thread-safe. #[inline] - pub fn borrow<'a>(&'a self) -> SlotRef<'a,()> { - unsafe { - cast::transmute(self.data.borrow()) - } + pub fn borrow<'a>(&'a self) -> Ref<'a,Option<LayoutData>> { + self.data_cell.borrow() } /// Borrows the layout data mutably. This function is *not* thread-safe. @@ -160,10 +173,8 @@ impl LayoutDataRef { /// prevent CSS selector matching from mutably accessing nodes it's not supposed to and racing /// on it. This has already resulted in one bug! #[inline] - pub fn mutate<'a>(&'a self) -> MutSlotRef<'a,()> { - unsafe { - cast::transmute(self.data.mutate()) - } + pub fn borrow_mut<'a>(&'a self) -> RefMut<'a,Option<LayoutData>> { + self.data_cell.borrow_mut() } } @@ -193,13 +204,15 @@ impl Clone for AbstractNode { impl AbstractNode { pub fn node<'a>(&'a self) -> &'a Node { unsafe { - &(*self.obj).data + let box_: *mut Box<Node> = cast::transmute(self.obj); + &(*box_).data } } pub fn mut_node<'a>(&'a self) -> &'a mut Node { unsafe { - &mut (*self.obj).data + let box_: *mut Box<Node> = cast::transmute(self.obj); + &mut (*box_).data } } @@ -217,20 +230,20 @@ impl AbstractNode { pub fn is_element(&self) -> bool { match self.type_id() { - ElementNodeTypeId(*) => true, + ElementNodeTypeId(..) => true, _ => false } } pub fn is_document(&self) -> bool { match self.type_id() { - DocumentNodeTypeId(*) => true, + DocumentNodeTypeId(..) => true, _ => false } } } -impl<'self> AbstractNode { +impl<'a> AbstractNode { // Unsafe accessors pub unsafe fn as_cacheable_wrapper(&self) -> @mut Reflectable { @@ -252,7 +265,7 @@ impl<'self> AbstractNode { /// FIXME(pcwalton): Mark unsafe? pub fn from_box<T>(ptr: *mut Box<T>) -> AbstractNode { AbstractNode { - obj: ptr as *mut Box<Node> + obj: ptr as *mut () } } @@ -291,27 +304,27 @@ impl<'self> AbstractNode { // Downcasting borrows // - pub fn transmute<T, R>(self, f: &fn(&T) -> R) -> R { + pub fn transmute<'a, T, R>(self, f: |&'a T| -> R) -> R { unsafe { let node_box: *mut Box<Node> = transmute(self.obj); let node = &mut (*node_box).data; let old = node.abstract; node.abstract = Some(self); - let box: *Box<T> = transmute(self.obj); - let rv = f(&(*box).data); + let box_: *Box<T> = transmute(self.obj); + let rv = f(&(*box_).data); node.abstract = old; rv } } - pub fn transmute_mut<T, R>(self, f: &fn(&mut T) -> R) -> R { + pub fn transmute_mut<T, R>(self, f: |&mut T| -> R) -> R { unsafe { let node_box: *mut Box<Node> = transmute(self.obj); let node = &mut (*node_box).data; let old = node.abstract; node.abstract = Some(self); - let box: *Box<T> = transmute(self.obj); - let rv = f(cast::transmute(&(*box).data)); + let box_: *Box<T> = transmute(self.obj); + let rv = f(cast::transmute(&(*box_).data)); node.abstract = old; rv } @@ -323,14 +336,14 @@ impl<'self> AbstractNode { self.is_text() || self.is_comment() } - pub fn with_imm_characterdata<R>(self, f: &fn(&CharacterData) -> R) -> R { + pub fn with_imm_characterdata<R>(self, f: |&CharacterData| -> R) -> R { if !self.is_characterdata() { fail!(~"node is not characterdata"); } self.transmute(f) } - pub fn with_mut_characterdata<R>(self, f: &fn(&mut CharacterData) -> R) -> R { + pub fn with_mut_characterdata<R>(self, f: |&mut CharacterData| -> R) -> R { if !self.is_characterdata() { fail!(~"node is not characterdata"); } @@ -341,14 +354,14 @@ impl<'self> AbstractNode { self.type_id() == DoctypeNodeTypeId } - pub fn with_imm_doctype<R>(self, f: &fn(&DocumentType) -> R) -> R { + pub fn with_imm_doctype<R>(self, f: |&DocumentType| -> R) -> R { if !self.is_doctype() { fail!(~"node is not doctype"); } self.transmute(f) } - pub fn with_mut_doctype<R>(self, f: &fn(&mut DocumentType) -> R) -> R { + pub fn with_mut_doctype<R>(self, f: |&mut DocumentType| -> R) -> R { if !self.is_doctype() { fail!(~"node is not doctype"); } @@ -375,14 +388,14 @@ impl<'self> AbstractNode { } } - pub fn with_imm_text<R>(self, f: &fn(&Text) -> R) -> R { + pub fn with_imm_text<R>(self, f: |&Text| -> R) -> R { if !self.is_text() { fail!(~"node is not text"); } self.transmute(f) } - pub fn with_mut_text<R>(self, f: &fn(&mut Text) -> R) -> R { + pub fn with_mut_text<R>(self, f: |&mut Text| -> R) -> R { if !self.is_text() { fail!(~"node is not text"); } @@ -390,7 +403,7 @@ impl<'self> AbstractNode { } // FIXME: This should be doing dynamic borrow checking for safety. - pub fn with_imm_element<R>(self, f: &fn(&Element) -> R) -> R { + pub fn with_imm_element<R>(self, f: |&Element| -> R) -> R { if !self.is_element() { fail!(~"node is not an element"); } @@ -398,7 +411,7 @@ impl<'self> AbstractNode { } // FIXME: This should be doing dynamic borrow checking for safety. - pub fn as_mut_element<R>(self, f: &fn(&mut Element) -> R) -> R { + pub fn as_mut_element<R>(self, f: |&mut Element| -> R) -> R { if !self.is_element() { fail!(~"node is not an element"); } @@ -413,7 +426,7 @@ impl<'self> AbstractNode { } } - pub fn with_mut_image_element<R>(self, f: &fn(&mut HTMLImageElement) -> R) -> R { + pub fn with_mut_image_element<R>(self, f: |&mut HTMLImageElement| -> R) -> R { if !self.is_image_element() { fail!(~"node is not an image element"); } @@ -424,7 +437,7 @@ impl<'self> AbstractNode { self.type_id() == ElementNodeTypeId(HTMLIframeElementTypeId) } - pub fn with_mut_iframe_element<R>(self, f: &fn(&mut HTMLIFrameElement) -> R) -> R { + pub fn with_mut_iframe_element<R>(self, f: |&mut HTMLIFrameElement| -> R) -> R { if !self.is_iframe_element() { fail!(~"node is not an iframe element"); } @@ -440,12 +453,12 @@ impl<'self> AbstractNode { } pub unsafe fn raw_object(self) -> *mut Box<Node> { - self.obj + cast::transmute(self.obj) } pub fn from_raw(raw: *mut Box<Node>) -> AbstractNode { AbstractNode { - obj: raw + obj: raw as *mut () } } @@ -479,10 +492,6 @@ impl<'self> AbstractNode { // Convenience accessors // - fn is_leaf(&self) -> bool { - self.first_child().is_none() - } - pub fn children(&self) -> AbstractNodeChildrenIterator { self.node().children() } @@ -610,35 +619,6 @@ impl AbstractNode { child_node.set_next_sibling(None); child_node.set_parent_node(None); } - - // - // Low-level pointer stitching wrappers - // - - fn set_parent_node(&self, new_parent_node: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_parent_node(new_parent_node) - } - - fn set_first_child(&self, new_first_child: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_first_child(new_first_child) - } - - fn set_last_child(&self, new_last_child: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_last_child(new_last_child) - } - - fn set_prev_sibling(&self, new_prev_sibling: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_prev_sibling(new_prev_sibling) - } - - fn set_next_sibling(&self, new_next_sibling: Option<AbstractNode>) { - let node = self.mut_node(); - node.set_next_sibling(new_next_sibling) - } } // @@ -652,9 +632,9 @@ pub struct AbstractNodeChildrenIterator { impl Iterator<AbstractNode> for AbstractNodeChildrenIterator { fn next(&mut self) -> Option<AbstractNode> { let node = self.current_node; - self.current_node = do self.current_node.and_then |node| { + self.current_node = self.current_node.and_then(|node| { node.next_sibling() - }; + }); node } } @@ -766,9 +746,9 @@ impl Node { assert!(node.reflector().get_jsobject().is_null()); let node = reflect_dom_object(node, document.document().window, wrap_fn); assert!(node.reflector().get_jsobject().is_not_null()); - // This surrenders memory management of the node! + // JS owns the node now, so transmute_copy to not increase the refcount AbstractNode { - obj: unsafe { transmute(node) }, + obj: unsafe { cast::transmute_copy(&node) }, } } @@ -798,16 +778,19 @@ impl Node { flags: NodeFlags::new(type_id), - layout_data: LayoutDataRef::init(), + layout_data: LayoutDataRef::new(), } } /// Sends layout data, if any, back to the script task to be destroyed. pub unsafe fn reap_layout_data(&mut self) { if self.layout_data.is_present() { - let layout_data = util::replace(&mut self.layout_data, LayoutDataRef::init()); - let js_window = utils::global_object_for_dom_object(self); - (*js_window).data.page.reap_dead_layout_data(layout_data) + let layout_data = util::replace(&mut self.layout_data, LayoutDataRef::new()); + let layout_chan = layout_data.take_chan(); + match layout_chan { + None => {} + Some(chan) => chan.send(ReapLayoutDataMsg(layout_data)), + } } } @@ -825,17 +808,17 @@ impl Node { pub fn NodeName(&self, abstract_self: AbstractNode) -> DOMString { match self.type_id { - ElementNodeTypeId(*) => { - do abstract_self.with_imm_element |element| { + ElementNodeTypeId(..) => { + abstract_self.with_imm_element(|element| { element.TagName() - } + }) } CommentNodeTypeId => ~"#comment", TextNodeTypeId => ~"#text", DoctypeNodeTypeId => { - do abstract_self.with_imm_doctype |doctype| { + abstract_self.with_imm_doctype(|doctype| { doctype.name.clone() - } + }) }, DocumentFragmentNodeTypeId => ~"#document-fragment", DocumentNodeTypeId(_) => ~"#document" @@ -848,7 +831,7 @@ impl Node { pub fn GetOwnerDocument(&self) -> Option<AbstractDocument> { match self.type_id { - ElementNodeTypeId(*) | + ElementNodeTypeId(..) | CommentNodeTypeId | TextNodeTypeId | DoctypeNodeTypeId | @@ -889,9 +872,9 @@ impl Node { match self.type_id { // ProcessingInstruction CommentNodeTypeId | TextNodeTypeId => { - do abstract_self.with_imm_characterdata() |characterdata| { + abstract_self.with_imm_characterdata(|characterdata| { Some(characterdata.Data()) - } + }) } _ => { None @@ -906,21 +889,21 @@ impl Node { pub fn GetTextContent(&self, abstract_self: AbstractNode) -> Option<DOMString> { match self.type_id { - DocumentFragmentNodeTypeId | ElementNodeTypeId(*) => { + DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { let mut content = ~""; for node in abstract_self.traverse_preorder() { if node.is_text() { - do node.with_imm_text() |text| { + node.with_imm_text(|text| { content = content + text.element.Data(); - } + }) } } Some(content) } CommentNodeTypeId | TextNodeTypeId => { - do abstract_self.with_imm_characterdata() |characterdata| { + abstract_self.with_imm_characterdata(|characterdata| { Some(characterdata.Data()) - } + }) } DoctypeNodeTypeId | DocumentNodeTypeId(_) => { None @@ -968,9 +951,9 @@ impl Node { // Step 1. match parent.type_id() { - DocumentNodeTypeId(*) | + DocumentNodeTypeId(..) | DocumentFragmentNodeTypeId | - ElementNodeTypeId(*) => (), + ElementNodeTypeId(..) => (), _ => { return Err(HierarchyRequest); }, @@ -999,7 +982,7 @@ impl Node { TextNodeTypeId | // ProcessingInstructionNodeTypeId | CommentNodeTypeId => (), - DocumentNodeTypeId(*) => return Err(HierarchyRequest), + DocumentNodeTypeId(..) => return Err(HierarchyRequest), } // Step 5. @@ -1241,7 +1224,7 @@ impl Node { -> ErrorResult { let value = null_str_as_empty(&value); match self.type_id { - DocumentFragmentNodeTypeId | ElementNodeTypeId(*) => { + DocumentFragmentNodeTypeId | ElementNodeTypeId(..) => { // Step 1-2. let node = if value.len() == 0 { None @@ -1255,13 +1238,13 @@ impl Node { CommentNodeTypeId | TextNodeTypeId => { self.wait_until_safe_to_modify_dom(); - do abstract_self.with_mut_characterdata() |characterdata| { + abstract_self.with_mut_characterdata(|characterdata| { characterdata.data = value.clone(); // Notify the document that the content of this node is different let document = self.owner_doc(); document.document().content_changed(); - } + }) } DoctypeNodeTypeId | DocumentNodeTypeId(_) => {} } diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 54660c4286a..f9ba483c4f9 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -18,19 +18,17 @@ use servo_msg::compositor_msg::ScriptListener; use servo_net::image_cache_task::ImageCacheTask; use js::glue::*; -use js::jsapi::{JSObject, JSContext, JS_DefineProperty}; -use js::jsapi::{JSPropertyOp, JSStrictPropertyOp, JSTracer}; +use js::jsapi::{JSObject, JSContext, JS_DefineProperty, JSTracer, JSVal}; use js::{JSVAL_NULL, JSPROP_ENUMERATE}; -use std::cell::Cell; -use std::comm; +use std::cast; use std::comm::SharedChan; +use std::comm::Select; use std::hashmap::HashSet; +use std::io::timer::Timer; +use std::num; use std::ptr; -use std::int; -use std::rt::io::timer::Timer; -use std::task::spawn_with; -use js::jsapi::JSVal; +use std::to_bytes::Cb; pub enum TimerControlMsg { TimerMessage_Fire(~TimerData), @@ -38,6 +36,29 @@ pub enum TimerControlMsg { TimerMessage_TriggerExit //XXXjdm this is just a quick hack to talk to the script task } +pub struct TimerHandle { + handle: i32, + cancel_chan: Option<Chan<()>>, +} + +impl IterBytes for TimerHandle { + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + self.handle.iter_bytes(lsb0, f) + } +} + +impl Eq for TimerHandle { + fn eq(&self, other: &TimerHandle) -> bool { + self.handle == other.handle + } +} + +impl TimerHandle { + fn cancel(&self) { + self.cancel_chan.as_ref().map(|chan| chan.send(())); + } +} + pub struct Window { eventtarget: EventTarget, page: @mut Page, @@ -47,7 +68,7 @@ pub struct Window { location: Option<@mut Location>, navigator: Option<@mut Navigator>, image_cache_task: ImageCacheTask, - active_timers: ~HashSet<i32>, + active_timers: ~HashSet<TimerHandle>, next_timer_handle: i32, } @@ -61,6 +82,9 @@ impl Window { impl Drop for Window { fn drop(&mut self) { self.timer_chan.send(TimerMessage_Close); + for handle in self.active_timers.iter() { + handle.cancel(); + } } } @@ -160,29 +184,40 @@ impl Reflectable for Window { impl Window { pub fn SetTimeout(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 { - let timeout = int::max(0, timeout) as u64; + let timeout = num::max(0, timeout) as u64; let handle = self.next_timer_handle; self.next_timer_handle += 1; // Post a delayed message to the per-window timer task; it will dispatch it // to the relevant script handler that will deal with it. - let tm = Cell::new(Timer::new().unwrap()); + let tm = Timer::new().unwrap(); + let (cancel_port, cancel_chan) = Chan::new(); let chan = self.timer_chan.clone(); - do spawn { - let mut tm = tm.take(); - tm.sleep(timeout); - chan.send(TimerMessage_Fire(~TimerData { - handle: handle, - funval: callback, - args: ~[] - })); - } - self.active_timers.insert(handle); + spawn(proc() { + let mut tm = tm; + let mut timeout_port = tm.oneshot(timeout); + let mut cancel_port = cancel_port; + + let select = Select::new(); + let timeout_handle = select.add(&mut timeout_port); + let _cancel_handle = select.add(&mut cancel_port); + let id = select.wait(); + if id == timeout_handle.id { + chan.send(TimerMessage_Fire(~TimerData { + handle: handle, + funval: callback, + args: ~[], + })); + } + }); + self.active_timers.insert(TimerHandle { handle: handle, cancel_chan: Some(cancel_chan) }); handle } pub fn ClearTimeout(&mut self, handle: i32) { - self.active_timers.remove(&handle); + // FIXME(#1477): active_timers should be a HashMap and this should + // cancel the removed timer. + self.active_timers.remove(&TimerHandle { handle: handle, cancel_chan: None }); } pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) { @@ -199,7 +234,6 @@ impl Window { self.page.join_layout(); } - #[fixed_stack_segment] pub fn new(cx: *JSContext, page: @mut Page, script_chan: ScriptChan, @@ -212,9 +246,9 @@ impl Window { script_chan: script_chan.clone(), compositor: compositor, timer_chan: { - let (timer_port, timer_chan) = comm::stream::<TimerControlMsg>(); + let (timer_port, timer_chan): (Port<TimerControlMsg>, SharedChan<TimerControlMsg>) = SharedChan::new(); let id = page.id.clone(); - do spawn_with(script_chan) |script_chan| { + spawn(proc() { loop { match timer_port.recv() { TimerMessage_Close => break, @@ -222,8 +256,8 @@ impl Window { TimerMessage_TriggerExit => script_chan.send(ExitWindowMsg(id)), } } - } - SharedChan::new(timer_chan) + }); + timer_chan }, location: None, navigator: None, @@ -236,13 +270,13 @@ impl Window { unsafe { let fn_names = ["window","self"]; for str in fn_names.iter() { - do (*str).to_c_str().with_ref |name| { + (*str).to_c_str().with_ref(|name| { JS_DefineProperty(cx, global, name, RUST_OBJECT_TO_JSVAL(global), - Some(GetJSClassHookStubPointer(PROPERTY_STUB) as JSPropertyOp), - Some(GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as JSStrictPropertyOp), + Some(cast::transmute(GetJSClassHookStubPointer(PROPERTY_STUB))), + Some(cast::transmute(GetJSClassHookStubPointer(STRICT_PROPERTY_STUB))), JSPROP_ENUMERATE); - } + }) } diff --git a/src/components/script/html/cssparse.rs b/src/components/script/html/cssparse.rs index 0ba1aadbe03..5f5ba17653b 100644 --- a/src/components/script/html/cssparse.rs +++ b/src/components/script/html/cssparse.rs @@ -4,10 +4,7 @@ /// Some little helpers for hooking up the HTML parser with the CSS parser. -use std::cell::Cell; -use std::comm; use std::comm::Port; -use std::task; use encoding::EncodingRef; use encoding::all::UTF_8; use style::Stylesheet; @@ -23,25 +20,22 @@ pub enum StylesheetProvenance { pub fn spawn_css_parser(provenance: StylesheetProvenance, resource_task: ResourceTask) -> Port<Stylesheet> { - let (result_port, result_chan) = comm::stream(); + let (result_port, result_chan) = Chan::new(); // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding let environment_encoding = UTF_8 as EncodingRef; - let provenance_cell = Cell::new(provenance); - do task::spawn { + spawn(proc() { // TODO: CSS parsing should take a base URL. - let _url = do provenance_cell.with_ref |p| { - match *p { - UrlProvenance(ref the_url) => (*the_url).clone(), - InlineProvenance(ref the_url, _) => (*the_url).clone() - } + let _url = match provenance { + UrlProvenance(ref the_url) => (*the_url).clone(), + InlineProvenance(ref the_url, _) => (*the_url).clone() }; - let sheet = match provenance_cell.take() { + let sheet = match provenance { UrlProvenance(url) => { debug!("cssparse: loading style sheet at {:s}", url.to_str()); - let (input_port, input_chan) = comm::stream(); + let (input_port, input_chan) = Chan::new(); resource_task.send(Load(url, input_chan)); let LoadResponse { metadata: metadata, progress_port: progress_port } = input_port.recv(); @@ -56,7 +50,7 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance, } }; result_chan.send(sheet); - } + }); return result_port; } @@ -69,7 +63,7 @@ impl Iterator<~[u8]> for ProgressMsgPortIterator { fn next(&mut self) -> Option<~[u8]> { match self.progress_port.recv() { Payload(data) => Some(data), - Done(*) => None + Done(..) => None } } } diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 94eac3b1bef..c59ef9ab376 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -22,9 +22,8 @@ use servo_net::image_cache_task::ImageCacheTask; use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource}; use servo_util::url::make_url; use std::cast; -use std::cell::Cell; +use std::cell::RefCell; use std::comm::{Port, SharedChan}; -use std::comm; use std::from_str::FromStr; use std::str::eq_slice; use std::str; @@ -107,11 +106,11 @@ fn css_link_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, let mut result_vec = ~[]; loop { - match from_parent.recv() { - CSSTaskNewFile(provenance) => { + match from_parent.recv_opt() { + Some(CSSTaskNewFile(provenance)) => { result_vec.push(spawn_css_parser(provenance, resource_task.clone())); } - CSSTaskExit => { + Some(CSSTaskExit) | None => { break; } } @@ -120,7 +119,7 @@ fn css_link_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, // Send the sheets back in order // FIXME: Shouldn't wait until after we've recieved CSSTaskExit to start sending these for port in result_vec.iter() { - to_parent.send(HtmlDiscoveredStyle(port.recv())); + to_parent.try_send(HtmlDiscoveredStyle(port.recv())); } } @@ -130,30 +129,30 @@ fn js_script_listener(to_parent: SharedChan<HtmlDiscoveryMessage>, let mut result_vec = ~[]; loop { - match from_parent.recv() { - JSTaskNewFile(url) => { + match from_parent.recv_opt() { + Some(JSTaskNewFile(url)) => { match load_whole_resource(&resource_task, url.clone()) { Err(_) => { error!("error loading script {:s}", url.to_str()); } Ok((metadata, bytes)) => { result_vec.push(JSFile { - data: str::from_utf8(bytes), + data: str::from_utf8(bytes).to_owned(), url: metadata.final_url, }); } } } - JSTaskNewInlineScript(data, url) => { + Some(JSTaskNewInlineScript(data, url)) => { result_vec.push(JSFile { data: data, url: url }); } - JSTaskExit => { + Some(JSTaskExit) | None => { break; } } } - to_parent.send(HtmlDiscoveredScript(result_vec)); + to_parent.try_send(HtmlDiscoveredScript(result_vec)); } // Silly macros to handle constructing DOM nodes. This produces bad code and should be optimized @@ -253,30 +252,23 @@ pub fn parse_html(cx: *JSContext, // Spawn a CSS parser to receive links to CSS style sheets. let resource_task2 = resource_task.clone(); - let (discovery_port, discovery_chan) = comm::stream(); - let discovery_chan = SharedChan::new(discovery_chan); - - let stylesheet_chan = Cell::new(discovery_chan.clone()); - let (css_msg_port, css_msg_chan) = comm::stream(); - let css_msg_port = Cell::new(css_msg_port); - do spawn { - css_link_listener(stylesheet_chan.take(), css_msg_port.take(), resource_task2.clone()); - } - - let css_chan = SharedChan::new(css_msg_chan); + let (discovery_port, discovery_chan) = SharedChan::new(); + let stylesheet_chan = discovery_chan.clone(); + let (css_msg_port, css_chan) = SharedChan::new(); + spawn(proc() { + css_link_listener(stylesheet_chan, css_msg_port, resource_task2.clone()); + }); // Spawn a JS parser to receive JavaScript. let resource_task2 = resource_task.clone(); - let js_result_chan = Cell::new(discovery_chan.clone()); - let (js_msg_port, js_msg_chan) = comm::stream(); - let js_msg_port = Cell::new(js_msg_port); - do spawn { - js_script_listener(js_result_chan.take(), js_msg_port.take(), resource_task2.clone()); - } - let js_chan = SharedChan::new(js_msg_chan); + let js_result_chan = discovery_chan.clone(); + let (js_msg_port, js_chan) = SharedChan::new(); + spawn(proc() { + js_script_listener(js_result_chan, js_msg_port, resource_task2.clone()); + }); // Wait for the LoadResponse so that the parser knows the final URL. - let (input_port, input_chan) = comm::stream(); + let (input_port, input_chan) = Chan::new(); resource_task.send(Load(url.clone(), input_chan)); let load_response = input_port.recv(); @@ -305,9 +297,10 @@ pub fn parse_html(cx: *JSContext, parser.enable_styling(true); let (css_chan2, css_chan3, js_chan2) = (css_chan.clone(), css_chan.clone(), js_chan.clone()); - let next_subpage_id = Cell::new(next_subpage_id); - - parser.set_tree_handler(~hubbub::TreeHandler { + + let next_subpage_id = RefCell::new(next_subpage_id); + + let tree_handler = hubbub::TreeHandler { create_comment: |data: ~str| { debug!("create comment"); let comment = Comment::new(data, document); @@ -333,19 +326,19 @@ pub fn parse_html(cx: *JSContext, let node = build_element_from_tag(tag.name.clone(), document); debug!("-- attach attrs"); - do node.as_mut_element |element| { + node.as_mut_element(|element| { for attr in tag.attributes.iter() { element.set_attr(node, attr.name.clone(), attr.value.clone()); } - } + }); // Spawn additional parsing, network loads, etc. from tag and attrs match node.type_id() { // Handle CSS style sheets from <link> elements ElementNodeTypeId(HTMLLinkElementTypeId) => { - do node.with_imm_element |element| { + node.with_imm_element(|element| { match (element.get_attr(Null, "rel"), element.get_attr(Null, "href")) { (Some(rel), Some(href)) => { if "stylesheet" == rel { @@ -356,13 +349,12 @@ pub fn parse_html(cx: *JSContext, } _ => {} } - } + }); } ElementNodeTypeId(HTMLIframeElementTypeId) => { - let iframe_chan = Cell::new(discovery_chan.clone()); - do node.with_mut_iframe_element |iframe_element| { - let iframe_chan = iframe_chan.take(); + let iframe_chan = discovery_chan.clone(); + node.with_mut_iframe_element(|iframe_element| { let sandboxed = iframe_element.is_sandboxed(); let elem = &mut iframe_element.htmlelement.element; let src_opt = elem.get_attr(Null, "src").map(|x| x.to_str()); @@ -371,8 +363,8 @@ pub fn parse_html(cx: *JSContext, iframe_element.frame = Some(iframe_url.clone()); // Subpage Id - let subpage_id = next_subpage_id.take(); - next_subpage_id.put_back(SubpageId(*subpage_id + 1)); + let subpage_id = next_subpage_id.get(); + next_subpage_id.set(SubpageId(*subpage_id + 1)); // Pipeline Id let pipeline_id = { @@ -388,15 +380,15 @@ pub fn parse_html(cx: *JSContext, subpage_id, sandboxed))); } - } + }); } //FIXME: This should be taken care of by set_attr, but we don't have // access to a window so HTMLImageElement::AfterSetAttr bails. ElementNodeTypeId(HTMLImageElementTypeId) => { - do node.with_mut_image_element |image_element| { + node.with_mut_image_element(|image_element| { image_element.update_image(image_cache_task.clone(), Some(url2.clone())); - } + }); } _ => {} @@ -460,7 +452,7 @@ pub fn parse_html(cx: *JSContext, complete_script: |script| { unsafe { let scriptnode: AbstractNode = NodeWrapping::from_hubbub_node(script); - do scriptnode.with_imm_element |script| { + scriptnode.with_imm_element(|script| { match script.get_attr(Null, "src") { Some(src) => { debug!("found script: {:s}", src); @@ -472,16 +464,16 @@ pub fn parse_html(cx: *JSContext, debug!("iterating over children {:?}", scriptnode.first_child()); for child in scriptnode.children() { debug!("child = {:?}", child); - do child.with_imm_text() |text| { + child.with_imm_text(|text| { data.push(text.element.data.to_str()); // FIXME: Bad copy. - } + }); } debug!("script data = {:?}", data); js_chan2.send(JSTaskNewInlineScript(data.concat(), url3.clone())); } } - } + }); } debug!("complete script"); }, @@ -490,23 +482,22 @@ pub fn parse_html(cx: *JSContext, unsafe { let style: AbstractNode = NodeWrapping::from_hubbub_node(style); let url = FromStr::from_str("http://example.com/"); // FIXME - let url_cell = Cell::new(url); - let mut data = ~[]; debug!("iterating over children {:?}", style.first_child()); for child in style.children() { debug!("child = {:?}", child); - do child.with_imm_text() |text| { + child.with_imm_text(|text| { data.push(text.element.data.to_str()); // FIXME: Bad copy. - } + }); } debug!("style data = {:?}", data); - let provenance = InlineProvenance(url_cell.take().unwrap(), data.concat()); + let provenance = InlineProvenance(url.unwrap(), data.concat()); css_chan3.send(CSSTaskNewFile(provenance)); } }, - }); + }; + parser.set_tree_handler(&tree_handler); debug!("set tree handler"); debug!("loaded page"); @@ -516,10 +507,10 @@ pub fn parse_html(cx: *JSContext, debug!("received data"); parser.parse_chunk(data); } - Done(Err(*)) => { + Done(Err(..)) => { fail!("Failed to load page URL {:s}", url.to_str()); } - Done(*) => { + Done(..) => { break; } } diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs index c0b35ef6a3f..613e61a3429 100644 --- a/src/components/script/layout_interface.rs +++ b/src/components/script/layout_interface.rs @@ -122,9 +122,11 @@ pub struct Reflow { /// Encapsulates a channel to the layout task. #[deriving(Clone)] pub struct LayoutChan(SharedChan<Msg>); + impl LayoutChan { - pub fn new(chan: Chan<Msg>) -> LayoutChan { - LayoutChan(SharedChan::new(chan)) + pub fn new() -> (Port<Msg>, LayoutChan) { + let (port, chan) = SharedChan::new(); + (port, LayoutChan(chan)) } } diff --git a/src/components/script/script.rc b/src/components/script/script.rc index 1715ff8de8f..0e25bea39e2 100644 --- a/src/components/script/script.rc +++ b/src/components/script/script.rc @@ -2,14 +2,11 @@ * 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 = "script", - vers = "0.1", - uuid = "536a45e2-b605-4ee0-b54c-466810f1ffc1", - url = "http://servo.org/")]; +#[crate_id = "github.com/mozilla/servo#script:0.1"]; +#[crate_type = "lib"]; #[comment = "The Servo Parallel Browser Project"]; #[license = "MPL"]; -#[crate_type = "lib"]; #[feature(globs, macro_rules, struct_variant, managed_boxes)]; @@ -17,11 +14,12 @@ extern mod geom; extern mod hubbub; extern mod encoding; extern mod js; -extern mod servo_net (name = "net"); -extern mod servo_util (name = "util"); +extern mod servo_net = "net"; +extern mod servo_util = "util"; extern mod style; -extern mod servo_msg (name = "msg"); +extern mod servo_msg = "msg"; extern mod extra; +extern mod native; // Macros mod macros; diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 1938ef92ff3..4b70c13f0cc 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -14,15 +14,15 @@ use dom::event::Event; use dom::eventtarget::AbstractEventTarget; use dom::htmldocument::HTMLDocument; use dom::namespace::Null; -use dom::node::{AbstractNode, LayoutDataRef}; -use dom::window::{TimerData, Window}; +use dom::node::AbstractNode; +use dom::window::{TimerData, TimerHandle, Window}; use html::hubbub_html_parser::HtmlParserResult; use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript}; use html::hubbub_html_parser; use layout_interface::{AddStylesheetMsg, DocumentDamage}; use layout_interface::{ContentBoxQuery, ContentBoxResponse}; use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery}; -use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg, ReapLayoutDataMsg}; +use layout_interface::{LayoutChan, MatchSelectorsDocumentDamage, QueryMsg}; use layout_interface::{Reflow, ReflowDocumentDamage, ReflowForDisplay, ReflowGoal, ReflowMsg}; use layout_interface::ContentChangedDocumentDamage; use layout_interface; @@ -46,12 +46,9 @@ use servo_net::image_cache_task::ImageCacheTask; use servo_net::resource_task::ResourceTask; use servo_util::geometry::to_frac_px; use servo_util::url::make_url; -use std::cell::Cell; use std::comm::{Port, SharedChan}; -use std::comm; use std::ptr; use std::str::eq_slice; -use std::task::{spawn_sched, SingleThreaded}; use std::util::replace; /// Messages used to control the script task. @@ -90,8 +87,9 @@ pub struct ScriptChan(SharedChan<ScriptMsg>); impl ScriptChan { /// Creates a new script chan. - pub fn new(chan: Chan<ScriptMsg>) -> ScriptChan { - ScriptChan(SharedChan::new(chan)) + pub fn new() -> (Port<ScriptMsg>, ScriptChan) { + let (port, chan) = SharedChan::new(); + (port, ScriptChan(chan)) } } @@ -140,8 +138,8 @@ pub struct PageTree { inner: ~[PageTree], } -pub struct PageTreeIterator<'self> { - priv stack: ~[&'self mut PageTree], +pub struct PageTreeIterator<'a> { + priv stack: ~[&'a mut PageTree], } impl PageTree { @@ -203,7 +201,7 @@ impl PageTree { } } -impl<'self> Iterator<@mut Page> for PageTreeIterator<'self> { +impl<'a> Iterator<@mut Page> for PageTreeIterator<'a> { fn next(&mut self) -> Option<@mut Page> { if !self.stack.is_empty() { let next = self.stack.pop(); @@ -254,12 +252,14 @@ impl Page { let join_port = replace(&mut self.layout_join_port, None); match join_port { Some(ref join_port) => { - if !join_port.peek() { - info!("script: waiting on layout"); + match join_port.try_recv() { + None => { + info!("script: waiting on layout"); + join_port.recv(); + } + Some(_) => {} } - join_port.recv(); - debug!("script: layout joined") } None => fail!(~"reader forked but no join port?"), @@ -307,7 +307,7 @@ impl Page { compositor.set_ready_state(PerformingLayout); // Layout will let us know when it's done. - let (join_port, join_chan) = comm::stream(); + let (join_port, join_chan) = Chan::new(); self.layout_join_port = Some(join_port); self.last_reflow_id += 1; @@ -359,11 +359,6 @@ impl Page { js_context: js_context, }); } - - /// Sends the given layout data back to the layout task to be destroyed. - pub unsafe fn reap_dead_layout_data(&self, layout_data: LayoutDataRef) { - self.layout_chan.send(ReapLayoutDataMsg(layout_data)) - } } /// Information for one frame in the browsing context. @@ -412,7 +407,6 @@ pub struct ScriptTask { } /// Returns the relevant page from the associated JS Context. -#[fixed_stack_segment] pub fn page_from_context(js_context: *JSContext) -> *mut Page { unsafe { JS_GetContextPrivate(js_context) as *mut Page @@ -468,24 +462,7 @@ impl ScriptTask { resource_task: ResourceTask, image_cache_task: ImageCacheTask, window_size: Size2D<uint>) { - let parms = Cell::new((compositor, - layout_chan, - port, - chan, - constellation_chan, - resource_task, - image_cache_task)); - // Since SpiderMonkey is blocking it needs to run in its own thread. - // If we don't do this then we'll just end up with a bunch of SpiderMonkeys - // starving all the other tasks. - do spawn_sched(SingleThreaded) { - let (compositor, - layout_chan, - port, - chan, - constellation_chan, - resource_task, - image_cache_task) = parms.take(); + spawn(proc() { let script_task = ScriptTask::new(id, @compositor as @ScriptListener, layout_chan, @@ -496,7 +473,7 @@ impl ScriptTask { image_cache_task, window_size); script_task.start(); - } + }); } /// Handle incoming control messages. @@ -520,12 +497,13 @@ impl ScriptTask { // Store new resizes, and gather all other events. let mut sequential = ~[]; + + // Receive at least one message so we don't spinloop. + let mut event = self.port.recv(); + loop { - // Receive at least one message so we don't spinloop. - let event = self.port.recv(); match event { ResizeMsg(id, size) => { - debug!("script got resize message"); let page = self.page_tree.find(id).expect("resize sent to nonexistent pipeline").page; page.resize_event = Some(size); } @@ -534,9 +512,9 @@ impl ScriptTask { } } - // Break if there are no more messages. - if !self.port.peek() { - break; + match self.port.try_recv() { + None => break, + Some(ev) => event = ev, } } @@ -556,7 +534,7 @@ impl ScriptTask { self.handle_exit_window_msg(id); return false }, - ResizeMsg(*) => fail!("should have handled ResizeMsg already"), + ResizeMsg(..) => fail!("should have handled ResizeMsg already"), } } @@ -579,14 +557,14 @@ impl ScriptTask { } /// Handles a timer that fired. - #[fixed_stack_segment] fn handle_fire_timer_msg(&mut self, id: PipelineId, timer_data: ~TimerData) { let page = self.page_tree.find(id).expect("ScriptTask: received fire timer msg for a pipeline ID not associated with this script task. This is a bug.").page; let window = page.frame.expect("ScriptTask: Expect a timeout to have a document").window; - if !window.active_timers.contains(&timer_data.handle) { + if !window.active_timers.contains(&TimerHandle { handle: timer_data.handle, cancel_chan: None }) { return; } + window.active_timers.remove(&TimerHandle { handle: timer_data.handle, cancel_chan: None }); unsafe { let this_value = if timer_data.args.len() > 0 { RUST_JSVAL_TO_OBJECT(timer_data.args[0]) @@ -711,7 +689,6 @@ impl ScriptTask { // // Note: We can parse the next document in parallel with any previous documents. let document = HTMLDocument::new(window); - let html_parsing_result = hubbub_html_parser::parse_html(cx.ptr, document, url.clone(), @@ -736,7 +713,7 @@ impl ScriptTask { let mut js_scripts = None; loop { - match discovery_port.try_recv() { + match discovery_port.recv_opt() { Some(HtmlDiscoveredScript(scripts)) => { assert!(js_scripts.is_none()); js_scripts = Some(scripts); @@ -805,20 +782,20 @@ impl ScriptTask { None => { let doc_node = AbstractNode::from_document(document); let mut anchors = doc_node.traverse_preorder().filter(|node| node.is_anchor_element()); - do anchors.find |node| { - do node.with_imm_element |elem| { + anchors.find(|node| { + node.with_imm_element(|elem| { match elem.get_attr(Null, "name") { Some(name) => eq_slice(name, fragid), None => false } - } - } + }) + }) } } } fn scroll_fragment_point(&self, pipeline_id: PipelineId, page: &mut Page, node: AbstractNode) { - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); match page.query_layout(ContentBoxQuery(node, chan), port) { ContentBoxResponse(rect) => { let point = Point2D(to_frac_px(rect.origin.x).to_f32().unwrap(), @@ -870,7 +847,7 @@ impl ScriptTask { if root.is_none() { return; } - let (port, chan) = comm::stream(); + let (port, chan) = Chan::new(); match page.query_layout(HitTestQuery(root.unwrap(), point, chan), port) { Ok(node) => match node { HitTestResponse(node) => { @@ -886,11 +863,11 @@ impl ScriptTask { } } if node.is_element() { - do node.with_imm_element |element| { + node.with_imm_element(|element| { if "a" == element.tag_name { self.load_url_from_element(page, element) } - } + }) } } }, @@ -899,8 +876,8 @@ impl ScriptTask { } } } - MouseDownEvent(*) => {} - MouseUpEvent(*) => {} + MouseDownEvent(..) => {} + MouseUpEvent(..) => {} } } @@ -910,9 +887,9 @@ impl ScriptTask { for href in attr.iter() { debug!("ScriptTask: clicked on link to {:s}", *href); let click_frag = href.starts_with("#"); - let current_url = do page.url.as_ref().map |&(ref url, _)| { + let current_url = page.url.as_ref().map(|&(ref url, _)| { url.clone() - }; + }); debug!("ScriptTask: current url is {:?}", current_url); let url = make_url(href.to_owned(), current_url); @@ -933,29 +910,15 @@ fn shut_down_layout(page: @mut Page) { page.join_layout(); // Tell the layout task to begin shutting down. - let (response_port, response_chan) = comm::stream(); + let (response_port, response_chan) = Chan::new(); page.layout_chan.send(layout_interface::PrepareToExitMsg(response_chan)); response_port.recv(); - // Destroy all nodes. - // - // If there was a leak, the layout task will soon crash safely when it detects that local data - // is missing from its heap. - // - // FIXME(pcwalton): *But*, for now, because we use `@mut` boxes to hold onto Nodes, if this - // didn't destroy all the nodes there will be an *exploitable* security vulnerability as the - // nodes try to access the destroyed JS context. We need to change this so that the only actor - // who can judge a JS object dead (and thus run its drop glue) is the JS engine itself; thus it - // will be impossible (absent a serious flaw in the JS engine) for the JS context to be dead - // before nodes are. - unsafe { - let document_node = AbstractNode::from_document(page.frame.as_ref().unwrap().document); - for node in document_node.traverse_preorder() { - node.mut_node().reap_layout_data() - } - } + // Destroy all nodes. Setting frame and js_info to None will trigger our + // compartment to shutdown, run GC, etc. + page.frame = None; + page.js_info = None; // Destroy the layout task. If there were node leaks, layout will now crash safely. page.layout_chan.send(layout_interface::ExitNowMsg); } - diff --git a/src/components/style/common_types.rs b/src/components/style/common_types.rs index 4eace37554e..eac41697eb1 100644 --- a/src/components/style/common_types.rs +++ b/src/components/style/common_types.rs @@ -43,6 +43,7 @@ pub mod specified { _ => None } } + #[allow(dead_code)] pub fn parse(input: &ComponentValue) -> Option<Length> { Length::parse_internal(input, /* negative_ok = */ true) } @@ -87,6 +88,7 @@ pub mod specified { _ => None } } + #[allow(dead_code)] #[inline] pub fn parse(input: &ComponentValue) -> Option<LengthOrPercentage> { LengthOrPercentage::parse_internal(input, /* negative_ok = */ true) @@ -145,6 +147,7 @@ pub mod specified { _ => None } } + #[allow(dead_code)] #[inline] pub fn parse(input: &ComponentValue) -> Option<LengthOrPercentageOrNone> { LengthOrPercentageOrNone::parse_internal(input, /* negative_ok = */ true) diff --git a/src/components/style/errors.rs b/src/components/style/errors.rs index e43630bb1aa..fa97d5229c9 100644 --- a/src/components/style/errors.rs +++ b/src/components/style/errors.rs @@ -31,7 +31,7 @@ pub fn log_css_error(location: SourceLocation, message: &str) { } -pub fn with_errors_silenced<T>(f: &fn() -> T) -> T { +pub fn with_errors_silenced<T>(f: || -> T) -> T { local_data::set(silence_errors, ()); let result = f(); local_data::pop(silence_errors); diff --git a/src/components/style/media_queries.rs b/src/components/style/media_queries.rs index abccc41e7f5..06866736305 100644 --- a/src/components/style/media_queries.rs +++ b/src/components/style/media_queries.rs @@ -121,12 +121,12 @@ pub fn parse_media_query_list(input: &[ComponentValue]) -> MediaQueryList { impl MediaQueryList { pub fn evaluate(&self, device: &Device) -> bool { - do self.media_queries.iter().any |mq| { + self.media_queries.iter().any(|mq| { match mq.media_type { MediaType(media_type) => media_type == device.media_type, All => true, } // TODO: match Level 3 expressions - } + }) } } diff --git a/src/components/style/node.rs b/src/components/style/node.rs index fef83d75810..546ef329795 100644 --- a/src/components/style/node.rs +++ b/src/components/style/node.rs @@ -14,7 +14,7 @@ pub trait TNode<E:TElement> : Clone { fn is_element(&self) -> bool; /// FIXME(pcwalton): This should not use the `with` pattern. - fn with_element<R>(&self, f: &fn(&E) -> R) -> R; + fn with_element<'a, R>(&self, f: |&E| -> R) -> R; } pub trait TElement { diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index 1bf23662020..4c6f2511658 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -74,8 +74,8 @@ pub mod longhands { pub fn parse_declared(input: &[ComponentValue]) -> Option<DeclaredValue<SpecifiedValue>> { match CSSWideKeyword::parse(input) { - Some(Left(keyword)) => Some(CSSWideKeyword(keyword)), - Some(Right(Unset)) => Some(CSSWideKeyword(${ + Some(Some(keyword)) => Some(CSSWideKeyword(keyword)), + Some(None) => Some(CSSWideKeyword(${ "Inherit" if inherited else "Initial"})), None => parse_specified(input), } @@ -118,14 +118,14 @@ pub mod longhands { ${to_rust_ident(values.split()[0])} } pub fn from_component_value(v: &ComponentValue) -> Option<SpecifiedValue> { - do get_ident_lower(v).and_then |keyword| { + get_ident_lower(v).and_then(|keyword| { match keyword.as_slice() { % for value in values.split(): "${value}" => Some(${to_rust_ident(value)}), % endfor _ => None, } - } + }) } </%self:single_component_value> </%def> @@ -648,12 +648,12 @@ pub mod longhands { /// <length> | <percentage> /// TODO: support <absolute-size> and <relative-size> pub fn from_component_value(input: &ComponentValue) -> Option<SpecifiedValue> { - do specified::LengthOrPercentage::parse_non_negative(input).map |value| { + specified::LengthOrPercentage::parse_non_negative(input).map(|value| { match value { specified::LP_Length(value) => value, specified::LP_Percentage(value) => specified::Em(value), } - } + }) } </%self:single_component_value> @@ -767,9 +767,9 @@ pub mod shorthands { // TODO: other background-* properties <%self:shorthand name="background" sub_properties="background-color"> - do one_component_value(input).and_then(specified::CSSColor::parse).map |color| { + one_component_value(input).and_then(specified::CSSColor::parse).map(|color| { Longhands { background_color: Some(color) } - } + }) </%self:shorthand> ${four_sides_shorthand("margin", "margin-%s", "margin_top::from_component_value")} @@ -818,13 +818,13 @@ pub mod shorthands { 'border-%s-%s' % (side, prop) for prop in ['color', 'style', 'width'] )}"> - do parse_border(input).map |(color, style, width)| { + parse_border(input).map(|(color, style, width)| { Longhands { % for prop in ["color", "style", "width"]: ${"border_%s_%s: %s," % (side, prop, prop)} % endfor } - } + }) </%self:shorthand> % endfor @@ -833,7 +833,7 @@ pub mod shorthands { for side in ['top', 'right', 'bottom', 'left'] for prop in ['color', 'style', 'width'] )}"> - do parse_border(input).map |(color, style, width)| { + parse_border(input).map(|(color, style, width)| { Longhands { % for side in ["top", "right", "bottom", "left"]: % for prop in ["color", "style", "width"]: @@ -841,7 +841,7 @@ pub mod shorthands { % endfor % endfor } - } + }) </%self:shorthand> <%self:shorthand name="font" sub_properties="font-style font-variant font-weight @@ -966,18 +966,16 @@ pub enum CSSWideKeyword { Inherit, } -struct Unset; - impl CSSWideKeyword { - pub fn parse(input: &[ComponentValue]) -> Option<Either<CSSWideKeyword, Unset>> { - do one_component_value(input).and_then(get_ident_lower).and_then |keyword| { + pub fn parse(input: &[ComponentValue]) -> Option<Option<CSSWideKeyword>> { + one_component_value(input).and_then(get_ident_lower).and_then(|keyword| { match keyword.as_slice() { - "initial" => Some(Left(Initial)), - "inherit" => Some(Left(Inherit)), - "unset" => Some(Right(Unset)), + "initial" => Some(Some(Initial)), + "inherit" => Some(Some(Inherit)), + "unset" => Some(None), _ => None } - } + }) } } @@ -1018,14 +1016,14 @@ impl PropertyDeclaration { % endfor % for shorthand in SHORTHANDS: "${shorthand.name}" => match CSSWideKeyword::parse(value) { - Some(Left(keyword)) => { + Some(Some(keyword)) => { % for sub_property in shorthand.sub_properties: result_list.push(${sub_property.ident}_declaration( CSSWideKeyword(keyword) )); % endfor }, - Some(Right(Unset)) => { + Some(None) => { % for sub_property in shorthand.sub_properties: result_list.push(${sub_property.ident}_declaration( CSSWideKeyword(${ diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index 3d48fd66a57..5d19530fa00 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use extra::arc::Arc; -use extra::sort::tim_sort; use std::ascii::StrAsciiExt; use std::hashmap::HashMap; use std::str; @@ -86,11 +85,9 @@ impl SelectorMap { match element.get_attr(None, "class") { Some(ref class_attr) => { - for class in class_attr.split_iter(SELECTOR_WHITESPACE) { - SelectorMap::get_matching_rules_from_hash(node, - &self.class_hash, - class, - matching_rules_list) + for class in class_attr.split(SELECTOR_WHITESPACE) { + SelectorMap::get_matching_rules_from_hash( + node, &self.class_hash, class, matching_rules_list); } } None => {} @@ -108,7 +105,13 @@ impl SelectorMap { }); // Sort only the rules we just added. - tim_sort(matching_rules_list.mut_slice_from(init_len)); + matching_rules_list.mut_slice_from(init_len).sort_by(|a, b| { + if a < b { + Less + } else { + Greater + } + }); } fn get_matching_rules_from_hash<E:TElement, @@ -292,11 +295,11 @@ impl Stylist { ); let device = &Device { media_type: Screen }; // TODO, use Print when printing - do iter_style_rules(stylesheet.rules.as_slice(), device) |style_rule| { + iter_style_rules(stylesheet.rules.as_slice(), device, |style_rule| { append!(normal); append!(important); self.rules_source_order += 1; - } + }); } /// Returns the applicable CSS declarations for the given element. This corresponds to @@ -344,7 +347,7 @@ impl Stylist { let mut declaration_iter = matching_rules_list.move_iter().map(|rule| { let Rule { declarations, - _ + .. } = rule; declarations }); @@ -436,9 +439,9 @@ impl Ord for Rule { fn matches_compound_selector<E:TElement,N:TNode<E>>(selector: &CompoundSelector, element: &N) -> bool { - if !do selector.simple_selectors.iter().all |simple_selector| { + if !selector.simple_selectors.iter().all(|simple_selector| { matches_simple_selector(simple_selector, element) - } { + }) { return false } match selector.next { @@ -479,77 +482,77 @@ fn matches_simple_selector<E:TElement,N:TNode<E>>(selector: &SimpleSelector, ele // TODO: case-sensitivity depends on the document type // TODO: intern element names LocalNameSelector(ref name) => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { element.get_local_name().eq_ignore_ascii_case(name.as_slice()) - } + }) } NamespaceSelector(ref url) => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { element.get_namespace_url() == url.as_slice() - } + }) } // TODO: case-sensitivity depends on the document type and quirks mode // TODO: cache and intern IDs on elements. IDSelector(ref id) => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { match element.get_attr(None, "id") { Some(attr) => str::eq_slice(attr, *id), None => false } - } + }) } // TODO: cache and intern classe names on elements. ClassSelector(ref class) => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { match element.get_attr(None, "class") { None => false, // TODO: case-sensitivity depends on the document type and quirks mode Some(ref class_attr) - => class_attr.split_iter(SELECTOR_WHITESPACE).any(|c| c == class.as_slice()), + => class_attr.split(SELECTOR_WHITESPACE).any(|c| c == class.as_slice()), } - } + }) } AttrExists(ref attr) => match_attribute(attr, element, |_| true), AttrEqual(ref attr, ref value) => match_attribute(attr, element, |v| v == value.as_slice()), - AttrIncludes(ref attr, ref value) => do match_attribute(attr, element) |attr_value| { - attr_value.split_iter(SELECTOR_WHITESPACE).any(|v| v == value.as_slice()) - }, + AttrIncludes(ref attr, ref value) => match_attribute(attr, element, |attr_value| { + attr_value.split(SELECTOR_WHITESPACE).any(|v| v == value.as_slice()) + }), AttrDashMatch(ref attr, ref value, ref dashing_value) - => do match_attribute(attr, element) |attr_value| { + => match_attribute(attr, element, |attr_value| { attr_value == value.as_slice() || attr_value.starts_with(dashing_value.as_slice()) - }, - AttrPrefixMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| { + }), + AttrPrefixMatch(ref attr, ref value) => match_attribute(attr, element, |attr_value| { attr_value.starts_with(value.as_slice()) - }, - AttrSubstringMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| { + }), + AttrSubstringMatch(ref attr, ref value) => match_attribute(attr, element, |attr_value| { attr_value.contains(value.as_slice()) - }, - AttrSuffixMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| { + }), + AttrSuffixMatch(ref attr, ref value) => match_attribute(attr, element, |attr_value| { attr_value.ends_with(value.as_slice()) - }, + }), AnyLink => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { element.get_link().is_some() - } + }) } Link => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { match element.get_link() { Some(url) => !url_is_visited(url), None => false, } - } + }) } Visited => { - do element.with_element |element: &E| { + element.with_element(|element: &E| { match element.get_link() { Some(url) => url_is_visited(url), None => false, } - } + }) } FirstChild => matches_first_child(element), @@ -583,7 +586,8 @@ fn url_is_visited(_url: &str) -> bool { } #[inline] -fn matches_generic_nth_child<E:TElement, +fn matches_generic_nth_child<'a, + E:TElement, N:TNode<E>>( element: &N, a: i32, @@ -601,15 +605,6 @@ fn matches_generic_nth_child<E:TElement, None => return false }; - let mut element_local_name = ""; - let mut element_namespace = ""; - if is_of_type { - do element.with_element |element: &E| { - element_local_name = element.get_local_name(); - element_namespace = element.get_namespace_url(); - } - } - let mut index = 1; loop { if is_from_end { @@ -626,12 +621,14 @@ fn matches_generic_nth_child<E:TElement, if node.is_element() { if is_of_type { - do node.with_element |node: &E| { - if element_local_name == node.get_local_name() && - element_namespace == node.get_namespace_url() { - index += 1; - } - } + element.with_element(|element: &E| { + node.with_element(|node: &E| { + if element.get_local_name() == node.get_local_name() && + element.get_namespace_url() == node.get_namespace_url() { + index += 1; + } + }) + }) } else { index += 1; } @@ -704,18 +701,17 @@ fn match_attribute<E:TElement, N:TNode<E>>( attr: &AttrSelector, element: &N, - f: &fn(&str) -> bool) + f: |&str| -> bool) -> bool { - do element.with_element |element: &E| { + element.with_element(|element: &E| { // FIXME: avoid .clone() here? See #1367 match element.get_attr(attr.namespace.clone(), attr.name) { None => false, Some(value) => f(value) } - } + }) } - #[cfg(test)] mod tests { use extra::arc::Arc; diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs index 2e401e1a407..860c4a6d6bc 100644 --- a/src/components/style/selectors.rs +++ b/src/components/style/selectors.rs @@ -27,9 +27,6 @@ pub struct Selector { specificity: u32, } -pub static STYLE_ATTRIBUTE_SPECIFICITY: u32 = 1 << 31; - - #[deriving(Eq, Clone)] pub enum PseudoElement { Before, @@ -203,19 +200,19 @@ fn compute_specificity(mut selector: &CompoundSelector, specificity: &mut Specificity) { for simple_selector in simple_selectors.iter() { match simple_selector { - &LocalNameSelector(*) => specificity.element_selectors += 1, - &IDSelector(*) => specificity.id_selectors += 1, - &ClassSelector(*) - | &AttrExists(*) | &AttrEqual(*) | &AttrIncludes(*) | &AttrDashMatch(*) - | &AttrPrefixMatch(*) | &AttrSubstringMatch(*) | &AttrSuffixMatch(*) + &LocalNameSelector(..) => specificity.element_selectors += 1, + &IDSelector(..) => specificity.id_selectors += 1, + &ClassSelector(..) + | &AttrExists(..) | &AttrEqual(..) | &AttrIncludes(..) | &AttrDashMatch(..) + | &AttrPrefixMatch(..) | &AttrSubstringMatch(..) | &AttrSuffixMatch(..) | &AnyLink | &Link | &Visited | &FirstChild | &LastChild | &OnlyChild | &Root // | &Empty | &Lang(*) - | &NthChild(*) | &NthLastChild(*) - | &NthOfType(*) | &NthLastOfType(*) + | &NthChild(..) | &NthLastChild(..) + | &NthOfType(..) | &NthLastOfType(..) | &FirstOfType | &LastOfType | &OnlyOfType => specificity.class_like_selectors += 1, - &NamespaceSelector(*) => (), + &NamespaceSelector(..) => (), &Negation(ref negated) => simple_selectors_specificity(negated.as_slice(), specificity), } diff --git a/src/components/style/style.rc b/src/components/style/style.rc index d41e98682fc..a8e39526fa1 100644 --- a/src/components/style/style.rc +++ b/src/components/style/style.rc @@ -2,21 +2,18 @@ * 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 = "style", - vers = "0.1", - uuid = "4a50ca00-3283-11e3-aa6e-0800200c9a66", - url = "http://servo.org/")]; +#[crate_id = "github.com/mozilla/servo#style:0.1"]; +#[crate_type = "lib"]; #[comment = "The Servo Parallel Browser Project"]; #[license = "MPL"]; -#[crate_type = "lib"]; #[feature(globs, macro_rules, managed_boxes)]; extern mod extra; extern mod cssparser; extern mod encoding; -extern mod servo_util (name = "util"); +extern mod servo_util = "util"; // Public API diff --git a/src/components/style/stylesheets.rs b/src/components/style/stylesheets.rs index 673974961c5..0b5b1406457 100644 --- a/src/components/style/stylesheets.rs +++ b/src/components/style/stylesheets.rs @@ -151,7 +151,7 @@ pub fn parse_nested_at_rule(lower_name: &str, rule: AtRule, pub fn iter_style_rules<'a>(rules: &[CSSRule], device: &media_queries::Device, - callback: &fn(&StyleRule)) { + callback: |&StyleRule|) { for rule in rules.iter() { match *rule { CSSStyleRule(ref rule) => callback(rule), diff --git a/src/components/util/cache.rs b/src/components/util/cache.rs index 02859014bbd..b8c89a3ac90 100644 --- a/src/components/util/cache.rs +++ b/src/components/util/cache.rs @@ -7,7 +7,7 @@ use std::hashmap::HashMap; pub trait Cache<K: Eq, V: Clone> { fn insert(&mut self, key: K, value: V); fn find(&mut self, key: &K) -> Option<V>; - fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V; + fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V; fn evict_all(&mut self); } @@ -33,7 +33,7 @@ impl<K: Clone + Eq, V: Clone> Cache<K,V> for MonoCache<K,V> { } } - fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V { + fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V { match self.find(key) { Some(value) => value, None => { @@ -87,7 +87,7 @@ impl<K: Clone + Eq + Hash, V: Clone> Cache<K,V> for HashCache<K,V> { } } - fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V { + fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V { self.entries.find_or_insert_with(key.clone(), blk).clone() } @@ -149,7 +149,7 @@ impl<K: Clone + Eq, V: Clone> Cache<K,V> for LRUCache<K,V> { } } - fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V { + fn find_or_create(&mut self, key: &K, blk: |&K| -> V) -> V { match self.entries.iter().position(|&(ref k, _)| *k == *key) { Some(pos) => self.touch(pos), None => { @@ -191,7 +191,7 @@ fn test_lru_cache() { assert!(cache.find(&4).is_some()); // (2, 4) (no change) // Test find_or_create. - do cache.find_or_create(&1) |_| { one }; // (4, 1) + cache.find_or_create(&1, |_| { one }); // (4, 1) assert!(cache.find(&1).is_some()); // (4, 1) (no change) assert!(cache.find(&2).is_none()); // (4, 1) (no change) diff --git a/src/components/util/debug.rs b/src/components/util/debug.rs index 5c9aa700d5b..029db75d129 100644 --- a/src/components/util/debug.rs +++ b/src/components/util/debug.rs @@ -2,8 +2,8 @@ * 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::rt::io; -use std::rt::io::Writer; +use std::io; +use std::io::Writer; use std::vec::raw::buf_as_slice; use std::cast::transmute; use std::mem::size_of; diff --git a/src/components/util/geometry.rs b/src/components/util/geometry.rs index 4b2cb0c2e43..71184e5eec1 100644 --- a/src/components/util/geometry.rs +++ b/src/components/util/geometry.rs @@ -124,10 +124,6 @@ impl ToPrimitive for Au { } } -pub fn box<T:Clone + Ord + Add<T,T> + Sub<T,T>>(x: T, y: T, w: T, h: T) -> Rect<T> { - Rect(Point2D(x, y), Size2D(w, h)) -} - impl Au { /// FIXME(pcwalton): Workaround for lack of cross crate inlining of newtype structs! #[inline] diff --git a/src/components/util/io.rs b/src/components/util/io.rs index 45009723774..b034682cf16 100644 --- a/src/components/util/io.rs +++ b/src/components/util/io.rs @@ -2,7 +2,7 @@ * 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::rt::io::{io_error, IoError}; +use std::io::{io_error, IoError}; /// Helper for catching an I/O error and wrapping it in a Result object. The /// return result will be the last I/O error that happened or the result of the @@ -10,7 +10,7 @@ use std::rt::io::{io_error, IoError}; /// /// FIXME: This is a copy of std::rt::io::result which doesn't exist yet in our /// version of Rust. We should switch after the next Rust upgrade. -pub fn result<T>(cb: &fn() -> T) -> Result<T, IoError> { +pub fn result<T>(cb: || -> T) -> Result<T, IoError> { let mut err = None; let ret = io_error::cond.trap(|e| err = Some(e)).inside(cb); match err { diff --git a/src/components/util/slot.rs b/src/components/util/slot.rs deleted file mode 100644 index 34c12f2a0f5..00000000000 --- a/src/components/util/slot.rs +++ /dev/null @@ -1,141 +0,0 @@ -/* 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/. */ - -//! An in-place, dynamically borrowable slot. Useful for "mutable fields". Assuming this works out -//! well, this type should be upstreamed to the Rust standard library. - -use std::cast; -use std::util; - -#[unsafe_no_drop_flag] -#[no_freeze] -pub struct Slot<T> { - // NB: Must be priv, or else someone could borrow it. - priv value: T, - priv immutable_borrow_count: u8, - priv mutably_borrowed: bool, -} - -impl<T:Clone> Clone for Slot<T> { - #[inline] - fn clone(&self) -> Slot<T> { - Slot { - value: self.value.clone(), - immutable_borrow_count: 0, - mutably_borrowed: false, - } - } -} - -#[unsafe_destructor] -impl<T> Drop for Slot<T> { - fn drop(&mut self) { - // Noncopyable. - } -} - -pub struct SlotRef<'self,T> { - ptr: &'self T, - priv immutable_borrow_count: *mut u8, -} - -#[unsafe_destructor] -impl<'self,T> Drop for SlotRef<'self,T> { - #[inline] - fn drop(&mut self) { - unsafe { - *self.immutable_borrow_count -= 1 - } - } -} - -pub struct MutSlotRef<'self,T> { - ptr: &'self mut T, - priv mutably_borrowed: *mut bool, -} - -#[unsafe_destructor] -impl<'self,T> Drop for MutSlotRef<'self,T> { - #[inline] - fn drop(&mut self) { - unsafe { - *self.mutably_borrowed = false - } - } -} - -impl<T> Slot<T> { - #[inline] - pub fn init(value: T) -> Slot<T> { - Slot { - value: value, - immutable_borrow_count: 0, - mutably_borrowed: false, - } - } - - /// Borrows the data immutably. This function is thread-safe, but *bad things will happen if - /// you try to mutate the data while one of these pointers is held*. - #[inline] - pub unsafe fn borrow_unchecked<'a>(&'a self) -> &'a T { - &self.value - } - - #[inline] - pub fn borrow<'a>(&'a self) -> SlotRef<'a,T> { - unsafe { - if self.immutable_borrow_count == 255 || self.mutably_borrowed { - self.fail() - } - let immutable_borrow_count = cast::transmute_mut(&self.immutable_borrow_count); - *immutable_borrow_count += 1; - SlotRef { - ptr: &self.value, - immutable_borrow_count: immutable_borrow_count, - } - } - } - - #[inline] - pub fn mutate<'a>(&'a self) -> MutSlotRef<'a,T> { - unsafe { - if self.immutable_borrow_count > 0 || self.mutably_borrowed { - self.fail() - } - let mutably_borrowed = cast::transmute_mut(&self.mutably_borrowed); - *mutably_borrowed = true; - MutSlotRef { - ptr: cast::transmute_mut(&self.value), - mutably_borrowed: mutably_borrowed, - } - } - } - - #[inline] - pub fn set(&self, value: T) { - *self.mutate().ptr = value - } - - /// Replaces the slot's value with the given value and returns the old value. - #[inline] - pub fn replace(&self, value: T) -> T { - util::replace(self.mutate().ptr, value) - } - - #[inline(never)] - pub fn fail(&self) -> ! { - fail!("slot is borrowed") - } -} - -impl<T:Clone> Slot<T> { - #[inline] - pub fn get(&self) -> T { - self.value.clone() - } -} - - - - diff --git a/src/components/util/time.rs b/src/components/util/time.rs index bfc1a1bd43c..59b01d264e7 100644 --- a/src/components/util/time.rs +++ b/src/components/util/time.rs @@ -4,25 +4,36 @@ //! Timing functions. -use extra::sort::tim_sort; use extra::time::precise_time_ns; use extra::treemap::TreeMap; -use std::comm::{Port, SendDeferred, SharedChan}; +use std::comm::{Port, SharedChan}; use std::iter::AdditiveIterator; -use std::rt::io::timer::Timer; -use std::task::spawn_with; + + +// TODO: This code should be changed to use the commented code that uses timers +// directly, once native timers land in Rust. +extern { + pub fn usleep(secs: u64) -> u32; +} + +pub struct Timer; +impl Timer { + pub fn sleep(ms: u64) { + // + // let mut timer = Timer::new().unwrap(); + // timer.sleep(period); + unsafe { usleep((ms * 1000)); } + } +} + // front-end representation of the profiler used to communicate with the profiler #[deriving(Clone)] pub struct ProfilerChan(SharedChan<ProfilerMsg>); impl ProfilerChan { - pub fn new(chan: Chan<ProfilerMsg>) -> ProfilerChan { - ProfilerChan(SharedChan::new(chan)) - } - - pub fn send_deferred(&self, msg: ProfilerMsg) { - (**self).send_deferred(msg); + pub fn send(&self, msg: ProfilerMsg) { + (**self).send(msg); } } @@ -100,32 +111,35 @@ pub struct Profiler { } impl Profiler { - pub fn create(port: Port<ProfilerMsg>, chan: ProfilerChan, period: Option<f64>) { + pub fn create(period: Option<f64>) -> ProfilerChan { + let (port, chan) = SharedChan::new(); match period { Some(period) => { let period = (period * 1000f64) as u64; - do spawn { - let mut timer = Timer::new().unwrap(); + let chan = chan.clone(); + spawn(proc() { loop { - timer.sleep(period); + Timer::sleep(period); if !chan.try_send(PrintMsg) { break; } } - } + }); // Spawn the profiler - do spawn_with(port) |port| { + spawn(proc() { let mut profiler = Profiler::new(port); profiler.start(); - } + }); } None => { // no-op to handle profiler messages when the profiler is inactive - do spawn_with(port) |port| { - while port.try_recv().is_some() {} - } + spawn(proc() { + while port.recv_opt().is_some() {} + }); } } + + ProfilerChan(chan) } pub fn new(port: Port<ProfilerMsg>) -> Profiler { @@ -138,7 +152,7 @@ impl Profiler { pub fn start(&mut self) { loop { - let msg = self.port.try_recv(); + let msg = self.port.recv_opt(); match msg { Some (msg) => self.handle_msg(msg), None => break @@ -151,7 +165,7 @@ impl Profiler { TimeMsg(category, t) => self.buckets.find_mut(&category).unwrap().push(t), PrintMsg => match self.last_msg { // only print if more data has arrived since the last printout - Some(TimeMsg(*)) => self.print_buckets(), + Some(TimeMsg(..)) => self.print_buckets(), _ => () }, }; @@ -165,7 +179,13 @@ impl Profiler { for (category, data) in self.buckets.iter() { // FIXME(XXX): TreeMap currently lacks mut_iter() let mut data = data.clone(); - tim_sort(data); + data.sort_by(|a, b| { + if a < b { + Less + } else { + Greater + } + }); let data_len = data.len(); if data_len > 0 { let (mean, median, &min, &max) = @@ -184,17 +204,17 @@ impl Profiler { pub fn profile<T>(category: ProfilerCategory, profiler_chan: ProfilerChan, - callback: &fn() -> T) + callback: || -> T) -> T { let start_time = precise_time_ns(); let val = callback(); let end_time = precise_time_ns(); let ms = ((end_time - start_time) as f64 / 1000000f64); - profiler_chan.send_deferred(TimeMsg(category, ms)); + profiler_chan.send(TimeMsg(category, ms)); return val; } -pub fn time<T>(msg: &str, callback: &fn() -> T) -> T{ +pub fn time<T>(msg: &str, callback: || -> T) -> T{ let start_time = precise_time_ns(); let val = callback(); let end_time = precise_time_ns(); diff --git a/src/components/util/url.rs b/src/components/util/url.rs index 74571f84f5b..a3677dd6415 100644 --- a/src/components/util/url.rs +++ b/src/components/util/url.rs @@ -73,7 +73,7 @@ pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url { // Drop whitespace within data: URLs, e.g. newlines within a base64 // src="..." block. Whitespace intended as content should be // %-encoded or base64'd. - str_url.iter().filter(|&c| !c.is_whitespace()).collect() + str_url.chars().filter(|&c| !c.is_whitespace()).collect() }, _ => str_url } diff --git a/src/components/util/util.rc b/src/components/util/util.rc index 95e3b4e4662..9830de81d1a 100644 --- a/src/components/util/util.rc +++ b/src/components/util/util.rc @@ -2,10 +2,7 @@ * 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 = "util", - vers = "0.1", - uuid = "48421f49-17cf-41c5-a68e-ff669ff2ecd5", - url = "http://servo.org/")]; +#[crate_id = "github.com/mozilla/servo#util:0.1"]; #[crate_type = "lib"]; #[feature(macro_rules, managed_boxes)]; @@ -16,7 +13,6 @@ extern mod geom; pub mod cache; pub mod geometry; pub mod range; -pub mod slot; pub mod time; pub mod url; pub mod vec; diff --git a/src/components/util/vec.rs b/src/components/util/vec.rs index 7682eeab2ae..2c525c701cc 100644 --- a/src/components/util/vec.rs +++ b/src/components/util/vec.rs @@ -4,13 +4,13 @@ use std::cmp::{Ord, Eq}; -pub trait BinarySearchMethods<'self, T: Ord + Eq> { - fn binary_search(&self, key: &T) -> Option<&'self T>; +pub trait BinarySearchMethods<'a, T: Ord + Eq> { + fn binary_search(&self, key: &T) -> Option<&'a T>; fn binary_search_index(&self, key: &T) -> Option<uint>; } -impl<'self, T: Ord + Eq> BinarySearchMethods<'self, T> for &'self [T] { - fn binary_search(&self, key: &T) -> Option<&'self T> { +impl<'a, T: Ord + Eq> BinarySearchMethods<'a, T> for &'a [T] { + fn binary_search(&self, key: &T) -> Option<&'a T> { self.binary_search_index(key).map(|i| &self[i]) } @@ -39,6 +39,7 @@ impl<'self, T: Ord + Eq> BinarySearchMethods<'self, T> for &'self [T] { } } +#[cfg(test)] fn test_find_all_elems<T: Eq + Ord>(arr: &[T]) { let mut i = 0; while i < arr.len() { @@ -47,6 +48,7 @@ fn test_find_all_elems<T: Eq + Ord>(arr: &[T]) { } } +#[cfg(test)] fn test_miss_all_elems<T: Eq + Ord>(arr: &[T], misses: &[T]) { let mut i = 0; while i < misses.len() { @@ -57,6 +59,7 @@ fn test_miss_all_elems<T: Eq + Ord>(arr: &[T], misses: &[T]) { } } +#[cfg(test)] fn test_match<T: Eq>(b: &T, a: Option<&T>) -> bool { match a { None => false, @@ -70,9 +73,8 @@ pub fn zip_copies<A: Clone, B: Clone>(avec: &[A], bvec: &[B]) -> ~[(A,B)] { .collect() } +#[test] fn should_find_all_elements() { - #[test]; - let arr_odd = [1, 2, 4, 6, 7, 8, 9]; let arr_even = [1, 2, 5, 6, 7, 8, 9, 42]; let arr_double = [1, 1, 2, 2, 6, 8, 22]; @@ -88,9 +90,8 @@ fn should_find_all_elements() { test_find_all_elems(arr_three); } +#[test] fn should_not_find_missing_elements() { - #[test]; - let arr_odd = [1, 2, 4, 6, 7, 8, 9]; let arr_even = [1, 2, 5, 6, 7, 8, 9, 42]; let arr_double = [1, 1, 2, 2, 6, 8, 22]; diff --git a/src/platform/android/fontconfig b/src/platform/android/fontconfig -Subproject d0c6dd720f90e2e8f8d8a103754195096531b53 +Subproject 3f9c99be6ab7f733ec38e6c566a9cfb441e8f47 diff --git a/src/platform/linux/rust-fontconfig b/src/platform/linux/rust-fontconfig -Subproject a1e265ebb541c0402d5ce7a1e7dfdeaeac340fe +Subproject f3d71aa708eb44736c4fe526fbf1bb55010c623 diff --git a/src/platform/linux/rust-freetype b/src/platform/linux/rust-freetype -Subproject 710a4f1ac7bb5d6732b712574a7cfa098f804d0 +Subproject 03f4454a01cfcdcc8e7a7f6292f79a0d2250a2c diff --git a/src/platform/linux/rust-xlib b/src/platform/linux/rust-xlib -Subproject 965cc1f01134e186f01f048639b5ab1593f6d3c +Subproject 52eb54dc12212f1bf2bef803411f3ce7920f770 diff --git a/src/platform/macos/rust-cocoa b/src/platform/macos/rust-cocoa -Subproject 809e031c6c423655e3731c15295fb5f6eead53b +Subproject 0ed9f2272fc44afd20faba02fdf6b264fd7005b diff --git a/src/platform/macos/rust-core-foundation b/src/platform/macos/rust-core-foundation -Subproject 0a9090b60dc5ec8516ae73ae4398c91727231df +Subproject e855f9e03dbdd587092b93446e17eb1dd9313fe diff --git a/src/platform/macos/rust-core-graphics b/src/platform/macos/rust-core-graphics -Subproject bfb234fbafb11beeecb81dc763ecf8c7ab53923 +Subproject d6ab449173188761f72080c42660207154928e4 diff --git a/src/platform/macos/rust-core-text b/src/platform/macos/rust-core-text -Subproject bb5d9a1d1bb6e9720d3cd46b14530f24cccf51b +Subproject babcfa044f9a646a680c5528ac4aa777fd6d015 diff --git a/src/platform/macos/rust-io-surface b/src/platform/macos/rust-io-surface -Subproject 516e2c11b4ecc464f166a9b2a16d7bf25044c5d +Subproject f004673d5d172f2856b31d1b70253cd9dfba753 diff --git a/src/support/alert/rust-alert b/src/support/alert/rust-alert -Subproject ce3cdc68b942cabfaa766d0cfe34ecf758623fb +Subproject 906c01fd11e86964621ee55c78e93d9dff2bf76 diff --git a/src/support/azure/rust-azure b/src/support/azure/rust-azure -Subproject b6fd2d88ad921f6f36fc8ac1fdd5437e0ba1a45 +Subproject 7656f814a61f0b6bf557040b525761279095fc8 diff --git a/src/support/css/rust-cssparser b/src/support/css/rust-cssparser -Subproject 5178431109f4a51f38c257e36640702320c5495 +Subproject 0688d6ea9cea2b21ffa52286934be4942db7596 diff --git a/src/support/egl/rust-egl b/src/support/egl/rust-egl -Subproject 2eae43848b0a00d84f43e76b6d310bd69ffc7a3 +Subproject 0c0484e0c07a3e5ef3184f6182c96c354a06eeb diff --git a/src/support/encoding/rust-encoding b/src/support/encoding/rust-encoding -Subproject 1a6c011b697fe6d51a1d92a2504d6fac1b67d2d +Subproject f1cfdd64f6143fdcd864ec8fb607f7c231a723b diff --git a/src/support/geom/rust-geom b/src/support/geom/rust-geom -Subproject 928ee9d5055acd84a2f084b40c33e8556cbd008 +Subproject 883dda1f5089c305c5d6e6561ccbe7a0dfbd10f diff --git a/src/support/glfw/glfw-rs b/src/support/glfw/glfw-rs -Subproject 0920d683d5321e5d7a686d56d4183a34f7b173b +Subproject ca679e1cea938cd82d5aedae9fae26551a0cc6d diff --git a/src/support/glut/rust-glut b/src/support/glut/rust-glut -Subproject 633324e13f6b565615ef59f4463a4c528c90ba5 +Subproject bdc2aebba9111fafaa7a7b148014bcdeed3c7c0 diff --git a/src/support/harfbuzz/rust-harfbuzz b/src/support/harfbuzz/rust-harfbuzz -Subproject e29c85ecc7b0d61dcc669ce578c7957e88b617e +Subproject a3b9cdba9d4f2c3cec78437bd22649e75b59e68 diff --git a/src/support/http/rust-http b/src/support/http/rust-http -Subproject 9d8db21bfe189f81c0d88706475e282df0a6864 +Subproject 1a9a23b84cc28a7c39700f1c92a4cd1de1c98ce diff --git a/src/support/hubbub/rust-hubbub b/src/support/hubbub/rust-hubbub -Subproject 7254f84f81c464dbc78ddac84d7ecd494453a77 +Subproject a06f307be4f8220be14fa9b2203c4a08403851a diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers -Subproject e8123cee2432c1b430c3df781489493f8ecdb6c +Subproject 3caa5900ea6f5185f1ca4571a4f0e1215dab693 diff --git a/src/support/opengles/rust-opengles b/src/support/opengles/rust-opengles -Subproject 60776fdefad6c94fb08ca82b1b853340878c2ff +Subproject e1aa6d6e6f4412575908d003bb38df0d38cfa3c diff --git a/src/support/png/rust-png b/src/support/png/rust-png -Subproject 519c291139813bf6cda192a45745013d543c99f +Subproject 7a53b3042df5f483967b8bba283806d5f620954 diff --git a/src/support/sharegl/sharegl b/src/support/sharegl/sharegl -Subproject bb10edb7fb2428322a45664ebe8a9e0ce1679db +Subproject 64366a70cd162677fbda3c7722da6da4f8bcba0 diff --git a/src/support/spidermonkey/rust-mozjs b/src/support/spidermonkey/rust-mozjs -Subproject e3c4f8bfbea4f5523493c394576e76660fdf175 +Subproject da846919d0b99d84bffe89c5410b13ae64a969e diff --git a/src/support/stb-image/rust-stb-image b/src/support/stb-image/rust-stb-image -Subproject 0f55db952f5e5cd36f0f661e322e6c902ae172b +Subproject 9d0ae526ecc8fbdbfa29165c1dd634c2c71a858 diff --git a/src/test/harness/contenttest/contenttest.rs b/src/test/harness/contenttest/contenttest.rs index e7548b24610..1fd08edfdf9 100644 --- a/src/test/harness/contenttest/contenttest.rs +++ b/src/test/harness/contenttest/contenttest.rs @@ -13,10 +13,9 @@ extern mod extra; use extra::test::{TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName}; use extra::getopts::{getopts, reqopt}; use std::{os, str}; -use std::cell::Cell; -use std::os::list_dir_path; -use std::rt::io::Reader; -use std::rt::io::process::{Process, ProcessConfig, Ignored, CreatePipe, InheritFd}; +use std::io::fs; +use std::io::Reader; +use std::io::process::{Process, ProcessConfig, Ignored, CreatePipe, InheritFd, ExitStatus}; #[deriving(Clone)] struct Config { @@ -67,20 +66,19 @@ fn test_options(config: Config) -> TestOpts { } fn find_tests(config: Config) -> ~[TestDescAndFn] { - let mut files = list_dir_path(&Path::new(config.source_dir)); + let mut files = fs::readdir(&Path::new(config.source_dir)); files.retain(|file| file.extension_str() == Some("html") ); return files.map(|file| make_test(file.display().to_str()) ); } fn make_test(file: ~str) -> TestDescAndFn { - let f = Cell::new(file.clone()); TestDescAndFn { desc: TestDesc { - name: DynTestName(file), + name: DynTestName(file.clone()), ignore: false, should_fail: false }, - testfn: DynTestFn(|| { run_test(f.take()) }) + testfn: DynTestFn(proc() { run_test(file) }) } } @@ -113,15 +111,15 @@ fn run_test(file: ~str) { } let out = str::from_utf8(output); - let lines: ~[&str] = out.split_iter('\n').collect(); + let lines: ~[&str] = out.split('\n').collect(); for &line in lines.iter() { if line.contains("TEST-UNEXPECTED-FAIL") { - fail!(line); + fail!(line.to_owned()); } } let retval = prc.wait(); - if retval != 0 { + if retval != ExitStatus(0) { fail!("Servo exited with non-zero status {}", retval); } } diff --git a/src/test/harness/reftest/reftest.rs b/src/test/harness/reftest/reftest.rs index 2f83cf88583..fd22203a4e4 100644 --- a/src/test/harness/reftest/reftest.rs +++ b/src/test/harness/reftest/reftest.rs @@ -10,12 +10,11 @@ extern mod std; extern mod extra; -use std::cell::Cell; -use std::rt::io; -use std::rt::io::file; -use std::rt::io::Reader; +use std::io; +use std::io::{File, Reader}; +use std::io::process::ExitStatus; use std::os; -use std::run; +use std::run::{Process, ProcessOptions}; use std::str; use extra::test::{DynTestName, DynTestFn, TestDesc, TestOpts, TestDescAndFn}; use extra::test::run_tests_console; @@ -64,13 +63,13 @@ fn parse_lists(filenames: &[~str]) -> ~[TestDescAndFn] { let mut next_id = 0; for file in filenames.iter() { let file_path = Path::new(file.clone()); - let contents = match file::open(&file_path, io::Open, io::Read) { - Some(mut f) => str::from_utf8(f.read_to_end()), + let contents = match File::open_mode(&file_path, io::Open, io::Read) { + Some(mut f) => str::from_utf8_owned(f.read_to_end()), None => fail!("Could not open file") }; - for line in contents.line_iter() { - let parts: ~[&str] = line.split_iter(' ').filter(|p| !p.is_empty()).collect(); + for line in contents.lines() { + let parts: ~[&str] = line.split(' ').filter(|p| !p.is_empty()).collect(); if parts.len() != 3 { fail!("reftest line: '{:s}' doesn't match 'KIND LEFT RIGHT'", line); @@ -105,15 +104,14 @@ fn parse_lists(filenames: &[~str]) -> ~[TestDescAndFn] { fn make_test(reftest: Reftest) -> TestDescAndFn { let name = reftest.name.clone(); - let reftest = Cell::new(reftest); TestDescAndFn { desc: TestDesc { name: DynTestName(name), ignore: false, should_fail: false, }, - testfn: DynTestFn(|| { - check_reftest(reftest.take()); + testfn: DynTestFn(proc() { + check_reftest(reftest); }), } } @@ -123,22 +121,22 @@ fn check_reftest(reftest: Reftest) { let right_filename = format!("/tmp/servo-reftest-{:06u}-right.png", reftest.id); let args = ~[~"-o", left_filename.clone(), reftest.left.clone()]; - let mut process = run::Process::new("./servo", args, run::ProcessOptions::new()); + let mut process = Process::new("./servo", args, ProcessOptions::new()).unwrap(); let _retval = process.finish(); // assert!(retval == 0); let args = ~[~"-o", right_filename.clone(), reftest.right.clone()]; - let mut process = run::Process::new("./servo", args, run::ProcessOptions::new()); + let mut process = Process::new("./servo", args, ProcessOptions::new()).unwrap(); let _retval = process.finish(); // assert!(retval == 0); // check the pngs are bit equal let args = ~[left_filename.clone(), right_filename.clone()]; - let mut process = run::Process::new("cmp", args, run::ProcessOptions::new()); + let mut process = Process::new("cmp", args, ProcessOptions::new()).unwrap(); let retval = process.finish(); match reftest.kind { - Same => assert!(retval == 0), - Different => assert!(retval != 0), + Same => assert!(retval == ExitStatus(0)), + Different => assert!(retval != ExitStatus(0)), } } |