2010-06-22 14:00:16 -04:00
|
|
|
/*
|
|
|
|
JavaScript Timer Library
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
var namespace = {};
|
|
|
|
Components.utils.import('resource://foo-modules/jstimer.jsm', namespace);
|
|
|
|
|
|
|
|
var callback = function(aMessage) { alert(aMessage); };
|
|
|
|
var timeout = namespace.setTimeout(callback, 1000, 'OK');
|
|
|
|
namespace.clearTimeout(timeout);
|
|
|
|
var interval = namespace.setInterval(callback, 1000, 'OK');
|
|
|
|
namespace.clearInterval(interval);
|
|
|
|
|
2012-10-13 14:31:06 -04:00
|
|
|
license: The MIT License, Copyright (c) 2010 YUKI "Piro" Hiroshi
|
2010-06-22 14:00:16 -04:00
|
|
|
http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
|
|
|
|
original:
|
|
|
|
http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/jstimer.jsm
|
|
|
|
http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/jstimer.test.js
|
|
|
|
*/
|
|
|
|
|
|
|
|
var Cc = Components.classes;
|
|
|
|
var Ci = Components.interfaces;
|
|
|
|
|
|
|
|
var EXPORTED_SYMBOLS = [
|
|
|
|
'setTimeout',
|
|
|
|
'clearTimeout',
|
|
|
|
'setInterval',
|
|
|
|
'clearInterval'
|
|
|
|
];
|
|
|
|
|
|
|
|
function setTimeout()
|
|
|
|
{
|
|
|
|
var args = Array.slice(arguments);
|
|
|
|
var callback = args.shift();
|
|
|
|
var timeout = args.shift();
|
2010-06-28 05:58:34 -04:00
|
|
|
if (typeof callback != 'string') {
|
|
|
|
let source = callback;
|
|
|
|
callback = function() { source.apply(getGlobal(), args); };
|
|
|
|
callback.source = source;
|
|
|
|
}
|
2010-06-22 14:00:16 -04:00
|
|
|
return (new Timer(
|
2010-06-28 05:58:34 -04:00
|
|
|
callback,
|
2010-06-22 14:00:16 -04:00
|
|
|
timeout,
|
2010-06-28 12:04:04 -04:00
|
|
|
Ci.nsITimer.TYPE_ONE_SHOT,
|
|
|
|
getOwnerWindowFromCaller(arguments.callee.caller)
|
2010-06-22 14:00:16 -04:00
|
|
|
)).id;
|
|
|
|
}
|
|
|
|
|
|
|
|
function clearTimeout(aId)
|
|
|
|
{
|
|
|
|
Timer.cancel(aId);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setInterval()
|
|
|
|
{
|
|
|
|
var args = Array.slice(arguments);
|
|
|
|
var callback = args.shift();
|
|
|
|
var interval = args.shift();
|
2010-06-28 05:58:34 -04:00
|
|
|
if (typeof callback != 'string') {
|
|
|
|
let source = callback;
|
|
|
|
callback = function() { source.apply(getGlobal(), args); };
|
|
|
|
callback.source = source;
|
|
|
|
}
|
2010-06-22 14:00:16 -04:00
|
|
|
return (new Timer(
|
2010-06-28 05:58:34 -04:00
|
|
|
callback,
|
2010-06-22 14:00:16 -04:00
|
|
|
interval,
|
2010-06-28 12:04:04 -04:00
|
|
|
Ci.nsITimer.TYPE_REPEATING_SLACK,
|
|
|
|
getOwnerWindowFromCaller(arguments.callee.caller)
|
2010-06-22 14:00:16 -04:00
|
|
|
)).id;
|
|
|
|
}
|
|
|
|
|
|
|
|
function clearInterval(aId)
|
|
|
|
{
|
|
|
|
Timer.cancel(aId);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-28 12:04:04 -04:00
|
|
|
function Timer(aCallback, aTime, aType, aOwner) {
|
2010-06-22 14:00:16 -04:00
|
|
|
this.finished = false;
|
|
|
|
this.callback = aCallback;
|
|
|
|
this.type = aType;
|
2010-06-28 12:04:04 -04:00
|
|
|
this.owner = aOwner;
|
2010-06-22 14:00:16 -04:00
|
|
|
this.init(aTime);
|
|
|
|
|
|
|
|
Timer.instances[this.id] = this;
|
|
|
|
}
|
|
|
|
Timer.prototype = {
|
|
|
|
init : function(aTime, aType)
|
|
|
|
{
|
|
|
|
this.id = parseInt(Math.random() * 65000)
|
|
|
|
this.timer = Cc['@mozilla.org/timer;1']
|
|
|
|
.createInstance(Ci.nsITimer);
|
|
|
|
this.timer.init(this, aTime, this.type);
|
|
|
|
},
|
|
|
|
cancel : function()
|
|
|
|
{
|
|
|
|
if (!this.timer) return;
|
2010-06-28 05:58:34 -04:00
|
|
|
|
|
|
|
this.timer.cancel();
|
2010-06-22 14:00:16 -04:00
|
|
|
delete this.timer;
|
|
|
|
delete this.callback;
|
|
|
|
this.finished = true;
|
|
|
|
|
|
|
|
delete Timer.instances[this.id];
|
|
|
|
},
|
|
|
|
observe : function(aSubject, aTopic, aData)
|
|
|
|
{
|
|
|
|
if (aTopic != 'timer-callback') return;
|
2010-07-08 07:01:45 -04:00
|
|
|
this.notify(aSubject);
|
|
|
|
},
|
|
|
|
notify : function(aTimer)
|
|
|
|
{
|
2010-06-28 12:04:04 -04:00
|
|
|
if (this.owner && this.owner.closed) {
|
|
|
|
dump('jstimer.jsm:'+
|
|
|
|
' timer is stopped because the owner window was closed.\n'+
|
|
|
|
' type: '+(this.type == Ci.nsITimer.TYPE_ONE_SHOT ? 'TYPE_ONE_SHOT' : 'TYPE_REPEATING_SLACK' )+'\n'+
|
|
|
|
' callback: '+(this.callback.source || this.callback)+'\n');
|
|
|
|
this.cancel();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-22 14:00:16 -04:00
|
|
|
if (typeof this.callback == 'function')
|
|
|
|
this.callback();
|
|
|
|
else
|
|
|
|
evalInSandbox(this.callback);
|
|
|
|
|
|
|
|
if (this.type == Ci.nsITimer.TYPE_ONE_SHOT)
|
|
|
|
this.cancel();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Timer.instances = {};
|
|
|
|
Timer.cancel = function(aId) {
|
|
|
|
var timer = this.getInstanceById(aId);
|
|
|
|
if (timer)
|
|
|
|
timer.cancel();
|
|
|
|
};
|
|
|
|
Timer.getInstanceById = function(aId) {
|
|
|
|
return this.instances[aId] || null ;
|
|
|
|
};
|
|
|
|
|
|
|
|
function evalInSandbox(aCode, aSandboxOwner)
|
|
|
|
{
|
|
|
|
var sandbox = new Components.utils.Sandbox(aSandboxOwner || 'about:blank');
|
|
|
|
return Components.utils.evalInSandbox(aCode, sandbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getGlobal()
|
|
|
|
{
|
|
|
|
return (function() { return this; })();
|
|
|
|
}
|
2010-06-28 12:04:04 -04:00
|
|
|
|
|
|
|
function getOwnerWindowFromCaller(aCaller)
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
var global = aCaller.valueOf.call(null);
|
|
|
|
if (global && global instanceof Ci.nsIDOMWindow)
|
|
|
|
return global;
|
|
|
|
}
|
|
|
|
catch(e) {
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|