diff --git a/components/layout/animation.rs b/components/layout/animation.rs index ebde01323e5..9b1d0671b9a 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -26,7 +26,7 @@ pub fn update_animation_state(constellation_chan: &IpcSender, script_chan: &IpcSender, running_animations: &mut HashMap>, expired_animations: &mut HashMap>, - newly_transitioning_nodes: &mut Vec, + mut newly_transitioning_nodes: Option<&mut Vec>, new_animations_receiver: &Receiver, pipeline_id: PipelineId, timer: &Timer) { @@ -115,8 +115,11 @@ pub fn update_animation_state(constellation_chan: &IpcSender, // Add new running animations. for new_running_animation in new_running_animations { - if new_running_animation.is_transition() { - newly_transitioning_nodes.push(new_running_animation.node().to_untrusted_node_address()); + match newly_transitioning_nodes { + Some(ref mut nodes) if new_running_animation.is_transition() => { + nodes.push(new_running_animation.node().to_untrusted_node_address()); + } + _ => () } running_animations.entry(*new_running_animation.node()) diff --git a/components/layout/context.rs b/components/layout/context.rs index 214061e276f..8acbc3b254a 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -15,6 +15,7 @@ use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder}; use opaque_node::OpaqueNodeMethods; use parking_lot::RwLock; use script_layout_interface::{PendingImage, PendingImageState}; +use script_traits::UntrustedNodeAddress; use servo_url::ServoUrl; use std::borrow::{Borrow, BorrowMut}; use std::cell::{RefCell, RefMut}; @@ -96,7 +97,11 @@ pub struct LayoutContext<'a> { /// A list of in-progress image loads to be shared with the script thread. /// A None value means that this layout was not initiated by the script thread. - pub pending_images: Option>> + pub pending_images: Option>>, + + /// A list of nodes that have just initiated a CSS transition. + /// A None value means that this layout was not initiated by the script thread. + pub newly_transitioning_nodes: Option>>, } impl<'a> Drop for LayoutContext<'a> { diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 2bef4bc1c21..32b47d57a22 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -514,7 +514,7 @@ impl LayoutThread { // Create a layout context for use in building display lists, hit testing, &c. fn build_layout_context<'a>(&'a self, guards: StylesheetGuards<'a>, - request_images: bool, + script_initiated_layout: bool, snapshot_map: &'a SnapshotMap) -> LayoutContext<'a> { let thread_local_style_context_creation_data = @@ -538,7 +538,8 @@ impl LayoutThread { image_cache: self.image_cache.clone(), font_cache_thread: Mutex::new(self.font_cache_thread.clone()), webrender_image_cache: self.webrender_image_cache.clone(), - pending_images: if request_images { Some(Mutex::new(vec![])) } else { None }, + pending_images: if script_initiated_layout { Some(Mutex::new(vec![])) } else { None }, + newly_transitioning_nodes: if script_initiated_layout { Some(Mutex::new(vec![])) } else { None }, } } @@ -1252,6 +1253,12 @@ impl LayoutThread { }; rw_data.pending_images = pending_images; + let newly_transitioning_nodes = match context.newly_transitioning_nodes { + Some(ref nodes) => std_mem::replace(&mut *nodes.lock().unwrap(), vec![]), + None => vec![], + }; + rw_data.newly_transitioning_nodes = newly_transitioning_nodes; + let mut root_flow = match self.root_flow.borrow().clone() { Some(root_flow) => root_flow, None => return, @@ -1427,6 +1434,7 @@ impl LayoutThread { &mut *rw_data, &mut layout_context); assert!(layout_context.pending_images.is_none()); + assert!(layout_context.newly_transitioning_nodes.is_none()); } } @@ -1437,17 +1445,24 @@ impl LayoutThread { document: Option<&ServoLayoutDocument>, rw_data: &mut LayoutThreadData, context: &mut LayoutContext) { - assert!(rw_data.newly_transitioning_nodes.is_empty()); - - // Kick off animations if any were triggered, expire completed ones. - animation::update_animation_state(&self.constellation_chan, - &self.script_chan, - &mut *self.running_animations.write(), - &mut *self.expired_animations.write(), - &mut rw_data.newly_transitioning_nodes, - &self.new_animations_receiver, - self.id, - &self.timer); + { + let mut newly_transitioning_nodes = context + .newly_transitioning_nodes + .as_ref() + .map(|nodes| nodes.lock().unwrap()); + let newly_transitioning_nodes = newly_transitioning_nodes + .as_mut() + .map(|nodes| &mut **nodes); + // Kick off animations if any were triggered, expire completed ones. + animation::update_animation_state(&self.constellation_chan, + &self.script_chan, + &mut *self.running_animations.write(), + &mut *self.expired_animations.write(), + newly_transitioning_nodes, + &self.new_animations_receiver, + self.id, + &self.timer); + } profile(time::ProfilerCategory::LayoutRestyleDamagePropagation, self.profiler_metadata(),