Skip to content

Instantly share code, notes, and snippets.

@Hypercubed Hypercubed/index.js
Last active Sep 25, 2016

Embed
What would you like to do?
requirebin sketch
const mobx = require('mobx');
// Pattern 1, state is updated in autorun (or action)
const state = mobx.observable({
name: 'state1',
isBoolean: false,
isString: false,
input: 1
});
mobx.autorun(() => {
console.log('state someReallyExpensiveTest');
const r = someReallyExpensiveTest(state.input);
state.isBoolean = r.isBoolean;
state.isString = r.isString;
});
state.input = true;
console.log(state.name, state.isBoolean, state.isString);
state.input = 'string';
console.log(state.name, state.isBoolean, state.isString);
// Pattern 2, properties are computed and chained
const state2 = mobx.observable({
name: 'state2',
input: 2,
__result__ () {
console.log('state2 someReallyExpensiveTest');
return someReallyExpensiveTest(this.input);
},
isBoolean () {
return this.__result__.isBoolean;
},
isString () {
return this.__result__.isString;
}
});
state2.input = 'string';
console.log(state2.name, state2.isBoolean, state2.isString);
state2.input = true;
console.log(state2.name, state2.isBoolean, state2.isString);
function someReallyExpensiveTest(input) {
return {
isBoolean: typeof input === 'boolean',
isString: typeof input === 'string'
}
}
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,
getAtom: getAtom,
getDebugName: getDebugName,
getDependencyTree: getDependencyTree,
getObserverTree: getObserverTree,
isComputingDerivation: isComputingDerivation,
isSpyEnabled: isSpyEnabled,
resetGlobalState: resetGlobalState,
spyReport: spyReport,
spyReportEnd: spyReportEnd,
spyReportStart: spyReportStart,
trackTransitions: trackTransitions
};
exports._ = {
getAdministration: getAdministration,
resetGlobalState: resetGlobalState
};
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, "It is not allowed to assign new values to @action fields");
}, false, true);
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;
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", "`runInAction` expects a function");
invariant(fn.length === 0, "`runInAction` expects a function without arguments");
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 autorun(arg1, arg2, arg3) {
var name, view, scope;
if (typeof arg1 === "string") {
name = arg1;
view = arg2;
scope = arg3;
}
else if (typeof arg1 === "function") {
name = arg1.name || ("Autorun@" + getNextId());
view = arg1;
scope = arg2;
}
assertUnwrapped(view, "autorun methods cannot have modifiers");
invariant(typeof view === "function", "autorun expects a function");
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 if (typeof arg1 === "function") {
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 autorunUntil(predicate, effect, scope) {
deprecated("`autorunUntil` is deprecated, please use `when`.");
return when.apply(null, arguments);
}
exports.autorunUntil = autorunUntil;
function autorunAsync(arg1, arg2, arg3, arg4) {
var name, func, delay, scope;
if (typeof arg1 === "string") {
name = arg1;
func = arg2;
delay = arg3;
scope = arg4;
}
else if (typeof arg1 === "function") {
name = arg1.name || ("AutorunAsync@" + getNextId());
func = arg1;
delay = arg2;
scope = arg3;
}
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(arg1, arg2, arg3, arg4, arg5, arg6) {
var name, expression, effect, fireImmediately, delay, scope;
if (typeof arg1 === "string") {
name = arg1;
expression = arg2;
effect = arg3;
fireImmediately = arg4;
delay = arg5;
scope = arg6;
}
else {
name = arg1.name || arg2.name || ("Reaction@" + getNextId());
expression = arg1;
effect = arg2;
fireImmediately = arg3;
delay = arg4;
scope = arg5;
}
if (fireImmediately === void 0)
fireImmediately = false;
if (delay === void 0)
delay = 0;
var _a = getValueModeFromValue(expression, ValueMode.Reference), valueMode = _a[0], unwrappedExpression = _a[1];
var compareStructural = valueMode === ValueMode.Structure;
if (scope) {
unwrappedExpression = unwrappedExpression.bind(scope);
effect = action(name, effect.bind(scope));
}
var firstTime = true;
var isScheduled = false;
var nextValue = undefined;
var r = new Reaction(name, function () {
if (delay < 1) {
reactionRunner();
}
else if (!isScheduled) {
isScheduled = true;
setTimeout(function () {
isScheduled = false;
reactionRunner();
}, delay);
}
});
function reactionRunner() {
if (r.isDisposed)
return;
var changed = false;
r.track(function () {
var v = unwrappedExpression(r);
changed = valueDidChange(compareStructural, nextValue, v);
nextValue = v;
});
if (firstTime && fireImmediately)
effect(nextValue, r);
if (!firstTime && changed === true)
effect(nextValue, r);
if (firstTime)
firstTime = false;
}
r.schedule();
return r.getDisposer();
}
exports.reaction = reaction;
var computedDecorator = createClassPropertyDecorator(function (target, name, _, decoratorArgs, originalDescriptor) {
invariant(typeof originalDescriptor !== "undefined", "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property.");
var baseValue = originalDescriptor.get;
var setter = originalDescriptor.set;
invariant(typeof baseValue === "function", "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'");
var compareStructural = false;
if (decoratorArgs && decoratorArgs.length === 1 && decoratorArgs[0].asStructure === true)
compareStructural = true;
var adm = asObservableObject(target, undefined, ValueMode.Recursive);
defineObservableProperty(adm, name, compareStructural ? asStructure(baseValue) : baseValue, false, setter);
}, 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, true);
function computed(targetOrExpr, keyOrScopeOrSetter, baseDescriptor, options) {
if (typeof targetOrExpr === "function" && arguments.length < 3) {
if (typeof keyOrScopeOrSetter === "function")
return computedExpr(targetOrExpr, keyOrScopeOrSetter, undefined);
else
return computedExpr(targetOrExpr, undefined, keyOrScopeOrSetter);
}
return computedDecorator.apply(null, arguments);
}
exports.computed = computed;
function computedExpr(expr, setter, scope) {
var _a = getValueModeFromValue(expr, ValueMode.Recursive), mode = _a[0], value = _a[1];
return new ComputedValue(value, scope, mode === ValueMode.Structure, value.name, setter);
}
function createTransformer(transformer, onCleanup) {
invariant(typeof transformer === "function" && transformer.length === 1, "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) {
_super.call(this, function () { return transformer(sourceObject); }, null, false, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined);
this.sourceIdentifier = sourceIdentifier;
this.sourceObject = sourceObject;
}
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("[mobx.expr] 'expr' should only be used inside other reactive functions.");
return computed(expr, scope).get();
}
exports.expr = expr;
function extendObservable(target) {
var properties = [];
for (var _i = 1; _i < arguments.length; _i++) {
properties[_i - 1] = arguments[_i];
}
invariant(arguments.length >= 2, "extendObservable expected 2 or more arguments");
invariant(typeof target === "object", "extendObservable expects an object as first argument");
invariant(!(target instanceof ObservableMap), "extendObservable should not be used on maps, use map.merge instead");
properties.forEach(function (propSet) {
invariant(typeof propSet === "object", "all arguments of extendObservable should be objects");
extendObservableHelper(target, propSet, ValueMode.Recursive, null);
});
return target;
}
exports.extendObservable = extendObservable;
function extendObservableHelper(target, properties, mode, name) {
var adm = asObservableObject(target, name, mode);
for (var key in properties)
if (hasOwnProperty(properties, key)) {
if (target === properties && !isPropertyConfigurable(target, key))
continue;
setObservableObjectInstanceProperty(adm, key, properties[key]);
}
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) {
if (isPlainObject(thing) && !isObservableObject(thing)) {
deprecated("Passing plain objects to intercept / observe is deprecated and will be removed in 3.0");
return getAdministration(observable(thing)).intercept(handler);
}
return getAdministration(thing).intercept(handler);
}
function interceptProperty(thing, property, handler) {
if (isPlainObject(thing) && !isObservableObject(thing)) {
deprecated("Passing plain objects to intercept / observe is deprecated and will be removed in 3.0");
extendObservable(thing, {
property: thing[property]
});
return interceptProperty(thing, property, handler);
}
return getAdministration(thing, property).intercept(handler);
}
function isObservable(value, property) {
if (value === null || value === undefined)
return false;
if (property !== undefined) {
if (value instanceof ObservableMap || value instanceof ObservableArray)
throw new Error("[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead.");
else if (isObservableObject(value)) {
var o = value.$mobx;
return o.values && !!o.values[property];
}
return false;
}
return !!value.$mobx || value instanceof BaseAtom || value instanceof Reaction || value instanceof ComputedValue;
}
exports.isObservable = isObservable;
var decoratorImpl = createClassPropertyDecorator(function (target, name, baseValue) {
var prevA = allowStateChangesStart(true);
if (typeof baseValue === "function")
baseValue = asReference(baseValue);
var adm = asObservableObject(target, undefined, ValueMode.Recursive);
defineObservableProperty(adm, name, baseValue, true, undefined);
allowStateChangesEnd(prevA);
}, 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 observableDecorator(target, key, baseDescriptor) {
invariant(arguments.length >= 2 && arguments.length <= 3, "Illegal decorator config", key);
assertPropertyConfigurable(target, key);
invariant(!baseDescriptor || !baseDescriptor.get, "@observable can not be used on getters, use @computed instead");
return decoratorImpl.apply(null, arguments);
}
function observable(v, keyOrScope) {
if (v === void 0) { v = undefined; }
if (typeof arguments[1] === "string")
return observableDecorator.apply(null, arguments);
invariant(arguments.length < 3, "observable expects zero, one or two arguments");
if (isObservable(v))
return v;
var _a = getValueModeFromValue(v, ValueMode.Recursive), mode = _a[0], value = _a[1];
var sourceType = mode === ValueMode.Reference ? ValueType.Reference : getTypeOfValue(value);
switch (sourceType) {
case ValueType.Array:
case ValueType.PlainObject:
return makeChildObservable(value, mode);
case ValueType.Reference:
case ValueType.ComplexObject:
return new ObservableValue(value, mode);
case ValueType.ComplexFunction:
throw new Error("[mobx.observable] To be able to make a function reactive it should not have arguments. If you need an observable reference to a function, use `observable(asReference(f))`");
case ValueType.ViewFunction:
deprecated("Use `computed(expr)` instead of `observable(expr)`");
return computed(v, keyOrScope);
}
invariant(false, "Illegal State");
}
exports.observable = observable;
var ValueType;
(function (ValueType) {
ValueType[ValueType["Reference"] = 0] = "Reference";
ValueType[ValueType["PlainObject"] = 1] = "PlainObject";
ValueType[ValueType["ComplexObject"] = 2] = "ComplexObject";
ValueType[ValueType["Array"] = 3] = "Array";
ValueType[ValueType["ViewFunction"] = 4] = "ViewFunction";
ValueType[ValueType["ComplexFunction"] = 5] = "ComplexFunction";
})(ValueType || (ValueType = {}));
function getTypeOfValue(value) {
if (value === null || value === undefined)
return ValueType.Reference;
if (typeof value === "function")
return value.length ? ValueType.ComplexFunction : ValueType.ViewFunction;
if (Array.isArray(value) || value instanceof ObservableArray)
return ValueType.Array;
if (typeof value === "object")
return isPlainObject(value) ? ValueType.PlainObject : ValueType.ComplexObject;
return ValueType.Reference;
}
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) {
if (isPlainObject(thing) && !isObservableObject(thing)) {
deprecated("Passing plain objects to intercept / observe is deprecated and will be removed in 3.0");
return getAdministration(observable(thing)).observe(listener, fireImmediately);
}
return getAdministration(thing).observe(listener, fireImmediately);
}
function observeObservableProperty(thing, property, listener, fireImmediately) {
if (isPlainObject(thing) && !isObservableObject(thing)) {
deprecated("Passing plain objects to intercept / observe is deprecated and will be removed in 3.0");
extendObservable(thing, {
property: thing[property]
});
return 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 = null; }
function cache(value) {
if (detectCycles)
__alreadySeen.push([source, value]);
return value;
}
if (source instanceof Date || source instanceof RegExp)
return 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 (!source)
return source;
if (Array.isArray(source) || source instanceof ObservableArray) {
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 (source instanceof ObservableMap) {
var res_1 = cache({});
source.forEach(function (value, key) { return res_1[key] = toJS(value, detectCycles, __alreadySeen); });
return res_1;
}
if (isObservable(source) && source.$mobx instanceof ObservableValue)
return toJS(source(), detectCycles, __alreadySeen);
if (source instanceof ObservableValue)
return toJS(source.get(), detectCycles, __alreadySeen);
if (typeof source === "object") {
var res = cache({});
for (var key in source)
res[key] = toJS(source[key], detectCycles, __alreadySeen);
return res;
}
return source;
}
exports.toJS = toJS;
function toJSON(source, detectCycles, __alreadySeen) {
if (detectCycles === void 0) { detectCycles = true; }
if (__alreadySeen === void 0) { __alreadySeen = null; }
deprecated("toJSON is deprecated. Use toJS instead");
return toJS.apply(null, arguments);
}
exports.toJSON = toJSON;
function log(msg) {
console.log(msg);
return msg;
}
function whyRun(thing, prop) {
switch (arguments.length) {
case 0:
thing = globalState.trackingDerivation;
if (!thing)
return log("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 it's value.");
break;
case 2:
thing = getAtom(thing, prop);
break;
}
thing = getAtom(thing);
if (thing instanceof ComputedValue)
return log(thing.whyRun());
else if (thing instanceof Reaction)
return log(thing.whyRun());
else
invariant(false, "whyRun can only be used on reactions and computed values");
}
exports.whyRun = whyRun;
function createAction(actionName, fn) {
invariant(typeof fn === "function", "`action` can only be invoked on functions");
invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'");
var res = function () {
return executeAction(actionName, fn, this, arguments);
};
res.isMobxAction = true;
return res;
}
function executeAction(actionName, fn, scope, args) {
invariant(!(globalState.trackingDerivation instanceof ComputedValue), "Computed values or transformers should not invoke actions or trigger other side effects");
var notifySpy = isSpyEnabled();
var startTime;
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,
target: scope,
arguments: flattendArgs
});
}
var prevUntracked = untrackedStart();
transactionStart(actionName, scope, false);
var prevAllowStateChanges = allowStateChangesStart(true);
try {
return fn.apply(scope, args);
}
finally {
allowStateChangesEnd(prevAllowStateChanges);
transactionEnd(false);
untrackedEnd(prevUntracked);
if (notifySpy)
spyReportEnd({ time: Date.now() - startTime });
}
}
function useStrict(strict) {
if (arguments.length === 0) {
deprecated("`useStrict` without arguments is deprecated, use `isStrictModeEnabled()` instead");
return globalState.strictMode;
}
else {
invariant(globalState.trackingDerivation === null, "It is not allowed to set `useStrict` when a derivation is running");
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 = func();
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 () {
transactionStart("propagatingAtomChange", null, false);
propagateChanged(this);
transactionEnd(false);
};
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; }
_super.call(this, name);
this.name = name;
this.onBecomeObservedHandler = onBecomeObservedHandler;
this.onBecomeUnobservedHandler = onBecomeUnobservedHandler;
this.isPendingUnobservation = false;
this.isBeingTracked = false;
}
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 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.name = name || "ComputedValue@" + getNextId();
if (setter)
this.setter = createAction(name + "-setter", setter);
}
ComputedValue.prototype.peek = function () {
this.isComputing = true;
var prevAllowStateChanges = allowStateChangesStart(false);
var res = this.derivation.call(this.scope);
allowStateChangesEnd(prevAllowStateChanges);
this.isComputing = false;
return res;
};
;
ComputedValue.prototype.peekUntracked = function () {
var hasError = true;
try {
var res = this.peek();
hasError = false;
return res;
}
finally {
if (hasError)
handleExceptionInDerivation(this);
}
};
ComputedValue.prototype.onBecomeStale = function () {
propagateMaybeChanged(this);
};
ComputedValue.prototype.onBecomeUnobserved = function () {
invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row");
clearObserving(this);
this.value = undefined;
};
ComputedValue.prototype.get = function () {
invariant(!this.isComputing, "Cycle detected in computation " + this.name, this.derivation);
startBatch();
if (globalState.inBatch === 1) {
if (shouldCompute(this))
this.value = this.peekUntracked();
}
else {
reportObserved(this);
if (shouldCompute(this))
if (this.trackAndCompute())
propagateChangeConfirmed(this);
}
var result = this.value;
endBatch();
return result;
};
ComputedValue.prototype.recoverFromError = function () {
this.isComputing = false;
};
ComputedValue.prototype.set = function (value) {
if (this.setter)
this.setter.call(this.scope, value);
else
throw new Error("[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,
type: "compute",
fn: this.derivation,
target: this.scope
});
}
var oldValue = this.value;
var newValue = this.value = trackDerivedFunction(this, this.peek);
return valueDidChange(this.compareStructural, newValue, oldValue);
};
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(newValue, 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.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
?
" * This computation is suspended (not in use by any reaction) and won't run automatically.\n\tDidn't expect this computation to be suspended at this point?\n\t 1. Make sure this computation is used by a reaction (reaction, autorun, observer).\n\t 2. Check whether you are using this computation synchronously (in the same stack as they reaction that needs it).\n"
:
" * 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\tMissing items in this list?\n\t 1. Check whether all used values are properly marked as observable (use isObservable to verify)\n\t 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 * If the outcome of this computation changes, the following observers will be re-run:\n " + joinStrings(observers) + "\n"));
};
return 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;
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 hasError = true;
var prevUntracked = untrackedStart();
try {
var obs = derivation.observing, l = obs.length;
for (var i = 0; i < l; i++) {
var obj = obs[i];
if (obj instanceof ComputedValue) {
obj.get();
if (derivation.dependenciesState === IDerivationState.STALE) {
hasError = false;
untrackedEnd(prevUntracked);
return true;
}
}
}
hasError = false;
changeDependenciesStateTo0(derivation);
untrackedEnd(prevUntracked);
return false;
}
finally {
if (hasError) {
changeDependenciesStateTo0(derivation);
}
}
}
}
}
function isComputingDerivation() {
return globalState.trackingDerivation !== null;
}
function checkIfStateModificationsAreAllowed() {
if (!globalState.allowStateChanges) {
invariant(false, globalState.strictMode
? "It is not allowed to create or change state outside an `action` when MobX is in strict mode. Wrap the current method in `action` if this state change is intended"
: "It is not allowed to change the state when a computed value or transformer is being evaluated. Use 'autorun' to create reactive functions with side-effects.");
}
}
function trackDerivedFunction(derivation, f) {
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 hasException = true;
var result;
try {
result = f.call(derivation);
hasException = false;
}
finally {
if (hasException) {
handleExceptionInDerivation(derivation);
}
else {
globalState.trackingDerivation = prevTracking;
bindDependencies(derivation);
}
}
return result;
}
function handleExceptionInDerivation(derivation) {
var message = ("[mobx] An uncaught exception occurred while calculating your computed value, autorun or transformer. Or inside the render() method of an observer based React component. " +
"These functions should never throw exceptions as MobX will not always be able to recover from them. " +
("Please fix the error reported after this message or enable 'Pause on (caught) exceptions' in your debugger to find the root cause. In: '" + derivation.name + "'. ") +
"For more details see https://github.com/mobxjs/mobx/issues/462");
if (isSpyEnabled()) {
spyReport({
type: "error",
message: message
});
}
console.warn(message);
changeDependenciesStateTo0(derivation);
derivation.newObserving = null;
derivation.unboundDepsCount = 0;
derivation.recoverFromError();
endBatch();
resetGlobalState();
}
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 = 4;
this.trackingDerivation = null;
this.runId = 0;
this.mobxGuid = 0;
this.inTransaction = 0;
this.isRunningReactions = false;
this.inBatch = 0;
this.pendingUnobservations = [];
this.pendingReactions = [];
this.allowStateChanges = true;
this.strictMode = false;
this.resetId = 0;
this.spyListeners = [];
}
return MobXGlobals;
}());
var globalState = (function () {
var res = new MobXGlobals();
if (global.__mobservableTrackingStack || global.__mobservableViewStack)
throw new Error("[mobx] An incompatible version of mobservable is already loaded.");
if (global.__mobxGlobal && global.__mobxGlobal.version !== res.version)
throw new Error("[mobx] An incompatible version of mobx is already loaded.");
if (global.__mobxGlobal)
return global.__mobxGlobal;
return global.__mobxGlobal = res;
})();
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 === 1) {
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 = [];
}
globalState.inBatch--;
}
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);
startBatch();
runReactions();
endBatch();
}
};
Reaction.prototype.isScheduled = function () {
return this._isScheduled;
};
Reaction.prototype.runReaction = function () {
if (!this.isDisposed) {
this._isScheduled = false;
if (shouldCompute(this)) {
this._isTrackPending = true;
this.onInvalidate();
if (this._isTrackPending && isSpyEnabled()) {
spyReport({
object: this,
type: "scheduled-reaction"
});
}
}
}
};
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;
trackDerivedFunction(this, fn);
this._isRunning = false;
this._isTrackPending = false;
if (this.isDisposed) {
clearObserving(this);
}
if (notify) {
spyReportEnd({
time: Date.now() - startTime
});
}
endBatch();
};
Reaction.prototype.recoverFromError = function () {
this._isRunning = false;
this._isTrackPending = false;
};
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;
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\tMissing items in this list?\n\t 1. Check whether all used values are properly marked as observable (use isObservable to verify)\n\t 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");
};
return Reaction;
}());
exports.Reaction = Reaction;
var MAX_REACTION_ITERATIONS = 100;
function runReactions() {
if (globalState.isRunningReactions === true || globalState.inTransaction > 0)
return;
globalState.isRunningReactions = true;
var allReactions = globalState.pendingReactions;
var iterations = 0;
while (allReactions.length > 0) {
if (++iterations === MAX_REACTION_ITERATIONS) {
resetGlobalState();
throw new 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]));
}
var remainingReactions = allReactions.splice(0);
for (var i = 0, l = remainingReactions.length; i < l; i++)
remainingReactions[i].runReaction();
}
globalState.isRunningReactions = false;
}
var spyEnabled = false;
function isSpyEnabled() {
return spyEnabled;
}
function spyReport(event) {
if (!spyEnabled)
return false;
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);
spyEnabled = globalState.spyListeners.length > 0;
return once(function () {
var idx = globalState.spyListeners.indexOf(listener);
if (idx !== -1)
globalState.spyListeners.splice(idx, 1);
spyEnabled = globalState.spyListeners.length > 0;
});
}
exports.spy = spy;
function trackTransitions(onReport) {
deprecated("trackTransitions is deprecated. Use mobx.spy instead");
if (typeof onReport === "boolean") {
deprecated("trackTransitions only takes a single callback function. If you are using the mobx-react-devtools, please update them first");
onReport = arguments[1];
}
if (!onReport) {
deprecated("trackTransitions without callback has been deprecated and is a no-op now. If you are using the mobx-react-devtools, please update them first");
return function () { };
}
return spy(onReport);
}
function transaction(action, thisArg, report) {
if (thisArg === void 0) { thisArg = undefined; }
if (report === void 0) { report = true; }
transactionStart((action.name) || "anonymous transaction", thisArg, report);
var res = action.call(thisArg);
transactionEnd(report);
return res;
}
exports.transaction = transaction;
function transactionStart(name, thisArg, report) {
if (thisArg === void 0) { thisArg = undefined; }
if (report === void 0) { report = true; }
startBatch();
globalState.inTransaction += 1;
if (report && isSpyEnabled()) {
spyReportStart({
type: "transaction",
target: thisArg,
name: name
});
}
}
function transactionEnd(report) {
if (report === void 0) { report = true; }
if (--globalState.inTransaction === 0) {
runReactions();
}
if (report && isSpyEnabled())
spyReportEnd();
endBatch();
}
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();
var interceptors = interceptable.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)
return null;
}
untrackedEnd(prevU);
return change;
}
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++) {
if (Array.isArray(change)) {
listeners[i].apply(null, change);
}
else {
listeners[i](change);
}
}
untrackedEnd(prevU);
}
var ValueMode;
(function (ValueMode) {
ValueMode[ValueMode["Recursive"] = 0] = "Recursive";
ValueMode[ValueMode["Reference"] = 1] = "Reference";
ValueMode[ValueMode["Structure"] = 2] = "Structure";
ValueMode[ValueMode["Flat"] = 3] = "Flat";
})(ValueMode || (ValueMode = {}));
function asReference(value) {
return new AsReference(value);
}
exports.asReference = asReference;
function asStructure(value) {
return new AsStructure(value);
}
exports.asStructure = asStructure;
function asFlat(value) {
return new AsFlat(value);
}
exports.asFlat = asFlat;
var AsReference = (function () {
function AsReference(value) {
this.value = value;
assertUnwrapped(value, "Modifiers are not allowed to be nested");
}
return AsReference;
}());
var AsStructure = (function () {
function AsStructure(value) {
this.value = value;
assertUnwrapped(value, "Modifiers are not allowed to be nested");
}
return AsStructure;
}());
var AsFlat = (function () {
function AsFlat(value) {
this.value = value;
assertUnwrapped(value, "Modifiers are not allowed to be nested");
}
return AsFlat;
}());
function asMap(data, modifierFunc) {
return map(data, modifierFunc);
}
exports.asMap = asMap;
function getValueModeFromValue(value, defaultMode) {
if (value instanceof AsReference)
return [ValueMode.Reference, value.value];
if (value instanceof AsStructure)
return [ValueMode.Structure, value.value];
if (value instanceof AsFlat)
return [ValueMode.Flat, value.value];
return [defaultMode, value];
}
function getValueModeFromModifierFunc(func) {
if (func === asReference)
return ValueMode.Reference;
else if (func === asStructure)
return ValueMode.Structure;
else if (func === asFlat)
return ValueMode.Flat;
invariant(func === undefined, "Cannot determine value mode from function. Please pass in one of these: mobx.asReference, mobx.asStructure or mobx.asFlat, got: " + func);
return ValueMode.Recursive;
}
function makeChildObservable(value, parentMode, name) {
var childMode;
if (isObservable(value))
return value;
switch (parentMode) {
case ValueMode.Reference:
return value;
case ValueMode.Flat:
assertUnwrapped(value, "Items inside 'asFlat' cannot have modifiers");
childMode = ValueMode.Reference;
break;
case ValueMode.Structure:
assertUnwrapped(value, "Items inside 'asStructure' cannot have modifiers");
childMode = ValueMode.Structure;
break;
case ValueMode.Recursive:
_a = getValueModeFromValue(value, ValueMode.Recursive), childMode = _a[0], value = _a[1];
break;
default:
invariant(false, "Illegal State");
}
if (Array.isArray(value))
return createObservableArray(value, childMode, name);
if (isPlainObject(value) && Object.isExtensible(value))
return extendObservableHelper(value, value, childMode, name);
return value;
var _a;
}
function assertUnwrapped(value, message) {
if (value instanceof AsReference || value instanceof AsStructure || value instanceof AsFlat)
throw new Error("[mobx] asStructure / asReference / asFlat cannot be used here. " + message);
}
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, mode, array, owned) {
this.mode = mode;
this.array = array;
this.owned = owned;
this.lastKnownLength = 0;
this.interceptors = null;
this.changeListeners = null;
this.atom = new BaseAtom(name || ("ObservableArray@" + getNextId()));
}
ObservableArrayAdministration.prototype.makeReactiveArrayItem = function (value) {
assertUnwrapped(value, "Array values cannot have modifiers");
if (this.mode === ValueMode.Flat || this.mode === ValueMode.Reference)
return value;
return makeChildObservable(value, this.mode, this.atom.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) {
checkIfStateModificationsAreAllowed();
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(this.makeReactiveArrayItem, this);
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, mode, name, owned) {
if (owned === void 0) { owned = false; }
_super.call(this);
var adm = new ObservableArrayAdministration(name, mode, this, owned);
addHiddenFinalProp(this, "$mobx", adm);
if (initialValues && initialValues.length) {
adm.updateArrayLength(0, initialValues.length);
adm.values = initialValues.map(adm.makeReactiveArrayItem, adm);
adm.notifyArraySplice(0, adm.values.slice(), EMPTY_ARRAY);
}
else {
adm.values = [];
}
if (safariPrototypeSetterInheritanceBug) {
Object.defineProperty(adm.array, "0", ENTRY_0);
}
}
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 - 0] = arguments[_i];
}
this.$mobx.atom.reportObserved();
return Array.prototype.concat.apply(this.slice(), arrays.map(function (a) { return isObservableArray(a) ? a.slice() : 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 - 0] = 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 - 0] = 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.toString = function () {
return "[mobx.array] " + Array.prototype.toString.apply(this.$mobx.values, arguments);
};
ObservableArray.prototype.toLocaleString = function () {
return "[mobx.array] " + 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",
"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];
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;
assertUnwrapped(newValue, "Modifiers cannot be used on array values. For non-reactive array values use makeReactive(asFlat(array)).");
if (index < values.length) {
checkIfStateModificationsAreAllowed();
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.makeReactiveArrayItem(newValue);
var changed = (adm.mode === ValueMode.Structure) ? !deepEquals(oldValue, newValue) : oldValue !== newValue;
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 && 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);
function createObservableArray(initialValues, mode, name) {
return new ObservableArray(initialValues, mode, name);
}
function fastArray(initialValues) {
deprecated("fastArray is deprecated. Please use `observable(asFlat([]))`");
return createObservableArray(initialValues, ValueMode.Flat, null);
}
exports.fastArray = fastArray;
function isObservableArray(thing) {
return thing instanceof ObservableArray;
}
exports.isObservableArray = isObservableArray;
var ObservableMapMarker = {};
var ObservableMap = (function () {
function ObservableMap(initialData, valueModeFunc) {
var _this = this;
this.$mobx = ObservableMapMarker;
this._data = {};
this._hasMap = {};
this.name = "ObservableMap@" + getNextId();
this._keys = new ObservableArray(null, ValueMode.Reference, this.name + ".keys()", true);
this.interceptors = null;
this.changeListeners = null;
this._valueMode = getValueModeFromModifierFunc(valueModeFunc);
if (this._valueMode === ValueMode.Flat)
this._valueMode = ValueMode.Reference;
allowStateChanges(true, function () {
if (isPlainObject(initialData))
_this.merge(initialData);
else if (Array.isArray(initialData))
initialData.forEach(function (_a) {
var key = _a[0], value = _a[1];
return _this.set(key, value);
});
});
}
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);
assertUnwrapped(value, "[mobx.map.set] Expected unwrapped value to be inserted to key '" + key + "'. If you need to use modifiers pass them as second argument to the constructor");
if (hasInterceptors(this)) {
var change = interceptChange(this, {
type: hasKey ? "update" : "add",
object: this,
newValue: value,
name: key
});
if (!change)
return;
value = change.newValue;
}
if (hasKey) {
this._updateValue(key, value);
}
else {
this._addValue(key, value);
}
};
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);
transaction(function () {
_this._keys.remove(key);
_this._updateHasMapEntry(key, false);
var observable = _this._data[key];
observable.setNewValue(undefined);
_this._data[key] = undefined;
}, undefined, false);
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, ValueMode.Reference, 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;
transaction(function () {
var observable = _this._data[name] = new ObservableValue(newValue, _this._valueMode, _this.name + "." + name, false);
newValue = observable.value;
_this._updateHasMapEntry(name, true);
_this._keys.push(name);
}, undefined, false);
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); });
};
ObservableMap.prototype.merge = function (other) {
var _this = this;
transaction(function () {
if (other instanceof ObservableMap)
other.keys().forEach(function (key) { return _this.set(key, other.get(key)); });
else
Object.keys(other).forEach(function (key) { return _this.set(key, other[key]); });
}, undefined, false);
return this;
};
ObservableMap.prototype.clear = function () {
var _this = this;
transaction(function () {
untracked(function () {
_this.keys().forEach(_this.delete, _this);
});
}, undefined, false);
};
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.toJs = function () {
deprecated("toJs is deprecated, use toJS instead");
return this.toJS();
};
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 false;
return true;
};
ObservableMap.prototype.assertValidKey = function (key) {
if (!this.isValidKey(key))
throw new Error("[mobx.map] Invalid key: '" + key + "'");
};
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, "`observe` doesn't support the fire immediately property for observable maps.");
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, valueModifier) {
return new ObservableMap(initialValues, valueModifier);
}
exports.map = map;
function isObservableMap(thing) {
return thing instanceof ObservableMap;
}
exports.isObservableMap = isObservableMap;
var ObservableObjectAdministration = (function () {
function ObservableObjectAdministration(target, name, mode) {
this.target = target;
this.name = name;
this.mode = mode;
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, mode) {
if (mode === void 0) { mode = ValueMode.Recursive; }
if (isObservableObject(target))
return target.$mobx;
if (!isPlainObject(target))
name = target.constructor.name + "@" + getNextId();
if (!name)
name = "ObservableObject@" + getNextId();
var adm = new ObservableObjectAdministration(target, name, mode);
addHiddenFinalProp(target, "$mobx", adm);
return adm;
}
function setObservableObjectInstanceProperty(adm, propName, value) {
if (adm.values[propName])
adm.target[propName] = value;
else
defineObservableProperty(adm, propName, value, true, undefined);
}
function defineObservableProperty(adm, propName, newValue, asInstanceProperty, setter) {
if (asInstanceProperty)
assertPropertyConfigurable(adm.target, propName);
var observable;
var name = adm.name + "." + propName;
var isComputed = true;
if (newValue instanceof ObservableValue) {
observable = newValue;
isComputed = false;
}
else if (newValue instanceof ComputedValue) {
observable = newValue;
if (!newValue.scope)
newValue.scope = adm.target;
}
else if (typeof newValue === "function" && newValue.length === 0 && !isAction(newValue)) {
observable = new ComputedValue(newValue, adm.target, false, name, setter);
}
else if (newValue instanceof AsStructure && typeof newValue.value === "function" && newValue.value.length === 0) {
observable = new ComputedValue(newValue.value, adm.target, true, name, setter);
}
else {
isComputed = false;
if (hasInterceptors(adm)) {
var change = interceptChange(adm, {
object: adm.target,
name: propName,
type: "add",
newValue: newValue
});
if (!change)
return;
newValue = change.newValue;
}
observable = new ObservableValue(newValue, adm.mode, name, false);
newValue = observable.value;
}
adm.values[propName] = observable;
if (asInstanceProperty) {
Object.defineProperty(adm.target, propName, isComputed ? generateComputedPropConfig(propName) : generateObservablePropConfig(propName));
}
if (!isComputed)
notifyPropertyAddition(adm, adm.target, propName, newValue);
}
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 = notifyListeners || hasListeners ? {
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();
}
function isObservableObject(thing) {
if (typeof thing === "object" && thing !== null) {
runLazyInitializers(thing);
return thing.$mobx instanceof ObservableObjectAdministration;
}
return false;
}
exports.isObservableObject = isObservableObject;
var UNCHANGED = {};
var ObservableValue = (function (_super) {
__extends(ObservableValue, _super);
function ObservableValue(value, mode, name, notifySpy) {
if (name === void 0) { name = "ObservableValue@" + getNextId(); }
if (notifySpy === void 0) { notifySpy = true; }
_super.call(this, name);
this.mode = mode;
this.hasUnreportedChange = false;
this.value = undefined;
var _a = getValueModeFromValue(value, ValueMode.Recursive), childmode = _a[0], unwrappedValue = _a[1];
if (this.mode === ValueMode.Recursive)
this.mode = childmode;
this.value = makeChildObservable(unwrappedValue, this.mode, this.name);
if (notifySpy && isSpyEnabled()) {
spyReport({ type: "create", object: this, newValue: this.value });
}
}
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) {
assertUnwrapped(newValue, "Modifiers cannot be used on non-initial values.");
checkIfStateModificationsAreAllowed();
if (hasInterceptors(this)) {
var change = interceptChange(this, { object: this, type: "update", newValue: newValue });
if (!change)
return UNCHANGED;
newValue = change.newValue;
}
var changed = valueDidChange(this.mode === ValueMode.Structure, this.value, newValue);
if (changed)
return makeChildObservable(newValue, this.mode, this.name);
return UNCHANGED;
};
ObservableValue.prototype.setNewValue = function (newValue) {
var oldValue = this.value;
this.value = newValue;
this.reportChanged();
if (hasListeners(this))
notifyListeners(this, [newValue, 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(this.value, undefined);
return registerListener(this, listener);
};
ObservableValue.prototype.toJSON = function () {
return this.get();
};
ObservableValue.prototype.toString = function () {
return this.name + "[" + this.value + "]";
};
return ObservableValue;
}(BaseAtom));
function getAtom(thing, property) {
if (typeof thing === "object" && thing !== null) {
if (isObservableArray(thing)) {
invariant(property === undefined, "It is not possible to get index atoms from arrays");
return thing.$mobx.atom;
}
if (isObservableMap(thing)) {
if (property === undefined)
return getAtom(thing._keys);
var observable_2 = thing._data[property] || thing._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)) {
invariant(!!property, "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 (thing instanceof BaseAtom || thing instanceof ComputedValue || thing instanceof Reaction) {
return thing;
}
}
else if (typeof thing === "function") {
if (thing.$mobx instanceof Reaction) {
return thing.$mobx;
}
}
invariant(false, "Cannot obtain atom from " + thing);
}
function getAdministration(thing, property) {
invariant(thing, "Expection some object");
if (property !== undefined)
return getAdministration(getAtom(thing, property));
if (thing instanceof BaseAtom || thing instanceof ComputedValue || thing instanceof Reaction)
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) {
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) {
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;
return function (target, key, descriptor) { return classPropertyDecorator(target, key, descriptor, outerArgs); };
};
}
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 SimpleEventEmitter = (function () {
function SimpleEventEmitter() {
this.listeners = [];
deprecated("extras.SimpleEventEmitter is deprecated and will be removed in the next major release");
}
SimpleEventEmitter.prototype.emit = function () {
var listeners = this.listeners.slice();
for (var i = 0, l = listeners.length; i < l; i++)
listeners[i].apply(null, arguments);
};
SimpleEventEmitter.prototype.on = function (listener) {
var _this = this;
this.listeners.push(listener);
return once(function () {
var idx = _this.listeners.indexOf(listener);
if (idx !== -1)
_this.listeners.splice(idx, 1);
});
};
SimpleEventEmitter.prototype.once = function (listener) {
var subscription = this.on(function () {
subscription();
listener.apply(this, arguments);
});
return subscription;
};
return SimpleEventEmitter;
}());
exports.SimpleEventEmitter = SimpleEventEmitter;
var EMPTY_ARRAY = [];
Object.freeze(EMPTY_ARRAY);
function getNextId() {
return ++globalState.mobxGuid;
}
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;
deprecatedMessages.push(msg);
console.error("[mobx] Deprecated: " + msg);
}
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 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) {
return compareStructural
? !deepEquals(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 deepEquals(a, b) {
if (a === null && b === null)
return true;
if (a === undefined && b === undefined)
return true;
var aIsArray = Array.isArray(a) || isObservableArray(a);
if (aIsArray !== (Array.isArray(b) || isObservableArray(b))) {
return false;
}
else if (aIsArray) {
if (a.length !== b.length)
return false;
for (var i = a.length - 1; i >= 0; i--)
if (!deepEquals(a[i], b[i]))
return false;
return true;
}
else if (typeof a === "object" && typeof b === "object") {
if (a === null || b === null)
return false;
if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length)
return false;
for (var prop in a) {
if (!(prop in b))
return false;
if (!deepEquals(a[prop], b[prop]))
return false;
}
return true;
}
return a === b;
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9tb2J4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xufTtcbnJlZ2lzdGVyR2xvYmFscygpO1xuZXhwb3J0cy5leHRyYXMgPSB7XG4gICAgYWxsb3dTdGF0ZUNoYW5nZXM6IGFsbG93U3RhdGVDaGFuZ2VzLFxuICAgIGdldEF0b206IGdldEF0b20sXG4gICAgZ2V0RGVidWdOYW1lOiBnZXREZWJ1Z05hbWUsXG4gICAgZ2V0RGVwZW5kZW5jeVRyZWU6IGdldERlcGVuZGVuY3lUcmVlLFxuICAgIGdldE9ic2VydmVyVHJlZTogZ2V0T2JzZXJ2ZXJUcmVlLFxuICAgIGlzQ29tcHV0aW5nRGVyaXZhdGlvbjogaXNDb21wdXRpbmdEZXJpdmF0aW9uLFxuICAgIGlzU3B5RW5hYmxlZDogaXNTcHlFbmFibGVkLFxuICAgIHJlc2V0R2xvYmFsU3RhdGU6IHJlc2V0R2xvYmFsU3RhdGUsXG4gICAgc3B5UmVwb3J0OiBzcHlSZXBvcnQsXG4gICAgc3B5UmVwb3J0RW5kOiBzcHlSZXBvcnRFbmQsXG4gICAgc3B5UmVwb3J0U3RhcnQ6IHNweVJlcG9ydFN0YXJ0LFxuICAgIHRyYWNrVHJhbnNpdGlvbnM6IHRyYWNrVHJhbnNpdGlvbnNcbn07XG5leHBvcnRzLl8gPSB7XG4gICAgZ2V0QWRtaW5pc3RyYXRpb246IGdldEFkbWluaXN0cmF0aW9uLFxuICAgIHJlc2V0R2xvYmFsU3RhdGU6IHJlc2V0R2xvYmFsU3RhdGVcbn07XG5pZiAodHlwZW9mIF9fTU9CWF9ERVZUT09MU19HTE9CQUxfSE9PS19fID09PSAnb2JqZWN0Jykge1xuICAgIF9fTU9CWF9ERVZUT09MU19HTE9CQUxfSE9PS19fLmluamVjdE1vYngobW9kdWxlLmV4cG9ydHMpO1xufVxudmFyIGFjdGlvbkZpZWxkRGVjb3JhdG9yID0gY3JlYXRlQ2xhc3NQcm9wZXJ0eURlY29yYXRvcihmdW5jdGlvbiAodGFyZ2V0LCBrZXksIHZhbHVlLCBhcmdzLCBvcmlnaW5hbERlc2NyaXB0b3IpIHtcbiAgICB2YXIgYWN0aW9uTmFtZSA9IChhcmdzICYmIGFyZ3MubGVuZ3RoID09PSAxKSA/IGFyZ3NbMF0gOiAodmFsdWUubmFtZSB8fCBrZXkgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCIpO1xuICAgIHZhciB3cmFwcGVkQWN0aW9uID0gYWN0aW9uKGFjdGlvbk5hbWUsIHZhbHVlKTtcbiAgICBhZGRIaWRkZW5Qcm9wKHRhcmdldCwga2V5LCB3cmFwcGVkQWN0aW9uKTtcbn0sIGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gdGhpc1trZXldO1xufSwgZnVuY3Rpb24gKCkge1xuICAgIGludmFyaWFudChmYWxzZSwgXCJJdCBpcyBub3QgYWxsb3dlZCB0byBhc3NpZ24gbmV3IHZhbHVlcyB0byBAYWN0aW9uIGZpZWxkc1wiKTtcbn0sIGZhbHNlLCB0cnVlKTtcbmZ1bmN0aW9uIGFjdGlvbihhcmcxLCBhcmcyLCBhcmczLCBhcmc0KSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUFjdGlvbihhcmcxLm5hbWUgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCIsIGFyZzEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiBhcmcyID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHJldHVybiBjcmVhdGVBY3Rpb24oYXJnMSwgYXJnMik7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpXG4gICAgICAgIHJldHVybiBuYW1lZEFjdGlvbkRlY29yYXRvcihhcmcxKTtcbiAgICByZXR1cm4gbmFtZWRBY3Rpb25EZWNvcmF0b3IoYXJnMikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbn1cbmV4cG9ydHMuYWN0aW9uID0gYWN0aW9uO1xuZnVuY3Rpb24gbmFtZWRBY3Rpb25EZWNvcmF0b3IobmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBwcm9wLCBkZXNjcmlwdG9yKSB7XG4gICAgICAgIGlmIChkZXNjcmlwdG9yICYmIHR5cGVvZiBkZXNjcmlwdG9yLnZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBjcmVhdGVBY3Rpb24obmFtZSwgZGVzY3JpcHRvci52YWx1ZSk7XG4gICAgICAgICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3Rpb25GaWVsZERlY29yYXRvcihuYW1lKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG59XG5mdW5jdGlvbiBydW5JbkFjdGlvbihhcmcxLCBhcmcyLCBhcmczKSB7XG4gICAgdmFyIGFjdGlvbk5hbWUgPSB0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIiA/IGFyZzEgOiBhcmcxLm5hbWUgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCI7XG4gICAgdmFyIGZuID0gdHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIiA/IGFyZzEgOiBhcmcyO1xuICAgIHZhciBzY29wZSA9IHR5cGVvZiBhcmcxID09PSBcImZ1bmN0aW9uXCIgPyBhcmcyIDogYXJnMztcbiAgICBpbnZhcmlhbnQodHlwZW9mIGZuID09PSBcImZ1bmN0aW9uXCIsIFwiYHJ1bkluQWN0aW9uYCBleHBlY3RzIGEgZnVuY3Rpb25cIik7XG4gICAgaW52YXJpYW50KGZuLmxlbmd0aCA9PT0gMCwgXCJgcnVuSW5BY3Rpb25gIGV4cGVjdHMgYSBmdW5jdGlvbiB3aXRob3V0IGFyZ3VtZW50c1wiKTtcbiAgICBpbnZhcmlhbnQodHlwZW9mIGFjdGlvbk5hbWUgPT09IFwic3RyaW5nXCIgJiYgYWN0aW9uTmFtZS5sZW5ndGggPiAwLCBcImFjdGlvbnMgc2hvdWxkIGhhdmUgdmFsaWQgbmFtZXMsIGdvdDogJ1wiICsgYWN0aW9uTmFtZSArIFwiJ1wiKTtcbiAgICByZXR1cm4gZXhlY3V0ZUFjdGlvbihhY3Rpb25OYW1lLCBmbiwgc2NvcGUsIHVuZGVmaW5lZCk7XG59XG5leHBvcnRzLnJ1bkluQWN0aW9uID0gcnVuSW5BY3Rpb247XG5mdW5jdGlvbiBpc0FjdGlvbih0aGluZykge1xuICAgIHJldHVybiB0eXBlb2YgdGhpbmcgPT09IFwiZnVuY3Rpb25cIiAmJiB0aGluZy5pc01vYnhBY3Rpb24gPT09IHRydWU7XG59XG5leHBvcnRzLmlzQWN0aW9uID0gaXNBY3Rpb247XG5mdW5jdGlvbiBhdXRvcnVuKGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgICB2YXIgbmFtZSwgdmlldywgc2NvcGU7XG4gICAgaWYgKHR5cGVvZiBhcmcxID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG5hbWUgPSBhcmcxO1xuICAgICAgICB2aWV3ID0gYXJnMjtcbiAgICAgICAgc2NvcGUgPSBhcmczO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgYXJnMSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIG5hbWUgPSBhcmcxLm5hbWUgfHwgKFwiQXV0b3J1bkBcIiArIGdldE5leHRJZCgpKTtcbiAgICAgICAgdmlldyA9IGFyZzE7XG4gICAgICAgIHNjb3BlID0gYXJnMjtcbiAgICB9XG4gICAgYXNzZXJ0VW53cmFwcGVkKHZpZXcsIFwiYXV0b3J1biBtZXRob2RzIGNhbm5vdCBoYXZlIG1vZGlmaWVyc1wiKTtcbiAgICBpbnZhcmlhbnQodHlwZW9mIHZpZXcgPT09IFwiZnVuY3Rpb25cIiwgXCJhdXRvcnVuIGV4cGVjdHMgYSBmdW5jdGlvblwiKTtcbiAgICBpZiAoc2NvcGUpXG4gICAgICAgIHZpZXcgPSB2aWV3LmJpbmQoc2NvcGUpO1xuICAgIHZhciByZWFjdGlvbiA9IG5ldyBSZWFjdGlvbihuYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudHJhY2socmVhY3Rpb25SdW5uZXIpO1xuICAgIH0pO1xuICAgIGZ1bmN0aW9uIHJlYWN0aW9uUnVubmVyKCkge1xuICAgICAgICB2aWV3KHJlYWN0aW9uKTtcbiAgICB9XG4gICAgcmVhY3Rpb24uc2NoZWR1bGUoKTtcbiAgICByZXR1cm4gcmVhY3Rpb24uZ2V0RGlzcG9zZXIoKTtcbn1cbmV4cG9ydHMuYXV0b3J1biA9IGF1dG9ydW47XG5mdW5jdGlvbiB3aGVuKGFyZzEsIGFyZzIsIGFyZzMsIGFyZzQpIHtcbiAgICB2YXIgbmFtZSwgcHJlZGljYXRlLCBlZmZlY3QsIHNjb3BlO1xuICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBuYW1lID0gYXJnMTtcbiAgICAgICAgcHJlZGljYXRlID0gYXJnMjtcbiAgICAgICAgZWZmZWN0ID0gYXJnMztcbiAgICAgICAgc2NvcGUgPSBhcmc0O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgYXJnMSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIG5hbWUgPSAoXCJXaGVuQFwiICsgZ2V0TmV4dElkKCkpO1xuICAgICAgICBwcmVkaWNhdGUgPSBhcmcxO1xuICAgICAgICBlZmZlY3QgPSBhcmcyO1xuICAgICAgICBzY29wZSA9IGFyZzM7XG4gICAgfVxuICAgIHZhciBkaXNwb3NlciA9IGF1dG9ydW4obmFtZSwgZnVuY3Rpb24gKHIpIHtcbiAgICAgICAgaWYgKHByZWRpY2F0ZS5jYWxsKHNjb3BlKSkge1xuICAgICAgICAgICAgci5kaXNwb3NlKCk7XG4gICAgICAgICAgICB2YXIgcHJldlVudHJhY2tlZCA9IHVudHJhY2tlZFN0YXJ0KCk7XG4gICAgICAgICAgICBlZmZlY3QuY2FsbChzY29wZSk7XG4gICAgICAgICAgICB1bnRyYWNrZWRFbmQocHJldlVudHJhY2tlZCk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gZGlzcG9zZXI7XG59XG5leHBvcnRzLndoZW4gPSB3aGVuO1xuZnVuY3Rpb24gYXV0b3J1blVudGlsKHByZWRpY2F0ZSwgZWZmZWN0LCBzY29wZSkge1xuICAgIGRlcHJlY2F0ZWQoXCJgYXV0b3J1blVudGlsYCBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGB3aGVuYC5cIik7XG4gICAgcmV0dXJuIHdoZW4uYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbn1cbmV4cG9ydHMuYXV0b3J1blVudGlsID0gYXV0b3J1blVudGlsO1xuZnVuY3Rpb24gYXV0b3J1bkFzeW5jKGFyZzEsIGFyZzIsIGFyZzMsIGFyZzQpIHtcbiAgICB2YXIgbmFtZSwgZnVuYywgZGVsYXksIHNjb3BlO1xuICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBuYW1lID0gYXJnMTtcbiAgICAgICAgZnVuYyA9IGFyZzI7XG4gICAgICAgIGRlbGF5ID0gYXJnMztcbiAgICAgICAgc2NvcGUgPSBhcmc0O1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgYXJnMSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIG5hbWUgPSBhcmcxLm5hbWUgfHwgKFwiQXV0b3J1bkFzeW5jQFwiICsgZ2V0TmV4dElkKCkpO1xuICAgICAgICBmdW5jID0gYXJnMTtcbiAgICAgICAgZGVsYXkgPSBhcmcyO1xuICAgICAgICBzY29wZSA9IGFyZzM7XG4gICAgfVxuICAgIGlmIChkZWxheSA9PT0gdm9pZCAwKVxuICAgICAgICBkZWxheSA9IDE7XG4gICAgaWYgKHNjb3BlKVxuICAgICAgICBmdW5jID0gZnVuYy5iaW5kKHNjb3BlKTtcbiAgICB2YXIgaXNTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICB2YXIgciA9IG5ldyBSZWFjdGlvbihuYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghaXNTY2hlZHVsZWQpIHtcbiAgICAgICAgICAgIGlzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKCFyLmlzRGlzcG9zZWQpXG4gICAgICAgICAgICAgICAgICAgIHIudHJhY2socmVhY3Rpb25SdW5uZXIpO1xuICAgICAgICAgICAgfSwgZGVsYXkpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gcmVhY3Rpb25SdW5uZXIoKSB7IGZ1bmMocik7IH1cbiAgICByLnNjaGVkdWxlKCk7XG4gICAgcmV0dXJuIHIuZ2V0RGlzcG9zZXIoKTtcbn1cbmV4cG9ydHMuYXV0b3J1bkFzeW5jID0gYXV0b3J1bkFzeW5jO1xuZnVuY3Rpb24gcmVhY3Rpb24oYXJnMSwgYXJnMiwgYXJnMywgYXJnNCwgYXJnNSwgYXJnNikge1xuICAgIHZhciBuYW1lLCBleHByZXNzaW9uLCBlZmZlY3QsIGZpcmVJbW1lZGlhdGVseSwgZGVsYXksIHNjb3BlO1xuICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBuYW1lID0gYXJnMTtcbiAgICAgICAgZXhwcmVzc2lvbiA9IGFyZzI7XG4gICAgICAgIGVmZmVjdCA9IGFyZzM7XG4gICAgICAgIGZpcmVJbW1lZGlhdGVseSA9IGFyZzQ7XG4gICAgICAgIGRlbGF5ID0gYXJnNTtcbiAgICAgICAgc2NvcGUgPSBhcmc2O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgbmFtZSA9IGFyZzEubmFtZSB8fCBhcmcyLm5hbWUgfHwgKFwiUmVhY3Rpb25AXCIgKyBnZXROZXh0SWQoKSk7XG4gICAgICAgIGV4cHJlc3Npb24gPSBhcmcxO1xuICAgICAgICBlZmZlY3QgPSBhcmcyO1xuICAgICAgICBmaXJlSW1tZWRpYXRlbHkgPSBhcmczO1xuICAgICAgICBkZWxheSA9IGFyZzQ7XG4gICAgICAgIHNjb3BlID0gYXJnNTtcbiAgICB9XG4gICAgaWYgKGZpcmVJbW1lZGlhdGVseSA9PT0gdm9pZCAwKVxuICAgICAgICBmaXJlSW1tZWRpYXRlbHkgPSBmYWxzZTtcbiAgICBpZiAoZGVsYXkgPT09IHZvaWQgMClcbiAgICAgICAgZGVsYXkgPSAwO1xuICAgIHZhciBfYSA9IGdldFZhbHVlTW9kZUZyb21WYWx1ZShleHByZXNzaW9uLCBWYWx1ZU1vZGUuUmVmZXJlbmNlKSwgdmFsdWVNb2RlID0gX2FbMF0sIHVud3JhcHBlZEV4cHJlc3Npb24gPSBfYVsxXTtcbiAgICB2YXIgY29tcGFyZVN0cnVjdHVyYWwgPSB2YWx1ZU1vZGUgPT09IFZhbHVlTW9kZS5TdHJ1Y3R1cmU7XG4gICAgaWYgKHNjb3BlKSB7XG4gICAgICAgIHVud3JhcHBlZEV4cHJlc3Npb24gPSB1bndyYXBwZWRFeHByZXNzaW9uLmJpbmQoc2NvcGUpO1xuICAgICAgICBlZmZlY3QgPSBhY3Rpb24obmFtZSwgZWZmZWN0LmJpbmQoc2NvcGUpKTtcbiAgICB9XG4gICAgdmFyIGZpcnN0VGltZSA9IHRydWU7XG4gICAgdmFyIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgdmFyIG5leHRWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICB2YXIgciA9IG5ldyBSZWFjdGlvbihuYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChkZWxheSA8IDEpIHtcbiAgICAgICAgICAgIHJlYWN0aW9uUnVubmVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIWlzU2NoZWR1bGVkKSB7XG4gICAgICAgICAgICBpc1NjaGVkdWxlZCA9IHRydWU7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpc1NjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlYWN0aW9uUnVubmVyKCk7XG4gICAgICAgICAgICB9LCBkZWxheSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBmdW5jdGlvbiByZWFjdGlvblJ1bm5lcigpIHtcbiAgICAgICAgaWYgKHIuaXNEaXNwb3NlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdmFyIGNoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgci50cmFjayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgdiA9IHVud3JhcHBlZEV4cHJlc3Npb24ocik7XG4gICAgICAgICAgICBjaGFuZ2VkID0gdmFsdWVEaWRDaGFuZ2UoY29tcGFyZVN0cnVjdHVyYWwsIG5leHRWYWx1ZSwgdik7XG4gICAgICAgICAgICBuZXh0VmFsdWUgPSB2O1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGZpcnN0VGltZSAmJiBmaXJlSW1tZWRpYXRlbHkpXG4gICAgICAgICAgICBlZmZlY3QobmV4dFZhbHVlLCByKTtcbiAgICAgICAgaWYgKCFmaXJzdFRpbWUgJiYgY2hhbmdlZCA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIGVmZmVjdChuZXh0VmFsdWUsIHIpO1xuICAgICAgICBpZiAoZmlyc3RUaW1lKVxuICAgICAgICAgICAgZmlyc3RUaW1lID0gZmFsc2U7XG4gICAgfVxuICAgIHIuc2NoZWR1bGUoKTtcbiAgICByZXR1cm4gci5nZXREaXNwb3NlcigpO1xufVxuZXhwb3J0cy5yZWFjdGlvbiA9IHJlYWN0aW9uO1xudmFyIGNvbXB1dGVkRGVjb3JhdG9yID0gY3JlYXRlQ2xhc3NQcm9wZXJ0eURlY29yYXRvcihmdW5jdGlvbiAodGFyZ2V0LCBuYW1lLCBfLCBkZWNvcmF0b3JBcmdzLCBvcmlnaW5hbERlc2NyaXB0b3IpIHtcbiAgICBpbnZhcmlhbnQodHlwZW9mIG9yaWdpbmFsRGVzY3JpcHRvciAhPT0gXCJ1bmRlZmluZWRcIiwgXCJAY29tcHV0ZWQgY2FuIG9ubHkgYmUgdXNlZCBvbiBnZXR0ZXIgZnVuY3Rpb25zLCBsaWtlOiAnQGNvbXB1dGVkIGdldCBteVByb3BzKCkgeyByZXR1cm4gLi4uOyB9Jy4gSXQgbG9va3MgbGlrZSBpdCB3YXMgdXNlZCBvbiBhIHByb3BlcnR5LlwiKTtcbiAgICB2YXIgYmFzZVZhbHVlID0gb3JpZ2luYWxEZXNjcmlwdG9yLmdldDtcbiAgICB2YXIgc2V0dGVyID0gb3JpZ2luYWxEZXNjcmlwdG9yLnNldDtcbiAgICBpbnZhcmlhbnQodHlwZW9mIGJhc2VWYWx1ZSA9PT0gXCJmdW5jdGlvblwiLCBcIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIG9uIGdldHRlciBmdW5jdGlvbnMsIGxpa2U6ICdAY29tcHV0ZWQgZ2V0IG15UHJvcHMoKSB7IHJldHVybiAuLi47IH0nXCIpO1xuICAgIHZhciBjb21wYXJlU3RydWN0dXJhbCA9IGZhbHNlO1xuICAgIGlmIChkZWNvcmF0b3JBcmdzICYmIGRlY29yYXRvckFyZ3MubGVuZ3RoID09PSAxICYmIGRlY29yYXRvckFyZ3NbMF0uYXNTdHJ1Y3R1cmUgPT09IHRydWUpXG4gICAgICAgIGNvbXBhcmVTdHJ1Y3R1cmFsID0gdHJ1ZTtcbiAgICB2YXIgYWRtID0gYXNPYnNlcnZhYmxlT2JqZWN0KHRhcmdldCwgdW5kZWZpbmVkLCBWYWx1ZU1vZGUuUmVjdXJzaXZlKTtcbiAgICBkZWZpbmVPYnNlcnZhYmxlUHJvcGVydHkoYWRtLCBuYW1lLCBjb21wYXJlU3RydWN0dXJhbCA/IGFzU3RydWN0dXJlKGJhc2VWYWx1ZSkgOiBiYXNlVmFsdWUsIGZhbHNlLCBzZXR0ZXIpO1xufSwgZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB2YXIgb2JzZXJ2YWJsZSA9IHRoaXMuJG1vYngudmFsdWVzW25hbWVdO1xuICAgIGlmIChvYnNlcnZhYmxlID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIG9ic2VydmFibGUuZ2V0KCk7XG59LCBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICB0aGlzLiRtb2J4LnZhbHVlc1tuYW1lXS5zZXQodmFsdWUpO1xufSwgZmFsc2UsIHRydWUpO1xuZnVuY3Rpb24gY29tcHV0ZWQodGFyZ2V0T3JFeHByLCBrZXlPclNjb3BlT3JTZXR0ZXIsIGJhc2VEZXNjcmlwdG9yLCBvcHRpb25zKSB7XG4gICAgaWYgKHR5cGVvZiB0YXJnZXRPckV4cHIgPT09IFwiZnVuY3Rpb25cIiAmJiBhcmd1bWVudHMubGVuZ3RoIDwgMykge1xuICAgICAgICBpZiAodHlwZW9mIGtleU9yU2NvcGVPclNldHRlciA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICAgICAgcmV0dXJuIGNvbXB1dGVkRXhwcih0YXJnZXRPckV4cHIsIGtleU9yU2NvcGVPclNldHRlciwgdW5kZWZpbmVkKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmV0dXJuIGNvbXB1dGVkRXhwcih0YXJnZXRPckV4cHIsIHVuZGVmaW5lZCwga2V5T3JTY29wZU9yU2V0dGVyKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXB1dGVkRGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG59XG5leHBvcnRzLmNvbXB1dGVkID0gY29tcHV0ZWQ7XG5mdW5jdGlvbiBjb21wdXRlZEV4cHIoZXhwciwgc2V0dGVyLCBzY29wZSkge1xuICAgIHZhciBfYSA9IGdldFZhbHVlTW9kZUZyb21WYWx1ZShleHByLCBWYWx1ZU1vZGUuUmVjdXJzaXZlKSwgbW9kZSA9IF9hWzBdLCB2YWx1ZSA9IF9hWzFdO1xuICAgIHJldHVybiBuZXcgQ29tcHV0ZWRWYWx1ZSh2YWx1ZSwgc2NvcGUsIG1vZGUgPT09IFZhbHVlTW9kZS5TdHJ1Y3R1cmUsIHZhbHVlLm5hbWUsIHNldHRlcik7XG59XG5mdW5jdGlvbiBjcmVhdGVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lciwgb25DbGVhbnVwKSB7XG4gICAgaW52YXJpYW50KHR5cGVvZiB0cmFuc2Zvcm1lciA9PT0gXCJmdW5jdGlvblwiICYmIHRyYW5zZm9ybWVyLmxlbmd0aCA9PT0gMSwgXCJjcmVhdGVUcmFuc2Zvcm1lciBleHBlY3RzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIG9uZSBhcmd1bWVudFwiKTtcbiAgICB2YXIgb2JqZWN0Q2FjaGUgPSB7fTtcbiAgICB2YXIgcmVzZXRJZCA9IGdsb2JhbFN0YXRlLnJlc2V0SWQ7XG4gICAgdmFyIFRyYW5zZm9ybWVyID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgX19leHRlbmRzKFRyYW5zZm9ybWVyLCBfc3VwZXIpO1xuICAgICAgICBmdW5jdGlvbiBUcmFuc2Zvcm1lcihzb3VyY2VJZGVudGlmaWVyLCBzb3VyY2VPYmplY3QpIHtcbiAgICAgICAgICAgIF9zdXBlci5jYWxsKHRoaXMsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRyYW5zZm9ybWVyKHNvdXJjZU9iamVjdCk7IH0sIG51bGwsIGZhbHNlLCBcIlRyYW5zZm9ybWVyLVwiICsgdHJhbnNmb3JtZXIubmFtZSArIFwiLVwiICsgc291cmNlSWRlbnRpZmllciwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIHRoaXMuc291cmNlSWRlbnRpZmllciA9IHNvdXJjZUlkZW50aWZpZXI7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZU9iamVjdCA9IHNvdXJjZU9iamVjdDtcbiAgICAgICAgfVxuICAgICAgICBUcmFuc2Zvcm1lci5wcm90b3R5cGUub25CZWNvbWVVbm9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGxhc3RWYWx1ZSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICBfc3VwZXIucHJvdG90eXBlLm9uQmVjb21lVW5vYnNlcnZlZC5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgZGVsZXRlIG9iamVjdENhY2hlW3RoaXMuc291cmNlSWRlbnRpZmllcl07XG4gICAgICAgICAgICBpZiAob25DbGVhbnVwKVxuICAgICAgICAgICAgICAgIG9uQ2xlYW51cChsYXN0VmFsdWUsIHRoaXMuc291cmNlT2JqZWN0KTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFRyYW5zZm9ybWVyO1xuICAgIH0oQ29tcHV0ZWRWYWx1ZSkpO1xuICAgIHJldHVybiBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgICAgIGlmIChyZXNldElkICE9PSBnbG9iYWxTdGF0ZS5yZXNldElkKSB7XG4gICAgICAgICAgICBvYmplY3RDYWNoZSA9IHt9O1xuICAgICAgICAgICAgcmVzZXRJZCA9IGdsb2JhbFN0YXRlLnJlc2V0SWQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGlkZW50aWZpZXIgPSBnZXRNZW1vaXphdGlvbklkKG9iamVjdCk7XG4gICAgICAgIHZhciByZWFjdGl2ZVRyYW5zZm9ybWVyID0gb2JqZWN0Q2FjaGVbaWRlbnRpZmllcl07XG4gICAgICAgIGlmIChyZWFjdGl2ZVRyYW5zZm9ybWVyKVxuICAgICAgICAgICAgcmV0dXJuIHJlYWN0aXZlVHJhbnNmb3JtZXIuZ2V0KCk7XG4gICAgICAgIHJlYWN0aXZlVHJhbnNmb3JtZXIgPSBvYmplY3RDYWNoZVtpZGVudGlmaWVyXSA9IG5ldyBUcmFuc2Zvcm1lcihpZGVudGlmaWVyLCBvYmplY3QpO1xuICAgICAgICByZXR1cm4gcmVhY3RpdmVUcmFuc2Zvcm1lci5nZXQoKTtcbiAgICB9O1xufVxuZXhwb3J0cy5jcmVhdGVUcmFuc2Zvcm1lciA9IGNyZWF0ZVRyYW5zZm9ybWVyO1xuZnVuY3Rpb24gZ2V0TWVtb2l6YXRpb25JZChvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0ID09PSBudWxsIHx8IHR5cGVvZiBvYmplY3QgIT09IFwib2JqZWN0XCIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4XSB0cmFuc2Zvcm0gZXhwZWN0ZWQgc29tZSBraW5kIG9mIG9iamVjdCwgZ290OiBcIiArIG9iamVjdCk7XG4gICAgdmFyIHRpZCA9IG9iamVjdC4kdHJhbnNmb3JtSWQ7XG4gICAgaWYgKHRpZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRpZCA9IGdldE5leHRJZCgpO1xuICAgICAgICBhZGRIaWRkZW5Qcm9wKG9iamVjdCwgXCIkdHJhbnNmb3JtSWRcIiwgdGlkKTtcbiAgICB9XG4gICAgcmV0dXJuIHRpZDtcbn1cbmZ1bmN0aW9uIGV4cHIoZXhwciwgc2NvcGUpIHtcbiAgICBpZiAoIWlzQ29tcHV0aW5nRGVyaXZhdGlvbigpKVxuICAgICAgICBjb25zb2xlLndhcm4oXCJbbW9ieC5leHByXSAnZXhwcicgc2hvdWxkIG9ubHkgYmUgdXNlZCBpbnNpZGUgb3RoZXIgcmVhY3RpdmUgZnVuY3Rpb25zLlwiKTtcbiAgICByZXR1cm4gY29tcHV0ZWQoZXhwciwgc2NvcGUpLmdldCgpO1xufVxuZXhwb3J0cy5leHByID0gZXhwcjtcbmZ1bmN0aW9uIGV4dGVuZE9ic2VydmFibGUodGFyZ2V0KSB7XG4gICAgdmFyIHByb3BlcnRpZXMgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDE7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICBwcm9wZXJ0aWVzW19pIC0gMV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICBpbnZhcmlhbnQoYXJndW1lbnRzLmxlbmd0aCA+PSAyLCBcImV4dGVuZE9ic2VydmFibGUgZXhwZWN0ZWQgMiBvciBtb3JlIGFyZ3VtZW50c1wiKTtcbiAgICBpbnZhcmlhbnQodHlwZW9mIHRhcmdldCA9PT0gXCJvYmplY3RcIiwgXCJleHRlbmRPYnNlcnZhYmxlIGV4cGVjdHMgYW4gb2JqZWN0IGFzIGZpcnN0IGFyZ3VtZW50XCIpO1xuICAgIGludmFyaWFudCghKHRhcmdldCBpbnN0YW5jZW9mIE9ic2VydmFibGVNYXApLCBcImV4dGVuZE9ic2VydmFibGUgc2hvdWxkIG5vdCBiZSB1c2VkIG9uIG1hcHMsIHVzZSBtYXAubWVyZ2UgaW5zdGVhZFwiKTtcbiAgICBwcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKHByb3BTZXQpIHtcbiAgICAgICAgaW52YXJpYW50KHR5cGVvZiBwcm9wU2V0ID09PSBcIm9iamVjdFwiLCBcImFsbCBhcmd1bWVudHMgb2YgZXh0ZW5kT2JzZXJ2YWJsZSBzaG91bGQgYmUgb2JqZWN0c1wiKTtcbiAgICAgICAgZXh0ZW5kT2JzZXJ2YWJsZUhlbHBlcih0YXJnZXQsIHByb3BTZXQsIFZhbHVlTW9kZS5SZWN1cnNpdmUsIG51bGwpO1xuICAgIH0pO1xuICAgIHJldHVybiB0YXJnZXQ7XG59XG5leHBvcnRzLmV4dGVuZE9ic2VydmFibGUgPSBleHRlbmRPYnNlcnZhYmxlO1xuZnVuY3Rpb24gZXh0ZW5kT2JzZXJ2YWJsZUhlbHBlcih0YXJnZXQsIHByb3BlcnRpZXMsIG1vZGUsIG5hbWUpIHtcbiAgICB2YXIgYWRtID0gYXNPYnNlcnZhYmxlT2JqZWN0KHRhcmdldCwgbmFtZSwgbW9kZSk7XG4gICAgZm9yICh2YXIga2V5IGluIHByb3BlcnRpZXMpXG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eShwcm9wZXJ0aWVzLCBrZXkpKSB7XG4gICAgICAgICAgICBpZiAodGFyZ2V0ID09PSBwcm9wZXJ0aWVzICYmICFpc1Byb3BlcnR5Q29uZmlndXJhYmxlKHRhcmdldCwga2V5KSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHNldE9ic2VydmFibGVPYmplY3RJbnN0YW5jZVByb3BlcnR5KGFkbSwga2V5LCBwcm9wZXJ0aWVzW2tleV0pO1xuICAgICAgICB9XG4gICAgcmV0dXJuIHRhcmdldDtcbn1cbmZ1bmN0aW9uIGdldERlcGVuZGVuY3lUcmVlKHRoaW5nLCBwcm9wZXJ0eSkge1xuICAgIHJldHVybiBub2RlVG9EZXBlbmRlbmN5VHJlZShnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSkpO1xufVxuZnVuY3Rpb24gbm9kZVRvRGVwZW5kZW5jeVRyZWUobm9kZSkge1xuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6IG5vZGUubmFtZVxuICAgIH07XG4gICAgaWYgKG5vZGUub2JzZXJ2aW5nICYmIG5vZGUub2JzZXJ2aW5nLmxlbmd0aCA+IDApXG4gICAgICAgIHJlc3VsdC5kZXBlbmRlbmNpZXMgPSB1bmlxdWUobm9kZS5vYnNlcnZpbmcpLm1hcChub2RlVG9EZXBlbmRlbmN5VHJlZSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGdldE9ic2VydmVyVHJlZSh0aGluZywgcHJvcGVydHkpIHtcbiAgICByZXR1cm4gbm9kZVRvT2JzZXJ2ZXJUcmVlKGdldEF0b20odGhpbmcsIHByb3BlcnR5KSk7XG59XG5mdW5jdGlvbiBub2RlVG9PYnNlcnZlclRyZWUobm9kZSkge1xuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICAgIG5hbWU6IG5vZGUubmFtZVxuICAgIH07XG4gICAgaWYgKGhhc09ic2VydmVycyhub2RlKSlcbiAgICAgICAgcmVzdWx0Lm9ic2VydmVycyA9IGdldE9ic2VydmVycyhub2RlKS5tYXAobm9kZVRvT2JzZXJ2ZXJUcmVlKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gaW50ZXJjZXB0KHRoaW5nLCBwcm9wT3JIYW5kbGVyLCBoYW5kbGVyKSB7XG4gICAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHJldHVybiBpbnRlcmNlcHRQcm9wZXJ0eSh0aGluZywgcHJvcE9ySGFuZGxlciwgaGFuZGxlcik7XG4gICAgZWxzZVxuICAgICAgICByZXR1cm4gaW50ZXJjZXB0SW50ZXJjZXB0YWJsZSh0aGluZywgcHJvcE9ySGFuZGxlcik7XG59XG5leHBvcnRzLmludGVyY2VwdCA9IGludGVyY2VwdDtcbmZ1bmN0aW9uIGludGVyY2VwdEludGVyY2VwdGFibGUodGhpbmcsIGhhbmRsZXIpIHtcbiAgICBpZiAoaXNQbGFpbk9iamVjdCh0aGluZykgJiYgIWlzT2JzZXJ2YWJsZU9iamVjdCh0aGluZykpIHtcbiAgICAgICAgZGVwcmVjYXRlZChcIlBhc3NpbmcgcGxhaW4gb2JqZWN0cyB0byBpbnRlcmNlcHQgLyBvYnNlcnZlIGlzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiAzLjBcIik7XG4gICAgICAgIHJldHVybiBnZXRBZG1pbmlzdHJhdGlvbihvYnNlcnZhYmxlKHRoaW5nKSkuaW50ZXJjZXB0KGhhbmRsZXIpO1xuICAgIH1cbiAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24odGhpbmcpLmludGVyY2VwdChoYW5kbGVyKTtcbn1cbmZ1bmN0aW9uIGludGVyY2VwdFByb3BlcnR5KHRoaW5nLCBwcm9wZXJ0eSwgaGFuZGxlcikge1xuICAgIGlmIChpc1BsYWluT2JqZWN0KHRoaW5nKSAmJiAhaXNPYnNlcnZhYmxlT2JqZWN0KHRoaW5nKSkge1xuICAgICAgICBkZXByZWNhdGVkKFwiUGFzc2luZyBwbGFpbiBvYmplY3RzIHRvIGludGVyY2VwdCAvIG9ic2VydmUgaXMgZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIDMuMFwiKTtcbiAgICAgICAgZXh0ZW5kT2JzZXJ2YWJsZSh0aGluZywge1xuICAgICAgICAgICAgcHJvcGVydHk6IHRoaW5nW3Byb3BlcnR5XVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGludGVyY2VwdFByb3BlcnR5KHRoaW5nLCBwcm9wZXJ0eSwgaGFuZGxlcik7XG4gICAgfVxuICAgIHJldHVybiBnZXRBZG1pbmlzdHJhdGlvbih0aGluZywgcHJvcGVydHkpLmludGVyY2VwdChoYW5kbGVyKTtcbn1cbmZ1bmN0aW9uIGlzT2JzZXJ2YWJsZSh2YWx1ZSwgcHJvcGVydHkpIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChwcm9wZXJ0eSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE9ic2VydmFibGVNYXAgfHwgdmFsdWUgaW5zdGFuY2VvZiBPYnNlcnZhYmxlQXJyYXkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieC5pc09ic2VydmFibGVdIGlzT2JzZXJ2YWJsZShvYmplY3QsIHByb3BlcnR5TmFtZSkgaXMgbm90IHN1cHBvcnRlZCBmb3IgYXJyYXlzIGFuZCBtYXBzLiBVc2UgbWFwLmhhcyBvciBhcnJheS5sZW5ndGggaW5zdGVhZC5cIik7XG4gICAgICAgIGVsc2UgaWYgKGlzT2JzZXJ2YWJsZU9iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHZhciBvID0gdmFsdWUuJG1vYng7XG4gICAgICAgICAgICByZXR1cm4gby52YWx1ZXMgJiYgISFvLnZhbHVlc1twcm9wZXJ0eV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gISF2YWx1ZS4kbW9ieCB8fCB2YWx1ZSBpbnN0YW5jZW9mIEJhc2VBdG9tIHx8IHZhbHVlIGluc3RhbmNlb2YgUmVhY3Rpb24gfHwgdmFsdWUgaW5zdGFuY2VvZiBDb21wdXRlZFZhbHVlO1xufVxuZXhwb3J0cy5pc09ic2VydmFibGUgPSBpc09ic2VydmFibGU7XG52YXIgZGVjb3JhdG9ySW1wbCA9IGNyZWF0ZUNsYXNzUHJvcGVydHlEZWNvcmF0b3IoZnVuY3Rpb24gKHRhcmdldCwgbmFtZSwgYmFzZVZhbHVlKSB7XG4gICAgdmFyIHByZXZBID0gYWxsb3dTdGF0ZUNoYW5nZXNTdGFydCh0cnVlKTtcbiAgICBpZiAodHlwZW9mIGJhc2VWYWx1ZSA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICBiYXNlVmFsdWUgPSBhc1JlZmVyZW5jZShiYXNlVmFsdWUpO1xuICAgIHZhciBhZG0gPSBhc09ic2VydmFibGVPYmplY3QodGFyZ2V0LCB1bmRlZmluZWQsIFZhbHVlTW9kZS5SZWN1cnNpdmUpO1xuICAgIGRlZmluZU9ic2VydmFibGVQcm9wZXJ0eShhZG0sIG5hbWUsIGJhc2VWYWx1ZSwgdHJ1ZSwgdW5kZWZpbmVkKTtcbiAgICBhbGxvd1N0YXRlQ2hhbmdlc0VuZChwcmV2QSk7XG59LCBmdW5jdGlvbiAobmFtZSkge1xuICAgIHZhciBvYnNlcnZhYmxlID0gdGhpcy4kbW9ieC52YWx1ZXNbbmFtZV07XG4gICAgaWYgKG9ic2VydmFibGUgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5nZXQoKTtcbn0sIGZ1bmN0aW9uIChuYW1lLCB2YWx1ZSkge1xuICAgIHNldFByb3BlcnR5VmFsdWUodGhpcywgbmFtZSwgdmFsdWUpO1xufSwgdHJ1ZSwgZmFsc2UpO1xuZnVuY3Rpb24gb2JzZXJ2YWJsZURlY29yYXRvcih0YXJnZXQsIGtleSwgYmFzZURlc2NyaXB0b3IpIHtcbiAgICBpbnZhcmlhbnQoYXJndW1lbnRzLmxlbmd0aCA+PSAyICYmIGFyZ3VtZW50cy5sZW5ndGggPD0gMywgXCJJbGxlZ2FsIGRlY29yYXRvciBjb25maWdcIiwga2V5KTtcbiAgICBhc3NlcnRQcm9wZXJ0eUNvbmZpZ3VyYWJsZSh0YXJnZXQsIGtleSk7XG4gICAgaW52YXJpYW50KCFiYXNlRGVzY3JpcHRvciB8fCAhYmFzZURlc2NyaXB0b3IuZ2V0LCBcIkBvYnNlcnZhYmxlIGNhbiBub3QgYmUgdXNlZCBvbiBnZXR0ZXJzLCB1c2UgQGNvbXB1dGVkIGluc3RlYWRcIik7XG4gICAgcmV0dXJuIGRlY29yYXRvckltcGwuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIG9ic2VydmFibGUodiwga2V5T3JTY29wZSkge1xuICAgIGlmICh2ID09PSB2b2lkIDApIHsgdiA9IHVuZGVmaW5lZDsgfVxuICAgIGlmICh0eXBlb2YgYXJndW1lbnRzWzFdID09PSBcInN0cmluZ1wiKVxuICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZURlY29yYXRvci5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgIGludmFyaWFudChhcmd1bWVudHMubGVuZ3RoIDwgMywgXCJvYnNlcnZhYmxlIGV4cGVjdHMgemVybywgb25lIG9yIHR3byBhcmd1bWVudHNcIik7XG4gICAgaWYgKGlzT2JzZXJ2YWJsZSh2KSlcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgdmFyIF9hID0gZ2V0VmFsdWVNb2RlRnJvbVZhbHVlKHYsIFZhbHVlTW9kZS5SZWN1cnNpdmUpLCBtb2RlID0gX2FbMF0sIHZhbHVlID0gX2FbMV07XG4gICAgdmFyIHNvdXJjZVR5cGUgPSBtb2RlID09PSBWYWx1ZU1vZGUuUmVmZXJlbmNlID8gVmFsdWVUeXBlLlJlZmVyZW5jZSA6IGdldFR5cGVPZlZhbHVlKHZhbHVlKTtcbiAgICBzd2l0Y2ggKHNvdXJjZVR5cGUpIHtcbiAgICAgICAgY2FzZSBWYWx1ZVR5cGUuQXJyYXk6XG4gICAgICAgIGNhc2UgVmFsdWVUeXBlLlBsYWluT2JqZWN0OlxuICAgICAgICAgICAgcmV0dXJuIG1ha2VDaGlsZE9ic2VydmFibGUodmFsdWUsIG1vZGUpO1xuICAgICAgICBjYXNlIFZhbHVlVHlwZS5SZWZlcmVuY2U6XG4gICAgICAgIGNhc2UgVmFsdWVUeXBlLkNvbXBsZXhPYmplY3Q6XG4gICAgICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGVWYWx1ZSh2YWx1ZSwgbW9kZSk7XG4gICAgICAgIGNhc2UgVmFsdWVUeXBlLkNvbXBsZXhGdW5jdGlvbjpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4Lm9ic2VydmFibGVdIFRvIGJlIGFibGUgdG8gbWFrZSBhIGZ1bmN0aW9uIHJlYWN0aXZlIGl0IHNob3VsZCBub3QgaGF2ZSBhcmd1bWVudHMuIElmIHlvdSBuZWVkIGFuIG9ic2VydmFibGUgcmVmZXJlbmNlIHRvIGEgZnVuY3Rpb24sIHVzZSBgb2JzZXJ2YWJsZShhc1JlZmVyZW5jZShmKSlgXCIpO1xuICAgICAgICBjYXNlIFZhbHVlVHlwZS5WaWV3RnVuY3Rpb246XG4gICAgICAgICAgICBkZXByZWNhdGVkKFwiVXNlIGBjb21wdXRlZChleHByKWAgaW5zdGVhZCBvZiBgb2JzZXJ2YWJsZShleHByKWBcIik7XG4gICAgICAgICAgICByZXR1cm4gY29tcHV0ZWQodiwga2V5T3JTY29wZSk7XG4gICAgfVxuICAgIGludmFyaWFudChmYWxzZSwgXCJJbGxlZ2FsIFN0YXRlXCIpO1xufVxuZXhwb3J0cy5vYnNlcnZhYmxlID0gb2JzZXJ2YWJsZTtcbnZhciBWYWx1ZVR5cGU7XG4oZnVuY3Rpb24gKFZhbHVlVHlwZSkge1xuICAgIFZhbHVlVHlwZVtWYWx1ZVR5cGVbXCJSZWZlcmVuY2VcIl0gPSAwXSA9IFwiUmVmZXJlbmNlXCI7XG4gICAgVmFsdWVUeXBlW1ZhbHVlVHlwZVtcIlBsYWluT2JqZWN0XCJdID0gMV0gPSBcIlBsYWluT2JqZWN0XCI7XG4gICAgVmFsdWVUeXBlW1ZhbHVlVHlwZVtcIkNvbXBsZXhPYmplY3RcIl0gPSAyXSA9IFwiQ29tcGxleE9iamVjdFwiO1xuICAgIFZhbHVlVHlwZVtWYWx1ZVR5cGVbXCJBcnJheVwiXSA9IDNdID0gXCJBcnJheVwiO1xuICAgIFZhbHVlVHlwZVtWYWx1ZVR5cGVbXCJWaWV3RnVuY3Rpb25cIl0gPSA0XSA9IFwiVmlld0Z1bmN0aW9uXCI7XG4gICAgVmFsdWVUeXBlW1ZhbHVlVHlwZVtcIkNvbXBsZXhGdW5jdGlvblwiXSA9IDVdID0gXCJDb21wbGV4RnVuY3Rpb25cIjtcbn0pKFZhbHVlVHlwZSB8fCAoVmFsdWVUeXBlID0ge30pKTtcbmZ1bmN0aW9uIGdldFR5cGVPZlZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiBWYWx1ZVR5cGUuUmVmZXJlbmNlO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgcmV0dXJuIHZhbHVlLmxlbmd0aCA/IFZhbHVlVHlwZS5Db21wbGV4RnVuY3Rpb24gOiBWYWx1ZVR5cGUuVmlld0Z1bmN0aW9uO1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSB8fCB2YWx1ZSBpbnN0YW5jZW9mIE9ic2VydmFibGVBcnJheSlcbiAgICAgICAgcmV0dXJuIFZhbHVlVHlwZS5BcnJheTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiKVxuICAgICAgICByZXR1cm4gaXNQbGFpbk9iamVjdCh2YWx1ZSkgPyBWYWx1ZVR5cGUuUGxhaW5PYmplY3QgOiBWYWx1ZVR5cGUuQ29tcGxleE9iamVjdDtcbiAgICByZXR1cm4gVmFsdWVUeXBlLlJlZmVyZW5jZTtcbn1cbmZ1bmN0aW9uIG9ic2VydmUodGhpbmcsIHByb3BPckNiLCBjYk9yRmlyZSwgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgaWYgKHR5cGVvZiBjYk9yRmlyZSA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICByZXR1cm4gb2JzZXJ2ZU9ic2VydmFibGVQcm9wZXJ0eSh0aGluZywgcHJvcE9yQ2IsIGNiT3JGaXJlLCBmaXJlSW1tZWRpYXRlbHkpO1xuICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIG9ic2VydmVPYnNlcnZhYmxlKHRoaW5nLCBwcm9wT3JDYiwgY2JPckZpcmUpO1xufVxuZXhwb3J0cy5vYnNlcnZlID0gb2JzZXJ2ZTtcbmZ1bmN0aW9uIG9ic2VydmVPYnNlcnZhYmxlKHRoaW5nLCBsaXN0ZW5lciwgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgaWYgKGlzUGxhaW5PYmplY3QodGhpbmcpICYmICFpc09ic2VydmFibGVPYmplY3QodGhpbmcpKSB7XG4gICAgICAgIGRlcHJlY2F0ZWQoXCJQYXNzaW5nIHBsYWluIG9iamVjdHMgdG8gaW50ZXJjZXB0IC8gb2JzZXJ2ZSBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gMy4wXCIpO1xuICAgICAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24ob2JzZXJ2YWJsZSh0aGluZykpLm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG4gICAgfVxuICAgIHJldHVybiBnZXRBZG1pbmlzdHJhdGlvbih0aGluZykub2JzZXJ2ZShsaXN0ZW5lciwgZmlyZUltbWVkaWF0ZWx5KTtcbn1cbmZ1bmN0aW9uIG9ic2VydmVPYnNlcnZhYmxlUHJvcGVydHkodGhpbmcsIHByb3BlcnR5LCBsaXN0ZW5lciwgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgaWYgKGlzUGxhaW5PYmplY3QodGhpbmcpICYmICFpc09ic2VydmFibGVPYmplY3QodGhpbmcpKSB7XG4gICAgICAgIGRlcHJlY2F0ZWQoXCJQYXNzaW5nIHBsYWluIG9iamVjdHMgdG8gaW50ZXJjZXB0IC8gb2JzZXJ2ZSBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gMy4wXCIpO1xuICAgICAgICBleHRlbmRPYnNlcnZhYmxlKHRoaW5nLCB7XG4gICAgICAgICAgICBwcm9wZXJ0eTogdGhpbmdbcHJvcGVydHldXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gb2JzZXJ2ZU9ic2VydmFibGVQcm9wZXJ0eSh0aGluZywgcHJvcGVydHksIGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpO1xuICAgIH1cbiAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24odGhpbmcsIHByb3BlcnR5KS5vYnNlcnZlKGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpO1xufVxuZnVuY3Rpb24gdG9KUyhzb3VyY2UsIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbikge1xuICAgIGlmIChkZXRlY3RDeWNsZXMgPT09IHZvaWQgMCkgeyBkZXRlY3RDeWNsZXMgPSB0cnVlOyB9XG4gICAgaWYgKF9fYWxyZWFkeVNlZW4gPT09IHZvaWQgMCkgeyBfX2FscmVhZHlTZWVuID0gbnVsbDsgfVxuICAgIGZ1bmN0aW9uIGNhY2hlKHZhbHVlKSB7XG4gICAgICAgIGlmIChkZXRlY3RDeWNsZXMpXG4gICAgICAgICAgICBfX2FscmVhZHlTZWVuLnB1c2goW3NvdXJjZSwgdmFsdWVdKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAoc291cmNlIGluc3RhbmNlb2YgRGF0ZSB8fCBzb3VyY2UgaW5zdGFuY2VvZiBSZWdFeHApXG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgaWYgKGRldGVjdEN5Y2xlcyAmJiBfX2FscmVhZHlTZWVuID09PSBudWxsKVxuICAgICAgICBfX2FscmVhZHlTZWVuID0gW107XG4gICAgaWYgKGRldGVjdEN5Y2xlcyAmJiBzb3VyY2UgIT09IG51bGwgJiYgdHlwZW9mIHNvdXJjZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IF9fYWxyZWFkeVNlZW4ubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgaWYgKF9fYWxyZWFkeVNlZW5baV1bMF0gPT09IHNvdXJjZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gX19hbHJlYWR5U2VlbltpXVsxXTtcbiAgICB9XG4gICAgaWYgKCFzb3VyY2UpXG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoc291cmNlKSB8fCBzb3VyY2UgaW5zdGFuY2VvZiBPYnNlcnZhYmxlQXJyYXkpIHtcbiAgICAgICAgdmFyIHJlcyA9IGNhY2hlKFtdKTtcbiAgICAgICAgdmFyIHRvQWRkID0gc291cmNlLm1hcChmdW5jdGlvbiAodmFsdWUpIHsgcmV0dXJuIHRvSlModmFsdWUsIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7IH0pO1xuICAgICAgICByZXMubGVuZ3RoID0gdG9BZGQubGVuZ3RoO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRvQWRkLmxlbmd0aDsgaSA8IGw7IGkrKylcbiAgICAgICAgICAgIHJlc1tpXSA9IHRvQWRkW2ldO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgICBpZiAoc291cmNlIGluc3RhbmNlb2YgT2JzZXJ2YWJsZU1hcCkge1xuICAgICAgICB2YXIgcmVzXzEgPSBjYWNoZSh7fSk7XG4gICAgICAgIHNvdXJjZS5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7IHJldHVybiByZXNfMVtrZXldID0gdG9KUyh2YWx1ZSwgZGV0ZWN0Q3ljbGVzLCBfX2FscmVhZHlTZWVuKTsgfSk7XG4gICAgICAgIHJldHVybiByZXNfMTtcbiAgICB9XG4gICAgaWYgKGlzT2JzZXJ2YWJsZShzb3VyY2UpICYmIHNvdXJjZS4kbW9ieCBpbnN0YW5jZW9mIE9ic2VydmFibGVWYWx1ZSlcbiAgICAgICAgcmV0dXJuIHRvSlMoc291cmNlKCksIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7XG4gICAgaWYgKHNvdXJjZSBpbnN0YW5jZW9mIE9ic2VydmFibGVWYWx1ZSlcbiAgICAgICAgcmV0dXJuIHRvSlMoc291cmNlLmdldCgpLCBkZXRlY3RDeWNsZXMsIF9fYWxyZWFkeVNlZW4pO1xuICAgIGlmICh0eXBlb2Ygc291cmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciByZXMgPSBjYWNoZSh7fSk7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBzb3VyY2UpXG4gICAgICAgICAgICByZXNba2V5XSA9IHRvSlMoc291cmNlW2tleV0sIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICAgIHJldHVybiBzb3VyY2U7XG59XG5leHBvcnRzLnRvSlMgPSB0b0pTO1xuZnVuY3Rpb24gdG9KU09OKHNvdXJjZSwgZGV0ZWN0Q3ljbGVzLCBfX2FscmVhZHlTZWVuKSB7XG4gICAgaWYgKGRldGVjdEN5Y2xlcyA9PT0gdm9pZCAwKSB7IGRldGVjdEN5Y2xlcyA9IHRydWU7IH1cbiAgICBpZiAoX19hbHJlYWR5U2VlbiA9PT0gdm9pZCAwKSB7IF9fYWxyZWFkeVNlZW4gPSBudWxsOyB9XG4gICAgZGVwcmVjYXRlZChcInRvSlNPTiBpcyBkZXByZWNhdGVkLiBVc2UgdG9KUyBpbnN0ZWFkXCIpO1xuICAgIHJldHVybiB0b0pTLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG59XG5leHBvcnRzLnRvSlNPTiA9IHRvSlNPTjtcbmZ1bmN0aW9uIGxvZyhtc2cpIHtcbiAgICBjb25zb2xlLmxvZyhtc2cpO1xuICAgIHJldHVybiBtc2c7XG59XG5mdW5jdGlvbiB3aHlSdW4odGhpbmcsIHByb3ApIHtcbiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgdGhpbmcgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgICAgICAgICBpZiAoIXRoaW5nKVxuICAgICAgICAgICAgICAgIHJldHVybiBsb2coXCJ3aHlSdW4oKSBjYW4gb25seSBiZSB1c2VkIGlmIGEgZGVyaXZhdGlvbiBpcyBhY3RpdmUsIG9yIGJ5IHBhc3NpbmcgYW4gY29tcHV0ZWQgdmFsdWUgLyByZWFjdGlvbiBleHBsaWNpdGx5LiBJZiB5b3UgaW52b2tlZCB3aHlSdW4gZnJvbSBpbnNpZGUgYSBjb21wdXRhdGlvbjsgdGhlIGNvbXB1dGF0aW9uIGlzIGN1cnJlbnRseSBzdXNwZW5kZWQgYnV0IHJlLWV2YWx1YXRpbmcgYmVjYXVzZSBzb21lYm9keSByZXF1ZXN0ZWQgaXQncyB2YWx1ZS5cIik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgdGhpbmcgPSBnZXRBdG9tKHRoaW5nLCBwcm9wKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICB0aGluZyA9IGdldEF0b20odGhpbmcpO1xuICAgIGlmICh0aGluZyBpbnN0YW5jZW9mIENvbXB1dGVkVmFsdWUpXG4gICAgICAgIHJldHVybiBsb2codGhpbmcud2h5UnVuKCkpO1xuICAgIGVsc2UgaWYgKHRoaW5nIGluc3RhbmNlb2YgUmVhY3Rpb24pXG4gICAgICAgIHJldHVybiBsb2codGhpbmcud2h5UnVuKCkpO1xuICAgIGVsc2VcbiAgICAgICAgaW52YXJpYW50KGZhbHNlLCBcIndoeVJ1biBjYW4gb25seSBiZSB1c2VkIG9uIHJlYWN0aW9ucyBhbmQgY29tcHV0ZWQgdmFsdWVzXCIpO1xufVxuZXhwb3J0cy53aHlSdW4gPSB3aHlSdW47XG5mdW5jdGlvbiBjcmVhdGVBY3Rpb24oYWN0aW9uTmFtZSwgZm4pIHtcbiAgICBpbnZhcmlhbnQodHlwZW9mIGZuID09PSBcImZ1bmN0aW9uXCIsIFwiYGFjdGlvbmAgY2FuIG9ubHkgYmUgaW52b2tlZCBvbiBmdW5jdGlvbnNcIik7XG4gICAgaW52YXJpYW50KHR5cGVvZiBhY3Rpb25OYW1lID09PSBcInN0cmluZ1wiICYmIGFjdGlvbk5hbWUubGVuZ3RoID4gMCwgXCJhY3Rpb25zIHNob3VsZCBoYXZlIHZhbGlkIG5hbWVzLCBnb3Q6ICdcIiArIGFjdGlvbk5hbWUgKyBcIidcIik7XG4gICAgdmFyIHJlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgICByZXMuaXNNb2J4QWN0aW9uID0gdHJ1ZTtcbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gZXhlY3V0ZUFjdGlvbihhY3Rpb25OYW1lLCBmbiwgc2NvcGUsIGFyZ3MpIHtcbiAgICBpbnZhcmlhbnQoIShnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb24gaW5zdGFuY2VvZiBDb21wdXRlZFZhbHVlKSwgXCJDb21wdXRlZCB2YWx1ZXMgb3IgdHJhbnNmb3JtZXJzIHNob3VsZCBub3QgaW52b2tlIGFjdGlvbnMgb3IgdHJpZ2dlciBvdGhlciBzaWRlIGVmZmVjdHNcIik7XG4gICAgdmFyIG5vdGlmeVNweSA9IGlzU3B5RW5hYmxlZCgpO1xuICAgIHZhciBzdGFydFRpbWU7XG4gICAgaWYgKG5vdGlmeVNweSkge1xuICAgICAgICBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB2YXIgbCA9IChhcmdzICYmIGFyZ3MubGVuZ3RoKSB8fCAwO1xuICAgICAgICB2YXIgZmxhdHRlbmRBcmdzID0gbmV3IEFycmF5KGwpO1xuICAgICAgICBpZiAobCA+IDApXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKylcbiAgICAgICAgICAgICAgICBmbGF0dGVuZEFyZ3NbaV0gPSBhcmdzW2ldO1xuICAgICAgICBzcHlSZXBvcnRTdGFydCh7XG4gICAgICAgICAgICB0eXBlOiBcImFjdGlvblwiLFxuICAgICAgICAgICAgbmFtZTogYWN0aW9uTmFtZSxcbiAgICAgICAgICAgIGZuOiBmbixcbiAgICAgICAgICAgIHRhcmdldDogc2NvcGUsXG4gICAgICAgICAgICBhcmd1bWVudHM6IGZsYXR0ZW5kQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgdmFyIHByZXZVbnRyYWNrZWQgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgIHRyYW5zYWN0aW9uU3RhcnQoYWN0aW9uTmFtZSwgc2NvcGUsIGZhbHNlKTtcbiAgICB2YXIgcHJldkFsbG93U3RhdGVDaGFuZ2VzID0gYWxsb3dTdGF0ZUNoYW5nZXNTdGFydCh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gZm4uYXBwbHkoc2NvcGUsIGFyZ3MpO1xuICAgIH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgYWxsb3dTdGF0ZUNoYW5nZXNFbmQocHJldkFsbG93U3RhdGVDaGFuZ2VzKTtcbiAgICAgICAgdHJhbnNhY3Rpb25FbmQoZmFsc2UpO1xuICAgICAgICB1bnRyYWNrZWRFbmQocHJldlVudHJhY2tlZCk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoeyB0aW1lOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lIH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHVzZVN0cmljdChzdHJpY3QpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBkZXByZWNhdGVkKFwiYHVzZVN0cmljdGAgd2l0aG91dCBhcmd1bWVudHMgaXMgZGVwcmVjYXRlZCwgdXNlIGBpc1N0cmljdE1vZGVFbmFibGVkKClgIGluc3RlYWRcIik7XG4gICAgICAgIHJldHVybiBnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaW52YXJpYW50KGdsb2JhbFN0YXRlLnRyYWNraW5nRGVyaXZhdGlvbiA9PT0gbnVsbCwgXCJJdCBpcyBub3QgYWxsb3dlZCB0byBzZXQgYHVzZVN0cmljdGAgd2hlbiBhIGRlcml2YXRpb24gaXMgcnVubmluZ1wiKTtcbiAgICAgICAgZ2xvYmFsU3RhdGUuc3RyaWN0TW9kZSA9IHN0cmljdDtcbiAgICAgICAgZ2xvYmFsU3RhdGUuYWxsb3dTdGF0ZUNoYW5nZXMgPSAhc3RyaWN0O1xuICAgIH1cbn1cbmV4cG9ydHMudXNlU3RyaWN0ID0gdXNlU3RyaWN0O1xuZnVuY3Rpb24gaXNTdHJpY3RNb2RlRW5hYmxlZCgpIHtcbiAgICByZXR1cm4gZ2xvYmFsU3RhdGUuc3RyaWN0TW9kZTtcbn1cbmV4cG9ydHMuaXNTdHJpY3RNb2RlRW5hYmxlZCA9IGlzU3RyaWN0TW9kZUVuYWJsZWQ7XG5mdW5jdGlvbiBhbGxvd1N0YXRlQ2hhbmdlcyhhbGxvd1N0YXRlQ2hhbmdlcywgZnVuYykge1xuICAgIHZhciBwcmV2ID0gYWxsb3dTdGF0ZUNoYW5nZXNTdGFydChhbGxvd1N0YXRlQ2hhbmdlcyk7XG4gICAgdmFyIHJlcyA9IGZ1bmMoKTtcbiAgICBhbGxvd1N0YXRlQ2hhbmdlc0VuZChwcmV2KTtcbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gYWxsb3dTdGF0ZUNoYW5nZXNTdGFydChhbGxvd1N0YXRlQ2hhbmdlcykge1xuICAgIHZhciBwcmV2ID0gZ2xvYmFsU3RhdGUuYWxsb3dTdGF0ZUNoYW5nZXM7XG4gICAgZ2xvYmFsU3RhdGUuYWxsb3dTdGF0ZUNoYW5nZXMgPSBhbGxvd1N0YXRlQ2hhbmdlcztcbiAgICByZXR1cm4gcHJldjtcbn1cbmZ1bmN0aW9uIGFsbG93U3RhdGVDaGFuZ2VzRW5kKHByZXYpIHtcbiAgICBnbG9iYWxTdGF0ZS5hbGxvd1N0YXRlQ2hhbmdlcyA9IHByZXY7XG59XG52YXIgQmFzZUF0b20gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEJhc2VBdG9tKG5hbWUpIHtcbiAgICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgeyBuYW1lID0gXCJBdG9tQFwiICsgZ2V0TmV4dElkKCk7IH1cbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5pc1BlbmRpbmdVbm9ic2VydmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnNJbmRleGVzID0ge307XG4gICAgICAgIHRoaXMuZGlmZlZhbHVlID0gMDtcbiAgICAgICAgdGhpcy5sYXN0QWNjZXNzZWRCeSA9IDA7XG4gICAgICAgIHRoaXMubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HO1xuICAgIH1cbiAgICBCYXNlQXRvbS5wcm90b3R5cGUub25CZWNvbWVVbm9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgQmFzZUF0b20ucHJvdG90eXBlLnJlcG9ydE9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXBvcnRPYnNlcnZlZCh0aGlzKTtcbiAgICB9O1xuICAgIEJhc2VBdG9tLnByb3RvdHlwZS5yZXBvcnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0cmFuc2FjdGlvblN0YXJ0KFwicHJvcGFnYXRpbmdBdG9tQ2hhbmdlXCIsIG51bGwsIGZhbHNlKTtcbiAgICAgICAgcHJvcGFnYXRlQ2hhbmdlZCh0aGlzKTtcbiAgICAgICAgdHJhbnNhY3Rpb25FbmQoZmFsc2UpO1xuICAgIH07XG4gICAgQmFzZUF0b20ucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lO1xuICAgIH07XG4gICAgcmV0dXJuIEJhc2VBdG9tO1xufSgpKTtcbmV4cG9ydHMuQmFzZUF0b20gPSBCYXNlQXRvbTtcbnZhciBBdG9tID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQXRvbSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBdG9tKG5hbWUsIG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyLCBvbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiQXRvbUBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIGlmIChvbkJlY29tZU9ic2VydmVkSGFuZGxlciA9PT0gdm9pZCAwKSB7IG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyID0gbm9vcDsgfVxuICAgICAgICBpZiAob25CZWNvbWVVbm9ic2VydmVkSGFuZGxlciA9PT0gdm9pZCAwKSB7IG9uQmVjb21lVW5vYnNlcnZlZEhhbmRsZXIgPSBub29wOyB9XG4gICAgICAgIF9zdXBlci5jYWxsKHRoaXMsIG5hbWUpO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyID0gb25CZWNvbWVPYnNlcnZlZEhhbmRsZXI7XG4gICAgICAgIHRoaXMub25CZWNvbWVVbm9ic2VydmVkSGFuZGxlciA9IG9uQmVjb21lVW5vYnNlcnZlZEhhbmRsZXI7XG4gICAgICAgIHRoaXMuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzQmVpbmdUcmFja2VkID0gZmFsc2U7XG4gICAgfVxuICAgIEF0b20ucHJvdG90eXBlLnJlcG9ydE9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBzdGFydEJhdGNoKCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucmVwb3J0T2JzZXJ2ZWQuY2FsbCh0aGlzKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzQmVpbmdUcmFja2VkKSB7XG4gICAgICAgICAgICB0aGlzLmlzQmVpbmdUcmFja2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMub25CZWNvbWVPYnNlcnZlZEhhbmRsZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICByZXR1cm4gISFnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgfTtcbiAgICBBdG9tLnByb3RvdHlwZS5vbkJlY29tZVVub2JzZXJ2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuaXNCZWluZ1RyYWNrZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyKCk7XG4gICAgfTtcbiAgICByZXR1cm4gQXRvbTtcbn0oQmFzZUF0b20pKTtcbmV4cG9ydHMuQXRvbSA9IEF0b207XG52YXIgQ29tcHV0ZWRWYWx1ZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29tcHV0ZWRWYWx1ZShkZXJpdmF0aW9uLCBzY29wZSwgY29tcGFyZVN0cnVjdHVyYWwsIG5hbWUsIHNldHRlcikge1xuICAgICAgICB0aGlzLmRlcml2YXRpb24gPSBkZXJpdmF0aW9uO1xuICAgICAgICB0aGlzLnNjb3BlID0gc2NvcGU7XG4gICAgICAgIHRoaXMuY29tcGFyZVN0cnVjdHVyYWwgPSBjb21wYXJlU3RydWN0dXJhbDtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HO1xuICAgICAgICB0aGlzLm9ic2VydmluZyA9IFtdO1xuICAgICAgICB0aGlzLm5ld09ic2VydmluZyA9IG51bGw7XG4gICAgICAgIHRoaXMuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLm9ic2VydmVycyA9IFtdO1xuICAgICAgICB0aGlzLm9ic2VydmVyc0luZGV4ZXMgPSB7fTtcbiAgICAgICAgdGhpcy5kaWZmVmFsdWUgPSAwO1xuICAgICAgICB0aGlzLnJ1bklkID0gMDtcbiAgICAgICAgdGhpcy5sYXN0QWNjZXNzZWRCeSA9IDA7XG4gICAgICAgIHRoaXMubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTtcbiAgICAgICAgdGhpcy51bmJvdW5kRGVwc0NvdW50ID0gMDtcbiAgICAgICAgdGhpcy5fX21hcGlkID0gXCIjXCIgKyBnZXROZXh0SWQoKTtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5pc0NvbXB1dGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lIHx8IFwiQ29tcHV0ZWRWYWx1ZUBcIiArIGdldE5leHRJZCgpO1xuICAgICAgICBpZiAoc2V0dGVyKVxuICAgICAgICAgICAgdGhpcy5zZXR0ZXIgPSBjcmVhdGVBY3Rpb24obmFtZSArIFwiLXNldHRlclwiLCBzZXR0ZXIpO1xuICAgIH1cbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5wZWVrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmlzQ29tcHV0aW5nID0gdHJ1ZTtcbiAgICAgICAgdmFyIHByZXZBbGxvd1N0YXRlQ2hhbmdlcyA9IGFsbG93U3RhdGVDaGFuZ2VzU3RhcnQoZmFsc2UpO1xuICAgICAgICB2YXIgcmVzID0gdGhpcy5kZXJpdmF0aW9uLmNhbGwodGhpcy5zY29wZSk7XG4gICAgICAgIGFsbG93U3RhdGVDaGFuZ2VzRW5kKHByZXZBbGxvd1N0YXRlQ2hhbmdlcyk7XG4gICAgICAgIHRoaXMuaXNDb21wdXRpbmcgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIDtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5wZWVrVW50cmFja2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGFzRXJyb3IgPSB0cnVlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIHJlcyA9IHRoaXMucGVlaygpO1xuICAgICAgICAgICAgaGFzRXJyb3IgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICBpZiAoaGFzRXJyb3IpXG4gICAgICAgICAgICAgICAgaGFuZGxlRXhjZXB0aW9uSW5EZXJpdmF0aW9uKHRoaXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5vbkJlY29tZVN0YWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBwcm9wYWdhdGVNYXliZUNoYW5nZWQodGhpcyk7XG4gICAgfTtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5vbkJlY29tZVVub2JzZXJ2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGludmFyaWFudCh0aGlzLmRlcGVuZGVuY2llc1N0YXRlICE9PSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORywgXCJJTlRFUk5BTCBFUlJPUiBvbmx5IG9uQmVjb21lVW5vYnNlcnZlZCBzaG91bGRuJ3QgYmUgY2FsbGVkIHR3aWNlIGluIGEgcm93XCIpO1xuICAgICAgICBjbGVhck9ic2VydmluZyh0aGlzKTtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaW52YXJpYW50KCF0aGlzLmlzQ29tcHV0aW5nLCBcIkN5Y2xlIGRldGVjdGVkIGluIGNvbXB1dGF0aW9uIFwiICsgdGhpcy5uYW1lLCB0aGlzLmRlcml2YXRpb24pO1xuICAgICAgICBzdGFydEJhdGNoKCk7XG4gICAgICAgIGlmIChnbG9iYWxTdGF0ZS5pbkJhdGNoID09PSAxKSB7XG4gICAgICAgICAgICBpZiAoc2hvdWxkQ29tcHV0ZSh0aGlzKSlcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy5wZWVrVW50cmFja2VkKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXBvcnRPYnNlcnZlZCh0aGlzKTtcbiAgICAgICAgICAgIGlmIChzaG91bGRDb21wdXRlKHRoaXMpKVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRyYWNrQW5kQ29tcHV0ZSgpKVxuICAgICAgICAgICAgICAgICAgICBwcm9wYWdhdGVDaGFuZ2VDb25maXJtZWQodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMudmFsdWU7XG4gICAgICAgIGVuZEJhdGNoKCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5yZWNvdmVyRnJvbUVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmlzQ29tcHV0aW5nID0gZmFsc2U7XG4gICAgfTtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGVyKVxuICAgICAgICAgICAgdGhpcy5zZXR0ZXIuY2FsbCh0aGlzLnNjb3BlLCB2YWx1ZSk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIltDb21wdXRlZFZhbHVlICdcIiArIHRoaXMubmFtZSArIFwiJ10gSXQgaXMgbm90IHBvc3NpYmxlIHRvIGFzc2lnbiBhIG5ldyB2YWx1ZSB0byBhIGNvbXB1dGVkIHZhbHVlLlwiKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnRyYWNrQW5kQ29tcHV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGlzU3B5RW5hYmxlZCgpKSB7XG4gICAgICAgICAgICBzcHlSZXBvcnQoe1xuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcyxcbiAgICAgICAgICAgICAgICB0eXBlOiBcImNvbXB1dGVcIixcbiAgICAgICAgICAgICAgICBmbjogdGhpcy5kZXJpdmF0aW9uLFxuICAgICAgICAgICAgICAgIHRhcmdldDogdGhpcy5zY29wZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9sZFZhbHVlID0gdGhpcy52YWx1ZTtcbiAgICAgICAgdmFyIG5ld1ZhbHVlID0gdGhpcy52YWx1ZSA9IHRyYWNrRGVyaXZlZEZ1bmN0aW9uKHRoaXMsIHRoaXMucGVlayk7XG4gICAgICAgIHJldHVybiB2YWx1ZURpZENoYW5nZSh0aGlzLmNvbXBhcmVTdHJ1Y3R1cmFsLCBuZXdWYWx1ZSwgb2xkVmFsdWUpO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uIChsaXN0ZW5lciwgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBmaXJzdFRpbWUgPSB0cnVlO1xuICAgICAgICB2YXIgcHJldlZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gYXV0b3J1bihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbmV3VmFsdWUgPSBfdGhpcy5nZXQoKTtcbiAgICAgICAgICAgIGlmICghZmlyc3RUaW1lIHx8IGZpcmVJbW1lZGlhdGVseSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2VSA9IHVudHJhY2tlZFN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIobmV3VmFsdWUsIHByZXZWYWx1ZSk7XG4gICAgICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpcnN0VGltZSA9IGZhbHNlO1xuICAgICAgICAgICAgcHJldlZhbHVlID0gbmV3VmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lICsgXCJbXCIgKyB0aGlzLmRlcml2YXRpb24udG9TdHJpbmcoKSArIFwiXVwiO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUud2h5UnVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNUcmFja2luZyA9IEJvb2xlYW4oZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uKTtcbiAgICAgICAgdmFyIG9ic2VydmluZyA9IHVuaXF1ZSh0aGlzLmlzQ29tcHV0aW5nID8gdGhpcy5uZXdPYnNlcnZpbmcgOiB0aGlzLm9ic2VydmluZykubWFwKGZ1bmN0aW9uIChkZXApIHsgcmV0dXJuIGRlcC5uYW1lOyB9KTtcbiAgICAgICAgdmFyIG9ic2VydmVycyA9IHVuaXF1ZShnZXRPYnNlcnZlcnModGhpcykubWFwKGZ1bmN0aW9uIChkZXApIHsgcmV0dXJuIGRlcC5uYW1lOyB9KSk7XG4gICAgICAgIHJldHVybiAoKFwiXFxuV2h5UnVuPyBjb21wdXRhdGlvbiAnXCIgKyB0aGlzLm5hbWUgKyBcIic6XFxuICogUnVubmluZyBiZWNhdXNlOiBcIiArIChpc1RyYWNraW5nID8gXCJbYWN0aXZlXSB0aGUgdmFsdWUgb2YgdGhpcyBjb21wdXRhdGlvbiBpcyBuZWVkZWQgYnkgYSByZWFjdGlvblwiIDogdGhpcy5pc0NvbXB1dGluZyA/IFwiW2dldF0gVGhlIHZhbHVlIG9mIHRoaXMgY29tcHV0ZWQgd2FzIHJlcXVlc3RlZCBvdXRzaWRlIGEgcmVhY3Rpb25cIiA6IFwiW2lkbGVdIG5vdCBydW5uaW5nIGF0IHRoZSBtb21lbnRcIikgKyBcIlxcblwiKSArXG4gICAgICAgICAgICAodGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5OT1RfVFJBQ0tJTkdcbiAgICAgICAgICAgICAgICA/XG4gICAgICAgICAgICAgICAgICAgIFwiICogVGhpcyBjb21wdXRhdGlvbiBpcyBzdXNwZW5kZWQgKG5vdCBpbiB1c2UgYnkgYW55IHJlYWN0aW9uKSBhbmQgd29uJ3QgcnVuIGF1dG9tYXRpY2FsbHkuXFxuXFx0RGlkbid0IGV4cGVjdCB0aGlzIGNvbXB1dGF0aW9uIHRvIGJlIHN1c3BlbmRlZCBhdCB0aGlzIHBvaW50P1xcblxcdCAgMS4gTWFrZSBzdXJlIHRoaXMgY29tcHV0YXRpb24gaXMgdXNlZCBieSBhIHJlYWN0aW9uIChyZWFjdGlvbiwgYXV0b3J1biwgb2JzZXJ2ZXIpLlxcblxcdCAgMi4gQ2hlY2sgd2hldGhlciB5b3UgYXJlIHVzaW5nIHRoaXMgY29tcHV0YXRpb24gc3luY2hyb25vdXNseSAoaW4gdGhlIHNhbWUgc3RhY2sgYXMgdGhleSByZWFjdGlvbiB0aGF0IG5lZWRzIGl0KS5cXG5cIlxuICAgICAgICAgICAgICAgIDpcbiAgICAgICAgICAgICAgICAgICAgXCIgKiBUaGlzIGNvbXB1dGF0aW9uIHdpbGwgcmUtcnVuIGlmIGFueSBvZiB0aGUgZm9sbG93aW5nIG9ic2VydmFibGVzIGNoYW5nZXM6XFxuICAgIFwiICsgam9pblN0cmluZ3Mob2JzZXJ2aW5nKSArIFwiXFxuICAgIFwiICsgKCh0aGlzLmlzQ29tcHV0aW5nICYmIGlzVHJhY2tpbmcpID8gXCIgKC4uLiBvciBhbnkgb2JzZXJ2YWJsZSBhY2Nlc3NlZCBkdXJpbmcgdGhlIHJlbWFpbmRlciBvZiB0aGUgY3VycmVudCBydW4pXCIgOiBcIlwiKSArIFwiXFxuXFx0TWlzc2luZyBpdGVtcyBpbiB0aGlzIGxpc3Q/XFxuXFx0ICAxLiBDaGVjayB3aGV0aGVyIGFsbCB1c2VkIHZhbHVlcyBhcmUgcHJvcGVybHkgbWFya2VkIGFzIG9ic2VydmFibGUgKHVzZSBpc09ic2VydmFibGUgdG8gdmVyaWZ5KVxcblxcdCAgMi4gTWFrZSBzdXJlIHlvdSBkaWRuJ3QgZGVyZWZlcmVuY2UgdmFsdWVzIHRvbyBlYXJseS4gTW9iWCBvYnNlcnZlcyBwcm9wcywgbm90IHByaW1pdGl2ZXMuIEUuZzogdXNlICdwZXJzb24ubmFtZScgaW5zdGVhZCBvZiAnbmFtZScgaW4geW91ciBjb21wdXRhdGlvbi5cXG4gICogSWYgdGhlIG91dGNvbWUgb2YgdGhpcyBjb21wdXRhdGlvbiBjaGFuZ2VzLCB0aGUgZm9sbG93aW5nIG9ic2VydmVycyB3aWxsIGJlIHJlLXJ1bjpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZlcnMpICsgXCJcXG5cIikpO1xuICAgIH07XG4gICAgcmV0dXJuIENvbXB1dGVkVmFsdWU7XG59KCkpO1xudmFyIElEZXJpdmF0aW9uU3RhdGU7XG4oZnVuY3Rpb24gKElEZXJpdmF0aW9uU3RhdGUpIHtcbiAgICBJRGVyaXZhdGlvblN0YXRlW0lEZXJpdmF0aW9uU3RhdGVbXCJOT1RfVFJBQ0tJTkdcIl0gPSAtMV0gPSBcIk5PVF9UUkFDS0lOR1wiO1xuICAgIElEZXJpdmF0aW9uU3RhdGVbSURlcml2YXRpb25TdGF0ZVtcIlVQX1RPX0RBVEVcIl0gPSAwXSA9IFwiVVBfVE9fREFURVwiO1xuICAgIElEZXJpdmF0aW9uU3RhdGVbSURlcml2YXRpb25TdGF0ZVtcIlBPU1NJQkxZX1NUQUxFXCJdID0gMV0gPSBcIlBPU1NJQkxZX1NUQUxFXCI7XG4gICAgSURlcml2YXRpb25TdGF0ZVtJRGVyaXZhdGlvblN0YXRlW1wiU1RBTEVcIl0gPSAyXSA9IFwiU1RBTEVcIjtcbn0pKElEZXJpdmF0aW9uU3RhdGUgfHwgKElEZXJpdmF0aW9uU3RhdGUgPSB7fSkpO1xuZXhwb3J0cy5JRGVyaXZhdGlvblN0YXRlID0gSURlcml2YXRpb25TdGF0ZTtcbmZ1bmN0aW9uIHNob3VsZENvbXB1dGUoZGVyaXZhdGlvbikge1xuICAgIHN3aXRjaCAoZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSkge1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTogcmV0dXJuIGZhbHNlO1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HOlxuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuU1RBTEU6IHJldHVybiB0cnVlO1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuUE9TU0lCTFlfU1RBTEU6IHtcbiAgICAgICAgICAgIHZhciBoYXNFcnJvciA9IHRydWU7XG4gICAgICAgICAgICB2YXIgcHJldlVudHJhY2tlZCA9IHVudHJhY2tlZFN0YXJ0KCk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhciBvYnMgPSBkZXJpdmF0aW9uLm9ic2VydmluZywgbCA9IG9icy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9iaiA9IG9ic1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIENvbXB1dGVkVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iai5nZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZXJpdmF0aW9uLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzRXJyb3IgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnRyYWNrZWRFbmQocHJldlVudHJhY2tlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGFzRXJyb3IgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjaGFuZ2VEZXBlbmRlbmNpZXNTdGF0ZVRvMChkZXJpdmF0aW9uKTtcbiAgICAgICAgICAgICAgICB1bnRyYWNrZWRFbmQocHJldlVudHJhY2tlZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc0Vycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZURlcGVuZGVuY2llc1N0YXRlVG8wKGRlcml2YXRpb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbmZ1bmN0aW9uIGlzQ29tcHV0aW5nRGVyaXZhdGlvbigpIHtcbiAgICByZXR1cm4gZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uICE9PSBudWxsO1xufVxuZnVuY3Rpb24gY2hlY2tJZlN0YXRlTW9kaWZpY2F0aW9uc0FyZUFsbG93ZWQoKSB7XG4gICAgaWYgKCFnbG9iYWxTdGF0ZS5hbGxvd1N0YXRlQ2hhbmdlcykge1xuICAgICAgICBpbnZhcmlhbnQoZmFsc2UsIGdsb2JhbFN0YXRlLnN0cmljdE1vZGVcbiAgICAgICAgICAgID8gXCJJdCBpcyBub3QgYWxsb3dlZCB0byBjcmVhdGUgb3IgY2hhbmdlIHN0YXRlIG91dHNpZGUgYW4gYGFjdGlvbmAgd2hlbiBNb2JYIGlzIGluIHN0cmljdCBtb2RlLiBXcmFwIHRoZSBjdXJyZW50IG1ldGhvZCBpbiBgYWN0aW9uYCBpZiB0aGlzIHN0YXRlIGNoYW5nZSBpcyBpbnRlbmRlZFwiXG4gICAgICAgICAgICA6IFwiSXQgaXMgbm90IGFsbG93ZWQgdG8gY2hhbmdlIHRoZSBzdGF0ZSB3aGVuIGEgY29tcHV0ZWQgdmFsdWUgb3IgdHJhbnNmb3JtZXIgaXMgYmVpbmcgZXZhbHVhdGVkLiBVc2UgJ2F1dG9ydW4nIHRvIGNyZWF0ZSByZWFjdGl2ZSBmdW5jdGlvbnMgd2l0aCBzaWRlLWVmZmVjdHMuXCIpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHRyYWNrRGVyaXZlZEZ1bmN0aW9uKGRlcml2YXRpb24sIGYpIHtcbiAgICBjaGFuZ2VEZXBlbmRlbmNpZXNTdGF0ZVRvMChkZXJpdmF0aW9uKTtcbiAgICBkZXJpdmF0aW9uLm5ld09ic2VydmluZyA9IG5ldyBBcnJheShkZXJpdmF0aW9uLm9ic2VydmluZy5sZW5ndGggKyAxMDApO1xuICAgIGRlcml2YXRpb24udW5ib3VuZERlcHNDb3VudCA9IDA7XG4gICAgZGVyaXZhdGlvbi5ydW5JZCA9ICsrZ2xvYmFsU3RhdGUucnVuSWQ7XG4gICAgdmFyIHByZXZUcmFja2luZyA9IGdsb2JhbFN0YXRlLnRyYWNraW5nRGVyaXZhdGlvbjtcbiAgICBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb24gPSBkZXJpdmF0aW9uO1xuICAgIHZhciBoYXNFeGNlcHRpb24gPSB0cnVlO1xuICAgIHZhciByZXN1bHQ7XG4gICAgdHJ5IHtcbiAgICAgICAgcmVzdWx0ID0gZi5jYWxsKGRlcml2YXRpb24pO1xuICAgICAgICBoYXNFeGNlcHRpb24gPSBmYWxzZTtcbiAgICB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIGlmIChoYXNFeGNlcHRpb24pIHtcbiAgICAgICAgICAgIGhhbmRsZUV4Y2VwdGlvbkluRGVyaXZhdGlvbihkZXJpdmF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlLnRyYWNraW5nRGVyaXZhdGlvbiA9IHByZXZUcmFja2luZztcbiAgICAgICAgICAgIGJpbmREZXBlbmRlbmNpZXMoZGVyaXZhdGlvbik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGhhbmRsZUV4Y2VwdGlvbkluRGVyaXZhdGlvbihkZXJpdmF0aW9uKSB7XG4gICAgdmFyIG1lc3NhZ2UgPSAoXCJbbW9ieF0gQW4gdW5jYXVnaHQgZXhjZXB0aW9uIG9jY3VycmVkIHdoaWxlIGNhbGN1bGF0aW5nIHlvdXIgY29tcHV0ZWQgdmFsdWUsIGF1dG9ydW4gb3IgdHJhbnNmb3JtZXIuIE9yIGluc2lkZSB0aGUgcmVuZGVyKCkgbWV0aG9kIG9mIGFuIG9ic2VydmVyIGJhc2VkIFJlYWN0IGNvbXBvbmVudC4gXCIgK1xuICAgICAgICBcIlRoZXNlIGZ1bmN0aW9ucyBzaG91bGQgbmV2ZXIgdGhyb3cgZXhjZXB0aW9ucyBhcyBNb2JYIHdpbGwgbm90IGFsd2F5cyBiZSBhYmxlIHRvIHJlY292ZXIgZnJvbSB0aGVtLiBcIiArXG4gICAgICAgIChcIlBsZWFzZSBmaXggdGhlIGVycm9yIHJlcG9ydGVkIGFmdGVyIHRoaXMgbWVzc2FnZSBvciBlbmFibGUgJ1BhdXNlIG9uIChjYXVnaHQpIGV4Y2VwdGlvbnMnIGluIHlvdXIgZGVidWdnZXIgdG8gZmluZCB0aGUgcm9vdCBjYXVzZS4gSW46ICdcIiArIGRlcml2YXRpb24ubmFtZSArIFwiJy4gXCIpICtcbiAgICAgICAgXCJGb3IgbW9yZSBkZXRhaWxzIHNlZSBodHRwczovL2dpdGh1Yi5jb20vbW9ieGpzL21vYngvaXNzdWVzLzQ2MlwiKTtcbiAgICBpZiAoaXNTcHlFbmFibGVkKCkpIHtcbiAgICAgICAgc3B5UmVwb3J0KHtcbiAgICAgICAgICAgIHR5cGU6IFwiZXJyb3JcIixcbiAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2VcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnNvbGUud2FybihtZXNzYWdlKTtcbiAgICBjaGFuZ2VEZXBlbmRlbmNpZXNTdGF0ZVRvMChkZXJpdmF0aW9uKTtcbiAgICBkZXJpdmF0aW9uLm5ld09ic2VydmluZyA9IG51bGw7XG4gICAgZGVyaXZhdGlvbi51bmJvdW5kRGVwc0NvdW50ID0gMDtcbiAgICBkZXJpdmF0aW9uLnJlY292ZXJGcm9tRXJyb3IoKTtcbiAgICBlbmRCYXRjaCgpO1xuICAgIHJlc2V0R2xvYmFsU3RhdGUoKTtcbn1cbmZ1bmN0aW9uIGJpbmREZXBlbmRlbmNpZXMoZGVyaXZhdGlvbikge1xuICAgIHZhciBwcmV2T2JzZXJ2aW5nID0gZGVyaXZhdGlvbi5vYnNlcnZpbmc7XG4gICAgdmFyIG9ic2VydmluZyA9IGRlcml2YXRpb24ub2JzZXJ2aW5nID0gZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmc7XG4gICAgZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmcgPSBudWxsO1xuICAgIHZhciBpMCA9IDAsIGwgPSBkZXJpdmF0aW9uLnVuYm91bmREZXBzQ291bnQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgdmFyIGRlcCA9IG9ic2VydmluZ1tpXTtcbiAgICAgICAgaWYgKGRlcC5kaWZmVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIGRlcC5kaWZmVmFsdWUgPSAxO1xuICAgICAgICAgICAgaWYgKGkwICE9PSBpKVxuICAgICAgICAgICAgICAgIG9ic2VydmluZ1tpMF0gPSBkZXA7XG4gICAgICAgICAgICBpMCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIG9ic2VydmluZy5sZW5ndGggPSBpMDtcbiAgICBsID0gcHJldk9ic2VydmluZy5sZW5ndGg7XG4gICAgd2hpbGUgKGwtLSkge1xuICAgICAgICB2YXIgZGVwID0gcHJldk9ic2VydmluZ1tsXTtcbiAgICAgICAgaWYgKGRlcC5kaWZmVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIHJlbW92ZU9ic2VydmVyKGRlcCwgZGVyaXZhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZGVwLmRpZmZWYWx1ZSA9IDA7XG4gICAgfVxuICAgIHdoaWxlIChpMC0tKSB7XG4gICAgICAgIHZhciBkZXAgPSBvYnNlcnZpbmdbaTBdO1xuICAgICAgICBpZiAoZGVwLmRpZmZWYWx1ZSA9PT0gMSkge1xuICAgICAgICAgICAgZGVwLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgICAgICBhZGRPYnNlcnZlcihkZXAsIGRlcml2YXRpb24pO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gY2xlYXJPYnNlcnZpbmcoZGVyaXZhdGlvbikge1xuICAgIHZhciBvYnMgPSBkZXJpdmF0aW9uLm9ic2VydmluZztcbiAgICB2YXIgaSA9IG9icy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSlcbiAgICAgICAgcmVtb3ZlT2JzZXJ2ZXIob2JzW2ldLCBkZXJpdmF0aW9uKTtcbiAgICBkZXJpdmF0aW9uLmRlcGVuZGVuY2llc1N0YXRlID0gSURlcml2YXRpb25TdGF0ZS5OT1RfVFJBQ0tJTkc7XG4gICAgb2JzLmxlbmd0aCA9IDA7XG59XG5mdW5jdGlvbiB1bnRyYWNrZWQoYWN0aW9uKSB7XG4gICAgdmFyIHByZXYgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgIHZhciByZXMgPSBhY3Rpb24oKTtcbiAgICB1bnRyYWNrZWRFbmQocHJldik7XG4gICAgcmV0dXJuIHJlcztcbn1cbmV4cG9ydHMudW50cmFja2VkID0gdW50cmFja2VkO1xuZnVuY3Rpb24gdW50cmFja2VkU3RhcnQoKSB7XG4gICAgdmFyIHByZXYgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gbnVsbDtcbiAgICByZXR1cm4gcHJldjtcbn1cbmZ1bmN0aW9uIHVudHJhY2tlZEVuZChwcmV2KSB7XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gcHJldjtcbn1cbmZ1bmN0aW9uIGNoYW5nZURlcGVuZGVuY2llc1N0YXRlVG8wKGRlcml2YXRpb24pIHtcbiAgICBpZiAoZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFKVxuICAgICAgICByZXR1cm47XG4gICAgZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTtcbiAgICB2YXIgb2JzID0gZGVyaXZhdGlvbi5vYnNlcnZpbmc7XG4gICAgdmFyIGkgPSBvYnMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0pXG4gICAgICAgIG9ic1tpXS5sb3dlc3RPYnNlcnZlclN0YXRlID0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFO1xufVxudmFyIHBlcnNpc3RlbnRLZXlzID0gW1wibW9ieEd1aWRcIiwgXCJyZXNldElkXCIsIFwic3B5TGlzdGVuZXJzXCIsIFwic3RyaWN0TW9kZVwiLCBcInJ1bklkXCJdO1xudmFyIE1vYlhHbG9iYWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBNb2JYR2xvYmFscygpIHtcbiAgICAgICAgdGhpcy52ZXJzaW9uID0gNDtcbiAgICAgICAgdGhpcy50cmFja2luZ0Rlcml2YXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLnJ1bklkID0gMDtcbiAgICAgICAgdGhpcy5tb2J4R3VpZCA9IDA7XG4gICAgICAgIHRoaXMuaW5UcmFuc2FjdGlvbiA9IDA7XG4gICAgICAgIHRoaXMuaXNSdW5uaW5nUmVhY3Rpb25zID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaW5CYXRjaCA9IDA7XG4gICAgICAgIHRoaXMucGVuZGluZ1Vub2JzZXJ2YXRpb25zID0gW107XG4gICAgICAgIHRoaXMucGVuZGluZ1JlYWN0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmFsbG93U3RhdGVDaGFuZ2VzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHJpY3RNb2RlID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVzZXRJZCA9IDA7XG4gICAgICAgIHRoaXMuc3B5TGlzdGVuZXJzID0gW107XG4gICAgfVxuICAgIHJldHVybiBNb2JYR2xvYmFscztcbn0oKSk7XG52YXIgZ2xvYmFsU3RhdGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciByZXMgPSBuZXcgTW9iWEdsb2JhbHMoKTtcbiAgICBpZiAoZ2xvYmFsLl9fbW9ic2VydmFibGVUcmFja2luZ1N0YWNrIHx8IGdsb2JhbC5fX21vYnNlcnZhYmxlVmlld1N0YWNrKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieF0gQW4gaW5jb21wYXRpYmxlIHZlcnNpb24gb2YgbW9ic2VydmFibGUgaXMgYWxyZWFkeSBsb2FkZWQuXCIpO1xuICAgIGlmIChnbG9iYWwuX19tb2J4R2xvYmFsICYmIGdsb2JhbC5fX21vYnhHbG9iYWwudmVyc2lvbiAhPT0gcmVzLnZlcnNpb24pXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4XSBBbiBpbmNvbXBhdGlibGUgdmVyc2lvbiBvZiBtb2J4IGlzIGFscmVhZHkgbG9hZGVkLlwiKTtcbiAgICBpZiAoZ2xvYmFsLl9fbW9ieEdsb2JhbClcbiAgICAgICAgcmV0dXJuIGdsb2JhbC5fX21vYnhHbG9iYWw7XG4gICAgcmV0dXJuIGdsb2JhbC5fX21vYnhHbG9iYWwgPSByZXM7XG59KSgpO1xuZnVuY3Rpb24gcmVnaXN0ZXJHbG9iYWxzKCkge1xufVxuZnVuY3Rpb24gcmVzZXRHbG9iYWxTdGF0ZSgpIHtcbiAgICBnbG9iYWxTdGF0ZS5yZXNldElkKys7XG4gICAgdmFyIGRlZmF1bHRHbG9iYWxzID0gbmV3IE1vYlhHbG9iYWxzKCk7XG4gICAgZm9yICh2YXIga2V5IGluIGRlZmF1bHRHbG9iYWxzKVxuICAgICAgICBpZiAocGVyc2lzdGVudEtleXMuaW5kZXhPZihrZXkpID09PSAtMSlcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlW2tleV0gPSBkZWZhdWx0R2xvYmFsc1trZXldO1xuICAgIGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzID0gIWdsb2JhbFN0YXRlLnN0cmljdE1vZGU7XG59XG5mdW5jdGlvbiBoYXNPYnNlcnZlcnMob2JzZXJ2YWJsZSkge1xuICAgIHJldHVybiBvYnNlcnZhYmxlLm9ic2VydmVycyAmJiBvYnNlcnZhYmxlLm9ic2VydmVycy5sZW5ndGggPiAwO1xufVxuZnVuY3Rpb24gZ2V0T2JzZXJ2ZXJzKG9ic2VydmFibGUpIHtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5vYnNlcnZlcnM7XG59XG5mdW5jdGlvbiBpbnZhcmlhbnRPYnNlcnZlcnMob2JzZXJ2YWJsZSkge1xuICAgIHZhciBsaXN0ID0gb2JzZXJ2YWJsZS5vYnNlcnZlcnM7XG4gICAgdmFyIG1hcCA9IG9ic2VydmFibGUub2JzZXJ2ZXJzSW5kZXhlcztcbiAgICB2YXIgbCA9IGxpc3QubGVuZ3RoO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIHZhciBpZCA9IGxpc3RbaV0uX19tYXBpZDtcbiAgICAgICAgaWYgKGkpIHtcbiAgICAgICAgICAgIGludmFyaWFudChtYXBbaWRdID09PSBpLCBcIklOVEVSTkFMIEVSUk9SIG1hcHMgZGVyaXZhdGlvbi5fX21hcGlkIHRvIGluZGV4IGluIGxpc3RcIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpbnZhcmlhbnQoIShpZCBpbiBtYXApLCBcIklOVEVSTkFMIEVSUk9SIG9ic2VydmVyIG9uIGluZGV4IDAgc2hvdWxkbnQgYmUgaGVsZCBpbiBtYXAuXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGludmFyaWFudChsaXN0Lmxlbmd0aCA9PT0gMCB8fCBPYmplY3Qua2V5cyhtYXApLmxlbmd0aCA9PT0gbGlzdC5sZW5ndGggLSAxLCBcIklOVEVSTkFMIEVSUk9SIHRoZXJlIGlzIG5vIGp1bmsgaW4gbWFwXCIpO1xufVxuZnVuY3Rpb24gYWRkT2JzZXJ2ZXIob2JzZXJ2YWJsZSwgbm9kZSkge1xuICAgIHZhciBsID0gb2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoO1xuICAgIGlmIChsKSB7XG4gICAgICAgIG9ic2VydmFibGUub2JzZXJ2ZXJzSW5kZXhlc1tub2RlLl9fbWFwaWRdID0gbDtcbiAgICB9XG4gICAgb2JzZXJ2YWJsZS5vYnNlcnZlcnNbbF0gPSBub2RlO1xuICAgIGlmIChvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPiBub2RlLmRlcGVuZGVuY2llc1N0YXRlKVxuICAgICAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBub2RlLmRlcGVuZGVuY2llc1N0YXRlO1xufVxuZnVuY3Rpb24gcmVtb3ZlT2JzZXJ2ZXIob2JzZXJ2YWJsZSwgbm9kZSkge1xuICAgIGlmIChvYnNlcnZhYmxlLm9ic2VydmVycy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgb2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID0gMDtcbiAgICAgICAgcXVldWVGb3JVbm9ic2VydmF0aW9uKG9ic2VydmFibGUpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGxpc3QgPSBvYnNlcnZhYmxlLm9ic2VydmVycztcbiAgICAgICAgdmFyIG1hcF8xID0gb2JzZXJ2YWJsZS5vYnNlcnZlcnNJbmRleGVzO1xuICAgICAgICB2YXIgZmlsbGVyID0gbGlzdC5wb3AoKTtcbiAgICAgICAgaWYgKGZpbGxlciAhPT0gbm9kZSkge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gbWFwXzFbbm9kZS5fX21hcGlkXSB8fCAwO1xuICAgICAgICAgICAgaWYgKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgbWFwXzFbZmlsbGVyLl9fbWFwaWRdID0gaW5kZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgbWFwXzFbZmlsbGVyLl9fbWFwaWRdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGlzdFtpbmRleF0gPSBmaWxsZXI7XG4gICAgICAgIH1cbiAgICAgICAgZGVsZXRlIG1hcF8xW25vZGUuX19tYXBpZF07XG4gICAgfVxufVxuZnVuY3Rpb24gcXVldWVGb3JVbm9ic2VydmF0aW9uKG9ic2VydmFibGUpIHtcbiAgICBpZiAoIW9ic2VydmFibGUuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbikge1xuICAgICAgICBvYnNlcnZhYmxlLmlzUGVuZGluZ1Vub2JzZXJ2YXRpb24gPSB0cnVlO1xuICAgICAgICBnbG9iYWxTdGF0ZS5wZW5kaW5nVW5vYnNlcnZhdGlvbnMucHVzaChvYnNlcnZhYmxlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBzdGFydEJhdGNoKCkge1xuICAgIGdsb2JhbFN0YXRlLmluQmF0Y2grKztcbn1cbmZ1bmN0aW9uIGVuZEJhdGNoKCkge1xuICAgIGlmIChnbG9iYWxTdGF0ZS5pbkJhdGNoID09PSAxKSB7XG4gICAgICAgIHZhciBsaXN0ID0gZ2xvYmFsU3RhdGUucGVuZGluZ1Vub2JzZXJ2YXRpb25zO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBvYnNlcnZhYmxlXzEgPSBsaXN0W2ldO1xuICAgICAgICAgICAgb2JzZXJ2YWJsZV8xLmlzUGVuZGluZ1Vub2JzZXJ2YXRpb24gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChvYnNlcnZhYmxlXzEub2JzZXJ2ZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIG9ic2VydmFibGVfMS5vbkJlY29tZVVub2JzZXJ2ZWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnbG9iYWxTdGF0ZS5wZW5kaW5nVW5vYnNlcnZhdGlvbnMgPSBbXTtcbiAgICB9XG4gICAgZ2xvYmFsU3RhdGUuaW5CYXRjaC0tO1xufVxuZnVuY3Rpb24gcmVwb3J0T2JzZXJ2ZWQob2JzZXJ2YWJsZSkge1xuICAgIHZhciBkZXJpdmF0aW9uID0gZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uO1xuICAgIGlmIChkZXJpdmF0aW9uICE9PSBudWxsKSB7XG4gICAgICAgIGlmIChkZXJpdmF0aW9uLnJ1bklkICE9PSBvYnNlcnZhYmxlLmxhc3RBY2Nlc3NlZEJ5KSB7XG4gICAgICAgICAgICBvYnNlcnZhYmxlLmxhc3RBY2Nlc3NlZEJ5ID0gZGVyaXZhdGlvbi5ydW5JZDtcbiAgICAgICAgICAgIGRlcml2YXRpb24ubmV3T2JzZXJ2aW5nW2Rlcml2YXRpb24udW5ib3VuZERlcHNDb3VudCsrXSA9IG9ic2VydmFibGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAob2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBpbnZhcmlhbnRMT1Mob2JzZXJ2YWJsZSwgbXNnKSB7XG4gICAgdmFyIG1pbiA9IGdldE9ic2VydmVycyhvYnNlcnZhYmxlKS5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIE1hdGgubWluKGEsIGIuZGVwZW5kZW5jaWVzU3RhdGUpOyB9LCAyKTtcbiAgICBpZiAobWluID49IG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSlcbiAgICAgICAgcmV0dXJuO1xuICAgIHRocm93IG5ldyBFcnJvcihcImxvd2VzdE9ic2VydmVyU3RhdGUgaXMgd3JvbmcgZm9yIFwiICsgbXNnICsgXCIgYmVjYXVzZSBcIiArIG1pbiArIFwiIDwgXCIgKyBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUpO1xufVxuZnVuY3Rpb24gcHJvcGFnYXRlQ2hhbmdlZChvYnNlcnZhYmxlKSB7XG4gICAgaWYgKG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5TVEFMRSlcbiAgICAgICAgcmV0dXJuO1xuICAgIG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuU1RBTEU7XG4gICAgdmFyIG9ic2VydmVycyA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBpID0gb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIHZhciBkID0gb2JzZXJ2ZXJzW2ldO1xuICAgICAgICBpZiAoZC5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFKVxuICAgICAgICAgICAgZC5vbkJlY29tZVN0YWxlKCk7XG4gICAgICAgIGQuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHByb3BhZ2F0ZUNoYW5nZUNvbmZpcm1lZChvYnNlcnZhYmxlKSB7XG4gICAgaWYgKG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5TVEFMRSlcbiAgICAgICAgcmV0dXJuO1xuICAgIG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuU1RBTEU7XG4gICAgdmFyIG9ic2VydmVycyA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBpID0gb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIHZhciBkID0gb2JzZXJ2ZXJzW2ldO1xuICAgICAgICBpZiAoZC5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5QT1NTSUJMWV9TVEFMRSlcbiAgICAgICAgICAgIGQuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFO1xuICAgICAgICBlbHNlIGlmIChkLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEUpXG4gICAgICAgICAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEU7XG4gICAgfVxufVxuZnVuY3Rpb24gcHJvcGFnYXRlTWF5YmVDaGFuZ2VkKG9ic2VydmFibGUpIHtcbiAgICBpZiAob2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlICE9PSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEUpXG4gICAgICAgIHJldHVybjtcbiAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlBPU1NJQkxZX1NUQUxFO1xuICAgIHZhciBvYnNlcnZlcnMgPSBvYnNlcnZhYmxlLm9ic2VydmVycztcbiAgICB2YXIgaSA9IG9ic2VydmVycy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgICB2YXIgZCA9IG9ic2VydmVyc1tpXTtcbiAgICAgICAgaWYgKGQuZGVwZW5kZW5jaWVzU3RhdGUgPT09IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURSkge1xuICAgICAgICAgICAgZC5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuUE9TU0lCTFlfU1RBTEU7XG4gICAgICAgICAgICBkLm9uQmVjb21lU3RhbGUoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbnZhciBSZWFjdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUmVhY3Rpb24obmFtZSwgb25JbnZhbGlkYXRlKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiUmVhY3Rpb25AXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm9uSW52YWxpZGF0ZSA9IG9uSW52YWxpZGF0ZTtcbiAgICAgICAgdGhpcy5vYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5uZXdPYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HO1xuICAgICAgICB0aGlzLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgIHRoaXMucnVuSWQgPSAwO1xuICAgICAgICB0aGlzLnVuYm91bmREZXBzQ291bnQgPSAwO1xuICAgICAgICB0aGlzLl9fbWFwaWQgPSBcIiNcIiArIGdldE5leHRJZCgpO1xuICAgICAgICB0aGlzLmlzRGlzcG9zZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNUcmFja1BlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgfVxuICAgIFJlYWN0aW9uLnByb3RvdHlwZS5vbkJlY29tZVN0YWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlKCk7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuc2NoZWR1bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5faXNTY2hlZHVsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2lzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlLnBlbmRpbmdSZWFjdGlvbnMucHVzaCh0aGlzKTtcbiAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgIHJ1blJlYWN0aW9ucygpO1xuICAgICAgICAgICAgZW5kQmF0Y2goKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUmVhY3Rpb24ucHJvdG90eXBlLmlzU2NoZWR1bGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNTY2hlZHVsZWQ7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUucnVuUmVhY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pc0Rpc3Bvc2VkKSB7XG4gICAgICAgICAgICB0aGlzLl9pc1NjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHNob3VsZENvbXB1dGUodGhpcykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9pc1RyYWNrUGVuZGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkludmFsaWRhdGUoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faXNUcmFja1BlbmRpbmcgJiYgaXNTcHlFbmFibGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3B5UmVwb3J0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic2NoZWR1bGVkLXJlYWN0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUudHJhY2sgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgc3RhcnRCYXRjaCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBzdGFydFRpbWU7XG4gICAgICAgIGlmIChub3RpZnkpIHtcbiAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydCh7XG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIHR5cGU6IFwicmVhY3Rpb25cIixcbiAgICAgICAgICAgICAgICBmbjogZm5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lzUnVubmluZyA9IHRydWU7XG4gICAgICAgIHRyYWNrRGVyaXZlZEZ1bmN0aW9uKHRoaXMsIGZuKTtcbiAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lzVHJhY2tQZW5kaW5nID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIGNsZWFyT2JzZXJ2aW5nKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub3RpZnkpIHtcbiAgICAgICAgICAgIHNweVJlcG9ydEVuZCh7XG4gICAgICAgICAgICAgICAgdGltZTogRGF0ZS5ub3coKSAtIHN0YXJ0