diff options
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/realtime-callbacks.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/realtime-callbacks.js | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/realtime-callbacks.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/realtime-callbacks.js new file mode 100644 index 0000000..ef63620 --- /dev/null +++ b/includes/external/matrix/node_modules/matrix-js-sdk/lib/realtime-callbacks.js @@ -0,0 +1,180 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.clearTimeout = clearTimeout; +exports.setTimeout = setTimeout; +var _logger = require("./logger"); +/* +Copyright 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/* A re-implementation of the javascript callback functions (setTimeout, + * clearTimeout; setInterval and clearInterval are not yet implemented) which + * try to improve handling of large clock jumps (as seen when + * suspending/resuming the system). + * + * In particular, if a timeout would have fired while the system was suspended, + * it will instead fire as soon as possible after resume. + */ + +// we schedule a callback at least this often, to check if we've missed out on +// some wall-clock time due to being suspended. +const TIMER_CHECK_PERIOD_MS = 1000; + +// counter, for making up ids to return from setTimeout +let count = 0; + +// the key for our callback with the real global.setTimeout +let realCallbackKey; +// a sorted list of the callbacks to be run. +// each is an object with keys [runAt, func, params, key]. +const callbackList = []; + +// var debuglog = logger.log.bind(logger); +/* istanbul ignore next */ +const debuglog = function (...params) {}; + +/** + * reimplementation of window.setTimeout, which will call the callback if + * the wallclock time goes past the deadline. + * + * @param func - callback to be called after a delay + * @param delayMs - number of milliseconds to delay by + * + * @returns an identifier for this callback, which may be passed into + * clearTimeout later. + */ +function setTimeout(func, delayMs, ...params) { + delayMs = delayMs || 0; + if (delayMs < 0) { + delayMs = 0; + } + const runAt = Date.now() + delayMs; + const key = count++; + debuglog("setTimeout: scheduling cb", key, "at", runAt, "(delay", delayMs, ")"); + const data = { + runAt: runAt, + func: func, + params: params, + key: key + }; + + // figure out where it goes in the list + const idx = binarySearch(callbackList, function (el) { + return el.runAt - runAt; + }); + callbackList.splice(idx, 0, data); + scheduleRealCallback(); + return key; +} + +/** + * reimplementation of window.clearTimeout, which mirrors setTimeout + * + * @param key - result from an earlier setTimeout call + */ +function clearTimeout(key) { + if (callbackList.length === 0) { + return; + } + + // remove the element from the list + let i; + for (i = 0; i < callbackList.length; i++) { + const cb = callbackList[i]; + if (cb.key == key) { + callbackList.splice(i, 1); + break; + } + } + + // iff it was the first one in the list, reschedule our callback. + if (i === 0) { + scheduleRealCallback(); + } +} + +// use the real global.setTimeout to schedule a callback to runCallbacks. +function scheduleRealCallback() { + if (realCallbackKey) { + global.clearTimeout(realCallbackKey); + } + const first = callbackList[0]; + if (!first) { + debuglog("scheduleRealCallback: no more callbacks, not rescheduling"); + return; + } + const timestamp = Date.now(); + const delayMs = Math.min(first.runAt - timestamp, TIMER_CHECK_PERIOD_MS); + debuglog("scheduleRealCallback: now:", timestamp, "delay:", delayMs); + realCallbackKey = global.setTimeout(runCallbacks, delayMs); +} +function runCallbacks() { + const timestamp = Date.now(); + debuglog("runCallbacks: now:", timestamp); + + // get the list of things to call + const callbacksToRun = []; + // eslint-disable-next-line + while (true) { + const first = callbackList[0]; + if (!first || first.runAt > timestamp) { + break; + } + const cb = callbackList.shift(); + debuglog("runCallbacks: popping", cb.key); + callbacksToRun.push(cb); + } + + // reschedule the real callback before running our functions, to + // keep the codepaths the same whether or not our functions + // register their own setTimeouts. + scheduleRealCallback(); + for (const cb of callbacksToRun) { + try { + cb.func.apply(global, cb.params); + } catch (e) { + _logger.logger.error("Uncaught exception in callback function", e); + } + } +} + +/* search in a sorted array. + * + * returns the index of the last element for which func returns + * greater than zero, or array.length if no such element exists. + */ +function binarySearch(array, func) { + // min is inclusive, max exclusive. + let min = 0; + let max = array.length; + while (min < max) { + const mid = min + max >> 1; + const res = func(array[mid]); + if (res > 0) { + // the element at 'mid' is too big; set it as the new max. + max = mid; + } else { + // the element at 'mid' is too small. 'min' is inclusive, so +1. + min = mid + 1; + } + } + // presumably, min==max now. + return min; +} +//# sourceMappingURL=realtime-callbacks.js.map
\ No newline at end of file |