made with requirebin
Created
May 31, 2017 13:52
-
-
Save caesarsol/fd993b488257f419093782ac741b18b9 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const mobx = require('mobx') | |
const a = mobx.observable({ | |
b: 1, | |
c: [], | |
}) | |
const dom = [ | |
document.createElement('div'), | |
document.createElement('div'), | |
document.createElement('div'), | |
document.createElement('div'), | |
] | |
dom.forEach((e, i) => { | |
e.style.background = ['steelblue', 'tomato'][i % 2] | |
document.body.appendChild(e) | |
}) | |
const start = Date.now() | |
document.body.addEventListener('click', () => { | |
a.b++ | |
a.c.push(Date.now() - start) | |
}) | |
// 1 | |
let oldValue = null | |
requestAnimationFrame(function loop() { | |
let b = a.b | |
dom[0].innerHTML = b | |
if (b !== oldValue) { | |
console.timeEnd() | |
} | |
oldValue = b | |
dom[2].innerHTML = a.c | |
requestAnimationFrame(loop) | |
}) | |
// 2 | |
mobx.autorun(() => { | |
dom[1].innerHTML += a.b + '<br>' | |
console.time() | |
}) | |
mobx.autorun(() => { | |
dom[3].innerHTML = a.c.join('<br>') | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setTimeout(function(){ | |
;require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"mobx":[function(require,module,exports){ | |
(function (global){ | |
"use strict"; | |
var __extends = (this && this.__extends) || function (d, b) { | |
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; | |
function __() { this.constructor = d; } | |
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | |
}; | |
registerGlobals(); | |
exports.extras = { | |
allowStateChanges: allowStateChanges, | |
deepEqual: deepEqual, | |
getAtom: getAtom, | |
getDebugName: getDebugName, | |
getDependencyTree: getDependencyTree, | |
getAdministration: getAdministration, | |
getGlobalState: getGlobalState, | |
getObserverTree: getObserverTree, | |
isComputingDerivation: isComputingDerivation, | |
isSpyEnabled: isSpyEnabled, | |
onReactionError: onReactionError, | |
resetGlobalState: resetGlobalState, | |
shareGlobalState: shareGlobalState, | |
spyReport: spyReport, | |
spyReportEnd: spyReportEnd, | |
spyReportStart: spyReportStart, | |
setReactionScheduler: setReactionScheduler | |
}; | |
if (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === "object") { | |
__MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx(module.exports); | |
} | |
var actionFieldDecorator = createClassPropertyDecorator(function (target, key, value, args, originalDescriptor) { | |
var actionName = (args && args.length === 1) ? args[0] : (value.name || key || "<unnamed action>"); | |
var wrappedAction = action(actionName, value); | |
addHiddenProp(target, key, wrappedAction); | |
}, function (key) { | |
return this[key]; | |
}, function () { | |
invariant(false, getMessage("m001")); | |
}, false, true); | |
var boundActionDecorator = createClassPropertyDecorator(function (target, key, value) { | |
defineBoundAction(target, key, value); | |
}, function (key) { | |
return this[key]; | |
}, function () { | |
invariant(false, getMessage("m001")); | |
}, false, false); | |
var action = function action(arg1, arg2, arg3, arg4) { | |
if (arguments.length === 1 && typeof arg1 === "function") | |
return createAction(arg1.name || "<unnamed action>", arg1); | |
if (arguments.length === 2 && typeof arg2 === "function") | |
return createAction(arg1, arg2); | |
if (arguments.length === 1 && typeof arg1 === "string") | |
return namedActionDecorator(arg1); | |
return namedActionDecorator(arg2).apply(null, arguments); | |
}; | |
exports.action = action; | |
action.bound = function boundAction(arg1, arg2, arg3) { | |
if (typeof arg1 === "function") { | |
var action_1 = createAction("<not yet bound action>", arg1); | |
action_1.autoBind = true; | |
return action_1; | |
} | |
return boundActionDecorator.apply(null, arguments); | |
}; | |
function namedActionDecorator(name) { | |
return function (target, prop, descriptor) { | |
if (descriptor && typeof descriptor.value === "function") { | |
descriptor.value = createAction(name, descriptor.value); | |
descriptor.enumerable = false; | |
descriptor.configurable = true; | |
return descriptor; | |
} | |
return actionFieldDecorator(name).apply(this, arguments); | |
}; | |
} | |
function runInAction(arg1, arg2, arg3) { | |
var actionName = typeof arg1 === "string" ? arg1 : arg1.name || "<unnamed action>"; | |
var fn = typeof arg1 === "function" ? arg1 : arg2; | |
var scope = typeof arg1 === "function" ? arg2 : arg3; | |
invariant(typeof fn === "function", getMessage("m002")); | |
invariant(fn.length === 0, getMessage("m003")); | |
invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'"); | |
return executeAction(actionName, fn, scope, undefined); | |
} | |
exports.runInAction = runInAction; | |
function isAction(thing) { | |
return typeof thing === "function" && thing.isMobxAction === true; | |
} | |
exports.isAction = isAction; | |
function defineBoundAction(target, propertyName, fn) { | |
var res = function () { | |
return executeAction(propertyName, fn, target, arguments); | |
}; | |
res.isMobxAction = true; | |
addHiddenProp(target, propertyName, res); | |
} | |
function autorun(arg1, arg2, arg3) { | |
var name, view, scope; | |
if (typeof arg1 === "string") { | |
name = arg1; | |
view = arg2; | |
scope = arg3; | |
} | |
else { | |
name = arg1.name || ("Autorun@" + getNextId()); | |
view = arg1; | |
scope = arg2; | |
} | |
invariant(typeof view === "function", getMessage("m004")); | |
invariant(isAction(view) === false, getMessage("m005")); | |
if (scope) | |
view = view.bind(scope); | |
var reaction = new Reaction(name, function () { | |
this.track(reactionRunner); | |
}); | |
function reactionRunner() { | |
view(reaction); | |
} | |
reaction.schedule(); | |
return reaction.getDisposer(); | |
} | |
exports.autorun = autorun; | |
function when(arg1, arg2, arg3, arg4) { | |
var name, predicate, effect, scope; | |
if (typeof arg1 === "string") { | |
name = arg1; | |
predicate = arg2; | |
effect = arg3; | |
scope = arg4; | |
} | |
else { | |
name = ("When@" + getNextId()); | |
predicate = arg1; | |
effect = arg2; | |
scope = arg3; | |
} | |
var disposer = autorun(name, function (r) { | |
if (predicate.call(scope)) { | |
r.dispose(); | |
var prevUntracked = untrackedStart(); | |
effect.call(scope); | |
untrackedEnd(prevUntracked); | |
} | |
}); | |
return disposer; | |
} | |
exports.when = when; | |
function autorunAsync(arg1, arg2, arg3, arg4) { | |
var name, func, delay, scope; | |
if (typeof arg1 === "string") { | |
name = arg1; | |
func = arg2; | |
delay = arg3; | |
scope = arg4; | |
} | |
else { | |
name = arg1.name || ("AutorunAsync@" + getNextId()); | |
func = arg1; | |
delay = arg2; | |
scope = arg3; | |
} | |
invariant(isAction(func) === false, getMessage("m006")); | |
if (delay === void 0) | |
delay = 1; | |
if (scope) | |
func = func.bind(scope); | |
var isScheduled = false; | |
var r = new Reaction(name, function () { | |
if (!isScheduled) { | |
isScheduled = true; | |
setTimeout(function () { | |
isScheduled = false; | |
if (!r.isDisposed) | |
r.track(reactionRunner); | |
}, delay); | |
} | |
}); | |
function reactionRunner() { func(r); } | |
r.schedule(); | |
return r.getDisposer(); | |
} | |
exports.autorunAsync = autorunAsync; | |
function reaction(expression, effect, arg3) { | |
if (arguments.length > 3) { | |
fail(getMessage("m007")); | |
} | |
if (isModifierDescriptor(expression)) { | |
fail(getMessage("m008")); | |
} | |
var opts; | |
if (typeof arg3 === "object") { | |
opts = arg3; | |
} | |
else { | |
opts = {}; | |
} | |
opts.name = opts.name || expression.name || effect.name || ("Reaction@" + getNextId()); | |
opts.fireImmediately = arg3 === true || opts.fireImmediately === true; | |
opts.delay = opts.delay || 0; | |
opts.compareStructural = opts.compareStructural || opts.struct || false; | |
effect = action(opts.name, opts.context ? effect.bind(opts.context) : effect); | |
if (opts.context) { | |
expression = expression.bind(opts.context); | |
} | |
var firstTime = true; | |
var isScheduled = false; | |
var nextValue; | |
var r = new Reaction(opts.name, function () { | |
if (opts.delay < 1) { | |
reactionRunner(); | |
} | |
else if (!isScheduled) { | |
isScheduled = true; | |
setTimeout(function () { | |
isScheduled = false; | |
reactionRunner(); | |
}, opts.delay); | |
} | |
}); | |
function reactionRunner() { | |
if (r.isDisposed) | |
return; | |
var changed = false; | |
r.track(function () { | |
var v = expression(r); | |
changed = valueDidChange(opts.compareStructural, nextValue, v); | |
nextValue = v; | |
}); | |
if (firstTime && opts.fireImmediately) | |
effect(nextValue, r); | |
if (!firstTime && changed === true) | |
effect(nextValue, r); | |
if (firstTime) | |
firstTime = false; | |
} | |
r.schedule(); | |
return r.getDisposer(); | |
} | |
exports.reaction = reaction; | |
function createComputedDecorator(compareStructural) { | |
return createClassPropertyDecorator(function (target, name, _, __, originalDescriptor) { | |
invariant(typeof originalDescriptor !== "undefined", getMessage("m009")); | |
invariant(typeof originalDescriptor.get === "function", getMessage("m010")); | |
var adm = asObservableObject(target, ""); | |
defineComputedProperty(adm, name, originalDescriptor.get, originalDescriptor.set, compareStructural, false); | |
}, function (name) { | |
var observable = this.$mobx.values[name]; | |
if (observable === undefined) | |
return undefined; | |
return observable.get(); | |
}, function (name, value) { | |
this.$mobx.values[name].set(value); | |
}, false, false); | |
} | |
var computedDecorator = createComputedDecorator(false); | |
var computedStructDecorator = createComputedDecorator(true); | |
var computed = (function computed(arg1, arg2, arg3) { | |
if (typeof arg2 === "string") { | |
return computedDecorator.apply(null, arguments); | |
} | |
invariant(typeof arg1 === "function", getMessage("m011")); | |
invariant(arguments.length < 3, getMessage("m012")); | |
var opts = typeof arg2 === "object" ? arg2 : {}; | |
opts.setter = typeof arg2 === "function" ? arg2 : opts.setter; | |
return new ComputedValue(arg1, opts.context, opts.compareStructural || opts.struct || false, opts.name || arg1.name || "", opts.setter); | |
}); | |
exports.computed = computed; | |
computed.struct = computedStructDecorator; | |
function createTransformer(transformer, onCleanup) { | |
invariant(typeof transformer === "function" && transformer.length < 2, "createTransformer expects a function that accepts one argument"); | |
var objectCache = {}; | |
var resetId = globalState.resetId; | |
var Transformer = (function (_super) { | |
__extends(Transformer, _super); | |
function Transformer(sourceIdentifier, sourceObject) { | |
var _this = _super.call(this, function () { return transformer(sourceObject); }, undefined, false, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined) || this; | |
_this.sourceIdentifier = sourceIdentifier; | |
_this.sourceObject = sourceObject; | |
return _this; | |
} | |
Transformer.prototype.onBecomeUnobserved = function () { | |
var lastValue = this.value; | |
_super.prototype.onBecomeUnobserved.call(this); | |
delete objectCache[this.sourceIdentifier]; | |
if (onCleanup) | |
onCleanup(lastValue, this.sourceObject); | |
}; | |
return Transformer; | |
}(ComputedValue)); | |
return function (object) { | |
if (resetId !== globalState.resetId) { | |
objectCache = {}; | |
resetId = globalState.resetId; | |
} | |
var identifier = getMemoizationId(object); | |
var reactiveTransformer = objectCache[identifier]; | |
if (reactiveTransformer) | |
return reactiveTransformer.get(); | |
reactiveTransformer = objectCache[identifier] = new Transformer(identifier, object); | |
return reactiveTransformer.get(); | |
}; | |
} | |
exports.createTransformer = createTransformer; | |
function getMemoizationId(object) { | |
if (object === null || typeof object !== "object") | |
throw new Error("[mobx] transform expected some kind of object, got: " + object); | |
var tid = object.$transformId; | |
if (tid === undefined) { | |
tid = getNextId(); | |
addHiddenProp(object, "$transformId", tid); | |
} | |
return tid; | |
} | |
function expr(expr, scope) { | |
if (!isComputingDerivation()) | |
console.warn(getMessage("m013")); | |
return computed(expr, { context: scope }).get(); | |
} | |
exports.expr = expr; | |
function extendObservable(target) { | |
var properties = []; | |
for (var _i = 1; _i < arguments.length; _i++) { | |
properties[_i - 1] = arguments[_i]; | |
} | |
return extendObservableHelper(target, deepEnhancer, properties); | |
} | |
exports.extendObservable = extendObservable; | |
function extendShallowObservable(target) { | |
var properties = []; | |
for (var _i = 1; _i < arguments.length; _i++) { | |
properties[_i - 1] = arguments[_i]; | |
} | |
return extendObservableHelper(target, referenceEnhancer, properties); | |
} | |
exports.extendShallowObservable = extendShallowObservable; | |
function extendObservableHelper(target, defaultEnhancer, properties) { | |
invariant(arguments.length >= 2, getMessage("m014")); | |
invariant(typeof target === "object", getMessage("m015")); | |
invariant(!(isObservableMap(target)), getMessage("m016")); | |
properties.forEach(function (propSet) { | |
invariant(typeof propSet === "object", getMessage("m017")); | |
invariant(!isObservable(propSet), getMessage("m018")); | |
}); | |
var adm = asObservableObject(target); | |
var definedProps = {}; | |
for (var i = properties.length - 1; i >= 0; i--) { | |
var propSet = properties[i]; | |
for (var key in propSet) | |
if (definedProps[key] !== true && hasOwnProperty(propSet, key)) { | |
definedProps[key] = true; | |
if (target === propSet && !isPropertyConfigurable(target, key)) | |
continue; | |
var descriptor = Object.getOwnPropertyDescriptor(propSet, key); | |
defineObservablePropertyFromDescriptor(adm, key, descriptor, defaultEnhancer); | |
} | |
} | |
return target; | |
} | |
function getDependencyTree(thing, property) { | |
return nodeToDependencyTree(getAtom(thing, property)); | |
} | |
function nodeToDependencyTree(node) { | |
var result = { | |
name: node.name | |
}; | |
if (node.observing && node.observing.length > 0) | |
result.dependencies = unique(node.observing).map(nodeToDependencyTree); | |
return result; | |
} | |
function getObserverTree(thing, property) { | |
return nodeToObserverTree(getAtom(thing, property)); | |
} | |
function nodeToObserverTree(node) { | |
var result = { | |
name: node.name | |
}; | |
if (hasObservers(node)) | |
result.observers = getObservers(node).map(nodeToObserverTree); | |
return result; | |
} | |
function intercept(thing, propOrHandler, handler) { | |
if (typeof handler === "function") | |
return interceptProperty(thing, propOrHandler, handler); | |
else | |
return interceptInterceptable(thing, propOrHandler); | |
} | |
exports.intercept = intercept; | |
function interceptInterceptable(thing, handler) { | |
return getAdministration(thing).intercept(handler); | |
} | |
function interceptProperty(thing, property, handler) { | |
return getAdministration(thing, property).intercept(handler); | |
} | |
function isComputed(value, property) { | |
if (value === null || value === undefined) | |
return false; | |
if (property !== undefined) { | |
if (isObservableObject(value) === false) | |
return false; | |
var atom = getAtom(value, property); | |
return isComputedValue(atom); | |
} | |
return isComputedValue(value); | |
} | |
exports.isComputed = isComputed; | |
function isObservable(value, property) { | |
if (value === null || value === undefined) | |
return false; | |
if (property !== undefined) { | |
if (isObservableArray(value) || isObservableMap(value)) | |
throw new Error(getMessage("m019")); | |
else if (isObservableObject(value)) { | |
var o = value.$mobx; | |
return o.values && !!o.values[property]; | |
} | |
return false; | |
} | |
return isObservableObject(value) || !!value.$mobx || isAtom(value) || isReaction(value) || isComputedValue(value); | |
} | |
exports.isObservable = isObservable; | |
var deepDecorator = createDecoratorForEnhancer(deepEnhancer); | |
var shallowDecorator = createDecoratorForEnhancer(shallowEnhancer); | |
var refDecorator = createDecoratorForEnhancer(referenceEnhancer); | |
var deepStructDecorator = createDecoratorForEnhancer(deepStructEnhancer); | |
var refStructDecorator = createDecoratorForEnhancer(refStructEnhancer); | |
function createObservable(v) { | |
if (v === void 0) { v = undefined; } | |
if (typeof arguments[1] === "string") | |
return deepDecorator.apply(null, arguments); | |
invariant(arguments.length <= 1, getMessage("m021")); | |
invariant(!isModifierDescriptor(v), getMessage("m020")); | |
if (isObservable(v)) | |
return v; | |
var res = deepEnhancer(v, undefined, undefined); | |
if (res !== v) | |
return res; | |
return observable.box(v); | |
} | |
var IObservableFactories = (function () { | |
function IObservableFactories() { | |
} | |
IObservableFactories.prototype.box = function (value, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("box"); | |
return new ObservableValue(value, deepEnhancer, name); | |
}; | |
IObservableFactories.prototype.shallowBox = function (value, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("shallowBox"); | |
return new ObservableValue(value, referenceEnhancer, name); | |
}; | |
IObservableFactories.prototype.array = function (initialValues, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("array"); | |
return new ObservableArray(initialValues, deepEnhancer, name); | |
}; | |
IObservableFactories.prototype.shallowArray = function (initialValues, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("shallowArray"); | |
return new ObservableArray(initialValues, referenceEnhancer, name); | |
}; | |
IObservableFactories.prototype.map = function (initialValues, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("map"); | |
return new ObservableMap(initialValues, deepEnhancer, name); | |
}; | |
IObservableFactories.prototype.shallowMap = function (initialValues, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("shallowMap"); | |
return new ObservableMap(initialValues, referenceEnhancer, name); | |
}; | |
IObservableFactories.prototype.object = function (props, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("object"); | |
var res = {}; | |
asObservableObject(res, name); | |
extendObservable(res, props); | |
return res; | |
}; | |
IObservableFactories.prototype.shallowObject = function (props, name) { | |
if (arguments.length > 2) | |
incorrectlyUsedAsDecorator("shallowObject"); | |
var res = {}; | |
asObservableObject(res, name); | |
extendShallowObservable(res, props); | |
return res; | |
}; | |
IObservableFactories.prototype.ref = function () { | |
if (arguments.length < 2) { | |
return createModifierDescriptor(referenceEnhancer, arguments[0]); | |
} | |
else { | |
return refDecorator.apply(null, arguments); | |
} | |
}; | |
IObservableFactories.prototype.shallow = function () { | |
if (arguments.length < 2) { | |
return createModifierDescriptor(shallowEnhancer, arguments[0]); | |
} | |
else { | |
return shallowDecorator.apply(null, arguments); | |
} | |
}; | |
IObservableFactories.prototype.deep = function () { | |
if (arguments.length < 2) { | |
return createModifierDescriptor(deepEnhancer, arguments[0]); | |
} | |
else { | |
return deepDecorator.apply(null, arguments); | |
} | |
}; | |
IObservableFactories.prototype.struct = function () { | |
if (arguments.length < 2) { | |
return createModifierDescriptor(deepStructEnhancer, arguments[0]); | |
} | |
else { | |
return deepStructDecorator.apply(null, arguments); | |
} | |
}; | |
return IObservableFactories; | |
}()); | |
exports.IObservableFactories = IObservableFactories; | |
var observable = createObservable; | |
exports.observable = observable; | |
Object.keys(IObservableFactories.prototype).forEach(function (key) { return observable[key] = IObservableFactories.prototype[key]; }); | |
observable.deep.struct = observable.struct; | |
observable.ref.struct = function () { | |
if (arguments.length < 2) { | |
return createModifierDescriptor(refStructEnhancer, arguments[0]); | |
} | |
else { | |
return refStructDecorator.apply(null, arguments); | |
} | |
}; | |
function incorrectlyUsedAsDecorator(methodName) { | |
fail("Expected one or two arguments to observable." + methodName + ". Did you accidentally try to use observable." + methodName + " as decorator?"); | |
} | |
function createDecoratorForEnhancer(enhancer) { | |
invariant(!!enhancer, ":("); | |
return createClassPropertyDecorator(function (target, name, baseValue, _, baseDescriptor) { | |
assertPropertyConfigurable(target, name); | |
invariant(!baseDescriptor || !baseDescriptor.get, getMessage("m022")); | |
var adm = asObservableObject(target, undefined); | |
defineObservableProperty(adm, name, baseValue, enhancer); | |
}, function (name) { | |
var observable = this.$mobx.values[name]; | |
if (observable === undefined) | |
return undefined; | |
return observable.get(); | |
}, function (name, value) { | |
setPropertyValue(this, name, value); | |
}, true, false); | |
} | |
function observe(thing, propOrCb, cbOrFire, fireImmediately) { | |
if (typeof cbOrFire === "function") | |
return observeObservableProperty(thing, propOrCb, cbOrFire, fireImmediately); | |
else | |
return observeObservable(thing, propOrCb, cbOrFire); | |
} | |
exports.observe = observe; | |
function observeObservable(thing, listener, fireImmediately) { | |
return getAdministration(thing).observe(listener, fireImmediately); | |
} | |
function observeObservableProperty(thing, property, listener, fireImmediately) { | |
return getAdministration(thing, property).observe(listener, fireImmediately); | |
} | |
function toJS(source, detectCycles, __alreadySeen) { | |
if (detectCycles === void 0) { detectCycles = true; } | |
if (__alreadySeen === void 0) { __alreadySeen = []; } | |
function cache(value) { | |
if (detectCycles) | |
__alreadySeen.push([source, value]); | |
return value; | |
} | |
if (isObservable(source)) { | |
if (detectCycles && __alreadySeen === null) | |
__alreadySeen = []; | |
if (detectCycles && source !== null && typeof source === "object") { | |
for (var i = 0, l = __alreadySeen.length; i < l; i++) | |
if (__alreadySeen[i][0] === source) | |
return __alreadySeen[i][1]; | |
} | |
if (isObservableArray(source)) { | |
var res = cache([]); | |
var toAdd = source.map(function (value) { return toJS(value, detectCycles, __alreadySeen); }); | |
res.length = toAdd.length; | |
for (var i = 0, l = toAdd.length; i < l; i++) | |
res[i] = toAdd[i]; | |
return res; | |
} | |
if (isObservableObject(source)) { | |
var res = cache({}); | |
for (var key in source) | |
res[key] = toJS(source[key], detectCycles, __alreadySeen); | |
return res; | |
} | |
if (isObservableMap(source)) { | |
var res_1 = cache({}); | |
source.forEach(function (value, key) { return res_1[key] = toJS(value, detectCycles, __alreadySeen); }); | |
return res_1; | |
} | |
if (isObservableValue(source)) | |
return toJS(source.get(), detectCycles, __alreadySeen); | |
} | |
return source; | |
} | |
exports.toJS = toJS; | |
function transaction(action, thisArg) { | |
if (thisArg === void 0) { thisArg = undefined; } | |
deprecated(getMessage("m023")); | |
return runInTransaction.apply(undefined, arguments); | |
} | |
exports.transaction = transaction; | |
function runInTransaction(action, thisArg) { | |
if (thisArg === void 0) { thisArg = undefined; } | |
return executeAction("", action); | |
} | |
function log(msg) { | |
console.log(msg); | |
return msg; | |
} | |
function whyRun(thing, prop) { | |
switch (arguments.length) { | |
case 0: | |
thing = globalState.trackingDerivation; | |
if (!thing) | |
return log(getMessage("m024")); | |
break; | |
case 2: | |
thing = getAtom(thing, prop); | |
break; | |
} | |
thing = getAtom(thing); | |
if (isComputedValue(thing)) | |
return log(thing.whyRun()); | |
else if (isReaction(thing)) | |
return log(thing.whyRun()); | |
return fail(getMessage("m025")); | |
} | |
exports.whyRun = whyRun; | |
function createAction(actionName, fn) { | |
invariant(typeof fn === "function", getMessage("m026")); | |
invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'"); | |
var res = function () { | |
return executeAction(actionName, fn, this, arguments); | |
}; | |
res.originalFn = fn; | |
res.isMobxAction = true; | |
return res; | |
} | |
function executeAction(actionName, fn, scope, args) { | |
var runInfo = startAction(actionName, fn, scope, args); | |
try { | |
return fn.apply(scope, args); | |
} | |
finally { | |
endAction(runInfo); | |
} | |
} | |
function startAction(actionName, fn, scope, args) { | |
var notifySpy = isSpyEnabled() && !!actionName; | |
var startTime = 0; | |
if (notifySpy) { | |
startTime = Date.now(); | |
var l = (args && args.length) || 0; | |
var flattendArgs = new Array(l); | |
if (l > 0) | |
for (var i = 0; i < l; i++) | |
flattendArgs[i] = args[i]; | |
spyReportStart({ | |
type: "action", | |
name: actionName, | |
fn: fn, | |
object: scope, | |
arguments: flattendArgs | |
}); | |
} | |
var prevDerivation = untrackedStart(); | |
startBatch(); | |
var prevAllowStateChanges = allowStateChangesStart(true); | |
return { | |
prevDerivation: prevDerivation, | |
prevAllowStateChanges: prevAllowStateChanges, | |
notifySpy: notifySpy, | |
startTime: startTime | |
}; | |
} | |
function endAction(runInfo) { | |
allowStateChangesEnd(runInfo.prevAllowStateChanges); | |
endBatch(); | |
untrackedEnd(runInfo.prevDerivation); | |
if (runInfo.notifySpy) | |
spyReportEnd({ time: Date.now() - runInfo.startTime }); | |
} | |
function useStrict(strict) { | |
invariant(globalState.trackingDerivation === null, getMessage("m028")); | |
globalState.strictMode = strict; | |
globalState.allowStateChanges = !strict; | |
} | |
exports.useStrict = useStrict; | |
function isStrictModeEnabled() { | |
return globalState.strictMode; | |
} | |
exports.isStrictModeEnabled = isStrictModeEnabled; | |
function allowStateChanges(allowStateChanges, func) { | |
var prev = allowStateChangesStart(allowStateChanges); | |
var res; | |
try { | |
res = func(); | |
} | |
finally { | |
allowStateChangesEnd(prev); | |
} | |
return res; | |
} | |
function allowStateChangesStart(allowStateChanges) { | |
var prev = globalState.allowStateChanges; | |
globalState.allowStateChanges = allowStateChanges; | |
return prev; | |
} | |
function allowStateChangesEnd(prev) { | |
globalState.allowStateChanges = prev; | |
} | |
var BaseAtom = (function () { | |
function BaseAtom(name) { | |
if (name === void 0) { name = "Atom@" + getNextId(); } | |
this.name = name; | |
this.isPendingUnobservation = true; | |
this.observers = []; | |
this.observersIndexes = {}; | |
this.diffValue = 0; | |
this.lastAccessedBy = 0; | |
this.lowestObserverState = IDerivationState.NOT_TRACKING; | |
} | |
BaseAtom.prototype.onBecomeUnobserved = function () { | |
}; | |
BaseAtom.prototype.reportObserved = function () { | |
reportObserved(this); | |
}; | |
BaseAtom.prototype.reportChanged = function () { | |
startBatch(); | |
propagateChanged(this); | |
endBatch(); | |
}; | |
BaseAtom.prototype.toString = function () { | |
return this.name; | |
}; | |
return BaseAtom; | |
}()); | |
exports.BaseAtom = BaseAtom; | |
var Atom = (function (_super) { | |
__extends(Atom, _super); | |
function Atom(name, onBecomeObservedHandler, onBecomeUnobservedHandler) { | |
if (name === void 0) { name = "Atom@" + getNextId(); } | |
if (onBecomeObservedHandler === void 0) { onBecomeObservedHandler = noop; } | |
if (onBecomeUnobservedHandler === void 0) { onBecomeUnobservedHandler = noop; } | |
var _this = _super.call(this, name) || this; | |
_this.name = name; | |
_this.onBecomeObservedHandler = onBecomeObservedHandler; | |
_this.onBecomeUnobservedHandler = onBecomeUnobservedHandler; | |
_this.isPendingUnobservation = false; | |
_this.isBeingTracked = false; | |
return _this; | |
} | |
Atom.prototype.reportObserved = function () { | |
startBatch(); | |
_super.prototype.reportObserved.call(this); | |
if (!this.isBeingTracked) { | |
this.isBeingTracked = true; | |
this.onBecomeObservedHandler(); | |
} | |
endBatch(); | |
return !!globalState.trackingDerivation; | |
}; | |
Atom.prototype.onBecomeUnobserved = function () { | |
this.isBeingTracked = false; | |
this.onBecomeUnobservedHandler(); | |
}; | |
return Atom; | |
}(BaseAtom)); | |
exports.Atom = Atom; | |
var isAtom = createInstanceofPredicate("Atom", BaseAtom); | |
var ComputedValue = (function () { | |
function ComputedValue(derivation, scope, compareStructural, name, setter) { | |
this.derivation = derivation; | |
this.scope = scope; | |
this.compareStructural = compareStructural; | |
this.dependenciesState = IDerivationState.NOT_TRACKING; | |
this.observing = []; | |
this.newObserving = null; | |
this.isPendingUnobservation = false; | |
this.observers = []; | |
this.observersIndexes = {}; | |
this.diffValue = 0; | |
this.runId = 0; | |
this.lastAccessedBy = 0; | |
this.lowestObserverState = IDerivationState.UP_TO_DATE; | |
this.unboundDepsCount = 0; | |
this.__mapid = "#" + getNextId(); | |
this.value = undefined; | |
this.isComputing = false; | |
this.isRunningSetter = false; | |
this.name = name || "ComputedValue@" + getNextId(); | |
if (setter) | |
this.setter = createAction(name + "-setter", setter); | |
} | |
ComputedValue.prototype.onBecomeStale = function () { | |
propagateMaybeChanged(this); | |
}; | |
ComputedValue.prototype.onBecomeUnobserved = function () { | |
invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, getMessage("m029")); | |
clearObserving(this); | |
this.value = undefined; | |
}; | |
ComputedValue.prototype.get = function () { | |
invariant(!this.isComputing, "Cycle detected in computation " + this.name, this.derivation); | |
if (globalState.inBatch === 0) { | |
startBatch(); | |
if (shouldCompute(this)) | |
this.value = this.computeValue(false); | |
endBatch(); | |
} | |
else { | |
reportObserved(this); | |
if (shouldCompute(this)) | |
if (this.trackAndCompute()) | |
propagateChangeConfirmed(this); | |
} | |
var result = this.value; | |
if (isCaughtException(result)) | |
throw result.cause; | |
return result; | |
}; | |
ComputedValue.prototype.peek = function () { | |
var res = this.computeValue(false); | |
if (isCaughtException(res)) | |
throw res.cause; | |
return res; | |
}; | |
ComputedValue.prototype.set = function (value) { | |
if (this.setter) { | |
invariant(!this.isRunningSetter, "The setter of computed value '" + this.name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?"); | |
this.isRunningSetter = true; | |
try { | |
this.setter.call(this.scope, value); | |
} | |
finally { | |
this.isRunningSetter = false; | |
} | |
} | |
else | |
invariant(false, "[ComputedValue '" + this.name + "'] It is not possible to assign a new value to a computed value."); | |
}; | |
ComputedValue.prototype.trackAndCompute = function () { | |
if (isSpyEnabled()) { | |
spyReport({ | |
object: this.scope, | |
type: "compute", | |
fn: this.derivation | |
}); | |
} | |
var oldValue = this.value; | |
var newValue = this.value = this.computeValue(true); | |
return isCaughtException(newValue) || valueDidChange(this.compareStructural, newValue, oldValue); | |
}; | |
ComputedValue.prototype.computeValue = function (track) { | |
this.isComputing = true; | |
globalState.computationDepth++; | |
var res; | |
if (track) { | |
res = trackDerivedFunction(this, this.derivation, this.scope); | |
} | |
else { | |
try { | |
res = this.derivation.call(this.scope); | |
} | |
catch (e) { | |
res = new CaughtException(e); | |
} | |
} | |
globalState.computationDepth--; | |
this.isComputing = false; | |
return res; | |
}; | |
; | |
ComputedValue.prototype.observe = function (listener, fireImmediately) { | |
var _this = this; | |
var firstTime = true; | |
var prevValue = undefined; | |
return autorun(function () { | |
var newValue = _this.get(); | |
if (!firstTime || fireImmediately) { | |
var prevU = untrackedStart(); | |
listener({ | |
type: "update", | |
object: _this, | |
newValue: newValue, | |
oldValue: prevValue | |
}); | |
untrackedEnd(prevU); | |
} | |
firstTime = false; | |
prevValue = newValue; | |
}); | |
}; | |
ComputedValue.prototype.toJSON = function () { | |
return this.get(); | |
}; | |
ComputedValue.prototype.toString = function () { | |
return this.name + "[" + this.derivation.toString() + "]"; | |
}; | |
ComputedValue.prototype.valueOf = function () { | |
return toPrimitive(this.get()); | |
}; | |
; | |
ComputedValue.prototype.whyRun = function () { | |
var isTracking = Boolean(globalState.trackingDerivation); | |
var observing = unique(this.isComputing ? this.newObserving : this.observing).map(function (dep) { return dep.name; }); | |
var observers = unique(getObservers(this).map(function (dep) { return dep.name; })); | |
return ("\nWhyRun? computation '" + this.name + "':\n * Running because: " + (isTracking ? "[active] the value of this computation is needed by a reaction" : this.isComputing ? "[get] The value of this computed was requested outside a reaction" : "[idle] not running at the moment") + "\n" + | |
(this.dependenciesState === IDerivationState.NOT_TRACKING ? getMessage("m032") : | |
" * This computation will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + ((this.isComputing && isTracking) ? " (... or any observable accessed during the remainder of the current run)" : "") + "\n\t" + getMessage("m038") + "\n\n * If the outcome of this computation changes, the following observers will be re-run:\n " + joinStrings(observers) + "\n")); | |
}; | |
return ComputedValue; | |
}()); | |
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf; | |
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue); | |
var IDerivationState; | |
(function (IDerivationState) { | |
IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING"; | |
IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE"; | |
IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE"; | |
IDerivationState[IDerivationState["STALE"] = 2] = "STALE"; | |
})(IDerivationState || (IDerivationState = {})); | |
exports.IDerivationState = IDerivationState; | |
var CaughtException = (function () { | |
function CaughtException(cause) { | |
this.cause = cause; | |
} | |
return CaughtException; | |
}()); | |
function isCaughtException(e) { | |
return e instanceof CaughtException; | |
} | |
function shouldCompute(derivation) { | |
switch (derivation.dependenciesState) { | |
case IDerivationState.UP_TO_DATE: return false; | |
case IDerivationState.NOT_TRACKING: | |
case IDerivationState.STALE: return true; | |
case IDerivationState.POSSIBLY_STALE: { | |
var prevUntracked = untrackedStart(); | |
var obs = derivation.observing, l = obs.length; | |
for (var i = 0; i < l; i++) { | |
var obj = obs[i]; | |
if (isComputedValue(obj)) { | |
try { | |
obj.get(); | |
} | |
catch (e) { | |
untrackedEnd(prevUntracked); | |
return true; | |
} | |
if (derivation.dependenciesState === IDerivationState.STALE) { | |
untrackedEnd(prevUntracked); | |
return true; | |
} | |
} | |
} | |
changeDependenciesStateTo0(derivation); | |
untrackedEnd(prevUntracked); | |
return false; | |
} | |
} | |
} | |
function isComputingDerivation() { | |
return globalState.trackingDerivation !== null; | |
} | |
function checkIfStateModificationsAreAllowed(atom) { | |
var hasObservers = atom.observers.length > 0; | |
if (globalState.computationDepth > 0 && hasObservers) | |
fail(getMessage("m031") + atom.name); | |
if (!globalState.allowStateChanges && hasObservers) | |
fail(getMessage(globalState.strictMode ? "m030a" : "m030b") + atom.name); | |
} | |
function trackDerivedFunction(derivation, f, context) { | |
changeDependenciesStateTo0(derivation); | |
derivation.newObserving = new Array(derivation.observing.length + 100); | |
derivation.unboundDepsCount = 0; | |
derivation.runId = ++globalState.runId; | |
var prevTracking = globalState.trackingDerivation; | |
globalState.trackingDerivation = derivation; | |
var result; | |
try { | |
result = f.call(context); | |
} | |
catch (e) { | |
result = new CaughtException(e); | |
} | |
globalState.trackingDerivation = prevTracking; | |
bindDependencies(derivation); | |
return result; | |
} | |
function bindDependencies(derivation) { | |
var prevObserving = derivation.observing; | |
var observing = derivation.observing = derivation.newObserving; | |
derivation.newObserving = null; | |
var i0 = 0, l = derivation.unboundDepsCount; | |
for (var i = 0; i < l; i++) { | |
var dep = observing[i]; | |
if (dep.diffValue === 0) { | |
dep.diffValue = 1; | |
if (i0 !== i) | |
observing[i0] = dep; | |
i0++; | |
} | |
} | |
observing.length = i0; | |
l = prevObserving.length; | |
while (l--) { | |
var dep = prevObserving[l]; | |
if (dep.diffValue === 0) { | |
removeObserver(dep, derivation); | |
} | |
dep.diffValue = 0; | |
} | |
while (i0--) { | |
var dep = observing[i0]; | |
if (dep.diffValue === 1) { | |
dep.diffValue = 0; | |
addObserver(dep, derivation); | |
} | |
} | |
} | |
function clearObserving(derivation) { | |
var obs = derivation.observing; | |
var i = obs.length; | |
while (i--) | |
removeObserver(obs[i], derivation); | |
derivation.dependenciesState = IDerivationState.NOT_TRACKING; | |
obs.length = 0; | |
} | |
function untracked(action) { | |
var prev = untrackedStart(); | |
var res = action(); | |
untrackedEnd(prev); | |
return res; | |
} | |
exports.untracked = untracked; | |
function untrackedStart() { | |
var prev = globalState.trackingDerivation; | |
globalState.trackingDerivation = null; | |
return prev; | |
} | |
function untrackedEnd(prev) { | |
globalState.trackingDerivation = prev; | |
} | |
function changeDependenciesStateTo0(derivation) { | |
if (derivation.dependenciesState === IDerivationState.UP_TO_DATE) | |
return; | |
derivation.dependenciesState = IDerivationState.UP_TO_DATE; | |
var obs = derivation.observing; | |
var i = obs.length; | |
while (i--) | |
obs[i].lowestObserverState = IDerivationState.UP_TO_DATE; | |
} | |
var persistentKeys = ["mobxGuid", "resetId", "spyListeners", "strictMode", "runId"]; | |
var MobXGlobals = (function () { | |
function MobXGlobals() { | |
this.version = 5; | |
this.trackingDerivation = null; | |
this.computationDepth = 0; | |
this.runId = 0; | |
this.mobxGuid = 0; | |
this.inBatch = 0; | |
this.pendingUnobservations = []; | |
this.pendingReactions = []; | |
this.isRunningReactions = false; | |
this.allowStateChanges = true; | |
this.strictMode = false; | |
this.resetId = 0; | |
this.spyListeners = []; | |
this.globalReactionErrorHandlers = []; | |
} | |
return MobXGlobals; | |
}()); | |
var globalState = new MobXGlobals(); | |
function shareGlobalState() { | |
var global = getGlobal(); | |
var ownState = globalState; | |
if (global.__mobservableTrackingStack || global.__mobservableViewStack) | |
throw new Error("[mobx] An incompatible version of mobservable is already loaded."); | |
if (global.__mobxGlobal && global.__mobxGlobal.version !== ownState.version) | |
throw new Error("[mobx] An incompatible version of mobx is already loaded."); | |
if (global.__mobxGlobal) | |
globalState = global.__mobxGlobal; | |
else | |
global.__mobxGlobal = ownState; | |
} | |
function getGlobalState() { | |
return globalState; | |
} | |
function registerGlobals() { | |
} | |
function resetGlobalState() { | |
globalState.resetId++; | |
var defaultGlobals = new MobXGlobals(); | |
for (var key in defaultGlobals) | |
if (persistentKeys.indexOf(key) === -1) | |
globalState[key] = defaultGlobals[key]; | |
globalState.allowStateChanges = !globalState.strictMode; | |
} | |
function hasObservers(observable) { | |
return observable.observers && observable.observers.length > 0; | |
} | |
function getObservers(observable) { | |
return observable.observers; | |
} | |
function invariantObservers(observable) { | |
var list = observable.observers; | |
var map = observable.observersIndexes; | |
var l = list.length; | |
for (var i = 0; i < l; i++) { | |
var id = list[i].__mapid; | |
if (i) { | |
invariant(map[id] === i, "INTERNAL ERROR maps derivation.__mapid to index in list"); | |
} | |
else { | |
invariant(!(id in map), "INTERNAL ERROR observer on index 0 shouldnt be held in map."); | |
} | |
} | |
invariant(list.length === 0 || Object.keys(map).length === list.length - 1, "INTERNAL ERROR there is no junk in map"); | |
} | |
function addObserver(observable, node) { | |
var l = observable.observers.length; | |
if (l) { | |
observable.observersIndexes[node.__mapid] = l; | |
} | |
observable.observers[l] = node; | |
if (observable.lowestObserverState > node.dependenciesState) | |
observable.lowestObserverState = node.dependenciesState; | |
} | |
function removeObserver(observable, node) { | |
if (observable.observers.length === 1) { | |
observable.observers.length = 0; | |
queueForUnobservation(observable); | |
} | |
else { | |
var list = observable.observers; | |
var map_1 = observable.observersIndexes; | |
var filler = list.pop(); | |
if (filler !== node) { | |
var index = map_1[node.__mapid] || 0; | |
if (index) { | |
map_1[filler.__mapid] = index; | |
} | |
else { | |
delete map_1[filler.__mapid]; | |
} | |
list[index] = filler; | |
} | |
delete map_1[node.__mapid]; | |
} | |
} | |
function queueForUnobservation(observable) { | |
if (!observable.isPendingUnobservation) { | |
observable.isPendingUnobservation = true; | |
globalState.pendingUnobservations.push(observable); | |
} | |
} | |
function startBatch() { | |
globalState.inBatch++; | |
} | |
function endBatch() { | |
if (--globalState.inBatch === 0) { | |
runReactions(); | |
var list = globalState.pendingUnobservations; | |
for (var i = 0; i < list.length; i++) { | |
var observable_1 = list[i]; | |
observable_1.isPendingUnobservation = false; | |
if (observable_1.observers.length === 0) { | |
observable_1.onBecomeUnobserved(); | |
} | |
} | |
globalState.pendingUnobservations = []; | |
} | |
} | |
function reportObserved(observable) { | |
var derivation = globalState.trackingDerivation; | |
if (derivation !== null) { | |
if (derivation.runId !== observable.lastAccessedBy) { | |
observable.lastAccessedBy = derivation.runId; | |
derivation.newObserving[derivation.unboundDepsCount++] = observable; | |
} | |
} | |
else if (observable.observers.length === 0) { | |
queueForUnobservation(observable); | |
} | |
} | |
function invariantLOS(observable, msg) { | |
var min = getObservers(observable).reduce(function (a, b) { return Math.min(a, b.dependenciesState); }, 2); | |
if (min >= observable.lowestObserverState) | |
return; | |
throw new Error("lowestObserverState is wrong for " + msg + " because " + min + " < " + observable.lowestObserverState); | |
} | |
function propagateChanged(observable) { | |
if (observable.lowestObserverState === IDerivationState.STALE) | |
return; | |
observable.lowestObserverState = IDerivationState.STALE; | |
var observers = observable.observers; | |
var i = observers.length; | |
while (i--) { | |
var d = observers[i]; | |
if (d.dependenciesState === IDerivationState.UP_TO_DATE) | |
d.onBecomeStale(); | |
d.dependenciesState = IDerivationState.STALE; | |
} | |
} | |
function propagateChangeConfirmed(observable) { | |
if (observable.lowestObserverState === IDerivationState.STALE) | |
return; | |
observable.lowestObserverState = IDerivationState.STALE; | |
var observers = observable.observers; | |
var i = observers.length; | |
while (i--) { | |
var d = observers[i]; | |
if (d.dependenciesState === IDerivationState.POSSIBLY_STALE) | |
d.dependenciesState = IDerivationState.STALE; | |
else if (d.dependenciesState === IDerivationState.UP_TO_DATE) | |
observable.lowestObserverState = IDerivationState.UP_TO_DATE; | |
} | |
} | |
function propagateMaybeChanged(observable) { | |
if (observable.lowestObserverState !== IDerivationState.UP_TO_DATE) | |
return; | |
observable.lowestObserverState = IDerivationState.POSSIBLY_STALE; | |
var observers = observable.observers; | |
var i = observers.length; | |
while (i--) { | |
var d = observers[i]; | |
if (d.dependenciesState === IDerivationState.UP_TO_DATE) { | |
d.dependenciesState = IDerivationState.POSSIBLY_STALE; | |
d.onBecomeStale(); | |
} | |
} | |
} | |
var Reaction = (function () { | |
function Reaction(name, onInvalidate) { | |
if (name === void 0) { name = "Reaction@" + getNextId(); } | |
this.name = name; | |
this.onInvalidate = onInvalidate; | |
this.observing = []; | |
this.newObserving = []; | |
this.dependenciesState = IDerivationState.NOT_TRACKING; | |
this.diffValue = 0; | |
this.runId = 0; | |
this.unboundDepsCount = 0; | |
this.__mapid = "#" + getNextId(); | |
this.isDisposed = false; | |
this._isScheduled = false; | |
this._isTrackPending = false; | |
this._isRunning = false; | |
} | |
Reaction.prototype.onBecomeStale = function () { | |
this.schedule(); | |
}; | |
Reaction.prototype.schedule = function () { | |
if (!this._isScheduled) { | |
this._isScheduled = true; | |
globalState.pendingReactions.push(this); | |
runReactions(); | |
} | |
}; | |
Reaction.prototype.isScheduled = function () { | |
return this._isScheduled; | |
}; | |
Reaction.prototype.runReaction = function () { | |
if (!this.isDisposed) { | |
startBatch(); | |
this._isScheduled = false; | |
if (shouldCompute(this)) { | |
this._isTrackPending = true; | |
this.onInvalidate(); | |
if (this._isTrackPending && isSpyEnabled()) { | |
spyReport({ | |
object: this, | |
type: "scheduled-reaction" | |
}); | |
} | |
} | |
endBatch(); | |
} | |
}; | |
Reaction.prototype.track = function (fn) { | |
startBatch(); | |
var notify = isSpyEnabled(); | |
var startTime; | |
if (notify) { | |
startTime = Date.now(); | |
spyReportStart({ | |
object: this, | |
type: "reaction", | |
fn: fn | |
}); | |
} | |
this._isRunning = true; | |
var result = trackDerivedFunction(this, fn, undefined); | |
this._isRunning = false; | |
this._isTrackPending = false; | |
if (this.isDisposed) { | |
clearObserving(this); | |
} | |
if (isCaughtException(result)) | |
this.reportExceptionInDerivation(result.cause); | |
if (notify) { | |
spyReportEnd({ | |
time: Date.now() - startTime | |
}); | |
} | |
endBatch(); | |
}; | |
Reaction.prototype.reportExceptionInDerivation = function (error) { | |
var _this = this; | |
if (this.errorHandler) { | |
this.errorHandler(error, this); | |
return; | |
} | |
var message = "[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '" + this; | |
var messageToUser = getMessage("m037"); | |
console.error(message || messageToUser, error); | |
if (isSpyEnabled()) { | |
spyReport({ | |
type: "error", | |
message: message, | |
error: error, | |
object: this | |
}); | |
} | |
globalState.globalReactionErrorHandlers.forEach(function (f) { return f(error, _this); }); | |
}; | |
Reaction.prototype.dispose = function () { | |
if (!this.isDisposed) { | |
this.isDisposed = true; | |
if (!this._isRunning) { | |
startBatch(); | |
clearObserving(this); | |
endBatch(); | |
} | |
} | |
}; | |
Reaction.prototype.getDisposer = function () { | |
var r = this.dispose.bind(this); | |
r.$mobx = this; | |
r.onError = registerErrorHandler; | |
return r; | |
}; | |
Reaction.prototype.toString = function () { | |
return "Reaction[" + this.name + "]"; | |
}; | |
Reaction.prototype.whyRun = function () { | |
var observing = unique(this._isRunning ? this.newObserving : this.observing).map(function (dep) { return dep.name; }); | |
return ("\nWhyRun? reaction '" + this.name + "':\n * Status: [" + (this.isDisposed ? "stopped" : this._isRunning ? "running" : this.isScheduled() ? "scheduled" : "idle") + "]\n * This reaction will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + ((this._isRunning) ? " (... or any observable accessed during the remainder of the current run)" : "") + "\n\t" + getMessage("m038") + "\n"); | |
}; | |
return Reaction; | |
}()); | |
exports.Reaction = Reaction; | |
function registerErrorHandler(handler) { | |
invariant(this && this.$mobx && isReaction(this.$mobx), "Invalid `this`"); | |
invariant(!this.$mobx.errorHandler, "Only one onErrorHandler can be registered"); | |
this.$mobx.errorHandler = handler; | |
} | |
function onReactionError(handler) { | |
globalState.globalReactionErrorHandlers.push(handler); | |
return function () { | |
var idx = globalState.globalReactionErrorHandlers.indexOf(handler); | |
if (idx >= 0) | |
globalState.globalReactionErrorHandlers.splice(idx, 1); | |
}; | |
} | |
var MAX_REACTION_ITERATIONS = 100; | |
var reactionScheduler = function (f) { return f(); }; | |
function runReactions() { | |
if (globalState.inBatch > 0 || globalState.isRunningReactions) | |
return; | |
reactionScheduler(runReactionsHelper); | |
} | |
function runReactionsHelper() { | |
globalState.isRunningReactions = true; | |
var allReactions = globalState.pendingReactions; | |
var iterations = 0; | |
while (allReactions.length > 0) { | |
if (++iterations === MAX_REACTION_ITERATIONS) { | |
console.error("Reaction doesn't converge to a stable state after " + MAX_REACTION_ITERATIONS + " iterations." | |
+ (" Probably there is a cycle in the reactive function: " + allReactions[0])); | |
allReactions.splice(0); | |
} | |
var remainingReactions = allReactions.splice(0); | |
for (var i = 0, l = remainingReactions.length; i < l; i++) | |
remainingReactions[i].runReaction(); | |
} | |
globalState.isRunningReactions = false; | |
} | |
var isReaction = createInstanceofPredicate("Reaction", Reaction); | |
function setReactionScheduler(fn) { | |
var baseScheduler = reactionScheduler; | |
reactionScheduler = function (f) { return fn(function () { return baseScheduler(f); }); }; | |
} | |
function isSpyEnabled() { | |
return !!globalState.spyListeners.length; | |
} | |
function spyReport(event) { | |
if (!globalState.spyListeners.length) | |
return; | |
var listeners = globalState.spyListeners; | |
for (var i = 0, l = listeners.length; i < l; i++) | |
listeners[i](event); | |
} | |
function spyReportStart(event) { | |
var change = objectAssign({}, event, { spyReportStart: true }); | |
spyReport(change); | |
} | |
var END_EVENT = { spyReportEnd: true }; | |
function spyReportEnd(change) { | |
if (change) | |
spyReport(objectAssign({}, change, END_EVENT)); | |
else | |
spyReport(END_EVENT); | |
} | |
function spy(listener) { | |
globalState.spyListeners.push(listener); | |
return once(function () { | |
var idx = globalState.spyListeners.indexOf(listener); | |
if (idx !== -1) | |
globalState.spyListeners.splice(idx, 1); | |
}); | |
} | |
exports.spy = spy; | |
function hasInterceptors(interceptable) { | |
return (interceptable.interceptors && interceptable.interceptors.length > 0); | |
} | |
function registerInterceptor(interceptable, handler) { | |
var interceptors = interceptable.interceptors || (interceptable.interceptors = []); | |
interceptors.push(handler); | |
return once(function () { | |
var idx = interceptors.indexOf(handler); | |
if (idx !== -1) | |
interceptors.splice(idx, 1); | |
}); | |
} | |
function interceptChange(interceptable, change) { | |
var prevU = untrackedStart(); | |
try { | |
var interceptors = interceptable.interceptors; | |
if (interceptors) | |
for (var i = 0, l = interceptors.length; i < l; i++) { | |
change = interceptors[i](change); | |
invariant(!change || change.type, "Intercept handlers should return nothing or a change object"); | |
if (!change) | |
break; | |
} | |
return change; | |
} | |
finally { | |
untrackedEnd(prevU); | |
} | |
} | |
function hasListeners(listenable) { | |
return listenable.changeListeners && listenable.changeListeners.length > 0; | |
} | |
function registerListener(listenable, handler) { | |
var listeners = listenable.changeListeners || (listenable.changeListeners = []); | |
listeners.push(handler); | |
return once(function () { | |
var idx = listeners.indexOf(handler); | |
if (idx !== -1) | |
listeners.splice(idx, 1); | |
}); | |
} | |
function notifyListeners(listenable, change) { | |
var prevU = untrackedStart(); | |
var listeners = listenable.changeListeners; | |
if (!listeners) | |
return; | |
listeners = listeners.slice(); | |
for (var i = 0, l = listeners.length; i < l; i++) { | |
listeners[i](change); | |
} | |
untrackedEnd(prevU); | |
} | |
function asReference(value) { | |
deprecated("asReference is deprecated, use observable.ref instead"); | |
return observable.ref(value); | |
} | |
exports.asReference = asReference; | |
function asStructure(value) { | |
deprecated("asStructure is deprecated. Use observable.struct, computed.struct or reaction options instead."); | |
return observable.struct(value); | |
} | |
exports.asStructure = asStructure; | |
function asFlat(value) { | |
deprecated("asFlat is deprecated, use observable.shallow instead"); | |
return observable.shallow(value); | |
} | |
exports.asFlat = asFlat; | |
function asMap(data) { | |
deprecated("asMap is deprecated, use observable.map or observable.shallowMap instead"); | |
return observable.map(data || {}); | |
} | |
exports.asMap = asMap; | |
function isModifierDescriptor(thing) { | |
return typeof thing === "object" && thing !== null && thing.isMobxModifierDescriptor === true; | |
} | |
exports.isModifierDescriptor = isModifierDescriptor; | |
function createModifierDescriptor(enhancer, initialValue) { | |
invariant(!isModifierDescriptor(initialValue), "Modifiers cannot be nested"); | |
return { | |
isMobxModifierDescriptor: true, | |
initialValue: initialValue, | |
enhancer: enhancer | |
}; | |
} | |
function deepEnhancer(v, _, name) { | |
if (isModifierDescriptor(v)) | |
fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it"); | |
if (isObservable(v)) | |
return v; | |
if (Array.isArray(v)) | |
return observable.array(v, name); | |
if (isPlainObject(v)) | |
return observable.object(v, name); | |
if (isES6Map(v)) | |
return observable.shallowMap(v, name); | |
return v; | |
} | |
function shallowEnhancer(v, _, name) { | |
if (isModifierDescriptor(v)) | |
fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it"); | |
if (v === undefined || v === null) | |
return v; | |
if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v)) | |
return v; | |
if (Array.isArray(v)) | |
return observable.shallowArray(v, name); | |
if (isPlainObject(v)) | |
return observable.shallowObject(v, name); | |
if (isES6Map(v)) | |
return observable.shallowMap(v, name); | |
return fail("The shallow modifier / decorator can only used in combination with arrays, objects and maps"); | |
} | |
function referenceEnhancer(newValue) { | |
return newValue; | |
} | |
function deepStructEnhancer(v, oldValue, name) { | |
if (deepEqual(v, oldValue)) | |
return oldValue; | |
if (isObservable(v)) | |
return v; | |
if (Array.isArray(v)) | |
return new ObservableArray(v, deepStructEnhancer, name); | |
if (isES6Map(v)) | |
return new ObservableMap(v, deepStructEnhancer, name); | |
if (isPlainObject(v)) { | |
var res = {}; | |
asObservableObject(res, name); | |
extendObservableHelper(res, deepStructEnhancer, [v]); | |
return res; | |
} | |
return v; | |
} | |
function refStructEnhancer(v, oldValue, name) { | |
if (deepEqual(v, oldValue)) | |
return oldValue; | |
return v; | |
} | |
var safariPrototypeSetterInheritanceBug = (function () { | |
var v = false; | |
var p = {}; | |
Object.defineProperty(p, "0", { set: function () { v = true; } }); | |
Object.create(p)["0"] = 1; | |
return v === false; | |
})(); | |
var OBSERVABLE_ARRAY_BUFFER_SIZE = 0; | |
var StubArray = (function () { | |
function StubArray() { | |
} | |
return StubArray; | |
}()); | |
StubArray.prototype = []; | |
var ObservableArrayAdministration = (function () { | |
function ObservableArrayAdministration(name, enhancer, array, owned) { | |
this.array = array; | |
this.owned = owned; | |
this.lastKnownLength = 0; | |
this.interceptors = null; | |
this.changeListeners = null; | |
this.atom = new BaseAtom(name || ("ObservableArray@" + getNextId())); | |
this.enhancer = function (newV, oldV) { return enhancer(newV, oldV, name + "[..]"); }; | |
} | |
ObservableArrayAdministration.prototype.intercept = function (handler) { | |
return registerInterceptor(this, handler); | |
}; | |
ObservableArrayAdministration.prototype.observe = function (listener, fireImmediately) { | |
if (fireImmediately === void 0) { fireImmediately = false; } | |
if (fireImmediately) { | |
listener({ | |
object: this.array, | |
type: "splice", | |
index: 0, | |
added: this.values.slice(), | |
addedCount: this.values.length, | |
removed: [], | |
removedCount: 0 | |
}); | |
} | |
return registerListener(this, listener); | |
}; | |
ObservableArrayAdministration.prototype.getArrayLength = function () { | |
this.atom.reportObserved(); | |
return this.values.length; | |
}; | |
ObservableArrayAdministration.prototype.setArrayLength = function (newLength) { | |
if (typeof newLength !== "number" || newLength < 0) | |
throw new Error("[mobx.array] Out of range: " + newLength); | |
var currentLength = this.values.length; | |
if (newLength === currentLength) | |
return; | |
else if (newLength > currentLength) | |
this.spliceWithArray(currentLength, 0, new Array(newLength - currentLength)); | |
else | |
this.spliceWithArray(newLength, currentLength - newLength); | |
}; | |
ObservableArrayAdministration.prototype.updateArrayLength = function (oldLength, delta) { | |
if (oldLength !== this.lastKnownLength) | |
throw new Error("[mobx] Modification exception: the internal structure of an observable array was changed. Did you use peek() to change it?"); | |
this.lastKnownLength += delta; | |
if (delta > 0 && oldLength + delta + 1 > OBSERVABLE_ARRAY_BUFFER_SIZE) | |
reserveArrayBuffer(oldLength + delta + 1); | |
}; | |
ObservableArrayAdministration.prototype.spliceWithArray = function (index, deleteCount, newItems) { | |
var _this = this; | |
checkIfStateModificationsAreAllowed(this.atom); | |
var length = this.values.length; | |
if (index === undefined) | |
index = 0; | |
else if (index > length) | |
index = length; | |
else if (index < 0) | |
index = Math.max(0, length + index); | |
if (arguments.length === 1) | |
deleteCount = length - index; | |
else if (deleteCount === undefined || deleteCount === null) | |
deleteCount = 0; | |
else | |
deleteCount = Math.max(0, Math.min(deleteCount, length - index)); | |
if (newItems === undefined) | |
newItems = []; | |
if (hasInterceptors(this)) { | |
var change = interceptChange(this, { | |
object: this.array, | |
type: "splice", | |
index: index, | |
removedCount: deleteCount, | |
added: newItems | |
}); | |
if (!change) | |
return EMPTY_ARRAY; | |
deleteCount = change.removedCount; | |
newItems = change.added; | |
} | |
newItems = newItems.map(function (v) { return _this.enhancer(v, undefined); }); | |
var lengthDelta = newItems.length - deleteCount; | |
this.updateArrayLength(length, lengthDelta); | |
var res = (_a = this.values).splice.apply(_a, [index, deleteCount].concat(newItems)); | |
if (deleteCount !== 0 || newItems.length !== 0) | |
this.notifyArraySplice(index, newItems, res); | |
return res; | |
var _a; | |
}; | |
ObservableArrayAdministration.prototype.notifyArrayChildUpdate = function (index, newValue, oldValue) { | |
var notifySpy = !this.owned && isSpyEnabled(); | |
var notify = hasListeners(this); | |
var change = notify || notifySpy ? { | |
object: this.array, | |
type: "update", | |
index: index, newValue: newValue, oldValue: oldValue | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
this.atom.reportChanged(); | |
if (notify) | |
notifyListeners(this, change); | |
if (notifySpy) | |
spyReportEnd(); | |
}; | |
ObservableArrayAdministration.prototype.notifyArraySplice = function (index, added, removed) { | |
var notifySpy = !this.owned && isSpyEnabled(); | |
var notify = hasListeners(this); | |
var change = notify || notifySpy ? { | |
object: this.array, | |
type: "splice", | |
index: index, removed: removed, added: added, | |
removedCount: removed.length, | |
addedCount: added.length | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
this.atom.reportChanged(); | |
if (notify) | |
notifyListeners(this, change); | |
if (notifySpy) | |
spyReportEnd(); | |
}; | |
return ObservableArrayAdministration; | |
}()); | |
var ObservableArray = (function (_super) { | |
__extends(ObservableArray, _super); | |
function ObservableArray(initialValues, enhancer, name, owned) { | |
if (name === void 0) { name = "ObservableArray@" + getNextId(); } | |
if (owned === void 0) { owned = false; } | |
var _this = _super.call(this) || this; | |
var adm = new ObservableArrayAdministration(name, enhancer, _this, owned); | |
addHiddenFinalProp(_this, "$mobx", adm); | |
if (initialValues && initialValues.length) { | |
adm.updateArrayLength(0, initialValues.length); | |
adm.values = initialValues.map(function (v) { return enhancer(v, undefined, name + "[..]"); }); | |
adm.notifyArraySplice(0, adm.values.slice(), EMPTY_ARRAY); | |
} | |
else { | |
adm.values = []; | |
} | |
if (safariPrototypeSetterInheritanceBug) { | |
Object.defineProperty(adm.array, "0", ENTRY_0); | |
} | |
return _this; | |
} | |
ObservableArray.prototype.intercept = function (handler) { | |
return this.$mobx.intercept(handler); | |
}; | |
ObservableArray.prototype.observe = function (listener, fireImmediately) { | |
if (fireImmediately === void 0) { fireImmediately = false; } | |
return this.$mobx.observe(listener, fireImmediately); | |
}; | |
ObservableArray.prototype.clear = function () { | |
return this.splice(0); | |
}; | |
ObservableArray.prototype.concat = function () { | |
var arrays = []; | |
for (var _i = 0; _i < arguments.length; _i++) { | |
arrays[_i] = arguments[_i]; | |
} | |
this.$mobx.atom.reportObserved(); | |
return Array.prototype.concat.apply(this.peek(), arrays.map(function (a) { return isObservableArray(a) ? a.peek() : a; })); | |
}; | |
ObservableArray.prototype.replace = function (newItems) { | |
return this.$mobx.spliceWithArray(0, this.$mobx.values.length, newItems); | |
}; | |
ObservableArray.prototype.toJS = function () { | |
return this.slice(); | |
}; | |
ObservableArray.prototype.toJSON = function () { | |
return this.toJS(); | |
}; | |
ObservableArray.prototype.peek = function () { | |
return this.$mobx.values; | |
}; | |
ObservableArray.prototype.find = function (predicate, thisArg, fromIndex) { | |
if (fromIndex === void 0) { fromIndex = 0; } | |
this.$mobx.atom.reportObserved(); | |
var items = this.$mobx.values, l = items.length; | |
for (var i = fromIndex; i < l; i++) | |
if (predicate.call(thisArg, items[i], i, this)) | |
return items[i]; | |
return undefined; | |
}; | |
ObservableArray.prototype.splice = function (index, deleteCount) { | |
var newItems = []; | |
for (var _i = 2; _i < arguments.length; _i++) { | |
newItems[_i - 2] = arguments[_i]; | |
} | |
switch (arguments.length) { | |
case 0: | |
return []; | |
case 1: | |
return this.$mobx.spliceWithArray(index); | |
case 2: | |
return this.$mobx.spliceWithArray(index, deleteCount); | |
} | |
return this.$mobx.spliceWithArray(index, deleteCount, newItems); | |
}; | |
ObservableArray.prototype.push = function () { | |
var items = []; | |
for (var _i = 0; _i < arguments.length; _i++) { | |
items[_i] = arguments[_i]; | |
} | |
var adm = this.$mobx; | |
adm.spliceWithArray(adm.values.length, 0, items); | |
return adm.values.length; | |
}; | |
ObservableArray.prototype.pop = function () { | |
return this.splice(Math.max(this.$mobx.values.length - 1, 0), 1)[0]; | |
}; | |
ObservableArray.prototype.shift = function () { | |
return this.splice(0, 1)[0]; | |
}; | |
ObservableArray.prototype.unshift = function () { | |
var items = []; | |
for (var _i = 0; _i < arguments.length; _i++) { | |
items[_i] = arguments[_i]; | |
} | |
var adm = this.$mobx; | |
adm.spliceWithArray(0, 0, items); | |
return adm.values.length; | |
}; | |
ObservableArray.prototype.reverse = function () { | |
this.$mobx.atom.reportObserved(); | |
var clone = this.slice(); | |
return clone.reverse.apply(clone, arguments); | |
}; | |
ObservableArray.prototype.sort = function (compareFn) { | |
this.$mobx.atom.reportObserved(); | |
var clone = this.slice(); | |
return clone.sort.apply(clone, arguments); | |
}; | |
ObservableArray.prototype.remove = function (value) { | |
var idx = this.$mobx.values.indexOf(value); | |
if (idx > -1) { | |
this.splice(idx, 1); | |
return true; | |
} | |
return false; | |
}; | |
ObservableArray.prototype.move = function (fromIndex, toIndex) { | |
function checkIndex(index) { | |
if (index < 0) { | |
throw new Error("[mobx.array] Index out of bounds: " + index + " is negative"); | |
} | |
var length = this.$mobx.values.length; | |
if (index >= length) { | |
throw new Error("[mobx.array] Index out of bounds: " + index + " is not smaller than " + length); | |
} | |
} | |
checkIndex.call(this, fromIndex); | |
checkIndex.call(this, toIndex); | |
if (fromIndex === toIndex) { | |
return; | |
} | |
var oldItems = this.$mobx.values; | |
var newItems; | |
if (fromIndex < toIndex) { | |
newItems = oldItems.slice(0, fromIndex).concat(oldItems.slice(fromIndex + 1, toIndex + 1), [oldItems[fromIndex]], oldItems.slice(toIndex + 1)); | |
} | |
else { | |
newItems = oldItems.slice(0, toIndex).concat([oldItems[fromIndex]], oldItems.slice(toIndex, fromIndex), oldItems.slice(fromIndex + 1)); | |
} | |
this.replace(newItems); | |
}; | |
ObservableArray.prototype.toString = function () { | |
this.$mobx.atom.reportObserved(); | |
return Array.prototype.toString.apply(this.$mobx.values, arguments); | |
}; | |
ObservableArray.prototype.toLocaleString = function () { | |
this.$mobx.atom.reportObserved(); | |
return Array.prototype.toLocaleString.apply(this.$mobx.values, arguments); | |
}; | |
return ObservableArray; | |
}(StubArray)); | |
declareIterator(ObservableArray.prototype, function () { | |
return arrayAsIterator(this.slice()); | |
}); | |
makeNonEnumerable(ObservableArray.prototype, [ | |
"constructor", | |
"intercept", | |
"observe", | |
"clear", | |
"concat", | |
"replace", | |
"toJS", | |
"toJSON", | |
"peek", | |
"find", | |
"splice", | |
"push", | |
"pop", | |
"shift", | |
"unshift", | |
"reverse", | |
"sort", | |
"remove", | |
"move", | |
"toString", | |
"toLocaleString" | |
]); | |
Object.defineProperty(ObservableArray.prototype, "length", { | |
enumerable: false, | |
configurable: true, | |
get: function () { | |
return this.$mobx.getArrayLength(); | |
}, | |
set: function (newLength) { | |
this.$mobx.setArrayLength(newLength); | |
} | |
}); | |
[ | |
"every", | |
"filter", | |
"forEach", | |
"indexOf", | |
"join", | |
"lastIndexOf", | |
"map", | |
"reduce", | |
"reduceRight", | |
"slice", | |
"some" | |
].forEach(function (funcName) { | |
var baseFunc = Array.prototype[funcName]; | |
invariant(typeof baseFunc === "function", "Base function not defined on Array prototype: '" + funcName + "'"); | |
addHiddenProp(ObservableArray.prototype, funcName, function () { | |
this.$mobx.atom.reportObserved(); | |
return baseFunc.apply(this.$mobx.values, arguments); | |
}); | |
}); | |
var ENTRY_0 = { | |
configurable: true, | |
enumerable: false, | |
set: createArraySetter(0), | |
get: createArrayGetter(0) | |
}; | |
function createArrayBufferItem(index) { | |
var set = createArraySetter(index); | |
var get = createArrayGetter(index); | |
Object.defineProperty(ObservableArray.prototype, "" + index, { | |
enumerable: false, | |
configurable: true, | |
set: set, get: get | |
}); | |
} | |
function createArraySetter(index) { | |
return function (newValue) { | |
var adm = this.$mobx; | |
var values = adm.values; | |
if (index < values.length) { | |
checkIfStateModificationsAreAllowed(adm.atom); | |
var oldValue = values[index]; | |
if (hasInterceptors(adm)) { | |
var change = interceptChange(adm, { | |
type: "update", | |
object: adm.array, | |
index: index, newValue: newValue | |
}); | |
if (!change) | |
return; | |
newValue = change.newValue; | |
} | |
newValue = adm.enhancer(newValue, oldValue); | |
var changed = newValue !== oldValue; | |
if (changed) { | |
values[index] = newValue; | |
adm.notifyArrayChildUpdate(index, newValue, oldValue); | |
} | |
} | |
else if (index === values.length) { | |
adm.spliceWithArray(index, 0, [newValue]); | |
} | |
else | |
throw new Error("[mobx.array] Index out of bounds, " + index + " is larger than " + values.length); | |
}; | |
} | |
function createArrayGetter(index) { | |
return function () { | |
var impl = this.$mobx; | |
if (impl) { | |
if (index < impl.values.length) { | |
impl.atom.reportObserved(); | |
return impl.values[index]; | |
} | |
console.warn("[mobx.array] Attempt to read an array index (" + index + ") that is out of bounds (" + impl.values.length + "). Please check length first. Out of bound indices will not be tracked by MobX"); | |
} | |
return undefined; | |
}; | |
} | |
function reserveArrayBuffer(max) { | |
for (var index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max; index++) | |
createArrayBufferItem(index); | |
OBSERVABLE_ARRAY_BUFFER_SIZE = max; | |
} | |
reserveArrayBuffer(1000); | |
var isObservableArrayAdministration = createInstanceofPredicate("ObservableArrayAdministration", ObservableArrayAdministration); | |
function isObservableArray(thing) { | |
return isObject(thing) && isObservableArrayAdministration(thing.$mobx); | |
} | |
exports.isObservableArray = isObservableArray; | |
var ObservableMapMarker = {}; | |
var ObservableMap = (function () { | |
function ObservableMap(initialData, enhancer, name) { | |
if (enhancer === void 0) { enhancer = deepEnhancer; } | |
if (name === void 0) { name = "ObservableMap@" + getNextId(); } | |
this.enhancer = enhancer; | |
this.name = name; | |
this.$mobx = ObservableMapMarker; | |
this._data = {}; | |
this._hasMap = {}; | |
this._keys = new ObservableArray(undefined, referenceEnhancer, this.name + ".keys()", true); | |
this.interceptors = null; | |
this.changeListeners = null; | |
this.merge(initialData); | |
} | |
ObservableMap.prototype._has = function (key) { | |
return typeof this._data[key] !== "undefined"; | |
}; | |
ObservableMap.prototype.has = function (key) { | |
if (!this.isValidKey(key)) | |
return false; | |
key = "" + key; | |
if (this._hasMap[key]) | |
return this._hasMap[key].get(); | |
return this._updateHasMapEntry(key, false).get(); | |
}; | |
ObservableMap.prototype.set = function (key, value) { | |
this.assertValidKey(key); | |
key = "" + key; | |
var hasKey = this._has(key); | |
if (hasInterceptors(this)) { | |
var change = interceptChange(this, { | |
type: hasKey ? "update" : "add", | |
object: this, | |
newValue: value, | |
name: key | |
}); | |
if (!change) | |
return this; | |
value = change.newValue; | |
} | |
if (hasKey) { | |
this._updateValue(key, value); | |
} | |
else { | |
this._addValue(key, value); | |
} | |
return this; | |
}; | |
ObservableMap.prototype.delete = function (key) { | |
var _this = this; | |
this.assertValidKey(key); | |
key = "" + key; | |
if (hasInterceptors(this)) { | |
var change = interceptChange(this, { | |
type: "delete", | |
object: this, | |
name: key | |
}); | |
if (!change) | |
return false; | |
} | |
if (this._has(key)) { | |
var notifySpy = isSpyEnabled(); | |
var notify = hasListeners(this); | |
var change = notify || notifySpy ? { | |
type: "delete", | |
object: this, | |
oldValue: this._data[key].value, | |
name: key | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
runInTransaction(function () { | |
_this._keys.remove(key); | |
_this._updateHasMapEntry(key, false); | |
var observable = _this._data[key]; | |
observable.setNewValue(undefined); | |
_this._data[key] = undefined; | |
}); | |
if (notify) | |
notifyListeners(this, change); | |
if (notifySpy) | |
spyReportEnd(); | |
return true; | |
} | |
return false; | |
}; | |
ObservableMap.prototype._updateHasMapEntry = function (key, value) { | |
var entry = this._hasMap[key]; | |
if (entry) { | |
entry.setNewValue(value); | |
} | |
else { | |
entry = this._hasMap[key] = new ObservableValue(value, referenceEnhancer, this.name + "." + key + "?", false); | |
} | |
return entry; | |
}; | |
ObservableMap.prototype._updateValue = function (name, newValue) { | |
var observable = this._data[name]; | |
newValue = observable.prepareNewValue(newValue); | |
if (newValue !== UNCHANGED) { | |
var notifySpy = isSpyEnabled(); | |
var notify = hasListeners(this); | |
var change = notify || notifySpy ? { | |
type: "update", | |
object: this, | |
oldValue: observable.value, | |
name: name, newValue: newValue | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
observable.setNewValue(newValue); | |
if (notify) | |
notifyListeners(this, change); | |
if (notifySpy) | |
spyReportEnd(); | |
} | |
}; | |
ObservableMap.prototype._addValue = function (name, newValue) { | |
var _this = this; | |
runInTransaction(function () { | |
var observable = _this._data[name] = new ObservableValue(newValue, _this.enhancer, _this.name + "." + name, false); | |
newValue = observable.value; | |
_this._updateHasMapEntry(name, true); | |
_this._keys.push(name); | |
}); | |
var notifySpy = isSpyEnabled(); | |
var notify = hasListeners(this); | |
var change = notify || notifySpy ? { | |
type: "add", | |
object: this, | |
name: name, newValue: newValue | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
if (notify) | |
notifyListeners(this, change); | |
if (notifySpy) | |
spyReportEnd(); | |
}; | |
ObservableMap.prototype.get = function (key) { | |
key = "" + key; | |
if (this.has(key)) | |
return this._data[key].get(); | |
return undefined; | |
}; | |
ObservableMap.prototype.keys = function () { | |
return arrayAsIterator(this._keys.slice()); | |
}; | |
ObservableMap.prototype.values = function () { | |
return arrayAsIterator(this._keys.map(this.get, this)); | |
}; | |
ObservableMap.prototype.entries = function () { | |
var _this = this; | |
return arrayAsIterator(this._keys.map(function (key) { return [key, _this.get(key)]; })); | |
}; | |
ObservableMap.prototype.forEach = function (callback, thisArg) { | |
var _this = this; | |
this.keys().forEach(function (key) { return callback.call(thisArg, _this.get(key), key, _this); }); | |
}; | |
ObservableMap.prototype.merge = function (other) { | |
var _this = this; | |
if (isObservableMap(other)) { | |
other = other.toJS(); | |
} | |
runInTransaction(function () { | |
if (isPlainObject(other)) | |
Object.keys(other).forEach(function (key) { return _this.set(key, other[key]); }); | |
else if (Array.isArray(other)) | |
other.forEach(function (_a) { | |
var key = _a[0], value = _a[1]; | |
return _this.set(key, value); | |
}); | |
else if (isES6Map(other)) | |
other.forEach(function (value, key) { return _this.set(key, value); }); | |
else if (other !== null && other !== undefined) | |
fail("Cannot initialize map from " + other); | |
}); | |
return this; | |
}; | |
ObservableMap.prototype.clear = function () { | |
var _this = this; | |
runInTransaction(function () { | |
untracked(function () { | |
_this.keys().forEach(_this.delete, _this); | |
}); | |
}); | |
}; | |
ObservableMap.prototype.replace = function (values) { | |
var _this = this; | |
runInTransaction(function () { | |
_this.clear(); | |
_this.merge(values); | |
}); | |
return this; | |
}; | |
Object.defineProperty(ObservableMap.prototype, "size", { | |
get: function () { | |
return this._keys.length; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
ObservableMap.prototype.toJS = function () { | |
var _this = this; | |
var res = {}; | |
this.keys().forEach(function (key) { return res[key] = _this.get(key); }); | |
return res; | |
}; | |
ObservableMap.prototype.toJSON = function () { | |
return this.toJS(); | |
}; | |
ObservableMap.prototype.isValidKey = function (key) { | |
if (key === null || key === undefined) | |
return false; | |
if (typeof key === "string" || typeof key === "number" || typeof key === "boolean") | |
return true; | |
return false; | |
}; | |
ObservableMap.prototype.assertValidKey = function (key) { | |
if (!this.isValidKey(key)) | |
throw new Error("[mobx.map] Invalid key: '" + key + "', only strings, numbers and booleans are accepted as key in observable maps."); | |
}; | |
ObservableMap.prototype.toString = function () { | |
var _this = this; | |
return this.name + "[{ " + this.keys().map(function (key) { return key + ": " + ("" + _this.get(key)); }).join(", ") + " }]"; | |
}; | |
ObservableMap.prototype.observe = function (listener, fireImmediately) { | |
invariant(fireImmediately !== true, getMessage("m033")); | |
return registerListener(this, listener); | |
}; | |
ObservableMap.prototype.intercept = function (handler) { | |
return registerInterceptor(this, handler); | |
}; | |
return ObservableMap; | |
}()); | |
exports.ObservableMap = ObservableMap; | |
declareIterator(ObservableMap.prototype, function () { | |
return this.entries(); | |
}); | |
function map(initialValues) { | |
deprecated("`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead"); | |
return observable.map(initialValues); | |
} | |
exports.map = map; | |
var isObservableMap = createInstanceofPredicate("ObservableMap", ObservableMap); | |
exports.isObservableMap = isObservableMap; | |
var ObservableObjectAdministration = (function () { | |
function ObservableObjectAdministration(target, name) { | |
this.target = target; | |
this.name = name; | |
this.values = {}; | |
this.changeListeners = null; | |
this.interceptors = null; | |
} | |
ObservableObjectAdministration.prototype.observe = function (callback, fireImmediately) { | |
invariant(fireImmediately !== true, "`observe` doesn't support the fire immediately property for observable objects."); | |
return registerListener(this, callback); | |
}; | |
ObservableObjectAdministration.prototype.intercept = function (handler) { | |
return registerInterceptor(this, handler); | |
}; | |
return ObservableObjectAdministration; | |
}()); | |
function asObservableObject(target, name) { | |
if (isObservableObject(target)) | |
return target.$mobx; | |
invariant(Object.isExtensible(target), getMessage("m035")); | |
if (!isPlainObject(target)) | |
name = (target.constructor.name || "ObservableObject") + "@" + getNextId(); | |
if (!name) | |
name = "ObservableObject@" + getNextId(); | |
var adm = new ObservableObjectAdministration(target, name); | |
addHiddenFinalProp(target, "$mobx", adm); | |
return adm; | |
} | |
function defineObservablePropertyFromDescriptor(adm, propName, descriptor, defaultEnhancer) { | |
if (adm.values[propName]) { | |
invariant("value" in descriptor, "The property " + propName + " in " + adm.name + " is already observable, cannot redefine it as computed property"); | |
adm.target[propName] = descriptor.value; | |
return; | |
} | |
if ("value" in descriptor) { | |
if (isModifierDescriptor(descriptor.value)) { | |
var modifierDescriptor = descriptor.value; | |
defineObservableProperty(adm, propName, modifierDescriptor.initialValue, modifierDescriptor.enhancer); | |
} | |
else if (isAction(descriptor.value) && descriptor.value.autoBind === true) { | |
defineBoundAction(adm.target, propName, descriptor.value.originalFn); | |
} | |
else if (isComputedValue(descriptor.value)) { | |
defineComputedPropertyFromComputedValue(adm, propName, descriptor.value); | |
} | |
else { | |
defineObservableProperty(adm, propName, descriptor.value, defaultEnhancer); | |
} | |
} | |
else { | |
defineComputedProperty(adm, propName, descriptor.get, descriptor.set, false, true); | |
} | |
} | |
function defineObservableProperty(adm, propName, newValue, enhancer) { | |
assertPropertyConfigurable(adm.target, propName); | |
if (hasInterceptors(adm)) { | |
var change = interceptChange(adm, { | |
object: adm.target, | |
name: propName, | |
type: "add", | |
newValue: newValue | |
}); | |
if (!change) | |
return; | |
newValue = change.newValue; | |
} | |
var observable = adm.values[propName] = new ObservableValue(newValue, enhancer, adm.name + "." + propName, false); | |
newValue = observable.value; | |
Object.defineProperty(adm.target, propName, generateObservablePropConfig(propName)); | |
notifyPropertyAddition(adm, adm.target, propName, newValue); | |
} | |
function defineComputedProperty(adm, propName, getter, setter, compareStructural, asInstanceProperty) { | |
if (asInstanceProperty) | |
assertPropertyConfigurable(adm.target, propName); | |
adm.values[propName] = new ComputedValue(getter, adm.target, compareStructural, adm.name + "." + propName, setter); | |
if (asInstanceProperty) { | |
Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName)); | |
} | |
} | |
function defineComputedPropertyFromComputedValue(adm, propName, computedValue) { | |
var name = adm.name + "." + propName; | |
computedValue.name = name; | |
if (!computedValue.scope) | |
computedValue.scope = adm.target; | |
adm.values[propName] = computedValue; | |
Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName)); | |
} | |
var observablePropertyConfigs = {}; | |
var computedPropertyConfigs = {}; | |
function generateObservablePropConfig(propName) { | |
var config = observablePropertyConfigs[propName]; | |
if (config) | |
return config; | |
return observablePropertyConfigs[propName] = { | |
configurable: true, | |
enumerable: true, | |
get: function () { | |
return this.$mobx.values[propName].get(); | |
}, | |
set: function (v) { | |
setPropertyValue(this, propName, v); | |
} | |
}; | |
} | |
function generateComputedPropConfig(propName) { | |
var config = computedPropertyConfigs[propName]; | |
if (config) | |
return config; | |
return computedPropertyConfigs[propName] = { | |
configurable: true, | |
enumerable: false, | |
get: function () { | |
return this.$mobx.values[propName].get(); | |
}, | |
set: function (v) { | |
return this.$mobx.values[propName].set(v); | |
} | |
}; | |
} | |
function setPropertyValue(instance, name, newValue) { | |
var adm = instance.$mobx; | |
var observable = adm.values[name]; | |
if (hasInterceptors(adm)) { | |
var change = interceptChange(adm, { | |
type: "update", | |
object: instance, | |
name: name, newValue: newValue | |
}); | |
if (!change) | |
return; | |
newValue = change.newValue; | |
} | |
newValue = observable.prepareNewValue(newValue); | |
if (newValue !== UNCHANGED) { | |
var notify = hasListeners(adm); | |
var notifySpy = isSpyEnabled(); | |
var change = notify || notifySpy ? { | |
type: "update", | |
object: instance, | |
oldValue: observable.value, | |
name: name, newValue: newValue | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
observable.setNewValue(newValue); | |
if (notify) | |
notifyListeners(adm, change); | |
if (notifySpy) | |
spyReportEnd(); | |
} | |
} | |
function notifyPropertyAddition(adm, object, name, newValue) { | |
var notify = hasListeners(adm); | |
var notifySpy = isSpyEnabled(); | |
var change = notify || notifySpy ? { | |
type: "add", | |
object: object, name: name, newValue: newValue | |
} : null; | |
if (notifySpy) | |
spyReportStart(change); | |
if (notify) | |
notifyListeners(adm, change); | |
if (notifySpy) | |
spyReportEnd(); | |
} | |
var isObservableObjectAdministration = createInstanceofPredicate("ObservableObjectAdministration", ObservableObjectAdministration); | |
function isObservableObject(thing) { | |
if (isObject(thing)) { | |
runLazyInitializers(thing); | |
return isObservableObjectAdministration(thing.$mobx); | |
} | |
return false; | |
} | |
exports.isObservableObject = isObservableObject; | |
var UNCHANGED = {}; | |
var ObservableValue = (function (_super) { | |
__extends(ObservableValue, _super); | |
function ObservableValue(value, enhancer, name, notifySpy) { | |
if (name === void 0) { name = "ObservableValue@" + getNextId(); } | |
if (notifySpy === void 0) { notifySpy = true; } | |
var _this = _super.call(this, name) || this; | |
_this.enhancer = enhancer; | |
_this.hasUnreportedChange = false; | |
_this.value = enhancer(value, undefined, name); | |
if (notifySpy && isSpyEnabled()) { | |
spyReport({ type: "create", object: _this, newValue: _this.value }); | |
} | |
return _this; | |
} | |
ObservableValue.prototype.set = function (newValue) { | |
var oldValue = this.value; | |
newValue = this.prepareNewValue(newValue); | |
if (newValue !== UNCHANGED) { | |
var notifySpy = isSpyEnabled(); | |
if (notifySpy) { | |
spyReportStart({ | |
type: "update", | |
object: this, | |
newValue: newValue, oldValue: oldValue | |
}); | |
} | |
this.setNewValue(newValue); | |
if (notifySpy) | |
spyReportEnd(); | |
} | |
}; | |
ObservableValue.prototype.prepareNewValue = function (newValue) { | |
checkIfStateModificationsAreAllowed(this); | |
if (hasInterceptors(this)) { | |
var change = interceptChange(this, { object: this, type: "update", newValue: newValue }); | |
if (!change) | |
return UNCHANGED; | |
newValue = change.newValue; | |
} | |
newValue = this.enhancer(newValue, this.value, this.name); | |
return this.value !== newValue | |
? newValue | |
: UNCHANGED; | |
}; | |
ObservableValue.prototype.setNewValue = function (newValue) { | |
var oldValue = this.value; | |
this.value = newValue; | |
this.reportChanged(); | |
if (hasListeners(this)) { | |
notifyListeners(this, { | |
type: "update", | |
object: this, | |
newValue: newValue, | |
oldValue: oldValue | |
}); | |
} | |
}; | |
ObservableValue.prototype.get = function () { | |
this.reportObserved(); | |
return this.value; | |
}; | |
ObservableValue.prototype.intercept = function (handler) { | |
return registerInterceptor(this, handler); | |
}; | |
ObservableValue.prototype.observe = function (listener, fireImmediately) { | |
if (fireImmediately) | |
listener({ | |
object: this, | |
type: "update", | |
newValue: this.value, | |
oldValue: undefined | |
}); | |
return registerListener(this, listener); | |
}; | |
ObservableValue.prototype.toJSON = function () { | |
return this.get(); | |
}; | |
ObservableValue.prototype.toString = function () { | |
return this.name + "[" + this.value + "]"; | |
}; | |
ObservableValue.prototype.valueOf = function () { | |
return toPrimitive(this.get()); | |
}; | |
return ObservableValue; | |
}(BaseAtom)); | |
ObservableValue.prototype[primitiveSymbol()] = ObservableValue.prototype.valueOf; | |
var isObservableValue = createInstanceofPredicate("ObservableValue", ObservableValue); | |
function getAtom(thing, property) { | |
if (typeof thing === "object" && thing !== null) { | |
if (isObservableArray(thing)) { | |
invariant(property === undefined, getMessage("m036")); | |
return thing.$mobx.atom; | |
} | |
if (isObservableMap(thing)) { | |
var anyThing = thing; | |
if (property === undefined) | |
return getAtom(anyThing._keys); | |
var observable_2 = anyThing._data[property] || anyThing._hasMap[property]; | |
invariant(!!observable_2, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'"); | |
return observable_2; | |
} | |
runLazyInitializers(thing); | |
if (isObservableObject(thing)) { | |
if (!property) | |
return fail("please specify a property"); | |
var observable_3 = thing.$mobx.values[property]; | |
invariant(!!observable_3, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'"); | |
return observable_3; | |
} | |
if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) { | |
return thing; | |
} | |
} | |
else if (typeof thing === "function") { | |
if (isReaction(thing.$mobx)) { | |
return thing.$mobx; | |
} | |
} | |
return fail("Cannot obtain atom from " + thing); | |
} | |
function getAdministration(thing, property) { | |
invariant(thing, "Expecting some object"); | |
if (property !== undefined) | |
return getAdministration(getAtom(thing, property)); | |
if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) | |
return thing; | |
if (isObservableMap(thing)) | |
return thing; | |
runLazyInitializers(thing); | |
if (thing.$mobx) | |
return thing.$mobx; | |
invariant(false, "Cannot obtain administration from " + thing); | |
} | |
function getDebugName(thing, property) { | |
var named; | |
if (property !== undefined) | |
named = getAtom(thing, property); | |
else if (isObservableObject(thing) || isObservableMap(thing)) | |
named = getAdministration(thing); | |
else | |
named = getAtom(thing); | |
return named.name; | |
} | |
function createClassPropertyDecorator(onInitialize, get, set, enumerable, allowCustomArguments) { | |
function classPropertyDecorator(target, key, descriptor, customArgs, argLen) { | |
invariant(allowCustomArguments || quacksLikeADecorator(arguments), "This function is a decorator, but it wasn't invoked like a decorator"); | |
if (!descriptor) { | |
var newDescriptor = { | |
enumerable: enumerable, | |
configurable: true, | |
get: function () { | |
if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true) | |
typescriptInitializeProperty(this, key, undefined, onInitialize, customArgs, descriptor); | |
return get.call(this, key); | |
}, | |
set: function (v) { | |
if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true) { | |
typescriptInitializeProperty(this, key, v, onInitialize, customArgs, descriptor); | |
} | |
else { | |
set.call(this, key, v); | |
} | |
} | |
}; | |
if (arguments.length < 3 || arguments.length === 5 && argLen < 3) { | |
Object.defineProperty(target, key, newDescriptor); | |
} | |
return newDescriptor; | |
} | |
else { | |
if (!hasOwnProperty(target, "__mobxLazyInitializers")) { | |
addHiddenProp(target, "__mobxLazyInitializers", (target.__mobxLazyInitializers && target.__mobxLazyInitializers.slice()) || []); | |
} | |
var value_1 = descriptor.value, initializer_1 = descriptor.initializer; | |
target.__mobxLazyInitializers.push(function (instance) { | |
onInitialize(instance, key, (initializer_1 ? initializer_1.call(instance) : value_1), customArgs, descriptor); | |
}); | |
return { | |
enumerable: enumerable, configurable: true, | |
get: function () { | |
if (this.__mobxDidRunLazyInitializers !== true) | |
runLazyInitializers(this); | |
return get.call(this, key); | |
}, | |
set: function (v) { | |
if (this.__mobxDidRunLazyInitializers !== true) | |
runLazyInitializers(this); | |
set.call(this, key, v); | |
} | |
}; | |
} | |
} | |
if (allowCustomArguments) { | |
return function () { | |
if (quacksLikeADecorator(arguments)) | |
return classPropertyDecorator.apply(null, arguments); | |
var outerArgs = arguments; | |
var argLen = arguments.length; | |
return function (target, key, descriptor) { return classPropertyDecorator(target, key, descriptor, outerArgs, argLen); }; | |
}; | |
} | |
return classPropertyDecorator; | |
} | |
function typescriptInitializeProperty(instance, key, v, onInitialize, customArgs, baseDescriptor) { | |
if (!hasOwnProperty(instance, "__mobxInitializedProps")) | |
addHiddenProp(instance, "__mobxInitializedProps", {}); | |
instance.__mobxInitializedProps[key] = true; | |
onInitialize(instance, key, v, customArgs, baseDescriptor); | |
} | |
function runLazyInitializers(instance) { | |
if (instance.__mobxDidRunLazyInitializers === true) | |
return; | |
if (instance.__mobxLazyInitializers) { | |
addHiddenProp(instance, "__mobxDidRunLazyInitializers", true); | |
instance.__mobxDidRunLazyInitializers && instance.__mobxLazyInitializers.forEach(function (initializer) { return initializer(instance); }); | |
} | |
} | |
function quacksLikeADecorator(args) { | |
return (args.length === 2 || args.length === 3) && typeof args[1] === "string"; | |
} | |
function iteratorSymbol() { | |
return (typeof Symbol === "function" && Symbol.iterator) || "@@iterator"; | |
} | |
var IS_ITERATING_MARKER = "__$$iterating"; | |
function arrayAsIterator(array) { | |
invariant(array[IS_ITERATING_MARKER] !== true, "Illegal state: cannot recycle array as iterator"); | |
addHiddenFinalProp(array, IS_ITERATING_MARKER, true); | |
var idx = -1; | |
addHiddenFinalProp(array, "next", function next() { | |
idx++; | |
return { | |
done: idx >= this.length, | |
value: idx < this.length ? this[idx] : undefined | |
}; | |
}); | |
return array; | |
} | |
function declareIterator(prototType, iteratorFactory) { | |
addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory); | |
} | |
var messages = { | |
"m001": "It is not allowed to assign new values to @action fields", | |
"m002": "`runInAction` expects a function", | |
"m003": "`runInAction` expects a function without arguments", | |
"m004": "autorun expects a function", | |
"m005": "Warning: attempted to pass an action to autorun. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.", | |
"m006": "Warning: attempted to pass an action to autorunAsync. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.", | |
"m007": "reaction only accepts 2 or 3 arguments. If migrating from MobX 2, please provide an options object", | |
"m008": "wrapping reaction expression in `asReference` is no longer supported, use options object instead", | |
"m009": "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property.", | |
"m010": "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'", | |
"m011": "First argument to `computed` should be an expression. If using computed as decorator, don't pass it arguments", | |
"m012": "computed takes one or two arguments if used as function", | |
"m013": "[mobx.expr] 'expr' should only be used inside other reactive functions.", | |
"m014": "extendObservable expected 2 or more arguments", | |
"m015": "extendObservable expects an object as first argument", | |
"m016": "extendObservable should not be used on maps, use map.merge instead", | |
"m017": "all arguments of extendObservable should be objects", | |
"m018": "extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540", | |
"m019": "[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead.", | |
"m020": "modifiers can only be used for individual object properties", | |
"m021": "observable expects zero or one arguments", | |
"m022": "@observable can not be used on getters, use @computed instead", | |
"m023": "Using `transaction` is deprecated, use `runInAction` or `(@)action` instead.", | |
"m024": "whyRun() can only be used if a derivation is active, or by passing an computed value / reaction explicitly. If you invoked whyRun from inside a computation; the computation is currently suspended but re-evaluating because somebody requested its value.", | |
"m025": "whyRun can only be used on reactions and computed values", | |
"m026": "`action` can only be invoked on functions", | |
"m028": "It is not allowed to set `useStrict` when a derivation is running", | |
"m029": "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row", | |
"m030a": "Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: ", | |
"m030b": "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, the render function of a React component? Tried to modify: ", | |
"m031": "Computed values are not allowed to not cause side effects by changing observables that are already being observed. Tried to modify: ", | |
"m032": "* This computation is suspended (not in use by any reaction) and won't run automatically.\n Didn't expect this computation to be suspended at this point?\n 1. Make sure this computation is used by a reaction (reaction, autorun, observer).\n 2. Check whether you are using this computation synchronously (in the same stack as they reaction that needs it).", | |
"m033": "`observe` doesn't support the fire immediately property for observable maps.", | |
"m034": "`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead", | |
"m035": "Cannot make the designated object observable; it is not extensible", | |
"m036": "It is not possible to get index atoms from arrays", | |
"m037": "Hi there! I'm sorry you have just run into an exception.\nIf your debugger ends up here, know that some reaction (like the render() of an observer component, autorun or reaction)\nthrew an exception and that mobx caught it, to avoid that it brings the rest of your application down.\nThe original cause of the exception (the code that caused this reaction to run (again)), is still in the stack.\n\nHowever, more interesting is the actual stack trace of the error itself.\nHopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\nSee `error.stack` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\nThat stack is more interesting than the stack of this console.error itself.\n\nIf the exception you see is an exception you created yourself, make sure to use `throw new Error(\"Oops\")` instead of `throw \"Oops\"`,\nbecause the javascript environment will only preserve the original stack trace in the first form.\n\nYou can also make sure the debugger pauses the next time this very same exception is thrown by enabling \"Pause on caught exception\".\n(Note that it might pause on many other, unrelated exception as well).\n\nIf that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n", | |
"m038": "Missing items in this list?\n 1. Check whether all used values are properly marked as observable (use isObservable to verify)\n 2. Make sure you didn't dereference values too early. MobX observes props, not primitives. E.g: use 'person.name' instead of 'name' in your computation.\n" | |
}; | |
function getMessage(id) { | |
return messages[id]; | |
} | |
var EMPTY_ARRAY = []; | |
Object.freeze(EMPTY_ARRAY); | |
function getGlobal() { | |
return global; | |
} | |
function getNextId() { | |
return ++globalState.mobxGuid; | |
} | |
function fail(message, thing) { | |
invariant(false, message, thing); | |
throw "X"; | |
} | |
function invariant(check, message, thing) { | |
if (!check) | |
throw new Error("[mobx] Invariant failed: " + message + (thing ? " in '" + thing + "'" : "")); | |
} | |
var deprecatedMessages = []; | |
function deprecated(msg) { | |
if (deprecatedMessages.indexOf(msg) !== -1) | |
return false; | |
deprecatedMessages.push(msg); | |
console.error("[mobx] Deprecated: " + msg); | |
return true; | |
} | |
function once(func) { | |
var invoked = false; | |
return function () { | |
if (invoked) | |
return; | |
invoked = true; | |
return func.apply(this, arguments); | |
}; | |
} | |
var noop = function () { }; | |
function unique(list) { | |
var res = []; | |
list.forEach(function (item) { | |
if (res.indexOf(item) === -1) | |
res.push(item); | |
}); | |
return res; | |
} | |
function joinStrings(things, limit, separator) { | |
if (limit === void 0) { limit = 100; } | |
if (separator === void 0) { separator = " - "; } | |
if (!things) | |
return ""; | |
var sliced = things.slice(0, limit); | |
return "" + sliced.join(separator) + (things.length > limit ? " (... and " + (things.length - limit) + "more)" : ""); | |
} | |
function isObject(value) { | |
return value !== null && typeof value === "object"; | |
} | |
function isPlainObject(value) { | |
if (value === null || typeof value !== "object") | |
return false; | |
var proto = Object.getPrototypeOf(value); | |
return proto === Object.prototype || proto === null; | |
} | |
function objectAssign() { | |
var res = arguments[0]; | |
for (var i = 1, l = arguments.length; i < l; i++) { | |
var source = arguments[i]; | |
for (var key in source) | |
if (hasOwnProperty(source, key)) { | |
res[key] = source[key]; | |
} | |
} | |
return res; | |
} | |
function valueDidChange(compareStructural, oldValue, newValue) { | |
if (typeof oldValue === 'number' && isNaN(oldValue)) { | |
return typeof newValue !== 'number' || !isNaN(newValue); | |
} | |
return compareStructural | |
? !deepEqual(oldValue, newValue) | |
: oldValue !== newValue; | |
} | |
var prototypeHasOwnProperty = Object.prototype.hasOwnProperty; | |
function hasOwnProperty(object, propName) { | |
return prototypeHasOwnProperty.call(object, propName); | |
} | |
function makeNonEnumerable(object, propNames) { | |
for (var i = 0; i < propNames.length; i++) { | |
addHiddenProp(object, propNames[i], object[propNames[i]]); | |
} | |
} | |
function addHiddenProp(object, propName, value) { | |
Object.defineProperty(object, propName, { | |
enumerable: false, | |
writable: true, | |
configurable: true, | |
value: value | |
}); | |
} | |
function addHiddenFinalProp(object, propName, value) { | |
Object.defineProperty(object, propName, { | |
enumerable: false, | |
writable: false, | |
configurable: true, | |
value: value | |
}); | |
} | |
function isPropertyConfigurable(object, prop) { | |
var descriptor = Object.getOwnPropertyDescriptor(object, prop); | |
return !descriptor || (descriptor.configurable !== false && descriptor.writable !== false); | |
} | |
function assertPropertyConfigurable(object, prop) { | |
invariant(isPropertyConfigurable(object, prop), "Cannot make property '" + prop + "' observable, it is not configurable and writable in the target object"); | |
} | |
function getEnumerableKeys(obj) { | |
var res = []; | |
for (var key in obj) | |
res.push(key); | |
return res; | |
} | |
function deepEqual(a, b) { | |
if (a === null && b === null) | |
return true; | |
if (a === undefined && b === undefined) | |
return true; | |
if (typeof a !== "object") | |
return a === b; | |
var aIsArray = isArrayLike(a); | |
var aIsMap = isMapLike(a); | |
if (aIsArray !== isArrayLike(b)) { | |
return false; | |
} | |
else if (aIsMap !== isMapLike(b)) { | |
return false; | |
} | |
else if (aIsArray) { | |
if (a.length !== b.length) | |
return false; | |
for (var i = a.length - 1; i >= 0; i--) | |
if (!deepEqual(a[i], b[i])) | |
return false; | |
return true; | |
} | |
else if (aIsMap) { | |
if (a.size !== b.size) | |
return false; | |
var equals_1 = true; | |
a.forEach(function (value, key) { | |
equals_1 = equals_1 && deepEqual(b.get(key), value); | |
}); | |
return equals_1; | |
} | |
else if (typeof a === "object" && typeof b === "object") { | |
if (a === null || b === null) | |
return false; | |
if (isMapLike(a) && isMapLike(b)) { | |
if (a.size !== b.size) | |
return false; | |
return deepEqual(observable.shallowMap(a).entries(), observable.shallowMap(b).entries()); | |
} | |
if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length) | |
return false; | |
for (var prop in a) { | |
if (!(prop in b)) | |
return false; | |
if (!deepEqual(a[prop], b[prop])) | |
return false; | |
} | |
return true; | |
} | |
return false; | |
} | |
function createInstanceofPredicate(name, clazz) { | |
var propName = "isMobX" + name; | |
clazz.prototype[propName] = true; | |
return function (x) { | |
return isObject(x) && x[propName] === true; | |
}; | |
} | |
function isArrayLike(x) { | |
return Array.isArray(x) || isObservableArray(x); | |
} | |
exports.isArrayLike = isArrayLike; | |
function isMapLike(x) { | |
return isES6Map(x) || isObservableMap(x); | |
} | |
function isES6Map(thing) { | |
if (getGlobal().Map !== undefined && thing instanceof getGlobal().Map) | |
return true; | |
return false; | |
} | |
function primitiveSymbol() { | |
return (typeof Symbol === "function" && Symbol.toPrimitive) || "@@toPrimitive"; | |
} | |
function toPrimitive(value) { | |
return value === null ? null : typeof value === "object" ? ("" + value) : value; | |
} | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{}]},{},[]) | |
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImxpYi9tb2J4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xufTtcbnJlZ2lzdGVyR2xvYmFscygpO1xuZXhwb3J0cy5leHRyYXMgPSB7XG4gICAgYWxsb3dTdGF0ZUNoYW5nZXM6IGFsbG93U3RhdGVDaGFuZ2VzLFxuICAgIGRlZXBFcXVhbDogZGVlcEVxdWFsLFxuICAgIGdldEF0b206IGdldEF0b20sXG4gICAgZ2V0RGVidWdOYW1lOiBnZXREZWJ1Z05hbWUsXG4gICAgZ2V0RGVwZW5kZW5jeVRyZWU6IGdldERlcGVuZGVuY3lUcmVlLFxuICAgIGdldEFkbWluaXN0cmF0aW9uOiBnZXRBZG1pbmlzdHJhdGlvbixcbiAgICBnZXRHbG9iYWxTdGF0ZTogZ2V0R2xvYmFsU3RhdGUsXG4gICAgZ2V0T2JzZXJ2ZXJUcmVlOiBnZXRPYnNlcnZlclRyZWUsXG4gICAgaXNDb21wdXRpbmdEZXJpdmF0aW9uOiBpc0NvbXB1dGluZ0Rlcml2YXRpb24sXG4gICAgaXNTcHlFbmFibGVkOiBpc1NweUVuYWJsZWQsXG4gICAgb25SZWFjdGlvbkVycm9yOiBvblJlYWN0aW9uRXJyb3IsXG4gICAgcmVzZXRHbG9iYWxTdGF0ZTogcmVzZXRHbG9iYWxTdGF0ZSxcbiAgICBzaGFyZUdsb2JhbFN0YXRlOiBzaGFyZUdsb2JhbFN0YXRlLFxuICAgIHNweVJlcG9ydDogc3B5UmVwb3J0LFxuICAgIHNweVJlcG9ydEVuZDogc3B5UmVwb3J0RW5kLFxuICAgIHNweVJlcG9ydFN0YXJ0OiBzcHlSZXBvcnRTdGFydCxcbiAgICBzZXRSZWFjdGlvblNjaGVkdWxlcjogc2V0UmVhY3Rpb25TY2hlZHVsZXJcbn07XG5pZiAodHlwZW9mIF9fTU9CWF9ERVZUT09MU19HTE9CQUxfSE9PS19fID09PSBcIm9iamVjdFwiKSB7XG4gICAgX19NT0JYX0RFVlRPT0xTX0dMT0JBTF9IT09LX18uaW5qZWN0TW9ieChtb2R1bGUuZXhwb3J0cyk7XG59XG52YXIgYWN0aW9uRmllbGREZWNvcmF0b3IgPSBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKGZ1bmN0aW9uICh0YXJnZXQsIGtleSwgdmFsdWUsIGFyZ3MsIG9yaWdpbmFsRGVzY3JpcHRvcikge1xuICAgIHZhciBhY3Rpb25OYW1lID0gKGFyZ3MgJiYgYXJncy5sZW5ndGggPT09IDEpID8gYXJnc1swXSA6ICh2YWx1ZS5uYW1lIHx8IGtleSB8fCBcIjx1bm5hbWVkIGFjdGlvbj5cIik7XG4gICAgdmFyIHdyYXBwZWRBY3Rpb24gPSBhY3Rpb24oYWN0aW9uTmFtZSwgdmFsdWUpO1xuICAgIGFkZEhpZGRlblByb3AodGFyZ2V0LCBrZXksIHdyYXBwZWRBY3Rpb24pO1xufSwgZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzW2tleV07XG59LCBmdW5jdGlvbiAoKSB7XG4gICAgaW52YXJpYW50KGZhbHNlLCBnZXRNZXNzYWdlKFwibTAwMVwiKSk7XG59LCBmYWxzZSwgdHJ1ZSk7XG52YXIgYm91bmRBY3Rpb25EZWNvcmF0b3IgPSBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKGZ1bmN0aW9uICh0YXJnZXQsIGtleSwgdmFsdWUpIHtcbiAgICBkZWZpbmVCb3VuZEFjdGlvbih0YXJnZXQsIGtleSwgdmFsdWUpO1xufSwgZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzW2tleV07XG59LCBmdW5jdGlvbiAoKSB7XG4gICAgaW52YXJpYW50KGZhbHNlLCBnZXRNZXNzYWdlKFwibTAwMVwiKSk7XG59LCBmYWxzZSwgZmFsc2UpO1xudmFyIGFjdGlvbiA9IGZ1bmN0aW9uIGFjdGlvbihhcmcxLCBhcmcyLCBhcmczLCBhcmc0KSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUFjdGlvbihhcmcxLm5hbWUgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCIsIGFyZzEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiBhcmcyID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHJldHVybiBjcmVhdGVBY3Rpb24oYXJnMSwgYXJnMik7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpXG4gICAgICAgIHJldHVybiBuYW1lZEFjdGlvbkRlY29yYXRvcihhcmcxKTtcbiAgICByZXR1cm4gbmFtZWRBY3Rpb25EZWNvcmF0b3IoYXJnMikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbn07XG5leHBvcnRzLmFjdGlvbiA9IGFjdGlvbjtcbmFjdGlvbi5ib3VuZCA9IGZ1bmN0aW9uIGJvdW5kQWN0aW9uKGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB2YXIgYWN0aW9uXzEgPSBjcmVhdGVBY3Rpb24oXCI8bm90IHlldCBib3VuZCBhY3Rpb24+XCIsIGFyZzEpO1xuICAgICAgICBhY3Rpb25fMS5hdXRvQmluZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBhY3Rpb25fMTtcbiAgICB9XG4gICAgcmV0dXJuIGJvdW5kQWN0aW9uRGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG59O1xuZnVuY3Rpb24gbmFtZWRBY3Rpb25EZWNvcmF0b3IobmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBwcm9wLCBkZXNjcmlwdG9yKSB7XG4gICAgICAgIGlmIChkZXNjcmlwdG9yICYmIHR5cGVvZiBkZXNjcmlwdG9yLnZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBjcmVhdGVBY3Rpb24obmFtZSwgZGVzY3JpcHRvci52YWx1ZSk7XG4gICAgICAgICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3Rpb25GaWVsZERlY29yYXRvcihuYW1lKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG59XG5mdW5jdGlvbiBydW5JbkFjdGlvbihhcmcxLCBhcmcyLCBhcmczKSB7XG4gICAgdmFyIGFjdGlvbk5hbWUgPSB0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIiA/IGFyZzEgOiBhcmcxLm5hbWUgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCI7XG4gICAgdmFyIGZuID0gdHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIiA/IGFyZzEgOiBhcmcyO1xuICAgIHZhciBzY29wZSA9IHR5cGVvZiBhcmcxID09PSBcImZ1bmN0aW9uXCIgPyBhcmcyIDogYXJnMztcbiAgICBpbnZhcmlhbnQodHlwZW9mIGZuID09PSBcImZ1bmN0aW9uXCIsIGdldE1lc3NhZ2UoXCJtMDAyXCIpKTtcbiAgICBpbnZhcmlhbnQoZm4ubGVuZ3RoID09PSAwLCBnZXRNZXNzYWdlKFwibTAwM1wiKSk7XG4gICAgaW52YXJpYW50KHR5cGVvZiBhY3Rpb25OYW1lID09PSBcInN0cmluZ1wiICYmIGFjdGlvbk5hbWUubGVuZ3RoID4gMCwgXCJhY3Rpb25zIHNob3VsZCBoYXZlIHZhbGlkIG5hbWVzLCBnb3Q6ICdcIiArIGFjdGlvbk5hbWUgKyBcIidcIik7XG4gICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHNjb3BlLCB1bmRlZmluZWQpO1xufVxuZXhwb3J0cy5ydW5JbkFjdGlvbiA9IHJ1bkluQWN0aW9uO1xuZnVuY3Rpb24gaXNBY3Rpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdHlwZW9mIHRoaW5nID09PSBcImZ1bmN0aW9uXCIgJiYgdGhpbmcuaXNNb2J4QWN0aW9uID09PSB0cnVlO1xufVxuZXhwb3J0cy5pc0FjdGlvbiA9IGlzQWN0aW9uO1xuZnVuY3Rpb24gZGVmaW5lQm91bmRBY3Rpb24odGFyZ2V0LCBwcm9wZXJ0eU5hbWUsIGZuKSB7XG4gICAgdmFyIHJlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24ocHJvcGVydHlOYW1lLCBmbiwgdGFyZ2V0LCBhcmd1bWVudHMpO1xuICAgIH07XG4gICAgcmVzLmlzTW9ieEFjdGlvbiA9IHRydWU7XG4gICAgYWRkSGlkZGVuUHJvcCh0YXJnZXQsIHByb3BlcnR5TmFtZSwgcmVzKTtcbn1cbmZ1bmN0aW9uIGF1dG9ydW4oYXJnMSwgYXJnMiwgYXJnMykge1xuICAgIHZhciBuYW1lLCB2aWV3LCBzY29wZTtcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbmFtZSA9IGFyZzE7XG4gICAgICAgIHZpZXcgPSBhcmcyO1xuICAgICAgICBzY29wZSA9IGFyZzM7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYW1lID0gYXJnMS5uYW1lIHx8IChcIkF1dG9ydW5AXCIgKyBnZXROZXh0SWQoKSk7XG4gICAgICAgIHZpZXcgPSBhcmcxO1xuICAgICAgICBzY29wZSA9IGFyZzI7XG4gICAgfVxuICAgIGludmFyaWFudCh0eXBlb2YgdmlldyA9PT0gXCJmdW5jdGlvblwiLCBnZXRNZXNzYWdlKFwibTAwNFwiKSk7XG4gICAgaW52YXJpYW50KGlzQWN0aW9uKHZpZXcpID09PSBmYWxzZSwgZ2V0TWVzc2FnZShcIm0wMDVcIikpO1xuICAgIGlmIChzY29wZSlcbiAgICAgICAgdmlldyA9IHZpZXcuYmluZChzY29wZSk7XG4gICAgdmFyIHJlYWN0aW9uID0gbmV3IFJlYWN0aW9uKG5hbWUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50cmFjayhyZWFjdGlvblJ1bm5lcik7XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gcmVhY3Rpb25SdW5uZXIoKSB7XG4gICAgICAgIHZpZXcocmVhY3Rpb24pO1xuICAgIH1cbiAgICByZWFjdGlvbi5zY2hlZHVsZSgpO1xuICAgIHJldHVybiByZWFjdGlvbi5nZXREaXNwb3NlcigpO1xufVxuZXhwb3J0cy5hdXRvcnVuID0gYXV0b3J1bjtcbmZ1bmN0aW9uIHdoZW4oYXJnMSwgYXJnMiwgYXJnMywgYXJnNCkge1xuICAgIHZhciBuYW1lLCBwcmVkaWNhdGUsIGVmZmVjdCwgc2NvcGU7XG4gICAgaWYgKHR5cGVvZiBhcmcxID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG5hbWUgPSBhcmcxO1xuICAgICAgICBwcmVkaWNhdGUgPSBhcmcyO1xuICAgICAgICBlZmZlY3QgPSBhcmczO1xuICAgICAgICBzY29wZSA9IGFyZzQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYW1lID0gKFwiV2hlbkBcIiArIGdldE5leHRJZCgpKTtcbiAgICAgICAgcHJlZGljYXRlID0gYXJnMTtcbiAgICAgICAgZWZmZWN0ID0gYXJnMjtcbiAgICAgICAgc2NvcGUgPSBhcmczO1xuICAgIH1cbiAgICB2YXIgZGlzcG9zZXIgPSBhdXRvcnVuKG5hbWUsIGZ1bmN0aW9uIChyKSB7XG4gICAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChzY29wZSkpIHtcbiAgICAgICAgICAgIHIuZGlzcG9zZSgpO1xuICAgICAgICAgICAgdmFyIHByZXZVbnRyYWNrZWQgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgICAgICAgICAgZWZmZWN0LmNhbGwoc2NvcGUpO1xuICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVbnRyYWNrZWQpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGRpc3Bvc2VyO1xufVxuZXhwb3J0cy53aGVuID0gd2hlbjtcbmZ1bmN0aW9uIGF1dG9ydW5Bc3luYyhhcmcxLCBhcmcyLCBhcmczLCBhcmc0KSB7XG4gICAgdmFyIG5hbWUsIGZ1bmMsIGRlbGF5LCBzY29wZTtcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbmFtZSA9IGFyZzE7XG4gICAgICAgIGZ1bmMgPSBhcmcyO1xuICAgICAgICBkZWxheSA9IGFyZzM7XG4gICAgICAgIHNjb3BlID0gYXJnNDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIG5hbWUgPSBhcmcxLm5hbWUgfHwgKFwiQXV0b3J1bkFzeW5jQFwiICsgZ2V0TmV4dElkKCkpO1xuICAgICAgICBmdW5jID0gYXJnMTtcbiAgICAgICAgZGVsYXkgPSBhcmcyO1xuICAgICAgICBzY29wZSA9IGFyZzM7XG4gICAgfVxuICAgIGludmFyaWFudChpc0FjdGlvbihmdW5jKSA9PT0gZmFsc2UsIGdldE1lc3NhZ2UoXCJtMDA2XCIpKTtcbiAgICBpZiAoZGVsYXkgPT09IHZvaWQgMClcbiAgICAgICAgZGVsYXkgPSAxO1xuICAgIGlmIChzY29wZSlcbiAgICAgICAgZnVuYyA9IGZ1bmMuYmluZChzY29wZSk7XG4gICAgdmFyIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgdmFyIHIgPSBuZXcgUmVhY3Rpb24obmFtZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWlzU2NoZWR1bGVkKSB7XG4gICAgICAgICAgICBpc1NjaGVkdWxlZCA9IHRydWU7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpc1NjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICghci5pc0Rpc3Bvc2VkKVxuICAgICAgICAgICAgICAgICAgICByLnRyYWNrKHJlYWN0aW9uUnVubmVyKTtcbiAgICAgICAgICAgIH0sIGRlbGF5KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGZ1bmN0aW9uIHJlYWN0aW9uUnVubmVyKCkgeyBmdW5jKHIpOyB9XG4gICAgci5zY2hlZHVsZSgpO1xuICAgIHJldHVybiByLmdldERpc3Bvc2VyKCk7XG59XG5leHBvcnRzLmF1dG9ydW5Bc3luYyA9IGF1dG9ydW5Bc3luYztcbmZ1bmN0aW9uIHJlYWN0aW9uKGV4cHJlc3Npb24sIGVmZmVjdCwgYXJnMykge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMykge1xuICAgICAgICBmYWlsKGdldE1lc3NhZ2UoXCJtMDA3XCIpKTtcbiAgICB9XG4gICAgaWYgKGlzTW9kaWZpZXJEZXNjcmlwdG9yKGV4cHJlc3Npb24pKSB7XG4gICAgICAgIGZhaWwoZ2V0TWVzc2FnZShcIm0wMDhcIikpO1xuICAgIH1cbiAgICB2YXIgb3B0cztcbiAgICBpZiAodHlwZW9mIGFyZzMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgb3B0cyA9IGFyZzM7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBvcHRzID0ge307XG4gICAgfVxuICAgIG9wdHMubmFtZSA9IG9wdHMubmFtZSB8fCBleHByZXNzaW9uLm5hbWUgfHwgZWZmZWN0Lm5hbWUgfHwgKFwiUmVhY3Rpb25AXCIgKyBnZXROZXh0SWQoKSk7XG4gICAgb3B0cy5maXJlSW1tZWRpYXRlbHkgPSBhcmczID09PSB0cnVlIHx8IG9wdHMuZmlyZUltbWVkaWF0ZWx5ID09PSB0cnVlO1xuICAgIG9wdHMuZGVsYXkgPSBvcHRzLmRlbGF5IHx8IDA7XG4gICAgb3B0cy5jb21wYXJlU3RydWN0dXJhbCA9IG9wdHMuY29tcGFyZVN0cnVjdHVyYWwgfHwgb3B0cy5zdHJ1Y3QgfHwgZmFsc2U7XG4gICAgZWZmZWN0ID0gYWN0aW9uKG9wdHMubmFtZSwgb3B0cy5jb250ZXh0ID8gZWZmZWN0LmJpbmQob3B0cy5jb250ZXh0KSA6IGVmZmVjdCk7XG4gICAgaWYgKG9wdHMuY29udGV4dCkge1xuICAgICAgICBleHByZXNzaW9uID0gZXhwcmVzc2lvbi5iaW5kKG9wdHMuY29udGV4dCk7XG4gICAgfVxuICAgIHZhciBmaXJzdFRpbWUgPSB0cnVlO1xuICAgIHZhciBpc1NjaGVkdWxlZCA9IGZhbHNlO1xuICAgIHZhciBuZXh0VmFsdWU7XG4gICAgdmFyIHIgPSBuZXcgUmVhY3Rpb24ob3B0cy5uYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChvcHRzLmRlbGF5IDwgMSkge1xuICAgICAgICAgICAgcmVhY3Rpb25SdW5uZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaXNTY2hlZHVsZWQpIHtcbiAgICAgICAgICAgIGlzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVhY3Rpb25SdW5uZXIoKTtcbiAgICAgICAgICAgIH0sIG9wdHMuZGVsYXkpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gcmVhY3Rpb25SdW5uZXIoKSB7XG4gICAgICAgIGlmIChyLmlzRGlzcG9zZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHZhciBjaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIHIudHJhY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHYgPSBleHByZXNzaW9uKHIpO1xuICAgICAgICAgICAgY2hhbmdlZCA9IHZhbHVlRGlkQ2hhbmdlKG9wdHMuY29tcGFyZVN0cnVjdHVyYWwsIG5leHRWYWx1ZSwgdik7XG4gICAgICAgICAgICBuZXh0VmFsdWUgPSB2O1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGZpcnN0VGltZSAmJiBvcHRzLmZpcmVJbW1lZGlhdGVseSlcbiAgICAgICAgICAgIGVmZmVjdChuZXh0VmFsdWUsIHIpO1xuICAgICAgICBpZiAoIWZpcnN0VGltZSAmJiBjaGFuZ2VkID09PSB0cnVlKVxuICAgICAgICAgICAgZWZmZWN0KG5leHRWYWx1ZSwgcik7XG4gICAgICAgIGlmIChmaXJzdFRpbWUpXG4gICAgICAgICAgICBmaXJzdFRpbWUgPSBmYWxzZTtcbiAgICB9XG4gICAgci5zY2hlZHVsZSgpO1xuICAgIHJldHVybiByLmdldERpc3Bvc2VyKCk7XG59XG5leHBvcnRzLnJlYWN0aW9uID0gcmVhY3Rpb247XG5mdW5jdGlvbiBjcmVhdGVDb21wdXRlZERlY29yYXRvcihjb21wYXJlU3RydWN0dXJhbCkge1xuICAgIHJldHVybiBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKGZ1bmN0aW9uICh0YXJnZXQsIG5hbWUsIF8sIF9fLCBvcmlnaW5hbERlc2NyaXB0b3IpIHtcbiAgICAgICAgaW52YXJpYW50KHR5cGVvZiBvcmlnaW5hbERlc2NyaXB0b3IgIT09IFwidW5kZWZpbmVkXCIsIGdldE1lc3NhZ2UoXCJtMDA5XCIpKTtcbiAgICAgICAgaW52YXJpYW50KHR5cGVvZiBvcmlnaW5hbERlc2NyaXB0b3IuZ2V0ID09PSBcImZ1bmN0aW9uXCIsIGdldE1lc3NhZ2UoXCJtMDEwXCIpKTtcbiAgICAgICAgdmFyIGFkbSA9IGFzT2JzZXJ2YWJsZU9iamVjdCh0YXJnZXQsIFwiXCIpO1xuICAgICAgICBkZWZpbmVDb21wdXRlZFByb3BlcnR5KGFkbSwgbmFtZSwgb3JpZ2luYWxEZXNjcmlwdG9yLmdldCwgb3JpZ2luYWxEZXNjcmlwdG9yLnNldCwgY29tcGFyZVN0cnVjdHVyYWwsIGZhbHNlKTtcbiAgICB9LCBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgb2JzZXJ2YWJsZSA9IHRoaXMuJG1vYngudmFsdWVzW25hbWVdO1xuICAgICAgICBpZiAob2JzZXJ2YWJsZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUuZ2V0KCk7XG4gICAgfSwgZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuJG1vYngudmFsdWVzW25hbWVdLnNldCh2YWx1ZSk7XG4gICAgfSwgZmFsc2UsIGZhbHNlKTtcbn1cbnZhciBjb21wdXRlZERlY29yYXRvciA9IGNyZWF0ZUNvbXB1dGVkRGVjb3JhdG9yKGZhbHNlKTtcbnZhciBjb21wdXRlZFN0cnVjdERlY29yYXRvciA9IGNyZWF0ZUNvbXB1dGVkRGVjb3JhdG9yKHRydWUpO1xudmFyIGNvbXB1dGVkID0gKGZ1bmN0aW9uIGNvbXB1dGVkKGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgICBpZiAodHlwZW9mIGFyZzIgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgcmV0dXJuIGNvbXB1dGVkRGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfVxuICAgIGludmFyaWFudCh0eXBlb2YgYXJnMSA9PT0gXCJmdW5jdGlvblwiLCBnZXRNZXNzYWdlKFwibTAxMVwiKSk7XG4gICAgaW52YXJpYW50KGFyZ3VtZW50cy5sZW5ndGggPCAzLCBnZXRNZXNzYWdlKFwibTAxMlwiKSk7XG4gICAgdmFyIG9wdHMgPSB0eXBlb2YgYXJnMiA9PT0gXCJvYmplY3RcIiA/IGFyZzIgOiB7fTtcbiAgICBvcHRzLnNldHRlciA9IHR5cGVvZiBhcmcyID09PSBcImZ1bmN0aW9uXCIgPyBhcmcyIDogb3B0cy5zZXR0ZXI7XG4gICAgcmV0dXJuIG5ldyBDb21wdXRlZFZhbHVlKGFyZzEsIG9wdHMuY29udGV4dCwgb3B0cy5jb21wYXJlU3RydWN0dXJhbCB8fCBvcHRzLnN0cnVjdCB8fCBmYWxzZSwgb3B0cy5uYW1lIHx8IGFyZzEubmFtZSB8fCBcIlwiLCBvcHRzLnNldHRlcik7XG59KTtcbmV4cG9ydHMuY29tcHV0ZWQgPSBjb21wdXRlZDtcbmNvbXB1dGVkLnN0cnVjdCA9IGNvbXB1dGVkU3RydWN0RGVjb3JhdG9yO1xuZnVuY3Rpb24gY3JlYXRlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXIsIG9uQ2xlYW51cCkge1xuICAgIGludmFyaWFudCh0eXBlb2YgdHJhbnNmb3JtZXIgPT09IFwiZnVuY3Rpb25cIiAmJiB0cmFuc2Zvcm1lci5sZW5ndGggPCAyLCBcImNyZWF0ZVRyYW5zZm9ybWVyIGV4cGVjdHMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgb25lIGFyZ3VtZW50XCIpO1xuICAgIHZhciBvYmplY3RDYWNoZSA9IHt9O1xuICAgIHZhciByZXNldElkID0gZ2xvYmFsU3RhdGUucmVzZXRJZDtcbiAgICB2YXIgVHJhbnNmb3JtZXIgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMoVHJhbnNmb3JtZXIsIF9zdXBlcik7XG4gICAgICAgIGZ1bmN0aW9uIFRyYW5zZm9ybWVyKHNvdXJjZUlkZW50aWZpZXIsIHNvdXJjZU9iamVjdCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgZnVuY3Rpb24gKCkgeyByZXR1cm4gdHJhbnNmb3JtZXIoc291cmNlT2JqZWN0KTsgfSwgdW5kZWZpbmVkLCBmYWxzZSwgXCJUcmFuc2Zvcm1lci1cIiArIHRyYW5zZm9ybWVyLm5hbWUgKyBcIi1cIiArIHNvdXJjZUlkZW50aWZpZXIsIHVuZGVmaW5lZCkgfHwgdGhpcztcbiAgICAgICAgICAgIF90aGlzLnNvdXJjZUlkZW50aWZpZXIgPSBzb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICAgICAgX3RoaXMuc291cmNlT2JqZWN0ID0gc291cmNlT2JqZWN0O1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgICAgICB9XG4gICAgICAgIFRyYW5zZm9ybWVyLnByb3RvdHlwZS5vbkJlY29tZVVub2JzZXJ2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGFzdFZhbHVlID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIF9zdXBlci5wcm90b3R5cGUub25CZWNvbWVVbm9ic2VydmVkLmNhbGwodGhpcyk7XG4gICAgICAgICAgICBkZWxldGUgb2JqZWN0Q2FjaGVbdGhpcy5zb3VyY2VJZGVudGlmaWVyXTtcbiAgICAgICAgICAgIGlmIChvbkNsZWFudXApXG4gICAgICAgICAgICAgICAgb25DbGVhbnVwKGxhc3RWYWx1ZSwgdGhpcy5zb3VyY2VPYmplY3QpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJhbnNmb3JtZXI7XG4gICAgfShDb21wdXRlZFZhbHVlKSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChvYmplY3QpIHtcbiAgICAgICAgaWYgKHJlc2V0SWQgIT09IGdsb2JhbFN0YXRlLnJlc2V0SWQpIHtcbiAgICAgICAgICAgIG9iamVjdENhY2hlID0ge307XG4gICAgICAgICAgICByZXNldElkID0gZ2xvYmFsU3RhdGUucmVzZXRJZDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaWRlbnRpZmllciA9IGdldE1lbW9pemF0aW9uSWQob2JqZWN0KTtcbiAgICAgICAgdmFyIHJlYWN0aXZlVHJhbnNmb3JtZXIgPSBvYmplY3RDYWNoZVtpZGVudGlmaWVyXTtcbiAgICAgICAgaWYgKHJlYWN0aXZlVHJhbnNmb3JtZXIpXG4gICAgICAgICAgICByZXR1cm4gcmVhY3RpdmVUcmFuc2Zvcm1lci5nZXQoKTtcbiAgICAgICAgcmVhY3RpdmVUcmFuc2Zvcm1lciA9IG9iamVjdENhY2hlW2lkZW50aWZpZXJdID0gbmV3IFRyYW5zZm9ybWVyKGlkZW50aWZpZXIsIG9iamVjdCk7XG4gICAgICAgIHJldHVybiByZWFjdGl2ZVRyYW5zZm9ybWVyLmdldCgpO1xuICAgIH07XG59XG5leHBvcnRzLmNyZWF0ZVRyYW5zZm9ybWVyID0gY3JlYXRlVHJhbnNmb3JtZXI7XG5mdW5jdGlvbiBnZXRNZW1vaXphdGlvbklkKG9iamVjdCkge1xuICAgIGlmIChvYmplY3QgPT09IG51bGwgfHwgdHlwZW9mIG9iamVjdCAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYnhdIHRyYW5zZm9ybSBleHBlY3RlZCBzb21lIGtpbmQgb2Ygb2JqZWN0LCBnb3Q6IFwiICsgb2JqZWN0KTtcbiAgICB2YXIgdGlkID0gb2JqZWN0LiR0cmFuc2Zvcm1JZDtcbiAgICBpZiAodGlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGlkID0gZ2V0TmV4dElkKCk7XG4gICAgICAgIGFkZEhpZGRlblByb3Aob2JqZWN0LCBcIiR0cmFuc2Zvcm1JZFwiLCB0aWQpO1xuICAgIH1cbiAgICByZXR1cm4gdGlkO1xufVxuZnVuY3Rpb24gZXhwcihleHByLCBzY29wZSkge1xuICAgIGlmICghaXNDb21wdXRpbmdEZXJpdmF0aW9uKCkpXG4gICAgICAgIGNvbnNvbGUud2FybihnZXRNZXNzYWdlKFwibTAxM1wiKSk7XG4gICAgcmV0dXJuIGNvbXB1dGVkKGV4cHIsIHsgY29udGV4dDogc2NvcGUgfSkuZ2V0KCk7XG59XG5leHBvcnRzLmV4cHIgPSBleHByO1xuZnVuY3Rpb24gZXh0ZW5kT2JzZXJ2YWJsZSh0YXJnZXQpIHtcbiAgICB2YXIgcHJvcGVydGllcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHByb3BlcnRpZXNbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIHJldHVybiBleHRlbmRPYnNlcnZhYmxlSGVscGVyKHRhcmdldCwgZGVlcEVuaGFuY2VyLCBwcm9wZXJ0aWVzKTtcbn1cbmV4cG9ydHMuZXh0ZW5kT2JzZXJ2YWJsZSA9IGV4dGVuZE9ic2VydmFibGU7XG5mdW5jdGlvbiBleHRlbmRTaGFsbG93T2JzZXJ2YWJsZSh0YXJnZXQpIHtcbiAgICB2YXIgcHJvcGVydGllcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHByb3BlcnRpZXNbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIHJldHVybiBleHRlbmRPYnNlcnZhYmxlSGVscGVyKHRhcmdldCwgcmVmZXJlbmNlRW5oYW5jZXIsIHByb3BlcnRpZXMpO1xufVxuZXhwb3J0cy5leHRlbmRTaGFsbG93T2JzZXJ2YWJsZSA9IGV4dGVuZFNoYWxsb3dPYnNlcnZhYmxlO1xuZnVuY3Rpb24gZXh0ZW5kT2JzZXJ2YWJsZUhlbHBlcih0YXJnZXQsIGRlZmF1bHRFbmhhbmNlciwgcHJvcGVydGllcykge1xuICAgIGludmFyaWFudChhcmd1bWVudHMubGVuZ3RoID49IDIsIGdldE1lc3NhZ2UoXCJtMDE0XCIpKTtcbiAgICBpbnZhcmlhbnQodHlwZW9mIHRhcmdldCA9PT0gXCJvYmplY3RcIiwgZ2V0TWVzc2FnZShcIm0wMTVcIikpO1xuICAgIGludmFyaWFudCghKGlzT2JzZXJ2YWJsZU1hcCh0YXJnZXQpKSwgZ2V0TWVzc2FnZShcIm0wMTZcIikpO1xuICAgIHByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAocHJvcFNldCkge1xuICAgICAgICBpbnZhcmlhbnQodHlwZW9mIHByb3BTZXQgPT09IFwib2JqZWN0XCIsIGdldE1lc3NhZ2UoXCJtMDE3XCIpKTtcbiAgICAgICAgaW52YXJpYW50KCFpc09ic2VydmFibGUocHJvcFNldCksIGdldE1lc3NhZ2UoXCJtMDE4XCIpKTtcbiAgICB9KTtcbiAgICB2YXIgYWRtID0gYXNPYnNlcnZhYmxlT2JqZWN0KHRhcmdldCk7XG4gICAgdmFyIGRlZmluZWRQcm9wcyA9IHt9O1xuICAgIGZvciAodmFyIGkgPSBwcm9wZXJ0aWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHZhciBwcm9wU2V0ID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHByb3BTZXQpXG4gICAgICAgICAgICBpZiAoZGVmaW5lZFByb3BzW2tleV0gIT09IHRydWUgJiYgaGFzT3duUHJvcGVydHkocHJvcFNldCwga2V5KSkge1xuICAgICAgICAgICAgICAgIGRlZmluZWRQcm9wc1trZXldID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0ID09PSBwcm9wU2V0ICYmICFpc1Byb3BlcnR5Q29uZmlndXJhYmxlKHRhcmdldCwga2V5KSlcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHByb3BTZXQsIGtleSk7XG4gICAgICAgICAgICAgICAgZGVmaW5lT2JzZXJ2YWJsZVByb3BlcnR5RnJvbURlc2NyaXB0b3IoYWRtLCBrZXksIGRlc2NyaXB0b3IsIGRlZmF1bHRFbmhhbmNlcik7XG4gICAgICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQ7XG59XG5mdW5jdGlvbiBnZXREZXBlbmRlbmN5VHJlZSh0aGluZywgcHJvcGVydHkpIHtcbiAgICByZXR1cm4gbm9kZVRvRGVwZW5kZW5jeVRyZWUoZ2V0QXRvbSh0aGluZywgcHJvcGVydHkpKTtcbn1cbmZ1bmN0aW9uIG5vZGVUb0RlcGVuZGVuY3lUcmVlKG5vZGUpIHtcbiAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiBub2RlLm5hbWVcbiAgICB9O1xuICAgIGlmIChub2RlLm9ic2VydmluZyAmJiBub2RlLm9ic2VydmluZy5sZW5ndGggPiAwKVxuICAgICAgICByZXN1bHQuZGVwZW5kZW5jaWVzID0gdW5pcXVlKG5vZGUub2JzZXJ2aW5nKS5tYXAobm9kZVRvRGVwZW5kZW5jeVRyZWUpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBnZXRPYnNlcnZlclRyZWUodGhpbmcsIHByb3BlcnR5KSB7XG4gICAgcmV0dXJuIG5vZGVUb09ic2VydmVyVHJlZShnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSkpO1xufVxuZnVuY3Rpb24gbm9kZVRvT2JzZXJ2ZXJUcmVlKG5vZGUpIHtcbiAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiBub2RlLm5hbWVcbiAgICB9O1xuICAgIGlmIChoYXNPYnNlcnZlcnMobm9kZSkpXG4gICAgICAgIHJlc3VsdC5vYnNlcnZlcnMgPSBnZXRPYnNlcnZlcnMobm9kZSkubWFwKG5vZGVUb09ic2VydmVyVHJlZSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGludGVyY2VwdCh0aGluZywgcHJvcE9ySGFuZGxlciwgaGFuZGxlcikge1xuICAgIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICByZXR1cm4gaW50ZXJjZXB0UHJvcGVydHkodGhpbmcsIHByb3BPckhhbmRsZXIsIGhhbmRsZXIpO1xuICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIGludGVyY2VwdEludGVyY2VwdGFibGUodGhpbmcsIHByb3BPckhhbmRsZXIpO1xufVxuZXhwb3J0cy5pbnRlcmNlcHQgPSBpbnRlcmNlcHQ7XG5mdW5jdGlvbiBpbnRlcmNlcHRJbnRlcmNlcHRhYmxlKHRoaW5nLCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIGdldEFkbWluaXN0cmF0aW9uKHRoaW5nKS5pbnRlcmNlcHQoaGFuZGxlcik7XG59XG5mdW5jdGlvbiBpbnRlcmNlcHRQcm9wZXJ0eSh0aGluZywgcHJvcGVydHksIGhhbmRsZXIpIHtcbiAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24odGhpbmcsIHByb3BlcnR5KS5pbnRlcmNlcHQoaGFuZGxlcik7XG59XG5mdW5jdGlvbiBpc0NvbXB1dGVkKHZhbHVlLCBwcm9wZXJ0eSkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZU9iamVjdCh2YWx1ZSkgPT09IGZhbHNlKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgYXRvbSA9IGdldEF0b20odmFsdWUsIHByb3BlcnR5KTtcbiAgICAgICAgcmV0dXJuIGlzQ29tcHV0ZWRWYWx1ZShhdG9tKTtcbiAgICB9XG4gICAgcmV0dXJuIGlzQ29tcHV0ZWRWYWx1ZSh2YWx1ZSk7XG59XG5leHBvcnRzLmlzQ29tcHV0ZWQgPSBpc0NvbXB1dGVkO1xuZnVuY3Rpb24gaXNPYnNlcnZhYmxlKHZhbHVlLCBwcm9wZXJ0eSkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZUFycmF5KHZhbHVlKSB8fCBpc09ic2VydmFibGVNYXAodmFsdWUpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGdldE1lc3NhZ2UoXCJtMDE5XCIpKTtcbiAgICAgICAgZWxzZSBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICAgICAgdmFyIG8gPSB2YWx1ZS4kbW9ieDtcbiAgICAgICAgICAgIHJldHVybiBvLnZhbHVlcyAmJiAhIW8udmFsdWVzW3Byb3BlcnR5XTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBpc09ic2VydmFibGVPYmplY3QodmFsdWUpIHx8ICEhdmFsdWUuJG1vYnggfHwgaXNBdG9tKHZhbHVlKSB8fCBpc1JlYWN0aW9uKHZhbHVlKSB8fCBpc0NvbXB1dGVkVmFsdWUodmFsdWUpO1xufVxuZXhwb3J0cy5pc09ic2VydmFibGUgPSBpc09ic2VydmFibGU7XG52YXIgZGVlcERlY29yYXRvciA9IGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKGRlZXBFbmhhbmNlcik7XG52YXIgc2hhbGxvd0RlY29yYXRvciA9IGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKHNoYWxsb3dFbmhhbmNlcik7XG52YXIgcmVmRGVjb3JhdG9yID0gY3JlYXRlRGVjb3JhdG9yRm9yRW5oYW5jZXIocmVmZXJlbmNlRW5oYW5jZXIpO1xudmFyIGRlZXBTdHJ1Y3REZWNvcmF0b3IgPSBjcmVhdGVEZWNvcmF0b3JGb3JFbmhhbmNlcihkZWVwU3RydWN0RW5oYW5jZXIpO1xudmFyIHJlZlN0cnVjdERlY29yYXRvciA9IGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKHJlZlN0cnVjdEVuaGFuY2VyKTtcbmZ1bmN0aW9uIGNyZWF0ZU9ic2VydmFibGUodikge1xuICAgIGlmICh2ID09PSB2b2lkIDApIHsgdiA9IHVuZGVmaW5lZDsgfVxuICAgIGlmICh0eXBlb2YgYXJndW1lbnRzWzFdID09PSBcInN0cmluZ1wiKVxuICAgICAgICByZXR1cm4gZGVlcERlY29yYXRvci5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgIGludmFyaWFudChhcmd1bWVudHMubGVuZ3RoIDw9IDEsIGdldE1lc3NhZ2UoXCJtMDIxXCIpKTtcbiAgICBpbnZhcmlhbnQoIWlzTW9kaWZpZXJEZXNjcmlwdG9yKHYpLCBnZXRNZXNzYWdlKFwibTAyMFwiKSk7XG4gICAgaWYgKGlzT2JzZXJ2YWJsZSh2KSlcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgdmFyIHJlcyA9IGRlZXBFbmhhbmNlcih2LCB1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gICAgaWYgKHJlcyAhPT0gdilcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5ib3godik7XG59XG52YXIgSU9ic2VydmFibGVGYWN0b3JpZXMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIElPYnNlcnZhYmxlRmFjdG9yaWVzKCkge1xuICAgIH1cbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuYm94ID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwiYm94XCIpO1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGVWYWx1ZSh2YWx1ZSwgZGVlcEVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5zaGFsbG93Qm94ID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwic2hhbGxvd0JveFwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlVmFsdWUodmFsdWUsIHJlZmVyZW5jZUVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5hcnJheSA9IGZ1bmN0aW9uIChpbml0aWFsVmFsdWVzLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwiYXJyYXlcIik7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZUFycmF5KGluaXRpYWxWYWx1ZXMsIGRlZXBFbmhhbmNlciwgbmFtZSk7XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvd0FycmF5ID0gZnVuY3Rpb24gKGluaXRpYWxWYWx1ZXMsIG5hbWUpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKVxuICAgICAgICAgICAgaW5jb3JyZWN0bHlVc2VkQXNEZWNvcmF0b3IoXCJzaGFsbG93QXJyYXlcIik7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZUFycmF5KGluaXRpYWxWYWx1ZXMsIHJlZmVyZW5jZUVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5tYXAgPSBmdW5jdGlvbiAoaW5pdGlhbFZhbHVlcywgbmFtZSkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDIpXG4gICAgICAgICAgICBpbmNvcnJlY3RseVVzZWRBc0RlY29yYXRvcihcIm1hcFwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlTWFwKGluaXRpYWxWYWx1ZXMsIGRlZXBFbmhhbmNlciwgbmFtZSk7XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvd01hcCA9IGZ1bmN0aW9uIChpbml0aWFsVmFsdWVzLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwic2hhbGxvd01hcFwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlTWFwKGluaXRpYWxWYWx1ZXMsIHJlZmVyZW5jZUVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5vYmplY3QgPSBmdW5jdGlvbiAocHJvcHMsIG5hbWUpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKVxuICAgICAgICAgICAgaW5jb3JyZWN0bHlVc2VkQXNEZWNvcmF0b3IoXCJvYmplY3RcIik7XG4gICAgICAgIHZhciByZXMgPSB7fTtcbiAgICAgICAgYXNPYnNlcnZhYmxlT2JqZWN0KHJlcywgbmFtZSk7XG4gICAgICAgIGV4dGVuZE9ic2VydmFibGUocmVzLCBwcm9wcyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvd09iamVjdCA9IGZ1bmN0aW9uIChwcm9wcywgbmFtZSkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDIpXG4gICAgICAgICAgICBpbmNvcnJlY3RseVVzZWRBc0RlY29yYXRvcihcInNoYWxsb3dPYmplY3RcIik7XG4gICAgICAgIHZhciByZXMgPSB7fTtcbiAgICAgICAgYXNPYnNlcnZhYmxlT2JqZWN0KHJlcywgbmFtZSk7XG4gICAgICAgIGV4dGVuZFNoYWxsb3dPYnNlcnZhYmxlKHJlcywgcHJvcHMpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgSU9ic2VydmFibGVGYWN0b3JpZXMucHJvdG90eXBlLnJlZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTW9kaWZpZXJEZXNjcmlwdG9yKHJlZmVyZW5jZUVuaGFuY2VyLCBhcmd1bWVudHNbMF0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJlZkRlY29yYXRvci5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTW9kaWZpZXJEZXNjcmlwdG9yKHNoYWxsb3dFbmhhbmNlciwgYXJndW1lbnRzWzBdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBzaGFsbG93RGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5kZWVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVNb2RpZmllckRlc2NyaXB0b3IoZGVlcEVuaGFuY2VyLCBhcmd1bWVudHNbMF0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRlZXBEZWNvcmF0b3IuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSU9ic2VydmFibGVGYWN0b3JpZXMucHJvdG90eXBlLnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTW9kaWZpZXJEZXNjcmlwdG9yKGRlZXBTdHJ1Y3RFbmhhbmNlciwgYXJndW1lbnRzWzBdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBkZWVwU3RydWN0RGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBJT2JzZXJ2YWJsZUZhY3Rvcmllcztcbn0oKSk7XG5leHBvcnRzLklPYnNlcnZhYmxlRmFjdG9yaWVzID0gSU9ic2VydmFibGVGYWN0b3JpZXM7XG52YXIgb2JzZXJ2YWJsZSA9IGNyZWF0ZU9ic2VydmFibGU7XG5leHBvcnRzLm9ic2VydmFibGUgPSBvYnNlcnZhYmxlO1xuT2JqZWN0LmtleXMoSU9ic2VydmFibGVGYWN0b3JpZXMucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIG9ic2VydmFibGVba2V5XSA9IElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZVtrZXldOyB9KTtcbm9ic2VydmFibGUuZGVlcC5zdHJ1Y3QgPSBvYnNlcnZhYmxlLnN0cnVjdDtcbm9ic2VydmFibGUucmVmLnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZU1vZGlmaWVyRGVzY3JpcHRvcihyZWZTdHJ1Y3RFbmhhbmNlciwgYXJndW1lbnRzWzBdKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiByZWZTdHJ1Y3REZWNvcmF0b3IuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICB9XG59O1xuZnVuY3Rpb24gaW5jb3JyZWN0bHlVc2VkQXNEZWNvcmF0b3IobWV0aG9kTmFtZSkge1xuICAgIGZhaWwoXCJFeHBlY3RlZCBvbmUgb3IgdHdvIGFyZ3VtZW50cyB0byBvYnNlcnZhYmxlLlwiICsgbWV0aG9kTmFtZSArIFwiLiBEaWQgeW91IGFjY2lkZW50YWxseSB0cnkgdG8gdXNlIG9ic2VydmFibGUuXCIgKyBtZXRob2ROYW1lICsgXCIgYXMgZGVjb3JhdG9yP1wiKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKGVuaGFuY2VyKSB7XG4gICAgaW52YXJpYW50KCEhZW5oYW5jZXIsIFwiOihcIik7XG4gICAgcmV0dXJuIGNyZWF0ZUNsYXNzUHJvcGVydHlEZWNvcmF0b3IoZnVuY3Rpb24gKHRhcmdldCwgbmFtZSwgYmFzZVZhbHVlLCBfLCBiYXNlRGVzY3JpcHRvcikge1xuICAgICAgICBhc3NlcnRQcm9wZXJ0eUNvbmZpZ3VyYWJsZSh0YXJnZXQsIG5hbWUpO1xuICAgICAgICBpbnZhcmlhbnQoIWJhc2VEZXNjcmlwdG9yIHx8ICFiYXNlRGVzY3JpcHRvci5nZXQsIGdldE1lc3NhZ2UoXCJtMDIyXCIpKTtcbiAgICAgICAgdmFyIGFkbSA9IGFzT2JzZXJ2YWJsZU9iamVjdCh0YXJnZXQsIHVuZGVmaW5lZCk7XG4gICAgICAgIGRlZmluZU9ic2VydmFibGVQcm9wZXJ0eShhZG0sIG5hbWUsIGJhc2VWYWx1ZSwgZW5oYW5jZXIpO1xuICAgIH0sIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHZhciBvYnNlcnZhYmxlID0gdGhpcy4kbW9ieC52YWx1ZXNbbmFtZV07XG4gICAgICAgIGlmIChvYnNlcnZhYmxlID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZS5nZXQoKTtcbiAgICB9LCBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgc2V0UHJvcGVydHlWYWx1ZSh0aGlzLCBuYW1lLCB2YWx1ZSk7XG4gICAgfSwgdHJ1ZSwgZmFsc2UpO1xufVxuZnVuY3Rpb24gb2JzZXJ2ZSh0aGluZywgcHJvcE9yQ2IsIGNiT3JGaXJlLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICBpZiAodHlwZW9mIGNiT3JGaXJlID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHJldHVybiBvYnNlcnZlT2JzZXJ2YWJsZVByb3BlcnR5KHRoaW5nLCBwcm9wT3JDYiwgY2JPckZpcmUsIGZpcmVJbW1lZGlhdGVseSk7XG4gICAgZWxzZVxuICAgICAgICByZXR1cm4gb2JzZXJ2ZU9ic2VydmFibGUodGhpbmcsIHByb3BPckNiLCBjYk9yRmlyZSk7XG59XG5leHBvcnRzLm9ic2VydmUgPSBvYnNlcnZlO1xuZnVuY3Rpb24gb2JzZXJ2ZU9ic2VydmFibGUodGhpbmcsIGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24odGhpbmcpLm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG59XG5mdW5jdGlvbiBvYnNlcnZlT2JzZXJ2YWJsZVByb3BlcnR5KHRoaW5nLCBwcm9wZXJ0eSwgbGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSkge1xuICAgIHJldHVybiBnZXRBZG1pbmlzdHJhdGlvbih0aGluZywgcHJvcGVydHkpLm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG59XG5mdW5jdGlvbiB0b0pTKHNvdXJjZSwgZGV0ZWN0Q3ljbGVzLCBfX2FscmVhZHlTZWVuKSB7XG4gICAgaWYgKGRldGVjdEN5Y2xlcyA9PT0gdm9pZCAwKSB7IGRldGVjdEN5Y2xlcyA9IHRydWU7IH1cbiAgICBpZiAoX19hbHJlYWR5U2VlbiA9PT0gdm9pZCAwKSB7IF9fYWxyZWFkeVNlZW4gPSBbXTsgfVxuICAgIGZ1bmN0aW9uIGNhY2hlKHZhbHVlKSB7XG4gICAgICAgIGlmIChkZXRlY3RDeWNsZXMpXG4gICAgICAgICAgICBfX2FscmVhZHlTZWVuLnB1c2goW3NvdXJjZSwgdmFsdWVdKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAoaXNPYnNlcnZhYmxlKHNvdXJjZSkpIHtcbiAgICAgICAgaWYgKGRldGVjdEN5Y2xlcyAmJiBfX2FscmVhZHlTZWVuID09PSBudWxsKVxuICAgICAgICAgICAgX19hbHJlYWR5U2VlbiA9IFtdO1xuICAgICAgICBpZiAoZGV0ZWN0Q3ljbGVzICYmIHNvdXJjZSAhPT0gbnVsbCAmJiB0eXBlb2Ygc291cmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IF9fYWxyZWFkeVNlZW4ubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgICAgIGlmIChfX2FscmVhZHlTZWVuW2ldWzBdID09PSBzb3VyY2UpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfX2FscmVhZHlTZWVuW2ldWzFdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc09ic2VydmFibGVBcnJheShzb3VyY2UpKSB7XG4gICAgICAgICAgICB2YXIgcmVzID0gY2FjaGUoW10pO1xuICAgICAgICAgICAgdmFyIHRvQWRkID0gc291cmNlLm1hcChmdW5jdGlvbiAodmFsdWUpIHsgcmV0dXJuIHRvSlModmFsdWUsIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7IH0pO1xuICAgICAgICAgICAgcmVzLmxlbmd0aCA9IHRvQWRkLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdG9BZGQubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgICAgIHJlc1tpXSA9IHRvQWRkW2ldO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHNvdXJjZSkpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSBjYWNoZSh7fSk7XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKVxuICAgICAgICAgICAgICAgIHJlc1trZXldID0gdG9KUyhzb3VyY2Vba2V5XSwgZGV0ZWN0Q3ljbGVzLCBfX2FscmVhZHlTZWVuKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZU1hcChzb3VyY2UpKSB7XG4gICAgICAgICAgICB2YXIgcmVzXzEgPSBjYWNoZSh7fSk7XG4gICAgICAgICAgICBzb3VyY2UuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkgeyByZXR1cm4gcmVzXzFba2V5XSA9IHRvSlModmFsdWUsIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7IH0pO1xuICAgICAgICAgICAgcmV0dXJuIHJlc18xO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc09ic2VydmFibGVWYWx1ZShzb3VyY2UpKVxuICAgICAgICAgICAgcmV0dXJuIHRvSlMoc291cmNlLmdldCgpLCBkZXRlY3RDeWNsZXMsIF9fYWxyZWFkeVNlZW4pO1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlO1xufVxuZXhwb3J0cy50b0pTID0gdG9KUztcbmZ1bmN0aW9uIHRyYW5zYWN0aW9uKGFjdGlvbiwgdGhpc0FyZykge1xuICAgIGlmICh0aGlzQXJnID09PSB2b2lkIDApIHsgdGhpc0FyZyA9IHVuZGVmaW5lZDsgfVxuICAgIGRlcHJlY2F0ZWQoZ2V0TWVzc2FnZShcIm0wMjNcIikpO1xuICAgIHJldHVybiBydW5JblRyYW5zYWN0aW9uLmFwcGx5KHVuZGVmaW5lZCwgYXJndW1lbnRzKTtcbn1cbmV4cG9ydHMudHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbjtcbmZ1bmN0aW9uIHJ1bkluVHJhbnNhY3Rpb24oYWN0aW9uLCB0aGlzQXJnKSB7XG4gICAgaWYgKHRoaXNBcmcgPT09IHZvaWQgMCkgeyB0aGlzQXJnID0gdW5kZWZpbmVkOyB9XG4gICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oXCJcIiwgYWN0aW9uKTtcbn1cbmZ1bmN0aW9uIGxvZyhtc2cpIHtcbiAgICBjb25zb2xlLmxvZyhtc2cpO1xuICAgIHJldHVybiBtc2c7XG59XG5mdW5jdGlvbiB3aHlSdW4odGhpbmcsIHByb3ApIHtcbiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgdGhpbmcgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgICAgICAgICBpZiAoIXRoaW5nKVxuICAgICAgICAgICAgICAgIHJldHVybiBsb2coZ2V0TWVzc2FnZShcIm0wMjRcIikpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHRoaW5nID0gZ2V0QXRvbSh0aGluZywgcHJvcCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgdGhpbmcgPSBnZXRBdG9tKHRoaW5nKTtcbiAgICBpZiAoaXNDb21wdXRlZFZhbHVlKHRoaW5nKSlcbiAgICAgICAgcmV0dXJuIGxvZyh0aGluZy53aHlSdW4oKSk7XG4gICAgZWxzZSBpZiAoaXNSZWFjdGlvbih0aGluZykpXG4gICAgICAgIHJldHVybiBsb2codGhpbmcud2h5UnVuKCkpO1xuICAgIHJldHVybiBmYWlsKGdldE1lc3NhZ2UoXCJtMDI1XCIpKTtcbn1cbmV4cG9ydHMud2h5UnVuID0gd2h5UnVuO1xuZnVuY3Rpb24gY3JlYXRlQWN0aW9uKGFjdGlvbk5hbWUsIGZuKSB7XG4gICAgaW52YXJpYW50KHR5cGVvZiBmbiA9PT0gXCJmdW5jdGlvblwiLCBnZXRNZXNzYWdlKFwibTAyNlwiKSk7XG4gICAgaW52YXJpYW50KHR5cGVvZiBhY3Rpb25OYW1lID09PSBcInN0cmluZ1wiICYmIGFjdGlvbk5hbWUubGVuZ3RoID4gMCwgXCJhY3Rpb25zIHNob3VsZCBoYXZlIHZhbGlkIG5hbWVzLCBnb3Q6ICdcIiArIGFjdGlvbk5hbWUgKyBcIidcIik7XG4gICAgdmFyIHJlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgICByZXMub3JpZ2luYWxGbiA9IGZuO1xuICAgIHJlcy5pc01vYnhBY3Rpb24gPSB0cnVlO1xuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBleGVjdXRlQWN0aW9uKGFjdGlvbk5hbWUsIGZuLCBzY29wZSwgYXJncykge1xuICAgIHZhciBydW5JbmZvID0gc3RhcnRBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHNjb3BlLCBhcmdzKTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gZm4uYXBwbHkoc2NvcGUsIGFyZ3MpO1xuICAgIH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgZW5kQWN0aW9uKHJ1bkluZm8pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHN0YXJ0QWN0aW9uKGFjdGlvbk5hbWUsIGZuLCBzY29wZSwgYXJncykge1xuICAgIHZhciBub3RpZnlTcHkgPSBpc1NweUVuYWJsZWQoKSAmJiAhIWFjdGlvbk5hbWU7XG4gICAgdmFyIHN0YXJ0VGltZSA9IDA7XG4gICAgaWYgKG5vdGlmeVNweSkge1xuICAgICAgICBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB2YXIgbCA9IChhcmdzICYmIGFyZ3MubGVuZ3RoKSB8fCAwO1xuICAgICAgICB2YXIgZmxhdHRlbmRBcmdzID0gbmV3IEFycmF5KGwpO1xuICAgICAgICBpZiAobCA+IDApXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKylcbiAgICAgICAgICAgICAgICBmbGF0dGVuZEFyZ3NbaV0gPSBhcmdzW2ldO1xuICAgICAgICBzcHlSZXBvcnRTdGFydCh7XG4gICAgICAgICAgICB0eXBlOiBcImFjdGlvblwiLFxuICAgICAgICAgICAgbmFtZTogYWN0aW9uTmFtZSxcbiAgICAgICAgICAgIGZuOiBmbixcbiAgICAgICAgICAgIG9iamVjdDogc2NvcGUsXG4gICAgICAgICAgICBhcmd1bWVudHM6IGZsYXR0ZW5kQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgdmFyIHByZXZEZXJpdmF0aW9uID0gdW50cmFja2VkU3RhcnQoKTtcbiAgICBzdGFydEJhdGNoKCk7XG4gICAgdmFyIHByZXZBbGxvd1N0YXRlQ2hhbmdlcyA9IGFsbG93U3RhdGVDaGFuZ2VzU3RhcnQodHJ1ZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcHJldkRlcml2YXRpb246IHByZXZEZXJpdmF0aW9uLFxuICAgICAgICBwcmV2QWxsb3dTdGF0ZUNoYW5nZXM6IHByZXZBbGxvd1N0YXRlQ2hhbmdlcyxcbiAgICAgICAgbm90aWZ5U3B5OiBub3RpZnlTcHksXG4gICAgICAgIHN0YXJ0VGltZTogc3RhcnRUaW1lXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGVuZEFjdGlvbihydW5JbmZvKSB7XG4gICAgYWxsb3dTdGF0ZUNoYW5nZXNFbmQocnVuSW5mby5wcmV2QWxsb3dTdGF0ZUNoYW5nZXMpO1xuICAgIGVuZEJhdGNoKCk7XG4gICAgdW50cmFja2VkRW5kKHJ1bkluZm8ucHJldkRlcml2YXRpb24pO1xuICAgIGlmIChydW5JbmZvLm5vdGlmeVNweSlcbiAgICAgICAgc3B5UmVwb3J0RW5kKHsgdGltZTogRGF0ZS5ub3coKSAtIHJ1bkluZm8uc3RhcnRUaW1lIH0pO1xufVxuZnVuY3Rpb24gdXNlU3RyaWN0KHN0cmljdCkge1xuICAgIGludmFyaWFudChnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb24gPT09IG51bGwsIGdldE1lc3NhZ2UoXCJtMDI4XCIpKTtcbiAgICBnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlID0gc3RyaWN0O1xuICAgIGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzID0gIXN0cmljdDtcbn1cbmV4cG9ydHMudXNlU3RyaWN0ID0gdXNlU3RyaWN0O1xuZnVuY3Rpb24gaXNTdHJpY3RNb2RlRW5hYmxlZCgpIHtcbiAgICByZXR1cm4gZ2xvYmFsU3RhdGUuc3RyaWN0TW9kZTtcbn1cbmV4cG9ydHMuaXNTdHJpY3RNb2RlRW5hYmxlZCA9IGlzU3RyaWN0TW9kZUVuYWJsZWQ7XG5mdW5jdGlvbiBhbGxvd1N0YXRlQ2hhbmdlcyhhbGxvd1N0YXRlQ2hhbmdlcywgZnVuYykge1xuICAgIHZhciBwcmV2ID0gYWxsb3dTdGF0ZUNoYW5nZXNTdGFydChhbGxvd1N0YXRlQ2hhbmdlcyk7XG4gICAgdmFyIHJlcztcbiAgICB0cnkge1xuICAgICAgICByZXMgPSBmdW5jKCk7XG4gICAgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICBhbGxvd1N0YXRlQ2hhbmdlc0VuZChwcmV2KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGFsbG93U3RhdGVDaGFuZ2VzU3RhcnQoYWxsb3dTdGF0ZUNoYW5nZXMpIHtcbiAgICB2YXIgcHJldiA9IGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzO1xuICAgIGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzID0gYWxsb3dTdGF0ZUNoYW5nZXM7XG4gICAgcmV0dXJuIHByZXY7XG59XG5mdW5jdGlvbiBhbGxvd1N0YXRlQ2hhbmdlc0VuZChwcmV2KSB7XG4gICAgZ2xvYmFsU3RhdGUuYWxsb3dTdGF0ZUNoYW5nZXMgPSBwcmV2O1xufVxudmFyIEJhc2VBdG9tID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlQXRvbShuYW1lKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiQXRvbUBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbiA9IHRydWU7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXJzID0gW107XG4gICAgICAgIHRoaXMub2JzZXJ2ZXJzSW5kZXhlcyA9IHt9O1xuICAgICAgICB0aGlzLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgIHRoaXMubGFzdEFjY2Vzc2VkQnkgPSAwO1xuICAgICAgICB0aGlzLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORztcbiAgICB9XG4gICAgQmFzZUF0b20ucHJvdG90eXBlLm9uQmVjb21lVW5vYnNlcnZlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIEJhc2VBdG9tLnByb3RvdHlwZS5yZXBvcnRPYnNlcnZlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVwb3J0T2JzZXJ2ZWQodGhpcyk7XG4gICAgfTtcbiAgICBCYXNlQXRvbS5wcm90b3R5cGUucmVwb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc3RhcnRCYXRjaCgpO1xuICAgICAgICBwcm9wYWdhdGVDaGFuZ2VkKHRoaXMpO1xuICAgICAgICBlbmRCYXRjaCgpO1xuICAgIH07XG4gICAgQmFzZUF0b20ucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lO1xuICAgIH07XG4gICAgcmV0dXJuIEJhc2VBdG9tO1xufSgpKTtcbmV4cG9ydHMuQmFzZUF0b20gPSBCYXNlQXRvbTtcbnZhciBBdG9tID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQXRvbSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBdG9tKG5hbWUsIG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyLCBvbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiQXRvbUBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIGlmIChvbkJlY29tZU9ic2VydmVkSGFuZGxlciA9PT0gdm9pZCAwKSB7IG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyID0gbm9vcDsgfVxuICAgICAgICBpZiAob25CZWNvbWVVbm9ic2VydmVkSGFuZGxlciA9PT0gdm9pZCAwKSB7IG9uQmVjb21lVW5vYnNlcnZlZEhhbmRsZXIgPSBub29wOyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIG5hbWUpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICBfdGhpcy5vbkJlY29tZU9ic2VydmVkSGFuZGxlciA9IG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyO1xuICAgICAgICBfdGhpcy5vbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyID0gb25CZWNvbWVVbm9ic2VydmVkSGFuZGxlcjtcbiAgICAgICAgX3RoaXMuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbiA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc0JlaW5nVHJhY2tlZCA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEF0b20ucHJvdG90eXBlLnJlcG9ydE9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBzdGFydEJhdGNoKCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucmVwb3J0T2JzZXJ2ZWQuY2FsbCh0aGlzKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzQmVpbmdUcmFja2VkKSB7XG4gICAgICAgICAgICB0aGlzLmlzQmVpbmdUcmFja2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMub25CZWNvbWVPYnNlcnZlZEhhbmRsZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICByZXR1cm4gISFnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgfTtcbiAgICBBdG9tLnByb3RvdHlwZS5vbkJlY29tZVVub2JzZXJ2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuaXNCZWluZ1RyYWNrZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyKCk7XG4gICAgfTtcbiAgICByZXR1cm4gQXRvbTtcbn0oQmFzZUF0b20pKTtcbmV4cG9ydHMuQXRvbSA9IEF0b207XG52YXIgaXNBdG9tID0gY3JlYXRlSW5zdGFuY2VvZlByZWRpY2F0ZShcIkF0b21cIiwgQmFzZUF0b20pO1xudmFyIENvbXB1dGVkVmFsdWUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbXB1dGVkVmFsdWUoZGVyaXZhdGlvbiwgc2NvcGUsIGNvbXBhcmVTdHJ1Y3R1cmFsLCBuYW1lLCBzZXR0ZXIpIHtcbiAgICAgICAgdGhpcy5kZXJpdmF0aW9uID0gZGVyaXZhdGlvbjtcbiAgICAgICAgdGhpcy5zY29wZSA9IHNjb3BlO1xuICAgICAgICB0aGlzLmNvbXBhcmVTdHJ1Y3R1cmFsID0gY29tcGFyZVN0cnVjdHVyYWw7XG4gICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORztcbiAgICAgICAgdGhpcy5vYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5uZXdPYnNlcnZpbmcgPSBudWxsO1xuICAgICAgICB0aGlzLmlzUGVuZGluZ1Vub2JzZXJ2YXRpb24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnNJbmRleGVzID0ge307XG4gICAgICAgIHRoaXMuZGlmZlZhbHVlID0gMDtcbiAgICAgICAgdGhpcy5ydW5JZCA9IDA7XG4gICAgICAgIHRoaXMubGFzdEFjY2Vzc2VkQnkgPSAwO1xuICAgICAgICB0aGlzLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEU7XG4gICAgICAgIHRoaXMudW5ib3VuZERlcHNDb3VudCA9IDA7XG4gICAgICAgIHRoaXMuX19tYXBpZCA9IFwiI1wiICsgZ2V0TmV4dElkKCk7XG4gICAgICAgIHRoaXMudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaXNDb21wdXRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1J1bm5pbmdTZXR0ZXIgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZSB8fCBcIkNvbXB1dGVkVmFsdWVAXCIgKyBnZXROZXh0SWQoKTtcbiAgICAgICAgaWYgKHNldHRlcilcbiAgICAgICAgICAgIHRoaXMuc2V0dGVyID0gY3JlYXRlQWN0aW9uKG5hbWUgKyBcIi1zZXR0ZXJcIiwgc2V0dGVyKTtcbiAgICB9XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUub25CZWNvbWVTdGFsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcHJvcGFnYXRlTWF5YmVDaGFuZ2VkKHRoaXMpO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUub25CZWNvbWVVbm9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpbnZhcmlhbnQodGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSAhPT0gSURlcml2YXRpb25TdGF0ZS5OT1RfVFJBQ0tJTkcsIGdldE1lc3NhZ2UoXCJtMDI5XCIpKTtcbiAgICAgICAgY2xlYXJPYnNlcnZpbmcodGhpcyk7XG4gICAgICAgIHRoaXMudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgfTtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGludmFyaWFudCghdGhpcy5pc0NvbXB1dGluZywgXCJDeWNsZSBkZXRlY3RlZCBpbiBjb21wdXRhdGlvbiBcIiArIHRoaXMubmFtZSwgdGhpcy5kZXJpdmF0aW9uKTtcbiAgICAgICAgaWYgKGdsb2JhbFN0YXRlLmluQmF0Y2ggPT09IDApIHtcbiAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgIGlmIChzaG91bGRDb21wdXRlKHRoaXMpKVxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLmNvbXB1dGVWYWx1ZShmYWxzZSk7XG4gICAgICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVwb3J0T2JzZXJ2ZWQodGhpcyk7XG4gICAgICAgICAgICBpZiAoc2hvdWxkQ29tcHV0ZSh0aGlzKSlcbiAgICAgICAgICAgICAgICBpZiAodGhpcy50cmFja0FuZENvbXB1dGUoKSlcbiAgICAgICAgICAgICAgICAgICAgcHJvcGFnYXRlQ2hhbmdlQ29uZmlybWVkKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLnZhbHVlO1xuICAgICAgICBpZiAoaXNDYXVnaHRFeGNlcHRpb24ocmVzdWx0KSlcbiAgICAgICAgICAgIHRocm93IHJlc3VsdC5jYXVzZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnBlZWsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLmNvbXB1dGVWYWx1ZShmYWxzZSk7XG4gICAgICAgIGlmIChpc0NhdWdodEV4Y2VwdGlvbihyZXMpKVxuICAgICAgICAgICAgdGhyb3cgcmVzLmNhdXNlO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRlcikge1xuICAgICAgICAgICAgaW52YXJpYW50KCF0aGlzLmlzUnVubmluZ1NldHRlciwgXCJUaGUgc2V0dGVyIG9mIGNvbXB1dGVkIHZhbHVlICdcIiArIHRoaXMubmFtZSArIFwiJyBpcyB0cnlpbmcgdG8gdXBkYXRlIGl0c2VsZi4gRGlkIHlvdSBpbnRlbmQgdG8gdXBkYXRlIGFuIF9vYnNlcnZhYmxlXyB2YWx1ZSwgaW5zdGVhZCBvZiB0aGUgY29tcHV0ZWQgcHJvcGVydHk/XCIpO1xuICAgICAgICAgICAgdGhpcy5pc1J1bm5pbmdTZXR0ZXIgPSB0cnVlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRlci5jYWxsKHRoaXMuc2NvcGUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNSdW5uaW5nU2V0dGVyID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgaW52YXJpYW50KGZhbHNlLCBcIltDb21wdXRlZFZhbHVlICdcIiArIHRoaXMubmFtZSArIFwiJ10gSXQgaXMgbm90IHBvc3NpYmxlIHRvIGFzc2lnbiBhIG5ldyB2YWx1ZSB0byBhIGNvbXB1dGVkIHZhbHVlLlwiKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnRyYWNrQW5kQ29tcHV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGlzU3B5RW5hYmxlZCgpKSB7XG4gICAgICAgICAgICBzcHlSZXBvcnQoe1xuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcy5zY29wZSxcbiAgICAgICAgICAgICAgICB0eXBlOiBcImNvbXB1dGVcIixcbiAgICAgICAgICAgICAgICBmbjogdGhpcy5kZXJpdmF0aW9uXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLnZhbHVlO1xuICAgICAgICB2YXIgbmV3VmFsdWUgPSB0aGlzLnZhbHVlID0gdGhpcy5jb21wdXRlVmFsdWUodHJ1ZSk7XG4gICAgICAgIHJldHVybiBpc0NhdWdodEV4Y2VwdGlvbihuZXdWYWx1ZSkgfHwgdmFsdWVEaWRDaGFuZ2UodGhpcy5jb21wYXJlU3RydWN0dXJhbCwgbmV3VmFsdWUsIG9sZFZhbHVlKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLmNvbXB1dGVWYWx1ZSA9IGZ1bmN0aW9uICh0cmFjaykge1xuICAgICAgICB0aGlzLmlzQ29tcHV0aW5nID0gdHJ1ZTtcbiAgICAgICAgZ2xvYmFsU3RhdGUuY29tcHV0YXRpb25EZXB0aCsrO1xuICAgICAgICB2YXIgcmVzO1xuICAgICAgICBpZiAodHJhY2spIHtcbiAgICAgICAgICAgIHJlcyA9IHRyYWNrRGVyaXZlZEZ1bmN0aW9uKHRoaXMsIHRoaXMuZGVyaXZhdGlvbiwgdGhpcy5zY29wZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlcyA9IHRoaXMuZGVyaXZhdGlvbi5jYWxsKHRoaXMuc2NvcGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXMgPSBuZXcgQ2F1Z2h0RXhjZXB0aW9uKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdsb2JhbFN0YXRlLmNvbXB1dGF0aW9uRGVwdGgtLTtcbiAgICAgICAgdGhpcy5pc0NvbXB1dGluZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgO1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLm9ic2VydmUgPSBmdW5jdGlvbiAobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZmlyc3RUaW1lID0gdHJ1ZTtcbiAgICAgICAgdmFyIHByZXZWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIGF1dG9ydW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG5ld1ZhbHVlID0gX3RoaXMuZ2V0KCk7XG4gICAgICAgICAgICBpZiAoIWZpcnN0VGltZSB8fCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldlUgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiBfdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IG5ld1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZTogcHJldlZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpcnN0VGltZSA9IGZhbHNlO1xuICAgICAgICAgICAgcHJldlZhbHVlID0gbmV3VmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lICsgXCJbXCIgKyB0aGlzLmRlcml2YXRpb24udG9TdHJpbmcoKSArIFwiXVwiO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudmFsdWVPZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRvUHJpbWl0aXZlKHRoaXMuZ2V0KCkpO1xuICAgIH07XG4gICAgO1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLndoeVJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlzVHJhY2tpbmcgPSBCb29sZWFuKGdsb2JhbFN0YXRlLnRyYWNraW5nRGVyaXZhdGlvbik7XG4gICAgICAgIHZhciBvYnNlcnZpbmcgPSB1bmlxdWUodGhpcy5pc0NvbXB1dGluZyA/IHRoaXMubmV3T2JzZXJ2aW5nIDogdGhpcy5vYnNlcnZpbmcpLm1hcChmdW5jdGlvbiAoZGVwKSB7IHJldHVybiBkZXAubmFtZTsgfSk7XG4gICAgICAgIHZhciBvYnNlcnZlcnMgPSB1bmlxdWUoZ2V0T2JzZXJ2ZXJzKHRoaXMpLm1hcChmdW5jdGlvbiAoZGVwKSB7IHJldHVybiBkZXAubmFtZTsgfSkpO1xuICAgICAgICByZXR1cm4gKFwiXFxuV2h5UnVuPyBjb21wdXRhdGlvbiAnXCIgKyB0aGlzLm5hbWUgKyBcIic6XFxuICogUnVubmluZyBiZWNhdXNlOiBcIiArIChpc1RyYWNraW5nID8gXCJbYWN0aXZlXSB0aGUgdmFsdWUgb2YgdGhpcyBjb21wdXRhdGlvbiBpcyBuZWVkZWQgYnkgYSByZWFjdGlvblwiIDogdGhpcy5pc0NvbXB1dGluZyA/IFwiW2dldF0gVGhlIHZhbHVlIG9mIHRoaXMgY29tcHV0ZWQgd2FzIHJlcXVlc3RlZCBvdXRzaWRlIGEgcmVhY3Rpb25cIiA6IFwiW2lkbGVdIG5vdCBydW5uaW5nIGF0IHRoZSBtb21lbnRcIikgKyBcIlxcblwiICtcbiAgICAgICAgICAgICh0aGlzLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORyA/IGdldE1lc3NhZ2UoXCJtMDMyXCIpIDpcbiAgICAgICAgICAgICAgICBcIiAqIFRoaXMgY29tcHV0YXRpb24gd2lsbCByZS1ydW4gaWYgYW55IG9mIHRoZSBmb2xsb3dpbmcgb2JzZXJ2YWJsZXMgY2hhbmdlczpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZpbmcpICsgXCJcXG4gICAgXCIgKyAoKHRoaXMuaXNDb21wdXRpbmcgJiYgaXNUcmFja2luZykgPyBcIiAoLi4uIG9yIGFueSBvYnNlcnZhYmxlIGFjY2Vzc2VkIGR1cmluZyB0aGUgcmVtYWluZGVyIG9mIHRoZSBjdXJyZW50IHJ1bilcIiA6IFwiXCIpICsgXCJcXG5cXHRcIiArIGdldE1lc3NhZ2UoXCJtMDM4XCIpICsgXCJcXG5cXG4gICogSWYgdGhlIG91dGNvbWUgb2YgdGhpcyBjb21wdXRhdGlvbiBjaGFuZ2VzLCB0aGUgZm9sbG93aW5nIG9ic2VydmVycyB3aWxsIGJlIHJlLXJ1bjpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZlcnMpICsgXCJcXG5cIikpO1xuICAgIH07XG4gICAgcmV0dXJuIENvbXB1dGVkVmFsdWU7XG59KCkpO1xuQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGVbcHJpbWl0aXZlU3ltYm9sKCldID0gQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudmFsdWVPZjtcbnZhciBpc0NvbXB1dGVkVmFsdWUgPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiQ29tcHV0ZWRWYWx1ZVwiLCBDb21wdXRlZFZhbHVlKTtcbnZhciBJRGVyaXZhdGlvblN0YXRlO1xuKGZ1bmN0aW9uIChJRGVyaXZhdGlvblN0YXRlKSB7XG4gICAgSURlcml2YXRpb25TdGF0ZVtJRGVyaXZhdGlvblN0YXRlW1wiTk9UX1RSQUNLSU5HXCJdID0gLTFdID0gXCJOT1RfVFJBQ0tJTkdcIjtcbiAgICBJRGVyaXZhdGlvblN0YXRlW0lEZXJpdmF0aW9uU3RhdGVbXCJVUF9UT19EQVRFXCJdID0gMF0gPSBcIlVQX1RPX0RBVEVcIjtcbiAgICBJRGVyaXZhdGlvblN0YXRlW0lEZXJpdmF0aW9uU3RhdGVbXCJQT1NTSUJMWV9TVEFMRVwiXSA9IDFdID0gXCJQT1NTSUJMWV9TVEFMRVwiO1xuICAgIElEZXJpdmF0aW9uU3RhdGVbSURlcml2YXRpb25TdGF0ZVtcIlNUQUxFXCJdID0gMl0gPSBcIlNUQUxFXCI7XG59KShJRGVyaXZhdGlvblN0YXRlIHx8IChJRGVyaXZhdGlvblN0YXRlID0ge30pKTtcbmV4cG9ydHMuSURlcml2YXRpb25TdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGU7XG52YXIgQ2F1Z2h0RXhjZXB0aW9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYXVnaHRFeGNlcHRpb24oY2F1c2UpIHtcbiAgICAgICAgdGhpcy5jYXVzZSA9IGNhdXNlO1xuICAgIH1cbiAgICByZXR1cm4gQ2F1Z2h0RXhjZXB0aW9uO1xufSgpKTtcbmZ1bmN0aW9uIGlzQ2F1Z2h0RXhjZXB0aW9uKGUpIHtcbiAgICByZXR1cm4gZSBpbnN0YW5jZW9mIENhdWdodEV4Y2VwdGlvbjtcbn1cbmZ1bmN0aW9uIHNob3VsZENvbXB1dGUoZGVyaXZhdGlvbikge1xuICAgIHN3aXRjaCAoZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSkge1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTogcmV0dXJuIGZhbHNlO1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HOlxuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuU1RBTEU6IHJldHVybiB0cnVlO1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuUE9TU0lCTFlfU1RBTEU6IHtcbiAgICAgICAgICAgIHZhciBwcmV2VW50cmFja2VkID0gdW50cmFja2VkU3RhcnQoKTtcbiAgICAgICAgICAgIHZhciBvYnMgPSBkZXJpdmF0aW9uLm9ic2VydmluZywgbCA9IG9icy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBvYmogPSBvYnNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGlzQ29tcHV0ZWRWYWx1ZShvYmopKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmouZ2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVudHJhY2tlZEVuZChwcmV2VW50cmFja2VkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZXJpdmF0aW9uLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1bnRyYWNrZWRFbmQocHJldlVudHJhY2tlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoYW5nZURlcGVuZGVuY2llc1N0YXRlVG8wKGRlcml2YXRpb24pO1xuICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVbnRyYWNrZWQpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gaXNDb21wdXRpbmdEZXJpdmF0aW9uKCkge1xuICAgIHJldHVybiBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb24gIT09IG51bGw7XG59XG5mdW5jdGlvbiBjaGVja0lmU3RhdGVNb2RpZmljYXRpb25zQXJlQWxsb3dlZChhdG9tKSB7XG4gICAgdmFyIGhhc09ic2VydmVycyA9IGF0b20ub2JzZXJ2ZXJzLmxlbmd0aCA+IDA7XG4gICAgaWYgKGdsb2JhbFN0YXRlLmNvbXB1dGF0aW9uRGVwdGggPiAwICYmIGhhc09ic2VydmVycylcbiAgICAgICAgZmFpbChnZXRNZXNzYWdlKFwibTAzMVwiKSArIGF0b20ubmFtZSk7XG4gICAgaWYgKCFnbG9iYWxTdGF0ZS5hbGxvd1N0YXRlQ2hhbmdlcyAmJiBoYXNPYnNlcnZlcnMpXG4gICAgICAgIGZhaWwoZ2V0TWVzc2FnZShnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlID8gXCJtMDMwYVwiIDogXCJtMDMwYlwiKSArIGF0b20ubmFtZSk7XG59XG5mdW5jdGlvbiB0cmFja0Rlcml2ZWRGdW5jdGlvbihkZXJpdmF0aW9uLCBmLCBjb250ZXh0KSB7XG4gICAgY2hhbmdlRGVwZW5kZW5jaWVzU3RhdGVUbzAoZGVyaXZhdGlvbik7XG4gICAgZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmcgPSBuZXcgQXJyYXkoZGVyaXZhdGlvbi5vYnNlcnZpbmcubGVuZ3RoICsgMTAwKTtcbiAgICBkZXJpdmF0aW9uLnVuYm91bmREZXBzQ291bnQgPSAwO1xuICAgIGRlcml2YXRpb24ucnVuSWQgPSArK2dsb2JhbFN0YXRlLnJ1bklkO1xuICAgIHZhciBwcmV2VHJhY2tpbmcgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gZGVyaXZhdGlvbjtcbiAgICB2YXIgcmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICAgIHJlc3VsdCA9IGYuY2FsbChjb250ZXh0KTtcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVzdWx0ID0gbmV3IENhdWdodEV4Y2VwdGlvbihlKTtcbiAgICB9XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gcHJldlRyYWNraW5nO1xuICAgIGJpbmREZXBlbmRlbmNpZXMoZGVyaXZhdGlvbik7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGJpbmREZXBlbmRlbmNpZXMoZGVyaXZhdGlvbikge1xuICAgIHZhciBwcmV2T2JzZXJ2aW5nID0gZGVyaXZhdGlvbi5vYnNlcnZpbmc7XG4gICAgdmFyIG9ic2VydmluZyA9IGRlcml2YXRpb24ub2JzZXJ2aW5nID0gZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmc7XG4gICAgZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmcgPSBudWxsO1xuICAgIHZhciBpMCA9IDAsIGwgPSBkZXJpdmF0aW9uLnVuYm91bmREZXBzQ291bnQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgdmFyIGRlcCA9IG9ic2VydmluZ1tpXTtcbiAgICAgICAgaWYgKGRlcC5kaWZmVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIGRlcC5kaWZmVmFsdWUgPSAxO1xuICAgICAgICAgICAgaWYgKGkwICE9PSBpKVxuICAgICAgICAgICAgICAgIG9ic2VydmluZ1tpMF0gPSBkZXA7XG4gICAgICAgICAgICBpMCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIG9ic2VydmluZy5sZW5ndGggPSBpMDtcbiAgICBsID0gcHJldk9ic2VydmluZy5sZW5ndGg7XG4gICAgd2hpbGUgKGwtLSkge1xuICAgICAgICB2YXIgZGVwID0gcHJldk9ic2VydmluZ1tsXTtcbiAgICAgICAgaWYgKGRlcC5kaWZmVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIHJlbW92ZU9ic2VydmVyKGRlcCwgZGVyaXZhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZGVwLmRpZmZWYWx1ZSA9IDA7XG4gICAgfVxuICAgIHdoaWxlIChpMC0tKSB7XG4gICAgICAgIHZhciBkZXAgPSBvYnNlcnZpbmdbaTBdO1xuICAgICAgICBpZiAoZGVwLmRpZmZWYWx1ZSA9PT0gMSkge1xuICAgICAgICAgICAgZGVwLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgICAgICBhZGRPYnNlcnZlcihkZXAsIGRlcml2YXRpb24pO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gY2xlYXJPYnNlcnZpbmcoZGVyaXZhdGlvbikge1xuICAgIHZhciBvYnMgPSBkZXJpdmF0aW9uLm9ic2VydmluZztcbiAgICB2YXIgaSA9IG9icy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSlcbiAgICAgICAgcmVtb3ZlT2JzZXJ2ZXIob2JzW2ldLCBkZXJpdmF0aW9uKTtcbiAgICBkZXJpdmF0aW9uLmRlcGVuZGVuY2llc1N0YXRlID0gSURlcml2YXRpb25TdGF0ZS5OT1RfVFJBQ0tJTkc7XG4gICAgb2JzLmxlbmd0aCA9IDA7XG59XG5mdW5jdGlvbiB1bnRyYWNrZWQoYWN0aW9uKSB7XG4gICAgdmFyIHByZXYgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgIHZhciByZXMgPSBhY3Rpb24oKTtcbiAgICB1bnRyYWNrZWRFbmQocHJldik7XG4gICAgcmV0dXJuIHJlcztcbn1cbmV4cG9ydHMudW50cmFja2VkID0gdW50cmFja2VkO1xuZnVuY3Rpb24gdW50cmFja2VkU3RhcnQoKSB7XG4gICAgdmFyIHByZXYgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gbnVsbDtcbiAgICByZXR1cm4gcHJldjtcbn1cbmZ1bmN0aW9uIHVudHJhY2tlZEVuZChwcmV2KSB7XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gcHJldjtcbn1cbmZ1bmN0aW9uIGNoYW5nZURlcGVuZGVuY2llc1N0YXRlVG8wKGRlcml2YXRpb24pIHtcbiAgICBpZiAoZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFKVxuICAgICAgICByZXR1cm47XG4gICAgZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTtcbiAgICB2YXIgb2JzID0gZGVyaXZhdGlvbi5vYnNlcnZpbmc7XG4gICAgdmFyIGkgPSBvYnMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0pXG4gICAgICAgIG9ic1tpXS5sb3dlc3RPYnNlcnZlclN0YXRlID0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFO1xufVxudmFyIHBlcnNpc3RlbnRLZXlzID0gW1wibW9ieEd1aWRcIiwgXCJyZXNldElkXCIsIFwic3B5TGlzdGVuZXJzXCIsIFwic3RyaWN0TW9kZVwiLCBcInJ1bklkXCJdO1xudmFyIE1vYlhHbG9iYWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBNb2JYR2xvYmFscygpIHtcbiAgICAgICAgdGhpcy52ZXJzaW9uID0gNTtcbiAgICAgICAgdGhpcy50cmFja2luZ0Rlcml2YXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLmNvbXB1dGF0aW9uRGVwdGggPSAwO1xuICAgICAgICB0aGlzLnJ1bklkID0gMDtcbiAgICAgICAgdGhpcy5tb2J4R3VpZCA9IDA7XG4gICAgICAgIHRoaXMuaW5CYXRjaCA9IDA7XG4gICAgICAgIHRoaXMucGVuZGluZ1Vub2JzZXJ2YXRpb25zID0gW107XG4gICAgICAgIHRoaXMucGVuZGluZ1JlYWN0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmlzUnVubmluZ1JlYWN0aW9ucyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFsbG93U3RhdGVDaGFuZ2VzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHJpY3RNb2RlID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVzZXRJZCA9IDA7XG4gICAgICAgIHRoaXMuc3B5TGlzdGVuZXJzID0gW107XG4gICAgICAgIHRoaXMuZ2xvYmFsUmVhY3Rpb25FcnJvckhhbmRsZXJzID0gW107XG4gICAgfVxuICAgIHJldHVybiBNb2JYR2xvYmFscztcbn0oKSk7XG52YXIgZ2xvYmFsU3RhdGUgPSBuZXcgTW9iWEdsb2JhbHMoKTtcbmZ1bmN0aW9uIHNoYXJlR2xvYmFsU3RhdGUoKSB7XG4gICAgdmFyIGdsb2JhbCA9IGdldEdsb2JhbCgpO1xuICAgIHZhciBvd25TdGF0ZSA9IGdsb2JhbFN0YXRlO1xuICAgIGlmIChnbG9iYWwuX19tb2JzZXJ2YWJsZVRyYWNraW5nU3RhY2sgfHwgZ2xvYmFsLl9fbW9ic2VydmFibGVWaWV3U3RhY2spXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4XSBBbiBpbmNvbXBhdGlibGUgdmVyc2lvbiBvZiBtb2JzZXJ2YWJsZSBpcyBhbHJlYWR5IGxvYWRlZC5cIik7XG4gICAgaWYgKGdsb2JhbC5fX21vYnhHbG9iYWwgJiYgZ2xvYmFsLl9fbW9ieEdsb2JhbC52ZXJzaW9uICE9PSBvd25TdGF0ZS52ZXJzaW9uKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieF0gQW4gaW5jb21wYXRpYmxlIHZlcnNpb24gb2YgbW9ieCBpcyBhbHJlYWR5IGxvYWRlZC5cIik7XG4gICAgaWYgKGdsb2JhbC5fX21vYnhHbG9iYWwpXG4gICAgICAgIGdsb2JhbFN0YXRlID0gZ2xvYmFsLl9fbW9ieEdsb2JhbDtcbiAgICBlbHNlXG4gICAgICAgIGdsb2JhbC5fX21vYnhHbG9iYWwgPSBvd25TdGF0ZTtcbn1cbmZ1bmN0aW9uIGdldEdsb2JhbFN0YXRlKCkge1xuICAgIHJldHVybiBnbG9iYWxTdGF0ZTtcbn1cbmZ1bmN0aW9uIHJlZ2lzdGVyR2xvYmFscygpIHtcbn1cbmZ1bmN0aW9uIHJlc2V0R2xvYmFsU3RhdGUoKSB7XG4gICAgZ2xvYmFsU3RhdGUucmVzZXRJZCsrO1xuICAgIHZhciBkZWZhdWx0R2xvYmFscyA9IG5ldyBNb2JYR2xvYmFscygpO1xuICAgIGZvciAodmFyIGtleSBpbiBkZWZhdWx0R2xvYmFscylcbiAgICAgICAgaWYgKHBlcnNpc3RlbnRLZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpXG4gICAgICAgICAgICBnbG9iYWxTdGF0ZVtrZXldID0gZGVmYXVsdEdsb2JhbHNba2V5XTtcbiAgICBnbG9iYWxTdGF0ZS5hbGxvd1N0YXRlQ2hhbmdlcyA9ICFnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlO1xufVxuZnVuY3Rpb24gaGFzT2JzZXJ2ZXJzKG9ic2VydmFibGUpIHtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5vYnNlcnZlcnMgJiYgb2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID4gMDtcbn1cbmZ1bmN0aW9uIGdldE9ic2VydmVycyhvYnNlcnZhYmxlKSB7XG4gICAgcmV0dXJuIG9ic2VydmFibGUub2JzZXJ2ZXJzO1xufVxuZnVuY3Rpb24gaW52YXJpYW50T2JzZXJ2ZXJzKG9ic2VydmFibGUpIHtcbiAgICB2YXIgbGlzdCA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBtYXAgPSBvYnNlcnZhYmxlLm9ic2VydmVyc0luZGV4ZXM7XG4gICAgdmFyIGwgPSBsaXN0Lmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBsaXN0W2ldLl9fbWFwaWQ7XG4gICAgICAgIGlmIChpKSB7XG4gICAgICAgICAgICBpbnZhcmlhbnQobWFwW2lkXSA9PT0gaSwgXCJJTlRFUk5BTCBFUlJPUiBtYXBzIGRlcml2YXRpb24uX19tYXBpZCB0byBpbmRleCBpbiBsaXN0XCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaW52YXJpYW50KCEoaWQgaW4gbWFwKSwgXCJJTlRFUk5BTCBFUlJPUiBvYnNlcnZlciBvbiBpbmRleCAwIHNob3VsZG50IGJlIGhlbGQgaW4gbWFwLlwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpbnZhcmlhbnQobGlzdC5sZW5ndGggPT09IDAgfHwgT2JqZWN0LmtleXMobWFwKS5sZW5ndGggPT09IGxpc3QubGVuZ3RoIC0gMSwgXCJJTlRFUk5BTCBFUlJPUiB0aGVyZSBpcyBubyBqdW5rIGluIG1hcFwiKTtcbn1cbmZ1bmN0aW9uIGFkZE9ic2VydmVyKG9ic2VydmFibGUsIG5vZGUpIHtcbiAgICB2YXIgbCA9IG9ic2VydmFibGUub2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICBpZiAobCkge1xuICAgICAgICBvYnNlcnZhYmxlLm9ic2VydmVyc0luZGV4ZXNbbm9kZS5fX21hcGlkXSA9IGw7XG4gICAgfVxuICAgIG9ic2VydmFibGUub2JzZXJ2ZXJzW2xdID0gbm9kZTtcbiAgICBpZiAob2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlID4gbm9kZS5kZXBlbmRlbmNpZXNTdGF0ZSlcbiAgICAgICAgb2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlID0gbm9kZS5kZXBlbmRlbmNpZXNTdGF0ZTtcbn1cbmZ1bmN0aW9uIHJlbW92ZU9ic2VydmVyKG9ic2VydmFibGUsIG5vZGUpIHtcbiAgICBpZiAob2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIG9ic2VydmFibGUub2JzZXJ2ZXJzLmxlbmd0aCA9IDA7XG4gICAgICAgIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBsaXN0ID0gb2JzZXJ2YWJsZS5vYnNlcnZlcnM7XG4gICAgICAgIHZhciBtYXBfMSA9IG9ic2VydmFibGUub2JzZXJ2ZXJzSW5kZXhlcztcbiAgICAgICAgdmFyIGZpbGxlciA9IGxpc3QucG9wKCk7XG4gICAgICAgIGlmIChmaWxsZXIgIT09IG5vZGUpIHtcbiAgICAgICAgICAgIHZhciBpbmRleCA9IG1hcF8xW25vZGUuX19tYXBpZF0gfHwgMDtcbiAgICAgICAgICAgIGlmIChpbmRleCkge1xuICAgICAgICAgICAgICAgIG1hcF8xW2ZpbGxlci5fX21hcGlkXSA9IGluZGV4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG1hcF8xW2ZpbGxlci5fX21hcGlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpc3RbaW5kZXhdID0gZmlsbGVyO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSBtYXBfMVtub2RlLl9fbWFwaWRdO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKSB7XG4gICAgaWYgKCFvYnNlcnZhYmxlLmlzUGVuZGluZ1Vub2JzZXJ2YXRpb24pIHtcbiAgICAgICAgb2JzZXJ2YWJsZS5pc1BlbmRpbmdVbm9ic2VydmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgZ2xvYmFsU3RhdGUucGVuZGluZ1Vub2JzZXJ2YXRpb25zLnB1c2gob2JzZXJ2YWJsZSk7XG4gICAgfVxufVxuZnVuY3Rpb24gc3RhcnRCYXRjaCgpIHtcbiAgICBnbG9iYWxTdGF0ZS5pbkJhdGNoKys7XG59XG5mdW5jdGlvbiBlbmRCYXRjaCgpIHtcbiAgICBpZiAoLS1nbG9iYWxTdGF0ZS5pbkJhdGNoID09PSAwKSB7XG4gICAgICAgIHJ1blJlYWN0aW9ucygpO1xuICAgICAgICB2YXIgbGlzdCA9IGdsb2JhbFN0YXRlLnBlbmRpbmdVbm9ic2VydmF0aW9ucztcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb2JzZXJ2YWJsZV8xID0gbGlzdFtpXTtcbiAgICAgICAgICAgIG9ic2VydmFibGVfMS5pc1BlbmRpbmdVbm9ic2VydmF0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAob2JzZXJ2YWJsZV8xLm9ic2VydmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBvYnNlcnZhYmxlXzEub25CZWNvbWVVbm9ic2VydmVkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2xvYmFsU3RhdGUucGVuZGluZ1Vub2JzZXJ2YXRpb25zID0gW107XG4gICAgfVxufVxuZnVuY3Rpb24gcmVwb3J0T2JzZXJ2ZWQob2JzZXJ2YWJsZSkge1xuICAgIHZhciBkZXJpdmF0aW9uID0gZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uO1xuICAgIGlmIChkZXJpdmF0aW9uICE9PSBudWxsKSB7XG4gICAgICAgIGlmIChkZXJpdmF0aW9uLnJ1bklkICE9PSBvYnNlcnZhYmxlLmxhc3RBY2Nlc3NlZEJ5KSB7XG4gICAgICAgICAgICBvYnNlcnZhYmxlLmxhc3RBY2Nlc3NlZEJ5ID0gZGVyaXZhdGlvbi5ydW5JZDtcbiAgICAgICAgICAgIGRlcml2YXRpb24ubmV3T2JzZXJ2aW5nW2Rlcml2YXRpb24udW5ib3VuZERlcHNDb3VudCsrXSA9IG9ic2VydmFibGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAob2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBpbnZhcmlhbnRMT1Mob2JzZXJ2YWJsZSwgbXNnKSB7XG4gICAgdmFyIG1pbiA9IGdldE9ic2VydmVycyhvYnNlcnZhYmxlKS5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIE1hdGgubWluKGEsIGIuZGVwZW5kZW5jaWVzU3RhdGUpOyB9LCAyKTtcbiAgICBpZiAobWluID49IG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSlcbiAgICAgICAgcmV0dXJuO1xuICAgIHRocm93IG5ldyBFcnJvcihcImxvd2VzdE9ic2VydmVyU3RhdGUgaXMgd3JvbmcgZm9yIFwiICsgbXNnICsgXCIgYmVjYXVzZSBcIiArIG1pbiArIFwiIDwgXCIgKyBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUpO1xufVxuZnVuY3Rpb24gcHJvcGFnYXRlQ2hhbmdlZChvYnNlcnZhYmxlKSB7XG4gICAgaWYgKG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5TVEFMRSlcbiAgICAgICAgcmV0dXJuO1xuICAgIG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuU1RBTEU7XG4gICAgdmFyIG9ic2VydmVycyA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBpID0gb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIHZhciBkID0gb2JzZXJ2ZXJzW2ldO1xuICAgICAgICBpZiAoZC5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFKVxuICAgICAgICAgICAgZC5vbkJlY29tZVN0YWxlKCk7XG4gICAgICAgIGQuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHByb3BhZ2F0ZUNoYW5nZUNvbmZpcm1lZChvYnNlcnZhYmxlKSB7XG4gICAgaWYgKG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5TVEFMRSlcbiAgICAgICAgcmV0dXJuO1xuICAgIG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuU1RBTEU7XG4gICAgdmFyIG9ic2VydmVycyA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBpID0gb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIHZhciBkID0gb2JzZXJ2ZXJzW2ldO1xuICAgICAgICBpZiAoZC5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5QT1NTSUJMWV9TVEFMRSlcbiAgICAgICAgICAgIGQuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFO1xuICAgICAgICBlbHNlIGlmIChkLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEUpXG4gICAgICAgICAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEU7XG4gICAgfVxufVxuZnVuY3Rpb24gcHJvcGFnYXRlTWF5YmVDaGFuZ2VkKG9ic2VydmFibGUpIHtcbiAgICBpZiAob2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlICE9PSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEUpXG4gICAgICAgIHJldHVybjtcbiAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlBPU1NJQkxZX1NUQUxFO1xuICAgIHZhciBvYnNlcnZlcnMgPSBvYnNlcnZhYmxlLm9ic2VydmVycztcbiAgICB2YXIgaSA9IG9ic2VydmVycy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgICB2YXIgZCA9IG9ic2VydmVyc1tpXTtcbiAgICAgICAgaWYgKGQuZGVwZW5kZW5jaWVzU3RhdGUgPT09IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURSkge1xuICAgICAgICAgICAgZC5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuUE9TU0lCTFlfU1RBTEU7XG4gICAgICAgICAgICBkLm9uQmVjb21lU3RhbGUoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbnZhciBSZWFjdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUmVhY3Rpb24obmFtZSwgb25JbnZhbGlkYXRlKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiUmVhY3Rpb25AXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm9uSW52YWxpZGF0ZSA9IG9uSW52YWxpZGF0ZTtcbiAgICAgICAgdGhpcy5vYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5uZXdPYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HO1xuICAgICAgICB0aGlzLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgIHRoaXMucnVuSWQgPSAwO1xuICAgICAgICB0aGlzLnVuYm91bmREZXBzQ291bnQgPSAwO1xuICAgICAgICB0aGlzLl9fbWFwaWQgPSBcIiNcIiArIGdldE5leHRJZCgpO1xuICAgICAgICB0aGlzLmlzRGlzcG9zZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNUcmFja1BlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgfVxuICAgIFJlYWN0aW9uLnByb3RvdHlwZS5vbkJlY29tZVN0YWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlKCk7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuc2NoZWR1bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5faXNTY2hlZHVsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2lzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlLnBlbmRpbmdSZWFjdGlvbnMucHVzaCh0aGlzKTtcbiAgICAgICAgICAgIHJ1blJlYWN0aW9ucygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuaXNTY2hlZHVsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1NjaGVkdWxlZDtcbiAgICB9O1xuICAgIFJlYWN0aW9uLnByb3RvdHlwZS5ydW5SZWFjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgIHRoaXMuX2lzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoc2hvdWxkQ29tcHV0ZSh0aGlzKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2lzVHJhY2tQZW5kaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uSW52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1RyYWNrUGVuZGluZyAmJiBpc1NweUVuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBzcHlSZXBvcnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzY2hlZHVsZWQtcmVhY3Rpb25cIlxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUudHJhY2sgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgc3RhcnRCYXRjaCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBzdGFydFRpbWU7XG4gICAgICAgIGlmIChub3RpZnkpIHtcbiAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydCh7XG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIHR5cGU6IFwicmVhY3Rpb25cIixcbiAgICAgICAgICAgICAgICBmbjogZm5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lzUnVubmluZyA9IHRydWU7XG4gICAgICAgIHZhciByZXN1bHQgPSB0cmFja0Rlcml2ZWRGdW5jdGlvbih0aGlzLCBmbiwgdW5kZWZpbmVkKTtcbiAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lzVHJhY2tQZW5kaW5nID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIGNsZWFyT2JzZXJ2aW5nKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0NhdWdodEV4Y2VwdGlvbihyZXN1bHQpKVxuICAgICAgICAgICAgdGhpcy5yZXBvcnRFeGNlcHRpb25JbkRlcml2YXRpb24ocmVzdWx0LmNhdXNlKTtcbiAgICAgICAgaWYgKG5vdGlmeSkge1xuICAgICAgICAgICAgc3B5UmVwb3J0RW5kKHtcbiAgICAgICAgICAgICAgICB0aW1lOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbmRCYXRjaCgpO1xuICAgIH07XG4gICAgUmVhY3Rpb24ucHJvdG90eXBlLnJlcG9ydEV4Y2VwdGlvbkluRGVyaXZhdGlvbiA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5lcnJvckhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyKGVycm9yLCB0aGlzKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWVzc2FnZSA9IFwiW21vYnhdIEVuY291bnRlcmVkIGFuIHVuY2F1Z2h0IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24gYnkgYSByZWFjdGlvbiBvciBvYnNlcnZlciBjb21wb25lbnQsIGluOiAnXCIgKyB0aGlzO1xuICAgICAgICB2YXIgbWVzc2FnZVRvVXNlciA9IGdldE1lc3NhZ2UoXCJtMDM3XCIpO1xuICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UgfHwgbWVzc2FnZVRvVXNlciwgZXJyb3IpO1xuICAgICAgICBpZiAoaXNTcHlFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHNweVJlcG9ydCh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2xvYmFsU3RhdGUuZ2xvYmFsUmVhY3Rpb25FcnJvckhhbmRsZXJzLmZvckVhY2goZnVuY3Rpb24gKGYpIHsgcmV0dXJuIGYoZXJyb3IsIF90aGlzKTsgfSk7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuZGlzcG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaXNEaXNwb3NlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzUnVubmluZykge1xuICAgICAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgICAgICBjbGVhck9ic2VydmluZyh0aGlzKTtcbiAgICAgICAgICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuZ2V0RGlzcG9zZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByID0gdGhpcy5kaXNwb3NlLmJpbmQodGhpcyk7XG4gICAgICAgIHIuJG1vYnggPSB0aGlzO1xuICAgICAgICByLm9uRXJyb3IgPSByZWdpc3RlckVycm9ySGFuZGxlcjtcbiAgICAgICAgcmV0dXJuIHI7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlJlYWN0aW9uW1wiICsgdGhpcy5uYW1lICsgXCJdXCI7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUud2h5UnVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb2JzZXJ2aW5nID0gdW5pcXVlKHRoaXMuX2lzUnVubmluZyA/IHRoaXMubmV3T2JzZXJ2aW5nIDogdGhpcy5vYnNlcnZpbmcpLm1hcChmdW5jdGlvbiAoZGVwKSB7IHJldHVybiBkZXAubmFtZTsgfSk7XG4gICAgICAgIHJldHVybiAoXCJcXG5XaHlSdW4/IHJlYWN0aW9uICdcIiArIHRoaXMubmFtZSArIFwiJzpcXG4gKiBTdGF0dXM6IFtcIiArICh0aGlzLmlzRGlzcG9zZWQgPyBcInN0b3BwZWRcIiA6IHRoaXMuX2lzUnVubmluZyA/IFwicnVubmluZ1wiIDogdGhpcy5pc1NjaGVkdWxlZCgpID8gXCJzY2hlZHVsZWRcIiA6IFwiaWRsZVwiKSArIFwiXVxcbiAqIFRoaXMgcmVhY3Rpb24gd2lsbCByZS1ydW4gaWYgYW55IG9mIHRoZSBmb2xsb3dpbmcgb2JzZXJ2YWJsZXMgY2hhbmdlczpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZpbmcpICsgXCJcXG4gICAgXCIgKyAoKHRoaXMuX2lzUnVubmluZykgPyBcIiAoLi4uIG9yIGFueSBvYnNlcnZhYmxlIGFjY2Vzc2VkIGR1cmluZyB0aGUgcmVtYWluZGVyIG9mIHRoZSBjdXJyZW50IHJ1bilcIiA6IFwiXCIpICsgXCJcXG5cXHRcIiArIGdldE1lc3NhZ2UoXCJtMDM4XCIpICsgXCJcXG5cIik7XG4gICAgfTtcbiAgICByZXR1cm4gUmVhY3Rpb247XG59KCkpO1xuZXhwb3J0cy5SZWFjdGlvbiA9IFJlYWN0aW9uO1xuZnVuY3Rpb24gcmVnaXN0ZXJFcnJvckhhbmRsZXIoaGFuZGxlcikge1xuICAgIGludmFyaWFudCh0aGlzICYmIHRoaXMuJG1vYnggJiYgaXNSZWFjdGlvbih0aGlzLiRtb2J4KSwgXCJJbnZhbGlkIGB0aGlzYFwiKTtcbiAgICBpbnZhcmlhbnQoIXRoaXMuJG1vYnguZXJyb3JIYW5kbGVyLCBcIk9ubHkgb25lIG9uRXJyb3JIYW5kbGVyIGNhbiBiZSByZWdpc3RlcmVkXCIpO1xuICAgIHRoaXMuJG1vYnguZXJyb3JIYW5kbGVyID0gaGFuZGxlcjtcbn1cbmZ1bmN0aW9uIG9uUmVhY3Rpb25FcnJvcihoYW5kbGVyKSB7XG4gICAgZ2xvYmFsU3RhdGUuZ2xvYmFsUmVhY3Rpb25FcnJvckhhbmRsZXJzLnB1c2goaGFuZGxlcik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlkeCA9IGdsb2JhbFN0YXRlLmdsb2JhbFJlYWN0aW9uRXJyb3JIYW5kbGVycy5pbmRleE9mKGhhbmRsZXIpO1xuICAgICAgICBpZiAoaWR4ID49IDApXG4gICAgICAgICAgICBnbG9iYWxTdGF0ZS5nbG9iYWxSZWFjdGlvbkVycm9ySGFuZGxlcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgfTtcbn1cbnZhciBNQVhfUkVBQ1RJT05fSVRFUkFUSU9OUyA9IDEwMDtcbnZhciByZWFjdGlvblNjaGVkdWxlciA9IGZ1bmN0aW9uIChmKSB7IHJldHVybiBmKCk7IH07XG5mdW5jdGlvbiBydW5SZWFjdGlvbnMoKSB7XG4gICAgaWYgKGdsb2JhbFN0YXRlLmluQmF0Y2ggPiAwIHx8IGdsb2JhbFN0YXRlLmlzUnVubmluZ1JlYWN0aW9ucylcbiAgICAgICAgcmV0dXJuO1xuICAgIHJlYWN0aW9uU2NoZWR1bGVyKHJ1blJlYWN0aW9uc0hlbHBlcik7XG59XG5mdW5jdGlvbiBydW5SZWFjdGlvbnNIZWxwZXIoKSB7XG4gICAgZ2xvYmFsU3RhdGUuaXNSdW5uaW5nUmVhY3Rpb25zID0gdHJ1ZTtcbiAgICB2YXIgYWxsUmVhY3Rpb25zID0gZ2xvYmFsU3RhdGUucGVuZGluZ1JlYWN0aW9ucztcbiAgICB2YXIgaXRlcmF0aW9ucyA9IDA7XG4gICAgd2hpbGUgKGFsbFJlYWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGlmICgrK2l0ZXJhdGlvbnMgPT09IE1BWF9SRUFDVElPTl9JVEVSQVRJT05TKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiUmVhY3Rpb24gZG9lc24ndCBjb252ZXJnZSB0byBhIHN0YWJsZSBzdGF0ZSBhZnRlciBcIiArIE1BWF9SRUFDVElPTl9JVEVSQVRJT05TICsgXCIgaXRlcmF0aW9ucy5cIlxuICAgICAgICAgICAgICAgICsgKFwiIFByb2JhYmx5IHRoZXJlIGlzIGEgY3ljbGUgaW4gdGhlIHJlYWN0aXZlIGZ1bmN0aW9uOiBcIiArIGFsbFJlYWN0aW9uc1swXSkpO1xuICAgICAgICAgICAgYWxsUmVhY3Rpb25zLnNwbGljZSgwKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVtYWluaW5nUmVhY3Rpb25zID0gYWxsUmVhY3Rpb25zLnNwbGljZSgwKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSByZW1haW5pbmdSZWFjdGlvbnMubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgcmVtYWluaW5nUmVhY3Rpb25zW2ldLnJ1blJlYWN0aW9uKCk7XG4gICAgfVxuICAgIGdsb2JhbFN0YXRlLmlzUnVubmluZ1JlYWN0aW9ucyA9IGZhbHNlO1xufVxudmFyIGlzUmVhY3Rpb24gPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiUmVhY3Rpb25cIiwgUmVhY3Rpb24pO1xuZnVuY3Rpb24gc2V0UmVhY3Rpb25TY2hlZHVsZXIoZm4pIHtcbiAgICB2YXIgYmFzZVNjaGVkdWxlciA9IHJlYWN0aW9uU2NoZWR1bGVyO1xuICAgIHJlYWN0aW9uU2NoZWR1bGVyID0gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIGZuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGJhc2VTY2hlZHVsZXIoZik7IH0pOyB9O1xufVxuZnVuY3Rpb24gaXNTcHlFbmFibGVkKCkge1xuICAgIHJldHVybiAhIWdsb2JhbFN0YXRlLnNweUxpc3RlbmVycy5sZW5ndGg7XG59XG5mdW5jdGlvbiBzcHlSZXBvcnQoZXZlbnQpIHtcbiAgICBpZiAoIWdsb2JhbFN0YXRlLnNweUxpc3RlbmVycy5sZW5ndGgpXG4gICAgICAgIHJldHVybjtcbiAgICB2YXIgbGlzdGVuZXJzID0gZ2xvYmFsU3RhdGUuc3B5TGlzdGVuZXJzO1xuICAgIGZvciAodmFyIGkgPSAwLCBsID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGw7IGkrKylcbiAgICAgICAgbGlzdGVuZXJzW2ldKGV2ZW50KTtcbn1cbmZ1bmN0aW9uIHNweVJlcG9ydFN0YXJ0KGV2ZW50KSB7XG4gICAgdmFyIGNoYW5nZSA9IG9iamVjdEFzc2lnbih7fSwgZXZlbnQsIHsgc3B5UmVwb3J0U3RhcnQ6IHRydWUgfSk7XG4gICAgc3B5UmVwb3J0KGNoYW5nZSk7XG59XG52YXIgRU5EX0VWRU5UID0geyBzcHlSZXBvcnRFbmQ6IHRydWUgfTtcbmZ1bmN0aW9uIHNweVJlcG9ydEVuZChjaGFuZ2UpIHtcbiAgICBpZiAoY2hhbmdlKVxuICAgICAgICBzcHlSZXBvcnQob2JqZWN0QXNzaWduKHt9LCBjaGFuZ2UsIEVORF9FVkVOVCkpO1xuICAgIGVsc2VcbiAgICAgICAgc3B5UmVwb3J0KEVORF9FVkVOVCk7XG59XG5mdW5jdGlvbiBzcHkobGlzdGVuZXIpIHtcbiAgICBnbG9iYWxTdGF0ZS5zcHlMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7XG4gICAgcmV0dXJuIG9uY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaWR4ID0gZ2xvYmFsU3RhdGUuc3B5TGlzdGVuZXJzLmluZGV4T2YobGlzdGVuZXIpO1xuICAgICAgICBpZiAoaWR4ICE9PSAtMSlcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlLnNweUxpc3RlbmVycy5zcGxpY2UoaWR4LCAxKTtcbiAgICB9KTtcbn1cbmV4cG9ydHMuc3B5ID0gc3B5O1xuZnVuY3Rpb24gaGFzSW50ZXJjZXB0b3JzKGludGVyY2VwdGFibGUpIHtcbiAgICByZXR1cm4gKGludGVyY2VwdGFibGUuaW50ZXJjZXB0b3JzICYmIGludGVyY2VwdGFibGUuaW50ZXJjZXB0b3JzLmxlbmd0aCA+IDApO1xufVxuZnVuY3Rpb24gcmVnaXN0ZXJJbnRlcmNlcHRvcihpbnRlcmNlcHRhYmxlLCBoYW5kbGVyKSB7XG4gICAgdmFyIGludGVyY2VwdG9ycyA9IGludGVyY2VwdGFibGUuaW50ZXJjZXB0b3JzIHx8IChpbnRlcmNlcHRhYmxlLmludGVyY2VwdG9ycyA9IFtdKTtcbiAgICBpbnRlcmNlcHRvcnMucHVzaChoYW5kbGVyKTtcbiAgICByZXR1cm4gb25jZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpZHggPSBpbnRlcmNlcHRvcnMuaW5kZXhPZihoYW5kbGVyKTtcbiAgICAgICAgaWYgKGlkeCAhPT0gLTEpXG4gICAgICAgICAgICBpbnRlcmNlcHRvcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBpbnRlcmNlcHRDaGFuZ2UoaW50ZXJjZXB0YWJsZSwgY2hhbmdlKSB7XG4gICAgdmFyIHByZXZVID0gdW50cmFja2VkU3RhcnQoKTtcbiAgICB0cnkge1xuICAgICAgICB2YXIgaW50ZXJjZXB0b3JzID0gaW50ZXJjZXB0YWJsZS5pbnRlcmNlcHRvcnM7XG4gICAgICAgIGlmIChpbnRlcmNlcHRvcnMpXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGludGVyY2VwdG9ycy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjaGFuZ2UgPSBpbnRlcmNlcHRvcnNbaV0oY2hhbmdlKTtcbiAgICAgICAgICAgICAgICBpbnZhcmlhbnQoIWNoYW5nZSB8fCBjaGFuZ2UudHlwZSwgXCJJbnRlcmNlcHQgaGFuZGxlcnMgc2hvdWxkIHJldHVybiBub3RoaW5nIG9yIGEgY2hhbmdlIG9iamVjdFwiKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaGFuZ2U7XG4gICAgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB1bnRyYWNrZWRFbmQocHJldlUpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGhhc0xpc3RlbmVycyhsaXN0ZW5hYmxlKSB7XG4gICAgcmV0dXJuIGxpc3RlbmFibGUuY2hhbmdlTGlzdGVuZXJzICYmIGxpc3RlbmFibGUuY2hhbmdlTGlzdGVuZXJzLmxlbmd0aCA+IDA7XG59XG5mdW5jdGlvbiByZWdpc3Rlckxpc3RlbmVyKGxpc3RlbmFibGUsIGhhbmRsZXIpIHtcbiAgICB2YXIgbGlzdGVuZXJzID0gbGlzdGVuYWJsZS5jaGFuZ2VMaXN0ZW5lcnMgfHwgKGxpc3RlbmFibGUuY2hhbmdlTGlzdGVuZXJzID0gW10pO1xuICAgIGxpc3RlbmVycy5wdXNoKGhhbmRsZXIpO1xuICAgIHJldHVybiBvbmNlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlkeCA9IGxpc3RlbmVycy5pbmRleE9mKGhhbmRsZXIpO1xuICAgICAgICBpZiAoaWR4ICE9PSAtMSlcbiAgICAgICAgICAgIGxpc3RlbmVycy5zcGxpY2UoaWR4LCAxKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIG5vdGlmeUxpc3RlbmVycyhsaXN0ZW5hYmxlLCBjaGFuZ2UpIHtcbiAgICB2YXIgcHJldlUgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBsaXN0ZW5hYmxlLmNoYW5nZUxpc3RlbmVycztcbiAgICBpZiAoIWxpc3RlbmVycylcbiAgICAgICAgcmV0dXJuO1xuICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5zbGljZSgpO1xuICAgIGZvciAodmFyIGkgPSAwLCBsID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICBsaXN0ZW5lcnNbaV0oY2hhbmdlKTtcbiAgICB9XG4gICAgdW50cmFja2VkRW5kKHByZXZVKTtcbn1cbmZ1bmN0aW9uIGFzUmVmZXJlbmNlKHZhbHVlKSB7XG4gICAgZGVwcmVjYXRlZChcImFzUmVmZXJlbmNlIGlzIGRlcHJlY2F0ZWQsIHVzZSBvYnNlcnZhYmxlLnJlZiBpbnN0ZWFkXCIpO1xuICAgIHJldHVybiBvYnNlcnZhYmxlLnJlZih2YWx1ZSk7XG59XG5leHBvcnRzLmFzUmVmZXJlbmNlID0gYXNSZWZlcmVuY2U7XG5mdW5jdGlvbiBhc1N0cnVjdHVyZSh2YWx1ZSkge1xuICAgIGRlcHJlY2F0ZWQoXCJhc1N0cnVjdHVyZSBpcyBkZXByZWNhdGVkLiBVc2Ugb2JzZXJ2YWJsZS5zdHJ1Y3QsIGNvbXB1dGVkLnN0cnVjdCBvciByZWFjdGlvbiBvcHRpb25zIGluc3RlYWQuXCIpO1xuICAgIHJldHVybiBvYnNlcnZhYmxlLnN0cnVjdCh2YWx1ZSk7XG59XG5leHBvcnRzLmFzU3RydWN0dXJlID0gYXNTdHJ1Y3R1cmU7XG5mdW5jdGlvbiBhc0ZsYXQodmFsdWUpIHtcbiAgICBkZXByZWNhdGVkKFwiYXNGbGF0IGlzIGRlcHJlY2F0ZWQsIHVzZSBvYnNlcnZhYmxlLnNoYWxsb3cgaW5zdGVhZFwiKTtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5zaGFsbG93KHZhbHVlKTtcbn1cbmV4cG9ydHMuYXNGbGF0ID0gYXNGbGF0O1xuZnVuY3Rpb24gYXNNYXAoZGF0YSkge1xuICAgIGRlcHJlY2F0ZWQoXCJhc01hcCBpcyBkZXByZWNhdGVkLCB1c2Ugb2JzZXJ2YWJsZS5tYXAgb3Igb2JzZXJ2YWJsZS5zaGFsbG93TWFwIGluc3RlYWRcIik7XG4gICAgcmV0dXJuIG9ic2VydmFibGUubWFwKGRhdGEgfHwge30pO1xufVxuZXhwb3J0cy5hc01hcCA9IGFzTWFwO1xuZnVuY3Rpb24gaXNNb2RpZmllckRlc2NyaXB0b3IodGhpbmcpIHtcbiAgICByZXR1cm4gdHlwZW9mIHRoaW5nID09PSBcIm9iamVjdFwiICYmIHRoaW5nICE9PSBudWxsICYmIHRoaW5nLmlzTW9ieE1vZGlmaWVyRGVzY3JpcHRvciA9PT0gdHJ1ZTtcbn1cbmV4cG9ydHMuaXNNb2RpZmllckRlc2NyaXB0b3IgPSBpc01vZGlmaWVyRGVzY3JpcHRvcjtcbmZ1bmN0aW9uIGNyZWF0ZU1vZGlmaWVyRGVzY3JpcHRvcihlbmhhbmNlciwgaW5pdGlhbFZhbHVlKSB7XG4gICAgaW52YXJpYW50KCFpc01vZGlmaWVyRGVzY3JpcHRvcihpbml0aWFsVmFsdWUpLCBcIk1vZGlmaWVycyBjYW5ub3QgYmUgbmVzdGVkXCIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGlzTW9ieE1vZGlmaWVyRGVzY3JpcHRvcjogdHJ1ZSxcbiAgICAgICAgaW5pdGlhbFZhbHVlOiBpbml0aWFsVmFsdWUsXG4gICAgICAgIGVuaGFuY2VyOiBlbmhhbmNlclxuICAgIH07XG59XG5mdW5jdGlvbiBkZWVwRW5oYW5jZXIodiwgXywgbmFtZSkge1xuICAgIGlmIChpc01vZGlmaWVyRGVzY3JpcHRvcih2KSlcbiAgICAgICAgZmFpbChcIllvdSB0cmllZCB0byBhc3NpZ24gYSBtb2RpZmllciB3cmFwcGVkIHZhbHVlIHRvIGEgY29sbGVjdGlvbiwgcGxlYXNlIGRlZmluZSBtb2RpZmllcnMgd2hlbiBjcmVhdGluZyB0aGUgY29sbGVjdGlvbiwgbm90IHdoZW4gbW9kaWZ5aW5nIGl0XCIpO1xuICAgIGlmIChpc09ic2VydmFibGUodikpXG4gICAgICAgIHJldHVybiB2O1xuICAgIGlmIChBcnJheS5pc0FycmF5KHYpKVxuICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZS5hcnJheSh2LCBuYW1lKTtcbiAgICBpZiAoaXNQbGFpbk9iamVjdCh2KSlcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUub2JqZWN0KHYsIG5hbWUpO1xuICAgIGlmIChpc0VTNk1hcCh2KSlcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUuc2hhbGxvd01hcCh2LCBuYW1lKTtcbiAgICByZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIHNoYWxsb3dFbmhhbmNlcih2LCBfLCBuYW1lKSB7XG4gICAgaWYgKGlzTW9kaWZpZXJEZXNjcmlwdG9yKHYpKVxuICAgICAgICBmYWlsKFwiWW91IHRyaWVkIHRvIGFzc2lnbiBhIG1vZGlmaWVyIHdyYXBwZWQgdmFsdWUgdG8gYSBjb2xsZWN0aW9uLCBwbGVhc2UgZGVmaW5lIG1vZGlmaWVycyB3aGVuIGNyZWF0aW5nIHRoZSBjb2xsZWN0aW9uLCBub3Qgd2hlbiBtb2RpZnlpbmcgaXRcIik7XG4gICAgaWYgKHYgPT09IHVuZGVmaW5lZCB8fCB2ID09PSBudWxsKVxuICAgICAgICByZXR1cm4gdjtcbiAgICBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHYpIHx8IGlzT2JzZXJ2YWJsZUFycmF5KHYpIHx8IGlzT2JzZXJ2YWJsZU1hcCh2KSlcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodikpXG4gICAgICAgIHJldHVybiBvYnNlcnZhYmxlLnNoYWxsb3dBcnJheSh2LCBuYW1lKTtcbiAgICBpZiAoaXNQbGFpbk9iamVjdCh2KSlcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUuc2hhbGxvd09iamVjdCh2LCBuYW1lKTtcbiAgICBpZiAoaXNFUzZNYXAodikpXG4gICAgICAgIHJldHVybiBvYnNlcnZhYmxlLnNoYWxsb3dNYXAodiwgbmFtZSk7XG4gICAgcmV0dXJuIGZhaWwoXCJUaGUgc2hhbGxvdyBtb2RpZmllciAvIGRlY29yYXRvciBjYW4gb25seSB1c2VkIGluIGNvbWJpbmF0aW9uIHdpdGggYXJyYXlzLCBvYmplY3RzIGFuZCBtYXBzXCIpO1xufVxuZnVuY3Rpb24gcmVmZXJlbmNlRW5oYW5jZXIobmV3VmFsdWUpIHtcbiAgICByZXR1cm4gbmV3VmFsdWU7XG59XG5mdW5jdGlvbiBkZWVwU3RydWN0RW5oYW5jZXIodiwgb2xkVmFsdWUsIG5hbWUpIHtcbiAgICBpZiAoZGVlcEVxdWFsKHYsIG9sZFZhbHVlKSlcbiAgICAgICAgcmV0dXJuIG9sZFZhbHVlO1xuICAgIGlmIChpc09ic2VydmFibGUodikpXG4gICAgICAgIHJldHVybiB2O1xuICAgIGlmIChBcnJheS5pc0FycmF5KHYpKVxuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGVBcnJheSh2LCBkZWVwU3RydWN0RW5oYW5jZXIsIG5hbWUpO1xuICAgIGlmIChpc0VTNk1hcCh2KSlcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlTWFwKHYsIGRlZXBTdHJ1Y3RFbmhhbmNlciwgbmFtZSk7XG4gICAgaWYgKGlzUGxhaW5PYmplY3QodikpIHtcbiAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICBhc09ic2VydmFibGVPYmplY3QocmVzLCBuYW1lKTtcbiAgICAgICAgZXh0ZW5kT2JzZXJ2YWJsZUhlbHBlcihyZXMsIGRlZXBTdHJ1Y3RFbmhhbmNlciwgW3ZdKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgcmV0dXJuIHY7XG59XG5mdW5jdGlvbiByZWZTdHJ1Y3RFbmhhbmNlcih2LCBvbGRWYWx1ZSwgbmFtZSkge1xuICAgIGlmIChkZWVwRXF1YWwodiwgb2xkVmFsdWUpKVxuICAgICAgICByZXR1cm4gb2xkVmFsdWU7XG4gICAgcmV0dXJuIHY7XG59XG52YXIgc2FmYXJpUHJvdG90eXBlU2V0dGVySW5oZXJpdGFuY2VCdWcgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciB2ID0gZmFsc2U7XG4gICAgdmFyIHAgPSB7fTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocCwgXCIwXCIsIHsgc2V0OiBmdW5jdGlvbiAoKSB7IHYgPSB0cnVlOyB9IH0pO1xuICAgIE9iamVjdC5jcmVhdGUocClbXCIwXCJdID0gMTtcbiAgICByZXR1cm4gdiA9PT0gZmFsc2U7XG59KSgpO1xudmFyIE9CU0VSVkFCTEVfQVJSQVlfQlVGRkVSX1NJWkUgPSAwO1xudmFyIFN0dWJBcnJheSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU3R1YkFycmF5KCkge1xuICAgIH1cbiAgICByZXR1cm4gU3R1YkFycmF5O1xufSgpKTtcblN0dWJBcnJheS5wcm90b3R5cGUgPSBbXTtcbnZhciBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24obmFtZSwgZW5oYW5jZXIsIGFycmF5LCBvd25lZCkge1xuICAgICAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG4gICAgICAgIHRoaXMub3duZWQgPSBvd25lZDtcbiAgICAgICAgdGhpcy5sYXN0S25vd25MZW5ndGggPSAwO1xuICAgICAgICB0aGlzLmludGVyY2VwdG9ycyA9IG51bGw7XG4gICAgICAgIHRoaXMuY2hhbmdlTGlzdGVuZXJzID0gbnVsbDtcbiAgICAgICAgdGhpcy5hdG9tID0gbmV3IEJhc2VBdG9tKG5hbWUgfHwgKFwiT2JzZXJ2YWJsZUFycmF5QFwiICsgZ2V0TmV4dElkKCkpKTtcbiAgICAgICAgdGhpcy5lbmhhbmNlciA9IGZ1bmN0aW9uIChuZXdWLCBvbGRWKSB7IHJldHVybiBlbmhhbmNlcihuZXdWLCBvbGRWLCBuYW1lICsgXCJbLi5dXCIpOyB9O1xuICAgIH1cbiAgICBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbi5wcm90b3R5cGUuaW50ZXJjZXB0ID0gZnVuY3Rpb24gKGhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVySW50ZXJjZXB0b3IodGhpcywgaGFuZGxlcik7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbi5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uIChsaXN0ZW5lciwgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgIGlmIChmaXJlSW1tZWRpYXRlbHkgPT09IHZvaWQgMCkgeyBmaXJlSW1tZWRpYXRlbHkgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgICAgICBsaXN0ZW5lcih7XG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLmFycmF5LFxuICAgICAgICAgICAgICAgIHR5cGU6IFwic3BsaWNlXCIsXG4gICAgICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICAgICAgYWRkZWQ6IHRoaXMudmFsdWVzLnNsaWNlKCksXG4gICAgICAgICAgICAgICAgYWRkZWRDb3VudDogdGhpcy52YWx1ZXMubGVuZ3RoLFxuICAgICAgICAgICAgICAgIHJlbW92ZWQ6IFtdLFxuICAgICAgICAgICAgICAgIHJlbW92ZWRDb3VudDogMFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVyTGlzdGVuZXIodGhpcywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLmdldEFycmF5TGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheUFkbWluaXN0cmF0aW9uLnByb3RvdHlwZS5zZXRBcnJheUxlbmd0aCA9IGZ1bmN0aW9uIChuZXdMZW5ndGgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuZXdMZW5ndGggIT09IFwibnVtYmVyXCIgfHwgbmV3TGVuZ3RoIDwgMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4LmFycmF5XSBPdXQgb2YgcmFuZ2U6IFwiICsgbmV3TGVuZ3RoKTtcbiAgICAgICAgdmFyIGN1cnJlbnRMZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIGlmIChuZXdMZW5ndGggPT09IGN1cnJlbnRMZW5ndGgpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGVsc2UgaWYgKG5ld0xlbmd0aCA+IGN1cnJlbnRMZW5ndGgpXG4gICAgICAgICAgICB0aGlzLnNwbGljZVdpdGhBcnJheShjdXJyZW50TGVuZ3RoLCAwLCBuZXcgQXJyYXkobmV3TGVuZ3RoIC0gY3VycmVudExlbmd0aCkpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLnNwbGljZVdpdGhBcnJheShuZXdMZW5ndGgsIGN1cnJlbnRMZW5ndGggLSBuZXdMZW5ndGgpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLnVwZGF0ZUFycmF5TGVuZ3RoID0gZnVuY3Rpb24gKG9sZExlbmd0aCwgZGVsdGEpIHtcbiAgICAgICAgaWYgKG9sZExlbmd0aCAhPT0gdGhpcy5sYXN0S25vd25MZW5ndGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieF0gTW9kaWZpY2F0aW9uIGV4Y2VwdGlvbjogdGhlIGludGVybmFsIHN0cnVjdHVyZSBvZiBhbiBvYnNlcnZhYmxlIGFycmF5IHdhcyBjaGFuZ2VkLiBEaWQgeW91IHVzZSBwZWVrKCkgdG8gY2hhbmdlIGl0P1wiKTtcbiAgICAgICAgdGhpcy5sYXN0S25vd25MZW5ndGggKz0gZGVsdGE7XG4gICAgICAgIGlmIChkZWx0YSA+IDAgJiYgb2xkTGVuZ3RoICsgZGVsdGEgKyAxID4gT0JTRVJWQUJMRV9BUlJBWV9CVUZGRVJfU0laRSlcbiAgICAgICAgICAgIHJlc2VydmVBcnJheUJ1ZmZlcihvbGRMZW5ndGggKyBkZWx0YSArIDEpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLnNwbGljZVdpdGhBcnJheSA9IGZ1bmN0aW9uIChpbmRleCwgZGVsZXRlQ291bnQsIG5ld0l0ZW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGNoZWNrSWZTdGF0ZU1vZGlmaWNhdGlvbnNBcmVBbGxvd2VkKHRoaXMuYXRvbSk7XG4gICAgICAgIHZhciBsZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIGlmIChpbmRleCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgaW5kZXggPSAwO1xuICAgICAgICBlbHNlIGlmIChpbmRleCA+IGxlbmd0aClcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoO1xuICAgICAgICBlbHNlIGlmIChpbmRleCA8IDApXG4gICAgICAgICAgICBpbmRleCA9IE1hdGgubWF4KDAsIGxlbmd0aCArIGluZGV4KTtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpXG4gICAgICAgICAgICBkZWxldGVDb3VudCA9IGxlbmd0aCAtIGluZGV4O1xuICAgICAgICBlbHNlIGlmIChkZWxldGVDb3VudCA9PT0gdW5kZWZpbmVkIHx8IGRlbGV0ZUNvdW50ID09PSBudWxsKVxuICAgICAgICAgICAgZGVsZXRlQ291bnQgPSAwO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGVDb3VudCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGRlbGV0ZUNvdW50LCBsZW5ndGggLSBpbmRleCkpO1xuICAgICAgICBpZiAobmV3SXRlbXMgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIG5ld0l0ZW1zID0gW107XG4gICAgICAgIGlmIChoYXNJbnRlcmNlcHRvcnModGhpcykpIHtcbiAgICAgICAgICAgIHZhciBjaGFuZ2UgPSBpbnRlcmNlcHRDaGFuZ2UodGhpcywge1xuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcy5hcnJheSxcbiAgICAgICAgICAgICAgICB0eXBlOiBcInNwbGljZVwiLFxuICAgICAgICAgICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgICAgICAgICByZW1vdmVkQ291bnQ6IGRlbGV0ZUNvdW50LFxuICAgICAgICAgICAgICAgIGFkZGVkOiBuZXdJdGVtc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gRU1QVFlfQVJSQVk7XG4gICAgICAgICAgICBkZWxldGVDb3VudCA9IGNoYW5nZS5yZW1vdmVkQ291bnQ7XG4gICAgICAgICAgICBuZXdJdGVtcyA9IGNoYW5nZS5hZGRlZDtcbiAgICAgICAgfVxuICAgICAgICBuZXdJdGVtcyA9IG5ld0l0ZW1zLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gX3RoaXMuZW5oYW5jZXIodiwgdW5kZWZpbmVkKTsgfSk7XG4gICAgICAgIHZhciBsZW5ndGhEZWx0YSA9IG5ld0l0ZW1zLmxlbmd0aCAtIGRlbGV0ZUNvdW50O1xuICAgICAgICB0aGlzLnVwZGF0ZUFycmF5TGVuZ3RoKGxlbmd0aCwgbGVuZ3RoRGVsdGEpO1xuICAgICAgICB2YXIgcmVzID0gKF9hID0gdGhpcy52YWx1ZXMpLnNwbGljZS5hcHBseShfYSwgW2luZGV4LCBkZWxldGVDb3VudF0uY29uY2F0KG5ld0l0ZW1zKSk7XG4gICAgICAgIGlmIChkZWxldGVDb3VudCAhPT0gMCB8fCBuZXdJdGVtcy5sZW5ndGggIT09IDApXG4gICAgICAgICAgICB0aGlzLm5vdGlmeUFycmF5U3BsaWNlKGluZGV4LCBuZXdJdGVtcywgcmVzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgdmFyIF9hO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLm5vdGlmeUFycmF5Q2hpbGRVcGRhdGUgPSBmdW5jdGlvbiAoaW5kZXgsIG5ld1ZhbHVlLCBvbGRWYWx1ZSkge1xuICAgICAgICB2YXIgbm90aWZ5U3B5ID0gIXRoaXMub3duZWQgJiYgaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBub3RpZnkgPSBoYXNMaXN0ZW5lcnModGhpcyk7XG4gICAgICAgIHZhciBjaGFuZ2UgPSBub3RpZnkgfHwgbm90aWZ5U3B5ID8ge1xuICAgICAgICAgICAgb2JqZWN0OiB0aGlzLmFycmF5LFxuICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgIGluZGV4OiBpbmRleCwgbmV3VmFsdWU6IG5ld1ZhbHVlLCBvbGRWYWx1ZTogb2xkVmFsdWVcbiAgICAgICAgfSA6IG51bGw7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICB0aGlzLmF0b20ucmVwb3J0Q2hhbmdlZCgpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIGNoYW5nZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheUFkbWluaXN0cmF0aW9uLnByb3RvdHlwZS5ub3RpZnlBcnJheVNwbGljZSA9IGZ1bmN0aW9uIChpbmRleCwgYWRkZWQsIHJlbW92ZWQpIHtcbiAgICAgICAgdmFyIG5vdGlmeVNweSA9ICF0aGlzLm93bmVkICYmIGlzU3B5RW5hYmxlZCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaGFzTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgICAgIG9iamVjdDogdGhpcy5hcnJheSxcbiAgICAgICAgICAgIHR5cGU6IFwic3BsaWNlXCIsXG4gICAgICAgICAgICBpbmRleDogaW5kZXgsIHJlbW92ZWQ6IHJlbW92ZWQsIGFkZGVkOiBhZGRlZCxcbiAgICAgICAgICAgIHJlbW92ZWRDb3VudDogcmVtb3ZlZC5sZW5ndGgsXG4gICAgICAgICAgICBhZGRlZENvdW50OiBhZGRlZC5sZW5ndGhcbiAgICAgICAgfSA6IG51bGw7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICB0aGlzLmF0b20ucmVwb3J0Q2hhbmdlZCgpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIGNoYW5nZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICB9O1xuICAgIHJldHVybiBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbjtcbn0oKSk7XG52YXIgT2JzZXJ2YWJsZUFycmF5ID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoT2JzZXJ2YWJsZUFycmF5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIE9ic2VydmFibGVBcnJheShpbml0aWFsVmFsdWVzLCBlbmhhbmNlciwgbmFtZSwgb3duZWQpIHtcbiAgICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgeyBuYW1lID0gXCJPYnNlcnZhYmxlQXJyYXlAXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICBpZiAob3duZWQgPT09IHZvaWQgMCkgeyBvd25lZCA9IGZhbHNlOyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIHZhciBhZG0gPSBuZXcgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24obmFtZSwgZW5oYW5jZXIsIF90aGlzLCBvd25lZCk7XG4gICAgICAgIGFkZEhpZGRlbkZpbmFsUHJvcChfdGhpcywgXCIkbW9ieFwiLCBhZG0pO1xuICAgICAgICBpZiAoaW5pdGlhbFZhbHVlcyAmJiBpbml0aWFsVmFsdWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgYWRtLnVwZGF0ZUFycmF5TGVuZ3RoKDAsIGluaXRpYWxWYWx1ZXMubGVuZ3RoKTtcbiAgICAgICAgICAgIGFkbS52YWx1ZXMgPSBpbml0aWFsVmFsdWVzLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gZW5oYW5jZXIodiwgdW5kZWZpbmVkLCBuYW1lICsgXCJbLi5dXCIpOyB9KTtcbiAgICAgICAgICAgIGFkbS5ub3RpZnlBcnJheVNwbGljZSgwLCBhZG0udmFsdWVzLnNsaWNlKCksIEVNUFRZX0FSUkFZKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGFkbS52YWx1ZXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2FmYXJpUHJvdG90eXBlU2V0dGVySW5oZXJpdGFuY2VCdWcpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhZG0uYXJyYXksIFwiMFwiLCBFTlRSWV8wKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUuaW50ZXJjZXB0ID0gZnVuY3Rpb24gKGhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuJG1vYnguaW50ZXJjZXB0KGhhbmRsZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5vYnNlcnZlID0gZnVuY3Rpb24gKGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICAgICAgaWYgKGZpcmVJbW1lZGlhdGVseSA9PT0gdm9pZCAwKSB7IGZpcmVJbW1lZGlhdGVseSA9IGZhbHNlOyB9XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4Lm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcGxpY2UoMCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLmNvbmNhdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFycmF5cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgYXJyYXlzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy4kbW9ieC5hdG9tLnJlcG9ydE9ic2VydmVkKCk7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KHRoaXMucGVlaygpLCBhcnJheXMubWFwKGZ1bmN0aW9uIChhKSB7IHJldHVybiBpc09ic2VydmFibGVBcnJheShhKSA/IGEucGVlaygpIDogYTsgfSkpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5yZXBsYWNlID0gZnVuY3Rpb24gKG5ld0l0ZW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnNwbGljZVdpdGhBcnJheSgwLCB0aGlzLiRtb2J4LnZhbHVlcy5sZW5ndGgsIG5ld0l0ZW1zKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUudG9KUyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2xpY2UoKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b0pTKCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLnBlZWsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnZhbHVlcztcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uIChwcmVkaWNhdGUsIHRoaXNBcmcsIGZyb21JbmRleCkge1xuICAgICAgICBpZiAoZnJvbUluZGV4ID09PSB2b2lkIDApIHsgZnJvbUluZGV4ID0gMDsgfVxuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgdmFyIGl0ZW1zID0gdGhpcy4kbW9ieC52YWx1ZXMsIGwgPSBpdGVtcy5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSBmcm9tSW5kZXg7IGkgPCBsOyBpKyspXG4gICAgICAgICAgICBpZiAocHJlZGljYXRlLmNhbGwodGhpc0FyZywgaXRlbXNbaV0sIGksIHRoaXMpKVxuICAgICAgICAgICAgICAgIHJldHVybiBpdGVtc1tpXTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUuc3BsaWNlID0gZnVuY3Rpb24gKGluZGV4LCBkZWxldGVDb3VudCkge1xuICAgICAgICB2YXIgbmV3SXRlbXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAyOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIG5ld0l0ZW1zW19pIC0gMl0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4kbW9ieC5zcGxpY2VXaXRoQXJyYXkoaW5kZXgpO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnNwbGljZVdpdGhBcnJheShpbmRleCwgZGVsZXRlQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnNwbGljZVdpdGhBcnJheShpbmRleCwgZGVsZXRlQ291bnQsIG5ld0l0ZW1zKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGl0ZW1zID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBpdGVtc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhZG0gPSB0aGlzLiRtb2J4O1xuICAgICAgICBhZG0uc3BsaWNlV2l0aEFycmF5KGFkbS52YWx1ZXMubGVuZ3RoLCAwLCBpdGVtcyk7XG4gICAgICAgIHJldHVybiBhZG0udmFsdWVzLmxlbmd0aDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcGxpY2UoTWF0aC5tYXgodGhpcy4kbW9ieC52YWx1ZXMubGVuZ3RoIC0gMSwgMCksIDEpWzBdO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5zaGlmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3BsaWNlKDAsIDEpWzBdO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS51bnNoaWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXRlbXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGl0ZW1zW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFkbSA9IHRoaXMuJG1vYng7XG4gICAgICAgIGFkbS5zcGxpY2VXaXRoQXJyYXkoMCwgMCwgaXRlbXMpO1xuICAgICAgICByZXR1cm4gYWRtLnZhbHVlcy5sZW5ndGg7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLnJldmVyc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuJG1vYnguYXRvbS5yZXBvcnRPYnNlcnZlZCgpO1xuICAgICAgICB2YXIgY2xvbmUgPSB0aGlzLnNsaWNlKCk7XG4gICAgICAgIHJldHVybiBjbG9uZS5yZXZlcnNlLmFwcGx5KGNsb25lLCBhcmd1bWVudHMpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5zb3J0ID0gZnVuY3Rpb24gKGNvbXBhcmVGbikge1xuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgdmFyIGNsb25lID0gdGhpcy5zbGljZSgpO1xuICAgICAgICByZXR1cm4gY2xvbmUuc29ydC5hcHBseShjbG9uZSwgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBpZHggPSB0aGlzLiRtb2J4LnZhbHVlcy5pbmRleE9mKHZhbHVlKTtcbiAgICAgICAgaWYgKGlkeCA+IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5tb3ZlID0gZnVuY3Rpb24gKGZyb21JbmRleCwgdG9JbmRleCkge1xuICAgICAgICBmdW5jdGlvbiBjaGVja0luZGV4KGluZGV4KSB7XG4gICAgICAgICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYnguYXJyYXldIEluZGV4IG91dCBvZiBib3VuZHM6IFwiICsgaW5kZXggKyBcIiBpcyBuZWdhdGl2ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBsZW5ndGggPSB0aGlzLiRtb2J4LnZhbHVlcy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYnguYXJyYXldIEluZGV4IG91dCBvZiBib3VuZHM6IFwiICsgaW5kZXggKyBcIiBpcyBub3Qgc21hbGxlciB0aGFuIFwiICsgbGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjaGVja0luZGV4LmNhbGwodGhpcywgZnJvbUluZGV4KTtcbiAgICAgICAgY2hlY2tJbmRleC5jYWxsKHRoaXMsIHRvSW5kZXgpO1xuICAgICAgICBpZiAoZnJvbUluZGV4ID09PSB0b0luZGV4KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9sZEl0ZW1zID0gdGhpcy4kbW9ieC52YWx1ZXM7XG4gICAgICAgIHZhciBuZXdJdGVtcztcbiAgICAgICAgaWYgKGZyb21JbmRleCA8IHRvSW5kZXgpIHtcbiAgICAgICAgICAgIG5ld0l0ZW1zID0gb2xkSXRlbXMuc2xpY2UoMCwgZnJvbUluZGV4KS5jb25jYXQob2xkSXRlbXMuc2xpY2UoZnJvbUluZGV4ICsgMSwgdG9JbmRleCArIDEpLCBbb2xkSXRlbXNbZnJvbUluZGV4XV0sIG9sZEl0ZW1zLnNsaWNlKHRvSW5kZXggKyAxKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBuZXdJdGVtcyA9IG9sZEl0ZW1zLnNsaWNlKDAsIHRvSW5kZXgpLmNvbmNhdChbb2xkSXRlbXNbZnJvbUluZGV4XV0sIG9sZEl0ZW1zLnNsaWNlKHRvSW5kZXgsIGZyb21JbmRleCksIG9sZEl0ZW1zLnNsaWNlKGZyb21JbmRleCArIDEpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlcGxhY2UobmV3SXRlbXMpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kbW9ieC5hdG9tLnJlcG9ydE9ic2VydmVkKCk7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUudG9TdHJpbmcuYXBwbHkodGhpcy4kbW9ieC52YWx1ZXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLnRvTG9jYWxlU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS50b0xvY2FsZVN0cmluZy5hcHBseSh0aGlzLiRtb2J4LnZhbHVlcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHJldHVybiBPYnNlcnZhYmxlQXJyYXk7XG59KFN0dWJBcnJheSkpO1xuZGVjbGFyZUl0ZXJhdG9yKE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYXJyYXlBc0l0ZXJhdG9yKHRoaXMuc2xpY2UoKSk7XG59KTtcbm1ha2VOb25FbnVtZXJhYmxlKE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUsIFtcbiAgICBcImNvbnN0cnVjdG9yXCIsXG4gICAgXCJpbnRlcmNlcHRcIixcbiAgICBcIm9ic2VydmVcIixcbiAgICBcImNsZWFyXCIsXG4gICAgXCJjb25jYXRcIixcbiAgICBcInJlcGxhY2VcIixcbiAgICBcInRvSlNcIixcbiAgICBcInRvSlNPTlwiLFxuICAgIFwicGVla1wiLFxuICAgIFwiZmluZFwiLFxuICAgIFwic3BsaWNlXCIsXG4gICAgXCJwdXNoXCIsXG4gICAgXCJwb3BcIixcbiAgICBcInNoaWZ0XCIsXG4gICAgXCJ1bnNoaWZ0XCIsXG4gICAgXCJyZXZlcnNlXCIsXG4gICAgXCJzb3J0XCIsXG4gICAgXCJyZW1vdmVcIixcbiAgICBcIm1vdmVcIixcbiAgICBcInRvU3RyaW5nXCIsXG4gICAgXCJ0b0xvY2FsZVN0cmluZ1wiXG5dKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLCBcImxlbmd0aFwiLCB7XG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kbW9ieC5nZXRBcnJheUxlbmd0aCgpO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAobmV3TGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuJG1vYnguc2V0QXJyYXlMZW5ndGgobmV3TGVuZ3RoKTtcbiAgICB9XG59KTtcbltcbiAgICBcImV2ZXJ5XCIsXG4gICAgXCJmaWx0ZXJcIixcbiAgICBcImZvckVhY2hcIixcbiAgICBcImluZGV4T2ZcIixcbiAgICBcImpvaW5cIixcbiAgICBcImxhc3RJbmRleE9mXCIsXG4gICAgXCJtYXBcIixcbiAgICBcInJlZHVjZVwiLFxuICAgIFwicmVkdWNlUmlnaHRcIixcbiAgICBcInNsaWNlXCIsXG4gICAgXCJzb21lXCJcbl0uZm9yRWFjaChmdW5jdGlvbiAoZnVuY05hbWUpIHtcbiAgICB2YXIgYmFzZUZ1bmMgPSBBcnJheS5wcm90b3R5cGVbZnVuY05hbWVdO1xuICAgIGludmFyaWFudCh0eXBlb2YgYmFzZUZ1bmMgPT09IFwiZnVuY3Rpb25cIiwgXCJCYXNlIGZ1bmN0aW9uIG5vdCBkZWZpbmVkIG9uIEFycmF5IHByb3RvdHlwZTogJ1wiICsgZnVuY05hbWUgKyBcIidcIik7XG4gICAgYWRkSGlkZGVuUHJvcChPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLCBmdW5jTmFtZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIGJhc2VGdW5jLmFwcGx5KHRoaXMuJG1vYngudmFsdWVzLCBhcmd1bWVudHMpO1xuICAgIH0pO1xufSk7XG52YXIgRU5UUllfMCA9IHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgc2V0OiBjcmVhdGVBcnJheVNldHRlcigwKSxcbiAgICBnZXQ6IGNyZWF0ZUFycmF5R2V0dGVyKDApXG59O1xuZnVuY3Rpb24gY3JlYXRlQXJyYXlCdWZmZXJJdGVtKGluZGV4KSB7XG4gICAgdmFyIHNldCA9IGNyZWF0ZUFycmF5U2V0dGVyKGluZGV4KTtcbiAgICB2YXIgZ2V0ID0gY3JlYXRlQXJyYXlHZXR0ZXIoaW5kZXgpO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLCBcIlwiICsgaW5kZXgsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgc2V0OiBzZXQsIGdldDogZ2V0XG4gICAgfSk7XG59XG5mdW5jdGlvbiBjcmVhdGVBcnJheVNldHRlcihpbmRleCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIGFkbSA9IHRoaXMuJG1vYng7XG4gICAgICAgIHZhciB2YWx1ZXMgPSBhZG0udmFsdWVzO1xuICAgICAgICBpZiAoaW5kZXggPCB2YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjaGVja0lmU3RhdGVNb2RpZmljYXRpb25zQXJlQWxsb3dlZChhZG0uYXRvbSk7XG4gICAgICAgICAgICB2YXIgb2xkVmFsdWUgPSB2YWx1ZXNbaW5kZXhdO1xuICAgICAgICAgICAgaWYgKGhhc0ludGVyY2VwdG9ycyhhZG0pKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGludGVyY2VwdENoYW5nZShhZG0sIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiBhZG0uYXJyYXksXG4gICAgICAgICAgICAgICAgICAgIGluZGV4OiBpbmRleCwgbmV3VmFsdWU6IG5ld1ZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKCFjaGFuZ2UpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZSA9IGNoYW5nZS5uZXdWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld1ZhbHVlID0gYWRtLmVuaGFuY2VyKG5ld1ZhbHVlLCBvbGRWYWx1ZSk7XG4gICAgICAgICAgICB2YXIgY2hhbmdlZCA9IG5ld1ZhbHVlICE9PSBvbGRWYWx1ZTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzW2luZGV4XSA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgIGFkbS5ub3RpZnlBcnJheUNoaWxkVXBkYXRlKGluZGV4LCBuZXdWYWx1ZSwgb2xkVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGluZGV4ID09PSB2YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBhZG0uc3BsaWNlV2l0aEFycmF5KGluZGV4LCAwLCBbbmV3VmFsdWVdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieC5hcnJheV0gSW5kZXggb3V0IG9mIGJvdW5kcywgXCIgKyBpbmRleCArIFwiIGlzIGxhcmdlciB0aGFuIFwiICsgdmFsdWVzLmxlbmd0aCk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUFycmF5R2V0dGVyKGluZGV4KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGltcGwgPSB0aGlzLiRtb2J4O1xuICAgICAgICBpZiAoaW1wbCkge1xuICAgICAgICAgICAgaWYgKGluZGV4IDwgaW1wbC52YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaW1wbC5hdG9tLnJlcG9ydE9ic2VydmVkKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGltcGwudmFsdWVzW2luZGV4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlttb2J4LmFycmF5XSBBdHRlbXB0IHRvIHJlYWQgYW4gYXJyYXkgaW5kZXggKFwiICsgaW5kZXggKyBcIikgdGhhdCBpcyBvdXQgb2YgYm91bmRzIChcIiArIGltcGwudmFsdWVzLmxlbmd0aCArIFwiKS4gUGxlYXNlIGNoZWNrIGxlbmd0aCBmaXJzdC4gT3V0IG9mIGJvdW5kIGluZGljZXMgd2lsbCBub3QgYmUgdHJhY2tlZCBieSBNb2JYXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHJlc2VydmVBcnJheUJ1ZmZlcihtYXgpIHtcbiAgICBmb3IgKHZhciBpbmRleCA9IE9CU0VSVkFCTEVfQVJSQVlfQlVGRkVSX1NJWkU7IGluZGV4IDwgbWF4OyBpbmRleCsrKVxuICAgICAgICBjcmVhdGVBcnJheUJ1ZmZlckl0ZW0oaW5kZXgpO1xuICAgIE9CU0VSVkFCTEVfQVJSQVlfQlVGRkVSX1NJWkUgPSBtYXg7XG59XG5yZXNlcnZlQXJyYXlCdWZmZXIoMTAwMCk7XG52YXIgaXNPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbiA9IGNyZWF0ZUluc3RhbmNlb2ZQcmVkaWNhdGUoXCJPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvblwiLCBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbik7XG5mdW5jdGlvbiBpc09ic2VydmFibGVBcnJheSh0aGluZykge1xuICAgIHJldHVybiBpc09iamVjdCh0aGluZykgJiYgaXNPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbih0aGluZy4kbW9ieCk7XG59XG5leHBvcnRzLmlzT2JzZXJ2YWJsZUFycmF5ID0gaXNPYnNlcnZhYmxlQXJyYXk7XG52YXIgT2JzZXJ2YWJsZU1hcE1hcmtlciA9IHt9O1xudmFyIE9ic2VydmFibGVNYXAgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE9ic2VydmFibGVNYXAoaW5pdGlhbERhdGEsIGVuaGFuY2VyLCBuYW1lKSB7XG4gICAgICAgIGlmIChlbmhhbmNlciA9PT0gdm9pZCAwKSB7IGVuaGFuY2VyID0gZGVlcEVuaGFuY2VyOyB9XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiT2JzZXJ2YWJsZU1hcEBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIHRoaXMuZW5oYW5jZXIgPSBlbmhhbmNlcjtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy4kbW9ieCA9IE9ic2VydmFibGVNYXBNYXJrZXI7XG4gICAgICAgIHRoaXMuX2RhdGEgPSB7fTtcbiAgICAgICAgdGhpcy5faGFzTWFwID0ge307XG4gICAgICAgIHRoaXMuX2tleXMgPSBuZXcgT2JzZXJ2YWJsZUFycmF5KHVuZGVmaW5lZCwgcmVmZXJlbmNlRW5oYW5jZXIsIHRoaXMubmFtZSArIFwiLmtleXMoKVwiLCB0cnVlKTtcbiAgICAgICAgdGhpcy5pbnRlcmNlcHRvcnMgPSBudWxsO1xuICAgICAgICB0aGlzLmNoYW5nZUxpc3RlbmVycyA9IG51bGw7XG4gICAgICAgIHRoaXMubWVyZ2UoaW5pdGlhbERhdGEpO1xuICAgIH1cbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5faGFzID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHRoaXMuX2RhdGFba2V5XSAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWRLZXkoa2V5KSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAga2V5ID0gXCJcIiArIGtleTtcbiAgICAgICAgaWYgKHRoaXMuX2hhc01hcFtrZXldKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2hhc01hcFtrZXldLmdldCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdXBkYXRlSGFzTWFwRW50cnkoa2V5LCBmYWxzZSkuZ2V0KCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICB0aGlzLmFzc2VydFZhbGlkS2V5KGtleSk7XG4gICAgICAgIGtleSA9IFwiXCIgKyBrZXk7XG4gICAgICAgIHZhciBoYXNLZXkgPSB0aGlzLl9oYXMoa2V5KTtcbiAgICAgICAgaWYgKGhhc0ludGVyY2VwdG9ycyh0aGlzKSkge1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGludGVyY2VwdENoYW5nZSh0aGlzLCB7XG4gICAgICAgICAgICAgICAgdHlwZTogaGFzS2V5ID8gXCJ1cGRhdGVcIiA6IFwiYWRkXCIsXG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICBuYW1lOiBrZXlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFjaGFuZ2UpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB2YWx1ZSA9IGNoYW5nZS5uZXdWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzS2V5KSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVWYWx1ZShrZXksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2FkZFZhbHVlKGtleSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFzc2VydFZhbGlkS2V5KGtleSk7XG4gICAgICAgIGtleSA9IFwiXCIgKyBrZXk7XG4gICAgICAgIGlmIChoYXNJbnRlcmNlcHRvcnModGhpcykpIHtcbiAgICAgICAgICAgIHZhciBjaGFuZ2UgPSBpbnRlcmNlcHRDaGFuZ2UodGhpcywge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiZGVsZXRlXCIsXG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIG5hbWU6IGtleVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2hhcyhrZXkpKSB7XG4gICAgICAgICAgICB2YXIgbm90aWZ5U3B5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgICAgICB2YXIgbm90aWZ5ID0gaGFzTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IG5vdGlmeSB8fCBub3RpZnlTcHkgPyB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJkZWxldGVcIixcbiAgICAgICAgICAgICAgICBvYmplY3Q6IHRoaXMsXG4gICAgICAgICAgICAgICAgb2xkVmFsdWU6IHRoaXMuX2RhdGFba2V5XS52YWx1ZSxcbiAgICAgICAgICAgICAgICBuYW1lOiBrZXlcbiAgICAgICAgICAgIH0gOiBudWxsO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICAgICAgcnVuSW5UcmFuc2FjdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuX2tleXMucmVtb3ZlKGtleSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuX3VwZGF0ZUhhc01hcEVudHJ5KGtleSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIHZhciBvYnNlcnZhYmxlID0gX3RoaXMuX2RhdGFba2V5XTtcbiAgICAgICAgICAgICAgICBvYnNlcnZhYmxlLnNldE5ld1ZhbHVlKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuX2RhdGFba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKG5vdGlmeSlcbiAgICAgICAgICAgICAgICBub3RpZnlMaXN0ZW5lcnModGhpcywgY2hhbmdlKTtcbiAgICAgICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICAgICAgc3B5UmVwb3J0RW5kKCk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5fdXBkYXRlSGFzTWFwRW50cnkgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICB2YXIgZW50cnkgPSB0aGlzLl9oYXNNYXBba2V5XTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICBlbnRyeS5zZXROZXdWYWx1ZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlbnRyeSA9IHRoaXMuX2hhc01hcFtrZXldID0gbmV3IE9ic2VydmFibGVWYWx1ZSh2YWx1ZSwgcmVmZXJlbmNlRW5oYW5jZXIsIHRoaXMubmFtZSArIFwiLlwiICsga2V5ICsgXCI/XCIsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW50cnk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5fdXBkYXRlVmFsdWUgPSBmdW5jdGlvbiAobmFtZSwgbmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIG9ic2VydmFibGUgPSB0aGlzLl9kYXRhW25hbWVdO1xuICAgICAgICBuZXdWYWx1ZSA9IG9ic2VydmFibGUucHJlcGFyZU5ld1ZhbHVlKG5ld1ZhbHVlKTtcbiAgICAgICAgaWYgKG5ld1ZhbHVlICE9PSBVTkNIQU5HRUQpIHtcbiAgICAgICAgICAgIHZhciBub3RpZnlTcHkgPSBpc1NweUVuYWJsZWQoKTtcbiAgICAgICAgICAgIHZhciBub3RpZnkgPSBoYXNMaXN0ZW5lcnModGhpcyk7XG4gICAgICAgICAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInVwZGF0ZVwiLFxuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcyxcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZTogb2JzZXJ2YWJsZS52YWx1ZSxcbiAgICAgICAgICAgICAgICBuYW1lOiBuYW1lLCBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgICAgIH0gOiBudWxsO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICAgICAgb2JzZXJ2YWJsZS5zZXROZXdWYWx1ZShuZXdWYWx1ZSk7XG4gICAgICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgICAgIG5vdGlmeUxpc3RlbmVycyh0aGlzLCBjaGFuZ2UpO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUuX2FkZFZhbHVlID0gZnVuY3Rpb24gKG5hbWUsIG5ld1ZhbHVlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJ1bkluVHJhbnNhY3Rpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG9ic2VydmFibGUgPSBfdGhpcy5fZGF0YVtuYW1lXSA9IG5ldyBPYnNlcnZhYmxlVmFsdWUobmV3VmFsdWUsIF90aGlzLmVuaGFuY2VyLCBfdGhpcy5uYW1lICsgXCIuXCIgKyBuYW1lLCBmYWxzZSk7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IG9ic2VydmFibGUudmFsdWU7XG4gICAgICAgICAgICBfdGhpcy5fdXBkYXRlSGFzTWFwRW50cnkobmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgICBfdGhpcy5fa2V5cy5wdXNoKG5hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIG5vdGlmeVNweSA9IGlzU3B5RW5hYmxlZCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaGFzTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgICAgIHR5cGU6IFwiYWRkXCIsXG4gICAgICAgICAgICBvYmplY3Q6IHRoaXMsXG4gICAgICAgICAgICBuYW1lOiBuYW1lLCBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgfSA6IG51bGw7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIGNoYW5nZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAga2V5ID0gXCJcIiArIGtleTtcbiAgICAgICAgaWYgKHRoaXMuaGFzKGtleSkpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0YVtrZXldLmdldCgpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5QXNJdGVyYXRvcih0aGlzLl9rZXlzLnNsaWNlKCkpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUudmFsdWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gYXJyYXlBc0l0ZXJhdG9yKHRoaXMuX2tleXMubWFwKHRoaXMuZ2V0LCB0aGlzKSk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5lbnRyaWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gYXJyYXlBc0l0ZXJhdG9yKHRoaXMuX2tleXMubWFwKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIFtrZXksIF90aGlzLmdldChrZXkpXTsgfSkpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUuZm9yRWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmtleXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgX3RoaXMuZ2V0KGtleSksIGtleSwgX3RoaXMpOyB9KTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLm1lcmdlID0gZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChpc09ic2VydmFibGVNYXAob3RoZXIpKSB7XG4gICAgICAgICAgICBvdGhlciA9IG90aGVyLnRvSlMoKTtcbiAgICAgICAgfVxuICAgICAgICBydW5JblRyYW5zYWN0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpc1BsYWluT2JqZWN0KG90aGVyKSlcbiAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhvdGhlcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBfdGhpcy5zZXQoa2V5LCBvdGhlcltrZXldKTsgfSk7XG4gICAgICAgICAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KG90aGVyKSlcbiAgICAgICAgICAgICAgICBvdGhlci5mb3JFYWNoKGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0gX2FbMF0sIHZhbHVlID0gX2FbMV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBlbHNlIGlmIChpc0VTNk1hcChvdGhlcikpXG4gICAgICAgICAgICAgICAgb3RoZXIuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkgeyByZXR1cm4gX3RoaXMuc2V0KGtleSwgdmFsdWUpOyB9KTtcbiAgICAgICAgICAgIGVsc2UgaWYgKG90aGVyICE9PSBudWxsICYmIG90aGVyICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgZmFpbChcIkNhbm5vdCBpbml0aWFsaXplIG1hcCBmcm9tIFwiICsgb3RoZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcnVuSW5UcmFuc2FjdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB1bnRyYWNrZWQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmtleXMoKS5mb3JFYWNoKF90aGlzLmRlbGV0ZSwgX3RoaXMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUucmVwbGFjZSA9IGZ1bmN0aW9uICh2YWx1ZXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcnVuSW5UcmFuc2FjdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5jbGVhcigpO1xuICAgICAgICAgICAgX3RoaXMubWVyZ2UodmFsdWVzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9ic2VydmFibGVNYXAucHJvdG90eXBlLCBcInNpemVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9rZXlzLmxlbmd0aDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUudG9KUyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICB0aGlzLmtleXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIHJlc1trZXldID0gX3RoaXMuZ2V0KGtleSk7IH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b0pTKCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5pc1ZhbGlkS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09PSBudWxsIHx8IGtleSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAodHlwZW9mIGtleSA9PT0gXCJzdHJpbmdcIiB8fCB0eXBlb2Yga2V5ID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBrZXkgPT09IFwiYm9vbGVhblwiKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmFzc2VydFZhbGlkS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZEtleShrZXkpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYngubWFwXSBJbnZhbGlkIGtleTogJ1wiICsga2V5ICsgXCInLCBvbmx5IHN0cmluZ3MsIG51bWJlcnMgYW5kIGJvb2xlYW5zIGFyZSBhY2NlcHRlZCBhcyBrZXkgaW4gb2JzZXJ2YWJsZSBtYXBzLlwiKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lICsgXCJbeyBcIiArIHRoaXMua2V5cygpLm1hcChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBrZXkgKyBcIjogXCIgKyAoXCJcIiArIF90aGlzLmdldChrZXkpKTsgfSkuam9pbihcIiwgXCIpICsgXCIgfV1cIjtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLm9ic2VydmUgPSBmdW5jdGlvbiAobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSkge1xuICAgICAgICBpbnZhcmlhbnQoZmlyZUltbWVkaWF0ZWx5ICE9PSB0cnVlLCBnZXRNZXNzYWdlKFwibTAzM1wiKSk7XG4gICAgICAgIHJldHVybiByZWdpc3Rlckxpc3RlbmVyKHRoaXMsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmludGVyY2VwdCA9IGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgIHJldHVybiByZWdpc3RlckludGVyY2VwdG9yKHRoaXMsIGhhbmRsZXIpO1xuICAgIH07XG4gICAgcmV0dXJuIE9ic2VydmFibGVNYXA7XG59KCkpO1xuZXhwb3J0cy5PYnNlcnZhYmxlTWFwID0gT2JzZXJ2YWJsZU1hcDtcbmRlY2xhcmVJdGVyYXRvcihPYnNlcnZhYmxlTWFwLnByb3RvdHlwZSwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXMoKTtcbn0pO1xuZnVuY3Rpb24gbWFwKGluaXRpYWxWYWx1ZXMpIHtcbiAgICBkZXByZWNhdGVkKFwiYG1vYngubWFwYCBpcyBkZXByZWNhdGVkLCB1c2UgYG5ldyBPYnNlcnZhYmxlTWFwYCBvciBgbW9ieC5vYnNlcnZhYmxlLm1hcGAgaW5zdGVhZFwiKTtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5tYXAoaW5pdGlhbFZhbHVlcyk7XG59XG5leHBvcnRzLm1hcCA9IG1hcDtcbnZhciBpc09ic2VydmFibGVNYXAgPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiT2JzZXJ2YWJsZU1hcFwiLCBPYnNlcnZhYmxlTWFwKTtcbmV4cG9ydHMuaXNPYnNlcnZhYmxlTWFwID0gaXNPYnNlcnZhYmxlTWFwO1xudmFyIE9ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2JzZXJ2YWJsZU9iamVjdEFkbWluaXN0cmF0aW9uKHRhcmdldCwgbmFtZSkge1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy52YWx1ZXMgPSB7fTtcbiAgICAgICAgdGhpcy5jaGFuZ2VMaXN0ZW5lcnMgPSBudWxsO1xuICAgICAgICB0aGlzLmludGVyY2VwdG9ycyA9IG51bGw7XG4gICAgfVxuICAgIE9ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbi5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uIChjYWxsYmFjaywgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgIGludmFyaWFudChmaXJlSW1tZWRpYXRlbHkgIT09IHRydWUsIFwiYG9ic2VydmVgIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgZmlyZSBpbW1lZGlhdGVseSBwcm9wZXJ0eSBmb3Igb2JzZXJ2YWJsZSBvYmplY3RzLlwiKTtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVyTGlzdGVuZXIodGhpcywgY2FsbGJhY2spO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU9iamVjdEFkbWluaXN0cmF0aW9uLnByb3RvdHlwZS5pbnRlcmNlcHQgPSBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICByZXR1cm4gcmVnaXN0ZXJJbnRlcmNlcHRvcih0aGlzLCBoYW5kbGVyKTtcbiAgICB9O1xuICAgIHJldHVybiBPYnNlcnZhYmxlT2JqZWN0QWRtaW5pc3RyYXRpb247XG59KCkpO1xuZnVuY3Rpb24gYXNPYnNlcnZhYmxlT2JqZWN0KHRhcmdldCwgbmFtZSkge1xuICAgIGlmIChpc09ic2VydmFibGVPYmplY3QodGFyZ2V0KSlcbiAgICAgICAgcmV0dXJuIHRhcmdldC4kbW9ieDtcbiAgICBpbnZhcmlhbnQoT2JqZWN0LmlzRXh0ZW5zaWJsZSh0YXJnZXQpLCBnZXRNZXNzYWdlKFwibTAzNVwiKSk7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHRhcmdldCkpXG4gICAgICAgIG5hbWUgPSAodGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWUgfHwgXCJPYnNlcnZhYmxlT2JqZWN0XCIpICsgXCJAXCIgKyBnZXROZXh0SWQoKTtcbiAgICBpZiAoIW5hbWUpXG4gICAgICAgIG5hbWUgPSBcIk9ic2VydmFibGVPYmplY3RAXCIgKyBnZXROZXh0SWQoKTtcbiAgICB2YXIgYWRtID0gbmV3IE9ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbih0YXJnZXQsIG5hbWUpO1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcCh0YXJnZXQsIFwiJG1vYnhcIiwgYWRtKTtcbiAgICByZXR1cm4gYWRtO1xufVxuZnVuY3Rpb24gZGVmaW5lT2JzZXJ2YWJsZVByb3BlcnR5RnJvbURlc2NyaXB0b3IoYWRtLCBwcm9wTmFtZSwgZGVzY3JpcHRvciwgZGVmYXVsdEVuaGFuY2VyKSB7XG4gICAgaWYgKGFkbS52YWx1ZXNbcHJvcE5hbWVdKSB7XG4gICAgICAgIGludmFyaWFudChcInZhbHVlXCIgaW4gZGVzY3JpcHRvciwgXCJUaGUgcHJvcGVydHkgXCIgKyBwcm9wTmFtZSArIFwiIGluIFwiICsgYWRtLm5hbWUgKyBcIiBpcyBhbHJlYWR5IG9ic2VydmFibGUsIGNhbm5vdCByZWRlZmluZSBpdCBhcyBjb21wdXRlZCBwcm9wZXJ0eVwiKTtcbiAgICAgICAgYWRtLnRhcmdldFtwcm9wTmFtZV0gPSBkZXNjcmlwdG9yLnZhbHVlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikge1xuICAgICAgICBpZiAoaXNNb2RpZmllckRlc2NyaXB0b3IoZGVzY3JpcHRvci52YWx1ZSkpIHtcbiAgICAgICAgICAgIHZhciBtb2RpZmllckRlc2NyaXB0b3IgPSBkZXNjcmlwdG9yLnZhbHVlO1xuICAgICAgICAgICAgZGVmaW5lT2JzZXJ2YWJsZVByb3BlcnR5KGFkbSwgcHJvcE5hbWUsIG1vZGlmaWVyRGVzY3JpcHRvci5pbml0aWFsVmFsdWUsIG1vZGlmaWVyRGVzY3JpcHRvci5lbmhhbmNlcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNBY3Rpb24oZGVzY3JpcHRvci52YWx1ZSkgJiYgZGVzY3JpcHRvci52YWx1ZS5hdXRvQmluZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgZGVmaW5lQm91bmRBY3Rpb24oYWRtLnRhcmdldCwgcHJvcE5hbWUsIGRlc2NyaXB0b3IudmFsdWUub3JpZ2luYWxGbik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNDb21wdXRlZFZhbHVlKGRlc2NyaXB0b3IudmFsdWUpKSB7XG4gICAgICAgICAgICBkZWZpbmVDb21wdXRlZFByb3BlcnR5RnJvbUNvbXB1dGVkVmFsdWUoYWRtLCBwcm9wTmFtZSwgZGVzY3JpcHRvci52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkZWZpbmVPYnNlcnZhYmxlUHJvcGVydHkoYWRtLCBwcm9wTmFtZSwgZGVzY3JpcHRvci52YWx1ZSwgZGVmYXVsdEVuaGFuY2VyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZGVmaW5lQ29tcHV0ZWRQcm9wZXJ0eShhZG0sIHByb3BOYW1lLCBkZXNjcmlwdG9yLmdldCwgZGVzY3JpcHRvci5zZXQsIGZhbHNlLCB0cnVlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBkZWZpbmVPYnNlcnZhYmxlUHJvcGVydHkoYWRtLCBwcm9wTmFtZSwgbmV3VmFsdWUsIGVuaGFuY2VyKSB7XG4gICAgYXNzZXJ0UHJvcGVydHlDb25maWd1cmFibGUoYWRtLnRhcmdldCwgcHJvcE5hbWUpO1xuICAgIGlmIChoYXNJbnRlcmNlcHRvcnMoYWRtKSkge1xuICAgICAgICB2YXIgY2hhbmdlID0gaW50ZXJjZXB0Q2hhbmdlKGFkbSwge1xuICAgICAgICAgICAgb2JqZWN0OiBhZG0udGFyZ2V0LFxuICAgICAgICAgICAgbmFtZTogcHJvcE5hbWUsXG4gICAgICAgICAgICB0eXBlOiBcImFkZFwiLFxuICAgICAgICAgICAgbmV3VmFsdWU6IG5ld1ZhbHVlXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgbmV3VmFsdWUgPSBjaGFuZ2UubmV3VmFsdWU7XG4gICAgfVxuICAgIHZhciBvYnNlcnZhYmxlID0gYWRtLnZhbHVlc1twcm9wTmFtZV0gPSBuZXcgT2JzZXJ2YWJsZVZhbHVlKG5ld1ZhbHVlLCBlbmhhbmNlciwgYWRtLm5hbWUgKyBcIi5cIiArIHByb3BOYW1lLCBmYWxzZSk7XG4gICAgbmV3VmFsdWUgPSBvYnNlcnZhYmxlLnZhbHVlO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhZG0udGFyZ2V0LCBwcm9wTmFtZSwgZ2VuZXJhdGVPYnNlcnZhYmxlUHJvcENvbmZpZyhwcm9wTmFtZSkpO1xuICAgIG5vdGlmeVByb3BlcnR5QWRkaXRpb24oYWRtLCBhZG0udGFyZ2V0LCBwcm9wTmFtZSwgbmV3VmFsdWUpO1xufVxuZnVuY3Rpb24gZGVmaW5lQ29tcHV0ZWRQcm9wZXJ0eShhZG0sIHByb3BOYW1lLCBnZXR0ZXIsIHNldHRlciwgY29tcGFyZVN0cnVjdHVyYWwsIGFzSW5zdGFuY2VQcm9wZXJ0eSkge1xuICAgIGlmIChhc0luc3RhbmNlUHJvcGVydHkpXG4gICAgICAgIGFzc2VydFByb3BlcnR5Q29uZmlndXJhYmxlKGFkbS50YXJnZXQsIHByb3BOYW1lKTtcbiAgICBhZG0udmFsdWVzW3Byb3BOYW1lXSA9IG5ldyBDb21wdXRlZFZhbHVlKGdldHRlciwgYWRtLnRhcmdldCwgY29tcGFyZVN0cnVjdHVyYWwsIGFkbS5uYW1lICsgXCIuXCIgKyBwcm9wTmFtZSwgc2V0dGVyKTtcbiAgICBpZiAoYXNJbnN0YW5jZVByb3BlcnR5KSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhZG0udGFyZ2V0LCBwcm9wTmFtZSwgZ2VuZXJhdGVDb21wdXRlZFByb3BDb25maWcocHJvcE5hbWUpKTtcbiAgICB9XG59XG5mdW5jdGlvbiBkZWZpbmVDb21wdXRlZFByb3BlcnR5RnJvbUNvbXB1dGVkVmFsdWUoYWRtLCBwcm9wTmFtZSwgY29tcHV0ZWRWYWx1ZSkge1xuICAgIHZhciBuYW1lID0gYWRtLm5hbWUgKyBcIi5cIiArIHByb3BOYW1lO1xuICAgIGNvbXB1dGVkVmFsdWUubmFtZSA9IG5hbWU7XG4gICAgaWYgKCFjb21wdXRlZFZhbHVlLnNjb3BlKVxuICAgICAgICBjb21wdXRlZFZhbHVlLnNjb3BlID0gYWRtLnRhcmdldDtcbiAgICBhZG0udmFsdWVzW3Byb3BOYW1lXSA9IGNvbXB1dGVkVmFsdWU7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFkbS50YXJnZXQsIHByb3BOYW1lLCBnZW5lcmF0ZUNvbXB1dGVkUHJvcENvbmZpZyhwcm9wTmFtZSkpO1xufVxudmFyIG9ic2VydmFibGVQcm9wZXJ0eUNvbmZpZ3MgPSB7fTtcbnZhciBjb21wdXRlZFByb3BlcnR5Q29uZmlncyA9IHt9O1xuZnVuY3Rpb24gZ2VuZXJhdGVPYnNlcnZhYmxlUHJvcENvbmZpZyhwcm9wTmFtZSkge1xuICAgIHZhciBjb25maWcgPSBvYnNlcnZhYmxlUHJvcGVydHlDb25maWdzW3Byb3BOYW1lXTtcbiAgICBpZiAoY29uZmlnKVxuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgIHJldHVybiBvYnNlcnZhYmxlUHJvcGVydHlDb25maWdzW3Byb3BOYW1lXSA9IHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnZhbHVlc1twcm9wTmFtZV0uZ2V0KCk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgIHNldFByb3BlcnR5VmFsdWUodGhpcywgcHJvcE5hbWUsIHYpO1xuICAgICAgICB9XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdlbmVyYXRlQ29tcHV0ZWRQcm9wQ29uZmlnKHByb3BOYW1lKSB7XG4gICAgdmFyIGNvbmZpZyA9IGNvbXB1dGVkUHJvcGVydHlDb25maWdzW3Byb3BOYW1lXTtcbiAgICBpZiAoY29uZmlnKVxuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgIHJldHVybiBjb21wdXRlZFByb3BlcnR5Q29uZmlnc1twcm9wTmFtZV0gPSB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJG1vYngudmFsdWVzW3Byb3BOYW1lXS5nZXQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJG1vYngudmFsdWVzW3Byb3BOYW1lXS5zZXQodik7XG4gICAgICAgIH1cbiAgICB9O1xufVxuZnVuY3Rpb24gc2V0UHJvcGVydHlWYWx1ZShpbnN0YW5jZSwgbmFtZSwgbmV3VmFsdWUpIHtcbiAgICB2YXIgYWRtID0gaW5zdGFuY2UuJG1vYng7XG4gICAgdmFyIG9ic2VydmFibGUgPSBhZG0udmFsdWVzW25hbWVdO1xuICAgIGlmIChoYXNJbnRlcmNlcHRvcnMoYWRtKSkge1xuICAgICAgICB2YXIgY2hhbmdlID0gaW50ZXJjZXB0Q2hhbmdlKGFkbSwge1xuICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgIG9iamVjdDogaW5zdGFuY2UsXG4gICAgICAgICAgICBuYW1lOiBuYW1lLCBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghY2hhbmdlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBuZXdWYWx1ZSA9IGNoYW5nZS5uZXdWYWx1ZTtcbiAgICB9XG4gICAgbmV3VmFsdWUgPSBvYnNlcnZhYmxlLnByZXBhcmVOZXdWYWx1ZShuZXdWYWx1ZSk7XG4gICAgaWYgKG5ld1ZhbHVlICE9PSBVTkNIQU5HRUQpIHtcbiAgICAgICAgdmFyIG5vdGlmeSA9IGhhc0xpc3RlbmVycyhhZG0pO1xuICAgICAgICB2YXIgbm90aWZ5U3B5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBjaGFuZ2UgPSBub3RpZnkgfHwgbm90aWZ5U3B5ID8ge1xuICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgIG9iamVjdDogaW5zdGFuY2UsXG4gICAgICAgICAgICBvbGRWYWx1ZTogb2JzZXJ2YWJsZS52YWx1ZSxcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsIG5ld1ZhbHVlOiBuZXdWYWx1ZVxuICAgICAgICB9IDogbnVsbDtcbiAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgIHNweVJlcG9ydFN0YXJ0KGNoYW5nZSk7XG4gICAgICAgIG9ic2VydmFibGUuc2V0TmV3VmFsdWUobmV3VmFsdWUpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKGFkbSwgY2hhbmdlKTtcbiAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgIHNweVJlcG9ydEVuZCgpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG5vdGlmeVByb3BlcnR5QWRkaXRpb24oYWRtLCBvYmplY3QsIG5hbWUsIG5ld1ZhbHVlKSB7XG4gICAgdmFyIG5vdGlmeSA9IGhhc0xpc3RlbmVycyhhZG0pO1xuICAgIHZhciBub3RpZnlTcHkgPSBpc1NweUVuYWJsZWQoKTtcbiAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgdHlwZTogXCJhZGRcIixcbiAgICAgICAgb2JqZWN0OiBvYmplY3QsIG5hbWU6IG5hbWUsIG5ld1ZhbHVlOiBuZXdWYWx1ZVxuICAgIH0gOiBudWxsO1xuICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgIHNweVJlcG9ydFN0YXJ0KGNoYW5nZSk7XG4gICAgaWYgKG5vdGlmeSlcbiAgICAgICAgbm90aWZ5TGlzdGVuZXJzKGFkbSwgY2hhbmdlKTtcbiAgICBpZiAobm90aWZ5U3B5KVxuICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbn1cbnZhciBpc09ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbiA9IGNyZWF0ZUluc3RhbmNlb2ZQcmVkaWNhdGUoXCJPYnNlcnZhYmxlT2JqZWN0QWRtaW5pc3RyYXRpb25cIiwgT2JzZXJ2YWJsZU9iamVjdEFkbWluaXN0cmF0aW9uKTtcbmZ1bmN0aW9uIGlzT2JzZXJ2YWJsZU9iamVjdCh0aGluZykge1xuICAgIGlmIChpc09iamVjdCh0aGluZykpIHtcbiAgICAgICAgcnVuTGF6eUluaXRpYWxpemVycyh0aGluZyk7XG4gICAgICAgIHJldHVybiBpc09ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbih0aGluZy4kbW9ieCk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmV4cG9ydHMuaXNPYnNlcnZhYmxlT2JqZWN0ID0gaXNPYnNlcnZhYmxlT2JqZWN0O1xudmFyIFVOQ0hBTkdFRCA9IHt9O1xudmFyIE9ic2VydmFibGVWYWx1ZSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKE9ic2VydmFibGVWYWx1ZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBPYnNlcnZhYmxlVmFsdWUodmFsdWUsIGVuaGFuY2VyLCBuYW1lLCBub3RpZnlTcHkpIHtcbiAgICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgeyBuYW1lID0gXCJPYnNlcnZhYmxlVmFsdWVAXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICBpZiAobm90aWZ5U3B5ID09PSB2b2lkIDApIHsgbm90aWZ5U3B5ID0gdHJ1ZTsgfVxuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBuYW1lKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbmhhbmNlciA9IGVuaGFuY2VyO1xuICAgICAgICBfdGhpcy5oYXNVbnJlcG9ydGVkQ2hhbmdlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnZhbHVlID0gZW5oYW5jZXIodmFsdWUsIHVuZGVmaW5lZCwgbmFtZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkgJiYgaXNTcHlFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHNweVJlcG9ydCh7IHR5cGU6IFwiY3JlYXRlXCIsIG9iamVjdDogX3RoaXMsIG5ld1ZhbHVlOiBfdGhpcy52YWx1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE9ic2VydmFibGVWYWx1ZS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKG5ld1ZhbHVlKSB7XG4gICAgICAgIHZhciBvbGRWYWx1ZSA9IHRoaXMudmFsdWU7XG4gICAgICAgIG5ld1ZhbHVlID0gdGhpcy5wcmVwYXJlTmV3VmFsdWUobmV3VmFsdWUpO1xuICAgICAgICBpZiAobmV3VmFsdWUgIT09IFVOQ0hBTkdFRCkge1xuICAgICAgICAgICAgdmFyIG5vdGlmeVNweSA9IGlzU3B5RW5hYmxlZCgpO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSkge1xuICAgICAgICAgICAgICAgIHNweVJlcG9ydFN0YXJ0KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsIG9sZFZhbHVlOiBvbGRWYWx1ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXROZXdWYWx1ZShuZXdWYWx1ZSk7XG4gICAgICAgICAgICBpZiAobm90aWZ5U3B5KVxuICAgICAgICAgICAgICAgIHNweVJlcG9ydEVuZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlVmFsdWUucHJvdG90eXBlLnByZXBhcmVOZXdWYWx1ZSA9IGZ1bmN0aW9uIChuZXdWYWx1ZSkge1xuICAgICAgICBjaGVja0lmU3RhdGVNb2RpZmljYXRpb25zQXJlQWxsb3dlZCh0aGlzKTtcbiAgICAgICAgaWYgKGhhc0ludGVyY2VwdG9ycyh0aGlzKSkge1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGludGVyY2VwdENoYW5nZSh0aGlzLCB7IG9iamVjdDogdGhpcywgdHlwZTogXCJ1cGRhdGVcIiwgbmV3VmFsdWU6IG5ld1ZhbHVlIH0pO1xuICAgICAgICAgICAgaWYgKCFjaGFuZ2UpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFVOQ0hBTkdFRDtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gY2hhbmdlLm5ld1ZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIG5ld1ZhbHVlID0gdGhpcy5lbmhhbmNlcihuZXdWYWx1ZSwgdGhpcy52YWx1ZSwgdGhpcy5uYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgIT09IG5ld1ZhbHVlXG4gICAgICAgICAgICA/IG5ld1ZhbHVlXG4gICAgICAgICAgICA6IFVOQ0hBTkdFRDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVWYWx1ZS5wcm90b3R5cGUuc2V0TmV3VmFsdWUgPSBmdW5jdGlvbiAobmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIG9sZFZhbHVlID0gdGhpcy52YWx1ZTtcbiAgICAgICAgdGhpcy52YWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLnJlcG9ydENoYW5nZWQoKTtcbiAgICAgICAgaWYgKGhhc0xpc3RlbmVycyh0aGlzKSkge1xuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInVwZGF0ZVwiLFxuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcyxcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICAgICAgb2xkVmFsdWU6IG9sZFZhbHVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlVmFsdWUucHJvdG90eXBlLmludGVyY2VwdCA9IGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgIHJldHVybiByZWdpc3RlckludGVyY2VwdG9yKHRoaXMsIGhhbmRsZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS5vYnNlcnZlID0gZnVuY3Rpb24gKGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICAgICAgaWYgKGZpcmVJbW1lZGlhdGVseSlcbiAgICAgICAgICAgIGxpc3RlbmVyKHtcbiAgICAgICAgICAgICAgICBvYmplY3Q6IHRoaXMsXG4gICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdGhpcy52YWx1ZSxcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZTogdW5kZWZpbmVkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVyTGlzdGVuZXIodGhpcywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldCgpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSArIFwiW1wiICsgdGhpcy52YWx1ZSArIFwiXVwiO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS52YWx1ZU9mID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdG9QcmltaXRpdmUodGhpcy5nZXQoKSk7XG4gICAgfTtcbiAgICByZXR1cm4gT2JzZXJ2YWJsZVZhbHVlO1xufShCYXNlQXRvbSkpO1xuT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZVtwcmltaXRpdmVTeW1ib2woKV0gPSBPYnNlcnZhYmxlVmFsdWUucHJvdG90eXBlLnZhbHVlT2Y7XG52YXIgaXNPYnNlcnZhYmxlVmFsdWUgPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiT2JzZXJ2YWJsZVZhbHVlXCIsIE9ic2VydmFibGVWYWx1ZSk7XG5mdW5jdGlvbiBnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSkge1xuICAgIGlmICh0eXBlb2YgdGhpbmcgPT09IFwib2JqZWN0XCIgJiYgdGhpbmcgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZUFycmF5KHRoaW5nKSkge1xuICAgICAgICAgICAgaW52YXJpYW50KHByb3BlcnR5ID09PSB1bmRlZmluZWQsIGdldE1lc3NhZ2UoXCJtMDM2XCIpKTtcbiAgICAgICAgICAgIHJldHVybiB0aGluZy4kbW9ieC5hdG9tO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc09ic2VydmFibGVNYXAodGhpbmcpKSB7XG4gICAgICAgICAgICB2YXIgYW55VGhpbmcgPSB0aGluZztcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0eSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgIHJldHVybiBnZXRBdG9tKGFueVRoaW5nLl9rZXlzKTtcbiAgICAgICAgICAgIHZhciBvYnNlcnZhYmxlXzIgPSBhbnlUaGluZy5fZGF0YVtwcm9wZXJ0eV0gfHwgYW55VGhpbmcuX2hhc01hcFtwcm9wZXJ0eV07XG4gICAgICAgICAgICBpbnZhcmlhbnQoISFvYnNlcnZhYmxlXzIsIFwidGhlIGVudHJ5ICdcIiArIHByb3BlcnR5ICsgXCInIGRvZXMgbm90IGV4aXN0IGluIHRoZSBvYnNlcnZhYmxlIG1hcCAnXCIgKyBnZXREZWJ1Z05hbWUodGhpbmcpICsgXCInXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG9ic2VydmFibGVfMjtcbiAgICAgICAgfVxuICAgICAgICBydW5MYXp5SW5pdGlhbGl6ZXJzKHRoaW5nKTtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZU9iamVjdCh0aGluZykpIHtcbiAgICAgICAgICAgIGlmICghcHJvcGVydHkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhaWwoXCJwbGVhc2Ugc3BlY2lmeSBhIHByb3BlcnR5XCIpO1xuICAgICAgICAgICAgdmFyIG9ic2VydmFibGVfMyA9IHRoaW5nLiRtb2J4LnZhbHVlc1twcm9wZXJ0eV07XG4gICAgICAgICAgICBpbnZhcmlhbnQoISFvYnNlcnZhYmxlXzMsIFwibm8gb2JzZXJ2YWJsZSBwcm9wZXJ0eSAnXCIgKyBwcm9wZXJ0eSArIFwiJyBmb3VuZCBvbiB0aGUgb2JzZXJ2YWJsZSBvYmplY3QgJ1wiICsgZ2V0RGVidWdOYW1lKHRoaW5nKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIHJldHVybiBvYnNlcnZhYmxlXzM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQXRvbSh0aGluZykgfHwgaXNDb21wdXRlZFZhbHVlKHRoaW5nKSB8fCBpc1JlYWN0aW9uKHRoaW5nKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaW5nO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIGlmIChpc1JlYWN0aW9uKHRoaW5nLiRtb2J4KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaW5nLiRtb2J4O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWlsKFwiQ2Fubm90IG9idGFpbiBhdG9tIGZyb20gXCIgKyB0aGluZyk7XG59XG5mdW5jdGlvbiBnZXRBZG1pbmlzdHJhdGlvbih0aGluZywgcHJvcGVydHkpIHtcbiAgICBpbnZhcmlhbnQodGhpbmcsIFwiRXhwZWN0aW5nIHNvbWUgb2JqZWN0XCIpO1xuICAgIGlmIChwcm9wZXJ0eSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24oZ2V0QXRvbSh0aGluZywgcHJvcGVydHkpKTtcbiAgICBpZiAoaXNBdG9tKHRoaW5nKSB8fCBpc0NvbXB1dGVkVmFsdWUodGhpbmcpIHx8IGlzUmVhY3Rpb24odGhpbmcpKVxuICAgICAgICByZXR1cm4gdGhpbmc7XG4gICAgaWYgKGlzT2JzZXJ2YWJsZU1hcCh0aGluZykpXG4gICAgICAgIHJldHVybiB0aGluZztcbiAgICBydW5MYXp5SW5pdGlhbGl6ZXJzKHRoaW5nKTtcbiAgICBpZiAodGhpbmcuJG1vYngpXG4gICAgICAgIHJldHVybiB0aGluZy4kbW9ieDtcbiAgICBpbnZhcmlhbnQoZmFsc2UsIFwiQ2Fubm90IG9idGFpbiBhZG1pbmlzdHJhdGlvbiBmcm9tIFwiICsgdGhpbmcpO1xufVxuZnVuY3Rpb24gZ2V0RGVidWdOYW1lKHRoaW5nLCBwcm9wZXJ0eSkge1xuICAgIHZhciBuYW1lZDtcbiAgICBpZiAocHJvcGVydHkgIT09IHVuZGVmaW5lZClcbiAgICAgICAgbmFtZWQgPSBnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSk7XG4gICAgZWxzZSBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHRoaW5nKSB8fCBpc09ic2VydmFibGVNYXAodGhpbmcpKVxuICAgICAgICBuYW1lZCA9IGdldEFkbWluaXN0cmF0aW9uKHRoaW5nKTtcbiAgICBlbHNlXG4gICAgICAgIG5hbWVkID0gZ2V0QXRvbSh0aGluZyk7XG4gICAgcmV0dXJuIG5hbWVkLm5hbWU7XG59XG5mdW5jdGlvbiBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKG9uSW5pdGlhbGl6ZSwgZ2V0LCBzZXQsIGVudW1lcmFibGUsIGFsbG93Q3VzdG9tQXJndW1lbnRzKSB7XG4gICAgZnVuY3Rpb24gY2xhc3NQcm9wZXJ0eURlY29yYXRvcih0YXJnZXQsIGtleSwgZGVzY3JpcHRvciwgY3VzdG9tQXJncywgYXJnTGVuKSB7XG4gICAgICAgIGludmFyaWFudChhbGxvd0N1c3RvbUFyZ3VtZW50cyB8fCBxdWFja3NMaWtlQURlY29yYXRvcihhcmd1bWVudHMpLCBcIlRoaXMgZnVuY3Rpb24gaXMgYSBkZWNvcmF0b3IsIGJ1dCBpdCB3YXNuJ3QgaW52b2tlZCBsaWtlIGEgZGVjb3JhdG9yXCIpO1xuICAgICAgICBpZiAoIWRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgIHZhciBuZXdEZXNjcmlwdG9yID0ge1xuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IGVudW1lcmFibGUsXG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX19tb2J4SW5pdGlhbGl6ZWRQcm9wcyB8fCB0aGlzLl9fbW9ieEluaXRpYWxpemVkUHJvcHNba2V5XSAhPT0gdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVzY3JpcHRJbml0aWFsaXplUHJvcGVydHkodGhpcywga2V5LCB1bmRlZmluZWQsIG9uSW5pdGlhbGl6ZSwgY3VzdG9tQXJncywgZGVzY3JpcHRvcik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXQuY2FsbCh0aGlzLCBrZXkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX19tb2J4SW5pdGlhbGl6ZWRQcm9wcyB8fCB0aGlzLl9fbW9ieEluaXRpYWxpemVkUHJvcHNba2V5XSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZXNjcmlwdEluaXRpYWxpemVQcm9wZXJ0eSh0aGlzLCBrZXksIHYsIG9uSW5pdGlhbGl6ZSwgY3VzdG9tQXJncywgZGVzY3JpcHRvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQuY2FsbCh0aGlzLCBrZXksIHYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMyB8fCBhcmd1bWVudHMubGVuZ3RoID09PSA1ICYmIGFyZ0xlbiA8IDMpIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIG5ld0Rlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ld0Rlc2NyaXB0b3I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3BlcnR5KHRhcmdldCwgXCJfX21vYnhMYXp5SW5pdGlhbGl6ZXJzXCIpKSB7XG4gICAgICAgICAgICAgICAgYWRkSGlkZGVuUHJvcCh0YXJnZXQsIFwiX19tb2J4TGF6eUluaXRpYWxpemVyc1wiLCAodGFyZ2V0Ll9fbW9ieExhenlJbml0aWFsaXplcnMgJiYgdGFyZ2V0Ll9fbW9ieExhenlJbml0aWFsaXplcnMuc2xpY2UoKSkgfHwgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHZhbHVlXzEgPSBkZXNjcmlwdG9yLnZhbHVlLCBpbml0aWFsaXplcl8xID0gZGVzY3JpcHRvci5pbml0aWFsaXplcjtcbiAgICAgICAgICAgIHRhcmdldC5fX21vYnhMYXp5SW5pdGlhbGl6ZXJzLnB1c2goZnVuY3Rpb24gKGluc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgb25Jbml0aWFsaXplKGluc3RhbmNlLCBrZXksIChpbml0aWFsaXplcl8xID8gaW5pdGlhbGl6ZXJfMS5jYWxsKGluc3RhbmNlKSA6IHZhbHVlXzEpLCBjdXN0b21BcmdzLCBkZXNjcmlwdG9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBlbnVtZXJhYmxlLCBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9fbW9ieERpZFJ1bkxhenlJbml0aWFsaXplcnMgIT09IHRydWUpXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5MYXp5SW5pdGlhbGl6ZXJzKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0LmNhbGwodGhpcywga2V5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVycyAhPT0gdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bkxhenlJbml0aWFsaXplcnModGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIHNldC5jYWxsKHRoaXMsIGtleSwgdik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYWxsb3dDdXN0b21Bcmd1bWVudHMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChxdWFja3NMaWtlQURlY29yYXRvcihhcmd1bWVudHMpKVxuICAgICAgICAgICAgICAgIHJldHVybiBjbGFzc1Byb3BlcnR5RGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB2YXIgb3V0ZXJBcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgdmFyIGFyZ0xlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKSB7IHJldHVybiBjbGFzc1Byb3BlcnR5RGVjb3JhdG9yKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yLCBvdXRlckFyZ3MsIGFyZ0xlbik7IH07XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBjbGFzc1Byb3BlcnR5RGVjb3JhdG9yO1xufVxuZnVuY3Rpb24gdHlwZXNjcmlwdEluaXRpYWxpemVQcm9wZXJ0eShpbnN0YW5jZSwga2V5LCB2LCBvbkluaXRpYWxpemUsIGN1c3RvbUFyZ3MsIGJhc2VEZXNjcmlwdG9yKSB7XG4gICAgaWYgKCFoYXNPd25Qcm9wZXJ0eShpbnN0YW5jZSwgXCJfX21vYnhJbml0aWFsaXplZFByb3BzXCIpKVxuICAgICAgICBhZGRIaWRkZW5Qcm9wKGluc3RhbmNlLCBcIl9fbW9ieEluaXRpYWxpemVkUHJvcHNcIiwge30pO1xuICAgIGluc3RhbmNlLl9fbW9ieEluaXRpYWxpemVkUHJvcHNba2V5XSA9IHRydWU7XG4gICAgb25Jbml0aWFsaXplKGluc3RhbmNlLCBrZXksIHYsIGN1c3RvbUFyZ3MsIGJhc2VEZXNjcmlwdG9yKTtcbn1cbmZ1bmN0aW9uIHJ1bkxhenlJbml0aWFsaXplcnMoaW5zdGFuY2UpIHtcbiAgICBpZiAoaW5zdGFuY2UuX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVycyA9PT0gdHJ1ZSlcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmIChpbnN0YW5jZS5fX21vYnhMYXp5SW5pdGlhbGl6ZXJzKSB7XG4gICAgICAgIGFkZEhpZGRlblByb3AoaW5zdGFuY2UsIFwiX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVyc1wiLCB0cnVlKTtcbiAgICAgICAgaW5zdGFuY2UuX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVycyAmJiBpbnN0YW5jZS5fX21vYnhMYXp5SW5pdGlhbGl6ZXJzLmZvckVhY2goZnVuY3Rpb24gKGluaXRpYWxpemVyKSB7IHJldHVybiBpbml0aWFsaXplcihpbnN0YW5jZSk7IH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHF1YWNrc0xpa2VBRGVjb3JhdG9yKGFyZ3MpIHtcbiAgICByZXR1cm4gKGFyZ3MubGVuZ3RoID09PSAyIHx8IGFyZ3MubGVuZ3RoID09PSAzKSAmJiB0eXBlb2YgYXJnc1sxXSA9PT0gXCJzdHJpbmdcIjtcbn1cbmZ1bmN0aW9uIGl0ZXJhdG9yU3ltYm9sKCkge1xuICAgIHJldHVybiAodHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvcikgfHwgXCJAQGl0ZXJhdG9yXCI7XG59XG52YXIgSVNfSVRFUkFUSU5HX01BUktFUiA9IFwiX18kJGl0ZXJhdGluZ1wiO1xuZnVuY3Rpb24gYXJyYXlBc0l0ZXJhdG9yKGFycmF5KSB7XG4gICAgaW52YXJpYW50KGFycmF5W0lTX0lURVJBVElOR19NQVJLRVJdICE9PSB0cnVlLCBcIklsbGVnYWwgc3RhdGU6IGNhbm5vdCByZWN5Y2xlIGFycmF5IGFzIGl0ZXJhdG9yXCIpO1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcChhcnJheSwgSVNfSVRFUkFUSU5HX01BUktFUiwgdHJ1ZSk7XG4gICAgdmFyIGlkeCA9IC0xO1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcChhcnJheSwgXCJuZXh0XCIsIGZ1bmN0aW9uIG5leHQoKSB7XG4gICAgICAgIGlkeCsrO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZG9uZTogaWR4ID49IHRoaXMubGVuZ3RoLFxuICAgICAgICAgICAgdmFsdWU6IGlkeCA8IHRoaXMubGVuZ3RoID8gdGhpc1tpZHhdIDogdW5kZWZpbmVkXG4gICAgICAgIH07XG4gICAgfSk7XG4gICAgcmV0dXJuIGFycmF5O1xufVxuZnVuY3Rpb24gZGVjbGFyZUl0ZXJhdG9yKHByb3RvdFR5cGUsIGl0ZXJhdG9yRmFjdG9yeSkge1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcChwcm90b3RUeXBlLCBpdGVyYXRvclN5bWJvbCgpLCBpdGVyYXRvckZhY3RvcnkpO1xufVxudmFyIG1lc3NhZ2VzID0ge1xuICAgIFwibTAwMVwiOiBcIkl0IGlzIG5vdCBhbGxvd2VkIHRvIGFzc2lnbiBuZXcgdmFsdWVzIHRvIEBhY3Rpb24gZmllbGRzXCIsXG4gICAgXCJtMDAyXCI6IFwiYHJ1bkluQWN0aW9uYCBleHBlY3RzIGEgZnVuY3Rpb25cIixcbiAgICBcIm0wMDNcIjogXCJgcnVuSW5BY3Rpb25gIGV4cGVjdHMgYSBmdW5jdGlvbiB3aXRob3V0IGFyZ3VtZW50c1wiLFxuICAgIFwibTAwNFwiOiBcImF1dG9ydW4gZXhwZWN0cyBhIGZ1bmN0aW9uXCIsXG4gICAgXCJtMDA1XCI6IFwiV2FybmluZzogYXR0ZW1wdGVkIHRvIHBhc3MgYW4gYWN0aW9uIHRvIGF1dG9ydW4uIEFjdGlvbnMgYXJlIHVudHJhY2tlZCBhbmQgd2lsbCBub3QgdHJpZ2dlciBvbiBzdGF0ZSBjaGFuZ2VzLiBVc2UgYHJlYWN0aW9uYCBvciB3cmFwIG9ubHkgeW91ciBzdGF0ZSBtb2RpZmljYXRpb24gY29kZSBpbiBhbiBhY3Rpb24uXCIsXG4gICAgXCJtMDA2XCI6IFwiV2FybmluZzogYXR0ZW1wdGVkIHRvIHBhc3MgYW4gYWN0aW9uIHRvIGF1dG9ydW5Bc3luYy4gQWN0aW9ucyBhcmUgdW50cmFja2VkIGFuZCB3aWxsIG5vdCB0cmlnZ2VyIG9uIHN0YXRlIGNoYW5nZXMuIFVzZSBgcmVhY3Rpb25gIG9yIHdyYXAgb25seSB5b3VyIHN0YXRlIG1vZGlmaWNhdGlvbiBjb2RlIGluIGFuIGFjdGlvbi5cIixcbiAgICBcIm0wMDdcIjogXCJyZWFjdGlvbiBvbmx5IGFjY2VwdHMgMiBvciAzIGFyZ3VtZW50cy4gSWYgbWlncmF0aW5nIGZyb20gTW9iWCAyLCBwbGVhc2UgcHJvdmlkZSBhbiBvcHRpb25zIG9iamVjdFwiLFxuICAgIFwibTAwOFwiOiBcIndyYXBwaW5nIHJlYWN0aW9uIGV4cHJlc3Npb24gaW4gYGFzUmVmZXJlbmNlYCBpcyBubyBsb25nZXIgc3VwcG9ydGVkLCB1c2Ugb3B0aW9ucyBvYmplY3QgaW5zdGVhZFwiLFxuICAgIFwibTAwOVwiOiBcIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIG9uIGdldHRlciBmdW5jdGlvbnMsIGxpa2U6ICdAY29tcHV0ZWQgZ2V0IG15UHJvcHMoKSB7IHJldHVybiAuLi47IH0nLiBJdCBsb29rcyBsaWtlIGl0IHdhcyB1c2VkIG9uIGEgcHJvcGVydHkuXCIsXG4gICAgXCJtMDEwXCI6IFwiQGNvbXB1dGVkIGNhbiBvbmx5IGJlIHVzZWQgb24gZ2V0dGVyIGZ1bmN0aW9ucywgbGlrZTogJ0Bjb21wdXRlZCBnZXQgbXlQcm9wcygpIHsgcmV0dXJuIC4uLjsgfSdcIixcbiAgICBcIm0wMTFcIjogXCJGaXJzdCBhcmd1bWVudCB0byBgY29tcHV0ZWRgIHNob3VsZCBiZSBhbiBleHByZXNzaW9uLiBJZiB1c2luZyBjb21wdXRlZCBhcyBkZWNvcmF0b3IsIGRvbid0IHBhc3MgaXQgYXJndW1lbnRzXCIsXG4gICAgXCJtMDEyXCI6IFwiY29tcHV0ZWQgdGFrZXMgb25lIG9yIHR3byBhcmd1bWVudHMgaWYgdXNlZCBhcyBmdW5jdGlvblwiLFxuICAgIFwibTAxM1wiOiBcIlttb2J4LmV4cHJdICdleHByJyBzaG91bGQgb25seSBiZSB1c2VkIGluc2lkZSBvdGhlciByZWFjdGl2ZSBmdW5jdGlvbnMuXCIsXG4gICAgXCJtMDE0XCI6IFwiZXh0ZW5kT2JzZXJ2YWJsZSBleHBlY3RlZCAyIG9yIG1vcmUgYXJndW1lbnRzXCIsXG4gICAgXCJtMDE1XCI6IFwiZXh0ZW5kT2JzZXJ2YWJsZSBleHBlY3RzIGFuIG9iamVjdCBhcyBmaXJzdCBhcmd1bWVudFwiLFxuICAgIFwibTAxNlwiOiBcImV4dGVuZE9ic2VydmFibGUgc2hvdWxkIG5vdCBiZSB1c2VkIG9uIG1hcHMsIHVzZSBtYXAubWVyZ2UgaW5zdGVhZFwiLFxuICAgIFwibTAxN1wiOiBcImFsbCBhcmd1bWVudHMgb2YgZXh0ZW5kT2JzZXJ2YWJsZSBzaG91bGQgYmUgb2JqZWN0c1wiLFxuICAgIFwibTAxOFwiOiBcImV4dGVuZGluZyBhbiBvYmplY3Qgd2l0aCBhbm90aGVyIG9ic2VydmFibGUgKG9iamVjdCkgaXMgbm90IHN1cHBvcnRlZC4gUGxlYXNlIGNvbnN0cnVjdCBhbiBleHBsaWNpdCBwcm9wZXJ0eW1hcCwgdXNpbmcgYHRvSlNgIGlmIG5lZWQuIFNlZSBpc3N1ZSAjNTQwXCIsXG4gICAgXCJtMDE5XCI6IFwiW21vYnguaXNPYnNlcnZhYmxlXSBpc09ic2VydmFibGUob2JqZWN0LCBwcm9wZXJ0eU5hbWUpIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGFycmF5cyBhbmQgbWFwcy4gVXNlIG1hcC5oYXMgb3IgYXJyYXkubGVuZ3RoIGluc3RlYWQuXCIsXG4gICAgXCJtMDIwXCI6IFwibW9kaWZpZXJzIGNhbiBvbmx5IGJlIHVzZWQgZm9yIGluZGl2aWR1YWwgb2JqZWN0IHByb3BlcnRpZXNcIixcbiAgICBcIm0wMjFcIjogXCJvYnNlcnZhYmxlIGV4cGVjdHMgemVybyBvciBvbmUgYXJndW1lbnRzXCIsXG4gICAgXCJtMDIyXCI6IFwiQG9ic2VydmFibGUgY2FuIG5vdCBiZSB1c2VkIG9uIGdldHRlcnMsIHVzZSBAY29tcHV0ZWQgaW5zdGVhZFwiLFxuICAgIFwibTAyM1wiOiBcIlVzaW5nIGB0cmFuc2FjdGlvbmAgaXMgZGVwcmVjYXRlZCwgdXNlIGBydW5JbkFjdGlvbmAgb3IgYChAKWFjdGlvbmAgaW5zdGVhZC5cIixcbiAgICBcIm0wMjRcIjogXCJ3aHlSdW4oKSBjYW4gb25seSBiZSB1c2VkIGlmIGEgZGVyaXZhdGlvbiBpcyBhY3RpdmUsIG9yIGJ5IHBhc3NpbmcgYW4gY29tcHV0ZWQgdmFsdWUgLyByZWFjdGlvbiBleHBsaWNpdGx5LiBJZiB5b3UgaW52b2tlZCB3aHlSdW4gZnJvbSBpbnNpZGUgYSBjb21wdXRhdGlvbjsgdGhlIGNvbXB1dGF0aW9uIGlzIGN1cnJlbnRseSBzdXNwZW5kZWQgYnV0IHJlLWV2YWx1YXRpbmcgYmVjYXVzZSBzb21lYm9keSByZXF1ZXN0ZWQgaXRzIHZhbHVlLlwiLFxuICAgIFwibTAyNVwiOiBcIndoeVJ1biBjYW4gb25seSBiZSB1c2VkIG9uIHJlYWN0aW9ucyBhbmQgY29tcHV0ZWQgdmFsdWVzXCIsXG4gICAgXCJtMDI2XCI6IFwiYGFjdGlvbmAgY2FuIG9ubHkgYmUgaW52b2tlZCBvbiBmdW5jdGlvbnNcIixcbiAgICBcIm0wMjhcIjogXCJJdCBpcyBub3QgYWxsb3dlZCB0byBzZXQgYHVzZVN0cmljdGAgd2hlbiBhIGRlcml2YXRpb24gaXMgcnVubmluZ1wiLFxuICAgIFwibTAyOVwiOiBcIklOVEVSTkFMIEVSUk9SIG9ubHkgb25CZWNvbWVVbm9ic2VydmVkIHNob3VsZG4ndCBiZSBjYWxsZWQgdHdpY2UgaW4gYSByb3dcIixcbiAgICBcIm0wMzBhXCI6IFwiU2luY2Ugc3RyaWN0LW1vZGUgaXMgZW5hYmxlZCwgY2hhbmdpbmcgb2JzZXJ2ZWQgb2JzZXJ2YWJsZSB2YWx1ZXMgb3V0c2lkZSBhY3Rpb25zIGlzIG5vdCBhbGxvd2VkLiBQbGVhc2Ugd3JhcCB0aGUgY29kZSBpbiBhbiBgYWN0aW9uYCBpZiB0aGlzIGNoYW5nZSBpcyBpbnRlbmRlZC4gVHJpZWQgdG8gbW9kaWZ5OiBcIixcbiAgICBcIm0wMzBiXCI6IFwiU2lkZSBlZmZlY3RzIGxpa2UgY2hhbmdpbmcgc3RhdGUgYXJlIG5vdCBhbGxvd2VkIGF0IHRoaXMgcG9pbnQuIEFyZSB5b3UgdHJ5aW5nIHRvIG1vZGlmeSBzdGF0ZSBmcm9tLCBmb3IgZXhhbXBsZSwgdGhlIHJlbmRlciBmdW5jdGlvbiBvZiBhIFJlYWN0IGNvbXBvbmVudD8gVHJpZWQgdG8gbW9kaWZ5OiBcIixcbiAgICBcIm0wMzFcIjogXCJDb21wdXRlZCB2YWx1ZXMgYXJlIG5vdCBhbGxvd2VkIHRvIG5vdCBjYXVzZSBzaWRlIGVmZmVjdHMgYnkgY2hhbmdpbmcgb2JzZXJ2YWJsZXMgdGhhdCBhcmUgYWxyZWFkeSBiZWluZyBvYnNlcnZlZC4gVHJpZWQgdG8gbW9kaWZ5OiBcIixcbiAgICBcIm0wMzJcIjogXCIqIFRoaXMgY29tcHV0YXRpb24gaXMgc3VzcGVuZGVkIChub3QgaW4gdXNlIGJ5IGFueSByZWFjdGlvbikgYW5kIHdvbid0IHJ1biBhdXRvbWF0aWNhbGx5Llxcblx0RGlkbid0IGV4cGVjdCB0aGlzIGNvbXB1dGF0aW9uIHRvIGJlIHN1c3BlbmRlZCBhdCB0aGlzIHBvaW50P1xcblx0ICAxLiBNYWtlIHN1cmUgdGhpcyBjb21wdXRhdGlvbiBpcyB1c2VkIGJ5IGEgcmVhY3Rpb24gKHJlYWN0aW9uLCBhdXRvcnVuLCBvYnNlcnZlcikuXFxuXHQgIDIuIENoZWNrIHdoZXRoZXIgeW91IGFyZSB1c2luZyB0aGlzIGNvbXB1dGF0aW9uIHN5bmNocm9ub3VzbHkgKGluIHRoZSBzYW1lIHN0YWNrIGFzIHRoZXkgcmVhY3Rpb24gdGhhdCBuZWVkcyBpdCkuXCIsXG4gICAgXCJtMDMzXCI6IFwiYG9ic2VydmVgIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgZmlyZSBpbW1lZGlhdGVseSBwcm9wZXJ0eSBmb3Igb2JzZXJ2YWJsZSBtYXBzLlwiLFxuICAgIFwibTAzNFwiOiBcImBtb2J4Lm1hcGAgaXMgZGVwcmVjYXRlZCwgdXNlIGBuZXcgT2JzZXJ2YWJsZU1hcGAgb3IgYG1vYngub2JzZXJ2YWJsZS5tYXBgIGluc3RlYWRcIixcbiAgICBcIm0wMzVcIjogXCJDYW5ub3QgbWFrZSB0aGUgZGVzaWduYXRlZCBvYmplY3Qgb2JzZXJ2YWJsZTsgaXQgaXMgbm90IGV4dGVuc2libGVcIixcbiAgICBcIm0wMzZcIjogXCJJdCBpcyBub3QgcG9zc2libGUgdG8gZ2V0IGluZGV4IGF0b21zIGZyb20gYXJyYXlzXCIsXG4gICAgXCJtMDM3XCI6IFwiSGkgdGhlcmUhIEknbSBzb3JyeSB5b3UgaGF2ZSBqdXN0IHJ1biBpbnRvIGFuIGV4Y2VwdGlvbi5cXG5JZiB5b3VyIGRlYnVnZ2VyIGVuZHMgdXAgaGVyZSwga25vdyB0aGF0IHNvbWUgcmVhY3Rpb24gKGxpa2UgdGhlIHJlbmRlcigpIG9mIGFuIG9ic2VydmVyIGNvbXBvbmVudCwgYXV0b3J1biBvciByZWFjdGlvbilcXG50aHJldyBhbiBleGNlcHRpb24gYW5kIHRoYXQgbW9ieCBjYXVnaHQgaXQsIHRvIGF2b2lkIHRoYXQgaXQgYnJpbmdzIHRoZSByZXN0IG9mIHlvdXIgYXBwbGljYXRpb24gZG93bi5cXG5UaGUgb3JpZ2luYWwgY2F1c2Ugb2YgdGhlIGV4Y2VwdGlvbiAodGhlIGNvZGUgdGhhdCBjYXVzZWQgdGhpcyByZWFjdGlvbiB0byBydW4gKGFnYWluKSksIGlzIHN0aWxsIGluIHRoZSBzdGFjay5cXG5cXG5Ib3dldmVyLCBtb3JlIGludGVyZXN0aW5nIGlzIHRoZSBhY3R1YWwgc3RhY2sgdHJhY2Ugb2YgdGhlIGVycm9yIGl0c2VsZi5cXG5Ib3BlZnVsbHkgdGhlIGVycm9yIGlzIGFuIGluc3RhbmNlb2YgRXJyb3IsIGJlY2F1c2UgaW4gdGhhdCBjYXNlIHlvdSBjYW4gaW5zcGVjdCB0aGUgb3JpZ2luYWwgc3RhY2sgb2YgdGhlIGVycm9yIGZyb20gd2hlcmUgaXQgd2FzIHRocm93bi5cXG5TZWUgYGVycm9yLnN0YWNrYCBwcm9wZXJ0eSwgb3IgcHJlc3MgdGhlIHZlcnkgc3VidGxlIFxcXCIoLi4uKVxcXCIgbGluayB5b3Ugc2VlIG5lYXIgdGhlIGNvbnNvbGUuZXJyb3IgbWVzc2FnZSB0aGF0IHByb2JhYmx5IGJyb3VnaHQgeW91IGhlcmUuXFxuVGhhdCBzdGFjayBpcyBtb3JlIGludGVyZXN0aW5nIHRoYW4gdGhlIHN0YWNrIG9mIHRoaXMgY29uc29sZS5lcnJvciBpdHNlbGYuXFxuXFxuSWYgdGhlIGV4Y2VwdGlvbiB5b3Ugc2VlIGlzIGFuIGV4Y2VwdGlvbiB5b3UgY3JlYXRlZCB5b3Vyc2VsZiwgbWFrZSBzdXJlIHRvIHVzZSBgdGhyb3cgbmV3IEVycm9yKFxcXCJPb3BzXFxcIilgIGluc3RlYWQgb2YgYHRocm93IFxcXCJPb3BzXFxcImAsXFxuYmVjYXVzZSB0aGUgamF2YXNjcmlwdCBlbnZpcm9ubWVudCB3aWxsIG9ubHkgcHJlc2VydmUgdGhlIG9yaWdpbmFsIHN0YWNrIHRyYWNlIGluIHRoZSBmaXJzdCBmb3JtLlxcblxcbllvdSBjYW4gYWxzbyBtYWtlIHN1cmUgdGhlIGRlYnVnZ2VyIHBhdXNlcyB0aGUgbmV4dCB0aW1lIHRoaXMgdmVyeSBzYW1lIGV4Y2VwdGlvbiBpcyB0aHJvd24gYnkgZW5hYmxpbmcgXFxcIlBhdXNlIG9uIGNhdWdodCBleGNlcHRpb25cXFwiLlxcbihOb3RlIHRoYXQgaXQgbWlnaHQgcGF1c2Ugb24gbWFueSBvdGhlciwgdW5yZWxhdGVkIGV4Y2VwdGlvbiBhcyB3ZWxsKS5cXG5cXG5JZiB0aGF0IGFsbCBkb2Vzbid0IGhlbHAgeW91IG91dCwgZmVlbCBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgaHR0cHM6Ly9naXRodWIuY29tL21vYnhqcy9tb2J4L2lzc3VlcyFcXG5cIixcbiAgICBcIm0wMzhcIjogXCJNaXNzaW5nIGl0ZW1zIGluIHRoaXMgbGlzdD9cXG4gICAgMS4gQ2hlY2sgd2hldGhlciBhbGwgdXNlZCB2YWx1ZXMgYXJlIHByb3Blcmx5IG1hcmtlZCBhcyBvYnNlcnZhYmxlICh1c2UgaXNPYnNlcnZhYmxlIHRvIHZlcmlmeSlcXG4gICAgMi4gTWFrZSBzdXJlIHlvdSBkaWRuJ3QgZGVyZWZlcmVuY2UgdmFsdWVzIHRvbyBlYXJseS4gTW9iWCBvYnNlcnZlcyBwcm9wcywgbm90IHByaW1pdGl2ZXMuIEUuZzogdXNlICdwZXJzb24ubmFtZScgaW5zdGVhZCBvZiAnbmFtZScgaW4geW91ciBjb21wdXRhdGlvbi5cXG5cIlxufTtcbmZ1bmN0aW9uIGdldE1lc3NhZ2UoaWQpIHtcbiAgICByZXR1cm4gbWVzc2FnZXNbaWRdO1xufVxudmFyIEVNUFRZX0FSUkFZID0gW107XG5PYmplY3QuZnJlZXplKEVNUFRZX0FSUkFZKTtcbmZ1bmN0aW9uIGdldEdsb2JhbCgpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xufVxuZnVuY3Rpb24gZ2V0TmV4dElkKCkge1xuICAgIHJldHVybiArK2dsb2JhbFN0YXRlLm1vYnhHdWlkO1xufVxuZnVuY3Rpb24gZmFpbChtZXNzYWdlLCB0aGluZykge1xuICAgIGludmFyaWFudChmYWxzZSwgbWVzc2FnZSwgdGhpbmcpO1xuICAgIHRocm93IFwiWFwiO1xufVxuZnVuY3Rpb24gaW52YXJpYW50KGNoZWNrLCBtZXNzYWdlLCB0aGluZykge1xuICAgIGlmICghY2hlY2spXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4XSBJbnZhcmlhbnQgZmFpbGVkOiBcIiArIG1lc3NhZ2UgKyAodGhpbmcgPyBcIiBpbiAnXCIgKyB0aGluZyArIFwiJ1wiIDogXCJcIikpO1xufVxudmFyIGRlcHJlY2F0ZWRNZXNzYWdlcyA9IFtdO1xuZnVuY3Rpb24gZGVwcmVjYXRlZChtc2cpIHtcbiAgICBpZiAoZGVwcmVjYXRlZE1lc3NhZ2VzLmluZGV4T2YobXNnKSAhPT0gLTEpXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICBkZXByZWNhdGVkTWVzc2FnZXMucHVzaChtc2cpO1xuICAgIGNvbnNvbGUuZXJyb3IoXCJbbW9ieF0gRGVwcmVjYXRlZDogXCIgKyBtc2cpO1xuICAgIHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gb25jZShmdW5jKSB7XG4gICAgdmFyIGludm9rZWQgPSBmYWxzZTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoaW52b2tlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgaW52b2tlZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbn1cbnZhciBub29wID0gZnVuY3Rpb24gKCkgeyB9O1xuZnVuY3Rpb24gdW5pcXVlKGxpc3QpIHtcbiAgICB2YXIgcmVzID0gW107XG4gICAgbGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmIChyZXMuaW5kZXhPZihpdGVtKSA9PT0gLTEpXG4gICAgICAgICAgICByZXMucHVzaChpdGVtKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gam9pblN0cmluZ3ModGhpbmdzLCBsaW1pdCwgc2VwYXJhdG9yKSB7XG4gICAgaWYgKGxpbWl0ID09PSB2b2lkIDApIHsgbGltaXQgPSAxMDA7IH1cbiAgICBpZiAoc2VwYXJhdG9yID09PSB2b2lkIDApIHsgc2VwYXJhdG9yID0gXCIgLSBcIjsgfVxuICAgIGlmICghdGhpbmdzKVxuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICB2YXIgc2xpY2VkID0gdGhpbmdzLnNsaWNlKDAsIGxpbWl0KTtcbiAgICByZXR1cm4gXCJcIiArIHNsaWNlZC5qb2luKHNlcGFyYXRvcikgKyAodGhpbmdzLmxlbmd0aCA+IGxpbWl0ID8gXCIgKC4uLiBhbmQgXCIgKyAodGhpbmdzLmxlbmd0aCAtIGxpbWl0KSArIFwibW9yZSlcIiA6IFwiXCIpO1xufVxuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiO1xufVxuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB2YXIgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgIHJldHVybiBwcm90byA9PT0gT2JqZWN0LnByb3RvdHlwZSB8fCBwcm90byA9PT0gbnVsbDtcbn1cbmZ1bmN0aW9uIG9iamVjdEFzc2lnbigpIHtcbiAgICB2YXIgcmVzID0gYXJndW1lbnRzWzBdO1xuICAgIGZvciAodmFyIGkgPSAxLCBsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKVxuICAgICAgICAgICAgaWYgKGhhc093blByb3BlcnR5KHNvdXJjZSwga2V5KSkge1xuICAgICAgICAgICAgICAgIHJlc1trZXldID0gc291cmNlW2tleV07XG4gICAgICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiB2YWx1ZURpZENoYW5nZShjb21wYXJlU3RydWN0dXJhbCwgb2xkVmFsdWUsIG5ld1ZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiBvbGRWYWx1ZSA9PT0gJ251bWJlcicgJiYgaXNOYU4ob2xkVmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgbmV3VmFsdWUgIT09ICdudW1iZXInIHx8ICFpc05hTihuZXdWYWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiBjb21wYXJlU3RydWN0dXJhbFxuICAgICAgICA/ICFkZWVwRXF1YWwob2xkVmFsdWUsIG5ld1ZhbHVlKVxuICAgICAgICA6IG9sZFZhbHVlICE9PSBuZXdWYWx1ZTtcbn1cbnZhciBwcm90b3R5cGVIYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5mdW5jdGlvbiBoYXNPd25Qcm9wZXJ0eShvYmplY3QsIHByb3BOYW1lKSB7XG4gICAgcmV0dXJuIHByb3RvdHlwZUhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wTmFtZSk7XG59XG5mdW5jdGlvbiBtYWtlTm9uRW51bWVyYWJsZShvYmplY3QsIHByb3BOYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFkZEhpZGRlblByb3Aob2JqZWN0LCBwcm9wTmFtZXNbaV0sIG9iamVjdFtwcm9wTmFtZXNbaV1dKTtcbiAgICB9XG59XG5mdW5jdGlvbiBhZGRIaWRkZW5Qcm9wKG9iamVjdCwgcHJvcE5hbWUsIHZhbHVlKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcE5hbWUsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgIH0pO1xufVxuZnVuY3Rpb24gYWRkSGlkZGVuRmluYWxQcm9wKG9iamVjdCwgcHJvcE5hbWUsIHZhbHVlKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcE5hbWUsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB2YWx1ZTogdmFsdWVcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGlzUHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wKSB7XG4gICAgdmFyIGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcCk7XG4gICAgcmV0dXJuICFkZXNjcmlwdG9yIHx8IChkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSAhPT0gZmFsc2UgJiYgZGVzY3JpcHRvci53cml0YWJsZSAhPT0gZmFsc2UpO1xufVxuZnVuY3Rpb24gYXNzZXJ0UHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wKSB7XG4gICAgaW52YXJpYW50KGlzUHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wKSwgXCJDYW5ub3QgbWFrZSBwcm9wZXJ0eSAnXCIgKyBwcm9wICsgXCInIG9ic2VydmFibGUsIGl0IGlzIG5vdCBjb25maWd1cmFibGUgYW5kIHdyaXRhYmxlIGluIHRoZSB0YXJnZXQgb2JqZWN0XCIpO1xufVxuZnVuY3Rpb24gZ2V0RW51bWVyYWJsZUtleXMob2JqKSB7XG4gICAgdmFyIHJlcyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopXG4gICAgICAgIHJlcy5wdXNoKGtleSk7XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGRlZXBFcXVhbChhLCBiKSB7XG4gICAgaWYgKGEgPT09IG51bGwgJiYgYiA9PT0gbnVsbClcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgaWYgKGEgPT09IHVuZGVmaW5lZCAmJiBiID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIGlmICh0eXBlb2YgYSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgcmV0dXJuIGEgPT09IGI7XG4gICAgdmFyIGFJc0FycmF5ID0gaXNBcnJheUxpa2UoYSk7XG4gICAgdmFyIGFJc01hcCA9IGlzTWFwTGlrZShhKTtcbiAgICBpZiAoYUlzQXJyYXkgIT09IGlzQXJyYXlMaWtlKGIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZWxzZSBpZiAoYUlzTWFwICE9PSBpc01hcExpa2UoYikpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIGlmIChhSXNBcnJheSkge1xuICAgICAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKHZhciBpID0gYS5sZW5ndGggLSAxOyBpID49IDA7IGktLSlcbiAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKGFbaV0sIGJbaV0pKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYgKGFJc01hcCkge1xuICAgICAgICBpZiAoYS5zaXplICE9PSBiLnNpemUpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHZhciBlcXVhbHNfMSA9IHRydWU7XG4gICAgICAgIGEuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgZXF1YWxzXzEgPSBlcXVhbHNfMSAmJiBkZWVwRXF1YWwoYi5nZXQoa2V5KSwgdmFsdWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGVxdWFsc18xO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgYSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgYiA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBpZiAoYSA9PT0gbnVsbCB8fCBiID09PSBudWxsKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoaXNNYXBMaWtlKGEpICYmIGlzTWFwTGlrZShiKSkge1xuICAgICAgICAgICAgaWYgKGEuc2l6ZSAhPT0gYi5zaXplKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBkZWVwRXF1YWwob2JzZXJ2YWJsZS5zaGFsbG93TWFwKGEpLmVudHJpZXMoKSwgb2JzZXJ2YWJsZS5zaGFsbG93TWFwKGIpLmVudHJpZXMoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGdldEVudW1lcmFibGVLZXlzKGEpLmxlbmd0aCAhPT0gZ2V0RW51bWVyYWJsZUtleXMoYikubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIGEpIHtcbiAgICAgICAgICAgIGlmICghKHByb3AgaW4gYikpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgaWYgKCFkZWVwRXF1YWwoYVtwcm9wXSwgYltwcm9wXSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKG5hbWUsIGNsYXp6KSB7XG4gICAgdmFyIHByb3BOYW1lID0gXCJpc01vYlhcIiArIG5hbWU7XG4gICAgY2xhenoucHJvdG90eXBlW3Byb3BOYW1lXSA9IHRydWU7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIHJldHVybiBpc09iamVjdCh4KSAmJiB4W3Byb3BOYW1lXSA9PT0gdHJ1ZTtcbiAgICB9O1xufVxuZnVuY3Rpb24gaXNBcnJheUxpa2UoeCkge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHgpIHx8IGlzT2JzZXJ2YWJsZUFycmF5KHgpO1xufVxuZXhwb3J0cy5pc0FycmF5TGlrZSA9IGlzQXJyYXlMaWtlO1xuZnVuY3Rpb24gaXNNYXBMaWtlKHgpIHtcbiAgICByZXR1cm4gaXNFUzZNYXAoeCkgfHwgaXNPYnNlcnZhYmxlTWFwKHgpO1xufVxuZnVuY3Rpb24gaXNFUzZNYXAodGhpbmcpIHtcbiAgICBpZiAoZ2V0R2xvYmFsKCkuTWFwICE9PSB1bmRlZmluZWQgJiYgdGhpbmcgaW5zdGFuY2VvZiBnZXRHbG9iYWwoKS5NYXApXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIHByaW1pdGl2ZVN5bWJvbCgpIHtcbiAgICByZXR1cm4gKHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wudG9QcmltaXRpdmUpIHx8IFwiQEB0b1ByaW1pdGl2ZVwiO1xufVxuZnVuY3Rpb24gdG9QcmltaXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgPyBudWxsIDogdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiID8gKFwiXCIgKyB2YWx1ZSkgOiB2YWx1ZTtcbn1cbiJdfQ== | |
'use strict' | |
const mobx = require('mobx') | |
const a = mobx.observable({ | |
b: 1, | |
c: [], | |
}) | |
const dom = [ | |
document.createElement('div'), | |
document.createElement('div'), | |
document.createElement('div'), | |
document.createElement('div'), | |
] | |
dom.forEach((e, i) => { | |
e.style.background = ['steelblue', 'tomato'][i % 2] | |
document.body.appendChild(e) | |
}) | |
const start = Date.now() | |
document.body.addEventListener('click', () => { | |
a.b++ | |
a.c.push(Date.now() - start) | |
}) | |
// 1 | |
let oldValue = null | |
requestAnimationFrame(function loop() { | |
let b = a.b | |
dom[0].innerHTML = b | |
if (b !== oldValue) { | |
console.timeEnd() | |
} | |
oldValue = b | |
dom[2].innerHTML = a.c | |
requestAnimationFrame(loop) | |
}) | |
// 2 | |
mobx.autorun(() => { | |
dom[1].innerHTML += a.b + '<br>' | |
console.time() | |
}) | |
mobx.autorun(() => { | |
dom[3].innerHTML = a.c.join('<br>') | |
}) | |
;}, 0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "requirebin-sketch", | |
"version": "1.0.0", | |
"dependencies": { | |
"mobx": "3.1.0" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <body> --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <head> --> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment