Bug 1384041 - Label the use of setTimeout of Timer.jsm in content-sessionStore.js. r=billm

MozReview-Commit-ID: i8Rn1eke4s
This commit is contained in:
Bevis Tseng 2017-07-28 16:03:51 +08:00
parent 17dd07bc88
commit 16c9a58ee8
4 changed files with 104 additions and 19 deletions

View File

@ -536,7 +536,7 @@ var SessionStorageListener = {
observe() {
// Collect data on the next tick so that any other observer
// that needs to purge data can do its work first.
setTimeout(() => this.collect(), 0);
setTimeoutWithTarget(() => this.collect(), 0, tabEventTarget);
},
// We don't want to send all the session storage data for all the frames
@ -733,7 +733,8 @@ var MessageQueue = {
if (!this._timeout && !this._timeoutDisabled) {
// Wait a little before sending the message to batch multiple changes.
this._timeout = setTimeout(() => this.send(), this.BATCH_DELAY_MS);
this._timeout = setTimeoutWithTarget(
() => this.send(), this.BATCH_DELAY_MS, tabEventTarget);
}
},

View File

@ -8,10 +8,12 @@
* JS module implementation of setTimeout and clearTimeout.
*/
this.EXPORTED_SYMBOLS = ["setTimeout", "clearTimeout", "setInterval", "clearInterval"];
this.EXPORTED_SYMBOLS = ["setTimeout", "setTimeoutWithTarget", "clearTimeout",
"setInterval", "setIntervalWithTarget", "clearInterval"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -21,29 +23,63 @@ var gNextId = 1; // setTimeout and setInterval must return a positive integer
var gTimerTable = new Map(); // int -> nsITimer
this.setTimeout = function setTimeout(aCallback, aMilliseconds) {
function _setTimeoutOrIsInterval(aCallback, aMilliseconds, aIsInterval,
aTarget, aArgs) {
let id = gNextId++;
let args = Array.slice(arguments, 2);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(function setTimeout_timer() {
gTimerTable.delete(id);
aCallback.apply(null, args);
}, aMilliseconds, timer.TYPE_ONE_SHOT);
if (aTarget) {
timer.target = aTarget;
}
let callback = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback,
Ci.nsINamed]),
// nsITimerCallback
notify() {
if (!aIsInterval) {
gTimerTable.delete(id);
}
aCallback.apply(null, aArgs);
},
// nsINamed
name: aIsInterval ? "setInterval() in Timer.jsm"
: "setTimeout() in Timer.jsm",
};
timer.initWithCallback(callback, aMilliseconds,
aIsInterval ? timer.TYPE_REPEATING_SLACK : timer.TYPE_ONE_SHOT);
gTimerTable.set(id, timer);
return id;
}
this.setInterval = function setInterval(aCallback, aMilliseconds) {
let id = gNextId++;
let args = Array.slice(arguments, 2);
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(function setInterval_timer() {
aCallback.apply(null, args);
}, aMilliseconds, timer.TYPE_REPEATING_SLACK);
this.setTimeout = function setTimeout(aCallback, aMilliseconds, ...aArgs) {
return _setTimeoutOrIsInterval(
aCallback, aMilliseconds, false, null, aArgs);
}
gTimerTable.set(id, timer);
return id;
this.setTimeoutWithTarget = function setTimeoutWithTarget(aCallback,
aMilliseconds,
aTarget,
...aArgs) {
return _setTimeoutOrIsInterval(
aCallback, aMilliseconds, false, aTarget, aArgs);
}
this.setInterval = function setInterval(aCallback, aMilliseconds, ...aArgs) {
return _setTimeoutOrIsInterval(
aCallback, aMilliseconds, true, null, aArgs);
}
this.setIntervalWithTarget = function setIntervalWithTarget(aCallback,
aMilliseconds,
aTarget,
...aArgs) {
return _setTimeoutOrIsInterval(
aCallback, aMilliseconds, true, aTarget, aArgs);
}
this.clearInterval = this.clearTimeout = function clearTimeout(aId) {

View File

@ -33,6 +33,29 @@ add_task(async function test_setTimeout() {
});
});
add_task(async function test_setTimeoutWithTarget() {
let target = Services.systemGroupEventTarget;
let timeout1 = imported.setTimeoutWithTarget(
() => do_throw("Should not be called"), 100, target);
do_check_eq(typeof timeout1, "number", "setTimeout returns a number");
do_check_true(timeout1 > 0, "setTimeout returns a positive number");
imported.clearTimeout(timeout1);
await new Promise((resolve) => {
let timeout2 = imported.setTimeoutWithTarget((param1, param2) => {
do_check_true(true, "Should be called");
do_check_eq(param1, 5, "first parameter is correct");
do_check_eq(param2, "test", "second parameter is correct");
resolve();
}, 100, target, 5, "test");
do_check_eq(typeof timeout2, "number", "setTimeout returns a number");
do_check_true(timeout2 > 0, "setTimeout returns a positive number");
do_check_neq(timeout1, timeout2, "Calling setTimeout again returns a different value");
});
});
add_task(async function test_setInterval() {
let interval1 = imported.setInterval(() => do_throw("Should not be called!"), 100);
do_check_eq(typeof interval1, "number", "setInterval returns a number");
@ -55,3 +78,28 @@ add_task(async function test_setInterval() {
}, 100, 15, "hola");
});
});
add_task(async function test_setIntervalWithTarget() {
let target = Services.systemGroupEventTarget;
let interval1 = imported.setIntervalWithTarget(
() => do_throw("Should not be called!"), 100, target);
do_check_eq(typeof interval1, "number", "setInterval returns a number");
do_check_true(interval1 > 0, "setTimeout returns a positive number");
imported.clearInterval(interval1);
const EXPECTED_CALLS = 5;
let calls = 0;
await new Promise((resolve) => {
imported.setIntervalWithTarget((param1, param2) => {
do_check_true(true, "Should be called");
do_check_eq(param1, 15, "first parameter is correct");
do_check_eq(param2, "hola", "second parameter is correct");
if (calls >= EXPECTED_CALLS) {
resolve();
}
calls++;
}, 100, target, 15, "hola");
});
});

View File

@ -212,7 +212,7 @@
"test.jsm": ["Foo"],
"test2.jsm": ["Bar"],
"test_bug883784.jsm": ["Test"],
"Timer.jsm": ["setTimeout", "clearTimeout", "setInterval", "clearInterval"],
"Timer.jsm": ["setTimeout", "setTimeoutWithTarget", "clearTimeout", "setInterval", "setIntervalWithTarget", "clearInterval"],
"tokenserverclient.js": ["TokenServerClient", "TokenServerClientError", "TokenServerClientNetworkError", "TokenServerClientServerError"],
"ToolboxProcess.jsm": ["BrowserToolboxProcess"],
"tps.jsm": ["ACTIONS", "TPS"],