foop
Version:
interfaces that describe their intentions.
243 lines (215 loc) • 21.6 kB
JavaScript
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/IE1hdGgubWluKHRpbWVXYWl0aW5nLCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSlcbiAgICAgIDogdGltZVdhaXRpbmdcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgY29uc3QgdGltZVNpbmNlTGFzdENhbGwgPSB0aW1lIC0gbGFzdENhbGxUaW1lXG4gICAgY29uc3QgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZVxuXG4gICAgLy8gRWl0aGVyIHRoaXMgaXMgdGhlIGZpcnN0IGNhbGwsIGFjdGl2aXR5IGhhcyBzdG9wcGVkIGFuZCB3ZSdyZSBhdCB0aGVcbiAgICAvLyB0cmFpbGluZyBlZGdlLCB0aGUgc3lzdGVtIHRpbWUgaGFzIGdvbmUgYmFja3dhcmRzIGFuZCB3ZSdyZSB0cmVhdGluZ1xuICAgIC8vIGl0IGFzIHRoZSB0cmFpbGluZyBlZGdlLCBvciB3ZSd2ZSBoaXQgdGhlIGBtYXhXYWl0YCBsaW1pdC5cbiAgICByZXR1cm4gKGlzVW5kZWZpbmVkKGxhc3RDYWxsVGltZSkgfHwgKHRpbWVTaW5jZUxhc3RDYWxsID49IHdhaXQpIHx8XG4gICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpXG4gIH1cblxuICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgY29uc3QgdGltZSA9IERhdGUubm93KClcbiAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpXG4gICAgfVxuXG4gICAgLy8gUmVzdGFydCB0aGUgdGltZXIuXG4gICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCByZW1haW5pbmdXYWl0KHRpbWUpKVxuICB9XG5cbiAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICB0aW1lcklkID0gdW5kZWZpbmVkXG5cbiAgICAvLyBPbmx5IGludm9rZSBpZiB3ZSBoYXZlIGBsYXN0QXJnc2Agd2hpY2ggbWVhbnMgYGZ1bmNgIGhhcyBiZWVuXG4gICAgLy8gZGVib3VuY2VkIGF0IGxlYXN0IG9uY2UuXG4gICAgaWYgKHRyYWlsaW5nICYmIGxhc3RBcmdzKSB7XG4gICAgICByZXR1cm4gaW52b2tlRnVuYyh0aW1lKVxuICAgIH1cbiAgICBsYXN0QXJncyA9IGxhc3RUaGlzID0gdW5kZWZpbmVkXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgIGlmICghaXNVbmRlZmluZWQodGltZXJJZCkpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aW1lcklkKVxuICAgIH1cbiAgICBsYXN0SW52b2tlVGltZSA9IDBcbiAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZFxuICB9XG5cbiAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgcmV0dXJuIGlzVW5kZWZpbmVkKHRpbWVySWQpID8gcmVzdWx0IDogdHJhaWxpbmdFZGdlKERhdGUubm93KCkpXG4gIH1cblxuICBmdW5jdGlvbiBkZWJvdW5jZWQoLi4uYXJncykge1xuICAgIGNvbnN0IHRpbWUgPSBEYXRlLm5vdygpXG4gICAgY29uc3QgaXNJbnZva2luZyA9IHNob3VsZEludm9rZSh0aW1lKVxuXG4gICAgbGFzdEFyZ3MgPSBhcmdzXG4gICAgbGFzdFRoaXMgPSB0aGlzXG4gICAgbGFzdENhbGxUaW1lID0gdGltZVxuXG4gICAgaWYgKGlzSW52b2tpbmcpIHtcbiAgICAgIGlmIChpc1VuZGVmaW5lZCh0aW1lcklkKSkge1xuICAgICAgICByZXR1cm4gbGVhZGluZ0VkZ2UobGFzdENhbGxUaW1lKVxuICAgICAgfVxuICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpXG4gICAgICAgIHJldHVybiBpbnZva2VGdW5jKGxhc3RDYWxsVGltZSlcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzVW5kZWZpbmVkKHRpbWVySWQpKSB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpXG4gICAgfVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWxcbiAgZGVib3VuY2VkLmZsdXNoID0gZmx1c2hcblxuICByZXR1cm4gZGVib3VuY2VkXG59XG5cbm1vZHVsZS5leHBvcnRzID0gZGVib3VuY2VcblxuXG4vLyB1bmRlcnNjb3JlIGpzIHZlcnNpb25cbi8vIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgaW1tZWRpYXRlKSB7XG4vLyAgIGxldCB0aW1lb3V0XG4vLyAgIGxldCByZXN1bHRcbi8vXG4vLyAgIGNvbnN0IGxhdGVyID0gZnVuY3Rpb24oY29udGV4dCwgYXJncykge1xuLy8gICAgIHRpbWVvdXQgPSBudWxsXG4vLyAgICAgaWYgKGFyZ3MpIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncylcbi8vICAgfVxuLy9cbi8vICAgY29uc3QgZGVib3VuY2VkID0gcmVzdEFyZ3MoZnVuY3Rpb24oYXJncykge1xuLy8gICAgIGlmICh0aW1lb3V0KSBjbGVhclRpbWVvdXQodGltZW91dClcbi8vICAgICBpZiAoaW1tZWRpYXRlKSB7XG4vLyAgICAgICBjb25zdCBjYWxsTm93ID0gIXRpbWVvdXRcbi8vICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KVxuLy8gICAgICAgaWYgKGNhbGxOb3cpIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpcywgYXJncylcbi8vICAgICB9XG4vLyAgICAgZWxzZSB7XG4vLyAgICAgICB0aW1lb3V0ID0gZGVsYXkobGF0ZXIsIHdhaXQsIHRoaXMsIGFyZ3MpXG4vLyAgICAgfVxuLy9cbi8vICAgICByZXR1cm4gcmVzdWx0XG4vLyAgIH0pXG4vL1xuLy8gICBkZWJvdW5jZWQuY2FuY2VsID0gZnVuY3Rpb24oKSB7XG4vLyAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpXG4vLyAgICAgdGltZW91dCA9IG51bGxcbi8vICAgfVxuLy9cbi8vICAgcmV0dXJuIGRlYm91bmNlZFxuLy8gfVxuIl0sIm5hbWVzIjpbImNvbnN0IiwibGV0Il0sIm1hcHBpbmdzIjoiQUFBQUEsR0FBSyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUM7QUFDOUNBLEdBQUssQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUFDO0FBQzVDQSxHQUFLLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUM7QUFDbENBLEdBQUssQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUNwQ0EsR0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFzRTlDLFNBQVMsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0VBQ3JDQyxHQUFHLENBQUMsUUFBUTtFQUNaQSxHQUFHLENBQUMsUUFBUTtFQUNaQSxHQUFHLENBQUMsT0FBTztFQUNYQSxHQUFHLENBQUMsTUFBTTtFQUNWQSxHQUFHLENBQUMsT0FBTztFQUNYQSxHQUFHLENBQUMsWUFBWTs7RUFFaEJBLEdBQUcsQ0FBQyxjQUFjLEdBQUcsQ0FBQztFQUN0QkEsR0FBRyxDQUFDLE9BQU8sR0FBRyxLQUFLO0VBQ25CQSxHQUFHLENB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