diff options
Diffstat (limited to 'components')
69 files changed, 1648 insertions, 625 deletions
diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs index c88f2a378b7..30e47c06082 100644 --- a/components/canvas/webgl_paint_thread.rs +++ b/components/canvas/webgl_paint_thread.rs @@ -6,7 +6,7 @@ use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasPixelData, CanvasData, Fro use euclid::size::Size2D; use gleam::gl; use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; -use offscreen_gl_context::{ColorAttachmentType, GLContext, GLContextAttributes, NativeGLContext}; +use offscreen_gl_context::{ColorAttachmentType, GLContext, GLLimits, GLContextAttributes, NativeGLContext}; use std::borrow::ToOwned; use std::sync::mpsc::channel; use util::thread::spawn_named; @@ -26,20 +26,24 @@ pub struct WebGLPaintThread { impl WebGLPaintThread { fn new(size: Size2D<i32>, attrs: GLContextAttributes, - webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Result<WebGLPaintThread, String> { - let data = if let Some(sender) = webrender_api_sender { + webrender_api_sender: Option<webrender_traits::RenderApiSender>) + -> Result<(WebGLPaintThread, GLLimits), String> { + let (data, limits) = if let Some(sender) = webrender_api_sender { let webrender_api = sender.create_api(); - let (id, _) = try!(webrender_api.request_webgl_context(&size, attrs)); - WebGLPaintTaskData::WebRender(webrender_api, id) + let (id, limits) = try!(webrender_api.request_webgl_context(&size, attrs)); + (WebGLPaintTaskData::WebRender(webrender_api, id), limits) } else { let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None)); - WebGLPaintTaskData::Servo(context) + let limits = context.borrow_limits().clone(); + (WebGLPaintTaskData::Servo(context), limits) }; - Ok(WebGLPaintThread { + let painter_object = WebGLPaintThread { size: size, data: data, - }) + }; + + Ok((painter_object, limits)) } pub fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) { @@ -59,13 +63,13 @@ impl WebGLPaintThread { pub fn start(size: Size2D<i32>, attrs: GLContextAttributes, webrender_api_sender: Option<webrender_traits::RenderApiSender>) - -> Result<IpcSender<CanvasMsg>, String> { + -> Result<(IpcSender<CanvasMsg>, GLLimits), String> { let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap(); let (result_chan, result_port) = channel(); spawn_named("WebGLThread".to_owned(), move || { let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender) { - Ok(thread) => { - result_chan.send(Ok(())).unwrap(); + Ok((thread, limits)) => { + result_chan.send(Ok(limits)).unwrap(); thread }, Err(e) => { @@ -95,8 +99,7 @@ impl WebGLPaintThread { } }); - try!(result_port.recv().unwrap()); - Ok(sender) + result_port.recv().unwrap().map(|limits| (sender, limits)) } fn send_data(&mut self, chan: IpcSender<CanvasData>) { diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index de33358873f..cec58afb9dd 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -89,7 +89,7 @@ git = "https://github.com/servo/webrender" app_units = {version = "0.2.3", features = ["plugins"]} euclid = {version = "0.6.4", features = ["plugins"]} gleam = "0.2.8" -image = "0.7" +image = "0.9" log = "0.3.5" num = "0.1.24" offscreen_gl_context = "0.1.2" diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 5950e13dc8f..e0fb0e144cb 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -755,7 +755,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { if !self.pipeline_details.contains_key(&pipeline_id) { self.pipeline_details.insert(pipeline_id, PipelineDetails::new()); } - self.pipeline_details.get_mut(&pipeline_id).unwrap() + self.pipeline_details.get_mut(&pipeline_id).expect("Insert then get failed!") } pub fn pipeline(&self, pipeline_id: PipelineId) -> Option<&CompositionPipeline> { @@ -2191,7 +2191,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { let src_slice = &orig_pixels[src_start .. src_start + stride]; (&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]); } - RgbImage::from_raw(width as u32, height as u32, pixels).unwrap() + RgbImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!") } fn composite_if_necessary(&mut self, reason: CompositingReason) { diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index b52a1a22395..74b09dcb477 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -39,7 +39,7 @@ use msg::webdriver_msg; use net_traits::image_cache_thread::ImageCacheThread; use net_traits::storage_thread::{StorageThread, StorageThreadMsg}; use net_traits::{self, ResourceThread}; -use offscreen_gl_context::GLContextAttributes; +use offscreen_gl_context::{GLContextAttributes, GLLimits}; use pipeline::{CompositionPipeline, InitialPipelineState, Pipeline, UnprivilegedPipelineContent}; use profile_traits::mem; use profile_traits::time; @@ -265,14 +265,14 @@ impl<'a> Iterator for FrameTreeIterator<'a> { let frame = match self.frames.get(&frame_id) { Some(frame) => frame, None => { - debug!("Frame {:?} iterated after closure.", frame_id); + warn!("Frame {:?} iterated after closure.", frame_id); continue; }, }; let pipeline = match self.pipelines.get(&frame.current) { Some(pipeline) => pipeline, None => { - debug!("Pipeline {:?} iterated after closure.", frame.current); + warn!("Pipeline {:?} iterated after closure.", frame.current); continue; }, }; @@ -461,25 +461,38 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // avoiding this panic would require a mechanism for dealing // with low-resource scenarios. let (server, token) = - IpcOneShotServer::<IpcSender<UnprivilegedPipelineContent>>::new().unwrap(); + IpcOneShotServer::<IpcSender<UnprivilegedPipelineContent>>::new() + .expect("Failed to create IPC one-shot server."); // If there is a sandbox, use the `gaol` API to create the child process. let child_process = if opts::get().sandbox { - let mut command = sandbox::Command::me().unwrap(); + let mut command = sandbox::Command::me().expect("Failed to get current sandbox."); command.arg("--content-process").arg(token); + + if let Ok(value) = env::var("RUST_BACKTRACE") { + command.env("RUST_BACKTRACE", value); + } + let profile = sandboxing::content_process_sandbox_profile(); - ChildProcess::Sandboxed(Sandbox::new(profile).start(&mut command).expect( - "Failed to start sandboxed child process!")) + ChildProcess::Sandboxed(Sandbox::new(profile).start(&mut command) + .expect("Failed to start sandboxed child process!")) } else { - let path_to_self = env::current_exe().unwrap(); + let path_to_self = env::current_exe() + .expect("Failed to get current executor."); let mut child_process = process::Command::new(path_to_self); child_process.arg("--content-process"); child_process.arg(token); - ChildProcess::Unsandboxed(child_process.spawn().unwrap()) + + if let Ok(value) = env::var("RUST_BACKTRACE") { + child_process.env("RUST_BACKTRACE", value); + } + + ChildProcess::Unsandboxed(child_process.spawn() + .expect("Failed to start unsandboxed child process!")) }; self.child_processes.push(child_process); - let (_receiver, sender) = server.accept().unwrap(); + let (_receiver, sender) = server.accept().expect("Server failed to accept."); sender.send(unprivileged_pipeline_content) .unwrap_or_else(|_| self.handle_send_error(pipeline_id)); } @@ -688,7 +701,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> debug!("constellation got set final url message"); pipeline.url = final_url; } else { - debug!("constellation got set final url message for dead pipeline"); + warn!("constellation got set final url message for dead pipeline"); } } Request::Script(FromScriptMsg::MozBrowserEvent(pipeline_id, @@ -722,16 +735,16 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> let result = self.clipboard_ctx.as_ref().map_or( "".to_owned(), |ctx| ctx.get_contents().unwrap_or_else(|e| { - debug!("Error getting clipboard contents ({}), defaulting to empty string", e); + warn!("Error getting clipboard contents ({}), defaulting to empty string", e); "".to_owned() }) ); - sender.send(result).unwrap_or_else(|e| debug!("Failed to send clipboard ({})", e)) + sender.send(result).unwrap_or_else(|e| warn!("Failed to send clipboard ({})", e)) } Request::Script(FromScriptMsg::SetClipboardContents(s)) => { if let Some(ref mut ctx) = self.clipboard_ctx { if let Err(e) = ctx.set_contents(s) { - debug!("Error setting clipboard contents ({})", e); + warn!("Error setting clipboard contents ({})", e); } } } @@ -739,7 +752,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> debug!("constellation got remove iframe message"); self.handle_remove_iframe_msg(pipeline_id); if let Some(sender) = sender { - sender.send(()).unwrap_or_else(|e| debug!("Error replying to remove iframe ({})", e)); + sender.send(()).unwrap_or_else(|e| warn!("Error replying to remove iframe ({})", e)); } } Request::Script(FromScriptMsg::NewFavicon(url)) => { @@ -805,20 +818,20 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> } self.image_cache_thread.exit(); self.resource_thread.send(net_traits::ControlMsg::Exit) - .unwrap_or_else(|e| debug!("Exit resource thread failed ({})", e)); + .unwrap_or_else(|e| warn!("Exit resource thread failed ({})", e)); self.devtools_chan.as_ref().map(|chan| { chan.send(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg)) - .unwrap_or_else(|e| debug!("Exit devtools failed ({})", e)); + .unwrap_or_else(|e| warn!("Exit devtools failed ({})", e)); }); self.storage_thread.send(StorageThreadMsg::Exit) - .unwrap_or_else(|e| debug!("Exit storage thread failed ({})", e)); + .unwrap_or_else(|e| warn!("Exit storage thread failed ({})", e)); self.font_cache_thread.exit(); self.compositor_proxy.send(ToCompositorMsg::ShutdownComplete); } fn handle_send_error(&mut self, pipeline_id: PipelineId) { let parent_info = match self.pipelines.get(&pipeline_id) { - None => return debug!("Pipeline {:?} send error after closure.", pipeline_id), + None => return warn!("Pipeline {:?} send error after closure.", pipeline_id), Some(pipeline) => pipeline.parent_info, }; // Treat send error the same as receiving a failure message @@ -832,7 +845,8 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // It's quite difficult to make Servo exit cleanly if some threads have failed. // Hard fail exists for test runners so we crash and that's good enough. let mut stderr = io::stderr(); - stderr.write_all("Pipeline failed in hard-fail mode. Crashing!\n".as_bytes()).unwrap(); + stderr.write_all("Pipeline failed in hard-fail mode. Crashing!\n".as_bytes()) + .expect("Failed to write to stderr!"); process::exit(1); } @@ -843,11 +857,11 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> while let Some(pending_pipeline_id) = self.pending_frames.iter().find(|pending| { pending.old_pipeline_id == Some(pipeline_id) }).map(|frame| frame.new_pipeline_id) { - debug!("removing pending frame change for failed pipeline"); + warn!("removing pending frame change for failed pipeline"); self.close_pipeline(pending_pipeline_id, ExitPipelineMode::Force); } - debug!("creating replacement pipeline for about:failure"); + warn!("creating replacement pipeline for about:failure"); let new_pipeline_id = PipelineId::new(); self.new_pipeline(new_pipeline_id, @@ -897,15 +911,15 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> fn handle_subframe_loaded(&mut self, pipeline_id: PipelineId) { let parent_info = match self.pipelines.get(&pipeline_id) { Some(pipeline) => pipeline.parent_info, - None => return debug!("Pipeline {:?} loaded after closure.", pipeline_id), + None => return warn!("Pipeline {:?} loaded after closure.", pipeline_id), }; let subframe_parent_id = match parent_info { Some(ref parent) => parent.0, - None => return debug!("Pipeline {:?} has no parent.", pipeline_id), + None => return warn!("Pipeline {:?} has no parent.", pipeline_id), }; let script_chan = match self.pipelines.get(&subframe_parent_id) { Some(pipeline) => pipeline.script_chan.clone(), - None => return debug!("Pipeline {:?} subframe loaded after closure.", subframe_parent_id), + None => return warn!("Pipeline {:?} subframe loaded after closure.", subframe_parent_id), }; let msg = ConstellationControlMsg::DispatchFrameLoadEvent { target: pipeline_id, @@ -929,7 +943,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> let old_pipeline = old_pipeline_id .and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id)); - let source_pipeline = self.pipelines.get(&load_info.containing_pipeline_id); + let source_pipeline = match self.pipelines.get(&load_info.containing_pipeline_id) { + Some(source_pipeline) => source_pipeline, + None => return warn!("Script loaded url in closed iframe {}.", load_info.containing_pipeline_id), + }; // If no url is specified, reload. let new_url = load_info.url.clone() @@ -938,25 +955,23 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // Compare the pipeline's url to the new url. If the origin is the same, // then reuse the script thread in creating the new pipeline - let script_chan = source_pipeline.and_then(|source_pipeline| { - let source_url = source_pipeline.url.clone(); - - let same_script = (source_url.host() == new_url.host() && - source_url.port() == new_url.port()) && - load_info.sandbox == IFrameSandboxState::IFrameUnsandboxed; - - // FIXME(tkuehn): Need to follow the standardized spec for checking same-origin - // Reuse the script thread if the URL is same-origin - if same_script { - debug!("Constellation: loading same-origin iframe, \ - parent url {:?}, iframe url {:?}", source_url, new_url); - Some(source_pipeline.script_chan.clone()) - } else { - debug!("Constellation: loading cross-origin iframe, \ - parent url {:?}, iframe url {:?}", source_url, new_url); - None - } - }); + let source_url = &source_pipeline.url; + + let same_script = source_url.host() == new_url.host() && + source_url.port() == new_url.port() && + load_info.sandbox == IFrameSandboxState::IFrameUnsandboxed; + + // FIXME(tkuehn): Need to follow the standardized spec for checking same-origin + // Reuse the script thread if the URL is same-origin + let script_chan = if same_script { + debug!("Constellation: loading same-origin iframe, \ + parent url {:?}, iframe url {:?}", source_url, new_url); + Some(source_pipeline.script_chan.clone()) + } else { + debug!("Constellation: loading cross-origin iframe, \ + parent url {:?}, iframe url {:?}", source_url, new_url); + None + }; let window_size = old_pipeline.and_then(|old_pipeline| old_pipeline.size); @@ -995,7 +1010,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> fn handle_tick_animation(&mut self, pipeline_id: PipelineId, tick_type: AnimationTickType) { let (layout_chan, script_chan) = match self.pipelines.get(&pipeline_id) { Some(pipeline) => (pipeline.layout_chan.0.clone(), pipeline.script_chan.clone()), - None => return debug!("Pipeline {:?} got tick after closure.", pipeline_id), + None => return warn!("Pipeline {:?} got tick after closure.", pipeline_id), }; match tick_type { AnimationTickType::Script => { @@ -1036,7 +1051,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> let script_chan = match self.pipelines.get(&parent_pipeline_id) { Some(parent_pipeline) => parent_pipeline.script_chan.clone(), None => { - debug!("Pipeline {:?} child loaded after closure", parent_pipeline_id); + warn!("Pipeline {:?} child loaded after closure", parent_pipeline_id); return None; }, }; @@ -1072,7 +1087,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // Send message to ScriptThread that will suspend all timers match self.pipelines.get(&source_id) { Some(source) => source.freeze(), - None => debug!("Pipeline {:?} loaded after closure", source_id), + None => warn!("Pipeline {:?} loaded after closure", source_id), }; Some(new_pipeline_id) } @@ -1132,7 +1147,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // If the frame_id lookup fails, then we are in the middle of tearing down // the root frame, so it is reasonable to silently ignore the navigation. let frame_id = match frame_id { - None => return debug!("Navigation after root's closure."), + None => return warn!("Navigation after root's closure."), Some(frame_id) => frame_id, }; @@ -1148,7 +1163,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> NavigationDirection::Forward => { match frame.next.pop() { None => { - debug!("no next page to navigate to"); + warn!("no next page to navigate to"); return; }, Some(next) => { @@ -1160,7 +1175,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> NavigationDirection::Back => { match frame.prev.pop() { None => { - debug!("no previous page to navigate to"); + warn!("no previous page to navigate to"); return; }, Some(prev) => { @@ -1175,7 +1190,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> (prev, next) }, None => { - debug!("no frame to navigate from"); + warn!("no frame to navigate from"); return; }, }; @@ -1203,13 +1218,13 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // This makes things like contentDocument work correctly. if let Some((parent_pipeline_id, subpage_id)) = pipeline_info { let script_chan = match self.pipelines.get(&parent_pipeline_id) { - None => return debug!("Pipeline {:?} child navigated after closure.", parent_pipeline_id), + None => return warn!("Pipeline {:?} child navigated after closure.", parent_pipeline_id), Some(pipeline) => pipeline.script_chan.clone(), }; let new_subpage_id = match self.pipelines.get(&next_pipeline_id) { - None => return debug!("Pipeline {:?} navigated to after closure.", next_pipeline_id), + None => return warn!("Pipeline {:?} navigated to after closure.", next_pipeline_id), Some(pipeline) => match pipeline.parent_info { - None => return debug!("Pipeline {:?} has no parent info.", next_pipeline_id), + None => return warn!("Pipeline {:?} has no parent info.", next_pipeline_id), Some((_, new_subpage_id)) => new_subpage_id, }, }; @@ -1267,7 +1282,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // so it is reasonable to silently ignore the event. match self.pipelines.get(&containing_pipeline_id) { Some(pipeline) => pipeline.trigger_mozbrowser_event(subpage_id, event), - None => debug!("Pipeline {:?} handling mozbrowser event after closure.", containing_pipeline_id), + None => warn!("Pipeline {:?} handling mozbrowser event after closure.", containing_pipeline_id), } } @@ -1280,7 +1295,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> .find(|x| x.old_pipeline_id == current_pipeline_id) .map(|x| x.new_pipeline_id).or(current_pipeline_id); resp_chan.send(pipeline_id) - .unwrap_or_else(|_| debug!("Failed get_pipeline response.")); + .unwrap_or_else(|_| warn!("Failed get_pipeline response.")); } fn handle_get_frame(&mut self, @@ -1288,21 +1303,21 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> resp_chan: IpcSender<Option<FrameId>>) { let frame_id = self.pipeline_to_frame_map.get(&pipeline_id).map(|x| *x); resp_chan.send(frame_id) - .unwrap_or_else(|_| debug!("Failed get_pipeline response.")); + .unwrap_or_else(|_| warn!("Failed get_pipeline response.")); } fn focus_parent_pipeline(&mut self, pipeline_id: PipelineId) { let parent_info = match self.pipelines.get(&pipeline_id) { Some(pipeline) => pipeline.parent_info, - None => return debug!("Pipeline {:?} focus parent after closure.", pipeline_id), + None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id), }; let (containing_pipeline_id, subpage_id) = match parent_info { Some(info) => info, - None => return debug!("Pipeline {:?} focus has no parent.", pipeline_id), + None => return warn!("Pipeline {:?} focus has no parent.", pipeline_id), }; let script_chan = match self.pipelines.get(&containing_pipeline_id) { Some(pipeline) => pipeline.script_chan.clone(), - None => return debug!("Pipeline {:?} focus after closure.", containing_pipeline_id), + None => return warn!("Pipeline {:?} focus after closure.", containing_pipeline_id), }; // Send a message to the parent of the provided pipeline (if it exists) @@ -1342,19 +1357,19 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> let webrender_api = self.webrender_api_sender.clone(); let sender = CanvasPaintThread::start(*size, webrender_api); response_sender.send(sender) - .unwrap_or_else(|e| debug!("Create canvas paint thread response failed ({})", e)) + .unwrap_or_else(|e| warn!("Create canvas paint thread response failed ({})", e)) } fn handle_create_webgl_paint_thread_msg( &mut self, size: &Size2D<i32>, attributes: GLContextAttributes, - response_sender: IpcSender<Result<IpcSender<CanvasMsg>, String>>) { + response_sender: IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>) { let webrender_api = self.webrender_api_sender.clone(); - let sender = WebGLPaintThread::start(*size, attributes, webrender_api); + let response = WebGLPaintThread::start(*size, attributes, webrender_api); - response_sender.send(sender) - .unwrap_or_else(|e| debug!("Create WebGL paint thread response failed ({})", e)) + response_sender.send(response) + .unwrap_or_else(|e| warn!("Create WebGL paint thread response failed ({})", e)) } fn handle_webdriver_msg(&mut self, msg: WebDriverCommandMsg) { @@ -1367,14 +1382,14 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> WebDriverCommandMsg::Refresh(pipeline_id, reply) => { let load_data = match self.pipelines.get(&pipeline_id) { Some(pipeline) => LoadData::new(pipeline.url.clone()), - None => return debug!("Pipeline {:?} Refresh after closure.", pipeline_id), + None => return warn!("Pipeline {:?} Refresh after closure.", pipeline_id), }; self.load_url_for_webdriver(pipeline_id, load_data, reply); } WebDriverCommandMsg::ScriptCommand(pipeline_id, cmd) => { let script_channel = match self.pipelines.get(&pipeline_id) { Some(pipeline) => pipeline.script_chan.clone(), - None => return debug!("Pipeline {:?} ScriptCommand after closure.", pipeline_id), + None => return warn!("Pipeline {:?} ScriptCommand after closure.", pipeline_id), }; let control_msg = ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, cmd); script_channel.send(control_msg) @@ -1383,7 +1398,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> WebDriverCommandMsg::SendKeys(pipeline_id, cmd) => { let script_channel = match self.pipelines.get(&pipeline_id) { Some(pipeline) => pipeline.script_chan.clone(), - None => return debug!("Pipeline {:?} SendKeys after closure.", pipeline_id), + None => return warn!("Pipeline {:?} SendKeys after closure.", pipeline_id), }; for (key, mods, state) in cmd { let event = CompositorEvent::KeyEvent(key, state, mods); @@ -1399,7 +1414,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> if Some(pipeline_id) == current_pipeline_id { self.compositor_proxy.send(ToCompositorMsg::CreatePng(reply)); } else { - reply.send(None).unwrap_or_else(|e| debug!("Screenshot reply failed ({})", e)); + reply.send(None).unwrap_or_else(|e| warn!("Screenshot reply failed ({})", e)); } }, } @@ -1532,18 +1547,18 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // Send Resize (or ResizeInactive) messages to each // pipeline in the frame tree. let frame = match self.frames.get(&root_frame_id) { - None => return debug!("Frame {:?} resized after closing.", root_frame_id), + None => return warn!("Frame {:?} resized after closing.", root_frame_id), Some(frame) => frame, }; let pipeline_id = frame.current; let pipeline = match self.pipelines.get(&pipeline_id) { - None => return debug!("Pipeline {:?} resized after closing.", pipeline_id), + None => return warn!("Pipeline {:?} resized after closing.", pipeline_id), Some(pipeline) => pipeline, }; let _ = pipeline.script_chan.send(ConstellationControlMsg::Resize(pipeline.id, new_size)); for pipeline_id in frame.prev.iter().chain(&frame.next) { let pipeline = match self.pipelines.get(&pipeline_id) { - None => { debug!("Inactive pipeline {:?} resized after closing.", pipeline_id); continue; }, + None => { warn!("Inactive pipeline {:?} resized after closing.", pipeline_id); continue; }, Some(pipeline) => pipeline, }; let _ = pipeline.script_chan.send(ConstellationControlMsg::ResizeInactive(pipeline.id, @@ -1555,7 +1570,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> for pending_frame in &self.pending_frames { let pipeline_id = pending_frame.new_pipeline_id; let pipeline = match self.pipelines.get(&pipeline_id) { - None => { debug!("Pending pipeline {:?} is closed", pipeline_id); continue; } + None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; } Some(pipeline) => pipeline, }; if pipeline.parent_info.is_none() { @@ -1606,7 +1621,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> let pipeline_id = frame.current; let pipeline = match self.pipelines.get(&pipeline_id) { - None => { debug!("Pipeline {:?} screenshot while closing.", pipeline_id); continue; }, + None => { warn!("Pipeline {:?} screenshot while closing.", pipeline_id); continue; }, Some(pipeline) => pipeline, }; @@ -1618,10 +1633,10 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // before we check whether the document is ready; otherwise, // there's a race condition where a webfont has finished loading, // but hasn't yet notified the document. - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!"); let msg = LayoutControlMsg::GetWebFontLoadState(sender); pipeline.layout_chan.0.send(msg) - .unwrap_or_else(|e| debug!("Get web font failed ({})", e)); + .unwrap_or_else(|e| warn!("Get web font failed ({})", e)); if receiver.recv().unwrap_or(true) { return ReadyToSave::WebFontNotLoaded; } @@ -1654,12 +1669,16 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> // epoch matches what the compositor has drawn. If they match // (and script is idle) then this pipeline won't change again // and can be considered stable. - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!"); let LayoutControlChan(ref layout_chan) = pipeline.layout_chan; - layout_chan.send(LayoutControlMsg::GetCurrentEpoch(sender)).unwrap(); - let layout_thread_epoch = receiver.recv().unwrap(); - if layout_thread_epoch != *compositor_epoch { - return ReadyToSave::EpochMismatch; + if let Err(e) = layout_chan.send(LayoutControlMsg::GetCurrentEpoch(sender)) { + warn!("Failed to send GetCurrentEpoch ({}).", e); + } + match receiver.recv() { + Err(e) => warn!("Failed to receive current epoch ({}).", e), + Ok(layout_thread_epoch) => if layout_thread_epoch != *compositor_epoch { + return ReadyToSave::EpochMismatch; + }, } } None => { @@ -1715,12 +1734,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> } if let None = self.frames.remove(&frame_id) { - debug!("Closing frame {:?} twice.", frame_id); + warn!("Closing frame {:?} twice.", frame_id); } if let Some((parent_pipeline_id, _)) = parent_info { let parent_pipeline = match self.pipelines.get_mut(&parent_pipeline_id) { - None => return debug!("Pipeline {:?} child closed after parent.", parent_pipeline_id), + None => return warn!("Pipeline {:?} child closed after parent.", parent_pipeline_id), Some(parent_pipeline) => parent_pipeline, }; parent_pipeline.remove_child(frame_id); @@ -1750,7 +1769,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> let pipeline = match self.pipelines.remove(&pipeline_id) { Some(pipeline) => pipeline, - None => return debug!("Closing pipeline {:?} twice.", pipeline_id), + None => return warn!("Closing pipeline {:?} twice.", pipeline_id), }; // If a child pipeline, remove from subpage map @@ -1835,12 +1854,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> if let Some(root_frame_id) = self.root_frame_id { if let Some(frame_tree) = self.frame_to_sendable(root_frame_id) { - let (chan, port) = ipc::channel().unwrap(); + let (chan, port) = ipc::channel().expect("Failed to create IPC channel!"); self.compositor_proxy.send(ToCompositorMsg::SetFrameTree(frame_tree, chan, self.compositor_sender.clone())); if port.recv().is_err() { - debug!("Compositor has discarded SetFrameTree"); + warn!("Compositor has discarded SetFrameTree"); return; // Our message has been discarded, probably shutting down. } } diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index 8c22ce0348b..3a45a486b8a 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -26,6 +26,7 @@ use profile_traits::time; use script_traits::{ConstellationControlMsg, InitialScriptState, MozBrowserEvent}; use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg}; use script_traits::{ScriptToCompositorMsg, ScriptThreadFactory, TimerEventRequest}; +use std::collections::HashMap; use std::mem; use std::sync::mpsc::{Receiver, Sender, channel}; use url::Url; @@ -33,7 +34,7 @@ use util; use util::geometry::{PagePx, ViewportPx}; use util::ipc::OptionalIpcSender; use util::opts::{self, Opts}; -use util::prefs; +use util::prefs::{self, Pref}; use util::thread; use webrender_traits; @@ -232,6 +233,7 @@ impl Pipeline { failure: failure, script_port: script_port, opts: (*opts::get()).clone(), + prefs: prefs::get_cloned(), layout_to_paint_chan: layout_to_paint_chan, pipeline_port: pipeline_port, layout_shutdown_chan: layout_shutdown_chan, @@ -408,6 +410,7 @@ pub struct UnprivilegedPipelineContent { script_port: Option<IpcReceiver<ConstellationControlMsg>>, layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>, opts: Opts, + prefs: HashMap<String, Pref>, paint_shutdown_chan: IpcSender<()>, pipeline_port: Option<IpcReceiver<LayoutControlMsg>>, pipeline_namespace_id: PipelineNamespaceId, @@ -472,6 +475,10 @@ impl UnprivilegedPipelineContent { pub fn opts(&self) -> Opts { self.opts.clone() } + + pub fn prefs(&self) -> HashMap<String, Pref> { + self.prefs.clone() + } } pub struct PrivilegedPipelineContent { diff --git a/components/compositing/sandboxing.rs b/components/compositing/sandboxing.rs index 41273cad0a7..945e0605f09 100644 --- a/components/compositing/sandboxing.rs +++ b/components/compositing/sandboxing.rs @@ -16,7 +16,9 @@ pub fn content_process_sandbox_profile() -> Profile { Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/Library/Fonts"))), Operation::FileReadAll(PathPattern::Subpath(PathBuf::from("/System/Library/Fonts"))), Operation::FileReadAll(PathPattern::Subpath(PathBuf::from( - "/System/Library/Frameworks/ApplicationServices.framework/"))), + "/System/Library/Frameworks/ApplicationServices.framework"))), + Operation::FileReadAll(PathPattern::Subpath(PathBuf::from( + "/System/Library/Frameworks/CoreGraphics.framework"))), Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/"))), Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/Library"))), Operation::FileReadMetadata(PathPattern::Literal(PathBuf::from("/System"))), diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index 823b78ed271..f470f7dcd48 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -27,7 +27,7 @@ serde = "0.7" serde_macros = "0.7" servo-skia = "0.20130412.0" smallvec = "0.1" -string_cache = {version = "0.2.11", features = ["heap_size"]} +string_cache = {version = "0.2.12", features = ["heap_size"]} time = "0.1.12" unicode-script = { version = "0.1", features = ["harfbuzz"] } url = {version = "0.5.7", features = ["heap_size"]} diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 7cb95e6fc54..ff7715e2cb7 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -38,7 +38,7 @@ fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFo #[cfg(target_os = "macos")] fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont { - let cgfont = template.ctfont().as_ref().unwrap().copy_to_CGFont(); + let cgfont = template.ctfont(pt_size.to_f64_px()).as_ref().unwrap().copy_to_CGFont(); ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px()) } diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs index a0667245cbe..abdb620ba36 100644 --- a/components/gfx/platform/macos/font.rs +++ b/components/gfx/platform/macos/font.rs @@ -72,7 +72,7 @@ impl FontHandleMethods for FontHandle { Some(s) => s.to_f64_px(), None => 0.0 }; - match template.ctfont() { + match template.ctfont(size) { Some(ref ctfont) => { Ok(FontHandle { font_data: template.clone(), diff --git a/components/gfx/platform/macos/font_template.rs b/components/gfx/platform/macos/font_template.rs index 3099bbd28ed..a36b49eebe3 100644 --- a/components/gfx/platform/macos/font_template.rs +++ b/components/gfx/platform/macos/font_template.rs @@ -2,6 +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 app_units::Au; use core_graphics::data_provider::CGDataProvider; use core_graphics::font::CGFont; use core_text; @@ -9,6 +10,7 @@ use core_text::font::CTFont; use serde::de::{Error, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::ToOwned; +use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::ops::Deref; @@ -26,7 +28,7 @@ pub struct FontTemplateData { /// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or /// `font_data` fields. /// - /// When sending a `FontTemplateData` instance across processes, this will be set to `None` on + /// When sending a `FontTemplateData` instance across processes, this will be cleared out on /// the other side, because `CTFont` instances cannot be sent across processes. This is /// harmless, however, because it can always be recreated. ctfont: CachedCTFont, @@ -41,29 +43,38 @@ unsafe impl Sync for FontTemplateData {} impl FontTemplateData { pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> FontTemplateData { FontTemplateData { - ctfont: CachedCTFont(Mutex::new(None)), + ctfont: CachedCTFont(Mutex::new(HashMap::new())), identifier: identifier.to_owned(), font_data: font_data } } /// Retrieves the Core Text font instance, instantiating it if necessary. - pub fn ctfont(&self) -> Option<CTFont> { - let mut ctfont = self.ctfont.lock().unwrap(); - if ctfont.is_none() { - *ctfont = match self.font_data { + pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> { + let mut ctfonts = self.ctfont.lock().unwrap(); + let pt_size_key = Au::from_f64_px(pt_size); + if !ctfonts.contains_key(&pt_size_key) { + // If you pass a zero font size to one of the Core Text APIs, it'll replace it with + // 12.0. We don't want that! (Issue #10492.) + let clamped_pt_size = pt_size.max(0.01); + let ctfont = match self.font_data { Some(ref bytes) => { let fontprov = CGDataProvider::from_buffer(bytes); let cgfont_result = CGFont::from_data_provider(fontprov); match cgfont_result { - Ok(cgfont) => Some(core_text::font::new_from_CGFont(&cgfont, 0.0)), + Ok(cgfont) => { + Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size)) + } Err(_) => None } } - None => core_text::font::new_from_name(&*self.identifier, 0.0).ok(), + None => core_text::font::new_from_name(&*self.identifier, clamped_pt_size).ok(), + }; + if let Some(ctfont) = ctfont { + ctfonts.insert(pt_size_key, ctfont); } } - ctfont.as_ref().map(|ctfont| (*ctfont).clone()) + ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone()) } /// Returns a clone of the data in this font. This may be a hugely expensive @@ -75,7 +86,7 @@ impl FontTemplateData { None => {} } - let path = Url::parse(&*self.ctfont() + let path = Url::parse(&*self.ctfont(0.0) .expect("No Core Text font available!") .url() .expect("No URL for Core Text font!") @@ -96,16 +107,16 @@ impl FontTemplateData { /// Returns the native font that underlies this font template, if applicable. pub fn native_font(&self) -> Option<CGFont> { - self.ctfont().map(|ctfont| ctfont.copy_to_CGFont()) + self.ctfont(0.0).map(|ctfont| ctfont.copy_to_CGFont()) } } #[derive(Debug)] -pub struct CachedCTFont(Mutex<Option<CTFont>>); +pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>); impl Deref for CachedCTFont { - type Target = Mutex<Option<CTFont>>; - fn deref(&self) -> &Mutex<Option<CTFont>> { + type Target = Mutex<HashMap<Au, CTFont>>; + fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> { &self.0 } } @@ -126,7 +137,7 @@ impl Deserialize for CachedCTFont { #[inline] fn visit_none<E>(&mut self) -> Result<CachedCTFont, E> where E: Error { - Ok(CachedCTFont(Mutex::new(None))) + Ok(CachedCTFont(Mutex::new(HashMap::new()))) } } diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index f7371a7a34a..35ca6cd1173 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -76,7 +76,7 @@ serde = "0.7" serde_json = "0.7" serde_macros = "0.7" smallvec = "0.1" -string_cache = {version = "0.2.11", features = ["heap_size"]} +string_cache = {version = "0.2.12", features = ["heap_size"]} time = "0.1" unicode-bidi = "0.2" unicode-script = { version = "0.1", features = ["harfbuzz"] } diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 4c8f749b086..eed7ec8aae3 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -13,9 +13,9 @@ use display_list_builder::{DisplayListBuildState, FlexFlowDisplayListBuilding}; use euclid::Point2D; use floats::FloatKind; use flow; -use flow::INLINE_POSITION_IS_STATIC; -use flow::IS_ABSOLUTELY_POSITIONED; use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; +use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED}; +use flow_ref::{self, FlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::{StackingContext, StackingContextId}; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; @@ -73,6 +73,19 @@ enum Mode { Block } +#[derive(Debug)] +struct FlexItem { + pub flow: FlowRef, +} + +impl FlexItem { + fn new(flow: FlowRef) -> FlexItem { + FlexItem { + flow: flow + } + } +} + /// A block with the CSS `display` property equal to `flex`. #[derive(Debug)] pub struct FlexFlow { @@ -84,23 +97,9 @@ pub struct FlexFlow { /// The available main axis size available_main_size: AxisSize, /// The available cross axis size - available_cross_size: AxisSize -} - -// TODO(zentner): This function should use flex-basis. -fn flex_item_inline_sizes(flow: &mut Flow) -> IntrinsicISizes { - let _scope = layout_debug_scope!("flex::flex_item_inline_sizes"); - debug!("flex_item_inline_sizes"); - let base = flow::mut_base(flow); - - debug!("FlexItem intrinsic inline sizes: {:?}, {:?}", - base.intrinsic_inline_sizes.minimum_inline_size, - base.intrinsic_inline_sizes.preferred_inline_size); - - IntrinsicISizes { - minimum_inline_size: base.intrinsic_inline_sizes.minimum_inline_size, - preferred_inline_size: base.intrinsic_inline_sizes.preferred_inline_size, - } + available_cross_size: AxisSize, + /// List of flex-items that belong to this flex-container + items: Vec<FlexItem> } impl FlexFlow { @@ -117,7 +116,8 @@ impl FlexFlow { block_flow: BlockFlow::from_fragment(fragment, flotation), main_mode: main_mode, available_main_size: AxisSize::Infinite, - available_cross_size: AxisSize::Infinite + available_cross_size: AxisSize::Infinite, + items: Vec::new() } } @@ -132,11 +132,15 @@ impl FlexFlow { let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); if !fixed_width { - for kid in self.block_flow.base.child_iter_mut() { - let is_absolutely_positioned = - flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED); + for kid in &mut self.items { + let base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow)); + let is_absolutely_positioned = base.flags.contains(IS_ABSOLUTELY_POSITIONED); if !is_absolutely_positioned { - computation.union_nonbreaking_inline(&flex_item_inline_sizes(kid)); + let flex_item_inline_sizes = IntrinsicISizes { + minimum_inline_size: base.intrinsic_inline_sizes.minimum_inline_size, + preferred_inline_size: base.intrinsic_inline_sizes.preferred_inline_size, + }; + computation.union_nonbreaking_inline(&flex_item_inline_sizes); } } } @@ -154,18 +158,17 @@ impl FlexFlow { let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); if !fixed_width { - for kid in self.block_flow.base.child_iter_mut() { - let is_absolutely_positioned = - flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED); - let child_base = flow::mut_base(kid); + for kid in &mut self.items { + let base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow)); + let is_absolutely_positioned = base.flags.contains(IS_ABSOLUTELY_POSITIONED); if !is_absolutely_positioned { computation.content_intrinsic_sizes.minimum_inline_size = max(computation.content_intrinsic_sizes.minimum_inline_size, - child_base.intrinsic_inline_sizes.minimum_inline_size); + base.intrinsic_inline_sizes.minimum_inline_size); computation.content_intrinsic_sizes.preferred_inline_size = max(computation.content_intrinsic_sizes.preferred_inline_size, - child_base.intrinsic_inline_sizes.preferred_inline_size); + base.intrinsic_inline_sizes.preferred_inline_size); } } } @@ -186,36 +189,33 @@ impl FlexFlow { // FIXME (mbrubeck): Get correct mode for absolute containing block let containing_block_mode = self.block_flow.base.writing_mode; - let mut iterator = self.block_flow.base.child_iter_mut().enumerate().peekable(); - while let Some((_, kid)) = iterator.next() { - { - let kid_base = flow::mut_base(kid); - kid_base.block_container_explicit_block_size = match self.available_main_size { - AxisSize::Definite(length) => Some(length), - _ => None - } - } - - // The inline-start margin edge of the child flow is at our inline-start content edge, - // and its inline-size is our content inline-size. - let kid_mode = flow::base(kid).writing_mode; + let container_block_size = match self.available_main_size { + AxisSize::Definite(length) => Some(length), + _ => None + }; + let container_inline_size = match self.available_cross_size { + AxisSize::Definite(length) => length, + AxisSize::MinMax(ref constraint) => constraint.clamp(content_inline_size), + AxisSize::Infinite => content_inline_size + }; + for kid in &mut self.items { { - let kid_base = flow::mut_base(kid); + let kid_base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow)); + kid_base.block_container_explicit_block_size = container_block_size; if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) { + // The inline-start margin edge of the child flow is at our inline-start content edge, + // and its inline-size is our content inline-size. kid_base.position.start.i = - if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() { + if kid_base.writing_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() { inline_start_content_edge } else { // The kid's inline 'start' is at the parent's 'end' inline_end_content_edge }; } - kid_base.block_container_inline_size = match self.available_main_size { - AxisSize::Definite(length) => length, - AxisSize::MinMax(ref constraint) => constraint.clamp(content_inline_size), - AxisSize::Infinite => content_inline_size, - }; + kid_base.block_container_inline_size = container_inline_size; kid_base.block_container_writing_mode = containing_block_mode; + kid_base.position.start.i = inline_start_content_edge; } } } @@ -247,25 +247,30 @@ impl FlexFlow { let even_content_inline_size = inline_size / child_count; - let inline_size = self.block_flow.base.block_container_inline_size; let container_mode = self.block_flow.base.block_container_writing_mode; self.block_flow.base.position.size.inline = inline_size; let block_container_explicit_block_size = self.block_flow.base.block_container_explicit_block_size; let mut inline_child_start = inline_start_content_edge; - for kid in self.block_flow.base.child_iter_mut() { - let kid_base = flow::mut_base(kid); + for kid in &mut self.items { + let base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow)); - kid_base.block_container_inline_size = even_content_inline_size; - kid_base.block_container_writing_mode = container_mode; - kid_base.block_container_explicit_block_size = block_container_explicit_block_size; - kid_base.position.start.i = inline_child_start; + base.block_container_inline_size = even_content_inline_size; + base.block_container_writing_mode = container_mode; + base.block_container_explicit_block_size = block_container_explicit_block_size; + base.position.start.i = inline_child_start; inline_child_start = inline_child_start + even_content_inline_size; } } // TODO(zentner): This function should actually flex elements! fn block_mode_assign_block_size<'a>(&mut self, layout_context: &'a LayoutContext<'a>) { + let mut cur_b = self.block_flow.fragment.border_padding.block_start; + for kid in &mut self.items { + let base = flow::mut_base(flow_ref::deref_mut(&mut kid.flow)); + base.position.start.b = cur_b; + cur_b = cur_b + base.position.size.block; + } self.block_flow.assign_block_size(layout_context) } @@ -334,6 +339,10 @@ impl Flow for FlexFlow { FlowClass::Flex } + fn as_block(&self) -> &BlockFlow { + &self.block_flow + } + fn as_mut_block(&mut self) -> &mut BlockFlow { &mut self.block_flow } @@ -351,8 +360,18 @@ impl Flow for FlexFlow { // Flexbox Section 9.1: Re-order the flex items (and any absolutely positioned flex // container children) according to their order. - // TODO(zentner): We need to re-order the items at some point. However, all the operations - // here ignore order, so we can afford to do it later, if necessary. + + let mut items = self.block_flow.base.children.iter_flow_ref_mut().map(|flow| { + FlexItem::new(flow.clone()) + }).collect::<Vec<FlexItem>>(); + + items.sort_by(|item1, item2| { + item1.flow.as_block().fragment.style.get_position().order.cmp( + &item2.flow.as_block().fragment.style.get_position().order + ) + }); + + self.items = items; match self.main_mode { Mode::Inline => self.inline_mode_bubble_inline_sizes(), diff --git a/components/layout/flow_list.rs b/components/layout/flow_list.rs index 37044008f7f..96f4d5ba7ef 100644 --- a/components/layout/flow_list.rs +++ b/components/layout/flow_list.rs @@ -64,6 +64,12 @@ impl FlowList { } } + /// Provide a forward iterator with FlowRef items + #[inline] + pub fn iter_flow_ref_mut<'a>(&'a mut self) -> linked_list::IterMut<'a, FlowRef> { + self.flows.iter_mut() + } + /// O(1) #[inline] pub fn is_empty(&self) -> bool { diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 439e8a79f60..03638be5fab 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -1029,12 +1029,15 @@ impl Fragment { fn style_specified_intrinsic_inline_size(&self) -> IntrinsicISizesContribution { let flags = self.quantities_included_in_intrinsic_inline_size(); let style = self.style(); - let specified = if flags.contains(INTRINSIC_INLINE_SIZE_INCLUDES_SPECIFIED) { - max(model::specified(style.min_inline_size(), Au(0)), - MaybeAuto::from_style(style.content_inline_size(), Au(0)).specified_or_zero()) - } else { - Au(0) - }; + let mut specified = Au(0); + + if flags.contains(INTRINSIC_INLINE_SIZE_INCLUDES_SPECIFIED) { + specified = MaybeAuto::from_style(style.content_inline_size(), Au(0)).specified_or_zero(); + specified = max(model::specified(style.min_inline_size(), Au(0)), specified); + if let Some(max) = model::specified_or_none(style.max_inline_size(), Au(0)) { + specified = min(specified, max) + } + } // FIXME(#2261, pcwalton): This won't work well for inlines: is this OK? let surrounding_inline_size = self.surrounding_intrinsic_inline_size(); @@ -1375,7 +1378,7 @@ impl Fragment { result.union_block(&block_flow.base.intrinsic_inline_sizes) } SpecificFragmentInfo::Image(ref mut image_fragment_info) => { - let image_inline_size = match self.style.content_inline_size() { + let mut image_inline_size = match self.style.content_inline_size() { LengthOrPercentageOrAuto::Auto | LengthOrPercentageOrAuto::Percentage(_) => { image_fragment_info.image_inline_size() @@ -1383,13 +1386,19 @@ impl Fragment { LengthOrPercentageOrAuto::Length(length) => length, LengthOrPercentageOrAuto::Calc(calc) => calc.length(), }; + + image_inline_size = max(model::specified(self.style.min_inline_size(), Au(0)), image_inline_size); + if let Some(max) = model::specified_or_none(self.style.max_inline_size(), Au(0)) { + image_inline_size = min(image_inline_size, max) + } + result.union_block(&IntrinsicISizes { minimum_inline_size: image_inline_size, preferred_inline_size: image_inline_size, }); } SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => { - let canvas_inline_size = match self.style.content_inline_size() { + let mut canvas_inline_size = match self.style.content_inline_size() { LengthOrPercentageOrAuto::Auto | LengthOrPercentageOrAuto::Percentage(_) => { canvas_fragment_info.canvas_inline_size() @@ -1397,6 +1406,12 @@ impl Fragment { LengthOrPercentageOrAuto::Length(length) => length, LengthOrPercentageOrAuto::Calc(calc) => calc.length(), }; + + canvas_inline_size = max(model::specified(self.style.min_inline_size(), Au(0)), canvas_inline_size); + if let Some(max) = model::specified_or_none(self.style.max_inline_size(), Au(0)) { + canvas_inline_size = min(canvas_inline_size, max) + } + result.union_block(&IntrinsicISizes { minimum_inline_size: canvas_inline_size, preferred_inline_size: canvas_inline_size, diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index fcf0e204a0d..1d21ab4e462 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -28,6 +28,7 @@ trait WebRenderStackingContextConverter { pipeline_id: webrender_traits::PipelineId, epoch: webrender_traits::Epoch, scroll_layer_id: Option<webrender_traits::ScrollLayerId>, + scroll_policy: ScrollPolicy, frame_builder: &mut WebRenderFrameBuilder) -> webrender_traits::StackingContextId; @@ -37,6 +38,7 @@ trait WebRenderStackingContextConverter { pipeline_id: webrender_traits::PipelineId, epoch: webrender_traits::Epoch, scroll_layer_id: Option<webrender_traits::ScrollLayerId>, + scroll_policy: ScrollPolicy, builder: &mut webrender_traits::DisplayListBuilder, frame_builder: &mut WebRenderFrameBuilder, force_positioned_stacking_level: bool); @@ -276,6 +278,7 @@ impl WebRenderStackingContextConverter for StackingContext { pipeline_id: webrender_traits::PipelineId, epoch: webrender_traits::Epoch, scroll_layer_id: Option<webrender_traits::ScrollLayerId>, + scroll_policy: ScrollPolicy, builder: &mut webrender_traits::DisplayListBuilder, frame_builder: &mut WebRenderFrameBuilder, force_positioned_stacking_level: bool) { @@ -295,6 +298,7 @@ impl WebRenderStackingContextConverter for StackingContext { pipeline_id, epoch, None, + scroll_policy, frame_builder); builder.push_stacking_context(child.web_render_stacking_level(), stacking_context_id); @@ -304,6 +308,7 @@ impl WebRenderStackingContextConverter for StackingContext { pipeline_id, epoch, scroll_layer_id, + scroll_policy, builder, frame_builder, true); @@ -323,19 +328,21 @@ impl WebRenderStackingContextConverter for StackingContext { pipeline_id: webrender_traits::PipelineId, epoch: webrender_traits::Epoch, scroll_layer_id: Option<webrender_traits::ScrollLayerId>, + mut scroll_policy: ScrollPolicy, frame_builder: &mut WebRenderFrameBuilder) -> webrender_traits::StackingContextId { - let scroll_policy = self.layer_info - .map_or(webrender_traits::ScrollPolicy::Scrollable, |info| { - match info.scroll_policy { - ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable, - ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed, - } - }); + if let Some(ref layer_info) = self.layer_info { + scroll_policy = layer_info.scroll_policy + } + + let webrender_scroll_policy = match scroll_policy { + ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable, + ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed, + }; let mut sc = webrender_traits::StackingContext::new(scroll_layer_id, - scroll_policy, + webrender_scroll_policy, self.bounds.to_rectf(), self.overflow.to_rectf(), self.z_index, @@ -351,6 +358,7 @@ impl WebRenderStackingContextConverter for StackingContext { pipeline_id, epoch, scroll_layer_id, + scroll_policy, &mut builder, frame_builder, false); @@ -386,6 +394,7 @@ impl WebRenderDisplayListConverter for DisplayList { pipeline_id, epoch, scroll_layer_id, + ScrollPolicy::Scrollable, frame_builder) } } diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index ad8ce2f5141..e76af843ea0 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -1050,7 +1050,7 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> { return TextContent::Text(data); } if let Some(input) = this.downcast::<HTMLInputElement>() { - let data = unsafe { input.get_value_for_layout() }; + let data = unsafe { input.value_for_layout() }; return TextContent::Text(data); } if let Some(area) = this.downcast::<HTMLTextAreaElement>() { @@ -1076,7 +1076,7 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> { } } if let Some(input) = this.downcast::<HTMLInputElement>() { - if let Some(selection) = unsafe { input.get_selection_for_layout() } { + if let Some(selection) = unsafe { input.selection_for_layout() } { return Some(Range::new(CharIndex(selection.begin()), CharIndex(selection.length()))); } diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index 58a60da2bb1..955ceb24fcb 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -44,6 +44,7 @@ openssl = "0.7.6" rustc-serialize = "0.3" threadpool = "1.0" time = "0.1.17" +unicase = "1.4.0" url = {version = "0.5.7", features = ["heap_size"]} uuid = { version = "0.2", features = ["v4"] } websocket = "0.16.1" diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index d99dc3f10e4..76140b1245f 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -5,12 +5,12 @@ use data_loader::decode; use fetch::cors_cache::{BasicCORSCache, CORSCache, CacheRequestDetails}; use http_loader::{NetworkHttpRequestFactory, create_http_connector, obtain_response}; -use hyper::header::{Accept, CacheControl, IfMatch, IfRange, IfUnmodifiedSince, Location}; -use hyper::header::{AcceptLanguage, ContentLength, ContentLanguage, HeaderView, Pragma}; -use hyper::header::{AccessControlAllowCredentials, AccessControlAllowOrigin}; -use hyper::header::{Authorization, Basic, CacheDirective, ContentEncoding, Encoding}; -use hyper::header::{ContentType, Headers, IfModifiedSince, IfNoneMatch}; -use hyper::header::{QualityItem, q, qitem, Referer as RefererHeader, UserAgent}; +use hyper::header::{Accept, AcceptLanguage, Authorization, AccessControlAllowCredentials}; +use hyper::header::{AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlAllowMethods}; +use hyper::header::{AccessControlRequestHeaders, AccessControlMaxAge, AccessControlRequestMethod, Basic}; +use hyper::header::{CacheControl, CacheDirective, ContentEncoding, ContentLength, ContentLanguage, ContentType}; +use hyper::header::{Encoding, HeaderView, Headers, IfMatch, IfRange, IfUnmodifiedSince, IfModifiedSince}; +use hyper::header::{IfNoneMatch, Pragma, Location, QualityItem, Referer as RefererHeader, UserAgent, q, qitem}; use hyper::method::Method; use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper::status::StatusCode; @@ -20,9 +20,12 @@ use net_traits::request::{RedirectMode, Referer, Request, RequestMode, ResponseT use net_traits::response::{HttpsState, TerminationReason}; use net_traits::response::{Response, ResponseBody, ResponseType}; use resource_thread::CancellationListener; +use std::collections::HashSet; use std::io::Read; +use std::iter::FromIterator; use std::rc::Rc; use std::thread; +use unicase::UniCase; use url::idna::domain_to_ascii; use url::{Origin as UrlOrigin, OpaqueOrigin, Url, UrlParser, whatwg_scheme_type_mapper}; use util::thread::spawn_named; @@ -210,7 +213,7 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re let internal_response = if response.is_network_error() { &network_error_res } else { - response.get_actual_response() + response.actual_response() }; // Step 13 @@ -245,7 +248,7 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re // Step 16 if request.synchronous { - response.get_actual_response().wait_until_done(); + response.actual_response().wait_until_done(); return response; } @@ -263,7 +266,7 @@ fn main_fetch(request: Rc<Request>, cors_flag: bool, recursive_flag: bool) -> Re let internal_response = if response.is_network_error() { &network_error_res } else { - response.get_actual_response() + response.actual_response() }; // Step 18 @@ -365,7 +368,7 @@ fn http_fetch(request: Rc<Request>, } // Substep 4 - let actual_response = res.get_actual_response(); + let actual_response = res.actual_response(); if actual_response.url_list.borrow().is_empty() { *actual_response.url_list.borrow_mut() = request.url_list.borrow().clone(); } @@ -390,7 +393,7 @@ fn http_fetch(request: Rc<Request>, }, request.method.borrow().clone()); let method_mismatch = !method_cache_match && (!is_simple_method(&request.method.borrow()) || - request.use_cors_preflight); + request.use_cors_preflight); let header_mismatch = request.headers.borrow().iter().any(|view| !cache.match_header(CacheRequestDetails { origin: origin.clone(), @@ -401,7 +404,7 @@ fn http_fetch(request: Rc<Request>, // Sub-substep 1 if method_mismatch || header_mismatch { - let preflight_result = preflight_fetch(request.clone()); + let preflight_result = cors_preflight_fetch(request.clone(), Some(cache)); // Sub-substep 2 if preflight_result.response_type == ResponseType::Error { return Response::network_error(); @@ -415,8 +418,7 @@ fn http_fetch(request: Rc<Request>, // Substep 3 let credentials = match request.credentials_mode { CredentialsMode::Include => true, - CredentialsMode::CredentialsSameOrigin if - request.response_tainting.get() == ResponseTainting::Basic + CredentialsMode::CredentialsSameOrigin if request.response_tainting.get() == ResponseTainting::Basic => true, _ => false }; @@ -437,7 +439,7 @@ fn http_fetch(request: Rc<Request>, let mut response = response.unwrap(); // Step 5 - match response.get_actual_response().status.unwrap() { + match response.actual_response().status.unwrap() { // Code 301, 302, 303, 307, 308 StatusCode::MovedPermanently | StatusCode::Found | StatusCode::SeeOther | @@ -518,21 +520,21 @@ fn http_redirect_fetch(request: Rc<Request>, assert_eq!(response.return_internal.get(), true); // Step 3 - // this step is done early, because querying if Location is available says + // this step is done early, because querying if Location exists says // if it is None or Some, making it easy to seperate from the retrieval failure case - if !response.get_actual_response().headers.has::<Location>() { + if !response.actual_response().headers.has::<Location>() { return Rc::try_unwrap(response).ok().unwrap(); } // Step 2 - let location = match response.get_actual_response().headers.get::<Location>() { + let location = match response.actual_response().headers.get::<Location>() { Some(&Location(ref location)) => location.clone(), // Step 4 _ => return Response::network_error() }; // Step 5 - let response_url = response.get_actual_response().url.as_ref().unwrap(); + let response_url = response.actual_response().url.as_ref().unwrap(); let location_url = UrlParser::new().base_url(response_url).parse(&*location); // Step 6 @@ -575,7 +577,7 @@ fn http_redirect_fetch(request: Rc<Request>, } // Step 13 - let status_code = response.get_actual_response().status.unwrap(); + let status_code = response.actual_response().status.unwrap(); if ((status_code == StatusCode::MovedPermanently || status_code == StatusCode::Found) && *request.method.borrow() == Method::Post) || status_code == StatusCode::SeeOther { @@ -876,11 +878,11 @@ fn http_network_fetch(request: Rc<Request>, // Substep 2 - // TODO how can I tell if response was retrieved over HTTPS? + // TODO Determine if response was retrieved over HTTPS // TODO Servo needs to decide what ciphers are to be treated as "deprecated" response.https_state = HttpsState::None; - // TODO how do I read request? + // TODO Read request // Step 5 // TODO when https://bugzilla.mozilla.org/show_bug.cgi?id=1030660 @@ -925,8 +927,113 @@ fn http_network_fetch(request: Rc<Request>, } /// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch) -fn preflight_fetch(_request: Rc<Request>) -> Response { - // TODO: Implement preflight fetch spec +fn cors_preflight_fetch(request: Rc<Request>, cache: Option<BasicCORSCache>) -> Response { + // Step 1 + let mut preflight = Request::new(request.current_url(), Some(request.origin.borrow().clone()), false); + *preflight.method.borrow_mut() = Method::Options; + preflight.initiator = request.initiator.clone(); + preflight.type_ = request.type_.clone(); + preflight.destination = request.destination.clone(); + preflight.referer = request.referer.clone(); + + // Step 2 + preflight.headers.borrow_mut().set::<AccessControlRequestMethod>( + AccessControlRequestMethod(request.method.borrow().clone())); + + // Step 3, 4 + let mut value = request.headers.borrow().iter() + .filter_map(|ref view| if is_simple_header(view) { + None + } else { + Some(UniCase(view.name().to_owned())) + }).collect::<Vec<UniCase<String>>>(); + value.sort(); + + // Step 5 + preflight.headers.borrow_mut().set::<AccessControlRequestHeaders>( + AccessControlRequestHeaders(value)); + + // Step 6 + let preflight = Rc::new(preflight); + let response = http_network_or_cache_fetch(preflight.clone(), false, false); + + // Step 7 + if cors_check(request.clone(), &response).is_ok() && + response.status.map_or(false, |status| status.is_success()) { + // Substep 1 + let mut methods = if response.headers.has::<AccessControlAllowMethods>() { + match response.headers.get::<AccessControlAllowMethods>() { + Some(&AccessControlAllowMethods(ref m)) => m.clone(), + // Substep 3 + None => return Response::network_error() + } + } else { + vec![] + }; + + // Substep 2 + let header_names = if response.headers.has::<AccessControlAllowHeaders>() { + match response.headers.get::<AccessControlAllowHeaders>() { + Some(&AccessControlAllowHeaders(ref hn)) => hn.clone(), + // Substep 3 + None => return Response::network_error() + } + } else { + vec![] + }; + + // Substep 4 + if methods.is_empty() && request.use_cors_preflight { + methods = vec![request.method.borrow().clone()]; + } + + // Substep 5 + if methods.iter().all(|method| *method != *request.method.borrow()) && + !is_simple_method(&*request.method.borrow()) { + return Response::network_error(); + } + + // Substep 6 + let set: HashSet<&UniCase<String>> = HashSet::from_iter(header_names.iter()); + if request.headers.borrow().iter().any(|ref hv| !set.contains(&UniCase(hv.name().to_owned())) && + !is_simple_header(hv)) { + return Response::network_error(); + } + + // Substep 7, 8 + let max_age = response.headers.get::<AccessControlMaxAge>().map(|acma| acma.0).unwrap_or(0); + + // TODO: Substep 9 - Need to define what an imposed limit on max-age is + + // Substep 10 + let mut cache = match cache { + Some(c) => c, + None => return response + }; + + // Substep 11, 12 + for method in &methods { + cache.match_method_and_update(CacheRequestDetails { + origin: request.origin.borrow().clone(), + destination: request.current_url(), + credentials: request.credentials_mode == CredentialsMode::Include + }, method.clone(), max_age); + } + + // Substep 13, 14 + for header_name in &header_names { + cache.match_header_and_update(CacheRequestDetails { + origin: request.origin.borrow().clone(), + destination: request.current_url(), + credentials: request.credentials_mode == CredentialsMode::Include + }, &*header_name, max_age); + } + + // Substep 15 + return response; + } + + // Step 8 Response::network_error() } @@ -934,7 +1041,6 @@ fn preflight_fetch(_request: Rc<Request>) -> Response { fn cors_check(request: Rc<Request>, response: &Response) -> Result<(), ()> { // Step 1 - // let headers = request.headers.borrow(); let origin = response.headers.get::<AccessControlAllowOrigin>().cloned(); // Step 2 @@ -942,18 +1048,18 @@ fn cors_check(request: Rc<Request>, response: &Response) -> Result<(), ()> { // Step 3 if request.credentials_mode != CredentialsMode::Include && - origin == AccessControlAllowOrigin::Any { + origin == AccessControlAllowOrigin::Any { return Ok(()); } // Step 4 let origin = match origin { AccessControlAllowOrigin::Value(origin) => origin, - // if it's Any or Null at this point, I see nothing to do but return Err(()) + // if it's Any or Null at this point, there's nothing to do but return Err(()) _ => return Err(()) }; - // strings are already utf-8 encoded, so I don't need to re-encode origin for this step + // strings are already utf-8 encoded, so there's no need to re-encode origin for this step match ascii_serialise_origin(&request.origin.borrow()) { Ok(request_origin) => { if request_origin != origin { diff --git a/components/net/lib.rs b/components/net/lib.rs index dafb7f55c47..47342299130 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -29,6 +29,7 @@ extern crate openssl; extern crate rustc_serialize; extern crate threadpool; extern crate time; +extern crate unicase; extern crate url; extern crate util; extern crate uuid; @@ -49,7 +50,7 @@ pub mod resource_thread; pub mod storage_thread; pub mod websocket_loader; -/// An implementation of the [Fetch spec](https://fetch.spec.whatwg.org/) +/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/) pub mod fetch { pub mod cors_cache; pub mod methods; diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index c22a270c03f..d8cdd4213f0 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -24,7 +24,7 @@ path = "../plugins" heapsize = "0.3.0" heapsize_plugin = "0.1.2" hyper = { version = "0.8", features = [ "serde-serialization" ] } -image = "0.7" +image = "0.9" lazy_static = "0.1.15" log = "0.3.5" serde = "0.7" diff --git a/components/net_traits/response.rs b/components/net_traits/response.rs index 9e6cedd2765..1c1796df52a 100644 --- a/components/net_traits/response.rs +++ b/components/net_traits/response.rs @@ -144,7 +144,7 @@ impl Response { } } - pub fn get_actual_response(&self) -> &Response { + pub fn actual_response(&self) -> &Response { if self.return_internal.get() && self.internal_response.is_some() { &**self.internal_response.as_ref().unwrap() } else { diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 6a8a5d1b25e..9fda41e036f 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -75,7 +75,7 @@ heapsize = "0.3.0" heapsize_plugin = "0.1.2" html5ever = {version = "0.5.1", features = ["heap_size", "unstable"]} hyper = { version = "0.8", features = [ "serde-serialization" ] } -image = "0.7" +image = "0.9" libc = "0.2" log = "0.3.5" num = "0.1.24" @@ -91,7 +91,7 @@ rustc-serialize = "0.3" selectors = {version = "0.5", features = ["heap_size"]} serde = "0.7" smallvec = "0.1" -string_cache = {version = "0.2.11", features = ["heap_size", "unstable"]} +string_cache = {version = "0.2.12", features = ["heap_size", "unstable"]} time = "0.1.12" unicase = "1.0" url = {version = "0.5.7", features = ["heap_size"]} diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 51c29764125..57b7be5c7bb 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -3800,22 +3800,6 @@ class CGUnionConversionStruct(CGThing): pre="impl FromJSValConvertible for %s {\n" % self.type, post="\n}") - conversions.append(CGGeneric( - "throw_not_in_union(cx, \"%s\");\n" - "Err(())" % ", ".join(names))) - method = CGWrapper( - CGIndenter(CGList(conversions, "\n\n")), - pre="unsafe fn from_jsval(cx: *mut JSContext,\n" - " value: HandleValue, _option: ()) -> Result<%s, ()> {\n" % self.type, - post="\n}") - return CGWrapper( - CGIndenter(CGList([ - CGGeneric("type Config = ();"), - method, - ], "\n")), - pre="impl FromJSValConvertible for %s {\n" % self.type, - post="\n}") - def try_method(self, t): templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider) returnType = "Result<Option<%s>, ()>" % templateVars["typeName"] diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index d171715d474..10b9a481382 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -566,7 +566,7 @@ impl<T: Castable> Root<T> { impl<T: Reflectable> Root<T> { /// Create a new stack-bounded root for the provided JS-owned value. - /// It cannot not outlive its associated `RootCollection`, and it gives + /// It cannot outlive its associated `RootCollection`, and it gives /// out references which cannot outlive this new `Root`. pub fn new(unrooted: NonZero<*const T>) -> Root<T> { debug_assert!(thread_state::get().is_script()); diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 9cc2d13fb77..50c3fbf682f 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -62,6 +62,7 @@ use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread}; use net_traits::response::HttpsState; use net_traits::storage_thread::StorageType; +use offscreen_gl_context::GLLimits; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; use script_runtime::ScriptChan; @@ -88,6 +89,7 @@ use style::properties::PropertyDeclarationBlock; use style::restyle_hints::ElementSnapshot; use style::selector_impl::PseudoElement; use style::values::specified::Length; +use url::Origin as UrlOrigin; use url::Url; use util::str::{DOMString, LengthOrPercentageOrAuto}; use uuid::Uuid; @@ -275,7 +277,7 @@ impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A, B, C) { } } -no_jsmanaged_fields!(bool, f32, f64, String, Url, AtomicBool, AtomicUsize, Uuid); +no_jsmanaged_fields!(bool, f32, f64, String, Url, AtomicBool, AtomicUsize, UrlOrigin, Uuid); no_jsmanaged_fields!(usize, u8, u16, u32, u64); no_jsmanaged_fields!(isize, i8, i16, i32, i64); no_jsmanaged_fields!(Sender<T>); @@ -308,7 +310,7 @@ no_jsmanaged_fields!(StorageType); no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle); no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending); no_jsmanaged_fields!(RepetitionStyle); -no_jsmanaged_fields!(WebGLError); +no_jsmanaged_fields!(WebGLError, GLLimits); no_jsmanaged_fields!(TimeProfilerChan); no_jsmanaged_fields!(MemProfilerChan); no_jsmanaged_fields!(PseudoElement); diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index aa5c7d9f72b..492b98f0edf 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -19,7 +19,7 @@ use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::UnionTypes::HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D; use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern; -use dom::bindings::error::{Error, Fallible}; +use dom::bindings::error::{Error, Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, LayoutJS, Root}; @@ -277,7 +277,7 @@ impl CanvasRenderingContext2D { dy: f64, dw: Option<f64>, dh: Option<f64>) - -> Fallible<()> { + -> ErrorResult { let result = match image { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLCanvasElement(ref canvas) => { self.draw_html_canvas_element(canvas.r(), @@ -333,7 +333,7 @@ impl CanvasRenderingContext2D { dy: f64, dw: Option<f64>, dh: Option<f64>) - -> Fallible<()> { + -> ErrorResult { // 1. Check the usability of the image argument if !canvas.is_valid() { return Err(Error::InvalidState); @@ -408,7 +408,7 @@ impl CanvasRenderingContext2D { dy: f64, dw: f64, dh: f64) - -> Fallible<()> { + -> ErrorResult { // Establish the source and destination rectangles let (source_rect, dest_rect) = self.adjust_source_dest_rects(image_size, sx, @@ -742,7 +742,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, dx: f64, dy: f64) - -> Fallible<()> { + -> ErrorResult { if !(dx.is_finite() && dy.is_finite()) { return Ok(()); } @@ -757,7 +757,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dy: f64, dw: f64, dh: f64) - -> Fallible<()> { + -> ErrorResult { if !(dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { return Ok(()); } @@ -776,7 +776,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dy: f64, dw: f64, dh: f64) - -> Fallible<()> { + -> ErrorResult { if !(sx.is_finite() && sy.is_finite() && sw.is_finite() && sh.is_finite() && dx.is_finite() && dy.is_finite() && dw.is_finite() && dh.is_finite()) { return Ok(()); @@ -852,7 +852,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc - fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> Fallible<()> { + fn Arc(&self, x: f64, y: f64, r: f64, start: f64, end: f64, ccw: bool) -> ErrorResult { if !([x, y, r, start, end].iter().all(|x| x.is_finite())) { return Ok(()); } @@ -872,7 +872,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto - fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> Fallible<()> { + fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult { if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) { return Ok(()); } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index ad68be7175f..723e461df30 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -94,6 +94,7 @@ use net_traits::CookieSource::NonHTTP; use net_traits::response::HttpsState; use net_traits::{AsyncResponseTarget, PendingAsyncLoad}; use num::ToPrimitive; +use origin::Origin; use script_runtime::ScriptChan; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable}; use script_traits::UntrustedNodeAddress; @@ -209,18 +210,22 @@ pub struct Document { modified_elements: DOMRefCell<HashMap<JS<Element>, ElementSnapshot>>, /// http://w3c.github.io/touch-events/#dfn-active-touch-point active_touch_points: DOMRefCell<Vec<JS<Touch>>>, - /// DOM-Related Navigation Timing properties: - /// http://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domLoading + /// Navigation Timing properties: + /// https://w3c.github.io/navigation-timing/#sec-PerformanceNavigationTiming dom_loading: Cell<u64>, dom_interactive: Cell<u64>, dom_content_loaded_event_start: Cell<u64>, dom_content_loaded_event_end: Cell<u64>, dom_complete: Cell<u64>, + load_event_start: Cell<u64>, + load_event_end: Cell<u64>, /// Vector to store CSS errors css_errors_store: DOMRefCell<Vec<CSSError>>, /// https://html.spec.whatwg.org/multipage/#concept-document-https-state https_state: Cell<HttpsState>, touchpad_pressure_phase: Cell<TouchpadPressurePhase>, + /// The document's origin. + origin: Origin, } #[derive(JSTraceable, HeapSizeOf)] @@ -544,14 +549,14 @@ impl Document { DocumentReadyState::Loading => { // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserconnected self.trigger_mozbrowser_event(MozBrowserEvent::Connected); - update_with_current_time(&self.dom_loading); + update_with_current_time_ms(&self.dom_loading); }, DocumentReadyState::Complete => { // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadend self.trigger_mozbrowser_event(MozBrowserEvent::LoadEnd); - update_with_current_time(&self.dom_complete); + update_with_current_time_ms(&self.dom_complete); }, - DocumentReadyState::Interactive => update_with_current_time(&self.dom_interactive), + DocumentReadyState::Interactive => update_with_current_time_ms(&self.dom_interactive), }; self.ready_state.set(state); @@ -1447,7 +1452,7 @@ impl Document { } self.domcontentloaded_dispatched.set(true); - update_with_current_time(&self.dom_content_loaded_event_start); + update_with_current_time_ms(&self.dom_content_loaded_event_start); let chan = MainThreadScriptChan(self.window().main_thread_script_chan().clone()).clone(); let doctarget = Trusted::new(self.upcast::<EventTarget>(), chan); @@ -1458,7 +1463,7 @@ impl Document { ReflowQueryType::NoQuery, ReflowReason::DOMContentLoaded); - update_with_current_time(&self.dom_content_loaded_event_end); + update_with_current_time_ms(&self.dom_content_loaded_event_end); } pub fn notify_constellation_load(&self) { @@ -1513,6 +1518,14 @@ impl Document { self.dom_complete.get() } + pub fn get_load_event_start(&self) -> u64 { + self.load_event_start.get() + } + + pub fn get_load_event_end(&self) -> u64 { + self.load_event_end.get() + } + // https://html.spec.whatwg.org/multipage/#fire-a-focus-event fn fire_focus_event(&self, focus_event_type: FocusEventType, node: &Node, relatedTarget: Option<&EventTarget>) { let (event_name, does_bubble) = match focus_event_type { @@ -1534,14 +1547,6 @@ impl Document { /// https://html.spec.whatwg.org/multipage/#cookie-averse-document-object fn is_cookie_averse(&self) -> bool { - /// https://url.spec.whatwg.org/#network-scheme - fn url_has_network_scheme(url: &Url) -> bool { - match &*url.scheme { - "ftp" | "http" | "https" => true, - _ => false, - } - } - self.browsing_context.is_none() || !url_has_network_scheme(&self.url) } @@ -1580,6 +1585,14 @@ impl LayoutDocumentHelpers for LayoutJS<Document> { } } +/// https://url.spec.whatwg.org/#network-scheme +fn url_has_network_scheme(url: &Url) -> bool { + match &*url.scheme { + "ftp" | "http" | "https" => true, + _ => false, + } +} + impl Document { pub fn new_inherited(window: &Window, browsing_context: Option<&BrowsingContext>, @@ -1598,6 +1611,15 @@ impl Document { (DocumentReadyState::Complete, true) }; + // Incomplete implementation of Document origin specification at + // https://html.spec.whatwg.org/multipage/#origin:document + let origin = if url_has_network_scheme(&url) { + Origin::new(&url) + } else { + // Default to DOM standard behaviour + Origin::opaque_identifier() + }; + Document { node: Node::new_document_node(), window: JS::from_ref(window), @@ -1658,9 +1680,12 @@ impl Document { dom_content_loaded_event_start: Cell::new(Default::default()), dom_content_loaded_event_end: Cell::new(Default::default()), dom_complete: Cell::new(Default::default()), + load_event_start: Cell::new(Default::default()), + load_event_end: Cell::new(Default::default()), css_errors_store: DOMRefCell::new(vec![]), https_state: Cell::new(HttpsState::None), touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick), + origin: origin, } } @@ -1856,9 +1881,18 @@ impl DocumentMethods for Document { // https://html.spec.whatwg.org/multipage/#relaxing-the-same-origin-restriction fn Domain(&self) -> DOMString { - // TODO: This should use the effective script origin when it exists - let origin = self.window.get_url(); - DOMString::from(origin.serialize_host().unwrap_or_else(|| "".to_owned())) + // Step 1. + if self.browsing_context().is_none() { + return DOMString::new(); + } + + if let Some(host) = self.origin.host() { + // Step 4. + DOMString::from(host.serialize()) + } else { + // Step 3. + DOMString::new() + } } // https://dom.spec.whatwg.org/#dom-document-documenturi @@ -2485,10 +2519,11 @@ impl DocumentMethods for Document { return Ok(DOMString::new()); } - let url = self.url(); - if !is_scheme_host_port_tuple(&url) { + if !self.origin.is_scheme_host_port_tuple() { return Err(Error::Security); } + + let url = self.url(); let (tx, rx) = ipc::channel().unwrap(); let _ = self.window.resource_thread().send(GetCookiesForUrl((*url).clone(), tx, NonHTTP)); let cookies = rx.recv().unwrap(); @@ -2501,10 +2536,11 @@ impl DocumentMethods for Document { return Ok(()); } - let url = self.url(); - if !is_scheme_host_port_tuple(url) { + if !self.origin.is_scheme_host_port_tuple() { return Err(Error::Security); } + + let url = self.url(); let _ = self.window .resource_thread() .send(SetCookiesForUrl((*url).clone(), String::from(cookie), NonHTTP)); @@ -2708,13 +2744,10 @@ impl DocumentMethods for Document { } } -fn is_scheme_host_port_tuple(url: &Url) -> bool { - url.host().is_some() && url.port_or_default().is_some() -} - -fn update_with_current_time(marker: &Cell<u64>) { +fn update_with_current_time_ms(marker: &Cell<u64>) { if marker.get() == Default::default() { - let current_time_ms = time::get_time().sec * 1000; + let time = time::get_time(); + let current_time_ms = time.sec * 1000 + time.nsec as i64 / 1000000; marker.set(current_time_ms as u64); } } @@ -2744,8 +2777,15 @@ impl DocumentProgressHandler { EventCancelable::NotCancelable); let wintarget = window.upcast::<EventTarget>(); event.set_trusted(true); + + // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventStart + update_with_current_time_ms(&document.load_event_start); + let _ = wintarget.dispatch_event_with_target(document.upcast(), &event); + // http://w3c.github.io/navigation-timing/#widl-PerformanceNavigationTiming-loadEventEnd + update_with_current_time_ms(&document.load_event_end); + document.notify_constellation_load(); window.reflow(ReflowGoal::ForDisplay, diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4e2af78f31a..e14e1af0d97 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -377,7 +377,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { }, // Others _ => { - match this.get_size_for_layout() { + match this.size_for_layout() { 0 => None, s => Some(s as i32), } @@ -571,7 +571,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { // TODO option and menuitem can also have a checked state. match self.downcast::<HTMLInputElement>() { Some(input) => unsafe { - input.get_checked_state_for_layout() + input.checked_state_for_layout() }, None => false, } @@ -583,7 +583,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { // TODO progress elements can also be matched with :indeterminate match self.downcast::<HTMLInputElement>() { Some(input) => unsafe { - input.get_indeterminate_state_for_layout() + input.indeterminate_state_for_layout() }, None => false, } @@ -1489,7 +1489,7 @@ impl ElementMethods for Element { } /// https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML - fn SetInnerHTML(&self, value: DOMString) -> Fallible<()> { + fn SetInnerHTML(&self, value: DOMString) -> ErrorResult { let context_node = self.upcast::<Node>(); // Step 1. let frag = try!(context_node.parse_fragment(value)); @@ -1510,7 +1510,7 @@ impl ElementMethods for Element { } // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML - fn SetOuterHTML(&self, value: DOMString) -> Fallible<()> { + fn SetOuterHTML(&self, value: DOMString) -> ErrorResult { let context_document = document_from_node(self); let context_node = self.upcast::<Node>(); // Step 1. diff --git a/components/script/dom/htmlbaseelement.rs b/components/script/dom/htmlbaseelement.rs index 7f1ce7641d3..241c209c7a8 100644 --- a/components/script/dom/htmlbaseelement.rs +++ b/components/script/dom/htmlbaseelement.rs @@ -2,8 +2,9 @@ * 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::attr::Attr; +use dom::attr::{Attr, AttrValue}; use dom::bindings::codegen::Bindings::HTMLBaseElementBinding; +use dom::bindings::codegen::Bindings::HTMLBaseElementBinding::HTMLBaseElementMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::document::Document; @@ -60,6 +61,33 @@ impl HTMLBaseElement { } } +impl HTMLBaseElementMethods for HTMLBaseElement { + // https://html.spec.whatwg.org/multipage/#dom-base-href + fn Href(&self) -> DOMString { + let document = document_from_node(self); + + // Step 1. + if !self.upcast::<Element>().has_attribute(&atom!("href")) { + return DOMString::from(document.base_url().serialize()); + } + + // Step 2. + let fallback_base_url = document.fallback_base_url(); + + // Step 3. + let url = self.upcast::<Element>().get_url_attribute(&atom!("href")); + + // Step 4. + let url_record = fallback_base_url.join(&*url); + + // Step 5, 6. + DOMString::from(url_record.ok().map_or("".to_owned(), |record| record.serialize())) + } + + // https://html.spec.whatwg.org/multipage/#dom-base-href + make_url_setter!(SetHref, "href"); +} + impl VirtualMethods for HTMLBaseElement { fn super_type(&self) -> Option<&VirtualMethods> { Some(self.upcast::<HTMLElement>() as &VirtualMethods) diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 70a2a7ad730..3e7421de443 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -414,7 +414,7 @@ impl HTMLFormElement { HTMLElementTypeId::HTMLInputElement => { let input = child.downcast::<HTMLInputElement>().unwrap(); // Step 3.2-3.7 - if let Some(datum) = input.get_form_datum(submitter) { + if let Some(datum) = input.form_datum(submitter) { data_set.push(datum); } } diff --git a/components/script/dom/htmlhrelement.rs b/components/script/dom/htmlhrelement.rs index 93fdebbc954..bea12efbfea 100644 --- a/components/script/dom/htmlhrelement.rs +++ b/components/script/dom/htmlhrelement.rs @@ -37,6 +37,12 @@ impl HTMLHRElement { } impl HTMLHRElementMethods for HTMLHRElement { + // https://html.spec.whatwg.org/multipage/#dom-hr-align + make_getter!(Align, "align"); + + // https://html.spec.whatwg.org/multipage/#dom-hr-align + make_atomic_setter!(SetAlign, "align"); + // https://html.spec.whatwg.org/multipage/#dom-hr-color make_getter!(Color, "color"); @@ -86,6 +92,7 @@ impl VirtualMethods for HTMLHRElement { fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { match name { + &atom!("align") => AttrValue::from_dimension(value), &atom!("color") => AttrValue::from_legacy_color(value), &atom!("width") => AttrValue::from_dimension(value), _ => self.super_type().unwrap().parse_plain_attribute(name, value), diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index beb3134698f..7273e063e0b 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -367,7 +367,7 @@ impl MozBrowserEventDetailBuilder for HTMLIFrameElement { } } -pub fn Navigate(iframe: &HTMLIFrameElement, direction: NavigationDirection) -> Fallible<()> { +pub fn Navigate(iframe: &HTMLIFrameElement, direction: NavigationDirection) -> ErrorResult { if iframe.Mozbrowser() { if iframe.upcast::<Node>().is_in_doc() { let window = window_from_node(iframe); @@ -468,17 +468,17 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement { } // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goBack - fn GoBack(&self) -> Fallible<()> { + fn GoBack(&self) -> ErrorResult { Navigate(self, NavigationDirection::Back) } // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goForward - fn GoForward(&self) -> Fallible<()> { + fn GoForward(&self) -> ErrorResult { Navigate(self, NavigationDirection::Forward) } // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/reload - fn Reload(&self, _hardReload: bool) -> Fallible<()> { + fn Reload(&self, _hardReload: bool) -> ErrorResult { if self.Mozbrowser() { if self.upcast::<Node>().is_in_doc() { self.navigate_or_reload_child_browsing_context(None); @@ -492,7 +492,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement { } // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/stop - fn Stop(&self) -> Fallible<()> { + fn Stop(&self) -> ErrorResult { Err(Error::NotSupported) } diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index c36bcb02651..92291600ca3 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -21,6 +21,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, NodeDamage, document_from_node, window_from_node}; use dom::values::UNSIGNED_LONG_MAX; use dom::virtualmethods::VirtualMethods; +use heapsize::HeapSizeOf; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use net_traits::image::base::{Image, ImageMetadata}; @@ -33,17 +34,31 @@ use string_cache::Atom; use url::Url; use util::str::{DOMString, LengthOrPercentageOrAuto}; +#[derive(JSTraceable, HeapSizeOf)] +#[allow(dead_code)] +enum State { + Unavailable, + PartiallyAvailable, + CompletelyAvailable, + Broken, +} +#[derive(JSTraceable, HeapSizeOf)] +struct ImageRequest { + state: State, + url: Option<Url>, + image: Option<Arc<Image>>, + metadata: Option<ImageMetadata>, +} #[dom_struct] pub struct HTMLImageElement { htmlelement: HTMLElement, - url: DOMRefCell<Option<Url>>, - image: DOMRefCell<Option<Arc<Image>>>, - metadata: DOMRefCell<Option<ImageMetadata>>, + current_request: DOMRefCell<ImageRequest>, + pending_request: DOMRefCell<ImageRequest>, } impl HTMLImageElement { pub fn get_url(&self) -> Option<Url>{ - self.url.borrow().clone() + self.current_request.borrow().url.clone() } } @@ -77,8 +92,8 @@ impl Runnable for ImageResponseHandlerRunnable { } ImageResponse::None => (None, None, true) }; - *element_ref.image.borrow_mut() = image; - *element_ref.metadata.borrow_mut() = metadata; + element_ref.current_request.borrow_mut().image = image; + element_ref.current_request.borrow_mut().metadata = metadata; // Mark the node dirty let document = document_from_node(&*element); @@ -104,14 +119,14 @@ impl HTMLImageElement { let image_cache = window.image_cache_thread(); match value { None => { - *self.url.borrow_mut() = None; - *self.image.borrow_mut() = None; + self.current_request.borrow_mut().url = None; + self.current_request.borrow_mut().image = None; } Some((src, base_url)) => { let img_url = base_url.join(&src); // FIXME: handle URL parse errors more gracefully. let img_url = img_url.unwrap(); - *self.url.borrow_mut() = Some(img_url.clone()); + self.current_request.borrow_mut().url = Some(img_url.clone()); let trusted_node = Trusted::new(self, window.networking_task_source()); let (responder_sender, responder_receiver) = ipc::channel().unwrap(); @@ -134,13 +149,21 @@ impl HTMLImageElement { } } } - fn new_inherited(localName: Atom, prefix: Option<DOMString>, document: &Document) -> HTMLImageElement { HTMLImageElement { htmlelement: HTMLElement::new_inherited(localName, prefix, document), - url: DOMRefCell::new(None), - image: DOMRefCell::new(None), - metadata: DOMRefCell::new(None), + current_request: DOMRefCell::new(ImageRequest { + state: State::Unavailable, + url: None, + image: None, + metadata: None + }), + pending_request: DOMRefCell::new(ImageRequest { + state: State::Unavailable, + url: None, + image: None, + metadata: None + }), } } @@ -182,12 +205,12 @@ pub trait LayoutHTMLImageElementHelpers { impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> { #[allow(unsafe_code)] unsafe fn image(&self) -> Option<Arc<Image>> { - (*self.unsafe_get()).image.borrow_for_layout().clone() + (*self.unsafe_get()).current_request.borrow_for_layout().image.clone() } #[allow(unsafe_code)] unsafe fn image_url(&self) -> Option<Url> { - (*self.unsafe_get()).url.borrow_for_layout().clone() + (*self.unsafe_get()).current_request.borrow_for_layout().url.clone() } #[allow(unsafe_code)] @@ -224,6 +247,11 @@ impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-src make_setter!(SetSrc, "src"); + // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin + make_enumerated_getter!(CrossOrigin, "crossorigin", "anonymous", ("use-credentials")); + // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin + make_setter!(SetCrossOrigin, "crossorigin"); + // https://html.spec.whatwg.org/multipage/#dom-img-usemap make_getter!(UseMap, "usemap"); // https://html.spec.whatwg.org/multipage/#dom-img-usemap @@ -260,7 +288,7 @@ impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-naturalwidth fn NaturalWidth(&self) -> u32 { - let metadata = self.metadata.borrow(); + let ref metadata = self.current_request.borrow().metadata; match *metadata { Some(ref metadata) => metadata.width, @@ -270,7 +298,7 @@ impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-naturalheight fn NaturalHeight(&self) -> u32 { - let metadata = self.metadata.borrow(); + let ref metadata = self.current_request.borrow().metadata; match *metadata { Some(ref metadata) => metadata.height, @@ -280,10 +308,19 @@ impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-complete fn Complete(&self) -> bool { - let image = self.image.borrow(); + let ref image = self.current_request.borrow().image; image.is_some() } + // https://html.spec.whatwg.org/multipage/#dom-img-currentsrc + fn CurrentSrc(&self) -> DOMString { + let ref url = self.current_request.borrow().url; + match *url { + Some(ref url) => DOMString::from(url.serialize()), + None => DOMString::from(""), + } + } + // https://html.spec.whatwg.org/multipage/#dom-img-name make_getter!(Name, "name"); diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 174a312448f..9c969ceec98 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -164,7 +164,7 @@ impl HTMLInputElement { } // https://html.spec.whatwg.org/multipage/#input-type-attr-summary - fn get_value_mode(&self) -> ValueMode { + fn value_mode(&self) -> ValueMode { match self.input_type.get() { InputType::InputSubmit | InputType::InputReset | @@ -208,15 +208,15 @@ impl HTMLInputElement { pub trait LayoutHTMLInputElementHelpers { #[allow(unsafe_code)] - unsafe fn get_value_for_layout(self) -> String; + unsafe fn value_for_layout(self) -> String; #[allow(unsafe_code)] - unsafe fn get_size_for_layout(self) -> u32; + unsafe fn size_for_layout(self) -> u32; #[allow(unsafe_code)] - unsafe fn get_selection_for_layout(self) -> Option<Range<isize>>; + unsafe fn selection_for_layout(self) -> Option<Range<isize>>; #[allow(unsafe_code)] - unsafe fn get_checked_state_for_layout(self) -> bool; + unsafe fn checked_state_for_layout(self) -> bool; #[allow(unsafe_code)] - unsafe fn get_indeterminate_state_for_layout(self) -> bool; + unsafe fn indeterminate_state_for_layout(self) -> bool; } #[allow(unsafe_code)] @@ -226,7 +226,7 @@ unsafe fn get_raw_textinput_value(input: LayoutJS<HTMLInputElement>) -> DOMStrin impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { #[allow(unsafe_code)] - unsafe fn get_value_for_layout(self) -> String { + unsafe fn value_for_layout(self) -> String { #[allow(unsafe_code)] unsafe fn get_raw_attr_value(input: LayoutJS<HTMLInputElement>, default: &str) -> String { let elem = input.upcast::<Element>(); @@ -245,7 +245,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { InputType::InputPassword => { let text = get_raw_textinput_value(self); if !text.is_empty() { - // The implementation of get_selection_for_layout expects a 1:1 mapping of chars. + // The implementation of selection_for_layout expects a 1:1 mapping of chars. text.chars().map(|_| '●').collect() } else { String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone()) @@ -254,7 +254,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { _ => { let text = get_raw_textinput_value(self); if !text.is_empty() { - // The implementation of get_selection_for_layout expects a 1:1 mapping of chars. + // The implementation of selection_for_layout expects a 1:1 mapping of chars. String::from(text) } else { String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone()) @@ -265,19 +265,19 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn get_size_for_layout(self) -> u32 { + unsafe fn size_for_layout(self) -> u32 { (*self.unsafe_get()).size.get() } #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn get_selection_for_layout(self) -> Option<Range<isize>> { + unsafe fn selection_for_layout(self) -> Option<Range<isize>> { if !(*self.unsafe_get()).upcast::<Element>().focus_state() { return None; } // Use the raw textinput to get the index as long as we use a 1:1 char mapping - // in get_value_for_layout. + // in value_for_layout. let raw = match (*self.unsafe_get()).input_type.get() { InputType::InputText | InputType::InputPassword => get_raw_textinput_value(self), @@ -293,18 +293,37 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn get_checked_state_for_layout(self) -> bool { + unsafe fn checked_state_for_layout(self) -> bool { self.upcast::<Element>().get_state_for_layout().contains(IN_CHECKED_STATE) } #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn get_indeterminate_state_for_layout(self) -> bool { + unsafe fn indeterminate_state_for_layout(self) -> bool { self.upcast::<Element>().get_state_for_layout().contains(IN_INDETERMINATE_STATE) } } impl HTMLInputElementMethods for HTMLInputElement { + + // https://html.spec.whatwg.org/multipage/#attr-input-accept + make_getter!(Accept, "accept"); + + // https://html.spec.whatwg.org/multipage/#attr-input-accept + make_setter!(SetAccept, "accept"); + + // https://html.spec.whatwg.org/multipage/#attr-input-alt + make_getter!(Alt, "alt"); + + // https://html.spec.whatwg.org/multipage/#attr-input-alt + make_setter!(SetAlt, "alt"); + + // https://html.spec.whatwg.org/multipage/#attr-input-dirName + make_getter!(DirName, "dirname"); + + // https://html.spec.whatwg.org/multipage/#attr-input-dirName + make_setter!(SetDirName, "dirname"); + // https://html.spec.whatwg.org/multipage/#dom-fe-disabled make_bool_getter!(Disabled, "disabled"); @@ -361,7 +380,7 @@ impl HTMLInputElementMethods for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#dom-input-value fn Value(&self) -> DOMString { - match self.get_value_mode() { + match self.value_mode() { ValueMode::Value => self.textinput.borrow().get_content(), ValueMode::Default => { self.upcast::<Element>() @@ -384,7 +403,7 @@ impl HTMLInputElementMethods for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#dom-input-value fn SetValue(&self, value: DOMString) -> ErrorResult { - match self.get_value_mode() { + match self.value_mode() { ValueMode::Value => { self.textinput.borrow_mut().set_content(value); self.value_dirty.set(true); @@ -458,12 +477,54 @@ impl HTMLInputElementMethods for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#attr-fs-formnovalidate make_bool_setter!(SetFormNoValidate, "formnovalidate"); + // https://html.spec.whatwg.org/multipage/#attr-input-max + make_getter!(Max, "max"); + + // https://html.spec.whatwg.org/multipage/#attr-input-max + make_setter!(SetMax, "max"); + // https://html.spec.whatwg.org/multipage/#dom-input-maxlength make_int_getter!(MaxLength, "maxlength", DEFAULT_MAX_LENGTH); // https://html.spec.whatwg.org/multipage/#dom-input-maxlength make_limited_int_setter!(SetMaxLength, "maxlength", DEFAULT_MAX_LENGTH); + // https://html.spec.whatwg.org/multipage/#attr-input-min + make_getter!(Min, "min"); + + // https://html.spec.whatwg.org/multipage/#attr-input-min + make_setter!(SetMin, "min"); + + // https://html.spec.whatwg.org/multipage/#attr-input-multiple + make_bool_getter!(Multiple, "multiple"); + + // https://html.spec.whatwg.org/multipage/#attr-input-multiple + make_bool_setter!(SetMultiple, "multiple"); + + // https://html.spec.whatwg.org/multipage/#attr-input-pattern + make_getter!(Pattern, "pattern"); + + // https://html.spec.whatwg.org/multipage/#attr-input-pattern + make_setter!(SetPattern, "pattern"); + + // https://html.spec.whatwg.org/multipage/#attr-input-required + make_bool_getter!(Required, "required"); + + // https://html.spec.whatwg.org/multipage/#attr-input-required + make_bool_setter!(SetRequired, "required"); + + // https://html.spec.whatwg.org/multipage/#attr-input-src + make_getter!(Src, "src"); + + // https://html.spec.whatwg.org/multipage/#attr-input-src + make_setter!(SetSrc, "src"); + + // https://html.spec.whatwg.org/multipage/#attr-input-step + make_getter!(Step, "step"); + + // https://html.spec.whatwg.org/multipage/#attr-input-step + make_setter!(SetStep, "step"); + // https://html.spec.whatwg.org/multipage/#dom-input-indeterminate fn Indeterminate(&self) -> bool { self.upcast::<Element>().state().contains(IN_INDETERMINATE_STATE) @@ -581,7 +642,7 @@ fn in_same_group(other: &HTMLInputElement, owner: Option<&HTMLFormElement>, other.input_type.get() == InputType::InputRadio && // TODO Both a and b are in the same home subtree. other.form_owner().r() == owner && - match (other.get_radio_group_name(), group) { + match (other.radio_group_name(), group) { (Some(ref s1), Some(s2)) => compatibility_caseless_match_str(s1, s2) && s2 != &atom!(""), _ => false } @@ -596,7 +657,7 @@ impl HTMLInputElement { /// https://html.spec.whatwg.org/multipage/#constructing-the-form-data-set /// Steps range from 3.1 to 3.7 which related to the HTMLInputElement - pub fn get_form_datum(&self, submitter: Option<FormSubmitter>) -> Option<FormDatum> { + pub fn form_datum(&self, submitter: Option<FormSubmitter>) -> Option<FormDatum> { // Step 3.2 let ty = self.type_(); // Step 3.4 @@ -632,7 +693,7 @@ impl HTMLInputElement { } // https://html.spec.whatwg.org/multipage/#radio-button-group - fn get_radio_group_name(&self) -> Option<Atom> { + fn radio_group_name(&self) -> Option<Atom> { //TODO: determine form owner self.upcast::<Element>() .get_attribute(&ns!(), &atom!("name")) @@ -648,19 +709,15 @@ impl HTMLInputElement { if self.input_type.get() == InputType::InputRadio && checked { broadcast_radio_checked(self, - self.get_radio_group_name().as_ref()); + self.radio_group_name().as_ref()); } self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); //TODO: dispatch change event } - pub fn get_indeterminate_state(&self) -> bool { - self.Indeterminate() - } - // https://html.spec.whatwg.org/multipage/#concept-fe-mutable - fn mutable(&self) -> bool { + fn is_mutable(&self) -> bool { // https://html.spec.whatwg.org/multipage/#the-input-element:concept-fe-mutable // https://html.spec.whatwg.org/multipage/#the-readonly-attribute:concept-fe-mutable !(self.upcast::<Element>().disabled_state() || self.ReadOnly()) @@ -740,9 +797,9 @@ impl VirtualMethods for HTMLInputElement { }; // https://html.spec.whatwg.org/multipage/#input-type-change - let (old_value_mode, old_idl_value) = (self.get_value_mode(), self.Value()); + let (old_value_mode, old_idl_value) = (self.value_mode(), self.Value()); self.input_type.set(new_type); - let new_value_mode = self.get_value_mode(); + let new_value_mode = self.value_mode(); match (&old_value_mode, old_idl_value.is_empty(), new_value_mode) { @@ -774,7 +831,7 @@ impl VirtualMethods for HTMLInputElement { // Step 5 if new_type == InputType::InputRadio { self.radio_group_updated( - self.get_radio_group_name().as_ref()); + self.radio_group_name().as_ref()); } // TODO: Step 6 - value sanitization @@ -783,7 +840,7 @@ impl VirtualMethods for HTMLInputElement { if self.input_type.get() == InputType::InputRadio { broadcast_radio_checked( self, - self.get_radio_group_name().as_ref()); + self.radio_group_name().as_ref()); } self.input_type.set(InputType::InputText); } @@ -916,7 +973,7 @@ impl Activatable for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#checkbox-state-%28type=checkbox%29:activation-behaviour-2 // https://html.spec.whatwg.org/multipage/#radio-button-state-%28type=radio%29:activation-behaviour-2 InputType::InputSubmit | InputType::InputReset - | InputType::InputCheckbox | InputType::InputRadio => self.mutable(), + | InputType::InputCheckbox | InputType::InputRadio => self.is_mutable(), _ => false } } @@ -927,7 +984,7 @@ impl Activatable for HTMLInputElement { let mut cache = self.activation_state.borrow_mut(); let ty = self.input_type.get(); cache.old_type = ty; - cache.was_mutable = self.mutable(); + cache.was_mutable = self.is_mutable(); if cache.was_mutable { match ty { // https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):activation-behavior @@ -952,7 +1009,7 @@ impl Activatable for HTMLInputElement { let owner = self.form_owner(); let doc = document_from_node(self); let doc_node = doc.upcast::<Node>(); - let group = self.get_radio_group_name();; + let group = self.radio_group_name();; // Safe since we only manipulate the DOM tree after finding an element let checked_member = doc_node.query_selector_iter(DOMString::from("input[type=radio]")) @@ -998,16 +1055,12 @@ impl Activatable for HTMLInputElement { InputType::InputRadio => { // We want to restore state only if the element had been changed in the first place if cache.was_mutable { - let name = self.get_radio_group_name(); match cache.checked_radio.r() { Some(o) => { // Avoiding iterating through the whole tree here, instead // we can check if the conditions for radio group siblings apply - if name == o.get_radio_group_name() && // TODO should be compatibility caseless - self.form_owner() == o.form_owner() && - // TODO Both a and b are in the same home subtree - o.input_type.get() == InputType::InputRadio { - o.SetChecked(true); + if in_same_group(&o, self.form_owner().r(), self.radio_group_name().as_ref()) { + o.SetChecked(true); } else { self.SetChecked(false); } @@ -1024,8 +1077,8 @@ impl Activatable for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps fn activation_behavior(&self, _event: &Event, _target: &EventTarget) { let ty = self.input_type.get(); - if self.activation_state.borrow().old_type != ty { - // Type changed, abandon ship + if self.activation_state.borrow().old_type != ty || !self.is_mutable() { + // Type changed or input is immutable, abandon ship // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27414 return; } @@ -1033,34 +1086,31 @@ impl Activatable for HTMLInputElement { InputType::InputSubmit => { // https://html.spec.whatwg.org/multipage/#submit-button-state-(type=submit):activation-behavior // FIXME (Manishearth): support document owners (needs ability to get parent browsing context) - if self.mutable() /* and document owner is fully active */ { - self.form_owner().map(|o| { - o.submit(SubmittedFrom::NotFromFormSubmitMethod, - FormSubmitter::InputElement(self.clone())) - }); - } + // Check if document owner is fully active + self.form_owner().map(|o| { + o.submit(SubmittedFrom::NotFromFormSubmitMethod, + FormSubmitter::InputElement(self.clone())) + }); }, InputType::InputReset => { // https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset):activation-behavior // FIXME (Manishearth): support document owners (needs ability to get parent browsing context) - if self.mutable() /* and document owner is fully active */ { - self.form_owner().map(|o| { - o.reset(ResetFrom::NotFromFormResetMethod) - }); - } + // Check if document owner is fully active + self.form_owner().map(|o| { + o.reset(ResetFrom::NotFromFormResetMethod) + }); }, InputType::InputCheckbox | InputType::InputRadio => { // https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):activation-behavior // https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):activation-behavior - if self.mutable() { - let target = self.upcast::<EventTarget>(); - target.fire_event("input", - EventBubbles::Bubbles, - EventCancelable::NotCancelable); - target.fire_event("change", - EventBubbles::Bubbles, - EventCancelable::NotCancelable); - } + // Check if document owner is fully active + let target = self.upcast::<EventTarget>(); + target.fire_event("input", + EventBubbles::Bubbles, + EventCancelable::NotCancelable); + target.fire_event("change", + EventBubbles::Bubbles, + EventCancelable::NotCancelable); }, _ => () } diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs index ab611716b90..4ea908675b1 100644 --- a/components/script/dom/htmltableelement.rs +++ b/components/script/dom/htmltableelement.rs @@ -7,13 +7,15 @@ use dom::attr::{Attr, AttrValue}; use dom::bindings::codegen::Bindings::HTMLTableElementBinding; use dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; +use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, Root, RootedReference}; +use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root, RootedReference}; use dom::document::Document; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; use dom::htmlcollection::{CollectionFilter, HTMLCollection}; use dom::htmlelement::HTMLElement; use dom::htmltablecaptionelement::HTMLTableCaptionElement; +use dom::htmltablecolelement::HTMLTableColElement; use dom::htmltablerowelement::HTMLTableRowElement; use dom::htmltablesectionelement::HTMLTableSectionElement; use dom::node::{Node, document_from_node, window_from_node}; @@ -28,6 +30,7 @@ pub struct HTMLTableElement { htmlelement: HTMLElement, border: Cell<Option<u32>>, cellspacing: Cell<Option<u32>>, + tbodies: MutNullableHeap<JS<HTMLCollection>>, } impl HTMLTableElement { @@ -37,6 +40,7 @@ impl HTMLTableElement { htmlelement: HTMLElement::new_inherited(localName, prefix, document), border: Cell::new(None), cellspacing: Cell::new(None), + tbodies: Default::default(), } } @@ -50,6 +54,70 @@ impl HTMLTableElement { pub fn get_border(&self) -> Option<u32> { self.border.get() } + + // https://html.spec.whatwg.org/multipage/#dom-table-thead + // https://html.spec.whatwg.org/multipage/#dom-table-tfoot + fn get_first_section_of_type(&self, atom: &Atom) -> Option<Root<HTMLTableSectionElement>> { + self.upcast::<Node>() + .child_elements() + .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == atom) + .and_then(|n| n.downcast().map(Root::from_ref)) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-thead + // https://html.spec.whatwg.org/multipage/#dom-table-tfoot + fn set_first_section_of_type<P>(&self, + atom: &Atom, + section: Option<&HTMLTableSectionElement>, + reference_predicate: P) + -> ErrorResult + where P: FnMut(&Root<Element>) -> bool { + if let Some(e) = section { + if e.upcast::<Element>().local_name() != atom { + return Err(Error::HierarchyRequest) + } + } + + self.delete_first_section_of_type(atom); + + let node = self.upcast::<Node>(); + + if let Some(section) = section { + let reference_element = node.child_elements().find(reference_predicate); + let reference_node = reference_element.r().map(|e| e.upcast()); + + try!(node.InsertBefore(section.upcast(), reference_node)); + } + + Ok(()) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-createthead + // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot + fn create_section_of_type(&self, atom: &Atom) -> Root<HTMLTableSectionElement> { + if let Some(section) = self.get_first_section_of_type(atom) { + return section + } + + let section = HTMLTableSectionElement::new(atom.clone(), + None, + document_from_node(self).r()); + match atom { + &atom!("thead") => self.SetTHead(Some(§ion)), + &atom!("tfoot") => self.SetTFoot(Some(§ion)), + _ => unreachable!("unexpected section type") + }.expect("unexpected section type"); + + section + } + + // https://html.spec.whatwg.org/multipage/#dom-table-deletethead + // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot + fn delete_first_section_of_type(&self, atom: &Atom) { + if let Some(thead) = self.get_first_section_of_type(atom) { + thead.upcast::<Node>().remove_self(); + } + } } impl HTMLTableElementMethods for HTMLTableElement { @@ -119,6 +187,83 @@ impl HTMLTableElementMethods for HTMLTableElement { } } + + // https://html.spec.whatwg.org/multipage/#dom-table-thead + fn GetTHead(&self) -> Option<Root<HTMLTableSectionElement>> { + self.get_first_section_of_type(&atom!("thead")) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-thead + fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult { + self.set_first_section_of_type(&atom!("thead"), thead, |n| { + !n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>() + }) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-createthead + fn CreateTHead(&self) -> Root<HTMLTableSectionElement> { + self.create_section_of_type(&atom!("thead")) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-deletethead + fn DeleteTHead(&self) { + self.delete_first_section_of_type(&atom!("thead")) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-tfoot + fn GetTFoot(&self) -> Option<Root<HTMLTableSectionElement>> { + self.get_first_section_of_type(&atom!("tfoot")) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-tfoot + fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult { + self.set_first_section_of_type(&atom!("tfoot"), tfoot, |n| { + if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() { + return false; + } + + if n.is::<HTMLTableSectionElement>() { + let name = n.local_name(); + if name == &atom!("thead") || name == &atom!("tbody") { + return false; + } + + } + + true + }) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot + fn CreateTFoot(&self) -> Root<HTMLTableSectionElement> { + self.create_section_of_type(&atom!("tfoot")) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot + fn DeleteTFoot(&self) { + self.delete_first_section_of_type(&atom!("tfoot")) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-tbodies + fn TBodies(&self) -> Root<HTMLCollection> { + #[derive(JSTraceable)] + struct TBodiesFilter; + impl CollectionFilter for TBodiesFilter { + fn filter(&self, elem: &Element, root: &Node) -> bool { + elem.is::<HTMLTableSectionElement>() + && elem.local_name() == &atom!("tbody") + && elem.upcast::<Node>().GetParentNode().r() == Some(root) + } + } + + self.tbodies.or_init(|| { + let window = window_from_node(self); + let filter = box TBodiesFilter; + HTMLCollection::create(window.r(), self.upcast(), filter) + }) + } + + // https://html.spec.whatwg.org/multipage/#dom-table-createtbody fn CreateTBody(&self) -> Root<HTMLTableSectionElement> { let tbody = HTMLTableSectionElement::new(atom!("tbody"), diff --git a/components/script/dom/htmltablerowelement.rs b/components/script/dom/htmltablerowelement.rs index be0a9c9f5fb..bb83e00b0db 100644 --- a/components/script/dom/htmltablerowelement.rs +++ b/components/script/dom/htmltablerowelement.rs @@ -4,7 +4,9 @@ use cssparser::RGBA; use dom::attr::AttrValue; +use dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods; use dom::bindings::codegen::Bindings::HTMLTableRowElementBinding::{self, HTMLTableRowElementMethods}; +use dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::HTMLTableSectionElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; @@ -14,7 +16,9 @@ use dom::element::{Element, RawLayoutElementHelpers}; use dom::htmlcollection::{CollectionFilter, HTMLCollection}; use dom::htmlelement::HTMLElement; use dom::htmltabledatacellelement::HTMLTableDataCellElement; +use dom::htmltableelement::HTMLTableElement; use dom::htmltableheadercellelement::HTMLTableHeaderCellElement; +use dom::htmltablesectionelement::HTMLTableSectionElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use string_cache::Atom; @@ -52,6 +56,14 @@ impl HTMLTableRowElement { document, HTMLTableRowElementBinding::Wrap) } + + /// Determine the index for this `HTMLTableRowElement` within the given + /// `HTMLCollection`. Returns `-1` if not found within collection. + fn row_index(&self, collection: Root<HTMLCollection>) -> i32 { + collection.elements_iter() + .position(|elem| (&elem as &Element) == self.upcast()) + .map_or(-1, |i| i as i32) + } } impl HTMLTableRowElementMethods for HTMLTableRowElement { @@ -87,6 +99,42 @@ impl HTMLTableRowElementMethods for HTMLTableRowElement { || self.Cells(), |n| n.is::<HTMLTableDataCellElement>()) } + + // https://html.spec.whatwg.org/multipage/#dom-tr-rowindex + fn RowIndex(&self) -> i32 { + let parent = match self.upcast::<Node>().GetParentNode() { + Some(parent) => parent, + None => return -1, + }; + if let Some(table) = parent.downcast::<HTMLTableElement>() { + return self.row_index(table.Rows()); + } + if !parent.is::<HTMLTableSectionElement>() { + return -1; + } + let grandparent = match parent.upcast::<Node>().GetParentNode() { + Some(parent) => parent, + None => return -1, + }; + grandparent.downcast::<HTMLTableElement>() + .map_or(-1, |table| self.row_index(table.Rows())) + } + + // https://html.spec.whatwg.org/multipage/#dom-tr-sectionrowindex + fn SectionRowIndex(&self) -> i32 { + let parent = match self.upcast::<Node>().GetParentNode() { + Some(parent) => parent, + None => return -1, + }; + let collection = if let Some(table) = parent.downcast::<HTMLTableElement>() { + table.Rows() + } else if let Some(table_section) = parent.downcast::<HTMLTableSectionElement>() { + table_section.Rows() + } else { + return -1; + }; + self.row_index(collection) + } } pub trait HTMLTableRowElementLayoutHelpers { diff --git a/components/script/dom/performancetiming.rs b/components/script/dom/performancetiming.rs index c9f2458de3e..02da92f3b89 100644 --- a/components/script/dom/performancetiming.rs +++ b/components/script/dom/performancetiming.rs @@ -76,6 +76,16 @@ impl PerformanceTimingMethods for PerformanceTiming { fn DomComplete(&self) -> u64 { self.document.get_dom_complete() } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-loadEventStart + fn LoadEventStart(&self) -> u64 { + self.document.get_load_event_start() + } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-loadEventEnd + fn LoadEventEnd(&self) -> u64 { + self.document.get_load_event_end() + } } diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 996e6eb4cee..d288e9422c4 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -167,6 +167,17 @@ impl WebGLProgram { WebGLActiveInfo::new(self.global().r(), size, ty, DOMString::from(name))) } + /// glGetActiveAttrib + pub fn get_active_attrib(&self, index: u32) -> WebGLResult<Root<WebGLActiveInfo>> { + let (sender, receiver) = ipc::channel().unwrap(); + self.renderer + .send(CanvasMsg::WebGL(WebGLCommand::GetActiveAttrib(self.id, index, sender))) + .unwrap(); + + receiver.recv().unwrap().map(|(size, ty, name)| + WebGLActiveInfo::new(self.global().r(), size, ty, DOMString::from(name))) + } + /// glGetAttribLocation pub fn get_attrib_location(&self, name: DOMString) -> WebGLResult<Option<i32>> { if name.len() > MAX_UNIFORM_AND_ATTRIBUTE_LEN { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 920fd91bbad..4c6996cbb90 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -31,7 +31,7 @@ use js::jsapi::{JSContext, JSObject, RootedValue}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue}; use net_traits::image::base::PixelFormat; use net_traits::image_cache_thread::ImageResponse; -use offscreen_gl_context::GLContextAttributes; +use offscreen_gl_context::{GLContextAttributes, GLLimits}; use script_traits::ScriptMsg as ConstellationMsg; use std::cell::Cell; use util::str::DOMString; @@ -71,6 +71,8 @@ pub struct WebGLRenderingContext { reflector_: Reflector, #[ignore_heap_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender<CanvasMsg>, + #[ignore_heap_size_of = "Defined in offscreen_gl_context"] + limits: GLLimits, canvas: JS<HTMLCanvasElement>, #[ignore_heap_size_of = "Defined in webrender_traits"] last_error: Cell<Option<WebGLError>>, @@ -95,10 +97,11 @@ impl WebGLRenderingContext { .unwrap(); let result = receiver.recv().unwrap(); - result.map(|ipc_renderer| { + result.map(|(ipc_renderer, context_limits)| { WebGLRenderingContext { reflector_: Reflector::new(), ipc_renderer: ipc_renderer, + limits: context_limits, canvas: JS::from_ref(canvas), last_error: Cell::new(None), texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE), @@ -139,6 +142,9 @@ impl WebGLRenderingContext { } pub fn webgl_error(&self, err: WebGLError) { + // TODO(emilio): Add useful debug messages to this + warn!("WebGL error: {:?}, previous error was {:?}", err, self.last_error.get()); + // If an error has been detected no further errors must be // recorded until `getError` has been called if self.last_error.get().is_none() { @@ -155,7 +161,7 @@ impl WebGLRenderingContext { if let Some(texture) = texture { handle_potential_webgl_error!(self, texture.tex_parameter(target, name, value)); } else { - return self.webgl_error(InvalidOperation); + self.webgl_error(InvalidOperation) } } @@ -164,6 +170,10 @@ impl WebGLRenderingContext { } fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) { + if indx > self.limits.max_vertex_attribs { + return self.webgl_error(InvalidValue); + } + self.ipc_renderer .send(CanvasMsg::WebGL(WebGLCommand::VertexAttrib(indx, x, y, z, w))) .unwrap(); @@ -680,6 +690,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 fn CreateShader(&self, shader_type: u32) -> Option<Root<WebGLShader>> { + match shader_type { + constants::VERTEX_SHADER | constants::FRAGMENT_SHADER => {}, + _ => { + self.webgl_error(InvalidEnum); + return None; + } + } WebGLShader::maybe_new(self.global().r(), self.ipc_renderer.clone(), shader_type) } @@ -737,13 +754,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } if first < 0 || count < 0 { - self.webgl_error(InvalidValue); - } else { - self.ipc_renderer - .send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count))) - .unwrap(); - self.mark_as_dirty(); + return self.webgl_error(InvalidValue); } + + self.ipc_renderer + .send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count))) + .unwrap(); + self.mark_as_dirty(); }, _ => self.webgl_error(InvalidEnum), } @@ -790,6 +807,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn EnableVertexAttribArray(&self, attrib_id: u32) { + if attrib_id > self.limits.max_vertex_attribs { + return self.webgl_error(InvalidValue); + } + self.ipc_renderer .send(CanvasMsg::WebGL(WebGLCommand::EnableVertexAttribArray(attrib_id))) .unwrap() @@ -807,6 +828,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn GetActiveAttrib(&self, program: Option<&WebGLProgram>, index: u32) -> Option<Root<WebGLActiveInfo>> { + program.and_then(|p| match p.get_active_attrib(index) { + Ok(ret) => Some(ret), + Err(error) => { + self.webgl_error(error); + None + }, + }) + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn GetAttribLocation(&self, program: Option<&WebGLProgram>, name: DOMString) -> i32 { if let Some(program) = program { handle_potential_webgl_error!(self, program.get_attrib_location(name), None).unwrap_or(-1) @@ -1188,7 +1220,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.vertex_attrib(indx, x, 0f32, 0f32, 1f32) } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn VertexAttrib1fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data) { @@ -1206,7 +1237,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.vertex_attrib(indx, x, y, 0f32, 1f32) } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn VertexAttrib2fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data) { @@ -1257,6 +1287,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn VertexAttribPointer(&self, attrib_id: u32, size: i32, data_type: u32, normalized: bool, stride: i32, offset: i64) { + if attrib_id > self.limits.max_vertex_attribs { + return self.webgl_error(InvalidValue); + } + if let constants::FLOAT = data_type { let msg = CanvasMsg::WebGL( WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset as u32)); diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs index 804dc3cdcf8..495417065d7 100644 --- a/components/script/dom/webglshader.rs +++ b/components/script/dom/webglshader.rs @@ -101,6 +101,7 @@ impl WebGLShader { &BuiltInResources::default()).unwrap(); match validator.compile_and_translate(&[source]) { Ok(translated_source) => { + debug!("Shader translated: {}", translated_source); // NOTE: At this point we should be pretty sure that the compilation in the paint thread // will succeed. // It could be interesting to retrieve the info log from the paint thread though diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index dba69a515b0..10cf77ccc83 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -310,4 +310,5 @@ partial interface CSSStyleDeclaration { [SetterThrows, TreatNullAs=EmptyString] attribute DOMString flexDirection; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString flex-direction; + [SetterThrows, TreatNullAs=EmptyString] attribute DOMString order; }; diff --git a/components/script/dom/webidls/HTMLBaseElement.webidl b/components/script/dom/webidls/HTMLBaseElement.webidl index 5c59c62f9be..549a6df1004 100644 --- a/components/script/dom/webidls/HTMLBaseElement.webidl +++ b/components/script/dom/webidls/HTMLBaseElement.webidl @@ -5,6 +5,6 @@ // https://html.spec.whatwg.org/multipage/#htmlbaseelement interface HTMLBaseElement : HTMLElement { - // attribute DOMString href; - // attribute DOMString target; + attribute DOMString href; +// attribute DOMString target; }; diff --git a/components/script/dom/webidls/HTMLHRElement.webidl b/components/script/dom/webidls/HTMLHRElement.webidl index f203527b2bf..e3ba6113748 100644 --- a/components/script/dom/webidls/HTMLHRElement.webidl +++ b/components/script/dom/webidls/HTMLHRElement.webidl @@ -10,7 +10,7 @@ interface HTMLHRElement : HTMLElement { // https://html.spec.whatwg.org/multipage/#HTMLHRElement-partial partial interface HTMLHRElement { - // attribute DOMString align; + attribute DOMString align; attribute DOMString color; // attribute boolean noShade; // attribute DOMString size; diff --git a/components/script/dom/webidls/HTMLImageElement.webidl b/components/script/dom/webidls/HTMLImageElement.webidl index 34cd6f5d645..69bd2f7d4c1 100644 --- a/components/script/dom/webidls/HTMLImageElement.webidl +++ b/components/script/dom/webidls/HTMLImageElement.webidl @@ -9,7 +9,7 @@ interface HTMLImageElement : HTMLElement { attribute DOMString alt; attribute DOMString src; // attribute DOMString srcset; - // attribute DOMString crossOrigin; + attribute DOMString crossOrigin; attribute DOMString useMap; attribute boolean isMap; attribute unsigned long width; @@ -17,7 +17,7 @@ interface HTMLImageElement : HTMLElement { readonly attribute unsigned long naturalWidth; readonly attribute unsigned long naturalHeight; readonly attribute boolean complete; - + readonly attribute DOMString currentSrc; // also has obsolete members }; @@ -32,3 +32,9 @@ partial interface HTMLImageElement { [TreatNullAs=EmptyString] attribute DOMString border; }; + +// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlimageelement-interface +partial interface HTMLImageElement { + // readonly attribute long x; + // readonly attribute long y; +}; diff --git a/components/script/dom/webidls/HTMLInputElement.webidl b/components/script/dom/webidls/HTMLInputElement.webidl index 2e1c6215f2b..66907c5cd23 100644 --- a/components/script/dom/webidls/HTMLInputElement.webidl +++ b/components/script/dom/webidls/HTMLInputElement.webidl @@ -5,13 +5,13 @@ // https://html.spec.whatwg.org/multipage/#htmlinputelement interface HTMLInputElement : HTMLElement { - // attribute DOMString accept; - // attribute DOMString alt; + attribute DOMString accept; + attribute DOMString alt; // attribute DOMString autocomplete; // attribute boolean autofocus; attribute boolean defaultChecked; attribute boolean checked; - // attribute DOMString dirName; + attribute DOMString dirName; attribute boolean disabled; readonly attribute HTMLFormElement? form; //readonly attribute FileList? files; @@ -24,21 +24,21 @@ interface HTMLInputElement : HTMLElement { attribute boolean indeterminate; // attribute DOMString inputMode; //readonly attribute HTMLElement? list; - // attribute DOMString max; + attribute DOMString max; [SetterThrows] attribute long maxLength; - // attribute DOMString min; + attribute DOMString min; // attribute long minLength; - // attribute boolean multiple; + attribute boolean multiple; attribute DOMString name; - // attribute DOMString pattern; + attribute DOMString pattern; attribute DOMString placeholder; attribute boolean readOnly; - // attribute boolean required; + attribute boolean required; [SetterThrows] attribute unsigned long size; - // attribute DOMString src; - // attribute DOMString step; + attribute DOMString src; + attribute DOMString step; attribute DOMString type; attribute DOMString defaultValue; [TreatNullAs=EmptyString, SetterThrows] diff --git a/components/script/dom/webidls/HTMLTableElement.webidl b/components/script/dom/webidls/HTMLTableElement.webidl index 2697f4c1e93..af95685b5b5 100644 --- a/components/script/dom/webidls/HTMLTableElement.webidl +++ b/components/script/dom/webidls/HTMLTableElement.webidl @@ -8,13 +8,15 @@ interface HTMLTableElement : HTMLElement { attribute HTMLTableCaptionElement? caption; HTMLElement createCaption(); void deleteCaption(); - // attribute HTMLTableSectionElement? tHead; - //HTMLElement createTHead(); - //void deleteTHead(); - // attribute HTMLTableSectionElement? tFoot; - //HTMLElement createTFoot(); - //void deleteTFoot(); - //readonly attribute HTMLCollection tBodies; + [SetterThrows] + attribute HTMLTableSectionElement? tHead; + HTMLTableSectionElement createTHead(); + void deleteTHead(); + [SetterThrows] + attribute HTMLTableSectionElement? tFoot; + HTMLTableSectionElement createTFoot(); + void deleteTFoot(); + readonly attribute HTMLCollection tBodies; HTMLTableSectionElement createTBody(); readonly attribute HTMLCollection rows; //HTMLElement insertRow(optional long index = -1); diff --git a/components/script/dom/webidls/HTMLTableRowElement.webidl b/components/script/dom/webidls/HTMLTableRowElement.webidl index 66538630c9d..fe6c93e6be5 100644 --- a/components/script/dom/webidls/HTMLTableRowElement.webidl +++ b/components/script/dom/webidls/HTMLTableRowElement.webidl @@ -5,8 +5,8 @@ // https://html.spec.whatwg.org/multipage/#htmltablerowelement interface HTMLTableRowElement : HTMLElement { - //readonly attribute long rowIndex; - //readonly attribute long sectionRowIndex; + readonly attribute long rowIndex; + readonly attribute long sectionRowIndex; readonly attribute HTMLCollection cells; [Throws] HTMLElement insertCell(optional long index = -1); diff --git a/components/script/dom/webidls/PerformanceTiming.webidl b/components/script/dom/webidls/PerformanceTiming.webidl index a016f2b1616..7a2fdaebec0 100644 --- a/components/script/dom/webidls/PerformanceTiming.webidl +++ b/components/script/dom/webidls/PerformanceTiming.webidl @@ -27,6 +27,6 @@ interface PerformanceTiming { readonly attribute unsigned long long domContentLoadedEventStart; readonly attribute unsigned long long domContentLoadedEventEnd; readonly attribute unsigned long long domComplete; - /* readonly attribute unsigned long long loadEventStart; - readonly attribute unsigned long long loadEventEnd; */ + readonly attribute unsigned long long loadEventStart; + readonly attribute unsigned long long loadEventEnd; }; diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl index 7be7a82d41e..d2c93d9a3c5 100644 --- a/components/script/dom/webidls/WebGLRenderingContext.webidl +++ b/components/script/dom/webidls/WebGLRenderingContext.webidl @@ -567,7 +567,7 @@ interface WebGLRenderingContextBase void generateMipmap(GLenum target); - //WebGLActiveInfo? getActiveAttrib(WebGLProgram? program, GLuint index); + WebGLActiveInfo? getActiveAttrib(WebGLProgram? program, GLuint index); WebGLActiveInfo? getActiveUniform(WebGLProgram? program, GLuint index); //sequence<WebGLShader>? getAttachedShaders(WebGLProgram? program); diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index 59ec9db7b4b..e92c7abbcab 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::WebSocketBinding; use dom::bindings::codegen::Bindings::WebSocketBinding::{BinaryType, WebSocketMethods}; use dom::bindings::codegen::UnionTypes::StringOrStringSequence; use dom::bindings::conversions::{ToJSValConvertible}; -use dom::bindings::error::{Error, Fallible}; +use dom::bindings::error::{Error, Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; @@ -385,7 +385,7 @@ impl WebSocketMethods for WebSocket { } // https://html.spec.whatwg.org/multipage/#dom-websocket-send - fn Send(&self, data: USVString) -> Fallible<()> { + fn Send(&self, data: USVString) -> ErrorResult { let data_byte_len = data.0.as_bytes().len() as u64; let send_data = try!(self.send_impl(data_byte_len)); @@ -400,7 +400,7 @@ impl WebSocketMethods for WebSocket { } // https://html.spec.whatwg.org/multipage/#dom-websocket-send - fn Send_(&self, blob: &Blob) -> Fallible<()> { + fn Send_(&self, blob: &Blob) -> ErrorResult { /* As per https://html.spec.whatwg.org/multipage/#websocket the buffered amount needs to be clamped to u32, even though Blob.Size() is u64 @@ -420,7 +420,7 @@ impl WebSocketMethods for WebSocket { } // https://html.spec.whatwg.org/multipage/#dom-websocket-close - fn Close(&self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{ + fn Close(&self, code: Option<u16>, reason: Option<USVString>) -> ErrorResult { if let Some(code) = code { //Fail if the supplied code isn't normal and isn't reserved for libraries, frameworks, and applications if code != close_code::NORMAL && (code < 3000 || code > 4999) { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index da415c5d0f2..8a3affefe06 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1383,6 +1383,7 @@ impl Window { pipelineid: id, script_chan: Arc::new(Mutex::new(control_chan)), }; + let current_time = time::get_time(); let win = box Window { eventtarget: EventTarget::new_inherited(), script_chan: script_chan, @@ -1402,7 +1403,7 @@ impl Window { devtools_chan: devtools_chan, browsing_context: Default::default(), performance: Default::default(), - navigation_start: time::get_time().sec as u64, + navigation_start: (current_time.sec * 1000 + current_time.nsec as i64 / 1000000) as u64, navigation_start_precise: time::precise_time_ns() as f64, screen: Default::default(), session_storage: Default::default(), diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 1d7c2bffd34..8d6716201af 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -828,6 +828,12 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // https://xhr.spec.whatwg.org/#the-responsexml-attribute fn GetResponseXML(&self) -> Fallible<Option<Root<Document>>> { + // TODO(#2823): Until [Exposed] is implemented, this attribute needs to return null + // explicitly in the worker scope. + if let GlobalRoot::Worker(_) = self.global() { + return Ok(None); + } + match self.response_type.get() { XMLHttpRequestResponseType::_empty | XMLHttpRequestResponseType::Document => { // Step 3 diff --git a/components/script/lib.rs b/components/script/lib.rs index d3913865070..e525a62b70d 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -90,6 +90,7 @@ pub mod dom; pub mod layout_interface; mod mem; mod network_listener; +pub mod origin; pub mod page; pub mod parse; pub mod reporter; diff --git a/components/script/origin.rs b/components/script/origin.rs new file mode 100644 index 00000000000..096ffbbd6fb --- /dev/null +++ b/components/script/origin.rs @@ -0,0 +1,73 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::cell::RefCell; +use std::rc::Rc; +use url::{OpaqueOrigin, Origin as UrlOrigin}; +use url::{Url, Host}; + +/// A representation of an [origin](https://html.spec.whatwg.org/multipage/#origin-2). +#[derive(HeapSizeOf)] +pub struct Origin { + #[ignore_heap_size_of = "Rc<T> has unclear ownership semantics"] + inner: Rc<RefCell<UrlOrigin>>, +} + +// We can't use RefCell inside JSTraceable, but Origin doesn't contain JS values and +// DOMRefCell makes it much harder to write unit tests (due to setting up required TLS). +no_jsmanaged_fields!(Origin); + +impl Origin { + /// Create a new origin comprising a unique, opaque identifier. + pub fn opaque_identifier() -> Origin { + let opaque = UrlOrigin::UID(OpaqueOrigin::new()); + Origin { + inner: Rc::new(RefCell::new(opaque)), + } + } + + /// Create a new origin for the given URL. + pub fn new(url: &Url) -> Origin { + Origin { + inner: Rc::new(RefCell::new(url.origin())), + } + } + + pub fn set(&self, origin: UrlOrigin) { + *self.inner.borrow_mut() = origin; + } + + /// Does this origin represent a host/scheme/port tuple? + pub fn is_scheme_host_port_tuple(&self) -> bool { + match *self.inner.borrow() { + UrlOrigin::Tuple(..) => true, + UrlOrigin::UID(..) => false, + } + } + + /// Return the host associated with this origin. + pub fn host(&self) -> Option<Host> { + match *self.inner.borrow() { + UrlOrigin::Tuple(_, ref host, _) => Some(host.clone()), + UrlOrigin::UID(..) => None, + } + } + + /// https://html.spec.whatwg.org/multipage/#same-origin + pub fn same_origin(&self, other: &Origin) -> bool { + *self.inner.borrow() == *other.inner.borrow() + } + + pub fn copy(&self) -> Origin { + Origin { + inner: Rc::new(RefCell::new(self.inner.borrow().clone())), + } + } + + pub fn alias(&self) -> Origin { + Origin { + inner: self.inner.clone(), + } + } +} diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 509a7e93e71..6147fc8bd2b 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -13,6 +13,8 @@ use js::glue::CollectServoSizes; use js::jsapi::{DisableIncrementalGC, GCDescription, GCProgress}; use js::jsapi::{JSContext, JS_GetRuntime, JSRuntime, JSTracer, SetDOMCallbacks, SetGCSliceCallback}; use js::jsapi::{JSGCInvocationKind, JSGCStatus, JS_AddExtraGCRootsTracer, JS_SetGCCallback}; +use js::jsapi::{JSGCMode, JSGCParamKey, JS_SetGCParameter, JS_SetGlobalJitCompilerOption}; +use js::jsapi::{JSJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, JS_SetParallelParsingEnabled}; use js::jsapi::{JSObject, RuntimeOptionsRef, SetPreserveWrapperCallback}; use js::rust::Runtime; use libc; @@ -130,6 +132,181 @@ pub fn new_rt_and_cx() -> Runtime { if let Some(val) = get_pref("js.ion.enabled").as_boolean() { rt_opts.set_ion_(val); } + if let Some(val) = get_pref("js.asmjs.enabled").as_boolean() { + rt_opts.set_asmJS_(val); + } + if let Some(val) = get_pref("js.strict.enabled").as_boolean() { + rt_opts.set_extraWarnings_(val); + } + // TODO: handle js.strict.debug.enabled + // TODO: handle js.throw_on_asmjs_validation_failure (needs new Spidermonkey) + if let Some(val) = get_pref("js.native_regexp.enabled").as_boolean() { + rt_opts.set_nativeRegExp_(val); + } + if let Some(val) = get_pref("js.parallel_parsing.enabled").as_boolean() { + unsafe { JS_SetParallelParsingEnabled(runtime.rt(), val); } + } + if let Some(val) = get_pref("js.offthread_compilation_enabled").as_boolean() { + unsafe { JS_SetOffthreadIonCompilationEnabled(runtime.rt(), val); } + } + if let Some(val) = get_pref("js.baseline.unsafe_eager_compilation.enabled").as_boolean() { + let trigger: i32 = if val { + 0 + } else { + -1 + }; + unsafe { + JS_SetGlobalJitCompilerOption(runtime.rt(), + JSJitCompilerOption::JSJITCOMPILER_BASELINE_WARMUP_TRIGGER, + trigger as u32); + } + } + if let Some(val) = get_pref("js.ion.unsafe_eager_compilation.enabled").as_boolean() { + let trigger: i64 = if val { + 0 + } else { + -1 + }; + unsafe { + JS_SetGlobalJitCompilerOption(runtime.rt(), + JSJitCompilerOption::JSJITCOMPILER_ION_WARMUP_TRIGGER, + trigger as u32); + } + } + // TODO: handle js.discard_system_source.enabled + // TODO: handle js.asyncstack.enabled (needs new Spidermonkey) + // TODO: handle js.throw_on_debugee_would_run (needs new Spidermonkey) + // TODO: handle js.dump_stack_on_debugee_would_run (needs new Spidermonkey) + if let Some(val) = get_pref("js.werror.enabled").as_boolean() { + rt_opts.set_werror_(val); + } + // TODO: handle js.shared_memory.enabled + if let Some(val) = get_pref("js.mem.high_water_mark").as_i64() { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_MAX_MALLOC_BYTES, val as u32 * 1024 * 1024); + } + } + if let Some(val) = get_pref("js.mem.max").as_i64() { + let max = if val <= 0 || val >= 0x1000 { + -1 + } else { + val * 1024 * 1024 + }; + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_MAX_BYTES, max as u32); + } + } + // NOTE: This is disabled above, so enabling it here will do nothing for now. + if let Some(val) = get_pref("js.mem.gc.incremental.enabled").as_boolean() { + let compartment = if let Some(val) = get_pref("js.mem.gc.per_compartment.enabled").as_boolean() { + val + } else { + false + }; + let mode = if val { + JSGCMode::JSGC_MODE_INCREMENTAL + } else if compartment { + JSGCMode::JSGC_MODE_COMPARTMENT + } else { + JSGCMode::JSGC_MODE_GLOBAL + }; + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_MODE, mode as u32); + } + } + if let Some(val) = get_pref("js.mem.gc.incremental.slice_ms").as_i64() { + if val >= 0 && val < 100000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_SLICE_TIME_BUDGET, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.compacting.enabled").as_boolean() { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_COMPACTING_ENABLED, val as u32); + } + } + if let Some(val) = get_pref("js.mem.gc.high_frequency_time_limit_ms").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_HIGH_FREQUENCY_TIME_LIMIT, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.dynamic_mark_slice.enabled").as_boolean() { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_DYNAMIC_MARK_SLICE, val as u32); + } + } + // TODO: handle js.mem.gc.refresh_frame_slices.enabled + if let Some(val) = get_pref("js.mem.gc.dynamic_heap_growth.enabled").as_boolean() { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_DYNAMIC_HEAP_GROWTH, val as u32); + } + } + if let Some(val) = get_pref("js.mem.gc.low_frequency_heap_growth").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_LOW_FREQUENCY_HEAP_GROWTH, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.high_frequency_heap_growth_min").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.high_frequency_heap_growth_max").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.high_frequency_low_limit_mb").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_HIGH_FREQUENCY_LOW_LIMIT, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.high_frequency_high_limit_mb").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_HIGH_FREQUENCY_HIGH_LIMIT, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.allocation_threshold_mb").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_ALLOCATION_THRESHOLD, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.decommit_threshold_mb").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_DECOMMIT_THRESHOLD, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.empty_chunk_count_min").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_MIN_EMPTY_CHUNK_COUNT, val as u32); + } + } + } + if let Some(val) = get_pref("js.mem.gc.empty_chunk_count_max").as_i64() { + if val >= 0 && val < 10000 { + unsafe { + JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_MAX_EMPTY_CHUNK_COUNT, val as u32); + } + } + } runtime } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index b9027c96390..7cb24e110bc 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -52,7 +52,8 @@ use hyper::mime::{Mime, SubLevel, TopLevel}; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use js::jsapi::{DOMProxyShadowsResult, HandleId, HandleObject, RootedValue}; -use js::jsapi::{JSAutoRequest, JSContext, JS_SetWrapObjectCallbacks, JSTracer}; +use js::jsapi::{JSAutoRequest, JS_SetWrapObjectCallbacks}; +use js::jsapi::{JSContext, JSTracer}; use js::jsval::UndefinedValue; use js::rust::Runtime; use layout_interface::{ReflowQueryType}; diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 7c82de027bf..10bb4864c4b 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -14,7 +14,7 @@ use euclid::size::Size2D; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::{Failure, NavigationDirection, PipelineId}; use msg::constellation_msg::{LoadData, SubpageId}; -use offscreen_gl_context::GLContextAttributes; +use offscreen_gl_context::{GLContextAttributes, GLLimits}; use style_traits::cursor::Cursor; use style_traits::viewport::ViewportConstraints; use url::Url; @@ -43,8 +43,8 @@ pub enum ScriptMsg { /// Requests that a new WebGL thread be created. (This is done in the constellation because /// WebGL uses the GPU and we don't want to give untrusted content access to the GPU.) CreateWebGLPaintThread(Size2D<i32>, - GLContextAttributes, - IpcSender<Result<IpcSender<CanvasMsg>, String>>), + GLContextAttributes, + IpcSender<Result<(IpcSender<CanvasMsg>, GLLimits), String>>), /// Dispatched after the DOM load event has fired on a document /// Causes a `load` event to be dispatched to any enclosing frame context element /// for the given pipeline. diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 4a782120ee1..73bf74a008c 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -18,8 +18,8 @@ dependencies = [ "gfx_tests 0.0.1", "gleam 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "glutin_app 0.0.1", - "image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "image 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "layers 0.2.4 (git+https://github.com/servo/rust-layers)", "layout 0.0.1", "layout_tests 0.0.1", @@ -49,15 +49,6 @@ dependencies = [ ] [[package]] -name = "advapi32-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "aho-corasick" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -92,6 +83,15 @@ dependencies = [ ] [[package]] +name = "arrayvec" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "aster" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -119,10 +119,10 @@ dependencies = [ [[package]] name = "bincode" -version = "0.5.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -155,11 +155,6 @@ source = "git+https://github.com/browserhtml/browserhtml?branch=gh-pages#0ca5084 [[package]] name = "byteorder" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -172,7 +167,7 @@ dependencies = [ "euclid 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "layers 0.2.4 (git+https://github.com/servo/rust-layers)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,7 +187,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "offscreen_gl_context 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -251,7 +246,7 @@ name = "cmake" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -302,8 +297,8 @@ dependencies = [ "gfx 0.0.1", "gfx_traits 0.0.1", "gleam 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "image 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "layers 0.2.4 (git+https://github.com/servo/rust-layers)", "layout_traits 0.0.1", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -413,7 +408,7 @@ version = "0.0.1" dependencies = [ "devtools_traits 0.0.1", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "plugins 0.0.1", @@ -432,7 +427,7 @@ dependencies = [ "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "msg 0.0.1", "plugins 0.0.1", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -658,12 +653,8 @@ dependencies = [ [[package]] name = "gcc" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "gdi32-sys" @@ -695,9 +686,9 @@ dependencies = [ "harfbuzz-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "layers 0.2.4 (git+https://github.com/servo/rust-layers)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -714,7 +705,7 @@ dependencies = [ "servo-skia 0.20130412.6 (registry+https://github.com/rust-lang/crates.io-index)", "simd 0.1.0 (git+https://github.com/huonw/simd)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", @@ -729,7 +720,7 @@ name = "gfx_tests" version = "0.0.1" dependencies = [ "gfx 0.0.1", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "style 0.0.1", ] @@ -751,11 +742,11 @@ dependencies = [ [[package]] name = "gif" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lzw 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -890,7 +881,7 @@ dependencies = [ "phf 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -918,30 +909,31 @@ dependencies = [ "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "image" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gif 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gif 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "jpeg-decoder 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jpeg-decoder 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "png 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "immeta" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -965,12 +957,12 @@ dependencies = [ [[package]] name = "ipc-channel" -version = "0.2.1" -source = "git+https://github.com/servo/ipc-channel#f85a07bdb2615e439bee7308d37266ac3dd23708" +version = "0.2.2" +source = "git+https://github.com/servo/ipc-channel#e43fb22c431740a9bc54ce96caebd0e67d1a0586" dependencies = [ - "bincode 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -980,10 +972,10 @@ dependencies = [ [[package]] name = "jpeg-decoder" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1058,7 +1050,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "layout_traits 0.0.1", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1075,7 +1067,7 @@ dependencies = [ "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1098,7 +1090,7 @@ name = "layout_traits" version = "0.0.1" dependencies = [ "gfx 0.0.1", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "msg 0.0.1", "net_traits 0.0.1", "profile_traits 0.0.1", @@ -1112,7 +1104,7 @@ dependencies = [ [[package]] name = "lazy_static" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1139,7 +1131,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1156,7 +1148,7 @@ name = "libz-sys" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1171,7 +1163,7 @@ dependencies = [ [[package]] name = "lzw" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1240,7 +1232,7 @@ name = "miniz-sys" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1263,7 +1255,7 @@ dependencies = [ "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "layers 0.2.4 (git+https://github.com/servo/rust-layers)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1283,8 +1275,8 @@ dependencies = [ "devtools_traits 0.0.1", "flate2 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "immeta 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "immeta 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1295,11 +1287,12 @@ dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_traits 0.1.0 (git+https://github.com/servo/webrender_traits)", - "websocket 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1322,13 +1315,13 @@ dependencies = [ "devtools_traits 0.0.1", "flate2 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "msg 0.0.1", "net 0.0.1", "net_traits 0.0.1", "plugins 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", ] @@ -1340,9 +1333,9 @@ dependencies = [ "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "plugins 0.0.1", @@ -1350,7 +1343,7 @@ dependencies = [ "serde_macros 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "websocket 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1361,6 +1354,14 @@ dependencies = [ ] [[package]] +name = "nodrop" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "num" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1406,6 +1407,11 @@ dependencies = [ ] [[package]] +name = "odds" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "offscreen_gl_context" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1428,8 +1434,8 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys-extras 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1452,7 +1458,7 @@ name = "openssl-sys-extras" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1561,7 +1567,7 @@ name = "profile" version = "0.0.1" dependencies = [ "hbs-pow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", @@ -1578,7 +1584,7 @@ version = "0.0.1" dependencies = [ "energy-monitor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "energymon 0.2.0 (git+https://github.com/energymon/energymon-rust.git)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "plugins 0.0.1", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1712,8 +1718,8 @@ dependencies = [ "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "image 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "js 0.1.2 (git+https://github.com/servo/rust-mozjs)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1735,15 +1741,15 @@ dependencies = [ "selectors 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_traits 0.1.0 (git+https://github.com/servo/webrender_traits)", - "websocket 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.1.1 (git+https://github.com/Ygg01/xml5ever)", ] @@ -1752,7 +1758,9 @@ name = "script_tests" version = "0.0.1" dependencies = [ "msg 0.0.1", + "plugins 0.0.1", "script 0.0.1", + "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", ] @@ -1767,7 +1775,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1795,7 +1803,7 @@ dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1884,7 +1892,7 @@ dependencies = [ "gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "osmesa-sys 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1893,7 +1901,7 @@ dependencies = [ "user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-kbd 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wayland-window 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wayland-window 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "x11-dl 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1922,7 +1930,7 @@ name = "shared_library" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1956,13 +1964,13 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "debug_unreachable 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "phf_generator 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1980,7 +1988,7 @@ dependencies = [ "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1990,7 +1998,7 @@ dependencies = [ "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2007,7 +2015,7 @@ dependencies = [ "msg 0.0.1", "plugins 0.0.1", "selectors 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2022,7 +2030,7 @@ dependencies = [ "euclid 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", @@ -2038,7 +2046,7 @@ dependencies = [ name = "task_info" version = "0.0.1" dependencies = [ - "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2051,12 +2059,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "1.1.3" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2103,8 +2112,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicase" -version = "1.0.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-bidi" @@ -2184,10 +2196,10 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "js 0.1.2 (git+https://github.com/servo/rust-mozjs)", "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2197,7 +2209,7 @@ dependencies = [ "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2244,7 +2256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "dlib 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2263,16 +2275,16 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dlib 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wayland-window" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "wayland-client 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2293,8 +2305,8 @@ version = "0.0.1" dependencies = [ "compositing 0.0.1", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "image 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "plugins 0.0.1", @@ -2319,8 +2331,8 @@ dependencies = [ "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "gleam 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", - "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "offscreen_gl_context 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2339,7 +2351,7 @@ dependencies = [ "core-graphics 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-channel 0.2.1 (git+https://github.com/servo/ipc-channel)", + "ipc-channel 0.2.2 (git+https://github.com/servo/ipc-channel)", "offscreen_gl_context 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2347,17 +2359,17 @@ dependencies = [ [[package]] name = "websocket" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2424,7 +2436,7 @@ dependencies = [ "phf 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index f412b16af0a..a06e3093031 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -19,7 +19,7 @@ doc = false bench = false [dev-dependencies] -image = "0.7" +image = "0.9" [dev-dependencies.gfx_tests] path = "../../tests/unit/gfx" diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 6ddcd58222a..47c66b97590 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -81,8 +81,8 @@ use profile_traits::mem; use profile_traits::time; use std::rc::Rc; use std::sync::mpsc::Sender; -use util::opts; use util::resource_files::resources_dir_path; +use util::{opts, prefs}; pub use gleam::gl; @@ -251,6 +251,7 @@ pub fn run_content_process(token: String) { let unprivileged_content = unprivileged_content_receiver.recv().unwrap(); opts::set_defaults(unprivileged_content.opts()); + prefs::extend_prefs(unprivileged_content.prefs()); // Enter the sandbox if necessary. if opts::get().sandbox { @@ -275,7 +276,8 @@ pub unsafe extern fn __errno_location() -> *mut i32 { #[cfg(not(target_os = "windows"))] fn create_sandbox() { - ChildSandbox::new(sandboxing::content_process_sandbox_profile()).activate().unwrap(); + ChildSandbox::new(sandboxing::content_process_sandbox_profile()).activate() + .expect("Failed to activate sandbox!"); } #[cfg(target_os = "windows")] diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 82284240a26..6aee2f66cfd 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -31,7 +31,7 @@ euclid = {version = "0.6.4", features = ["plugins"]} fnv = "1.0" heapsize = "0.3.0" heapsize_plugin = "0.1.2" -lazy_static = "0.1.10" +lazy_static = "0.1.16" log = "0.3.5" matches = "0.1" num = "0.1.24" @@ -40,7 +40,6 @@ selectors = {version = "0.5", features = ["heap_size", "unstable"]} serde = {version = "0.7", features = ["nightly"]} serde_macros = "0.7" smallvec = "0.1" -string_cache = {version = "0.2.11", features = ["heap_size"]} +string_cache = {version = "0.2.12", features = ["heap_size"]} time = "0.1" url = {version = "0.5.7", features = ["heap_size"]} - diff --git a/components/style/animation.rs b/components/style/animation.rs index a7622c90f34..9c0242aa971 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -24,7 +24,7 @@ use properties::longhands::transition_timing_function::computed_value::{Transiti use properties::longhands::vertical_align::computed_value::T as VerticalAlign; use properties::longhands::visibility::computed_value::T as Visibility; use properties::longhands::z_index::computed_value::T as ZIndex; -use properties::style_struct_traits::TBox; +use properties::style_struct_traits::Box; use properties::{ComputedValues, ServoComputedValues}; use std::cmp::Ordering; use std::iter::repeat; diff --git a/components/style/build.rs b/components/style/build.rs index 88e301b6bba..4f7eaf76013 100644 --- a/components/style/build.rs +++ b/components/style/build.rs @@ -50,8 +50,8 @@ import sys from mako.template import Template from mako import exceptions try: - print(Template(filename=os.environ['TEMPLATE'], input_encoding='utf8').render(PRODUCT=os.environ['PRODUCT']) - .encode('utf8')) + template = Template(open(os.environ['TEMPLATE'], 'rb').read(), input_encoding='utf8') + print(template.render(PRODUCT=os.environ['PRODUCT']).encode('utf8')) except: sys.stderr.write(exceptions.text_error_template().render().encode('utf8')) sys.exit(1) diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index f3c2f512cf8..ecbfe5af015 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -9,6 +9,7 @@ // can be escaped. In the above example, Vec<<&Foo> achieves the desired result of Vec<&Foo>. use std::ascii::AsciiExt; +use std::boxed::Box as StdBox; use std::collections::HashSet; use std::fmt; use std::intrinsics; @@ -16,7 +17,8 @@ use std::mem; use std::sync::Arc; use app_units::Au; -use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser, Delimiter, +use cssparser::Color as CSSParserColor; +use cssparser::{Parser, RGBA, AtRuleParser, DeclarationParser, Delimiter, DeclarationListParser, parse_important, ToCss, TokenSerializationType}; use error_reporting::ParseErrorReporter; use url::Url; @@ -143,6 +145,9 @@ def new_style_struct(name, is_inherited, gecko_name=None, additional_methods=Non THIS_STYLE_STRUCT = style_struct return "" +def active_style_structs(): + return filter(lambda s: s.additional_methods or s.longhands, STYLE_STRUCTS) + def switch_to_style_struct(name): global THIS_STYLE_STRUCT @@ -202,8 +207,9 @@ pub mod longhands { use properties::longhands; use properties::property_bit_field::PropertyBitField; use properties::{ComputedValues, ServoComputedValues, PropertyDeclaration}; - use properties::style_struct_traits::T${THIS_STYLE_STRUCT.trait_name}; + use properties::style_struct_traits::${THIS_STYLE_STRUCT.trait_name}; use properties::style_structs; + use std::boxed::Box as StdBox; use std::collections::HashMap; use std::sync::Arc; use values::computed::{TContext, ToComputedValue}; @@ -217,7 +223,7 @@ pub mod longhands { context: &mut computed::Context<C>, seen: &mut PropertyBitField, cacheable: &mut bool, - error_reporter: &mut Box<ParseErrorReporter + Send>) { + error_reporter: &mut StdBox<ParseErrorReporter + Send>) { let declared_value = match *declaration { PropertyDeclaration::${property.camel_case}(ref declared_value) => { declared_value @@ -538,7 +544,6 @@ pub mod longhands { %> pub use self::computed_value::T as SpecifiedValue; use values::computed::{Context, ComputedValueAsSpecified}; - use properties::style_struct_traits::TInheritedText; pub mod computed_value { #[allow(non_camel_case_types)] @@ -590,7 +595,7 @@ pub mod longhands { context: &mut computed::Context<C>, _seen: &mut PropertyBitField, _cacheable: &mut bool, - _error_reporter: &mut Box<ParseErrorReporter + Send>) { + _error_reporter: &mut StdBox<ParseErrorReporter + Send>) { longhands::_servo_display_for_hypothetical_box::derive_from_display(context); longhands::_servo_text_decorations_in_effect::derive_from_display(context); } @@ -907,7 +912,11 @@ pub mod longhands { // CSS 2.1, Section 11 - Visual effects // Non-standard, see https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-box#Specifications - ${single_keyword("-servo-overflow-clip-box", "padding-box content-box", internal=True)} + ${single_keyword("-servo-overflow-clip-box", "padding-box content-box", products="servo", + internal=True)} + + ${single_keyword("overflow-clip-box", "padding-box content-box", products="gecko", + internal=True)} // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`. ${single_keyword("overflow-x", "visible hidden scroll auto")} @@ -950,6 +959,16 @@ pub mod longhands { } </%self:longhand> + // CSSOM View Module + // https://www.w3.org/TR/cssom-view-1/ + ${single_keyword("scroll-behavior", "auto smooth", products="gecko")} + + // Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-x + ${single_keyword("scroll-snap-type-x", "none mandatory proximity", products="gecko")} + + // Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-y + ${single_keyword("scroll-snap-type-y", "none mandatory proximity", products="gecko")} + ${switch_to_style_struct("InheritedBox")} // TODO: collapse. Well, do tables first. @@ -1352,6 +1371,12 @@ pub mod longhands { // CSS 2.1, Section 13 - Paged media + ${switch_to_style_struct("Box")} + + ${single_keyword("page-break-after", "auto always avoid left right", products="gecko")} + ${single_keyword("page-break-before", "auto always avoid left right", products="gecko")} + ${single_keyword("page-break-inside", "auto avoid", products="gecko")} + // CSS 2.1, Section 14 - Colors and Backgrounds ${new_style_struct("Background", is_inherited=False, gecko_name="nsStyleBackground")} @@ -1681,7 +1706,8 @@ pub mod longhands { "longhands::color::computed_value::T")])} <%self:raw_longhand name="color"> - use cssparser::{Color, RGBA}; + use cssparser::Color as CSSParserColor; + use cssparser::RGBA; use values::specified::{CSSColor, CSSRGBA}; impl ToComputedValue for SpecifiedValue { @@ -1705,8 +1731,8 @@ pub mod longhands { -> Result<DeclaredValue<SpecifiedValue>, ()> { let value = try!(CSSColor::parse(input)); let rgba = match value.parsed { - Color::RGBA(rgba) => rgba, - Color::CurrentColor => return Ok(DeclaredValue::Inherit) + CSSParserColor::RGBA(rgba) => rgba, + CSSParserColor::CurrentColor => return Ok(DeclaredValue::Inherit) }; Ok(DeclaredValue::Value(CSSRGBA { parsed: rgba, @@ -2024,6 +2050,8 @@ pub mod longhands { "normal ultra-condensed extra-condensed condensed semi-condensed semi-expanded \ expanded extra-expanded ultra-expanded")} + ${single_keyword("font-kerning", "auto none normal", products="gecko")} + // CSS 2.1, Section 16 - Text ${switch_to_style_struct("InheritedText")} @@ -2229,7 +2257,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::computed::ComputedValueAsSpecified; - use properties::style_struct_traits::TInheritedText; impl ComputedValueAsSpecified for SpecifiedValue {} @@ -2307,11 +2334,14 @@ pub mod longhands { context: &mut computed::Context<C>, _seen: &mut PropertyBitField, _cacheable: &mut bool, - _error_reporter: &mut Box<ParseErrorReporter + Send>) { + _error_reporter: &mut StdBox<ParseErrorReporter + Send>) { longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(context); } </%self:longhand> + ${single_keyword("text-decoration-style", "-moz-none solid double dotted dashed wavy", + products="gecko")} + ${switch_to_style_struct("InheritedText")} <%self:longhand name="-servo-text-decorations-in-effect" @@ -2320,7 +2350,7 @@ pub mod longhands { use std::fmt; use values::computed::ComputedValueAsSpecified; - use properties::style_struct_traits::{TBox, TColor, TText}; + use properties::style_struct_traits::{Box, Color, Text}; impl ComputedValueAsSpecified for SpecifiedValue {} @@ -2437,6 +2467,16 @@ pub mod longhands { ${single_keyword("text-rendering", "auto optimizespeed optimizelegibility geometricprecision")} + // CSS Text Module Level 3 + // https://www.w3.org/TR/css-text-3/ + ${single_keyword("hyphens", "none manual auto", products="gecko")} + + // CSS Ruby Layout Module Level 1 + // https://www.w3.org/TR/css-ruby-1/ + ${single_keyword("ruby-align", "start center space-between space-around", products="gecko")} + + ${single_keyword("ruby-position", "over under", products="gecko")} + // CSS 2.1, Section 17 - Tables ${new_style_struct("Table", is_inherited=False, gecko_name="nsStyleTable")} @@ -2539,8 +2579,11 @@ pub mod longhands { } </%self:longhand> - // CSS 2.1, Section 18 - User interface + // CSS Fragmentation Module Level 3 + // https://www.w3.org/TR/css-break-3/ + ${switch_to_style_struct("Border")} + ${single_keyword("box-decoration-break", "slice clone", products="gecko")} // CSS Writing Modes Level 3 // http://dev.w3.org/csswg/css-writing-modes/ @@ -2552,8 +2595,16 @@ pub mod longhands { // FIXME(SimonSapin): initial (first) value should be 'mixed', when that's implemented ${single_keyword("text-orientation", "sideways sideways-left sideways-right", experimental=True)} + // CSS Color Module Level 4 + // https://drafts.csswg.org/css-color/ + ${single_keyword("color-adjust", "economy exact", products="gecko")} + // CSS Basic User Interface Module Level 3 // http://dev.w3.org/csswg/css-ui/ + ${switch_to_style_struct("Box")} + + ${single_keyword("resize", "none both horizontal vertical", products="gecko")} + ${switch_to_style_struct("Position")} ${single_keyword("box-sizing", "content-box border-box")} @@ -4160,6 +4211,8 @@ pub mod longhands { ${single_keyword("backface-visibility", "visible hidden")} + ${single_keyword("transform-box", "border-box fill-box view-box", products="gecko")} + ${single_keyword("transform-style", "auto flat preserve-3d")} <%self:longhand name="transform-origin"> @@ -4314,11 +4367,26 @@ pub mod longhands { } </%self:longhand> + // Compositing and Blending Level 1 + // http://www.w3.org/TR/compositing-1/ + ${single_keyword("isolation", "auto isolate", products="gecko")} + ${single_keyword("mix-blend-mode", """normal multiply screen overlay darken lighten color-dodge color-burn hard-light soft-light difference exclusion hue saturation color luminosity""")} + // CSS Masking Module Level 1 + // https://www.w3.org/TR/css-masking-1/ + ${single_keyword("mask-type", "luminance alpha", products="gecko")} + + // CSS Image Values and Replaced Content Module Level 3 + // https://drafts.csswg.org/css-images-3/ + + ${switch_to_style_struct("Position")} + + ${single_keyword("object-fit", "fill contain cover none scale-down", products="gecko")} + ${switch_to_style_struct("InheritedBox")} <%self:longhand name="image-rendering"> @@ -4906,6 +4974,65 @@ pub mod longhands { // Flex container properties ${single_keyword("flex-direction", "row row-reverse column column-reverse", experimental=True)} + + // https://drafts.csswg.org/css-flexbox/#propdef-order + <%self:longhand name="order"> + use values::computed::ComputedValueAsSpecified; + + impl ComputedValueAsSpecified for SpecifiedValue {} + + pub type SpecifiedValue = computed_value::T; + + pub mod computed_value { + pub type T = i32; + } + + #[inline] + pub fn get_initial_value() -> computed_value::T { + 0 + } + + fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { + specified::parse_integer(input) + } + </%self:longhand> + + ${single_keyword("flex-wrap", "nowrap wrap wrap-reverse", products="gecko")} + + // SVG 1.1 (Second Edition) + // https://www.w3.org/TR/SVG/ + ${new_style_struct("SVG", is_inherited=True)} + + // Section 10 - Text + ${single_keyword("dominant-baseline", + """auto use-script no-change reset-size ideographic alphabetic hanging + mathematical central middle text-after-edge text-before-edge""", + products="gecko")} + + ${single_keyword("text-anchor", "start middle end", products="gecko")} + + // Section 11 - Painting: Filling, Stroking and Marker Symbols + ${single_keyword("color-interpolation", "auto sRGB linearRGB", products="gecko")} + + ${single_keyword("color-interpolation-filters", "auto sRGB linearRGB", products="gecko")} + + ${single_keyword("fill-rule", "nonzero evenodd", products="gecko")} + + ${single_keyword("shape-rendering", "auto optimizeSpeed crispEdges geometricPrecision", + products="gecko")} + + ${single_keyword("stroke-linecap", "butt round square", products="gecko")} + + ${single_keyword("stroke-linejoin", "miter round bevel", products="gecko")} + + ${switch_to_style_struct("Effects")} + + ${single_keyword("vector-effect", "none non-scaling-stroke", products="gecko")} + + ${switch_to_style_struct("SVG")} + + // Section 14 - Clipping, Masking and Compositing + ${single_keyword("clip-rule", "nonzero evenodd", products="gecko")} } @@ -5670,7 +5797,7 @@ mod property_bit_field { value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, f: F, - error_reporter: &mut Box<ParseErrorReporter + Send>) + error_reporter: &mut StdBox<ParseErrorReporter + Send>) where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) { if let DeclaredValue::WithVariables { @@ -5697,7 +5824,7 @@ mod property_bit_field { from_shorthand: Option<Shorthand>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, f: F, - error_reporter: &mut Box<ParseErrorReporter + Send>) + error_reporter: &mut StdBox<ParseErrorReporter + Send>) where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) { f(& ::custom_properties::substitute(css, first_token_type, custom_properties) @@ -5747,13 +5874,13 @@ pub struct PropertyDeclarationBlock { pub normal: Arc<Vec<PropertyDeclaration>>, } -pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: Box<ParseErrorReporter + Send>) +pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>) -> PropertyDeclarationBlock { let context = ParserContext::new(Origin::Author, base_url, error_reporter); parse_property_declaration_list(&context, &mut Parser::new(input)) } -pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: Box<ParseErrorReporter + Send>) +pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>) -> Result<Vec<PropertyDeclaration>, ()> { let context = ParserContext::new(Origin::Author, base_url, error_reporter); let mut results = vec![]; @@ -6166,8 +6293,8 @@ impl PropertyDeclaration { pub mod style_struct_traits { use super::longhands; - % for style_struct in STYLE_STRUCTS: - pub trait T${style_struct.trait_name}: Clone { + % for style_struct in active_style_structs(): + pub trait ${style_struct.trait_name}: Clone { % for longhand in style_struct.longhands: #[allow(non_snake_case)] fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T); @@ -6187,7 +6314,7 @@ pub mod style_structs { use super::longhands; use std::hash::{Hash, Hasher}; - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): % if style_struct.trait_name == "Font": #[derive(Clone, HeapSizeOf, Debug)] % else: @@ -6213,7 +6340,7 @@ pub mod style_structs { } % endif - impl super::style_struct_traits::T${style_struct.trait_name} for ${style_struct.servo_struct_name} { + impl super::style_struct_traits::${style_struct.trait_name} for ${style_struct.servo_struct_name} { % for longhand in style_struct.longhands: fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) { self.${longhand.ident} = v; @@ -6303,8 +6430,8 @@ pub mod style_structs { } pub trait ComputedValues : Clone + Send + Sync + 'static { - % for style_struct in STYLE_STRUCTS: - type Concrete${style_struct.trait_name}: style_struct_traits::T${style_struct.trait_name}; + % for style_struct in active_style_structs(): + type Concrete${style_struct.trait_name}: style_struct_traits::${style_struct.trait_name}; % endfor // Temporary bailout case for stuff we haven't made work with the trait @@ -6318,7 +6445,7 @@ pub trait ComputedValues : Clone + Send + Sync + 'static { shareable: bool, writing_mode: WritingMode, root_font_size: Au, - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): ${style_struct.ident}: Arc<Self::Concrete${style_struct.trait_name}>, % endfor ) -> Self; @@ -6327,7 +6454,7 @@ pub trait ComputedValues : Clone + Send + Sync + 'static { fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(f: F); - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): fn clone_${style_struct.trait_name_lower}(&self) -> Arc<Self::Concrete${style_struct.trait_name}>; fn get_${style_struct.trait_name_lower}<'a>(&'a self) -> @@ -6345,7 +6472,7 @@ pub trait ComputedValues : Clone + Send + Sync + 'static { #[derive(Clone, HeapSizeOf)] pub struct ServoComputedValues { - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): ${style_struct.ident}: Arc<style_structs::${style_struct.servo_struct_name}>, % endfor custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, @@ -6355,7 +6482,7 @@ pub struct ServoComputedValues { } impl ComputedValues for ServoComputedValues { - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): type Concrete${style_struct.trait_name} = style_structs::${style_struct.servo_struct_name}; % endfor @@ -6366,7 +6493,7 @@ impl ComputedValues for ServoComputedValues { shareable: bool, writing_mode: WritingMode, root_font_size: Au, - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): ${style_struct.ident}: Arc<style_structs::${style_struct.servo_struct_name}>, % endfor ) -> Self { @@ -6375,7 +6502,7 @@ impl ComputedValues for ServoComputedValues { shareable: shareable, writing_mode: writing_mode, root_font_size: root_font_size, - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): ${style_struct.ident}: ${style_struct.ident}, % endfor } @@ -6387,7 +6514,7 @@ impl ComputedValues for ServoComputedValues { CASCADE_PROPERTY.with(|x| f(x)); } - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): #[inline] fn clone_${style_struct.trait_name_lower}(&self) -> Arc<Self::Concrete${style_struct.trait_name}> { @@ -6430,10 +6557,10 @@ impl ServoComputedValues { /// Usage example: /// let top_color = style.resolve_color(style.Border.border_top_color); #[inline] - pub fn resolve_color(&self, color: Color) -> RGBA { + pub fn resolve_color(&self, color: CSSParserColor) -> RGBA { match color { - Color::RGBA(rgba) => rgba, - Color::CurrentColor => self.get_color().color, + CSSParserColor::RGBA(rgba) => rgba, + CSSParserColor::CurrentColor => self.get_color().color, } } @@ -6589,7 +6716,7 @@ impl ServoComputedValues { pub fn computed_value_to_string(&self, name: &str) -> Result<String, ()> { match name { - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): % for longhand in style_struct.longhands: "${longhand.name}" => Ok(self.${style_struct.ident}.${longhand.ident}.to_css_string()), % endfor @@ -6606,7 +6733,7 @@ impl ServoComputedValues { /// Return a WritingMode bitflags from the relevant CSS properties. -pub fn get_writing_mode<S: style_struct_traits::TInheritedBox>(inheritedbox_style: &S) -> WritingMode { +pub fn get_writing_mode<S: style_struct_traits::InheritedBox>(inheritedbox_style: &S) -> WritingMode { use logical_geometry; let mut flags = WritingMode::empty(); match inheritedbox_style.clone_direction() { @@ -6643,7 +6770,7 @@ pub fn get_writing_mode<S: style_struct_traits::TInheritedBox>(inheritedbox_styl /// The initial values for all style structs as defined by the specification. lazy_static! { pub static ref INITIAL_SERVO_VALUES: ServoComputedValues = ServoComputedValues { - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): ${style_struct.ident}: Arc::new(style_structs::${style_struct.servo_struct_name} { % for longhand in style_struct.longhands: ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(), @@ -6670,7 +6797,7 @@ fn cascade_with_cached_declarations<C: ComputedValues>( parent_style: &C, cached_style: &C, custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, - mut error_reporter: Box<ParseErrorReporter + Send>) + mut error_reporter: StdBox<ParseErrorReporter + Send>) -> C { let mut context = computed::Context { is_root_element: false, @@ -6681,7 +6808,7 @@ fn cascade_with_cached_declarations<C: ComputedValues>( shareable, WritingMode::empty(), parent_style.root_font_size(), - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): % if style_struct.inherited: parent_style % else: @@ -6698,13 +6825,13 @@ fn cascade_with_cached_declarations<C: ComputedValues>( // Declarations are already stored in reverse order. for declaration in sub_list.declarations.iter() { match *declaration { - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): % for property in style_struct.longhands: % if property.derived_from is None: PropertyDeclaration::${property.camel_case}(ref ${'_' if not style_struct.inherited else ''}declared_value) => { - use properties::style_struct_traits::T${style_struct.trait_name}; + use properties::style_struct_traits::${style_struct.trait_name}; % if style_struct.inherited: if seen.get_${property.ident}() { continue @@ -6762,7 +6889,7 @@ fn cascade_with_cached_declarations<C: ComputedValues>( if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || seen.get_font_family() { - use properties::style_struct_traits::TFont; + use properties::style_struct_traits::Font; context.mutate_style().mutate_font().compute_font_hash(); } @@ -6775,11 +6902,11 @@ pub type CascadePropertyFn<C /*: ComputedValues */> = context: &mut computed::Context<C>, seen: &mut PropertyBitField, cacheable: &mut bool, - error_reporter: &mut Box<ParseErrorReporter + Send>); + error_reporter: &mut StdBox<ParseErrorReporter + Send>); pub fn make_cascade_vec<C: ComputedValues>() -> Vec<Option<CascadePropertyFn<C>>> { let mut result: Vec<Option<CascadePropertyFn<C>>> = Vec::new(); - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): % for property in style_struct.longhands: let discriminant; unsafe { @@ -6826,9 +6953,9 @@ pub fn cascade<C: ComputedValues>( shareable: bool, parent_style: Option<<&C>, cached_style: Option<<&C>, - mut error_reporter: Box<ParseErrorReporter + Send>) + mut error_reporter: StdBox<ParseErrorReporter + Send>) -> (C, bool) { - use properties::style_struct_traits::{TBorder, TBox, TColor, TFont, TOutline}; + use properties::style_struct_traits::{Border, Box, Color, Font, Outline}; let initial_values = C::initial_values(); let (is_root_element, inherited_style) = match parent_style { Some(parent_style) => (false, parent_style), @@ -6874,7 +7001,7 @@ pub fn cascade<C: ComputedValues>( shareable, WritingMode::empty(), inherited_style.root_font_size(), - % for style_struct in STYLE_STRUCTS: + % for style_struct in active_style_structs(): % if style_struct.inherited: inherited_style % else: @@ -7007,7 +7134,7 @@ pub fn cascade<C: ComputedValues>( if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || seen.get_font_family() { - use properties::style_struct_traits::TFont; + use properties::style_struct_traits::Font; style.mutate_font().compute_font_hash(); } diff --git a/components/style/values.rs b/components/style/values.rs index dff9f3935cd..754125bfc21 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -1437,7 +1437,7 @@ pub mod computed { use app_units::Au; use euclid::size::Size2D; use properties::ComputedValues; - use properties::style_struct_traits::TFont; + use properties::style_struct_traits::Font; use std::fmt; use super::AuExtensionMethods; use super::specified::AngleOrCorner; diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 07bb2a7f392..7a4bdf9379c 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -44,7 +44,7 @@ rustc-serialize = "0.3" serde = "0.7" serde_macros = "0.7" smallvec = "0.1" -string_cache = {version = "0.2.11", features = ["heap_size"]} +string_cache = {version = "0.2.12", features = ["heap_size"]} url = {version = "0.5.7", features = ["heap_size", "serde_serialization"]} [target.x86_64-pc-windows-gnu.dependencies] diff --git a/components/util/prefs.rs b/components/util/prefs.rs index ff7fbbe5a7e..43286f2137f 100644 --- a/components/util/prefs.rs +++ b/components/util/prefs.rs @@ -19,10 +19,11 @@ lazy_static! { }; } -#[derive(PartialEq, Clone, Debug)] +#[derive(PartialEq, Clone, Debug, Deserialize, Serialize)] pub enum PrefValue { Boolean(bool), String(String), + Number(f64), Missing } @@ -31,6 +32,9 @@ impl PrefValue { let value = match data { Json::Boolean(x) => PrefValue::Boolean(x), Json::String(x) => PrefValue::String(x), + Json::F64(x) => PrefValue::Number(x), + Json::I64(x) => PrefValue::Number(x as f64), + Json::U64(x) => PrefValue::Number(x as f64), _ => return Err(()) }; Ok(value) @@ -53,6 +57,13 @@ impl PrefValue { _ => None } } + + pub fn as_i64(&self) -> Option<i64> { + match *self { + PrefValue::Number(x) => Some(x as i64), + _ => None, + } + } } impl ToJson for PrefValue { @@ -63,13 +74,16 @@ impl ToJson for PrefValue { }, PrefValue::String(ref x) => { Json::String(x.clone()) - } + }, + PrefValue::Number(x) => { + Json::F64(x) + }, PrefValue::Missing => Json::Null } } } -#[derive(Debug)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub enum Pref { NoDefault(Arc<PrefValue>), WithDefault(Arc<PrefValue>, Option<Arc<PrefValue>>) @@ -136,13 +150,17 @@ pub fn read_prefs_from_file<T>(mut file: T) Ok(x) => { prefs.insert(name, x); }, - Err(_) => println!("Ignoring non-boolean/string preference value for {:?}", name) + Err(_) => println!("Ignoring non-boolean/string/i64 preference value for {:?}", name), } } } Ok(prefs) } +pub fn get_cloned() -> HashMap<String, Pref> { + PREFS.lock().unwrap().clone() +} + pub fn extend_prefs(extension: HashMap<String, Pref>) { PREFS.lock().unwrap().extend(extension); } diff --git a/components/util/resource_files.rs b/components/util/resource_files.rs index dcb9646f42c..9df1b2de89c 100644 --- a/components/util/resource_files.rs +++ b/components/util/resource_files.rs @@ -2,6 +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::env; use std::fs::File; use std::io::{self, Read}; use std::path::PathBuf; @@ -25,35 +26,35 @@ pub fn resources_dir_path() -> PathBuf { #[cfg(not(target_os = "android"))] pub fn resources_dir_path() -> PathBuf { - use std::env; + let mut dir = CMD_RESOURCE_DIR.lock().unwrap(); + + if let Some(ref path) = *dir { + return PathBuf::from(path); + } - match *CMD_RESOURCE_DIR.lock().unwrap() { - Some(ref path) => PathBuf::from(path), - None => { - // FIXME: Find a way to not rely on the executable being - // under `<servo source>[/$target_triple]/target/debug` - // or `<servo source>[/$target_triple]/target/release`. - let mut path = env::current_exe().expect("can't get exe path"); - // Follow symlink - path = path.canonicalize().expect("path does not exist"); + // FIXME: Find a way to not rely on the executable being + // under `<servo source>[/$target_triple]/target/debug` + // or `<servo source>[/$target_triple]/target/release`. + let mut path = env::current_exe().expect("can't get exe path"); + // Follow symlink + path = path.canonicalize().expect("path does not exist"); + path.pop(); + path.push("resources"); + if !path.is_dir() { // resources dir not in same dir as exe? + // exe is probably in target/{debug,release} so we need to go back to topdir + path.pop(); + path.pop(); + path.pop(); + path.push("resources"); + if !path.is_dir() { + // exe is probably in target/$target_triple/{debug,release} so go back one more + path.pop(); path.pop(); path.push("resources"); - if !path.is_dir() { // resources dir not in same dir as exe? - // exe is probably in target/{debug,release} so we need to go back to topdir - path.pop(); - path.pop(); - path.pop(); - path.push("resources"); - if !path.is_dir() { - // exe is probably in target/$target_triple/{debug,release} so go back one more - path.pop(); - path.pop(); - path.push("resources"); - } - } - path } } + *dir = Some(path.to_str().unwrap().to_owned()); + path } pub fn read_resource_file(relative_path_components: &[&str]) -> io::Result<Vec<u8>> { diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index 547ae03fc8e..02b90a58fe3 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -24,7 +24,7 @@ path = "../util" git = "https://github.com/servo/ipc-channel" [dependencies] -image = "0.7" +image = "0.9" log = "0.3.5" hyper = "0.8" rustc-serialize = "0.3.4" |