Bug 1464396 - Part 1: Hold all animation's created time. r=pbro
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 29 May 2018 10:09:35 +0900
changeset 420193 732a958aa5cd2d822f80993e8d7be5cf3e8b6128
parent 420192 01356631164ab02fa39a383dcd22a4618e7ed412
child 420194 9353259c9adfd54bdfb6859f9e8a5f186eb7c3e1
push id64542
push userdakatsuka@mozilla.com
push dateTue, 29 May 2018 04:28:34 +0000
treeherderautoland@97aee105338e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1464396
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1464396 - Part 1: Hold all animation's created time. r=pbro For now, we had taken over the createdTime to new actor from previous actor. However, if the selected node changed, can not take over that. To resolve this, hold all animation's createdTime. MozReview-Commit-ID: 5UcwGaWkcNg
devtools/server/actors/animation.js
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -611,25 +611,30 @@ exports.AnimationsActor = protocol.Actor
 
     this.onWillNavigate = this.onWillNavigate.bind(this);
     this.onNavigate = this.onNavigate.bind(this);
     this.onAnimationMutation = this.onAnimationMutation.bind(this);
 
     this.allAnimationsPaused = false;
     this.tabActor.on("will-navigate", this.onWillNavigate);
     this.tabActor.on("navigate", this.onNavigate);
+
+    this.animationCreatedTimeMap = new Map();
   },
 
   destroy: function() {
     Actor.prototype.destroy.call(this);
     this.tabActor.off("will-navigate", this.onWillNavigate);
     this.tabActor.off("navigate", this.onNavigate);
 
     this.stopAnimationPlayerUpdates();
     this.tabActor = this.observer = this.actors = this.walker = null;
+
+    this.animationCreatedTimeMap.clear();
+    this.animationCreatedTimeMap = null;
   },
 
   /**
    * Clients can optionally call this with a reference to their WalkerActor.
    * If they do, then AnimationPlayerActor's forms are going to also include
    * NodeActor IDs when the corresponding NodeActors do exist.
    * This, in turns, is helpful for clients to avoid having to go back once more
    * to the server to get a NodeActor for a particular animation.
@@ -645,39 +650,31 @@ exports.AnimationsActor = protocol.Actor
    * Note that calling this method a second time will destroy all previously
    * retrieved AnimationPlayerActors. Indeed, the lifecycle of these actors
    * is managed here on the server and tied to getAnimationPlayersForNode
    * being called.
    * @param {NodeActor} nodeActor The NodeActor as defined in
    * /devtools/server/actors/inspector
    */
   getAnimationPlayersForNode: function(nodeActor) {
-    let animations = nodeActor.rawNode.getAnimations({subtree: true});
+    this.updateAllAnimationsCreatedTime();
 
-    const createdTimeMap = new Map();
+    let animations = nodeActor.rawNode.getAnimations({subtree: true});
 
     // Destroy previously stored actors
     if (this.actors) {
       for (const actor of this.actors) {
-        // Take the createdTime over new actors.
-        createdTimeMap.set(actor.player, actor.createdTime);
         actor.destroy();
       }
     }
 
     this.actors = [];
 
     for (const animation of animations) {
-      let createdTime = createdTimeMap.get(animation);
-
-      if (typeof createdTime === "undefined") {
-        // If no previous actor, set startTime or currentTime of timeline as created time.
-        createdTime = animation.startTime || animation.timeline.currentTime;
-      }
-
+      const createdTime = this.getCreatedTime(animation);
       const actor = AnimationPlayerActor(this, animation, createdTime);
       this.actors.push(actor);
     }
 
     // When a front requests the list of players for a node, start listening
     // for animation mutations on this node to send updates to the front, until
     // either getAnimationPlayersForNode is called again or
     // stopAnimationPlayerUpdates is called.
@@ -743,17 +740,18 @@ exports.AnimationsActor = protocol.Actor
         if (index !== -1) {
           eventData.push({
             type: "removed",
             player: this.actors[index]
           });
           this.actors.splice(index, 1);
         }
 
-        const createdTime = player.startTime || player.timeline.currentTime;
+        this.updateAnimationCreatedTime(player);
+        const createdTime = this.getCreatedTime(player);
         const actor = AnimationPlayerActor(this, player, createdTime);
         this.actors.push(actor);
         eventData.push({
           type: "added",
           player: actor
         });
         readyPromises.push(player.ready);
       }
@@ -949,9 +947,50 @@ exports.AnimationsActor = protocol.Actor
       // We can not play with playbackRate zero.
       return;
     }
 
     // Play animation in a synchronous fashion by setting the start time directly.
     const currentTime = player.currentTime || 0;
     player.startTime = player.timeline.currentTime - currentTime / player.playbackRate;
   },
+
+  /**
+   * Return created fime of given animaiton.
+   *
+   * @param {Object} animation
+   */
+  getCreatedTime(animation) {
+    return this.animationCreatedTimeMap.get(animation);
+  },
+
+  /**
+   * Update all animation created time map.
+   */
+  updateAllAnimationsCreatedTime() {
+    const currentAnimations = this.getAllAnimations(this.tabActor.window.document);
+
+    // Remove invalid animations.
+    for (const previousAnimation of this.animationCreatedTimeMap.keys()) {
+      if (!currentAnimations.includes(previousAnimation)) {
+        this.animationCreatedTimeMap.delete(previousAnimation);
+      }
+    }
+
+    for (const animation of currentAnimations) {
+      this.updateAnimationCreatedTime(animation);
+    }
+  },
+
+  /**
+   * Update animation created time map.
+   *
+   * @param {Object} animation
+   */
+  updateAnimationCreatedTime(animation) {
+    if (!this.animationCreatedTimeMap.has(animation)) {
+      const createdTime =
+        animation.startTime ||
+        animation.timeline.currentTime - animation.currentTime / animation.playbackRate;
+      this.animationCreatedTimeMap.set(animation, createdTime);
+    }
+  },
 });