"use strict"; /* * Async utility functions for the RSpade framework. * These functions handle asynchronous operations, delays, debouncing, and mutexes. */ // ============================================================================ // ASYNC UTILITIES // ============================================================================ /** * Pauses execution for specified milliseconds * @param {number} [milliseconds=0] - Delay in milliseconds (0 uses requestAnimationFrame) * @returns {Promise} Promise that resolves after delay * @example await sleep(1000); // Wait 1 second */ function sleep() { let milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; return new Promise(resolve => { if (milliseconds == 0 && requestAnimationFrame) { requestAnimationFrame(resolve); } else { setTimeout(resolve, milliseconds); } }); } /** * Creates a debounced function with exclusivity and promise fan-in * * This function, when invoked, immediately runs the callback exclusively. * For subsequent invocations, it applies a delay before running the callback exclusively again. * The delay starts after the current asynchronous operation resolves. * * If 'delay' is set to 0, the function will only prevent enqueueing multiple executions of the * same method more than once, but will still run them immediately in an exclusive sequential manner. * * The most recent invocation of the function will be the parameters that get passed to the function * when it invokes. * * The function returns a promise that resolves when the next exclusive execution completes. * * Usage as function: * const debouncedFn = debounce(myFunction, 250); * * Usage as decorator: * @debounce(250) * myMethod() { ... } * * @param {function|number} callback_or_delay The callback function OR delay when used as decorator * @param {number} delay The delay in milliseconds before subsequent invocations * @param {boolean} immediate if true, the first time the action is called, the callback executes immediately * @returns {function} A function that when invoked, runs the callback immediately and exclusively, * * @decorator */ function debounce(callback_or_delay, delay) { let immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; // Decorator usage: @debounce(250) or @debounce(250, true) // First argument is a number (the delay), returns decorator function if (typeof callback_or_delay === 'number') { const decorator_delay = callback_or_delay; const decorator_immediate = delay || false; // TC39 decorator form: receives (value, context) return function (value, context) { if (context.kind === 'method') { return debounce_impl(value, decorator_delay, decorator_immediate); } }; } // Function usage: debounce(fn, 250) // First argument is a function (the callback) const callback = callback_or_delay; return debounce_impl(callback, delay, immediate); } /** * Internal implementation of debounce logic * @private */ function debounce_impl(callback, delay) { let immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; let running = false; let queued = false; let last_end_time = 0; // timestamp of last completed run let timer = null; let next_args = []; let next_context = null; let resolve_queue = []; let reject_queue = []; const run_function = async () => { const these_resolves = resolve_queue; const these_rejects = reject_queue; const args = next_args; const context = next_context; resolve_queue = []; reject_queue = []; next_args = []; next_context = null; queued = false; running = true; try { const result = await callback.apply(context, args); for (const resolve of these_resolves) resolve(result); } catch (err) { for (const reject of these_rejects) reject(err); } finally { running = false; last_end_time = Date.now(); if (queued) { clearTimeout(timer); timer = setTimeout(run_function, Math.max(delay, 0)); } else { timer = null; } } }; return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } next_args = args; next_context = this; return new Promise((resolve, reject) => { resolve_queue.push(resolve); reject_queue.push(reject); // Nothing running and nothing scheduled if (!running && !timer) { const first_call = last_end_time === 0; if (immediate && first_call) { run_function(); return; } const since = first_call ? Infinity : Date.now() - last_end_time; if (since >= delay) { run_function(); } else { const wait = Math.max(delay - since, 0); clearTimeout(timer); timer = setTimeout(run_function, wait); } return; } // If we're already running or a timer exists, just mark queued. // The finally{} of run_function handles scheduling after full delay. queued = true; }); }; } // ============================================================================ // READ-WRITE LOCK FUNCTIONS - Delegated to ReadWriteLock class // ============================================================================ /** * Acquire an exclusive write lock by name. * Only one writer runs at a time; blocks readers until finished. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ function rwlock(name, cb) { return ReadWriteLock.acquire(name, cb); } /** * Acquire a shared read lock by name. * Multiple readers run in parallel, but readers are blocked by queued/active writers. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ function rwlock_read(name, cb) { return ReadWriteLock.acquire_read(name, cb); } /** * Forcefully clear all locks and queues for a given name. * @param {string} name */ function rwlock_force_unlock(name) { ReadWriteLock.force_unlock(name); } /** * Inspect lock state for debugging. * @param {string} name * @returns {{readers:number, writer_active:boolean, reader_q:number, writer_q:number}} */ function rwlock_pending(name) { return ReadWriteLock.pending(name); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJzbGVlcCIsIm1pbGxpc2Vjb25kcyIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVxdWVzdEFuaW1hdGlvbkZyYW1lIiwic2V0VGltZW91dCIsImRlYm91bmNlIiwiY2FsbGJhY2tfb3JfZGVsYXkiLCJkZWxheSIsImltbWVkaWF0ZSIsImRlY29yYXRvcl9kZWxheSIsImRlY29yYXRvcl9pbW1lZGlhdGUiLCJ2YWx1ZSIsImNvbnRleHQiLCJraW5kIiwiZGVib3VuY2VfaW1wbCIsImNhbGxiYWNrIiwicnVubmluZyIsInF1ZXVlZCIsImxhc3RfZW5kX3RpbWUiLCJ0aW1lciIsIm5leHRfYXJncyIsIm5leHRfY29udGV4dCIsInJlc29sdmVfcXVldWUiLCJyZWplY3RfcXVldWUiLCJydW5fZnVuY3Rpb24iLCJ0aGVzZV9yZXNvbHZlcyIsInRoZXNlX3JlamVjdHMiLCJhcmdzIiwicmVzdWx0IiwiYXBwbHkiLCJlcnIiLCJyZWplY3QiLCJEYXRlIiwibm93IiwiY2xlYXJUaW1lb3V0IiwiTWF0aCIsIm1heCIsIl9sZW4iLCJBcnJheSIsIl9rZXkiLCJwdXNoIiwiZmlyc3RfY2FsbCIsInNpbmNlIiwiSW5maW5pdHkiLCJ3YWl0Iiwicndsb2NrIiwibmFtZSIsImNiIiwiUmVhZFdyaXRlTG9jayIsImFjcXVpcmUiLCJyd2xvY2tfcmVhZCIsImFjcXVpcmVfcmVhZCIsInJ3bG9ja19mb3JjZV91bmxvY2siLCJmb3JjZV91bmxvY2siLCJyd2xvY2tfcGVuZGluZyIsInBlbmRpbmciXSwic291cmNlcyI6WyJhcHAvUlNwYWRlL0NvcmUvSnMvYXN5bmMuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIEFzeW5jIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgYXN5bmNocm9ub3VzIG9wZXJhdGlvbnMsIGRlbGF5cywgZGVib3VuY2luZywgYW5kIG11dGV4ZXMuXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQVNZTkMgVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogUGF1c2VzIGV4ZWN1dGlvbiBmb3Igc3BlY2lmaWVkIG1pbGxpc2Vjb25kc1xuICogQHBhcmFtIHtudW1iZXJ9IFttaWxsaXNlY29uZHM9MF0gLSBEZWxheSBpbiBtaWxsaXNlY29uZHMgKDAgdXNlcyByZXF1ZXN0QW5pbWF0aW9uRnJhbWUpXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIGRlbGF5XG4gKiBAZXhhbXBsZSBhd2FpdCBzbGVlcCgxMDAwKTsgLy8gV2FpdCAxIHNlY29uZFxuICovXG5mdW5jdGlvbiBzbGVlcChtaWxsaXNlY29uZHMgPSAwKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIGlmIChtaWxsaXNlY29uZHMgPT0gMCAmJiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShyZXNvbHZlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgbWlsbGlzZWNvbmRzKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gd2l0aCBleGNsdXNpdml0eSBhbmQgcHJvbWlzZSBmYW4taW5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uLCB3aGVuIGludm9rZWQsIGltbWVkaWF0ZWx5IHJ1bnMgdGhlIGNhbGxiYWNrIGV4Y2x1c2l2ZWx5LlxuICogRm9yIHN1YnNlcXVlbnQgaW52b2NhdGlvbnMsIGl0IGFwcGxpZXMgYSBkZWxheSBiZWZvcmUgcnVubmluZyB0aGUgY2FsbGJhY2sgZXhjbHVzaXZlbHkgYWdhaW4uXG4gKiBUaGUgZGVsYXkgc3RhcnRzIGFmdGVyIHRoZSBjdXJyZW50IGFzeW5jaHJvbm91cyBvcGVyYXRpb24gcmVzb2x2ZXMuXG4gKlxuICogSWYgJ2RlbGF5JyBpcyBzZXQgdG8gMCwgdGhlIGZ1bmN0aW9uIHdpbGwgb25seSBwcmV2ZW50IGVucXVldWVpbmcgbXVsdGlwbGUgZXhlY3V0aW9ucyBvZiB0aGVcbiAqIHNhbWUgbWV0aG9kIG1vcmUgdGhhbiBvbmNlLCBidXQgd2lsbCBzdGlsbCBydW4gdGhlbSBpbW1lZGlhdGVseSBpbiBhbiBleGNsdXNpdmUgc2VxdWVudGlhbCBtYW5uZXIuXG4gKlxuICogVGhlIG1vc3QgcmVjZW50IGludm9jYXRpb24gb2YgdGhlIGZ1bmN0aW9uIHdpbGwgYmUgdGhlIHBhcmFtZXRlcnMgdGhhdCBnZXQgcGFzc2VkIHRvIHRoZSBmdW5jdGlvblxuICogd2hlbiBpdCBpbnZva2VzLlxuICpcbiAqIFRoZSBmdW5jdGlvbiByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG5leHQgZXhjbHVzaXZlIGV4ZWN1dGlvbiBjb21wbGV0ZXMuXG4gKlxuICogVXNhZ2UgYXMgZnVuY3Rpb246XG4gKiAgIGNvbnN0IGRlYm91bmNlZEZuID0gZGVib3VuY2UobXlGdW5jdGlvbiwgMjUwKTtcbiAqXG4gKiBVc2FnZSBhcyBkZWNvcmF0b3I6XG4gKiAgIEBkZWJvdW5jZSgyNTApXG4gKiAgIG15TWV0aG9kKCkgeyAuLi4gfVxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb258bnVtYmVyfSBjYWxsYmFja19vcl9kZWxheSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gT1IgZGVsYXkgd2hlbiB1c2VkIGFzIGRlY29yYXRvclxuICogQHBhcmFtIHtudW1iZXJ9IGRlbGF5IFRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHN1YnNlcXVlbnQgaW52b2NhdGlvbnNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaW1tZWRpYXRlIGlmIHRydWUsIHRoZSBmaXJzdCB0aW1lIHRoZSBhY3Rpb24gaXMgY2FsbGVkLCB0aGUgY2FsbGJhY2sgZXhlY3V0ZXMgaW1tZWRpYXRlbHlcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0aGF0IHdoZW4gaW52b2tlZCwgcnVucyB0aGUgY2FsbGJhY2sgaW1tZWRpYXRlbHkgYW5kIGV4Y2x1c2l2ZWx5LFxuICpcbiAqIEBkZWNvcmF0b3JcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoY2FsbGJhY2tfb3JfZGVsYXksIGRlbGF5LCBpbW1lZGlhdGUgPSBmYWxzZSkge1xuICAgIC8vIERlY29yYXRvciB1c2FnZTogQGRlYm91bmNlKDI1MCkgb3IgQGRlYm91bmNlKDI1MCwgdHJ1ZSlcbiAgICAvLyBGaXJzdCBhcmd1bWVudCBpcyBhIG51bWJlciAodGhlIGRlbGF5KSwgcmV0dXJucyBkZWNvcmF0b3IgZnVuY3Rpb25cbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrX29yX2RlbGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JfZGVsYXkgPSBjYWxsYmFja19vcl9kZWxheTtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9yX2ltbWVkaWF0ZSA9IGRlbGF5IHx8IGZhbHNlO1xuXG4gICAgICAgIC8vIFRDMzkgZGVjb3JhdG9yIGZvcm06IHJlY2VpdmVzICh2YWx1ZSwgY29udGV4dClcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgY29udGV4dCkge1xuICAgICAgICAgICAgaWYgKGNvbnRleHQua2luZCA9PT0gJ21ldGhvZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVib3VuY2VfaW1wbCh2YWx1ZSwgZGVjb3JhdG9yX2RlbGF5LCBkZWNvcmF0b3JfaW1tZWRpYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGdW5jdGlvbiB1c2FnZTogZGVib3VuY2UoZm4sIDI1MClcbiAgICAvLyBGaXJzdCBhcmd1bWVudCBpcyBhIGZ1bmN0aW9uICh0aGUgY2FsbGJhY2spXG4gICAgY29uc3QgY2FsbGJhY2sgPSBjYWxsYmFja19vcl9kZWxheTtcbiAgICByZXR1cm4gZGVib3VuY2VfaW1wbChjYWxsYmFjaywgZGVsYXksIGltbWVkaWF0ZSk7XG59XG5cbi8qKlxuICogSW50ZXJuYWwgaW1wbGVtZW50YXRpb24gb2YgZGVib3VuY2UgbG9naWNcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGRlYm91bmNlX2ltcGwoY2FsbGJhY2ssIGRlbGF5LCBpbW1lZGlhdGUgPSBmYWxzZSkge1xuICAgIGxldCBydW5uaW5nID0gZmFsc2U7XG4gICAgbGV0IHF1ZXVlZCA9IGZhbHNlO1xuICAgIGxldCBsYXN0X2VuZF90aW1lID0gMDsgLy8gdGltZXN0YW1wIG9mIGxhc3QgY29tcGxldGVkIHJ1blxuICAgIGxldCB0aW1lciA9IG51bGw7XG5cbiAgICBsZXQgbmV4dF9hcmdzID0gW107XG4gICAgbGV0IG5leHRfY29udGV4dCA9IG51bGw7XG4gICAgbGV0IHJlc29sdmVfcXVldWUgPSBbXTtcbiAgICBsZXQgcmVqZWN0X3F1ZXVlID0gW107XG5cbiAgICBjb25zdCBydW5fZnVuY3Rpb24gPSBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHRoZXNlX3Jlc29sdmVzID0gcmVzb2x2ZV9xdWV1ZTtcbiAgICAgICAgY29uc3QgdGhlc2VfcmVqZWN0cyA9IHJlamVjdF9xdWV1ZTtcbiAgICAgICAgY29uc3QgYXJncyA9IG5leHRfYXJncztcbiAgICAgICAgY29uc3QgY29udGV4dCA9IG5leHRfY29udGV4dDtcblxuICAgICAgICByZXNvbHZlX3F1ZXVlID0gW107XG4gICAgICAgIHJlamVjdF9xdWV1ZSA9IFtdO1xuICAgICAgICBuZXh0X2FyZ3MgPSBbXTtcbiAgICAgICAgbmV4dF9jb250ZXh0ID0gbnVsbDtcbiAgICAgICAgcXVldWVkID0gZmFsc2U7XG4gICAgICAgIHJ1bm5pbmcgPSB0cnVlO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjYWxsYmFjay5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVzb2x2ZSBvZiB0aGVzZV9yZXNvbHZlcykgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVqZWN0IG9mIHRoZXNlX3JlamVjdHMpIHJlamVjdChlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgcnVubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgbGFzdF9lbmRfdGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBpZiAocXVldWVkKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQocnVuX2Z1bmN0aW9uLCBNYXRoLm1heChkZWxheSwgMCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aW1lciA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIG5leHRfYXJncyA9IGFyZ3M7XG4gICAgICAgIG5leHRfY29udGV4dCA9IHRoaXM7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmVfcXVldWUucHVzaChyZXNvbHZlKTtcbiAgICAgICAgICAgIHJlamVjdF9xdWV1ZS5wdXNoKHJlamVjdCk7XG5cbiAgICAgICAgICAgIC8vIE5vdGhpbmcgcnVubmluZyBhbmQgbm90aGluZyBzY2hlZHVsZWRcbiAgICAgICAgICAgIGlmICghcnVubmluZyAmJiAhdGltZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdF9jYWxsID0gbGFzdF9lbmRfdGltZSA9PT0gMDtcblxuICAgICAgICAgICAgICAgIGlmIChpbW1lZGlhdGUgJiYgZmlyc3RfY2FsbCkge1xuICAgICAgICAgICAgICAgICAgICBydW5fZnVuY3Rpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNpbmNlID0gZmlyc3RfY2FsbCA/IEluZmluaXR5IDogRGF0ZS5ub3coKSAtIGxhc3RfZW5kX3RpbWU7XG4gICAgICAgICAgICAgICAgaWYgKHNpbmNlID49IGRlbGF5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bl9mdW5jdGlvbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHdhaXQgPSBNYXRoLm1heChkZWxheSAtIHNpbmNlLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KHJ1bl9mdW5jdGlvbiwgd2FpdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgd2UncmUgYWxyZWFkeSBydW5uaW5nIG9yIGEgdGltZXIgZXhpc3RzLCBqdXN0IG1hcmsgcXVldWVkLlxuICAgICAgICAgICAgLy8gVGhlIGZpbmFsbHl7fSBvZiBydW5fZnVuY3Rpb24gaGFuZGxlcyBzY2hlZHVsaW5nIGFmdGVyIGZ1bGwgZGVsYXkuXG4gICAgICAgICAgICBxdWV1ZWQgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBSRUFELVdSSVRFIExPQ0sgRlVOQ1RJT05TIC0gRGVsZWdhdGVkIHRvIFJlYWRXcml0ZUxvY2sgY2xhc3Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBBY3F1aXJlIGFuIGV4Y2x1c2l2ZSB3cml0ZSBsb2NrIGJ5IG5hbWUuXG4gKiBPbmx5IG9uZSB3cml0ZXIgcnVucyBhdCBhIHRpbWU7IGJsb2NrcyByZWFkZXJzIHVudGlsIGZpbmlzaGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fFByb21pc2U8YW55Pn0gY2JcbiAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gKi9cbmZ1bmN0aW9uIHJ3bG9jayhuYW1lLCBjYikge1xuICAgIHJldHVybiBSZWFkV3JpdGVMb2NrLmFjcXVpcmUobmFtZSwgY2IpO1xufVxuXG4vKipcbiAqIEFjcXVpcmUgYSBzaGFyZWQgcmVhZCBsb2NrIGJ5IG5hbWUuXG4gKiBNdWx0aXBsZSByZWFkZXJzIHJ1biBpbiBwYXJhbGxlbCwgYnV0IHJlYWRlcnMgYXJlIGJsb2NrZWQgYnkgcXVldWVkL2FjdGl2ZSB3cml0ZXJzLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fFByb21pc2U8YW55Pn0gY2JcbiAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gKi9cbmZ1bmN0aW9uIHJ3bG9ja19yZWFkKG5hbWUsIGNiKSB7XG4gICAgcmV0dXJuIFJlYWRXcml0ZUxvY2suYWNxdWlyZV9yZWFkKG5hbWUsIGNiKTtcbn1cblxuLyoqXG4gKiBGb3JjZWZ1bGx5IGNsZWFyIGFsbCBsb2NrcyBhbmQgcXVldWVzIGZvciBhIGdpdmVuIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICovXG5mdW5jdGlvbiByd2xvY2tfZm9yY2VfdW5sb2NrKG5hbWUpIHtcbiAgICBSZWFkV3JpdGVMb2NrLmZvcmNlX3VubG9jayhuYW1lKTtcbn1cblxuLyoqXG4gKiBJbnNwZWN0IGxvY2sgc3RhdGUgZm9yIGRlYnVnZ2luZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcmV0dXJucyB7e3JlYWRlcnM6bnVtYmVyLCB3cml0ZXJfYWN0aXZlOmJvb2xlYW4sIHJlYWRlcl9xOm51bWJlciwgd3JpdGVyX3E6bnVtYmVyfX1cbiAqL1xuZnVuY3Rpb24gcndsb2NrX3BlbmRpbmcobmFtZSkge1xuICAgIHJldHVybiBSZWFkV3JpdGVMb2NrLnBlbmRpbmcobmFtZSk7XG59XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNBLEtBQUtBLENBQUEsRUFBbUI7RUFBQSxJQUFsQkMsWUFBWSxHQUFBQyxTQUFBLENBQUFDLE1BQUEsUUFBQUQsU0FBQSxRQUFBRSxTQUFBLEdBQUFGLFNBQUEsTUFBRyxDQUFDO0VBQzNCLE9BQU8sSUFBSUcsT0FBTyxDQUFFQyxPQUFPLElBQUs7SUFDNUIsSUFBSUwsWUFBWSxJQUFJLENBQUMsSUFBSU0scUJBQXFCLEVBQUU7TUFDNUNBLHFCQUFxQixDQUFDRCxPQUFPLENBQUM7SUFDbEMsQ0FBQyxNQUFNO01BQ0hFLFVBQVUsQ0FBQ0YsT0FBTyxFQUFFTCxZQUFZLENBQUM7SUFDckM7RUFDSixDQUFDLENBQUM7QUFDTjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU1EsUUFBUUEsQ0FBQ0MsaUJBQWlCLEVBQUVDLEtBQUssRUFBcUI7RUFBQSxJQUFuQkMsU0FBUyxH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