Bug 1875768 - Call the appropriate postfork handler on MacOS r=glandium
[gecko.git] / toolkit / modules / Timer.sys.mjs
blobc77fe90e11abf1c7f22b79e5af4ab3ca27c6b2ca
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /**
6  * JS module implementation of setTimeout and clearTimeout.
7  */
9 // This gives us >=2^30 unique timer IDs, enough for 1 per ms for 12.4 days.
10 var gNextId = 1; // setTimeout and setInterval must return a positive integer
12 var gTimerTable = new Map(); // int -> nsITimer or idleCallback
14 // Don't generate this for every timer.
15 var setTimeout_timerCallbackQI = ChromeUtils.generateQI([
16   "nsITimerCallback",
17   "nsINamed",
18 ]);
20 function _setTimeoutOrIsInterval(
21   aCallback,
22   aMilliseconds,
23   aIsInterval,
24   aTarget,
25   aArgs
26 ) {
27   if (typeof aCallback !== "function") {
28     throw new Error(
29       `callback is not a function in ${
30         aIsInterval ? "setInterval" : "setTimeout"
31       }`
32     );
33   }
34   let id = gNextId++;
35   let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
37   if (aTarget) {
38     timer.target = aTarget;
39   }
41   let callback = {
42     QueryInterface: setTimeout_timerCallbackQI,
44     // nsITimerCallback
45     notify() {
46       if (!aIsInterval) {
47         gTimerTable.delete(id);
48       }
49       aCallback.apply(null, aArgs);
50     },
52     // nsINamed
53     get name() {
54       return `${
55         aIsInterval ? "setInterval" : "setTimeout"
56       }() for ${Cu.getDebugName(aCallback)}`;
57     },
58   };
60   timer.initWithCallback(
61     callback,
62     aMilliseconds,
63     aIsInterval ? timer.TYPE_REPEATING_SLACK : timer.TYPE_ONE_SHOT
64   );
66   gTimerTable.set(id, timer);
67   return id;
70 export function setTimeout(aCallback, aMilliseconds, ...aArgs) {
71   return _setTimeoutOrIsInterval(aCallback, aMilliseconds, false, null, aArgs);
74 export function setTimeoutWithTarget(
75   aCallback,
76   aMilliseconds,
77   aTarget,
78   ...aArgs
79 ) {
80   return _setTimeoutOrIsInterval(
81     aCallback,
82     aMilliseconds,
83     false,
84     aTarget,
85     aArgs
86   );
89 export function setInterval(aCallback, aMilliseconds, ...aArgs) {
90   return _setTimeoutOrIsInterval(aCallback, aMilliseconds, true, null, aArgs);
93 export function setIntervalWithTarget(
94   aCallback,
95   aMilliseconds,
96   aTarget,
97   ...aArgs
98 ) {
99   return _setTimeoutOrIsInterval(
100     aCallback,
101     aMilliseconds,
102     true,
103     aTarget,
104     aArgs
105   );
108 function clear(aId) {
109   if (gTimerTable.has(aId)) {
110     gTimerTable.get(aId).cancel();
111     gTimerTable.delete(aId);
112   }
114 export var clearInterval = clear;
115 export var clearTimeout = clear;
117 export function requestIdleCallback(aCallback, aOptions) {
118   if (typeof aCallback !== "function") {
119     throw new Error("callback is not a function in requestIdleCallback");
120   }
121   let id = gNextId++;
123   let callback = (...aArgs) => {
124     if (gTimerTable.has(id)) {
125       gTimerTable.delete(id);
126       aCallback(...aArgs);
127     }
128   };
130   ChromeUtils.idleDispatch(callback, aOptions);
131   gTimerTable.set(id, callback);
132   return id;
135 export function cancelIdleCallback(aId) {
136   if (gTimerTable.has(aId)) {
137     gTimerTable.delete(aId);
138   }