Bug 995027 - MockProvider._delayCallback can lose or mis-call callbacks in several ways. r=irving, a=test-only
authorBenjamin Smedberg <benjamin@smedbergs.us>
Mon, 28 Apr 2014 10:48:03 -0400
changeset 199085 025e2cc8643095b704f10f49ea9332675261b997
parent 199084 0f40e6c752c8ec96d68d6036c1dd588c524e31df
child 199086 bdef20bf49fb59191bb3e7f1532e181d4e71dfb3
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersirving, test-only
bugs995027
milestone31.0a2
Bug 995027 - MockProvider._delayCallback can lose or mis-call callbacks in several ways. r=irving, a=test-only
testing/profiles/prefs_general.js
toolkit/mozapps/extensions/test/browser/head.js
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -49,16 +49,17 @@ user_pref("toolkit.telemetry.prompted", 
 user_pref("toolkit.telemetry.notifiedOptOut", 999);
 // Existing tests assume there is no font size inflation.
 user_pref("font.size.inflation.emPerLine", 0);
 user_pref("font.size.inflation.minTwips", 0);
 
 // AddonManager tests require that the experiments provider be present.
 user_pref("experiments.supported", true);
 user_pref("experiments.logging.level", "Trace");
+user_pref("experiments.logging.dump", true);
 // Point the manifest at something local so we don't risk it hitting production
 // data and installing experiments that may vary over time.
 user_pref("experiments.manifest.uri", "http://%(server)s/experiments-dummy/manifest");
 
 // Only load extensions from the application and user profile
 // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
 user_pref("extensions.enabledScopes", 5);
 // Disable metadata caching for installed add-ons by default
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -778,18 +778,23 @@ MockProvider.prototype = {
   startup: function MP_startup() {
     this.started = true;
   },
 
   /**
    * Called when the provider should shutdown.
    */
   shutdown: function MP_shutdown() {
-    for (let timer of this.callbackTimers)
+    if (this.callbackTimers.length) {
+      info("MockProvider: pending callbacks at shutdown(): calling immediately");
+    }
+    for (let timer of this.callbackTimers) {
+      timer.callback();
       timer.cancel();
+    }
     this.callbackTimers = [];
 
     this.started = false;
   },
 
   /**
    * Called to get an Addon with a particular ID.
    *
@@ -963,27 +968,30 @@ MockProvider.prototype = {
    * The delay is specified by the apiDelay property, in milliseconds.
    * Parameters to send to the callback should be specified as arguments after
    * the aCallback argument.
    *
    * @param aCallback Callback to eventually call
    */
   _delayCallback: function MP_delayCallback(aCallback, ...aArgs) {
     if (!this.useAsyncCallbacks) {
-      aCallback.apply(null, params);
+      aCallback.apply(null, aArgs);
       return;
     }
 
     var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     // Need to keep a reference to the timer, so it doesn't get GC'ed
-    var pos = this.callbackTimers.length;
     this.callbackTimers.push(timer);
-    var self = this;
-    timer.initWithCallback(function() {
-      self.callbackTimers.splice(pos, 1);
+    timer.initWithCallback(() => {
+      let idx = this.callbackTimers.indexOf(timer);
+      if (idx == -1) {
+        info("MockProvider._delayCallback lost track of a timer.");
+      } else {
+        this.callbackTimers.splice(idx, 1);
+      }
       aCallback.apply(null, aArgs);
     }, this.apiDelay, timer.TYPE_ONE_SHOT);
   }
 };
 
 /***** Mock Addon object for the Mock Provider *****/
 
 function MockAddon(aId, aName, aType, aOperationsRequiringRestart) {