diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-23 10:50:37 -0700 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-05-23 10:50:37 -0700 |
commit | 7d02c2055d5c5c7a5a6b1fff34bbef75e1da7cf6 (patch) | |
tree | 0b7f005ac4432a7159527b94a5586eda02547d77 | |
parent | 208337976d0b913e00fe9c090c6868027092a0a1 (diff) | |
parent | 1e9be028cf6f5f347dcf2d6f66caa850ec3ee6e4 (diff) | |
download | servo-7d02c2055d5c5c7a5a6b1fff34bbef75e1da7cf6.tar.gz servo-7d02c2055d5c5c7a5a6b1fff34bbef75e1da7cf6.zip |
Auto merge of #11341 - nox:raf, r=pcwalton
Use a simple Vec for the animation frame list
Adding an animation frame list is now just pushing a new pair onto the vector,
while canceling one is setting its callback to None.
This means we can't send NoAnimationCallbacksPresent anymore to the constellation
when all entries were cancelled, but I'm not sure that's very important anyway.
The good downside of this change is that when running the callbacks, if no
new one was queued during their execution, we can just swap back the original Vec
into the Document in run_the_animation_frame_callbacks, thus reusing the
original allocation.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11341)
<!-- Reviewable:end -->
-rw-r--r-- | components/script/dom/document.rs | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 10645b761d7..2aebe049d21 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -112,8 +112,8 @@ use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::boxed::FnBox; use std::cell::{Cell, Ref, RefMut}; +use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::collections::{BTreeMap, HashMap}; use std::default::Default; use std::mem; use std::ptr; @@ -200,7 +200,7 @@ pub struct Document { /// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks /// List of animation frame callbacks #[ignore_heap_size_of = "closures are hard"] - animation_frame_list: DOMRefCell<BTreeMap<u32, Box<FnBox(f64)>>>, + animation_frame_list: DOMRefCell<Vec<(u32, Option<Box<FnBox(f64)>>)>>, /// Whether we're in the process of running animation callbacks. /// /// Tracking this is not necessary for correctness. Instead, it is an optimization to avoid @@ -1282,7 +1282,7 @@ impl Document { let ident = self.animation_frame_ident.get() + 1; self.animation_frame_ident.set(ident); - self.animation_frame_list.borrow_mut().insert(ident, callback); + self.animation_frame_list.borrow_mut().push((ident, Some(callback))); // No need to send a `ChangeRunningAnimationsState` if we're running animation callbacks: // we're guaranteed to already be in the "animation callbacks present" state. @@ -1303,25 +1303,25 @@ impl Document { /// https://html.spec.whatwg.org/multipage/#dom-window-cancelanimationframe pub fn cancel_animation_frame(&self, ident: u32) { - self.animation_frame_list.borrow_mut().remove(&ident); - if self.animation_frame_list.borrow().is_empty() { - let event = ConstellationMsg::ChangeRunningAnimationsState(self.window.pipeline(), - AnimationState::NoAnimationCallbacksPresent); - self.window.constellation_chan().send(event).unwrap(); + let mut list = self.animation_frame_list.borrow_mut(); + if let Some(mut pair) = list.iter_mut().find(|pair| pair.0 == ident) { + pair.1 = None; } } /// https://html.spec.whatwg.org/multipage/#run-the-animation-frame-callbacks pub fn run_the_animation_frame_callbacks(&self) { - let animation_frame_list = - mem::replace(&mut *self.animation_frame_list.borrow_mut(), BTreeMap::new()); + let mut animation_frame_list = + mem::replace(&mut *self.animation_frame_list.borrow_mut(), vec![]); self.running_animation_callbacks.set(true); let performance = self.window.Performance(); let performance = performance.r(); let timing = performance.Now(); - for (_, callback) in animation_frame_list { - callback(*timing); + for (_, callback) in animation_frame_list.drain(..) { + if let Some(callback) = callback { + callback(*timing); + } } // Only send the animation change state message after running any callbacks. @@ -1329,6 +1329,8 @@ impl Document { // the next frame (which is the common case), we won't send a NoAnimationCallbacksPresent // message quickly followed by an AnimationCallbacksPresent message. if self.animation_frame_list.borrow().is_empty() { + mem::swap(&mut *self.animation_frame_list.borrow_mut(), + &mut animation_frame_list); let event = ConstellationMsg::ChangeRunningAnimationsState(self.window.pipeline(), AnimationState::NoAnimationCallbacksPresent); self.window.constellation_chan().send(event).unwrap(); @@ -1686,7 +1688,7 @@ impl Document { asap_scripts_set: DOMRefCell::new(vec![]), scripting_enabled: Cell::new(browsing_context.is_some()), animation_frame_ident: Cell::new(0), - animation_frame_list: DOMRefCell::new(BTreeMap::new()), + animation_frame_list: DOMRefCell::new(vec![]), running_animation_callbacks: Cell::new(false), loader: DOMRefCell::new(doc_loader), current_parser: Default::default(), |