From acbe837e592046e2a155bd9982a9a39203e6b15b Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Mon, 16 Apr 2012 16:14:04 -0700 Subject: [PATCH] Bug 745885 - Improvements to CommonUtils.namedTimer; r=rnewman --- .../tests/unit/test_utils_namedTimer.js | 29 ++++++++++++-- services/common/utils.js | 40 +++++++++++++++---- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/services/common/tests/unit/test_utils_namedTimer.js b/services/common/tests/unit/test_utils_namedTimer.js index 61a65e26037e..5418de20249e 100644 --- a/services/common/tests/unit/test_utils_namedTimer.js +++ b/services/common/tests/unit/test_utils_namedTimer.js @@ -49,7 +49,32 @@ add_test(function test_delay() { } CommonUtils.namedTimer(callback, delay, that, "_zetimer"); CommonUtils.namedTimer(callback, 2 * delay, that, "_zetimer"); - run_next_test(); +}); + +add_test(function test_repeating() { + _("Ensure a repeating timer type works."); + + const delay = 100; + let count = 0; + let that = {}; + let t0 = Date.now(); + function callback() { + count += 1; + + if (count < 2) { + return; + } + + let elapsed = Date.now() - t0; + let expectedDelay = 2 * delay; + do_check_true(elapsed > expectedDelay); + + this._letimer.clear(); + run_next_test(); + } + + CommonUtils.namedTimer(callback, delay, that, "_letimer", + Ci.nsITimer.TYPE_REPEATING_SLACK); }); add_test(function test_clear() { @@ -64,6 +89,4 @@ add_test(function test_clear() { that._zetimer.clear(); do_check_eq(that._zetimer, null); CommonUtils.nextTick(run_next_test); - - run_next_test(); }); diff --git a/services/common/utils.js b/services/common/utils.js index d0b77f77ba2b..91341d9e735a 100644 --- a/services/common/utils.js +++ b/services/common/utils.js @@ -89,10 +89,34 @@ let CommonUtils = { * Return a timer that is scheduled to call the callback after waiting the * provided time or as soon as possible. The timer will be set as a property * of the provided object with the given timer name. + * + * @param callback + * (function) Called when the timer fires. + * @param wait + * (number) Integer milliseconds timer delay. + * @param thisObj + * (object) Context callback is bound to during call. Timer is also + * attached to this object. + * @param name + * (string) Property in thisObj to assign created timer to. + * @param type + * (nsITimer.TYPE_*) Type of timer to create. Defaults to + * TYPE_ONE_SHOT. */ - namedTimer: function namedTimer(callback, wait, thisObj, name) { + namedTimer: function namedTimer(callback, wait, thisObj, name, type) { if (!thisObj || !name) { - throw "You must provide both an object and a property name for the timer!"; + throw new Error("You must provide both an object and a property name " + + "for the timer!"); + } + + // TYPE_ONE_SHOT is conveniently 0. + type = type || Ci.nsITimer.TYPE_ONE_SHOT; + + // We rely below on TYPE_ONE_SHOT being the only timer that should be + // cancelled after firing. If we see a type that was not known when this + // was implemented, scream loudly. + if (type > Ci.nsITimer.TYPE_REPEATING_PRECISE) { + throw new Error("Unknown timer type seen: " + type); } // Delay an existing timer if it exists @@ -102,11 +126,11 @@ let CommonUtils = { } // Create a special timer that we can add extra properties - let timer = {}; + let timer = {_type: type}; timer.__proto__ = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); // Provide an easy way to clear out the timer - timer.clear = function() { + timer.clear = function clear() { thisObj[name] = null; timer.cancel(); }; @@ -114,11 +138,13 @@ let CommonUtils = { // Initialize the timer with a smart callback timer.initWithCallback({ notify: function notify() { - // Clear out the timer once it's been triggered - timer.clear(); + // Clear out the timer once it's been triggered if it's a one shot. + if (timer._type == Ci.nsITimer.TYPE_ONE_SHOT) { + timer.clear(); + } callback.call(thisObj, timer); } - }, wait, timer.TYPE_ONE_SHOT); + }, wait, type); return thisObj[name] = timer; },