aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/animation.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-05-15 15:00:19 -0500
committerGitHub <noreply@github.com>2017-05-15 15:00:19 -0500
commitfa251ec96b445b9ba8439d76e05870a88c2caa0f (patch)
treed4fe49b542c7585a7f9acec508082c8e82f391ef /components/layout/animation.rs
parentdfb939629616490af4248c58ec3675244dc10e27 (diff)
parentb0bf2b4bad636acfba66d55571b417ebae795408 (diff)
downloadservo-fa251ec96b445b9ba8439d76e05870a88c2caa0f.tar.gz
servo-fa251ec96b445b9ba8439d76e05870a88c2caa0f.zip
Auto merge of #16295 - jdm:transition-safety, r=nox
Root nodes for the duration of their CSS transitions This ensures that we can pass a node address as part of the asynchronous transition end notification, making it safe to fire the corresponding DOM event on the node from the script thread. Without explicitly rooting this node when the transition starts, we risk the node being GCed before the transition is complete. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #14972 - [X] There are tests for these changes <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16295) <!-- Reviewable:end -->
Diffstat (limited to 'components/layout/animation.rs')
-rw-r--r--components/layout/animation.rs20
1 files changed, 17 insertions, 3 deletions
diff --git a/components/layout/animation.rs b/components/layout/animation.rs
index be6d5baf77c..d1673ac44a1 100644
--- a/components/layout/animation.rs
+++ b/components/layout/animation.rs
@@ -9,7 +9,9 @@ use flow::{self, Flow};
use gfx::display_list::OpaqueNode;
use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId;
+use opaque_node::OpaqueNodeMethods;
use script_traits::{AnimationState, ConstellationControlMsg, LayoutMsg as ConstellationMsg};
+use script_traits::UntrustedNodeAddress;
use std::collections::HashMap;
use std::sync::mpsc::Receiver;
use style::animation::{Animation, update_style_for_animation};
@@ -24,6 +26,7 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
script_chan: &IpcSender<ConstellationControlMsg>,
running_animations: &mut HashMap<OpaqueNode, Vec<Animation>>,
expired_animations: &mut HashMap<OpaqueNode, Vec<Animation>>,
+ mut newly_transitioning_nodes: Option<&mut Vec<UntrustedNodeAddress>>,
new_animations_receiver: &Receiver<Animation>,
pipeline_id: PipelineId,
timer: &Timer) {
@@ -71,7 +74,7 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
let mut animations_still_running = vec![];
for mut running_animation in running_animations.drain(..) {
let still_running = !running_animation.is_expired() && match running_animation {
- Animation::Transition(_, _, started_at, ref frame, _expired) => {
+ Animation::Transition(_, started_at, ref frame, _expired) => {
now < started_at + frame.duration
}
Animation::Keyframes(_, _, ref mut state) => {
@@ -86,8 +89,8 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
continue
}
- if let Animation::Transition(_, unsafe_node, _, ref frame, _) = running_animation {
- script_chan.send(ConstellationControlMsg::TransitionEnd(unsafe_node,
+ if let Animation::Transition(node, _, ref frame, _) = running_animation {
+ script_chan.send(ConstellationControlMsg::TransitionEnd(node.to_untrusted_node_address(),
frame.property_animation
.property_name().into(),
frame.duration))
@@ -112,6 +115,17 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
// Add new running animations.
for new_running_animation in new_running_animations {
+ if new_running_animation.is_transition() {
+ match newly_transitioning_nodes {
+ Some(ref mut nodes) => {
+ nodes.push(new_running_animation.node().to_untrusted_node_address());
+ }
+ None => {
+ warn!("New transition encountered from compositor-initiated layout.");
+ }
+ }
+ }
+
running_animations.entry(*new_running_animation.node())
.or_insert_with(Vec::new)
.push(new_running_animation)