198 lines
25 KiB
Plaintext
198 lines
25 KiB
Plaintext
const { toString, hasOwnProperty } = Object.prototype;
|
|
const fnToStr = Function.prototype.toString;
|
|
const previousComparisons = new Map();
|
|
/**
|
|
* Performs a deep equality check on two JavaScript values, tolerating cycles.
|
|
*/
|
|
export function equal(a, b) {
|
|
try {
|
|
return check(a, b);
|
|
}
|
|
finally {
|
|
previousComparisons.clear();
|
|
}
|
|
}
|
|
// Allow default imports as well.
|
|
export default equal;
|
|
function check(a, b) {
|
|
// If the two values are strictly equal, our job is easy.
|
|
if (a === b) {
|
|
return true;
|
|
}
|
|
// Object.prototype.toString returns a representation of the runtime type of
|
|
// the given value that is considerably more precise than typeof.
|
|
const aTag = toString.call(a);
|
|
const bTag = toString.call(b);
|
|
// If the runtime types of a and b are different, they could maybe be equal
|
|
// under some interpretation of equality, but for simplicity and performance
|
|
// we just return false instead.
|
|
if (aTag !== bTag) {
|
|
return false;
|
|
}
|
|
switch (aTag) {
|
|
case '[object Array]':
|
|
// Arrays are a lot like other objects, but we can cheaply compare their
|
|
// lengths as a short-cut before comparing their elements.
|
|
if (a.length !== b.length)
|
|
return false;
|
|
// Fall through to object case...
|
|
case '[object Object]': {
|
|
if (previouslyCompared(a, b))
|
|
return true;
|
|
const aKeys = definedKeys(a);
|
|
const bKeys = definedKeys(b);
|
|
// If `a` and `b` have a different number of enumerable keys, they
|
|
// must be different.
|
|
const keyCount = aKeys.length;
|
|
if (keyCount !== bKeys.length)
|
|
return false;
|
|
// Now make sure they have the same keys.
|
|
for (let k = 0; k < keyCount; ++k) {
|
|
if (!hasOwnProperty.call(b, aKeys[k])) {
|
|
return false;
|
|
}
|
|
}
|
|
// Finally, check deep equality of all child properties.
|
|
for (let k = 0; k < keyCount; ++k) {
|
|
const key = aKeys[k];
|
|
if (!check(a[key], b[key])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
case '[object Error]':
|
|
return a.name === b.name && a.message === b.message;
|
|
case '[object Number]':
|
|
// Handle NaN, which is !== itself.
|
|
if (a !== a)
|
|
return b !== b;
|
|
// Fall through to shared +a === +b case...
|
|
case '[object Boolean]':
|
|
case '[object Date]':
|
|
return +a === +b;
|
|
case '[object RegExp]':
|
|
case '[object String]':
|
|
return a == `${b}`;
|
|
case '[object Map]':
|
|
case '[object Set]': {
|
|
if (a.size !== b.size)
|
|
return false;
|
|
if (previouslyCompared(a, b))
|
|
return true;
|
|
const aIterator = a.entries();
|
|
const isMap = aTag === '[object Map]';
|
|
while (true) {
|
|
const info = aIterator.next();
|
|
if (info.done)
|
|
break;
|
|
// If a instanceof Set, aValue === aKey.
|
|
const [aKey, aValue] = info.value;
|
|
// So this works the same way for both Set and Map.
|
|
if (!b.has(aKey)) {
|
|
return false;
|
|
}
|
|
// However, we care about deep equality of values only when dealing
|
|
// with Map structures.
|
|
if (isMap && !check(aValue, b.get(aKey))) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
case '[object Uint16Array]':
|
|
case '[object Uint8Array]': // Buffer, in Node.js.
|
|
case '[object Uint32Array]':
|
|
case '[object Int32Array]':
|
|
case '[object Int8Array]':
|
|
case '[object Int16Array]':
|
|
case '[object ArrayBuffer]':
|
|
// DataView doesn't need these conversions, but the equality check is
|
|
// otherwise the same.
|
|
a = new Uint8Array(a);
|
|
b = new Uint8Array(b);
|
|
// Fall through...
|
|
case '[object DataView]': {
|
|
let len = a.byteLength;
|
|
if (len === b.byteLength) {
|
|
while (len-- && a[len] === b[len]) {
|
|
// Keep looping as long as the bytes are equal.
|
|
}
|
|
}
|
|
return len === -1;
|
|
}
|
|
case '[object AsyncFunction]':
|
|
case '[object GeneratorFunction]':
|
|
case '[object AsyncGeneratorFunction]':
|
|
case '[object Function]': {
|
|
const aCode = fnToStr.call(a);
|
|
if (aCode !== fnToStr.call(b)) {
|
|
return false;
|
|
}
|
|
// We consider non-native functions equal if they have the same code
|
|
// (native functions require === because their code is censored).
|
|
// Note that this behavior is not entirely sound, since !== function
|
|
// objects with the same code can behave differently depending on
|
|
// their closure scope. However, any function can behave differently
|
|
// depending on the values of its input arguments (including this)
|
|
// and its calling context (including its closure scope), even
|
|
// though the function object is === to itself; and it is entirely
|
|
// possible for functions that are not === to behave exactly the
|
|
// same under all conceivable circumstances. Because none of these
|
|
// factors are statically decidable in JavaScript, JS function
|
|
// equality is not well-defined. This ambiguity allows us to
|
|
// consider the best possible heuristic among various imperfect
|
|
// options, and equating non-native functions that have the same
|
|
// code has enormous practical benefits, such as when comparing
|
|
// functions that are repeatedly passed as fresh function
|
|
// expressions within objects that are otherwise deeply equal. Since
|
|
// any function created from the same syntactic expression (in the
|
|
// same code location) will always stringify to the same code
|
|
// according to fnToStr.call, we can reasonably expect these
|
|
// repeatedly passed function expressions to have the same code, and
|
|
// thus behave "the same" (with all the caveats mentioned above),
|
|
// even though the runtime function objects are !== to one another.
|
|
return !endsWith(aCode, nativeCodeSuffix);
|
|
}
|
|
}
|
|
// Otherwise the values are not equal.
|
|
return false;
|
|
}
|
|
function definedKeys(obj) {
|
|
// Remember that the second argument to Array.prototype.filter will be
|
|
// used as `this` within the callback function.
|
|
return Object.keys(obj).filter(isDefinedKey, obj);
|
|
}
|
|
function isDefinedKey(key) {
|
|
return this[key] !== void 0;
|
|
}
|
|
const nativeCodeSuffix = "{ [native code] }";
|
|
function endsWith(full, suffix) {
|
|
const fromIndex = full.length - suffix.length;
|
|
return fromIndex >= 0 &&
|
|
full.indexOf(suffix, fromIndex) === fromIndex;
|
|
}
|
|
function previouslyCompared(a, b) {
|
|
// Though cyclic references can make an object graph appear infinite from the
|
|
// perspective of a depth-first traversal, the graph still contains a finite
|
|
// number of distinct object references. We use the previousComparisons cache
|
|
// to avoid comparing the same pair of object references more than once, which
|
|
// guarantees termination (even if we end up comparing every object in one
|
|
// graph to every object in the other graph, which is extremely unlikely),
|
|
// while still allowing weird isomorphic structures (like rings with different
|
|
// lengths) a chance to pass the equality test.
|
|
let bSet = previousComparisons.get(a);
|
|
if (bSet) {
|
|
// Return true here because we can be sure false will be returned somewhere
|
|
// else if the objects are not equivalent.
|
|
if (bSet.has(b))
|
|
return true;
|
|
}
|
|
else {
|
|
previousComparisons.set(a, bSet = new Set);
|
|
}
|
|
bSet.add(b);
|
|
return false;
|
|
}
|
|
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO0FBQ3RELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDO0FBQzVDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7QUFFM0Q7O0dBRUc7QUFDSCxNQUFNLFVBQVUsS0FBSyxDQUFDLENBQU0sRUFBRSxDQUFNO0lBQ2xDLElBQUk7UUFDRixPQUFPLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7S0FDcEI7WUFBUztRQUNSLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO0tBQzdCO0FBQ0gsQ0FBQztBQUVELGlDQUFpQztBQUNqQyxlQUFlLEtBQUssQ0FBQztBQUVyQixTQUFTLEtBQUssQ0FBQyxDQUFNLEVBQUUsQ0FBTTtJQUMzQix5REFBeUQ7SUFDekQsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQ1gsT0FBTyxJQUFJLENBQUM7S0FDYjtJQUVELDRFQUE0RTtJQUM1RSxpRUFBaUU7SUFDakUsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QixNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRTlCLDJFQUEyRTtJQUMzRSw0RUFBNEU7SUFDNUUsZ0NBQWdDO0lBQ2hDLElBQUksSUFBSSxLQUFLLElBQUksRUFBRTtRQUNqQixPQUFPLEtBQUssQ0FBQztLQUNkO0lBRUQsUUFBUSxJQUFJLEVBQUU7UUFDWixLQUFLLGdCQUFnQjtZQUNuQix3RUFBd0U7WUFDeEUsMERBQTBEO1lBQzFELElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsTUFB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LDRFQUE0RTtJQUM1RSw2RUFBNkU7SUFDN0UsOEVBQThFO0lBQzlFLDBFQUEwRTtJQUMxRSwwRUFBMEU7SUFDMUUsOEVBQThFO0lBQzlFLCtDQUErQztJQUMvQyxJQUFJLElBQUksR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsSUFBSSxJQUFJLEVBQUU7UUFDUiwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQztLQUM5QjtTQUFNO1FBQ0wsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQztLQUM1QztJQUNELElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDWixPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCB7IHRvU3RyaW5nLCBoYXNPd25Qcm9wZXJ0eSB9ID0gT2JqZWN0LnByb3RvdHlwZTtcbmNvbnN0IGZuVG9TdHIgPSBGdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmc7XG5jb25zdCBwcmV2aW91c0NvbXBhcmlzb25zID0gbmV3IE1hcDxvYmplY3QsIFNldDxvYmplY3Q+PigpO1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgZGVlcCBlcXVhbGl0eSBjaGVjayBvbiB0d28gSmF2YVNjcmlwdCB2YWx1ZXMsIHRvbGVyYXRpbmcgY3ljbGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXF1YWwoYTogYW55LCBiOiBhbnkpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gY2hlY2soYSwgYik7XG4gIH0gZmluYWxseSB7XG4gICAgcHJldmlvdXNDb21wYXJpc29ucy5jbGVhcigpO1xuICB9XG59XG5cbi8vIEFsbG93IGRlZmF1bHQgaW1wb3J0cyBhcyB3ZWxsLlxuZXhwb3J0IGRlZmF1bHQgZXF1YWw7XG5cbmZ1bmN0aW9uIGNoZWNrKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiB7XG4gIC8vIElmIHRoZSB0d28gdmFsdWVzIGFyZSBzdHJpY3RseSBlcXVhbCwgb3VyIGpvYiBpcyBlYXN5LlxuICBpZiAoYSA9PT0gYikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyByZXR1cm5zIGEgcmVwcmVzZW50YXRpb24gb2YgdGhlIHJ1bnRpbWUgdHlwZSBvZlxuICAvLyB0aGUgZ2l2ZW4gdmFsdWUgdGhhdCBpcyBjb25zaWRlcmFibHkgbW9yZSBwcmVjaXNlIHRoYW4gdHlwZW9mLlxuICBjb25zdCBhVGFnID0gdG9TdHJpbmcuY2FsbChhKTtcbiAgY29uc3QgYlRhZyA9IHRvU3RyaW5nLmNhbGwoYik7XG5cbiAgLy8gSWYgdGhlIHJ1bnRpbWUgdHlwZXMgb2YgYSBhbmQgYiBhcmUgZGlmZmVyZW50LCB0aGV5IGNvdWxkIG1heWJlIGJlIGVxdWFsXG4gIC8vIHVuZGVyIHNvbWUgaW50ZXJwcmV0YXRpb24gb2YgZXF1YWxpdHksIGJ1dCBmb3Igc2ltcGxpY2l0eSBhbmQgcGVyZm9ybWFuY2VcbiAgLy8gd2UganVzdCByZXR1cm4gZmFsc2UgaW5zdGVhZC5cbiAgaWYgKGFUYWcgIT09IGJUYWcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBzd2l0Y2ggKGFUYWcpIHtcbiAgICBjYXNlICdbb2JqZWN0IEFycmF5XSc6XG4gICAgICAvLyBBcnJheXMgYXJlIGEgbG90IGxpa2Ugb3RoZXIgb2JqZWN0cywgYnV0IHdlIGNhbiBjaGVhcGx5IGNvbXBhcmUgdGhlaXJcbiAgICAgIC8vIGxlbmd0aHMgYXMgYSBzaG9ydC1jdXQgYmVmb3JlIGNvbXBhcmluZyB0aGVpciBlbGVtZW50cy5cbiAgICAgIGlmIChhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgIC8vIEZhbGwgdGhyb3VnaCB0byBvYmplY3QgY2FzZS4uLlxuICAgIGNhc2UgJ1tvYmplY3QgT2JqZWN0XSc6IHtcbiAgICAgIGlmIChwcmV2aW91c2x5Q29tcGFyZWQoYSwgYikpIHJldHVybiB0cnVlO1xuXG4gICAgICBjb25zdCBhS2V5cyA9IGRlZmluZWRLZXlzKGEpO1xuICAgICAgY29uc3QgYktleXMgPSBkZWZpbmVkS2V5cyhiKTtcblxuICAgICAgLy8gSWYgYGFgIGFuZCBgYmAgaGF2ZSBhIGRpZmZlcmVudCBudW1iZXIgb2YgZW51bWVyYWJsZSBrZXlzLCB0aGV5XG4gICAgICAvLyBtdXN0IGJlIGRpZmZlcmVudC5cbiAgICAgIGNvbnN0IGtleUNvdW50ID0gYUtleXMubGVuZ3RoO1xuICAgICAgaWYgKGtleUNvdW50ICE9PSBiS2V5cy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgICAgLy8gTm93IG1ha2Ugc3VyZSB0aGV5IGhhdmUgdGhlIHNhbWUga2V5cy5cbiAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwga2V5Q291bnQ7ICsraykge1xuICAgICAgICBpZiAoIWhhc093blByb3BlcnR5LmNhbGwoYiwgYUtleXNba10pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEZpbmFsbHksIGNoZWNrIGRlZXAgZXF1YWxpdHkgb2YgYWxsIGNoaWxkIHByb3BlcnRpZXMuXG4gICAgICBmb3IgKGxldCBrID0gMDsgayA8IGtleUNvdW50OyArK2spIHtcbiAgICAgICAgY29uc3Qga2V5ID0gYUtleXNba107XG4gICAgICAgIGlmICghY2hlY2soYVtrZXldLCBiW2tleV0pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGNhc2UgJ1tvYmplY3QgRXJyb3JdJzpcbiAgICAgIHJldHVybiBhLm5hbWUgPT09IGIubmFtZSAmJiBhLm1lc3NhZ2UgPT09IGIubWVzc2FnZTtcblxuICAgIGNhc2UgJ1tvYmplY3QgTnVtYmVyXSc6XG4gICAgICAvLyBIYW5kbGUgTmFOLCB3aGljaCBpcyAhPT0gaXRzZWxmLlxuICAgICAgaWYgKGEgIT09IGEpIHJldHVybiBiICE9PSBiO1xuICAgICAgLy8gRmFsbCB0aHJvdWdoIHRvIHNoYXJlZCArYSA9PT0gK2IgY2FzZS4uLlxuICAgIGNhc2UgJ1tvYmplY3QgQm9vbGVhbl0nOlxuICAgIGNhc2UgJ1tvYmplY3QgRGF0ZV0nOlxuICAgICAgcmV0dXJuICthID09PSArYjtcblxuICAgIGNhc2UgJ1tvYmplY3QgUmVnRXhwXSc6XG4gICAgY2FzZSAnW29iamVjdCBTdHJpbmddJzpcbiAgICAgIHJldHVybiBhID09IGAke2J9YDtcblxuICAgIGNhc2UgJ1tvYmplY3QgTWFwXSc6XG4gICAgY2FzZSAnW29iamVjdCBTZXRdJzoge1xuICAgICAgaWYgKGEuc2l6ZSAhPT0gYi5zaXplKSByZXR1cm4gZmFsc2U7XG4gICAgICBpZiAocHJldmlvdXNseUNvbXBhcmVkKGEsIGIpKSByZXR1cm4gdHJ1ZTtcblxuICAgICAgY29uc3QgYUl0ZXJhdG9yID0gYS5lbnRyaWVzKCk7XG4gICAgICBjb25zdCBpc01hcCA9IGFUYWcgPT09ICdbb2JqZWN0IE1hcF0nO1xuXG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBjb25zdCBpbmZvID0gYUl0ZXJhdG9yLm5leHQoKTtcbiAgICAgICAgaWYgKGluZm8uZG9uZSkgYnJlYWs7XG5cbiAgICAgICAgLy8gSWYgYSBpbnN0YW5jZW9mIFNldCwgYVZhbHVlID09PSBhS2V5LlxuICAgICAgICBjb25zdCBbYUtleSwgYVZhbHVlXSA9IGluZm8udmFsdWU7XG5cbiAgICAgICAgLy8gU28gdGhpcyB3b3JrcyB0aGUgc2FtZSB3YXkgZm9yIGJvdGggU2V0IGFuZCBNYXAuXG4gICAgICAgIGlmICghYi5oYXMoYUtleSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIb3dldmVyLCB3ZSBjYXJlIGFib3V0IGRlZXAgZXF1YWxpdHkgb2YgdmFsdWVzIG9ubHkgd2hlbiBkZWFsaW5nXG4gICAgICAgIC8vIHdpdGggTWFwIHN0cnVjdHVyZXMuXG4gICAgICAgIGlmIChpc01hcCAmJiAhY2hlY2soYVZhbHVlLCBiLmdldChhS2V5KSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY2FzZSAnW29iamVjdCBVaW50MTZBcnJheV0nOlxuICAgIGNhc2UgJ1tvYmplY3QgVWludDhBcnJheV0nOiAvLyBCdWZmZXIsIGluIE5vZGUuanMuXG4gICAgY2FzZSAnW29iamVjdCBVaW50MzJBcnJheV0nOlxuICAgIGNhc2UgJ1tvYmplY3QgSW50MzJBcnJheV0nOlxuICAgIGNhc2UgJ1tvYmplY3QgSW50OEFycmF5XSc6XG4gICAgY2FzZSAnW29iamVjdCBJbnQxNkFycmF5XSc6XG4gICAgY2FzZSAnW29iamVjdCBBcnJheUJ1ZmZlcl0nOlxuICAgICAgLy8gRGF0YVZpZXcgZG9lc24ndCBuZWVkIHRoZXNlIGNvbnZlcnNpb25zLCBidXQgdGhlIGVxdWFsaXR5IGNoZWNrIGlzXG4gICAgICAvLyBvdGhlcndpc2UgdGhlIHNhbWUuXG4gICAgICBhID0gbmV3IFVpbnQ4QXJyYXkoYSk7XG4gICAgICBiID0gbmV3IFVpbnQ4QXJyYXkoYik7XG4gICAgICAvLyBGYWxsIHRocm91Z2guLi5cbiAgICBjYXNlICdbb2JqZWN0IERhdGFWaWV3XSc6IHtcbiAgICAgIGxldCBsZW4gPSBhLmJ5dGVMZW5ndGg7XG4gICAgICBpZiAobGVuID09PSBiLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgd2hpbGUgKGxlbi0tICYmIGFbbGVuXSA9PT0gYltsZW5dKSB7XG4gICAgICAgICAgLy8gS2VlcCBsb29waW5nIGFzIGxvbmcgYXMgdGhlIGJ5dGVzIGFyZSBlcXVhbC5cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGxlbiA9PT0gLTE7XG4gICAgfVxuXG4gICAgY2FzZSAnW29iamVjdCBBc3luY0Z1bmN0aW9uXSc6XG4gICAgY2FzZSAnW29iamVjdCBHZW5lcmF0b3JGdW5jdGlvbl0nOlxuICAgIGNhc2UgJ1tvYmplY3QgQXN5bmNHZW5lcmF0b3JGdW5jdGlvbl0nOlxuICAgIGNhc2UgJ1tvYmplY3QgRnVuY3Rpb25dJzoge1xuICAgICAgY29uc3QgYUNvZGUgPSBmblRvU3RyLmNhbGwoYSk7XG4gICAgICBpZiAoYUNvZGUgIT09IGZuVG9TdHIuY2FsbChiKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIC8vIFdlIGNvbnNpZGVyIG5vbi1uYXRpdmUgZnVuY3Rpb25zIGVxdWFsIGlmIHRoZXkgaGF2ZSB0aGUgc2FtZSBjb2RlXG4gICAgICAvLyAobmF0aXZlIGZ1bmN0aW9ucyByZXF1aXJlID09PSBiZWNhdXNlIHRoZWlyIGNvZGUgaXMgY2Vuc29yZWQpLlxuICAgICAgLy8gTm90ZSB0aGF0IHRoaXMgYmVoYXZpb3IgaXMgbm90IGVudGlyZWx5IHNvdW5kLCBzaW5jZSAhPT0gZnVuY3Rpb25cbiAgICAgIC8vIG9iamVjdHMgd2l0aCB0aGUgc2FtZSBjb2RlIGNhbiBiZWhhdmUgZGlmZmVyZW50bHkgZGVwZW5kaW5nIG9uXG4gICAgICAvLyB0aGVpciBjbG9zdXJlIHNjb3BlLiBIb3dldmVyLCBhbnkgZnVuY3Rpb24gY2FuIGJlaGF2ZSBkaWZmZXJlbnRseVxuICAgICAgLy8gZGVwZW5kaW5nIG9uIHRoZSB2YWx1ZXMgb2YgaXRzIGlucHV0IGFyZ3VtZW50cyAoaW5jbHVkaW5nIHRoaXMpXG4gICAgICAvLyBhbmQgaXRzIGNhbGxpbmcgY29udGV4dCAoaW5jbHVkaW5nIGl0cyBjbG9zdXJlIHNjb3BlKSwgZXZlblxuICAgICAgLy8gdGhvdWdoIHRoZSBmdW5jdGlvbiBvYmplY3QgaXMgPT09IHRvIGl0c2VsZjsgYW5kIGl0IGlzIGVudGlyZWx5XG4gICAgICAvLyBwb3NzaWJsZSBmb3IgZnVuY3Rpb25zIHRoYXQgYXJlIG5vdCA9PT0gdG8gYmVoYXZlIGV4YWN0bHkgdGhlXG4gICAgICAvLyBzYW1lIHVuZGVyIGFsbCBjb25jZWl2YWJsZSBjaXJjdW1zdGFuY2VzLiBCZWNhdXNlIG5vbmUgb2YgdGhlc2VcbiAgICAgIC8vIGZhY3RvcnMgYXJlIHN0YXRpY2FsbHkgZGVjaWRhYmxlIGluIEphdmFTY3JpcHQsIEpTIGZ1bmN0aW9uXG4gICAgICAvLyBlcXVhbGl0eSBpcyBub3Qgd2VsbC1kZWZpbmVkLiBUaGlzIGFtYmlndWl0eSBhbGxvd3MgdXMgdG9cbiAgICAgIC8vIGNvbnNpZGVyIHRoZSBiZXN0IHBvc3NpYmxlIGhldXJpc3RpYyBhbW9uZyB2YXJpb3VzIGltcGVyZmVjdFxuICAgICAgLy8gb3B0aW9ucywgYW5kIGVxdWF0aW5nIG5vbi1uYXRpdmUgZnVuY3Rpb25zIHRoYXQgaGF2ZSB0aGUgc2FtZVxuICAgICAgLy8gY29kZSBoYXMgZW5vcm1vdXMgcHJhY3RpY2FsIGJlbmVmaXRzLCBzdWNoIGFzIHdoZW4gY29tcGFyaW5nXG4gICAgICAvLyBmdW5jdGlvbnMgdGhhdCBhcmUgcmVwZWF0ZWRseSBwYXNzZWQgYXMgZnJlc2ggZnVuY3Rpb25cbiAgICAgIC8vIGV4cHJlc3Npb25zIHdpdGhpbiBvYmplY3RzIHRoYXQgYXJlIG90aGVyd2lzZSBkZWVwbHkgZXF1YWwuIFNpbmNlXG4gICAgICAvLyBhbnkgZnVuY3Rpb24gY3JlYXRlZCBmcm9tIHRoZSBzYW1lIHN5bnRhY3RpYyBleHByZXNzaW9uIChpbiB0aGVcbiAgICAgIC8vIHNhbWUgY29kZSBsb2NhdGlvbikgd2lsbCBhbHdheXMgc3RyaW5naWZ5IHRvIHRoZSBzYW1lIGNvZGVcbiAgICAgIC8vIGFjY29yZGluZyB0byBmblRvU3RyLmNhbGwsIHdlIGNhbiByZWFzb25hYmx5IGV4cGVjdCB0aGVzZVxuICAgICAgLy8gcmVwZWF0ZWRseSBwYXNzZWQgZnVuY3Rpb24gZXhwcmVzc2lvbnMgdG8gaGF2ZSB0aGUgc2FtZSBjb2RlLCBhbmRcbiAgICAgIC8vIHRodXMgYmVoYXZlIFwidGhlIHNhbWVcIiAod2l0aCBhbGwgdGhlIGNhdmVhdHMgbWVudGlvbmVkIGFib3ZlKSxcbiAgICAgIC8vIGV2ZW4gdGhvdWdoIHRoZSBydW50aW1lIGZ1bmN0aW9uIG9iamVjdHMgYXJlICE9PSB0byBvbmUgYW5vdGhlci5cbiAgICAgIHJldHVybiAhZW5kc1dpdGgoYUNvZGUsIG5hdGl2ZUNvZGVTdWZmaXgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIE90aGVyd2lzZSB0aGUgdmFsdWVzIGFyZSBub3QgZXF1YWwuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZGVmaW5lZEtleXM8VE9iamVjdCBleHRlbmRzIG9iamVjdD4ob2JqOiBUT2JqZWN0KSB7XG4gIC8vIFJlbWVtYmVyIHRoYXQgdGhlIHNlY29uZCBhcmd1bWVudCB0byBBcnJheS5wcm90b3R5cGUuZmlsdGVyIHdpbGwgYmVcbiAgLy8gdXNlZCBhcyBgdGhpc2Agd2l0aGluIHRoZSBjYWxsYmFjayBmdW5jdGlvbi5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikuZmlsdGVyKGlzRGVmaW5lZEtleSwgb2JqKTtcbn1cbmZ1bmN0aW9uIGlzRGVmaW5lZEtleTxUT2JqZWN0IGV4dGVuZHMgb2JqZWN0PihcbiAgdGhpczogVE9iamVjdCxcbiAga2V5OiBrZXlvZiBUT2JqZWN0LFxuKSB7XG4gIHJldHVybiB0aGlzW2tleV0gIT09IHZvaWQgMDtcbn1cblxuY29uc3QgbmF0aXZlQ29kZVN1ZmZpeCA9IFwieyBbbmF0aXZlIGNvZGVdIH1cIjtcblxuZnVuY3Rpb24gZW5kc1dpdGgoZnVsbDogc3RyaW5nLCBzdWZmaXg6IHN0cmluZykge1xuICBjb25zdCBmcm9tSW5kZXggPSBmdWxsLmxlbmd0aCAtIHN1ZmZpeC5sZW5ndGg7XG4gIHJldHVybiBmcm9tSW5kZXggPj0gMCAmJlxuICAgIGZ1bGwuaW5kZXhPZihzdWZmaXgsIGZyb21JbmRleCkgPT09IGZyb21JbmRleDtcbn1cblxuZnVuY3Rpb24gcHJldmlvdXNseUNvbXBhcmVkKGE6IG9iamVjdCwgYjogb2JqZWN0KTogYm9vbGVhbiB7XG4gIC8vIFRob3VnaCBjeWNsaWMgcmVmZXJlbmNlcyBjYW4gbWFrZSBhbiBvYmplY3QgZ3JhcGggYXBwZWFyIGluZmluaXRlIGZyb20gdGhlXG4gIC8vIHBlcnNwZWN0aXZlIG9mIGEgZGVwdGgtZmlyc3QgdHJhdmVyc2FsLCB0aGUgZ3JhcGggc3RpbGwgY29udGFpbnMgYSBmaW5pdGVcbiAgLy8gbnVtYmVyIG9mIGRpc3RpbmN0IG9iamVjdCByZWZlcmVuY2VzLiBXZSB1c2UgdGhlIHByZXZpb3VzQ29tcGFyaXNvbnMgY2FjaGVcbiAgLy8gdG8gYXZvaWQgY29tcGFyaW5nIHRoZSBzYW1lIHBhaXIgb2Ygb2JqZWN0IHJlZmVyZW5jZXMgbW9yZSB0aGFuIG9uY2UsIHdoaWNoXG4gIC8vIGd1YXJhbnRlZXMgdGVybWluYXRpb24gKGV2ZW4gaWYgd2UgZW5kIHVwIGNvbXBhcmluZyBldmVyeSBvYmplY3QgaW4gb25lXG4gIC8vIGdyYXBoIHRvIGV2ZXJ5IG9iamVjdCBpbiB0aGUgb3RoZXIgZ3JhcGgsIHdoaWNoIGlzIGV4dHJlbWVseSB1bmxpa2VseSksXG4gIC8vIHdoaWxlIHN0aWxsIGFsbG93aW5nIHdlaXJkIGlzb21vcnBoaWMgc3RydWN0dXJlcyAobGlrZSByaW5ncyB3aXRoIGRpZmZlcmVudFxuICAvLyBsZW5ndGhzKSBhIGNoYW5jZSB0byBwYXNzIHRoZSBlcXVhbGl0eSB0ZXN0LlxuICBsZXQgYlNldCA9IHByZXZpb3VzQ29tcGFyaXNvbnMuZ2V0KGEpO1xuICBpZiAoYlNldCkge1xuICAgIC8vIFJldHVybiB0cnVlIGhlcmUgYmVjYXVzZSB3ZSBjYW4gYmUgc3VyZSBmYWxzZSB3aWxsIGJlIHJldHVybmVkIHNvbWV3aGVyZVxuICAgIC8vIGVsc2UgaWYgdGhlIG9iamVjdHMgYXJlIG5vdCBlcXVpdmFsZW50LlxuICAgIGlmIChiU2V0LmhhcyhiKSkgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgcHJldmlvdXNDb21wYXJpc29ucy5zZXQoYSwgYlNldCA9IG5ldyBTZXQpO1xuICB9XG4gIGJTZXQuYWRkKGIpO1xuICByZXR1cm4gZmFsc2U7XG59XG4iXSwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdfQ== |