Bug 1462229 - Part 3: Guard that not touching null object during creating graph after animation inspector destroyed. r?gl draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Mon, 28 May 2018 09:27:55 +0900
changeset 800409 d93c389b4597b6d9a46cec8a25f3fb57af3bd25c
parent 800406 cef0e7c556903400248a0daf75d323eea19cfde1
child 800410 5cc58ec5192997305193b3d15b2f27d5088b632d
push id111343
push userbmo:dakatsuka@mozilla.com
push dateMon, 28 May 2018 00:29:00 +0000
reviewersgl
bugs1462229
milestone62.0a1
Bug 1462229 - Part 3: Guard that not touching null object during creating graph after animation inspector destroyed. r?gl MozReview-Commit-ID: 2UWt3aq1e4x
devtools/client/inspector/animation/animation.js
devtools/client/inspector/animation/components/graph/ComputedTimingPath.js
devtools/client/inspector/animation/components/graph/EffectTimingPath.js
devtools/client/inspector/animation/components/graph/NegativePath.js
devtools/client/inspector/animation/components/keyframes-graph/ComputedStylePath.js
--- a/devtools/client/inspector/animation/animation.js
+++ b/devtools/client/inspector/animation/animation.js
@@ -527,16 +527,21 @@ class AnimationInspector {
    *        true:  create animation with an element.
    *               If want to know computed value of the element, turn on.
    *        false: create animation without an element,
    *               If need to know only timing progress.
    * @return {Animation}
    *         https://drafts.csswg.org/web-animations/#the-animation-interface
    */
   simulateAnimation(keyframes, effectTiming, isElementNeeded) {
+    // Don't simulate animation if the animation inspector is already destroyed.
+    if (!this.win) {
+      return null;
+    }
+
     let targetEl = null;
 
     if (isElementNeeded) {
       if (!this.simulatedElement) {
         this.simulatedElement = this.win.document.createElement("div");
         this.win.document.documentElement.appendChild(this.simulatedElement);
       } else {
         // Reset styles.
@@ -637,16 +642,21 @@ class AnimationInspector {
             }
           }
         });
       }
     });
   }
 
   updateState(animations) {
+    // Animation inspector already destroyed
+    if (!this.inspector) {
+      return;
+    }
+
     this.stopAnimationsCurrentTimeTimer();
 
     this.inspector.store.dispatch(updateAnimations(animations));
 
     if (hasRunningAnimation(animations)) {
       this.startAnimationsCurrentTimeTimer();
     }
   }
--- a/devtools/client/inspector/animation/components/graph/ComputedTimingPath.js
+++ b/devtools/client/inspector/animation/components/graph/ComputedTimingPath.js
@@ -45,17 +45,23 @@ class ComputedTimingPath extends TimingP
     // is not affected by the easing in keyframes at all, computed value reflects that.
     const frames = keyframes.map(keyframe => {
       return {
         opacity: keyframe.offset,
         offset: keyframe.offset,
         easing: keyframe.easing
       };
     });
+
     const simulatedAnimation = simulateAnimation(frames, effectTiming, true);
+
+    if (!simulatedAnimation) {
+      return null;
+    }
+
     const simulatedElement = simulatedAnimation.effect.target;
     const win = simulatedElement.ownerGlobal;
     const endTime = simulatedAnimation.effect.getComputedTiming().endTime;
 
     // Set the underlying opacity to zero so that if we sample the animation's output
     // during the delay phase and it is not filling backwards, we get zero.
     simulatedElement.style.opacity = 0;
 
--- a/devtools/client/inspector/animation/components/graph/EffectTimingPath.js
+++ b/devtools/client/inspector/animation/components/graph/EffectTimingPath.js
@@ -31,16 +31,21 @@ class EffectTimingPath extends TimingPat
     } = this.props;
 
     const { state } = animation;
     const effectTiming = Object.assign({}, state, {
       iterations: state.iterationCount ? state.iterationCount : Infinity
     });
 
     const simulatedAnimation = simulateAnimation(null, effectTiming, false);
+
+    if (!simulatedAnimation) {
+      return null;
+    }
+
     const endTime = simulatedAnimation.effect.getComputedTiming().endTime;
 
     const getValueFunc = time => {
       if (time < 0) {
         return { x: time, y: 0 };
       }
 
       simulatedAnimation.currentTime = time < endTime ? time : endTime;
--- a/devtools/client/inspector/animation/components/graph/NegativePath.js
+++ b/devtools/client/inspector/animation/components/graph/NegativePath.js
@@ -47,16 +47,21 @@ class NegativePath extends PureComponent
       return {
         opacity: keyframe.offset,
         offset: keyframe.offset,
         easing: keyframe.easing
       };
     });
 
     const simulatedAnimation = simulateAnimation(frames, effectTiming, true);
+
+    if (!simulatedAnimation) {
+      return null;
+    }
+
     const simulatedElement = simulatedAnimation.effect.target;
     const win = simulatedElement.ownerGlobal;
 
     // Set the underlying opacity to zero so that if we sample the animation's output
     // during the delay phase and it is not filling backwards, we get zero.
     simulatedElement.style.opacity = 0;
 
     const getValueFunc = time => {
--- a/devtools/client/inspector/animation/components/keyframes-graph/ComputedStylePath.js
+++ b/devtools/client/inspector/animation/components/keyframes-graph/ComputedStylePath.js
@@ -78,17 +78,23 @@ class ComputedStylePath extends PureComp
         easing: keyframe.easing,
         [getJsPropertyName(propertyName)]: this.getPropertyValue(keyframe),
       };
     });
     const effect = {
       duration,
       fill: "forwards",
     };
+
     const simulatedAnimation = simulateAnimation(keyframes, effect, true);
+
+    if (!simulatedAnimation) {
+      return null;
+    }
+
     const simulatedElement = simulatedAnimation.effect.target;
     const win = simulatedElement.ownerGlobal;
     const threshold = getPreferredProgressThresholdByKeyframes(keyframes);
 
     const getSegment = time => {
       simulatedAnimation.currentTime = time;
       const computedStyle =
         win.getComputedStyle(simulatedElement).getPropertyValue(propertyName);
@@ -176,17 +182,23 @@ class ComputedStylePath extends PureComp
   renderGraph() {
     const { keyframes } = this.props;
 
     const segments = [];
 
     for (let i = 0; i < keyframes.length - 1; i++) {
       const startKeyframe = keyframes[i];
       const endKeyframe = keyframes[i + 1];
-      segments.push(...this.getPathSegments(startKeyframe, endKeyframe));
+      const keyframesSegments = this.getPathSegments(startKeyframe, endKeyframe);
+
+      if (!keyframesSegments) {
+        return null;
+      }
+
+      segments.push(...keyframesSegments);
     }
 
     return [
       this.renderPathSegments(segments),
       this.renderEasingHint(segments)
     ];
   }