treestyletab/modules/lib/jstimer.jsm

163 lines
3.6 KiB
JavaScript
Raw Normal View History

/*
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);
license: The MIT License, Copyright (c) 2010 SHIMODA "Piro" Hiroshi
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();
if (typeof callback != 'string') {
let source = callback;
callback = function() { source.apply(getGlobal(), args); };
callback.source = source;
}
return (new Timer(
callback,
timeout,
Ci.nsITimer.TYPE_ONE_SHOT,
getOwnerWindowFromCaller(arguments.callee.caller)
)).id;
}
function clearTimeout(aId)
{
Timer.cancel(aId);
}
function setInterval()
{
var args = Array.slice(arguments);
var callback = args.shift();
var interval = args.shift();
if (typeof callback != 'string') {
let source = callback;
callback = function() { source.apply(getGlobal(), args); };
callback.source = source;
}
return (new Timer(
callback,
interval,
Ci.nsITimer.TYPE_REPEATING_SLACK,
getOwnerWindowFromCaller(arguments.callee.caller)
)).id;
}
function clearInterval(aId)
{
Timer.cancel(aId);
}
function Timer(aCallback, aTime, aType, aOwner) {
this.finished = false;
this.callback = aCallback;
this.type = aType;
this.owner = aOwner;
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;
this.timer.cancel();
delete this.timer;
delete this.callback;
this.finished = true;
delete Timer.instances[this.id];
},
observe : function(aSubject, aTopic, aData)
{
if (aTopic != 'timer-callback') return;
this.notify(aSubject);
},
notify : function(aTimer)
{
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;
}
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; })();
}
function getOwnerWindowFromCaller(aCaller)
{
try {
var global = aCaller.valueOf.call(null);
if (global && global instanceof Ci.nsIDOMWindow)
return global;
}
catch(e) {
}
return null;
}