mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
/* 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';
|
|
|
|
module.metadata = {
|
|
"stability": "stable"
|
|
};
|
|
|
|
const { CC, Cc, Ci } = require("chrome");
|
|
const { when: unload } = require("./system/unload");
|
|
|
|
const { TYPE_ONE_SHOT, TYPE_REPEATING_SLACK } = Ci.nsITimer;
|
|
const Timer = CC("@mozilla.org/timer;1", "nsITimer");
|
|
const timers = Object.create(null);
|
|
const threadManager = Cc["@mozilla.org/thread-manager;1"].
|
|
getService(Ci.nsIThreadManager);
|
|
const prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
|
getService(Ci.nsIPrefService).
|
|
QueryInterface(Ci.nsIPrefBranch);
|
|
|
|
let MIN_DELAY = 4;
|
|
// Try to get min timeout delay used by browser.
|
|
try { MIN_DELAY = prefBranch.getIntPref("dom.min_timeout_value"); } finally {}
|
|
|
|
|
|
// Last timer id.
|
|
let lastID = 0;
|
|
|
|
// Sets typer either by timeout or by interval
|
|
// depending on a given type.
|
|
function setTimer(type, callback, delay, ...args) {
|
|
let id = ++ lastID;
|
|
let timer = timers[id] = Timer();
|
|
timer.initWithCallback({
|
|
notify: function notify() {
|
|
try {
|
|
if (type === TYPE_ONE_SHOT)
|
|
delete timers[id];
|
|
callback.apply(null, args);
|
|
}
|
|
catch(error) {
|
|
console.exception(error);
|
|
}
|
|
}
|
|
}, Math.max(delay || MIN_DELAY), type);
|
|
return id;
|
|
}
|
|
|
|
function unsetTimer(id) {
|
|
let timer = timers[id];
|
|
delete timers[id];
|
|
if (timer) timer.cancel();
|
|
}
|
|
|
|
let immediates = new Map();
|
|
|
|
let dispatcher = _ => {
|
|
// Allow scheduling of a new dispatch loop.
|
|
dispatcher.scheduled = false;
|
|
// Take a snapshot of timer `id`'s that have being present before
|
|
// starting a dispatch loop, in order to ignore timers registered
|
|
// in side effect to dispatch while also skipping immediates that
|
|
// were removed in side effect.
|
|
let ids = [id for ([id] of immediates)];
|
|
for (let id of ids) {
|
|
let immediate = immediates.get(id);
|
|
if (immediate) {
|
|
immediates.delete(id);
|
|
try { immediate(); }
|
|
catch (error) { console.exception(error); }
|
|
}
|
|
}
|
|
}
|
|
|
|
function setImmediate(callback, ...params) {
|
|
let id = ++ lastID;
|
|
// register new immediate timer with curried params.
|
|
immediates.set(id, _ => callback.apply(callback, params));
|
|
// if dispatch loop is not scheduled schedule one. Own scheduler
|
|
if (!dispatcher.scheduled) {
|
|
dispatcher.scheduled = true;
|
|
threadManager.currentThread.dispatch(dispatcher,
|
|
Ci.nsIThread.DISPATCH_NORMAL);
|
|
}
|
|
return id;
|
|
}
|
|
|
|
function clearImmediate(id) {
|
|
immediates.delete(id);
|
|
}
|
|
|
|
// Bind timers so that toString-ing them looks same as on native timers.
|
|
exports.setImmediate = setImmediate.bind(null);
|
|
exports.clearImmediate = clearImmediate.bind(null);
|
|
exports.setTimeout = setTimer.bind(null, TYPE_ONE_SHOT);
|
|
exports.setInterval = setTimer.bind(null, TYPE_REPEATING_SLACK);
|
|
exports.clearTimeout = unsetTimer.bind(null);
|
|
exports.clearInterval = unsetTimer.bind(null);
|
|
|
|
// all timers are cleared out on unload.
|
|
unload(function() {
|
|
immediates.clear();
|
|
Object.keys(timers).forEach(unsetTimer)
|
|
});
|