UNPKG

foop

Version:

interfaces that describe their intentions.

243 lines (215 loc) 21.6 kB
var isUndefined = require('../is/undefined') var isFunction = require('../is/function') var isObj = require('../is/obj') var noop = require('../util/noop') var toInteger = require('../cast/toInteger') // underscore.js // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. /** * Creates a debounced function that delays invoking `func` until after `wait` * milliseconds have elapsed since the last time the debounced function was * invoked. The debounced function comes with a `cancel` method to cancel * delayed `func` invocations and a `flush` method to immediately invoke them. * Provide `options` to indicate whether `func` should be invoked on the * leading and/or trailing edge of the `wait` timeout. The `func` is invoked * with the last arguments provided to the debounced function. Subsequent * calls to the debounced function return the result of the last `func` * invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is * invoked on the trailing edge of the timeout only if the debounced function * is invoked more than once during the `wait` timeout. * * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred * until the next tick, similar to `setTimeout` with a timeout of `0`. * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `debounce` and `throttle`. * * @since 5.0.0-beta.5 * * @param {Function} func The function to debounce. * @param {number} [wait=0] The number of milliseconds to delay. * @param {Object} [options={}] The options object. * @param {boolean} [options.leading=false] * Specify invoking on the leading edge of the timeout. * @param {number} [options.maxWait] * The maximum time `func` is allowed to be delayed before it's invoked. * @param {boolean} [options.trailing=true] * Specify invoking on the trailing edge of the timeout. * @return {Function} Returns the new debounced function. * * @fork 0.1.0 * @category Function * @func * * {@link https://github.com/lodash/lodash/blob/master/debounce.js lodash-debounce} * @see {@link lodash-debounce} * * @example * * // Avoid costly calculations while the window size is in flux. * jQuery(window).on('resize', debounce(calculateLayout, 150)) * * // Invoke `sendMail` when clicked, debouncing subsequent calls. * jQuery(element).on('click', debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })) * * // Ensure `batchLog` is invoked once after 1 second of debounced calls. * const debounced = debounce(batchLog, 250, { 'maxWait': 1000 }) * const source = new EventSource('/stream') * jQuery(source).on('message', debounced) * * // Cancel the trailing debounced invocation. * jQuery(window).on('popstate', debounced.cancel) * */ function debounce(func, wait, options) { var lastArgs var lastThis var maxWait var result var timerId var lastCallTime var lastInvokeTime = 0 var leading = false var maxing = false var trailing = true // @TODO this would be coercing if (!isFunction(func)) { func = noop // throw new TypeError('Expected a function') } // defaultTo(0) wait = toInteger(wait) // const optionsHas = hasIn(options) if (isObj(options)) { leading = !!options.leading maxing = 'maxWait' in options maxWait = maxing ? Math.max(toInteger(options.maxWait), wait) : maxWait trailing = 'trailing' in options ? !!options.trailing : trailing } function invokeFunc(time) { var args = lastArgs var thisArg = lastThis lastArgs = lastThis = undefined lastInvokeTime = time result = func.apply(thisArg, args) return result } function leadingEdge(time) { // Reset any `maxWait` timer. lastInvokeTime = time // Start the timer for the trailing edge. timerId = setTimeout(timerExpired, wait) // Invoke the leading edge. return leading ? invokeFunc(time) : result } function remainingWait(time) { var timeSinceLastCall = time - lastCallTime var timeSinceLastInvoke = time - lastInvokeTime var timeWaiting = wait - timeSinceLastCall return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting } function shouldInvoke(time) { var timeSinceLastCall = time - lastCallTime var timeSinceLastInvoke = time - lastInvokeTime // Either this is the first call, activity has stopped and we're at the // trailing edge, the system time has gone backwards and we're treating // it as the trailing edge, or we've hit the `maxWait` limit. return (isUndefined(lastCallTime) || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)) } function timerExpired() { var time = Date.now() if (shouldInvoke(time)) { return trailingEdge(time) } // Restart the timer. timerId = setTimeout(timerExpired, remainingWait(time)) } function trailingEdge(time) { timerId = undefined // Only invoke if we have `lastArgs` which means `func` has been // debounced at least once. if (trailing && lastArgs) { return invokeFunc(time) } lastArgs = lastThis = undefined return result } function cancel() { if (!isUndefined(timerId)) { clearTimeout(timerId) } lastInvokeTime = 0 lastArgs = lastCallTime = lastThis = timerId = undefined } function flush() { return isUndefined(timerId) ? result : trailingEdge(Date.now()) } function debounced(...args) { var time = Date.now() var isInvoking = shouldInvoke(time) lastArgs = args lastThis = this lastCallTime = time if (isInvoking) { if (isUndefined(timerId)) { return leadingEdge(lastCallTime) } if (maxing) { // Handle invocations in a tight loop. timerId = setTimeout(timerExpired, wait) return invokeFunc(lastCallTime) } } if (isUndefined(timerId)) { timerId = setTimeout(timerExpired, wait) } return result } debounced.cancel = cancel debounced.flush = flush return debounced } module.exports = debounce // underscore js version // module.exports = function(func, wait, immediate) { // let timeout // let result // // const later = function(context, args) { // timeout = null // if (args) result = func.apply(context, args) // } // // const debounced = restArgs(function(args) { // if (timeout) clearTimeout(timeout) // if (immediate) { // const callNow = !timeout // timeout = setTimeout(later, wait) // if (callNow) result = func.apply(this, args) // } // else { // timeout = delay(later, wait, this, args) // } // // return result // }) // // debounced.cancel = function() { // clearTimeout(timeout) // timeout = null // } // // return debounced // } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVib3VuY2UuanMiLCJzb3VyY2VzIjpbImRlYm91bmNlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IGlzVW5kZWZpbmVkID0gcmVxdWlyZSgnLi4vaXMvdW5kZWZpbmVkJylcbmNvbnN0IGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuLi9pcy9mdW5jdGlvbicpXG5jb25zdCBpc09iaiA9IHJlcXVpcmUoJy4uL2lzL29iaicpXG5jb25zdCBub29wID0gcmVxdWlyZSgnLi4vdXRpbC9ub29wJylcbmNvbnN0IHRvSW50ZWdlciA9IHJlcXVpcmUoJy4uL2Nhc3QvdG9JbnRlZ2VyJylcblxuXG4vLyB1bmRlcnNjb3JlLmpzXG4vLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90XG4vLyBiZSB0cmlnZ2VyZWQuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciBpdCBzdG9wcyBiZWluZyBjYWxsZWQgZm9yXG4vLyBOIG1pbGxpc2Vjb25kcy4gSWYgYGltbWVkaWF0ZWAgaXMgcGFzc2VkLCB0cmlnZ2VyIHRoZSBmdW5jdGlvbiBvbiB0aGVcbi8vIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuXG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gKiBtaWxsaXNlY29uZHMgaGF2ZSBlbGFwc2VkIHNpbmNlIHRoZSBsYXN0IHRpbWUgdGhlIGRlYm91bmNlZCBmdW5jdGlvbiB3YXNcbiAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICogUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb24gdGhlXG4gKiBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkXG4gKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gKiBjYWxscyB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYFxuICogaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgZGVib3VuY2VgIGFuZCBgdGhyb3R0bGVgLlxuICpcbiAqIEBzaW5jZSA1LjAuMC1iZXRhLjVcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWJvdW5jZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XVxuICogIFRoZSBtYXhpbXVtIHRpbWUgYGZ1bmNgIGlzIGFsbG93ZWQgdG8gYmUgZGVsYXllZCBiZWZvcmUgaXQncyBpbnZva2VkLlxuICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqXG4gKiBAZm9yayAwLjEuMFxuICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gKiBAZnVuY1xuICpcbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vbG9kYXNoL2xvZGFzaC9ibG9iL21hc3Rlci9kZWJvdW5jZS5qcyBsb2Rhc2gtZGVib3VuY2V9XG4gKiBAc2VlIHtAbGluayBsb2Rhc2gtZGVib3VuY2V9XG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBBdm9pZCBjb3N0bHkgY2FsY3VsYXRpb25zIHdoaWxlIHRoZSB3aW5kb3cgc2l6ZSBpcyBpbiBmbHV4LlxuICogalF1ZXJ5KHdpbmRvdykub24oJ3Jlc2l6ZScsIGRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKSlcbiAqXG4gKiAvLyBJbnZva2UgYHNlbmRNYWlsYCB3aGVuIGNsaWNrZWQsIGRlYm91bmNpbmcgc3Vic2VxdWVudCBjYWxscy5cbiAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBkZWJvdW5jZShzZW5kTWFpbCwgMzAwLCB7XG4gKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAqIH0pKVxuICpcbiAqIC8vIEVuc3VyZSBgYmF0Y2hMb2dgIGlzIGludm9rZWQgb25jZSBhZnRlciAxIHNlY29uZCBvZiBkZWJvdW5jZWQgY2FsbHMuXG4gKiBjb25zdCBkZWJvdW5jZWQgPSBkZWJvdW5jZShiYXRjaExvZywgMjUwLCB7ICdtYXhXYWl0JzogMTAwMCB9KVxuICogY29uc3Qgc291cmNlID0gbmV3IEV2ZW50U291cmNlKCcvc3RyZWFtJylcbiAqIGpRdWVyeShzb3VyY2UpLm9uKCdtZXNzYWdlJywgZGVib3VuY2VkKVxuICpcbiAqIC8vIENhbmNlbCB0aGUgdHJhaWxpbmcgZGVib3VuY2VkIGludm9jYXRpb24uXG4gKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCBkZWJvdW5jZWQuY2FuY2VsKVxuICpcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICBsZXQgbGFzdEFyZ3NcbiAgbGV0IGxhc3RUaGlzXG4gIGxldCBtYXhXYWl0XG4gIGxldCByZXN1bHRcbiAgbGV0IHRpbWVySWRcbiAgbGV0IGxhc3RDYWxsVGltZVxuXG4gIGxldCBsYXN0SW52b2tlVGltZSA9IDBcbiAgbGV0IGxlYWRpbmcgPSBmYWxzZVxuICBsZXQgbWF4aW5nID0gZmFsc2VcbiAgbGV0IHRyYWlsaW5nID0gdHJ1ZVxuXG4gIC8vIEBUT0RPIHRoaXMgd291bGQgYmUgY29lcmNpbmdcbiAgaWYgKCFpc0Z1bmN0aW9uKGZ1bmMpKSB7XG4gICAgZnVuYyA9IG5vb3BcbiAgICAvLyB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCBhIGZ1bmN0aW9uJylcbiAgfVxuICAvLyBkZWZhdWx0VG8oMClcbiAgd2FpdCA9IHRvSW50ZWdlcih3YWl0KVxuICAvLyBjb25zdCBvcHRpb25zSGFzID0gaGFzSW4ob3B0aW9ucylcblxuICBpZiAoaXNPYmoob3B0aW9ucykpIHtcbiAgICBsZWFkaW5nID0gISFvcHRpb25zLmxlYWRpbmdcbiAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9uc1xuICAgIG1heFdhaXQgPSBtYXhpbmcgPyBNYXRoLm1heCh0b0ludGVnZXIob3B0aW9ucy5tYXhXYWl0KSwgd2FpdCkgOiBtYXhXYWl0XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZ1xuICB9XG5cbiAgZnVuY3Rpb24gaW52b2tlRnVuYyh0aW1lKSB7XG4gICAgY29uc3QgYXJncyA9IGxhc3RBcmdzXG4gICAgY29uc3QgdGhpc0FyZyA9IGxhc3RUaGlzXG5cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkXG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lXG4gICAgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzKVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIGZ1bmN0aW9uIGxlYWRpbmdFZGdlKHRpbWUpIHtcbiAgICAvLyBSZXNldCBhbnkgYG1heFdhaXRgIHRpbWVyLlxuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZVxuICAgIC8vIFN0YXJ0IHRoZSB0aW1lciBmb3IgdGhlIHRyYWlsaW5nIGVkZ2UuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KVxuICAgIC8vIEludm9rZSB0aGUgbGVhZGluZyBlZGdlLlxuICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgY29uc3QgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lXG4gICAgY29uc3QgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZVxuICAgIGNvbnN0IHRpbWVXYWl0aW5nID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsXG5cbiAgICByZXR1cm4gbWF4aW5nXG4gICAgICA/IE1hdGgubWluKHRpbWVXYWl0aW5nLCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSlcbiAgICAgIDogdGltZVdhaXRpbmdcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgY29uc3QgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lXG4gICAgY29uc3QgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZVxuXG4gICAgLy8gRWl0aGVyIHRoaXMgaXMgdGhlIGZpcnN0IGNhbGwsIGFjdGl2aXR5IGhhcyBzdG9wcGVkIGFuZCB3ZSdyZSBhdCB0aGVcbiAgICAvLyB0cmFpbGluZyBlZGdlLCB0aGUgc3lzdGVtIHRpbWUgaGFzIGdvbmUgYmFja3dhcmRzIGFuZCB3ZSdyZSB0cmVhdGluZ1xuICAgIC8vIGl0IGFzIHRoZSB0cmFpbGluZyBlZGdlLCBvciB3ZSd2ZSBoaXQgdGhlIGBtYXhXYWl0YCBsaW1pdC5cbiAgICByZXR1cm4gKGlzVW5kZWZpbmVkKGxhc3RDYWxsVGltZSkgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpXG4gIH1cblxuICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgY29uc3QgdGltZSA9IERhdGUubm93KClcbiAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpXG4gICAgfVxuXG4gICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKVxuICB9XG5cbiAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICB0aW1lcklkID0gdW5kZWZpbmVkXG5cbiAgICAvLyBPbmx5IGludm9rZSBpZiB3ZSBoYXZlIGBsYXN0QXJnc2Agd2hpY2ggbWVhbnMgYGZ1bmNgIGhhcyBiZWVuXG4gICAgLy8gZGVib3VuY2VkIGF0IGxlYXN0IG9uY2UuXG4gICAgaWYgKHRyYWlsaW5nICYmIGxhc3RBcmdzKSB7XG4gICAgICByZXR1cm4gaW52b2tlRnVuYyh0aW1lKVxuICAgIH1cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgIGlmICghaXNVbmRlZmluZWQodGltZXJJZCkpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcklkKVxuICAgIH1cbiAgICBsYXN0SW52b2tlVGltZSA9IDBcbiAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZFxuICB9XG5cbiAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgcmV0dXJuIGlzVW5kZWZpbmVkKHRpbWVySWQpID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKERhdGUubm93KCkpXG4gIH1cblxuICBmdW5jdGlvbiBkZWJvdW5jZWQoLi4uYXJncykge1xuICAgIGNvbnN0IHRpbWUgPSBEYXRlLm5vdygpXG4gICAgY29uc3QgaXNJbnZva2luZyA9IHNob3VsZEludm9rZSh0aW1lKVxuXG4gICAgbGFzdEFyZ3MgPSBhcmdzXG4gICAgbGFzdFRoaXMgPSB0aGlzXG4gICAgbGFzdENhbGxUaW1lID0gdGltZVxuXG4gICAgaWYgKGlzSW52b2tpbmcpIHtcbiAgICAgIGlmIChpc1VuZGVmaW5lZCh0aW1lcklkKSkge1xuICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKVxuICAgICAgfVxuICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpXG4gICAgICAgIHJldHVybiBpbnZva2VGdW5jKGxhc3RDYWxsVGltZSlcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzVW5kZWZpbmVkKHRpbWVySWQpKSB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpXG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWxcbiAgZGVib3VuY2VkLmZsdXNoID0gZmx1c2hcblxuICByZXR1cm4gZGVib3VuY2VkXG59XG5cbm1vZHVsZS5leHBvcnRzID0gZGVib3VuY2VcblxuXG4vLyB1bmRlcnNjb3JlIGpzIHZlcnNpb25cbi8vIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgaW1tZWRpYXRlKSB7XG4vLyAgIGxldCB0aW1lb3V0XG4vLyAgIGxldCByZXN1bHRcbi8vXG4vLyAgIGNvbnN0IGxhdGVyID0gZnVuY3Rpb24oY29udGV4dCwgYXJncykge1xuLy8gICAgIHRpbWVvdXQgPSBudWxsXG4vLyAgICAgaWYgKGFyZ3MpIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncylcbi8vICAgfVxuLy9cbi8vICAgY29uc3QgZGVib3VuY2VkID0gcmVzdEFyZ3MoZnVuY3Rpb24oYXJncykge1xuLy8gICAgIGlmICh0aW1lb3V0KSBjbGVhclRpbWVvdXQodGltZW91dClcbi8vICAgICBpZiAoaW1tZWRpYXRlKSB7XG4vLyAgICAgICBjb25zdCBjYWxsTm93ID0gIXRpbWVvdXRcbi8vICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KVxuLy8gICAgICAgaWYgKGNhbGxOb3cpIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpcywgYXJncylcbi8vICAgICB9XG4vLyAgICAgZWxzZSB7XG4vLyAgICAgICB0aW1lb3V0ID0gZGVsYXkobGF0ZXIsIHdhaXQsIHRoaXMsIGFyZ3MpXG4vLyAgICAgfVxuLy9cbi8vICAgICByZXR1cm4gcmVzdWx0XG4vLyAgIH0pXG4vL1xuLy8gICBkZWJvdW5jZWQuY2FuY2VsID0gZnVuY3Rpb24oKSB7XG4vLyAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpXG4vLyAgICAgdGltZW91dCA9IG51bGxcbi8vICAgfVxuLy9cbi8vICAgcmV0dXJuIGRlYm91bmNlZFxuLy8gfVxuIl0sIm5hbWVzIjpbImNvbnN0IiwibGV0Il0sIm1hcHBpbmdzIjoiQUFBQUEsR0FBSyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUM7QUFDOUNBLEdBQUssQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDO0FBQzVDQSxHQUFLLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUM7QUFDbENBLEdBQUssQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUNwQ0EsR0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFzRTlDLFNBQVMsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0VBQ3JDQyxHQUFHLENBQUMsUUFBUTtFQUNaQSxHQUFHLENBQUMsUUFBUTtFQUNaQSxHQUFHLENBQUMsT0FBTztFQUNYQSxHQUFHLENBQUMsTUFBTTtFQUNWQSxHQUFHLENBQUMsT0FBTztFQUNYQSxHQUFHLENBQUMsWUFBWTs7RUFFaEJBLEdBQUcsQ0FBQyxjQUFjLEdBQUcsQ0FBQztFQUN0QkEsR0FBRyxDQUFDLE9BQU8sR0FBRyxLQUFLO0VBQ25CQSxHQUFHLENBQUMsTUFBTSxHQUFHLEtBQUs7RUFDbEJBLEdBQUcsQ0FBQyxRQUFRLEdBQUcsSUFBSTs7O0VBR25CLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUU7SUFDckIsSUFBSSxHQUFHLElBQUk7O0dBRVo7O0VBRUQsSUFBSSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUM7OztFQUd0QixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUNsQixPQUFPLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPO0lBQzNCLE1BQU0sR0FBRyxTQUFTLElBQUksT0FBTztJQUM3QixPQUFPLEdBQUcsTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxPQUFPO0lBQ3ZFLFFBQVEsR0FBRyxVQUFVLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxHQUFHLFFBQVE7R0FDakU7O0VBRUQsU0FBUyxVQUFVLENBQUMsSUFBSSxFQUFFO0lBQ3hCRCxHQUFLLENBQUMsSUFBSSxHQUFHLFFBQVE7SUFDckJBLEdBQUssQ0FBQyxPQUFPLEdBQUcsUUFBUTs7SUFFeEIsUUFBUSxHQUFHLFFBQVEsR0FBRyxTQUFTO0lBQy9CLGNBQWMsR0FBRyxJQUFJO0lBQ3JCLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUM7SUFDbEMsT0FBTyxNQUFNO0dBQ2Q7O0VBRUQsU0FBUyxXQUFXLENBQUMsSUFBSSxFQUFFOztJQUV6QixjQUFjLEdBQUcsSUFBSTs7SUFFckIsT0FBTyxHQUFHLFVBQVUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDOztJQUV4QyxPQUFPLE9BQU8sR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTTtHQUMzQzs7RUFFRCxTQUFTLGFBQWEsQ0FBQyxJQUFJLEVBQUU7SUFDM0JBLEdBQUssQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLEdBQUcsWUFBWTtJQUM3Q0EsR0FBSyxDQUFDLG1CQUFtQixHQUFHLElBQUksR0FBRyxjQUFjO0lBQ2pEQSxHQUFLLENBQUMsV0FBVyxHQUFHLElBQUksR0FBRyxpQkFBaUI7O0lBRTVDLE9BQU8sTUFBTTtRQUNULElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQztRQUNwRCxXQUFXO0dBQ2hCOztFQUVELFNBQVMsWUFBWSxDQUFDLElBQUksRUFBRTtJQUMxQkEsR0FBSyxDQUFDLGlCQUFpQixHQUFHLElBQUksR0FBRyxZQUFZO0lBQzdDQSxHQUFLLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxHQUFHLGNBQWM7Ozs7O0lBS2pELE9BQU8sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxJQUFJLENBQUM7TUFDOUQsQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxtQkFBbUIsSUFBSSxPQUFPLENBQUMsQ0FBQztHQUN6RTs7RUFFRCxTQUFTLFlBQVksR0FBRztJQUN0QkEsR0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFO0lBQ3ZCLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFO01BQ3RCLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQztLQUMxQjs7O0lBR0QsT0FBTyxHQUFHLFVBQVUsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO0dBQ3hEOztFQUVELFNBQVMsWUFBWSxDQUFDLElBQUksRUFBRTtJQUMxQixPQUFPLEdBQUcsU0FBUzs7OztJQUluQixJQUFJLFFBQVEsSUFBSSxRQUFRLEVBQUU7TUFDeEIsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDO0tBQ3hCO0lBQ0QsUUFBUSxHQUFHLFFBQVEsR0FBRyxTQUFTO0lBQy9CLE9BQU8sTUFBTTtHQUNkOztFQUVELFNBQVMsTUFBTSxHQUFHO0lBQ2hCLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLEVBQUU7TUFDekIsWUFBWSxDQUFDLE9BQU8sQ0FBQztLQUN0QjtJQUNELGNBQWMsR0FBRyxDQUFDO0lBQ2xCLFFBQVEsR0FBRyxZQUFZLEdBQUcsUUFBUSxHQUFHLE9BQU8sR0FBRyxTQUFTO0dBQ3pEOztFQUVELFNBQVMsS0FBSyxHQUFHO0lBQ2YsT0FBTyxXQUFXLENBQUMsT0FBTyxDQUFDLEdBQUcsTUFBTSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7R0FDaEU7O0VBRUQsU0FBUyxTQUFTLENBQUMsR0FBRyxJQUFJLEVBQUU7SUFDMUJBLEdBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRTtJQUN2QkEsR0FBSyxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDOztJQUVyQyxRQUFRLEdBQUcsSUFBSTtJQUNmLFFBQVEsR0FBRyxJQUFJO0lBQ2YsWUFBWSxHQUFHLElBQUk7O0lBRW5CLElBQUksVUFBVSxFQUFFO01BQ2QsSUFBSSxXQUFXLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDeEIsT0FBTyxXQUFXLENBQUMsWUFBWSxDQUFDO09BQ2pDO01BQ0QsSUFBSSxNQUFNLEVBQUU7O1FBRVYsT0FBTyxHQUFHLFVBQVUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDO1FBQ3hDLE9BQU8sVUFBVSxDQUFDLFlBQVksQ0FBQztPQUNoQztLQUNGO0lBQ0QsSUFBSSxXQUFXLENBQUMsT0FBTyxDQUFDLEVBQUU7TUFDeEIsT0FBTyxHQUFHLFVBQVUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDO0tBQ3pDO0lBQ0QsT0FBTyxNQUFNO0dBQ2Q7O0VBRUQsU0FBUyxDQUFDLE1BQU0sR0FBRyxNQUFNO0VBQ3pCLFNBQVMsQ0FBQyxLQUFLLEdBQUcsS0FBSzs7RUFFdkIsT0FBTyxTQUFTO0NBQ2pCOztBQUVELE1BQU0sQ0FBQyxPQUFPLEdBQUcsUUFBUTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==