1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { CC } = require("chrome");
const { Unknown } = require("./xpcom");
const { when: unload } = require("./unload");
const Timer = CC('@mozilla.org/timer;1', 'nsITimer');
// Registry for all timers.
const timers = (function(map, id) {
return Object.defineProperties(function registry(key, fallback) {
return key in map ? map[key] : fallback;
}, {
register: { value: function(value) (map[++id] = value, id) },
unregister: { value: function(key) delete map[key] },
forEach: { value: function(callback) Object.keys(map).forEach(callback) }
});
})(Object.create(null), 0);
const TimerCallback = Unknown.extend({
interfaces: [ 'nsITimerCallback' ],
initialize: function initialize(id, callback, rest) {
this.id = id;
this.callback = callback;
this.arguments = rest;
}
});
const TimeoutCallback = TimerCallback.extend({
type: 0, // nsITimer.TYPE_ONE_SHOT
notify: function notify() {
try {
timers.unregister(this.id);
this.callback.apply(null, this.arguments);
}
catch (error) {
console.exception(error);
}
}
});
const IntervalCallback = TimerCallback.extend({
type: 1, // nsITimer.TYPE_REPEATING_SLACK
notify: function notify() {
try {
this.callback.apply(null, this.arguments);
}
catch (error) {
console.exception(error);
}
}
});
function setTimer(TimerCallback, listener, delay) {
let timer = Timer();
let id = timers.register(timer);
let callback = TimerCallback.new(id, listener, Array.slice(arguments, 3));
timer.initWithCallback(callback, delay || 0, TimerCallback.type);
return id;
}
function unsetTimer(id) {
let timer = timers(id);
timers.unregister(id);
if (timer)
timer.cancel();
}
exports.setTimeout = setTimer.bind(null, TimeoutCallback);
exports.setInterval = setTimer.bind(null, IntervalCallback);
exports.clearTimeout = unsetTimer;
exports.clearInterval = unsetTimer;
unload(function() { timers.forEach(unsetTimer); });
|