UNPKG

@orbit/utils

Version:

Core utilities for Orbit.

224 lines 20.1 kB
/* eslint-disable @typescript-eslint/explicit-module-boundary-types, valid-jsdoc */ /** * Clones a value. If the value is an object, a deeply nested clone will be * created. * * Traverses all object properties (but not prototype properties). */ export function clone(obj) { if (obj === undefined || obj === null || typeof obj !== 'object') { return obj; } let dup; let type = Object.prototype.toString.call(obj); if (type === '[object Date]') { dup = new Date(); dup.setTime(obj.getTime()); } else if (type === '[object RegExp]') { dup = obj.constructor(obj); } else if (type === '[object Array]') { dup = []; for (let i = 0, len = obj.length; i < len; i++) { if (obj.hasOwnProperty(i)) { dup.push(clone(obj[i])); } } } else { let val; dup = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { val = obj[key]; if (typeof val === 'object') { val = clone(val); } dup[key] = val; } } } return dup; } /** * Expose properties and methods from one object on another. * * Methods will be called on `source` and will maintain `source` as the context. * * @deprecated since v0.17 */ export function expose(destination, source) { let properties; if (arguments.length > 2) { properties = Array.prototype.slice.call(arguments, 2); } else { properties = Object.keys(source); } properties.forEach((p) => { if (typeof source[p] === 'function') { destination[p] = function () { return source[p].apply(source, arguments); }; } else { destination[p] = source[p]; } }); } /** * Extend an object with the properties of one or more other objects. * * @deprecated since v0.17 */ export function extend(destination, ...sources) { sources.forEach((source) => { for (let p in source) { if (source.hasOwnProperty(p)) { destination[p] = source[p]; } } }); return destination; } /** * Converts an object to an `Array` if it's not already. * * @export * @param {*} obj * @returns {any[]} */ export function toArray(obj) { if (isNone(obj)) { return []; } else { return Array.isArray(obj) ? obj : [obj]; } } /** * Checks whether a value is a non-null object * * @export * @param {*} obj * @returns {boolean} */ export function isObject(obj) { return obj !== null && typeof obj === 'object'; } /** * Checks whether an object is null or undefined * * @export * @param {*} obj * @returns {boolean} */ export function isNone(obj) { return obj === undefined || obj === null; } /** * Merges properties from other objects into a base object. Properties that * resolve to `undefined` will not overwrite properties on the base object * that already exist. * * @deprecated since v0.17 */ export function merge(object, ...sources) { sources.forEach((source) => { Object.keys(source).forEach((field) => { if (source.hasOwnProperty(field)) { let value = source[field]; if (value !== undefined) { object[field] = clone(value); } } }); }); return object; } /** * Merges properties from other objects into a base object, traversing and * merging any objects that are encountered. * * Properties that resolve to `undefined` will not overwrite properties on the * base object that already exist. */ export function deepMerge(object, ...sources) { sources.forEach((source) => { Object.keys(source).forEach((field) => { if (source.hasOwnProperty(field)) { let a = object[field]; let b = source[field]; if (isObject(a) && isObject(b) && !Array.isArray(a) && !Array.isArray(b)) { deepMerge(a, b); } else if (b !== undefined) { object[field] = clone(b); } } }); }); return object; } /** * Retrieves a value from a nested path on an object. * * Returns any falsy value encountered while traversing the path. */ export function deepGet(obj, path) { let index = -1; let result = obj; while (++index < path.length) { result = result[path[index]]; if (!result) { return result; } } return result; } /** * Sets a value on an object at a nested path. * * This function will create objects along the path if necessary to allow * setting a deeply nested value. * * Returns `false` only if the current value is already strictly equal to the * requested `value` argument. Otherwise returns `true`. */ export function deepSet(obj, path, value) { let ptr = obj; let prop = path.pop(); let segment; for (let i = 0, l = path.length; i < l; i++) { segment = path[i]; if (ptr[segment] === undefined) { ptr[segment] = typeof segment === 'number' ? [] : {}; } ptr = ptr[segment]; } if (ptr[prop] === value) { return false; } else { ptr[prop] = value; return true; } } /** * Find an array of values that correspond to the keys of an object. * * This is a ponyfill for `Object.values`, which is still experimental. */ export function objectValues(obj) { if (Object.values) { return Object.values(obj); } else { return Object.keys(obj).map((k) => obj[k]); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqZWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vYmplY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1GQUFtRjtBQUVuRjs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxLQUFLLENBQUMsR0FBUTtJQUM1QixJQUFJLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLElBQUksSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLEVBQUU7UUFDaEUsT0FBTyxHQUFHLENBQUM7S0FDWjtJQUVELElBQUksR0FBUSxDQUFDO0lBQ2IsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRS9DLElBQUksSUFBSSxLQUFLLGVBQWUsRUFBRTtRQUM1QixHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNqQixHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0tBQzVCO1NBQU0sSUFBSSxJQUFJLEtBQUssaUJBQWlCLEVBQUU7UUFDckMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDNUI7U0FBTSxJQUFJLElBQUksS0FBSyxnQkFBZ0IsRUFBRTtRQUNwQyxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ1QsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM5QyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ3pCLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDekI7U0FDRjtLQUNGO1NBQU07UUFDTCxJQUFJLEdBQUcsQ0FBQztRQUVS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SSxDQUFDLEtBQUssS0FBSyxFQUFFO1FBQ3ZCLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7U0FBTTtRQUNMLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7UUFDbEIsT0FBTyxJQUFJLENBQUM7S0FDYjtBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxHQUFRO0lBQ25DLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtRQUNqQixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDM0I7U0FBTTtRQUNMLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzVDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1tb2R1bGUtYm91bmRhcnktdHlwZXMsIHZhbGlkLWpzZG9jICovXG5cbi8qKlxuICogQ2xvbmVzIGEgdmFsdWUuIElmIHRoZSB2YWx1ZSBpcyBhbiBvYmplY3QsIGEgZGVlcGx5IG5lc3RlZCBjbG9uZSB3aWxsIGJlXG4gKiBjcmVhdGVkLlxuICpcbiAqIFRyYXZlcnNlcyBhbGwgb2JqZWN0IHByb3BlcnRpZXMgKGJ1dCBub3QgcHJvdG90eXBlIHByb3BlcnRpZXMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvbmUob2JqOiBhbnkpOiBhbnkge1xuICBpZiAob2JqID09PSB1bmRlZmluZWQgfHwgb2JqID09PSBudWxsIHx8IHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIGxldCBkdXA6IGFueTtcbiAgbGV0IHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcblxuICBpZiAodHlwZSA9PT0gJ1tvYmplY3QgRGF0ZV0nKSB7XG4gICAgZHVwID0gbmV3IERhdGUoKTtcbiAgICBkdXAuc2V0VGltZShvYmouZ2V0VGltZSgpKTtcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnW29iamVjdCBSZWdFeHBdJykge1xuICAgIGR1cCA9IG9iai5jb25zdHJ1Y3RvcihvYmopO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEFycmF5XScpIHtcbiAgICBkdXAgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gb2JqLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGkpKSB7XG4gICAgICAgIGR1cC5wdXNoKGNsb25lKG9ialtpXSkpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgdmFsO1xuXG4gICAgZHVwID0ge307XG4gICAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIHZhbCA9IG9ialtrZXldO1xuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICB2YWwgPSBjbG9uZSh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIGR1cFtrZXldID0gdmFsO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZHVwO1xufVxuXG4vKipcbiAqIEV4cG9zZSBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGZyb20gb25lIG9iamVjdCBvbiBhbm90aGVyLlxuICpcbiAqIE1ldGhvZHMgd2lsbCBiZSBjYWxsZWQgb24gYHNvdXJjZWAgYW5kIHdpbGwgbWFpbnRhaW4gYHNvdXJjZWAgYXMgdGhlIGNvbnRleHQuXG4gKlxuICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4cG9zZShkZXN0aW5hdGlvbjogYW55LCBzb3VyY2U6IGFueSk6IHZvaWQge1xuICBsZXQgcHJvcGVydGllczogc3RyaW5nW107XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMikge1xuICAgIHByb3BlcnRpZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICB9IGVsc2Uge1xuICAgIHByb3BlcnRpZXMgPSBPYmplY3Qua2V5cyhzb3VyY2UpO1xuICB9XG5cbiAgcHJvcGVydGllcy5mb3JFYWNoKChwKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBzb3VyY2VbcF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGRlc3RpbmF0aW9uW3BdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gc291cmNlW3BdLmFwcGx5KHNvdXJjZSwgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlc3RpbmF0aW9uW3BdID0gc291cmNlW3BdO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogRXh0ZW5kIGFuIG9iamVjdCB3aXRoIHRoZSBwcm9wZXJ0aWVzIG9mIG9uZSBvciBtb3JlIG90aGVyIG9iamVjdHMuXG4gKlxuICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZChkZXN0aW5hdGlvbjogYW55LCAuLi5zb3VyY2VzOiBhbnlbXSk6IGFueSB7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlKSA9PiB7XG4gICAgZm9yIChsZXQgcCBpbiBzb3VyY2UpIHtcbiAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkocCkpIHtcbiAgICAgICAgZGVzdGluYXRpb25bcF0gPSBzb3VyY2VbcF07XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGRlc3RpbmF0aW9uO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGFuIG9iamVjdCB0byBhbiBgQXJyYXlgIGlmIGl0J3Mgbm90IGFscmVhZHkuXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHsqfSBvYmpcbiAqIEByZXR1cm5zIHthbnlbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvQXJyYXkob2JqOiB1bmtub3duKTogYW55W10ge1xuICBpZiAoaXNOb25lKG9iaikpIHtcbiAgICByZXR1cm4gW107XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkob2JqKSA/IG9iaiA6IFtvYmpdO1xuICB9XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSB2YWx1ZSBpcyBhIG5vbi1udWxsIG9iamVjdFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7Kn0gb2JqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0KG9iajogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gb2JqICE9PSBudWxsICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGFuIG9iamVjdCBpcyBudWxsIG9yIHVuZGVmaW5lZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7Kn0gb2JqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTm9uZShvYmo6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIG9iaiA9PT0gdW5kZWZpbmVkIHx8IG9iaiA9PT0gbnVsbDtcbn1cblxuLyoqXG4gKiBNZXJnZXMgcHJvcGVydGllcyBmcm9tIG90aGVyIG9iamVjdHMgaW50byBhIGJhc2Ugb2JqZWN0LiBQcm9wZXJ0aWVzIHRoYXRcbiAqIHJlc29sdmUgdG8gYHVuZGVmaW5lZGAgd2lsbCBub3Qgb3ZlcndyaXRlIHByb3BlcnRpZXMgb24gdGhlIGJhc2Ugb2JqZWN0XG4gKiB0aGF0IGFscmVhZHkgZXhpc3QuXG4gKlxuICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlKG9iamVjdDogYW55LCAuLi5zb3VyY2VzOiBhbnlbXSk6IGFueSB7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlKSA9PiB7XG4gICAgT2JqZWN0LmtleXMoc291cmNlKS5mb3JFYWNoKChmaWVsZCkgPT4ge1xuICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgbGV0IHZhbHVlID0gc291cmNlW2ZpZWxkXTtcbiAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBvYmplY3RbZmllbGRdID0gY2xvbmUodmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gb2JqZWN0O1xufVxuXG4vKipcbiAqIE1lcmdlcyBwcm9wZXJ0aWVzIGZyb20gb3RoZXIgb2JqZWN0cyBpbnRvIGEgYmFzZSBvYmplY3QsIHRyYXZlcnNpbmcgYW5kXG4gKiBtZXJnaW5nIGFueSBvYmplY3RzIHRoYXQgYXJlIGVuY291bnRlcmVkLlxuICpcbiAqIFByb3BlcnRpZXMgdGhhdCByZXNvbHZlIHRvIGB1bmRlZmluZWRgIHdpbGwgbm90IG92ZXJ3cml0ZSBwcm9wZXJ0aWVzIG9uIHRoZVxuICogYmFzZSBvYmplY3QgdGhhdCBhbHJlYWR5IGV4aXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcE1lcmdlKG9iamVjdDogYW55LCAuLi5zb3VyY2VzOiBhbnlbXSk6IGFueSB7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlKSA9PiB7XG4gICAgT2JqZWN0LmtleXMoc291cmNlKS5mb3JFYWNoKChmaWVsZCkgPT4ge1xuICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgbGV0IGEgPSBvYmplY3RbZmllbGRdO1xuICAgICAgICBsZXQgYiA9IHNvdXJjZVtmaWVsZF07XG4gICAgICAgIGlmIChcbiAgICAgICAgICBpc09iamVjdChhKSAmJlxuICAgICAgICAgIGlzT2JqZWN0KGIpICYmXG4gICAgICAgICAgIUFycmF5LmlzQXJyYXkoYSkgJiZcbiAgICAgICAgICAhQXJyYXkuaXNBcnJheShiKVxuICAgICAgICApIHtcbiAgICAgICAgICBkZWVwTWVyZ2UoYSwgYik7XG4gICAgICAgIH0gZWxzZSBpZiAoYiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgb2JqZWN0W2ZpZWxkXSA9IGNsb25lKGIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gb2JqZWN0O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyBhIHZhbHVlIGZyb20gYSBuZXN0ZWQgcGF0aCBvbiBhbiBvYmplY3QuXG4gKlxuICogUmV0dXJucyBhbnkgZmFsc3kgdmFsdWUgZW5jb3VudGVyZWQgd2hpbGUgdHJhdmVyc2luZyB0aGUgcGF0aC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBHZXQob2JqOiBhbnksIHBhdGg6IHN0cmluZ1tdKTogYW55IHtcbiAgbGV0IGluZGV4ID0gLTE7XG4gIGxldCByZXN1bHQgPSBvYmo7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBwYXRoLmxlbmd0aCkge1xuICAgIHJlc3VsdCA9IHJlc3VsdFtwYXRoW2luZGV4XV07XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBTZXRzIGEgdmFsdWUgb24gYW4gb2JqZWN0IGF0IGEgbmVzdGVkIHBhdGguXG4gKlxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGNyZWF0ZSBvYmplY3RzIGFsb25nIHRoZSBwYXRoIGlmIG5lY2Vzc2FyeSB0byBhbGxvd1xuICogc2V0dGluZyBhIGRlZXBseSBuZXN0ZWQgdmFsdWUuXG4gKlxuICogUmV0dXJucyBgZmFsc2VgIG9ubHkgaWYgdGhlIGN1cnJlbnQgdmFsdWUgaXMgYWxyZWFkeSBzdHJpY3RseSBlcXVhbCB0byB0aGVcbiAqIHJlcXVlc3RlZCBgdmFsdWVgIGFyZ3VtZW50LiBPdGhlcndpc2UgcmV0dXJucyBgdHJ1ZWAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWVwU2V0KG9iajogYW55LCBwYXRoOiBzdHJpbmdbXSwgdmFsdWU6IGFueSk6IGJvb2xlYW4ge1xuICBsZXQgcHRyID0gb2JqO1xuICBsZXQgcHJvcCA9IHBhdGgucG9wKCkgYXMgc3RyaW5nO1xuICBsZXQgc2VnbWVudDtcbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBwYXRoLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIHNlZ21lbnQgPSBwYXRoW2ldO1xuICAgIGlmIChwdHJbc2VnbWVudF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgcHRyW3NlZ21lbnRdID0gdHlwZW9mIHNlZ21lbnQgPT09ICdudW1iZXInID8gW10gOiB7fTtcbiAgICB9XG4gICAgcHRyID0gcHRyW3NlZ21lbnRdO1xuICB9XG4gIGlmIChwdHJbcHJvcF0gPT09IHZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IGVsc2Uge1xuICAgIHB0cltwcm9wXSA9IHZhbHVlO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbi8qKlxuICogRmluZCBhbiBhcnJheSBvZiB2YWx1ZXMgdGhhdCBjb3JyZXNwb25kIHRvIHRoZSBrZXlzIG9mIGFuIG9iamVjdC5cbiAqXG4gKiBUaGlzIGlzIGEgcG9ueWZpbGwgZm9yIGBPYmplY3QudmFsdWVzYCwgd2hpY2ggaXMgc3RpbGwgZXhwZXJpbWVudGFsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0VmFsdWVzKG9iajogYW55KTogYW55W10ge1xuICBpZiAoT2JqZWN0LnZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKG9iaik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubWFwKChrKSA9PiBvYmpba10pO1xuICB9XG59XG4iXX0=