Bug 995027 - MockProvider._delayCallback can lose or mis-call callbacks in several ways. r=irving
authorBenjamin Smedberg <benjamin@smedbergs.us>
Tue, 06 May 2014 14:50:11 -0400
changeset 181878 0fa36ab9858883694dc333696f52e5ebb858d4bb
parent 181877 19b40165000ecf796b92f191bcf2634759669430
child 181879 0202366e8b707a6f3ed8543d490fcedee49c38c4
push id43162
push userkwierso@gmail.com
push dateWed, 07 May 2014 01:07:29 +0000
treeherdermozilla-inbound@8fcfb1107b03 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersirving
bugs995027
milestone32.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 995027 - MockProvider._delayCallback can lose or mis-call callbacks in several ways. r=irving
toolkit/mozapps/extensions/test/browser/head.js
--- 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) {