Bug 1488379 - guard for errors; r=daisuke
authoryulia <ystartsev@mozilla.com>
Thu, 18 Oct 2018 08:54:56 +0000
changeset 500365 a0e2d7e922d83b15720c193f672312e639634a33
parent 500364 d522a86504a76831e59348784c25e81162fe540a
child 500366 1f35618c6e3c52748c84e62a15854dbb7a575206
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaisuke
bugs1488379
milestone64.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 1488379 - guard for errors; r=daisuke Depends on D7986 Differential Revision: https://phabricator.services.mozilla.com/D8736
devtools/client/inspector/animation/animation.js
devtools/client/inspector/animation/test/browser_animation_logic_mutations_fast.js
devtools/client/inspector/animation/test/head.js
--- a/devtools/client/inspector/animation/animation.js
+++ b/devtools/client/inspector/animation/animation.js
@@ -320,17 +320,22 @@ class AnimationInspector {
         animation.off("changed", this.onAnimationStateChanged);
       }
     }
 
     // Update existing other animations as well since the currentTime would be proceeded
     // sice the scrubber position is related the currentTime.
     // Also, don't update the state of removed animations since React components
     // may refer to the same instance still.
-    animations = await this.updateAnimations(animations);
+    try {
+      animations = await this.updateAnimations(animations);
+    } catch (_) {
+      console.error(`Updating Animations failed`);
+      return;
+    }
 
     this.updateState(animations.concat(addedAnimations));
   }
 
   onElementPickerStarted() {
     this.inspector.store.dispatch(updateElementPickerEnabled(true));
   }
 
--- a/devtools/client/inspector/animation/test/browser_animation_logic_mutations_fast.js
+++ b/devtools/client/inspector/animation/test/browser_animation_logic_mutations_fast.js
@@ -5,18 +5,28 @@
 
 // Test whether the animation inspector will not crash when remove/add animations faster.
 
 add_task(async function() {
   const tab = await addTab(URL_ROOT + "doc_mutations_fast.html");
   const { inspector } = await openAnimationInspector();
 
   info("Check state of the animation inspector after fast mutations");
+  const animationsFinished = waitForAnimations(inspector);
   await startFastMutations(tab);
   ok(inspector.panelWin.document.getElementById("animation-container"),
     "Animation inspector should be live");
+  await animationsFinished;
 });
 
 async function startFastMutations(tab) {
   await ContentTask.spawn(tab.linkedBrowser, {}, async function() {
     await content.wrappedJSObject.startFastMutations();
   });
 }
+
+function waitForAnimations(inspector) {
+  // wait at least once
+  let count = 1;
+  // queue any further waits
+  inspector.animationinspector.animationsFront.on("mutations", () => count++);
+  return waitForDispatch(inspector, "UPDATE_ANIMATIONS", () => count);
+}
--- a/devtools/client/inspector/animation/test/head.js
+++ b/devtools/client/inspector/animation/test/head.js
@@ -549,16 +549,61 @@ const setStyles = async function(animati
 const waitForRendering = async function(animationInspector) {
   await Promise.all([
     waitForAllAnimationTargets(animationInspector),
     waitForAllSummaryGraph(animationInspector),
     waitForAnimationDetail(animationInspector),
   ]);
 };
 
+// Wait until an action of `type` is dispatched. If it's part of an
+// async operation, wait until the `status` field is "done" or "error"
+function _afterDispatchDone(store, type) {
+  return new Promise(resolve => {
+    store.dispatch({
+      // Normally we would use `services.WAIT_UNTIL`, but use the
+      // internal name here so tests aren't forced to always pass it
+      // in
+      type: "@@service/waitUntil",
+      predicate: action => {
+        if (action.type === type) {
+          return true;
+        }
+        return false;
+      },
+      run: (dispatch, getState, action) => {
+        resolve(action);
+      }
+    });
+  });
+}
+
+/**
+ * Wait for a specific action type to be dispatch.
+ * If an async action, will wait for it to be done.
+ * This is a custom waitForDispatch, and rather than having a number to wait on
+ * the function has a callback, that returns a number. This allows us to wait for
+ * an unknown number of dispatches.
+ *
+ * @memberof mochitest/waits
+ * @param {Object} inspector
+ * @param {String} type
+ * @param {Function} repeat
+ * @return {Promise}
+ * @static
+ */
+async function waitForDispatch(inspector, type, repeat) {
+  let count = 0;
+
+  while (count < repeat()) {
+    await _afterDispatchDone(inspector.store, type);
+    count++;
+  }
+}
+
 /**
  * Wait for rendering of animation keyframes.
  *
  * @param {AnimationInspector} inspector
  */
 
 const waitForAnimationDetail = async function(animationInspector) {
   if (animationInspector.state.selectedAnimation &&