made with requirebin
Created
August 18, 2016 07:36
-
-
Save ds300/991784e3485cf1d5618d0bd332b28017 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const d = require("derivable") | |
const name = d.atom("World"); // the name of the user | |
const countryCode = d.atom("en"); // for i18n | |
// static constants don't need to be wrapped | |
const greetings = { | |
en: "Hello", | |
de: "Hallo", | |
es: "Hola", | |
cn: "您好", | |
fr: "Bonjour", | |
}; | |
// derive a greeting message based on the user's name and country. | |
const greeting = countryCode.derive(cc => greetings[cc]); | |
const message = d.derive`${greeting}, ${name}!`; // es6 tagged template strings! | |
// set up a Reactor to print the message every time it changes | |
message.react(msg => console.log(msg)); | |
// $> Hello, World! | |
countryCode.set("de"); | |
// $> Hallo, World! | |
name.set("Dagmar"); | |
// $> Hallo, Dagmar! | |
// we can avoid unwanted intermediate reactions by using transactions | |
d.transact(() => { | |
countryCode.set("fr"); | |
name.set("Étienne"); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setTimeout(function(){ | |
;require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"derivable":[function(require,module,exports){ | |
// UMD loader | |
(function (global, factory) { | |
"use strict"; | |
if (global && typeof global.define === "function" && global.define.amd) { | |
global.define(["exports"], factory); | |
} else if (typeof exports !== "undefined") { | |
factory(exports); | |
} else { | |
factory(global.Derivable = {}); | |
} | |
})(this, function (exports) { | |
"use strict"; | |
var util_keys = Object.keys; | |
function util_extend(obj) { | |
for (var i = 1; i < arguments.length; i++) { | |
var other = arguments[i]; | |
var keys = util_keys(other); | |
for (var j = keys.length; j--;) { | |
var prop = keys[j]; | |
obj[prop] = other[prop]; | |
} | |
} | |
return obj; | |
} | |
function _is(a, b) { | |
// SameValue algorithm | |
if (a === b) { // Steps 1-5, 7-10 | |
// Steps 6.b-6.e: +0 != -0 | |
return a !== 0 || 1 / a === 1 / b; | |
} else { | |
// Step 6.a: NaN == NaN | |
return a !== a && b !== b; | |
} | |
} | |
function util_equals (a, b) { | |
return _is(a, b) || (a && typeof a.equals === 'function' && a.equals(b)); | |
} | |
function util_addToArray (a, b) { | |
var i = a.indexOf(b); | |
if (i < 0) { | |
a.push(b); | |
} | |
} | |
function util_removeFromArray (a, b) { | |
var i = a.indexOf(b); | |
if (i >= 0) { | |
a.splice(i, 1); | |
} | |
} | |
function util_arrayContains (a, b) { | |
return a.indexOf(b) >= 0; | |
} | |
var nextId = 0; | |
function util_nextId () { | |
return nextId++; | |
} | |
function util_slice (a, i) { | |
return Array.prototype.slice.call(a, i); | |
} | |
var util_unique = Object.freeze({equals: function () { return false; }}); | |
function util_some (x) { | |
return (x !== null) && (x !== void 0); | |
} | |
var util_DEBUG_MODE = false; | |
function util_setDebugMode(val) { | |
util_DEBUG_MODE = !!val; | |
} | |
function util_setEquals(derivable, equals) { | |
derivable._equals = equals; | |
return derivable; | |
} | |
// node modes | |
var gc_NEW = 0, | |
gc_CHANGED = 1, | |
gc_UNCHANGED = 2, | |
gc_ORPHANED = 3, | |
gc_UNSTABLE = 4, | |
gc_STABLE = 5, | |
gc_DISOWNED = 6; | |
function gc_mark(node, reactors) { | |
// make everything unstable | |
if (node._type === types_REACTION) { | |
if (node.reacting) { | |
throw new Error("Cycle detected! Don't do this!"); | |
} | |
reactors.push(node); | |
} else { | |
for (var i = node._children.length; i--;) { | |
var child = node._children[i]; | |
if (child._state !== gc_UNSTABLE) { | |
child._state = gc_UNSTABLE; | |
gc_mark(child, reactors); | |
} | |
} | |
} | |
} | |
function gc_sweep(node) { | |
var i; | |
switch (node._state) { | |
case gc_CHANGED: | |
case gc_UNCHANGED: | |
// changed or unchanged means the node was visited | |
// during the react phase, which means we keep it in | |
// the graph for the next go round | |
for (i = node._children.length; i--;) { | |
var child = node._children[i]; | |
gc_sweep(child); | |
if (child._state !== gc_STABLE) { | |
node._children.splice(i, 1); | |
} | |
} | |
node._state = gc_STABLE; | |
break; | |
case gc_UNSTABLE: | |
if (node._type === types_REACTION) { | |
// only happens when reaction created in transaction. see issue #14 | |
node._state = gc_STABLE; | |
} else { | |
// unstable means the node was not visited during | |
// the react phase, which means we kick it out of the | |
// graph. | |
// but first we check if all of its parents were unchanged | |
// if so, we can avoid recalculating it in future by | |
// caching its parents' current values. | |
var stashedParentStates = []; | |
for (i = node._parents.length; i--;) { | |
var parent = node._parents[i]; | |
if (parent._state !== gc_UNCHANGED) { | |
// nope, its parents either have changed or weren't visited, | |
// so we have to orphan this node | |
node._state = gc_ORPHANED; | |
break; | |
} | |
stashedParentStates.push([parent, parent._value]); | |
} | |
if (node._state !== gc_ORPHANED) { | |
node._state = gc_DISOWNED; | |
node._parents = stashedParentStates; | |
} | |
} | |
break; | |
case gc_STABLE: | |
case gc_ORPHANED: | |
case gc_DISOWNED: | |
break; | |
default: | |
throw new Error("can't sweep state " + node._state); | |
} | |
} | |
function gc_abort_sweep(node) { | |
// set everything to unstable, kill all derivation caches and disconnect | |
// the graph | |
var doChildren = false; | |
switch (node._type) { | |
case types_ATOM: | |
node._state = gc_STABLE; | |
doChildren = true; | |
break; | |
case types_DERIVATION: | |
case types_LENS: | |
node._state = gc_NEW; | |
node._value = util_unique; | |
doChildren = true; | |
break; | |
case types_REACTION: | |
node._state = gc_STABLE; | |
doChildren = false; | |
break; | |
} | |
if (doChildren) { | |
for (var i = node._children.length; i--;) { | |
gc_abort_sweep(node._children[i]); | |
} | |
node._children = []; | |
} | |
} | |
var parentsStack = []; | |
function parents_capturingParents(f) { | |
var i = parentsStack.length; | |
parentsStack.push([]); | |
try { | |
f(); | |
return parentsStack[i]; | |
} finally { | |
parentsStack.pop(); | |
} | |
} | |
function parents_maybeCaptureParent(p) { | |
if (parentsStack.length > 0) { | |
util_addToArray(parentsStack[parentsStack.length - 1], p); | |
} | |
} | |
var types_ATOM = "ATOM", | |
types_DERIVATION = "DERIVATION", | |
types_LENS = "LENS", | |
types_REACTION = "REACTION"; | |
var RUNNING = 0, | |
COMPLETED = 1, | |
ABORTED = 3; | |
var TransactionAbortion = {}; | |
function abortTransaction() { | |
throw TransactionAbortion; | |
} | |
function transactions_newContext () { | |
return {currentTxn: null}; | |
} | |
function transactions_inTransaction (ctx) { | |
return ctx.currentTxn !== null; | |
} | |
function transactions_currentTransaction (ctx) { | |
return ctx.currentTxn; | |
} | |
function begin (ctx, txn) { | |
txn._parent = ctx.currentTxn; | |
txn._state = RUNNING; | |
ctx.currentTxn = txn; | |
} | |
function popTransaction (ctx, cb) { | |
var txn = ctx.currentTxn; | |
ctx.currentTxn = txn._parent; | |
if (txn._state !== RUNNING) { | |
throw new Error("unexpected state: " + txn._state); | |
} | |
cb(txn); | |
} | |
function commit (ctx) { | |
popTransaction(ctx, function (txn) { | |
txn._state = COMPLETED; | |
txn.onCommit && txn.onCommit(); | |
}); | |
} | |
function abort (ctx) { | |
popTransaction(ctx, function (txn) { | |
txn._state = ABORTED; | |
txn.onAbort && txn.onAbort(); | |
}); | |
} | |
function transactions_transact (ctx, txn, f) { | |
begin(ctx, txn); | |
try { | |
f(abortTransaction); | |
} catch (e) { | |
abort(ctx); | |
if (e !== TransactionAbortion) { | |
throw e; | |
} else { | |
return; | |
} | |
} | |
commit(ctx); | |
} | |
function transactions_ticker (ctx, txnConstructor) { | |
begin(ctx, txnConstructor()); | |
var disposed = false; | |
return { | |
tick: function () { | |
if (disposed) throw new Error("can't tick disposed ticker"); | |
commit(ctx); | |
begin(ctx, txnConstructor()); | |
}, | |
stop: function () { | |
if (disposed) throw new Error("ticker already disposed"); | |
commit(ctx); | |
} | |
} | |
} | |
function reactorBase (parent, control) { | |
var base = { | |
control: control, // the actual object the user gets | |
parent: parent, // the parent derivable | |
parentReactor: null, | |
dependentReactors: [], | |
_state: gc_STABLE, | |
active: false, // whether or not listening for changes in parent | |
_type: types_REACTION, | |
uid: util_nextId(), | |
reacting: false, // whether or not reaction function being invoked | |
yielding: false, // whether or not letting parentReactor react first | |
}; | |
if (util_DEBUG_MODE) { | |
base.stack = Error().stack; | |
} | |
return base; | |
} | |
var cycleMsg = "Cyclical Reactor Dependency! Not allowed!"; | |
function stop (base) { | |
if (base.active) { | |
util_removeFromArray(base.parent._children, base); | |
if (base.parentReactor) { | |
orphan(base); | |
} | |
base.active = false; | |
base.control.onStop && base.control.onStop(); | |
} | |
} | |
var parentReactorStack = []; | |
function start (base) { | |
if (!base.active) { | |
util_addToArray(base.parent._children, base); | |
base.active = true; | |
base.parent._get(); | |
// capture reactor dependency relationships | |
var len = parentReactorStack.length; | |
if (len > 0) { | |
base.parentReactor = parentReactorStack[len - 1]; | |
} | |
base.control.onStart && base.control.onStart(); | |
} | |
} | |
function orphan (base) { | |
if (base.parentReactor) { | |
base.parentReactor = null; | |
} | |
} | |
function adopt (parentBase, childBase) { | |
childBase.parentReactor = parentBase; | |
} | |
function reactors_maybeReact (base) { | |
if (base.yielding) { | |
throw Error(cycleMsg); | |
} | |
if (base.active && base._state === gc_UNSTABLE) { | |
if (base.parentReactor !== null) { | |
try { | |
base.yielding = true; | |
reactors_maybeReact(base.parentReactor); | |
} finally { | |
base.yielding = false; | |
} | |
} | |
// parent might have deactivated this one | |
if (base.active) { | |
var parent = base.parent, parentState = parent._state; | |
if (parentState === gc_UNSTABLE || | |
parentState === gc_ORPHANED || | |
parentState === gc_DISOWNED || | |
parentState === gc_NEW) { | |
parent._get(); | |
} | |
parentState = parent._state; | |
if (parentState === gc_UNCHANGED) { | |
base._state = gc_STABLE; | |
} else if (parentState === gc_CHANGED) { | |
force(base); | |
} else { | |
throw new Error("invalid parent state: " + parentState); | |
} | |
} | |
} | |
} | |
function force (base) { | |
// base.reacting check now in gc_mark; total solution there as opposed to here | |
if (base.control.react) { | |
base._state = gc_STABLE; | |
try { | |
base.reacting = true; | |
parentReactorStack.push(base); | |
if (!util_DEBUG_MODE) { | |
base.control.react(base.parent._get()); | |
} else { | |
try { | |
base.control.react(base.parent._get()); | |
} catch (e) { | |
console.error(base.stack); | |
throw e; | |
} | |
} | |
} finally { | |
parentReactorStack.pop(); | |
base.reacting = false; | |
} | |
} else { | |
throw new Error("No reactor function available."); | |
} | |
} | |
function reactors_Reactor () { | |
/*jshint validthis:true */ | |
this._type = types_REACTION; | |
} | |
function reactors_createBase (control, parent) { | |
if (control._base) { | |
throw new Error("This reactor has already been initialized"); | |
} | |
control._base = reactorBase(parent, control); | |
return control; | |
} | |
util_extend(reactors_Reactor.prototype, { | |
start: function () { | |
start(this._base); | |
return this; | |
}, | |
stop: function () { | |
stop(this._base); | |
return this; | |
}, | |
force: function () { | |
force(this._base); | |
return this; | |
}, | |
isActive: function () { | |
return this._base.active; | |
}, | |
orphan: function () { | |
orphan(this._base); | |
return this; | |
}, | |
adopt: function (child) { | |
if (child._type !== types_REACTION) { | |
throw Error("reactors can only adopt reactors"); | |
} | |
adopt(this._base, child._base); | |
return this; | |
} | |
}); | |
function reactors_StandardReactor (f) { | |
/*jshint validthis:true */ | |
this._type = types_REACTION; | |
this.react = f; | |
} | |
util_extend(reactors_StandardReactor.prototype, reactors_Reactor.prototype); | |
function reactors_anonymousReactor (descriptor) { | |
return util_extend(new reactors_Reactor(), descriptor); | |
} | |
function derivable_createPrototype (D, opts) { | |
var x = { | |
/** | |
* Creates a derived value whose state will always be f applied to this | |
* value | |
*/ | |
derive: function (f, a, b, c, d) { | |
var that = this; | |
switch (arguments.length) { | |
case 0: | |
return that; | |
case 1: | |
switch (typeof f) { | |
case 'function': | |
return D.derivation(function () { | |
return f(that.get()); | |
}); | |
case 'string': | |
case 'number': | |
return D.derivation(function () { | |
return that.get()[D.unpack(f)]; | |
}); | |
default: | |
if (f instanceof Array) { | |
return f.map(function (x) { | |
return that.derive(x); | |
}); | |
} else if (f instanceof RegExp) { | |
return D.derivation(function () { | |
return that.get().match(f); | |
}); | |
} else if (D.isDerivable(f)) { | |
return D.derivation(function () { | |
var deriver = f.get(); | |
var thing = that.get(); | |
switch (typeof deriver) { | |
case 'function': | |
return deriver(thing); | |
case 'string': | |
case 'number': | |
return thing[deriver]; | |
default: | |
if (deriver instanceof RegExp) { | |
return thing.match(deriver); | |
} else { | |
throw Error('type error'); | |
} | |
} | |
return that.get()[D.unpack(f)]; | |
}); | |
} else { | |
throw Error('type error'); | |
} | |
} | |
break; | |
case 2: | |
return D.derivation(function () { | |
return f(that.get(), D.unpack(a)); | |
}); | |
case 3: | |
return D.derivation(function () { | |
return f(that.get(), D.unpack(a), D.unpack(b)); | |
}); | |
case 4: | |
return D.derivation(function () { | |
return f(that.get(), | |
D.unpack(a), | |
D.unpack(b), | |
D.unpack(c)); | |
}); | |
case 5: | |
return D.derivation(function () { | |
return f(that.get(), | |
D.unpack(a), | |
D.unpack(b), | |
D.unpack(c), | |
D.unpack(d)); | |
}); | |
default: | |
var args = ([that]).concat(util_slice(arguments, 1)); | |
return D.derivation(function () { | |
return f.apply(null, args.map(D.unpack)); | |
}); | |
} | |
}, | |
reactor: function (f) { | |
if (typeof f === 'function') { | |
return reactors_createBase(new reactors_StandardReactor(f), this); | |
} else if (f instanceof reactors_Reactor) { | |
return reactors_createBase(f, this); | |
} else if (f && f.react) { | |
return reactors_createBase(reactors_anonymousReactor(f), this); | |
} else { | |
throw new Error("Unrecognized type for reactor " + f); | |
} | |
}, | |
react: function (f, opts) { | |
if (typeof f !== 'function') { | |
throw Error('the first argument to .react must be a function'); | |
} | |
opts = Object.assign({ | |
once: false, | |
from: true, | |
until: false, | |
when: true, | |
skipFirst: false, | |
}, opts); | |
// coerce fn or bool to derivable<bool> | |
function condDerivable(fOrD, name) { | |
if (!D.isDerivable(fOrD)) { | |
if (typeof fOrD === 'function') { | |
fOrD = D.derivation(fOrD); | |
} else if (typeof fOrD === 'boolean') { | |
fOrD = D.atom(fOrD); | |
} else { | |
throw Error('react ' + name + ' condition must be derivable'); | |
} | |
} | |
return fOrD.derive(function (x) { return !!x; }); | |
} | |
// wrap reactor so f doesn't get a .this context, and to allow | |
// stopping after one reaction if desired. | |
var reactor = this.reactor({ | |
react: function (val) { | |
if (opts.skipFirst) { | |
opts.skipFirst = false; | |
} else { | |
f(val); | |
if (opts.once) { | |
this.stop(); | |
controller.stop(); | |
} | |
} | |
}, | |
onStart: opts.onStart, | |
onStop: opts.onStop | |
}); | |
// listen to when and until conditions, starting and stopping the | |
// reactor as appropriate, and stopping this controller when until | |
// condition becomes true | |
var controller = D.struct({ | |
until: condDerivable(opts.until, 'until'), | |
when: condDerivable(opts.when, 'when') | |
}).reactor(function (conds) { | |
if (conds.until) { | |
reactor.stop(); | |
this.stop(); | |
} else if (conds.when) { | |
if (!reactor.isActive()) { | |
reactor.start().force(); | |
} | |
} else if (reactor.isActive()) { | |
reactor.stop(); | |
} | |
}); | |
// listen to from condition, starting the reactor controller | |
// when appropriate | |
condDerivable(opts.from, 'from').reactor(function (from) { | |
if (from) { | |
controller.start().force(); | |
this.stop(); | |
} | |
}).start().force(); | |
}, | |
get: function () { | |
parents_maybeCaptureParent(this); | |
return this._get(); // abstract protected method, in Java parlance | |
}, | |
is: function (other) { | |
return D.lift(opts.equals)(this, other); | |
}, | |
and: function (other) { | |
return this.derive(function (x) {return x && D.unpack(other);}); | |
}, | |
or: function (other) { | |
return this.derive(function (x) {return x || D.unpack(other);}); | |
}, | |
then: function (thenClause, elseClause) { | |
return this.derive(function (x) { | |
return D.unpack(x ? thenClause : elseClause); | |
}); | |
}, | |
mThen: function (thenClause, elseClause) { | |
return this.derive(function (x) { | |
return D.unpack(util_some(x) ? thenClause : elseClause); | |
}); | |
}, | |
mOr: function (other) { | |
return this.mThen(this, other); | |
}, | |
mDerive: function (arg) { | |
if (arguments.length === 1 && arg instanceof Array) { | |
var that = this; | |
return arg.map(function (a) { return that.mDerive(a); }); | |
} else { | |
return this.mThen(this.derive.apply(this, arguments)); | |
} | |
}, | |
mAnd: function (other) { | |
return this.mThen(other, this); | |
}, | |
not: function () { | |
return this.derive(function (x) { return !x; }); | |
}, | |
withEquality: function (equals) { | |
if (equals) { | |
if (typeof equals !== 'function') { | |
throw new Error('equals must be function'); | |
} | |
} else { | |
equals = null; | |
} | |
return util_setEquals(this._clone(), equals); | |
}, | |
}; | |
x.switch = function () { | |
var args = arguments; | |
return this.derive(function (x) { | |
var i; | |
for (i = 0; i < args.length-1; i+=2) { | |
if (opts.equals(x, D.unpack(args[i]))) { | |
return D.unpack(args[i+1]); | |
} | |
} | |
if (i === args.length - 1) { | |
return D.unpack(args[i]); | |
} | |
}); | |
}; | |
return x; | |
} | |
function derivation_createPrototype (D, opts) { | |
return { | |
_clone: function () { | |
return util_setEquals(D.derivation(this._deriver), this._equals); | |
}, | |
_forceGet: function () { | |
var that = this, | |
i; | |
var newParents = parents_capturingParents(function () { | |
var newState; | |
if (!util_DEBUG_MODE) { | |
newState = that._deriver(); | |
} else { | |
try { | |
newState = that._deriver(); | |
} catch (e) { | |
console.error(that._stack); | |
throw e; | |
} | |
} | |
var equals = that._equals || opts.equals; | |
that._state = equals(newState, that._value) ? gc_UNCHANGED : gc_CHANGED; | |
that._value = newState; | |
}); | |
// organise parents | |
for (i = this._parents.length; i--;) { | |
var possiblyFormerParent = this._parents[i]; | |
if (!util_arrayContains(newParents, possiblyFormerParent)) { | |
util_removeFromArray(possiblyFormerParent._children, this); | |
} | |
} | |
this._parents = newParents; | |
// add this as child to new parents | |
for (i = newParents.length; i--;) { | |
util_addToArray(newParents[i]._children, this); | |
} | |
}, | |
_get: function () { | |
var i, parent; | |
outer: switch (this._state) { | |
case gc_NEW: | |
case gc_ORPHANED: | |
this._forceGet(); | |
break; | |
case gc_UNSTABLE: | |
for (i = 0; i < this._parents.length; i++) { | |
parent = this._parents[i]; | |
var parentState = parent._state; | |
if (parentState === gc_UNSTABLE || | |
parentState === gc_ORPHANED || | |
parentState === gc_DISOWNED) { | |
parent._get(); | |
} | |
parentState = parent._state; | |
if (parentState === gc_CHANGED) { | |
this._forceGet(); | |
break outer; | |
} else if (!(parentState === gc_STABLE || | |
parentState === gc_UNCHANGED)) { | |
throw new Error("invalid parent mode: " + parentState); | |
} | |
} | |
this._state = gc_UNCHANGED; | |
break; | |
case gc_DISOWNED: | |
var parents = []; | |
for (i = 0; i < this._parents.length; i++) { | |
var parentStateTuple = this._parents[i], | |
state = parentStateTuple[1]; | |
parent = parentStateTuple[0]; | |
if (!opts.equals(parent._get(), state)) { | |
this._parents = []; | |
this._forceGet(); | |
break outer; | |
} else { | |
parents.push(parent); | |
} | |
} | |
for (i = parents.length; i--;) { | |
util_addToArray(parents[i]._children, this); | |
} | |
this._parents = parents; | |
this._state = gc_UNCHANGED; | |
break; | |
default: | |
// noop | |
} | |
return this._value; | |
} | |
} | |
} | |
function derivation_construct(obj, deriver) { | |
obj._children = []; | |
obj._parents = []; | |
obj._deriver = deriver; | |
obj._state = gc_NEW; | |
obj._type = types_DERIVATION; | |
obj._value = util_unique; | |
obj._equals = null; | |
if (util_DEBUG_MODE) { | |
obj._stack = Error().stack; | |
} | |
return obj; | |
} | |
function mutable_createPrototype (D, _) { | |
return { | |
swap: function (f) { | |
var args = util_slice(arguments, 0); | |
args[0] = this.get(); | |
return this.set(f.apply(null, args)); | |
}, | |
lens: function (monoLensDescriptor) { | |
var that = this; | |
return D.lens({ | |
get: function () { | |
return monoLensDescriptor.get(that.get()); | |
}, | |
set: function (val) { | |
that.set(monoLensDescriptor.set(that.get(), val)); | |
} | |
}); | |
} | |
} | |
} | |
function lens_createPrototype(D, _) { | |
return { | |
_clone: function () { | |
return util_setEquals(D.lens(this._lensDescriptor), this._equals); | |
}, | |
set: function (value) { | |
var that = this; | |
D.atomically(function () { | |
that._lensDescriptor.set(value); | |
}); | |
return this; | |
} | |
} | |
} | |
function lens_construct(derivation, descriptor) { | |
derivation._lensDescriptor = descriptor; | |
derivation._type = types_LENS; | |
return derivation; | |
} | |
function processReactorQueue (rq) { | |
for (var i = rq.length; i--;) { | |
reactors_maybeReact(rq[i]); | |
} | |
} | |
var TXN_CTX = transactions_newContext(); | |
function atom_inTxn () { | |
return transactions_inTransaction(TXN_CTX) | |
} | |
var NOOP_ARRAY = {push: function () {}}; | |
function TransactionState () { | |
this.inTxnValues = {}; | |
this.reactorQueue = []; | |
} | |
function getState (txnState, atom) { | |
var inTxnValue = txnState.inTxnValues[atom._uid]; | |
if (inTxnValue) { | |
return inTxnValue[1]; | |
} else { | |
return atom._value; | |
} | |
} | |
function setState (txnState, atom, state) { | |
txnState.inTxnValues[atom._uid] = [atom, state]; | |
gc_mark(atom, txnState.reactorQueue); | |
} | |
util_extend(TransactionState.prototype, { | |
onCommit: function () { | |
var i, atomValueTuple; | |
var keys = util_keys(this.inTxnValues); | |
if (atom_inTxn()) { | |
// push in-txn vals up to current txn | |
for (i = keys.length; i--;) { | |
atomValueTuple = this.inTxnValues[keys[i]]; | |
atomValueTuple[0].set(atomValueTuple[1]); | |
} | |
} else { | |
// change root state and run reactors. | |
for (i = keys.length; i--;) { | |
atomValueTuple = this.inTxnValues[keys[i]]; | |
atomValueTuple[0]._value = atomValueTuple[1]; | |
gc_mark(atomValueTuple[0], NOOP_ARRAY); | |
} | |
processReactorQueue(this.reactorQueue); | |
// then sweep for a clean finish | |
for (i = keys.length; i--;) { | |
gc_sweep(this.inTxnValues[keys[i]][0]); | |
} | |
} | |
}, | |
onAbort: function () { | |
if (!atom_inTxn()) { | |
var keys = util_keys(this.inTxnValues); | |
for (var i = keys.length; i--;) { | |
gc_abort_sweep(this.inTxnValues[keys[i]][0]); | |
} | |
} | |
} | |
}) | |
function atom_createPrototype (D, opts) { | |
return { | |
_clone: function () { | |
return util_setEquals(D.atom(this._value), this._equals); | |
}, | |
withValidator: function (f) { | |
if (f === null) { | |
return this._clone(); | |
} if (typeof f === 'function') { | |
var result = this._clone(); | |
var existing = this._validator; | |
if (existing) { | |
result._validator = function (x) { return f(x) && existing(x); } | |
} else { | |
result._validator = f; | |
} | |
return result; | |
} else { | |
throw new Error(".withValidator expects function or null"); | |
} | |
}, | |
validate: function () { | |
this._validate(this.get()); | |
}, | |
_validate: function (value) { | |
var validationResult = this._validator && this._validator(value); | |
if (this._validator && validationResult !== true) { | |
throw new Error("Failed validation with value: '" + value + "'." + | |
" Validator returned '" + validationResult + "' "); | |
} | |
}, | |
set: function (value) { | |
this._validate(value); | |
var equals = this._equals || opts.equals; | |
if (!equals(value, this._value)) { | |
this._state = gc_CHANGED; | |
if (atom_inTxn()) { | |
setState(transactions_currentTransaction(TXN_CTX), this, value); | |
} else { | |
this._value = value; | |
var reactorQueue = []; | |
gc_mark(this, reactorQueue); | |
processReactorQueue(reactorQueue); | |
gc_sweep(this); | |
} | |
} | |
return this; | |
}, | |
_get: function () { | |
if (atom_inTxn()) { | |
return getState(transactions_currentTransaction(TXN_CTX), this); | |
} | |
return this._value; | |
} | |
}; | |
} | |
function atom_construct (atom, value) { | |
atom._uid = util_nextId(); | |
atom._children = []; | |
atom._state = gc_STABLE; | |
atom._value = value; | |
atom._type = types_ATOM; | |
atom._equals = null; | |
return atom; | |
} | |
function atom_transact (f) { | |
transactions_transact(TXN_CTX, new TransactionState(), f); | |
} | |
function atom_transaction (f) { | |
return function () { | |
var args = util_slice(arguments, 0); | |
var that = this; | |
var result; | |
atom_transact(function () { | |
result = f.apply(that, args); | |
}); | |
return result; | |
} | |
} | |
var ticker = null; | |
function atom_ticker () { | |
if (ticker) { | |
ticker.refCount++; | |
} else { | |
ticker = transactions_ticker(TXN_CTX, function () { | |
return new TransactionState(); | |
}); | |
ticker.refCount = 1; | |
} | |
var done = false; | |
return { | |
tick: function () { | |
if (done) throw new Error('tyring to use ticker after release'); | |
ticker.tick(); | |
}, | |
release: function () { | |
if (done) throw new Error('ticker already released'); | |
if (--ticker.refCount === 0) { | |
ticker.stop(); | |
ticker = null; | |
} | |
done = true; | |
} | |
}; | |
} | |
var defaultConfig = { equals: util_equals }; | |
function constructModule (config) { | |
config = util_extend({}, defaultConfig, config || {}); | |
var D = { | |
transact: atom_transact, | |
defaultEquals: util_equals, | |
setDebugMode: util_setDebugMode, | |
transaction: atom_transaction, | |
ticker: atom_ticker, | |
Reactor: reactors_Reactor, | |
isAtom: function (x) { | |
return x && (x._type === types_ATOM || x._type === types_LENS); | |
}, | |
isDerivable: function (x) { | |
return x && (x._type === types_ATOM || | |
x._type === types_LENS || | |
x._type === types_DERIVATION); | |
}, | |
isDerivation: function (x) { | |
return x && (x._type === types_DERIVATION || x._type === types_LENS) | |
}, | |
isLensed: function (x) { | |
return x && x._type === types_LENS; | |
}, | |
isReactor: function (x) { | |
return x && x._type === types_REACTION; | |
}, | |
}; | |
var Derivable = derivable_createPrototype(D, config); | |
var Mutable = mutable_createPrototype(D, config); | |
var Atom = util_extend({}, Mutable, Derivable, | |
atom_createPrototype(D, config)); | |
var Derivation = util_extend({}, Derivable, | |
derivation_createPrototype(D, config)); | |
var Lens = util_extend({}, Mutable, Derivation, | |
lens_createPrototype(D, config)); | |
/** | |
* Constructs a new atom whose state is the given value | |
*/ | |
D.atom = function (val) { | |
return atom_construct(Object.create(Atom), val); | |
}; | |
/** | |
* Returns a copy of f which runs atomically | |
*/ | |
D.atomic = function (f) { | |
return function () { | |
var result; | |
var that = this; | |
var args = arguments; | |
D.atomically(function () { | |
result = f.apply(that, args); | |
}); | |
return result; | |
} | |
}; | |
D.atomically = function (f) { | |
if (atom_inTxn()) { | |
f(); | |
} else { | |
D.transact(f); | |
} | |
}; | |
D.derivation = function (f) { | |
return derivation_construct(Object.create(Derivation), f); | |
}; | |
/** | |
* Template string tag for derivable strings | |
*/ | |
D.derive = function (parts) { | |
var args = util_slice(arguments, 1); | |
return D.derivation(function () { | |
var s = ""; | |
for (var i=0; i<parts.length; i++) { | |
s += parts[i]; | |
if (i < args.length) { | |
s += D.unpack(args[i]); | |
} | |
} | |
return s; | |
}); | |
}; | |
/** | |
* creates a new lens | |
*/ | |
D.lens = function (descriptor) { | |
return lens_construct( | |
derivation_construct(Object.create(Lens), descriptor.get), | |
descriptor | |
); | |
}; | |
/** | |
* dereferences a thing if it is dereferencable, otherwise just returns it. | |
*/ | |
D.unpack = function (thing) { | |
if (D.isDerivable(thing)) { | |
return thing.get(); | |
} else { | |
return thing; | |
} | |
}; | |
/** | |
* lifts a non-monadic function to work on derivables | |
*/ | |
D.lift = function (f) { | |
return function () { | |
var args = arguments; | |
var that = this; | |
return D.derivation(function () { | |
return f.apply(that, Array.prototype.map.call(args, D.unpack)); | |
}); | |
} | |
}; | |
function deepUnpack (thing) { | |
if (D.isDerivable(thing)) { | |
return thing.get(); | |
} else if (thing instanceof Array) { | |
return thing.map(deepUnpack); | |
} else if (thing.constructor === Object) { | |
var result = {}; | |
var keys = util_keys(thing); | |
for (var i = keys.length; i--;) { | |
var prop = keys[i]; | |
result[prop] = deepUnpack(thing[prop]); | |
} | |
return result; | |
} else { | |
return thing; | |
} | |
} | |
D.struct = function (arg) { | |
if (arg.constructor === Object || arg instanceof Array) { | |
return D.derivation(function () { | |
return deepUnpack(arg); | |
}); | |
} else { | |
throw new Error("`struct` expects plain Object or Array"); | |
} | |
}; | |
function andOrFn (breakOn) { | |
return function () { | |
var args = arguments; | |
return D.derivation(function () { | |
var val; | |
for (var i = 0; i < args.length; i++) { | |
val = D.unpack(args[i]); | |
if (breakOn(val)) { | |
break; | |
} | |
} | |
return val; | |
}); | |
} | |
} | |
function identity (x) { return x; } | |
function complement (f) { return function (x) { return !f(x); }} | |
D.or = andOrFn(identity); | |
D.mOr = andOrFn(util_some); | |
D.and = andOrFn(complement(identity)); | |
D.mAnd = andOrFn(complement(util_some)); | |
return D; | |
} | |
util_extend(exports, constructModule()); | |
exports.withEquality = function (equals) { | |
return constructModule({equals: equals}); | |
}; | |
exports['default'] = exports; | |
}); | |
//# sourceMappingURL=derivable.js.map | |
},{}]},{},[]) | |
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImRpc3QvZGVyaXZhYmxlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvLyBVTUQgbG9hZGVyXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICBcInVzZSBzdHJpY3RcIjtcbiAgaWYgKGdsb2JhbCAmJiB0eXBlb2YgZ2xvYmFsLmRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGdsb2JhbC5kZWZpbmUuYW1kKSB7XG4gICAgZ2xvYmFsLmRlZmluZShbXCJleHBvcnRzXCJdLCBmYWN0b3J5KTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIGZhY3RvcnkoZXhwb3J0cyk7XG4gIH0gZWxzZSB7XG4gICAgZmFjdG9yeShnbG9iYWwuRGVyaXZhYmxlID0ge30pO1xuICB9XG59KSh0aGlzLCBmdW5jdGlvbiAoZXhwb3J0cykge1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB1dGlsX2tleXMgPSBPYmplY3Qua2V5cztcblxuZnVuY3Rpb24gdXRpbF9leHRlbmQob2JqKSB7XG4gIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIG90aGVyID0gYXJndW1lbnRzW2ldO1xuICAgIHZhciBrZXlzID0gdXRpbF9rZXlzKG90aGVyKTtcbiAgICBmb3IgKHZhciBqID0ga2V5cy5sZW5ndGg7IGotLTspIHtcbiAgICAgIHZhciBwcm9wID0ga2V5c1tqXTtcbiAgICAgIG9ialtwcm9wXSA9IG90aGVyW3Byb3BdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb2JqO1xufVxuXG5mdW5jdGlvbiBfaXMoYSwgYikge1xuICAvLyBTYW1lVmFsdWUgYWxnb3JpdGhtXG4gIGlmIChhID09PSBiKSB7IC8vIFN0ZXBzIDEtNSwgNy0xMFxuICAgIC8vIFN0ZXBzIDYuYi02LmU6ICswICE9IC0wXG4gICAgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT09IDEgLyBiO1xuICB9IGVsc2Uge1xuICAgIC8vIFN0ZXAgNi5hOiBOYU4gPT0gTmFOXG4gICAgcmV0dXJuIGEgIT09IGEgJiYgYiAhPT0gYjtcbiAgfVxufVxuXG5mdW5jdGlvbiB1dGlsX2VxdWFscyAoYSwgYikge1xuICByZXR1cm4gX2lzKGEsIGIpIHx8IChhICYmIHR5cGVvZiBhLmVxdWFscyA9PT0gJ2Z1bmN0aW9uJyAmJiBhLmVxdWFscyhiKSk7XG59XG5cbmZ1bmN0aW9uIHV0aWxfYWRkVG9BcnJheSAoYSwgYikge1xuICB2YXIgaSA9IGEuaW5kZXhPZihiKTtcbiAgaWYgKGkgPCAwKSB7XG4gICAgYS5wdXNoKGIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHV0aWxfcmVtb3ZlRnJvbUFycmF5IChhLCBiKSB7XG4gIHZhciBpID0gYS5pbmRleE9mKGIpO1xuICBpZiAoaSA+PSAwKSB7XG4gICAgYS5zcGxpY2UoaSwgMSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdXRpbF9hcnJheUNvbnRhaW5zIChhLCBiKSB7XG4gIHJldHVybiBhLmluZGV4T2YoYikgPj0gMDtcbn1cblxudmFyIG5leHRJZCA9IDA7XG5mdW5jdGlvbiB1dGlsX25leHRJZCAoKSB7XG4gIHJldHVybiBuZXh0SWQrKztcbn1cblxuZnVuY3Rpb24gdXRpbF9zbGljZSAoYSwgaSkge1xuICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYSwgaSk7XG59XG5cbnZhciB1dGlsX3VuaXF1ZSA9IE9iamVjdC5mcmVlemUoe2VxdWFsczogZnVuY3Rpb24gKCkgeyByZXR1cm4gZmFsc2U7IH19KTtcblxuZnVuY3Rpb24gdXRpbF9zb21lICh4KSB7XG4gIHJldHVybiAoeCAhPT0gbnVsbCkgJiYgKHggIT09IHZvaWQgMCk7XG59XG5cbnZhciB1dGlsX0RFQlVHX01PREUgPSBmYWxzZTtcbmZ1bmN0aW9uIHV0aWxfc2V0RGVidWdNb2RlKHZhbCkge1xuICB1dGlsX0RFQlVHX01PREUgPSAhIXZhbDtcbn1cblxuZnVuY3Rpb24gdXRpbF9zZXRFcXVhbHMoZGVyaXZhYmxlLCBlcXVhbHMpIHtcbiAgZGVyaXZhYmxlLl9lcXVhbHMgPSBlcXVhbHM7XG4gIHJldHVybiBkZXJpdmFibGU7XG59XG5cbi8vIG5vZGUgbW9kZXNcbnZhciBnY19ORVcgPSAwLFxuICAgIGdjX0NIQU5HRUQgPSAxLFxuICAgIGdjX1VOQ0hBTkdFRCA9IDIsXG4gICAgZ2NfT1JQSEFORUQgPSAzLFxuICAgIGdjX1VOU1RBQkxFID0gNCxcbiAgICBnY19TVEFCTEUgPSA1LFxuICAgIGdjX0RJU09XTkVEID0gNjtcblxuZnVuY3Rpb24gZ2NfbWFyayhub2RlLCByZWFjdG9ycykge1xuICAvLyBtYWtlIGV2ZXJ5dGhpbmcgdW5zdGFibGVcbiAgaWYgKG5vZGUuX3R5cGUgPT09IHR5cGVzX1JFQUNUSU9OKSB7XG4gICAgaWYgKG5vZGUucmVhY3RpbmcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkN5Y2xlIGRldGVjdGVkISBEb24ndCBkbyB0aGlzIVwiKTtcbiAgICB9XG4gICAgcmVhY3RvcnMucHVzaChub2RlKTtcbiAgfSBlbHNlIHtcbiAgICBmb3IgKHZhciBpID0gbm9kZS5fY2hpbGRyZW4ubGVuZ3RoOyBpLS07KSB7XG4gICAgICB2YXIgY2hpbGQgPSBub2RlLl9jaGlsZHJlbltpXTtcbiAgICAgIGlmIChjaGlsZC5fc3RhdGUgIT09IGdjX1VOU1RBQkxFKSB7XG4gICAgICAgIGNoaWxkLl9zdGF0ZSA9IGdjX1VOU1RBQkxFO1xuICAgICAgICBnY19tYXJrKGNoaWxkLCByZWFjdG9ycyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdjX3N3ZWVwKG5vZGUpIHtcbiAgdmFyIGk7XG4gIHN3aXRjaCAobm9kZS5fc3RhdGUpIHtcbiAgY2FzZSBnY19DSEFOR0VEOlxuICBjYXNlIGdjX1VOQ0hBTkdFRDpcbiAgICAvLyBjaGFuZ2VkIG9yIHVuY2hhbmdlZCBtZWFucyB0aGUgbm9kZSB3YXMgdmlzaXRlZFxuICAgIC8vIGR1cmluZyB0aGUgcmVhY3QgcGhhc2UsIHdoaWNoIG1lYW5zIHdlIGtlZXAgaXQgaW5cbiAgICAvLyB0aGUgZ3JhcGggZm9yIHRoZSBuZXh0IGdvIHJvdW5kXG4gICAgZm9yIChpID0gbm9kZS5fY2hpbGRyZW4ubGVuZ3RoOyBpLS07KSB7XG4gICAgICB2YXIgY2hpbGQgPSBub2RlLl9jaGlsZHJlbltpXTtcbiAgICAgIGdjX3N3ZWVwKGNoaWxkKTtcbiAgICAgIGlmIChjaGlsZC5fc3RhdGUgIT09IGdjX1NUQUJMRSkge1xuICAgICAgICBub2RlLl9jaGlsZHJlbi5zcGxpY2UoaSwgMSk7XG4gICAgICB9XG4gICAgfVxuICAgIG5vZGUuX3N0YXRlID0gZ2NfU1RBQkxFO1xuICAgIGJyZWFrO1xuICBjYXNlIGdjX1VOU1RBQkxFOlxuICAgIGlmIChub2RlLl90eXBlID09PSB0eXBlc19SRUFDVElPTikge1xuICAgICAgLy8gb25seSBoYXBwZW5zIHdoZW4gcmVhY3Rpb24gY3JlYXRlZCBpbiB0cmFuc2FjdGlvbi4gc2VlIGlzc3VlICMxNFxuICAgICAgbm9kZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHVuc3RhYmxlIG1lYW5zIHRoZSBub2RlIHdhcyBub3QgdmlzaXRlZCBkdXJpbmdcbiAgICAgIC8vIHRoZSByZWFjdCBwaGFzZSwgd2hpY2ggbWVhbnMgd2Uga2ljayBpdCBvdXQgb2YgdGhlXG4gICAgICAvLyBncmFwaC5cblxuICAgICAgLy8gYnV0IGZpcnN0IHdlIGNoZWNrIGlmIGFsbCBvZiBpdHMgcGFyZW50cyB3ZXJlIHVuY2hhbmdlZFxuICAgICAgLy8gaWYgc28sIHdlIGNhbiBhdm9pZCByZWNhbGN1bGF0aW5nIGl0IGluIGZ1dHVyZSBieVxuICAgICAgLy8gY2FjaGluZyBpdHMgcGFyZW50cycgY3VycmVudCB2YWx1ZXMuXG4gICAgICB2YXIgc3Rhc2hlZFBhcmVudFN0YXRlcyA9IFtdO1xuICAgICAgZm9yIChpID0gbm9kZS5fcGFyZW50cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IG5vZGUuX3BhcmVudHNbaV07XG4gICAgICAgIGlmIChwYXJlbnQuX3N0YXRlICE9PSBnY19VTkNIQU5HRUQpIHtcbiAgICAgICAgICAvLyBub3BlLCBpdHMgcGFyZW50cyBlaXRoZXIgaGF2ZSBjaGFuZ2VkIG9yIHdlcmVuJ3QgdmlzaXRlZCxcbiAgICAgICAgICAvLyBzbyB3ZSBoYXZlIHRvIG9ycGhhbiB0aGlzIG5vZGVcbiAgICAgICAgICBub2RlLl9zdGF0ZSA9IGdjX09SUEhBTkVEO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHN0YXNoZWRQYXJlbnRTdGF0ZXMucHVzaChbcGFyZW50LCBwYXJlbnQuX3ZhbHVlXSk7XG4gICAgICB9XG4gICAgICBpZiAobm9kZS5fc3RhdGUgIT09IGdjX09SUEhBTkVEKSB7XG4gICAgICAgIG5vZGUuX3N0YXRlID0gZ2NfRElTT1dORUQ7XG4gICAgICAgIG5vZGUuX3BhcmVudHMgPSBzdGFzaGVkUGFyZW50U3RhdGVzO1xuICAgICAgfVxuICAgIH1cbiAgICBicmVhaztcbiAgY2FzZSBnY19TVEFCTEU6XG4gIGNhc2UgZ2NfT1JQSEFORUQ6XG4gIGNhc2UgZ2NfRElTT1dORUQ6XG4gICAgYnJlYWs7XG4gIGRlZmF1bHQ6XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY2FuJ3Qgc3dlZXAgc3RhdGUgXCIgKyBub2RlLl9zdGF0ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2NfYWJvcnRfc3dlZXAobm9kZSkge1xuICAvLyBzZXQgZXZlcnl0aGluZyB0byB1bnN0YWJsZSwga2lsbCBhbGwgZGVyaXZhdGlvbiBjYWNoZXMgYW5kIGRpc2Nvbm5lY3RcbiAgLy8gdGhlIGdyYXBoXG4gIHZhciBkb0NoaWxkcmVuID0gZmFsc2U7XG4gIHN3aXRjaCAobm9kZS5fdHlwZSkge1xuICBjYXNlIHR5cGVzX0FUT006XG4gICAgbm9kZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgZG9DaGlsZHJlbiA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgdHlwZXNfREVSSVZBVElPTjpcbiAgY2FzZSB0eXBlc19MRU5TOlxuICAgIG5vZGUuX3N0YXRlID0gZ2NfTkVXO1xuICAgIG5vZGUuX3ZhbHVlID0gdXRpbF91bmlxdWU7XG4gICAgZG9DaGlsZHJlbiA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgdHlwZXNfUkVBQ1RJT046XG4gICAgbm9kZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgZG9DaGlsZHJlbiA9IGZhbHNlO1xuICAgIGJyZWFrO1xuICB9XG4gIGlmIChkb0NoaWxkcmVuKSB7XG4gICAgZm9yICh2YXIgaSA9IG5vZGUuX2NoaWxkcmVuLmxlbmd0aDsgaS0tOykge1xuICAgICAgZ2NfYWJvcnRfc3dlZXAobm9kZS5fY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgICBub2RlLl9jaGlsZHJlbiA9IFtdO1xuICB9XG59XG5cbnZhciBwYXJlbnRzU3RhY2sgPSBbXTtcblxuZnVuY3Rpb24gcGFyZW50c19jYXB0dXJpbmdQYXJlbnRzKGYpIHtcbiAgdmFyIGkgPSBwYXJlbnRzU3RhY2subGVuZ3RoO1xuICBwYXJlbnRzU3RhY2sucHVzaChbXSk7XG4gIHRyeSB7XG4gICAgZigpO1xuICAgIHJldHVybiBwYXJlbnRzU3RhY2tbaV07XG4gIH0gZmluYWxseSB7XG4gICAgcGFyZW50c1N0YWNrLnBvcCgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcmVudHNfbWF5YmVDYXB0dXJlUGFyZW50KHApIHtcbiAgaWYgKHBhcmVudHNTdGFjay5sZW5ndGggPiAwKSB7XG4gICAgdXRpbF9hZGRUb0FycmF5KHBhcmVudHNTdGFja1twYXJlbnRzU3RhY2subGVuZ3RoIC0gMV0sIHApO1xuICB9XG59XG5cbnZhciB0eXBlc19BVE9NID0gXCJBVE9NXCIsXG4gICAgdHlwZXNfREVSSVZBVElPTiA9IFwiREVSSVZBVElPTlwiLFxuICAgIHR5cGVzX0xFTlMgPSBcIkxFTlNcIixcbiAgICB0eXBlc19SRUFDVElPTiA9IFwiUkVBQ1RJT05cIjtcblxudmFyIFJVTk5JTkcgPSAwLFxuICAgIENPTVBMRVRFRCA9IDEsXG4gICAgQUJPUlRFRCA9IDM7XG5cbnZhciBUcmFuc2FjdGlvbkFib3J0aW9uID0ge307XG5cbmZ1bmN0aW9uIGFib3J0VHJhbnNhY3Rpb24oKSB7XG4gIHRocm93IFRyYW5zYWN0aW9uQWJvcnRpb247XG59XG5cbmZ1bmN0aW9uIHRyYW5zYWN0aW9uc19uZXdDb250ZXh0ICgpIHtcbiAgcmV0dXJuIHtjdXJyZW50VHhuOiBudWxsfTtcbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25zX2luVHJhbnNhY3Rpb24gKGN0eCkge1xuICByZXR1cm4gY3R4LmN1cnJlbnRUeG4gIT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIHRyYW5zYWN0aW9uc19jdXJyZW50VHJhbnNhY3Rpb24gKGN0eCkge1xuICByZXR1cm4gY3R4LmN1cnJlbnRUeG47XG59XG5cbmZ1bmN0aW9uIGJlZ2luIChjdHgsIHR4bikge1xuICB0eG4uX3BhcmVudCA9IGN0eC5jdXJyZW50VHhuO1xuICB0eG4uX3N0YXRlID0gUlVOTklORztcbiAgY3R4LmN1cnJlbnRUeG4gPSB0eG47XG59XG5cbmZ1bmN0aW9uIHBvcFRyYW5zYWN0aW9uIChjdHgsIGNiKSB7XG4gIHZhciB0eG4gPSBjdHguY3VycmVudFR4bjtcbiAgY3R4LmN1cnJlbnRUeG4gPSB0eG4uX3BhcmVudDtcbiAgaWYgKHR4bi5fc3RhdGUgIT09IFJVTk5JTkcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1bmV4cGVjdGVkIHN0YXRlOiBcIiArIHR4bi5fc3RhdGUpO1xuICB9XG4gIGNiKHR4bik7XG59XG5cbmZ1bmN0aW9uIGNvbW1pdCAoY3R4KSB7XG4gIHBvcFRyYW5zYWN0aW9uKGN0eCwgZnVuY3Rpb24gKHR4bikge1xuICAgIHR4bi5fc3RhdGUgPSBDT01QTEVURUQ7XG4gICAgdHhuLm9uQ29tbWl0ICYmIHR4bi5vbkNvbW1pdCgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gYWJvcnQgKGN0eCkge1xuICBwb3BUcmFuc2FjdGlvbihjdHgsIGZ1bmN0aW9uICh0eG4pIHtcbiAgICB0eG4uX3N0YXRlID0gQUJPUlRFRDtcbiAgICB0eG4ub25BYm9ydCAmJiB0eG4ub25BYm9ydCgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25zX3RyYW5zYWN0IChjdHgsIHR4biwgZikge1xuICBiZWdpbihjdHgsIHR4bik7XG4gIHRyeSB7XG4gICAgZihhYm9ydFRyYW5zYWN0aW9uKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGFib3J0KGN0eCk7XG4gICAgaWYgKGUgIT09IFRyYW5zYWN0aW9uQWJvcnRpb24pIHtcbiAgICAgIHRocm93IGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cbiAgY29tbWl0KGN0eCk7XG59XG5cbmZ1bmN0aW9uIHRyYW5zYWN0aW9uc190aWNrZXIgKGN0eCwgdHhuQ29uc3RydWN0b3IpIHtcbiAgYmVnaW4oY3R4LCB0eG5Db25zdHJ1Y3RvcigpKTtcbiAgdmFyIGRpc3Bvc2VkID0gZmFsc2U7XG4gIHJldHVybiB7XG4gICAgdGljazogZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGRpc3Bvc2VkKSB0aHJvdyBuZXcgRXJyb3IoXCJjYW4ndCB0aWNrIGRpc3Bvc2VkIHRpY2tlclwiKTtcbiAgICAgIGNvbW1pdChjdHgpO1xuICAgICAgYmVnaW4oY3R4LCB0eG5Db25zdHJ1Y3RvcigpKTtcbiAgICB9LFxuICAgIHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChkaXNwb3NlZCkgdGhyb3cgbmV3IEVycm9yKFwidGlja2VyIGFscmVhZHkgZGlzcG9zZWRcIik7XG4gICAgICBjb21taXQoY3R4KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVhY3RvckJhc2UgKHBhcmVudCwgY29udHJvbCkge1xuICB2YXIgYmFzZSA9IHtcbiAgICBjb250cm9sOiBjb250cm9sLCAgICAgIC8vIHRoZSBhY3R1YWwgb2JqZWN0IHRoZSB1c2VyIGdldHNcbiAgICBwYXJlbnQ6IHBhcmVudCwgICAgICAgIC8vIHRoZSBwYXJlbnQgZGVyaXZhYmxlXG4gICAgcGFyZW50UmVhY3RvcjogbnVsbCxcbiAgICBkZXBlbmRlbnRSZWFjdG9yczogW10sXG4gICAgX3N0YXRlOiBnY19TVEFCTEUsXG4gICAgYWN0aXZlOiBmYWxzZSwgICAgICAgICAvLyB3aGV0aGVyIG9yIG5vdCBsaXN0ZW5pbmcgZm9yIGNoYW5nZXMgaW4gcGFyZW50XG4gICAgX3R5cGU6IHR5cGVzX1JFQUNUSU9OLFxuICAgIHVpZDogdXRpbF9uZXh0SWQoKSxcbiAgICByZWFjdGluZzogZmFsc2UsICAgICAgIC8vIHdoZXRoZXIgb3Igbm90IHJlYWN0aW9uIGZ1bmN0aW9uIGJlaW5nIGludm9rZWRcbiAgICB5aWVsZGluZzogZmFsc2UsICAgICAgIC8vIHdoZXRoZXIgb3Igbm90IGxldHRpbmcgcGFyZW50UmVhY3RvciByZWFjdCBmaXJzdFxuICB9O1xuICBpZiAodXRpbF9ERUJVR19NT0RFKSB7XG4gICAgYmFzZS5zdGFjayA9IEVycm9yKCkuc3RhY2s7XG4gIH1cbiAgcmV0dXJuIGJhc2U7XG59XG52YXIgY3ljbGVNc2cgPSBcIkN5Y2xpY2FsIFJlYWN0b3IgRGVwZW5kZW5jeSEgTm90IGFsbG93ZWQhXCI7XG5cbmZ1bmN0aW9uIHN0b3AgKGJhc2UpIHtcbiAgaWYgKGJhc2UuYWN0aXZlKSB7XG4gICAgdXRpbF9yZW1vdmVGcm9tQXJyYXkoYmFzZS5wYXJlbnQuX2NoaWxkcmVuLCBiYXNlKTtcbiAgICBpZiAoYmFzZS5wYXJlbnRSZWFjdG9yKSB7XG4gICAgICBvcnBoYW4oYmFzZSk7XG4gICAgfVxuICAgIGJhc2UuYWN0aXZlID0gZmFsc2U7XG4gICAgYmFzZS5jb250cm9sLm9uU3RvcCAmJiBiYXNlLmNvbnRyb2wub25TdG9wKCk7XG4gIH1cbn1cblxudmFyIHBhcmVudFJlYWN0b3JTdGFjayA9IFtdO1xuXG5mdW5jdGlvbiBzdGFydCAoYmFzZSkge1xuICBpZiAoIWJhc2UuYWN0aXZlKSB7XG4gICAgdXRpbF9hZGRUb0FycmF5KGJhc2UucGFyZW50Ll9jaGlsZHJlbiwgYmFzZSk7XG4gICAgYmFzZS5hY3RpdmUgPSB0cnVlO1xuICAgIGJhc2UucGFyZW50Ll9nZXQoKTtcbiAgICAvLyBjYXB0dXJlIHJlYWN0b3IgZGVwZW5kZW5jeSByZWxhdGlvbnNoaXBzXG4gICAgdmFyIGxlbiA9IHBhcmVudFJlYWN0b3JTdGFjay5sZW5ndGg7XG4gICAgaWYgKGxlbiA+IDApIHtcbiAgICAgIGJhc2UucGFyZW50UmVhY3RvciA9IHBhcmVudFJlYWN0b3JTdGFja1tsZW4gLSAxXTtcbiAgICB9XG5cbiAgICBiYXNlLmNvbnRyb2wub25TdGFydCAmJiBiYXNlLmNvbnRyb2wub25TdGFydCgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG9ycGhhbiAoYmFzZSkge1xuICBpZiAoYmFzZS5wYXJlbnRSZWFjdG9yKSB7XG4gICAgYmFzZS5wYXJlbnRSZWFjdG9yID0gbnVsbDtcbiAgfVxufVxuXG5mdW5jdGlvbiBhZG9wdCAocGFyZW50QmFzZSwgY2hpbGRCYXNlKSB7XG4gIGNoaWxkQmFzZS5wYXJlbnRSZWFjdG9yID0gcGFyZW50QmFzZTtcbn1cblxuZnVuY3Rpb24gcmVhY3RvcnNfbWF5YmVSZWFjdCAoYmFzZSkge1xuICBpZiAoYmFzZS55aWVsZGluZykge1xuICAgIHRocm93IEVycm9yKGN5Y2xlTXNnKTtcbiAgfVxuICBpZiAoYmFzZS5hY3RpdmUgJiYgYmFzZS5fc3RhdGUgPT09IGdjX1VOU1RBQkxFKSB7XG4gICAgaWYgKGJhc2UucGFyZW50UmVhY3RvciAhPT0gbnVsbCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYmFzZS55aWVsZGluZyA9IHRydWU7XG4gICAgICAgIHJlYWN0b3JzX21heWJlUmVhY3QoYmFzZS5wYXJlbnRSZWFjdG9yKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGJhc2UueWllbGRpbmcgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gcGFyZW50IG1pZ2h0IGhhdmUgZGVhY3RpdmF0ZWQgdGhpcyBvbmVcbiAgICBpZiAoYmFzZS5hY3RpdmUpIHtcbiAgICAgIHZhciBwYXJlbnQgPSBiYXNlLnBhcmVudCwgcGFyZW50U3RhdGUgPSBwYXJlbnQuX3N0YXRlO1xuICAgICAgaWYgKHBhcmVudFN0YXRlID09PSBnY19VTlNUQUJMRSB8fFxuICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19PUlBIQU5FRCB8fFxuICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19ESVNPV05FRCB8fFxuICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19ORVcpIHtcbiAgICAgICAgcGFyZW50Ll9nZXQoKTtcbiAgICAgIH1cbiAgICAgIHBhcmVudFN0YXRlID0gcGFyZW50Ll9zdGF0ZTtcblxuICAgICAgaWYgKHBhcmVudFN0YXRlID09PSBnY19VTkNIQU5HRUQpIHtcbiAgICAgICAgYmFzZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgICB9IGVsc2UgaWYgKHBhcmVudFN0YXRlID09PSBnY19DSEFOR0VEKSB7XG4gICAgICAgIGZvcmNlKGJhc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBhcmVudCBzdGF0ZTogXCIgKyBwYXJlbnRTdGF0ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZvcmNlIChiYXNlKSB7XG4gIC8vIGJhc2UucmVhY3RpbmcgY2hlY2sgbm93IGluIGdjX21hcms7IHRvdGFsIHNvbHV0aW9uIHRoZXJlIGFzIG9wcG9zZWQgdG8gaGVyZVxuICBpZiAoYmFzZS5jb250cm9sLnJlYWN0KSB7XG4gICAgYmFzZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgdHJ5IHtcbiAgICAgIGJhc2UucmVhY3RpbmcgPSB0cnVlO1xuICAgICAgcGFyZW50UmVhY3RvclN0YWNrLnB1c2goYmFzZSk7XG4gICAgICBpZiAoIXV0aWxfREVCVUdfTU9ERSkge1xuICAgICAgICBiYXNlLmNvbnRyb2wucmVhY3QoYmFzZS5wYXJlbnQuX2dldCgpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYmFzZS5jb250cm9sLnJlYWN0KGJhc2UucGFyZW50Ll9nZXQoKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGJhc2Uuc3RhY2spO1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgcGFyZW50UmVhY3RvclN0YWNrLnBvcCgpO1xuICAgICAgYmFzZS5yZWFjdGluZyA9IGZhbHNlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIHJlYWN0b3IgZnVuY3Rpb24gYXZhaWxhYmxlLlwiKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZWFjdG9yc19SZWFjdG9yICgpIHtcbiAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cbiAgdGhpcy5fdHlwZSA9IHR5cGVzX1JFQUNUSU9OO1xufVxuXG5mdW5jdGlvbiByZWFjdG9yc19jcmVhdGVCYXNlIChjb250cm9sLCBwYXJlbnQpIHtcbiAgaWYgKGNvbnRyb2wuX2Jhc2UpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIHJlYWN0b3IgaGFzIGFscmVhZHkgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgfVxuICBjb250cm9sLl9iYXNlID0gcmVhY3RvckJhc2UocGFyZW50LCBjb250cm9sKTtcbiAgcmV0dXJuIGNvbnRyb2w7XG59XG5cbnV0aWxfZXh0ZW5kKHJlYWN0b3JzX1JlYWN0b3IucHJvdG90eXBlLCB7XG4gIHN0YXJ0OiBmdW5jdGlvbiAoKSB7XG4gICAgc3RhcnQodGhpcy5fYmFzZSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgICBzdG9wKHRoaXMuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBmb3JjZTogZnVuY3Rpb24gKCkge1xuICAgIGZvcmNlKHRoaXMuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBpc0FjdGl2ZTogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9iYXNlLmFjdGl2ZTtcbiAgfSxcbiAgb3JwaGFuOiBmdW5jdGlvbiAoKSB7XG4gICAgb3JwaGFuKHRoaXMuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBhZG9wdDogZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgaWYgKGNoaWxkLl90eXBlICE9PSB0eXBlc19SRUFDVElPTikge1xuICAgICAgdGhyb3cgRXJyb3IoXCJyZWFjdG9ycyBjYW4gb25seSBhZG9wdCByZWFjdG9yc1wiKTtcbiAgICB9XG4gICAgYWRvcHQodGhpcy5fYmFzZSwgY2hpbGQuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG59KTtcblxuZnVuY3Rpb24gcmVhY3RvcnNfU3RhbmRhcmRSZWFjdG9yIChmKSB7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIHRoaXMuX3R5cGUgPSB0eXBlc19SRUFDVElPTjtcbiAgdGhpcy5yZWFjdCA9IGY7XG59XG5cbnV0aWxfZXh0ZW5kKHJlYWN0b3JzX1N0YW5kYXJkUmVhY3Rvci5wcm90b3R5cGUsIHJlYWN0b3JzX1JlYWN0b3IucHJvdG90eXBlKTtcblxuZnVuY3Rpb24gcmVhY3RvcnNfYW5vbnltb3VzUmVhY3RvciAoZGVzY3JpcHRvcikge1xuICByZXR1cm4gdXRpbF9leHRlbmQobmV3IHJlYWN0b3JzX1JlYWN0b3IoKSwgZGVzY3JpcHRvcik7XG59XG5cbmZ1bmN0aW9uIGRlcml2YWJsZV9jcmVhdGVQcm90b3R5cGUgKEQsIG9wdHMpIHtcbiAgdmFyIHggPSB7XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlcml2ZWQgdmFsdWUgd2hvc2Ugc3RhdGUgd2lsbCBhbHdheXMgYmUgZiBhcHBsaWVkIHRvIHRoaXNcbiAgICAgKiB2YWx1ZVxuICAgICAqL1xuICAgIGRlcml2ZTogZnVuY3Rpb24gKGYsIGEsIGIsIGMsIGQpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhhdDtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgc3dpdGNoICh0eXBlb2YgZikge1xuICAgICAgICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgICAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gdGhhdC5nZXQoKVtELnVucGFjayhmKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgaWYgKGYgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgICByZXR1cm4gZi5tYXAoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5kZXJpdmUoeCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmdldCgpLm1hdGNoKGYpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoRC5pc0Rlcml2YWJsZShmKSkge1xuICAgICAgICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVyaXZlciA9IGYuZ2V0KCk7XG4gICAgICAgICAgICAgICAgdmFyIHRoaW5nID0gdGhhdC5nZXQoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGVvZiBkZXJpdmVyKSB7XG4gICAgICAgICAgICAgICAgICBjYXNlICdmdW5jdGlvbic6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkZXJpdmVyKHRoaW5nKTtcbiAgICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgICAgICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpbmdbZGVyaXZlcl07XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoZGVyaXZlciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGluZy5tYXRjaChkZXJpdmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcigndHlwZSBlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmdldCgpW0QudW5wYWNrKGYpXTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBFcnJvcigndHlwZSBlcnJvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpLCBELnVucGFjayhhKSk7XG4gICAgICAgIH0pO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpLCBELnVucGFjayhhKSwgRC51bnBhY2soYikpO1xuICAgICAgICB9KTtcbiAgICAgIGNhc2UgNDpcbiAgICAgICAgcmV0dXJuIEQuZGVyaXZhdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIGYodGhhdC5nZXQoKSxcbiAgICAgICAgICAgICAgICAgICBELnVucGFjayhhKSxcbiAgICAgICAgICAgICAgICAgICBELnVucGFjayhiKSxcbiAgICAgICAgICAgICAgICAgICBELnVucGFjayhjKSk7XG4gICAgICAgIH0pO1xuICAgICAgY2FzZSA1OlxuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGEpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGIpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGMpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGQpKTtcbiAgICAgICAgfSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgYXJncyA9IChbdGhhdF0pLmNvbmNhdCh1dGlsX3NsaWNlKGFyZ3VtZW50cywgMSkpO1xuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZi5hcHBseShudWxsLCBhcmdzLm1hcChELnVucGFjaykpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG5cblxuICAgIHJlYWN0b3I6IGZ1bmN0aW9uIChmKSB7XG4gICAgICBpZiAodHlwZW9mIGYgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHJlYWN0b3JzX2NyZWF0ZUJhc2UobmV3IHJlYWN0b3JzX1N0YW5kYXJkUmVhY3RvcihmKSwgdGhpcyk7XG4gICAgICB9IGVsc2UgaWYgKGYgaW5zdGFuY2VvZiByZWFjdG9yc19SZWFjdG9yKSB7XG4gICAgICAgIHJldHVybiByZWFjdG9yc19jcmVhdGVCYXNlKGYsIHRoaXMpO1xuICAgICAgfSBlbHNlIGlmIChmICYmIGYucmVhY3QpIHtcbiAgICAgICAgcmV0dXJuIHJlYWN0b3JzX2NyZWF0ZUJhc2UocmVhY3RvcnNfYW5vbnltb3VzUmVhY3RvcihmKSwgdGhpcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbnJlY29nbml6ZWQgdHlwZSBmb3IgcmVhY3RvciBcIiArIGYpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICByZWFjdDogZnVuY3Rpb24gKGYsIG9wdHMpIHtcbiAgICAgIGlmICh0eXBlb2YgZiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBFcnJvcigndGhlIGZpcnN0IGFyZ3VtZW50IHRvIC5yZWFjdCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgIH1cblxuICAgICAgb3B0cyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBvbmNlOiBmYWxzZSxcbiAgICAgICAgZnJvbTogdHJ1ZSxcbiAgICAgICAgdW50aWw6IGZhbHNlLFxuICAgICAgICB3aGVuOiB0cnVlLFxuICAgICAgICBza2lwRmlyc3Q6IGZhbHNlLFxuICAgICAgfSwgb3B0cyk7XG5cbiAgICAgIC8vIGNvZXJjZSBmbiBvciBib29sIHRvIGRlcml2YWJsZTxib29sPlxuICAgICAgZnVuY3Rpb24gY29uZERlcml2YWJsZShmT3JELCBuYW1lKSB7XG4gICAgICAgIGlmICghRC5pc0Rlcml2YWJsZShmT3JEKSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZk9yRCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgZk9yRCA9IEQuZGVyaXZhdGlvbihmT3JEKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmT3JEID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIGZPckQgPSBELmF0b20oZk9yRCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdyZWFjdCAnICsgbmFtZSArICcgY29uZGl0aW9uIG11c3QgYmUgZGVyaXZhYmxlJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmT3JELmRlcml2ZShmdW5jdGlvbiAoeCkgeyByZXR1cm4gISF4OyB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gd3JhcCByZWFjdG9yIHNvIGYgZG9lc24ndCBnZXQgYSAudGhpcyBjb250ZXh0LCBhbmQgdG8gYWxsb3dcbiAgICAgIC8vIHN0b3BwaW5nIGFmdGVyIG9uZSByZWFjdGlvbiBpZiBkZXNpcmVkLlxuICAgICAgdmFyIHJlYWN0b3IgPSB0aGlzLnJlYWN0b3Ioe1xuICAgICAgICByZWFjdDogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICAgIGlmIChvcHRzLnNraXBGaXJzdCkge1xuICAgICAgICAgICAgb3B0cy5za2lwRmlyc3QgPSBmYWxzZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZih2YWwpO1xuICAgICAgICAgICAgaWYgKG9wdHMub25jZSkge1xuICAgICAgICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgICAgICAgY29udHJvbGxlci5zdG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvblN0YXJ0OiBvcHRzLm9uU3RhcnQsXG4gICAgICAgIG9uU3RvcDogb3B0cy5vblN0b3BcbiAgICAgIH0pO1xuXG4gICAgICAvLyBsaXN0ZW4gdG8gd2hlbiBhbmQgdW50aWwgY29uZGl0aW9ucywgc3RhcnRpbmcgYW5kIHN0b3BwaW5nIHRoZVxuICAgICAgLy8gcmVhY3RvciBhcyBhcHByb3ByaWF0ZSwgYW5kIHN0b3BwaW5nIHRoaXMgY29udHJvbGxlciB3aGVuIHVudGlsXG4gICAgICAvLyBjb25kaXRpb24gYmVjb21lcyB0cnVlXG4gICAgICB2YXIgY29udHJvbGxlciA9IEQuc3RydWN0KHtcbiAgICAgICAgdW50aWw6IGNvbmREZXJpdmFibGUob3B0cy51bnRpbCwgJ3VudGlsJyksXG4gICAgICAgIHdoZW46IGNvbmREZXJpdmFibGUob3B0cy53aGVuLCAnd2hlbicpXG4gICAgICB9KS5yZWFjdG9yKGZ1bmN0aW9uIChjb25kcykge1xuICAgICAgICBpZiAoY29uZHMudW50aWwpIHtcbiAgICAgICAgICByZWFjdG9yLnN0b3AoKTtcbiAgICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb25kcy53aGVuKSB7XG4gICAgICAgICAgaWYgKCFyZWFjdG9yLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgICAgIHJlYWN0b3Iuc3RhcnQoKS5mb3JjZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChyZWFjdG9yLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgICByZWFjdG9yLnN0b3AoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIGxpc3RlbiB0byBmcm9tIGNvbmRpdGlvbiwgc3RhcnRpbmcgdGhlIHJlYWN0b3IgY29udHJvbGxlclxuICAgICAgLy8gd2hlbiBhcHByb3ByaWF0ZVxuICAgICAgY29uZERlcml2YWJsZShvcHRzLmZyb20sICdmcm9tJykucmVhY3RvcihmdW5jdGlvbiAoZnJvbSkge1xuICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgIGNvbnRyb2xsZXIuc3RhcnQoKS5mb3JjZSgpO1xuICAgICAgICAgIHRoaXMuc3RvcCgpO1xuICAgICAgICB9XG4gICAgICB9KS5zdGFydCgpLmZvcmNlKCk7XG4gICAgfSxcblxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcGFyZW50c19tYXliZUNhcHR1cmVQYXJlbnQodGhpcyk7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0KCk7IC8vIGFic3RyYWN0IHByb3RlY3RlZCBtZXRob2QsIGluIEphdmEgcGFybGFuY2VcbiAgICB9LFxuXG4gICAgaXM6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIEQubGlmdChvcHRzLmVxdWFscykodGhpcywgb3RoZXIpO1xuICAgIH0sXG5cbiAgICBhbmQ6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIHRoaXMuZGVyaXZlKGZ1bmN0aW9uICh4KSB7cmV0dXJuIHggJiYgRC51bnBhY2sob3RoZXIpO30pO1xuICAgIH0sXG5cbiAgICBvcjogZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXJpdmUoZnVuY3Rpb24gKHgpIHtyZXR1cm4geCB8fCBELnVucGFjayhvdGhlcik7fSk7XG4gICAgfSxcblxuICAgIHRoZW46IGZ1bmN0aW9uICh0aGVuQ2xhdXNlLCBlbHNlQ2xhdXNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXJpdmUoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgcmV0dXJuIEQudW5wYWNrKHggPyB0aGVuQ2xhdXNlIDogZWxzZUNsYXVzZSk7XG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgbVRoZW46IGZ1bmN0aW9uICh0aGVuQ2xhdXNlLCBlbHNlQ2xhdXNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXJpdmUoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgcmV0dXJuIEQudW5wYWNrKHV0aWxfc29tZSh4KSA/IHRoZW5DbGF1c2UgOiBlbHNlQ2xhdXNlKTtcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBtT3I6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIHRoaXMubVRoZW4odGhpcywgb3RoZXIpO1xuICAgIH0sXG5cbiAgICBtRGVyaXZlOiBmdW5jdGlvbiAoYXJnKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSAmJiBhcmcgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgIHJldHVybiBhcmcubWFwKGZ1bmN0aW9uIChhKSB7IHJldHVybiB0aGF0Lm1EZXJpdmUoYSk7IH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubVRoZW4odGhpcy5kZXJpdmUuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIG1BbmQ6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIHRoaXMubVRoZW4ob3RoZXIsIHRoaXMpO1xuICAgIH0sXG5cbiAgICBub3Q6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlcml2ZShmdW5jdGlvbiAoeCkgeyByZXR1cm4gIXg7IH0pO1xuICAgIH0sXG5cbiAgICB3aXRoRXF1YWxpdHk6IGZ1bmN0aW9uIChlcXVhbHMpIHtcbiAgICAgIGlmIChlcXVhbHMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlcXVhbHMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2VxdWFscyBtdXN0IGJlIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVxdWFscyA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB1dGlsX3NldEVxdWFscyh0aGlzLl9jbG9uZSgpLCBlcXVhbHMpO1xuICAgIH0sXG4gIH07XG5cbiAgeC5zd2l0Y2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgcmV0dXJuIHRoaXMuZGVyaXZlKGZ1bmN0aW9uICh4KSB7XG4gICAgICB2YXIgaTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBhcmdzLmxlbmd0aC0xOyBpKz0yKSB7XG4gICAgICAgIGlmIChvcHRzLmVxdWFscyh4LCBELnVucGFjayhhcmdzW2ldKSkpIHtcbiAgICAgICAgICByZXR1cm4gRC51bnBhY2soYXJnc1tpKzFdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGkgPT09IGFyZ3MubGVuZ3RoIC0gMSkge1xuICAgICAgICByZXR1cm4gRC51bnBhY2soYXJnc1tpXSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIHg7XG59XG5cbmZ1bmN0aW9uIGRlcml2YXRpb25fY3JlYXRlUHJvdG90eXBlIChELCBvcHRzKSB7XG4gIHJldHVybiB7XG4gICAgX2Nsb25lOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdXRpbF9zZXRFcXVhbHMoRC5kZXJpdmF0aW9uKHRoaXMuX2Rlcml2ZXIpLCB0aGlzLl9lcXVhbHMpO1xuICAgIH0sXG5cbiAgICBfZm9yY2VHZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcbiAgICAgICAgICBpO1xuICAgICAgdmFyIG5ld1BhcmVudHMgPSBwYXJlbnRzX2NhcHR1cmluZ1BhcmVudHMoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbmV3U3RhdGU7XG4gICAgICAgIGlmICghdXRpbF9ERUJVR19NT0RFKSB7XG4gICAgICAgICAgbmV3U3RhdGUgPSB0aGF0Ll9kZXJpdmVyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG5ld1N0YXRlID0gdGhhdC5fZGVyaXZlcigpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IodGhhdC5fc3RhY2spO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVxdWFscyA9IHRoYXQuX2VxdWFscyB8fCBvcHRzLmVxdWFscztcbiAgICAgICAgdGhhdC5fc3RhdGUgPSBlcXVhbHMobmV3U3RhdGUsIHRoYXQuX3ZhbHVlKSA/IGdjX1VOQ0hBTkdFRCA6IGdjX0NIQU5HRUQ7XG4gICAgICAgIHRoYXQuX3ZhbHVlID0gbmV3U3RhdGU7XG4gICAgICB9KTtcblxuICAgICAgLy8gb3JnYW5pc2UgcGFyZW50c1xuICAgICAgZm9yIChpID0gdGhpcy5fcGFyZW50cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgdmFyIHBvc3NpYmx5Rm9ybWVyUGFyZW50ID0gdGhpcy5fcGFyZW50c1tpXTtcbiAgICAgICAgaWYgKCF1dGlsX2FycmF5Q29udGFpbnMobmV3UGFyZW50cywgcG9zc2libHlGb3JtZXJQYXJlbnQpKSB7XG4gICAgICAgICAgdXRpbF9yZW1vdmVGcm9tQXJyYXkocG9zc2libHlGb3JtZXJQYXJlbnQuX2NoaWxkcmVuLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLl9wYXJlbnRzID0gbmV3UGFyZW50cztcblxuICAgICAgLy8gYWRkIHRoaXMgYXMgY2hpbGQgdG8gbmV3IHBhcmVudHNcbiAgICAgIGZvciAoaSA9IG5ld1BhcmVudHMubGVuZ3RoOyBpLS07KSB7XG4gICAgICAgIHV0aWxfYWRkVG9BcnJheShuZXdQYXJlbnRzW2ldLl9jaGlsZHJlbiwgdGhpcyk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIF9nZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBpLCBwYXJlbnQ7XG4gICAgICBvdXRlcjogc3dpdGNoICh0aGlzLl9zdGF0ZSkge1xuICAgICAgY2FzZSBnY19ORVc6XG4gICAgICBjYXNlIGdjX09SUEhBTkVEOlxuICAgICAgICB0aGlzLl9mb3JjZUdldCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgZ2NfVU5TVEFCTEU6XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLl9wYXJlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgcGFyZW50ID0gdGhpcy5fcGFyZW50c1tpXTtcbiAgICAgICAgICB2YXIgcGFyZW50U3RhdGUgPSBwYXJlbnQuX3N0YXRlO1xuICAgICAgICAgIGlmIChwYXJlbnRTdGF0ZSA9PT0gZ2NfVU5TVEFCTEUgfHxcbiAgICAgICAgICAgICAgcGFyZW50U3RhdGUgPT09IGdjX09SUEhBTkVEIHx8XG4gICAgICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19ESVNPV05FRCkge1xuICAgICAgICAgICAgcGFyZW50Ll9nZXQoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGFyZW50U3RhdGUgPSBwYXJlbnQuX3N0YXRlO1xuICAgICAgICAgIGlmIChwYXJlbnRTdGF0ZSA9PT0gZ2NfQ0hBTkdFRCkge1xuICAgICAgICAgICAgdGhpcy5fZm9yY2VHZXQoKTtcbiAgICAgICAgICAgIGJyZWFrIG91dGVyO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIShwYXJlbnRTdGF0ZSA9PT0gZ2NfU1RBQkxFIHx8XG4gICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19VTkNIQU5HRUQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBhcmVudCBtb2RlOiBcIiArIHBhcmVudFN0YXRlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RhdGUgPSBnY19VTkNIQU5HRUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBnY19ESVNPV05FRDpcbiAgICAgICAgdmFyIHBhcmVudHMgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuX3BhcmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgcGFyZW50U3RhdGVUdXBsZSA9IHRoaXMuX3BhcmVudHNbaV0sXG4gICAgICAgICAgICAgIHN0YXRlID0gcGFyZW50U3RhdGVUdXBsZVsxXTtcbiAgICAgICAgICBwYXJlbnQgPSBwYXJlbnRTdGF0ZVR1cGxlWzBdO1xuICAgICAgICAgIGlmICghb3B0cy5lcXVhbHMocGFyZW50Ll9nZXQoKSwgc3RhdGUpKSB7XG4gICAgICAgICAgICB0aGlzLl9wYXJlbnRzID0gW107XG4gICAgICAgICAgICB0aGlzLl9mb3JjZUdldCgpO1xuICAgICAgICAgICAgYnJlYWsgb3V0ZXI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaChwYXJlbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSBwYXJlbnRzLmxlbmd0aDsgaS0tOykge1xuICAgICAgICAgIHV0aWxfYWRkVG9BcnJheShwYXJlbnRzW2ldLl9jaGlsZHJlbiwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcGFyZW50cyA9IHBhcmVudHM7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gZ2NfVU5DSEFOR0VEO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBkZXJpdmF0aW9uX2NvbnN0cnVjdChvYmosIGRlcml2ZXIpIHtcbiAgb2JqLl9jaGlsZHJlbiA9IFtdO1xuICBvYmouX3BhcmVudHMgPSBbXTtcbiAgb2JqLl9kZXJpdmVyID0gZGVyaXZlcjtcbiAgb2JqLl9zdGF0ZSA9IGdjX05FVztcbiAgb2JqLl90eXBlID0gdHlwZXNfREVSSVZBVElPTjtcbiAgb2JqLl92YWx1ZSA9IHV0aWxfdW5pcXVlO1xuICBvYmouX2VxdWFscyA9IG51bGw7XG5cbiAgaWYgKHV0aWxfREVCVUdfTU9ERSkge1xuICAgIG9iai5fc3RhY2sgPSBFcnJvcigpLnN0YWNrO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZnVuY3Rpb24gbXV0YWJsZV9jcmVhdGVQcm90b3R5cGUgKEQsIF8pIHtcbiAgcmV0dXJuIHtcbiAgICBzd2FwOiBmdW5jdGlvbiAoZikge1xuICAgICAgdmFyIGFyZ3MgPSB1dGlsX3NsaWNlKGFyZ3VtZW50cywgMCk7XG4gICAgICBhcmdzWzBdID0gdGhpcy5nZXQoKTtcbiAgICAgIHJldHVybiB0aGlzLnNldChmLmFwcGx5KG51bGwsIGFyZ3MpKTtcbiAgICB9LFxuICAgIGxlbnM6IGZ1bmN0aW9uIChtb25vTGVuc0Rlc2NyaXB0b3IpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgIHJldHVybiBELmxlbnMoe1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gbW9ub0xlbnNEZXNjcmlwdG9yLmdldCh0aGF0LmdldCgpKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgICAgdGhhdC5zZXQobW9ub0xlbnNEZXNjcmlwdG9yLnNldCh0aGF0LmdldCgpLCB2YWwpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGxlbnNfY3JlYXRlUHJvdG90eXBlKEQsIF8pIHtcbiAgcmV0dXJuIHtcbiAgICBfY2xvbmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB1dGlsX3NldEVxdWFscyhELmxlbnModGhpcy5fbGVuc0Rlc2NyaXB0b3IpLCB0aGlzLl9lcXVhbHMpO1xuICAgIH0sXG5cbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgRC5hdG9taWNhbGx5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhhdC5fbGVuc0Rlc2NyaXB0b3Iuc2V0KHZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGxlbnNfY29uc3RydWN0KGRlcml2YXRpb24sIGRlc2NyaXB0b3IpIHtcbiAgZGVyaXZhdGlvbi5fbGVuc0Rlc2NyaXB0b3IgPSBkZXNjcmlwdG9yO1xuICBkZXJpdmF0aW9uLl90eXBlID0gdHlwZXNfTEVOUztcblxuICByZXR1cm4gZGVyaXZhdGlvbjtcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1JlYWN0b3JRdWV1ZSAocnEpIHtcbiAgZm9yICh2YXIgaSA9IHJxLmxlbmd0aDsgaS0tOykge1xuICAgIHJlYWN0b3JzX21heWJlUmVhY3QocnFbaV0pO1xuICB9XG59XG5cbnZhciBUWE5fQ1RYID0gdHJhbnNhY3Rpb25zX25ld0NvbnRleHQoKTtcblxuZnVuY3Rpb24gYXRvbV9pblR4biAoKSB7XG4gIHJldHVybiB0cmFuc2FjdGlvbnNfaW5UcmFuc2FjdGlvbihUWE5fQ1RYKVxufVxuXG52YXIgTk9PUF9BUlJBWSA9IHtwdXNoOiBmdW5jdGlvbiAoKSB7fX07XG5cbmZ1bmN0aW9uIFRyYW5zYWN0aW9uU3RhdGUgKCkge1xuICB0aGlzLmluVHhuVmFsdWVzID0ge307XG4gIHRoaXMucmVhY3RvclF1ZXVlID0gW107XG59XG5cbmZ1bmN0aW9uIGdldFN0YXRlICh0eG5TdGF0ZSwgYXRvbSkge1xuICB2YXIgaW5UeG5WYWx1ZSA9IHR4blN0YXRlLmluVHhuVmFsdWVzW2F0b20uX3VpZF07XG4gIGlmIChpblR4blZhbHVlKSB7XG4gICAgcmV0dXJuIGluVHhuVmFsdWVbMV07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0b20uX3ZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHNldFN0YXRlICh0eG5TdGF0ZSwgYXRvbSwgc3RhdGUpIHtcbiAgdHhuU3RhdGUuaW5UeG5WYWx1ZXNbYXRvbS5fdWlkXSA9IFthdG9tLCBzdGF0ZV07XG4gIGdjX21hcmsoYXRvbSwgdHhuU3RhdGUucmVhY3RvclF1ZXVlKTtcbn1cblxudXRpbF9leHRlbmQoVHJhbnNhY3Rpb25TdGF0ZS5wcm90b3R5cGUsIHtcbiAgb25Db21taXQ6IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgaSwgYXRvbVZhbHVlVHVwbGU7XG4gICAgdmFyIGtleXMgPSB1dGlsX2tleXModGhpcy5pblR4blZhbHVlcyk7XG4gICAgaWYgKGF0b21faW5UeG4oKSkge1xuICAgICAgLy8gcHVzaCBpbi10eG4gdmFscyB1cCB0byBjdXJyZW50IHR4blxuICAgICAgZm9yIChpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgYXRvbVZhbHVlVHVwbGUgPSB0aGlzLmluVHhuVmFsdWVzW2tleXNbaV1dO1xuICAgICAgICBhdG9tVmFsdWVUdXBsZVswXS5zZXQoYXRvbVZhbHVlVHVwbGVbMV0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBjaGFuZ2Ugcm9vdCBzdGF0ZSBhbmQgcnVuIHJlYWN0b3JzLlxuICAgICAgZm9yIChpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgYXRvbVZhbHVlVHVwbGUgPSB0aGlzLmluVHhuVmFsdWVzW2tleXNbaV1dO1xuICAgICAgICBhdG9tVmFsdWVUdXBsZVswXS5fdmFsdWUgPSBhdG9tVmFsdWVUdXBsZVsxXTtcbiAgICAgICAgZ2NfbWFyayhhdG9tVmFsdWVUdXBsZVswXSwgTk9PUF9BUlJBWSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NSZWFjdG9yUXVldWUodGhpcy5yZWFjdG9yUXVldWUpO1xuXG4gICAgICAvLyB0aGVuIHN3ZWVwIGZvciBhIGNsZWFuIGZpbmlzaFxuICAgICAgZm9yIChpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgZ2Nfc3dlZXAodGhpcy5pblR4blZhbHVlc1trZXlzW2ldXVswXSk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIG9uQWJvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIWF0b21faW5UeG4oKSkge1xuICAgICAgdmFyIGtleXMgPSB1dGlsX2tleXModGhpcy5pblR4blZhbHVlcyk7XG4gICAgICBmb3IgKHZhciBpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgZ2NfYWJvcnRfc3dlZXAodGhpcy5pblR4blZhbHVlc1trZXlzW2ldXVswXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59KVxuXG5cbmZ1bmN0aW9uIGF0b21fY3JlYXRlUHJvdG90eXBlIChELCBvcHRzKSB7XG4gIHJldHVybiB7XG4gICAgX2Nsb25lOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdXRpbF9zZXRFcXVhbHMoRC5hdG9tKHRoaXMuX3ZhbHVlKSwgdGhpcy5fZXF1YWxzKTtcbiAgICB9LFxuXG4gICAgd2l0aFZhbGlkYXRvcjogZnVuY3Rpb24gKGYpIHtcbiAgICAgIGlmIChmID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jbG9uZSgpO1xuICAgICAgfSBpZiAodHlwZW9mIGYgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuX2Nsb25lKCk7XG4gICAgICAgIHZhciBleGlzdGluZyA9IHRoaXMuX3ZhbGlkYXRvcjtcbiAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgcmVzdWx0Ll92YWxpZGF0b3IgPSBmdW5jdGlvbiAoeCkgeyByZXR1cm4gZih4KSAmJiBleGlzdGluZyh4KTsgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc3VsdC5fdmFsaWRhdG9yID0gZjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiLndpdGhWYWxpZGF0b3IgZXhwZWN0cyBmdW5jdGlvbiBvciBudWxsXCIpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICB2YWxpZGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgdGhpcy5fdmFsaWRhdGUodGhpcy5nZXQoKSk7XG4gICAgfSxcblxuICAgIF92YWxpZGF0ZTogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICB2YXIgdmFsaWRhdGlvblJlc3VsdCA9IHRoaXMuX3ZhbGlkYXRvciAmJiB0aGlzLl92YWxpZGF0b3IodmFsdWUpO1xuICAgICAgaWYgKHRoaXMuX3ZhbGlkYXRvciAmJiB2YWxpZGF0aW9uUmVzdWx0ICE9PSB0cnVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB2YWxpZGF0aW9uIHdpdGggdmFsdWU6ICdcIiArIHZhbHVlICsgXCInLlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiIFZhbGlkYXRvciByZXR1cm5lZCAnXCIgKyB2YWxpZGF0aW9uUmVzdWx0ICsgXCInIFwiKTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcblxuICAgICAgdGhpcy5fdmFsaWRhdGUodmFsdWUpO1xuICAgICAgdmFyIGVxdWFscyA9IHRoaXMuX2VxdWFscyB8fCBvcHRzLmVxdWFscztcbiAgICAgIGlmICghZXF1YWxzKHZhbHVlLCB0aGlzLl92YWx1ZSkpIHtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSBnY19DSEFOR0VEO1xuXG4gICAgICAgIGlmIChhdG9tX2luVHhuKCkpIHtcbiAgICAgICAgICBzZXRTdGF0ZSh0cmFuc2FjdGlvbnNfY3VycmVudFRyYW5zYWN0aW9uKFRYTl9DVFgpLCB0aGlzLCB2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICAgIHZhciByZWFjdG9yUXVldWUgPSBbXTtcbiAgICAgICAgICBnY19tYXJrKHRoaXMsIHJlYWN0b3JRdWV1ZSk7XG4gICAgICAgICAgcHJvY2Vzc1JlYWN0b3JRdWV1ZShyZWFjdG9yUXVldWUpO1xuICAgICAgICAgIGdjX3N3ZWVwKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX2dldDogZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGF0b21faW5UeG4oKSkge1xuICAgICAgICByZXR1cm4gZ2V0U3RhdGUodHJhbnNhY3Rpb25zX2N1cnJlbnRUcmFuc2FjdGlvbihUWE5fQ1RYKSwgdGhpcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBhdG9tX2NvbnN0cnVjdCAoYXRvbSwgdmFsdWUpIHtcbiAgYXRvbS5fdWlkID0gdXRpbF9uZXh0SWQoKTtcbiAgYXRvbS5fY2hpbGRyZW4gPSBbXTtcbiAgYXRvbS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gIGF0b20uX3ZhbHVlID0gdmFsdWU7XG4gIGF0b20uX3R5cGUgPSB0eXBlc19BVE9NO1xuICBhdG9tLl9lcXVhbHMgPSBudWxsO1xuICByZXR1cm4gYXRvbTtcbn1cblxuZnVuY3Rpb24gYXRvbV90cmFuc2FjdCAoZikge1xuICB0cmFuc2FjdGlvbnNfdHJhbnNhY3QoVFhOX0NUWCwgbmV3IFRyYW5zYWN0aW9uU3RhdGUoKSwgZik7XG59XG5cbmZ1bmN0aW9uIGF0b21fdHJhbnNhY3Rpb24gKGYpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYXJncyA9IHV0aWxfc2xpY2UoYXJndW1lbnRzLCAwKTtcbiAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgdmFyIHJlc3VsdDtcbiAgICBhdG9tX3RyYW5zYWN0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHJlc3VsdCA9IGYuYXBwbHkodGhhdCwgYXJncyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgdGlja2VyID0gbnVsbDtcblxuZnVuY3Rpb24gYXRvbV90aWNrZXIgKCkge1xuICBpZiAodGlja2VyKSB7XG4gICAgdGlja2VyLnJlZkNvdW50Kys7XG4gIH0gZWxzZSB7XG4gICAgdGlja2VyID0gdHJhbnNhY3Rpb25zX3RpY2tlcihUWE5fQ1RYLCBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uU3RhdGUoKTtcbiAgICB9KTtcbiAgICB0aWNrZXIucmVmQ291bnQgPSAxO1xuICB9XG4gIHZhciBkb25lID0gZmFsc2U7XG4gIHJldHVybiB7XG4gICAgdGljazogZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGRvbmUpIHRocm93IG5ldyBFcnJvcigndHlyaW5nIHRvIHVzZSB0aWNrZXIgYWZ0ZXIgcmVsZWFzZScpO1xuICAgICAgdGlja2VyLnRpY2soKTtcbiAgICB9LFxuICAgIHJlbGVhc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChkb25lKSB0aHJvdyBuZXcgRXJyb3IoJ3RpY2tlciBhbHJlYWR5IHJlbGVhc2VkJyk7XG4gICAgICBpZiAoLS10aWNrZXIucmVmQ291bnQgPT09IDApIHtcbiAgICAgICAgdGlja2VyLnN0b3AoKTtcbiAgICAgICAgdGlja2VyID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGRvbmUgPSB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxudmFyIGRlZmF1bHRDb25maWcgPSB7IGVxdWFsczogdXRpbF9lcXVhbHMgfTtcblxuZnVuY3Rpb24gY29uc3RydWN0TW9kdWxlIChjb25maWcpIHtcbiAgY29uZmlnID0gdXRpbF9leHRlbmQoe30sIGRlZmF1bHRDb25maWcsIGNvbmZpZyB8fCB7fSk7XG5cbiAgdmFyIEQgPSB7XG4gICAgdHJhbnNhY3Q6IGF0b21fdHJhbnNhY3QsXG4gICAgZGVmYXVsdEVxdWFsczogdXRpbF9lcXVhbHMsXG4gICAgc2V0RGVidWdNb2RlOiB1dGlsX3NldERlYnVnTW9kZSxcbiAgICB0cmFuc2FjdGlvbjogYXRvbV90cmFuc2FjdGlvbixcbiAgICB0aWNrZXI6IGF0b21fdGlja2VyLFxuICAgIFJlYWN0b3I6IHJlYWN0b3JzX1JlYWN0b3IsXG4gICAgaXNBdG9tOiBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIHggJiYgKHguX3R5cGUgPT09IHR5cGVzX0FUT00gfHwgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUyk7XG4gICAgfSxcbiAgICBpc0Rlcml2YWJsZTogZnVuY3Rpb24gKHgpIHtcbiAgICAgIHJldHVybiB4ICYmICh4Ll90eXBlID09PSB0eXBlc19BVE9NIHx8XG4gICAgICAgICAgICAgICAgICAgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUyB8fFxuICAgICAgICAgICAgICAgICAgIHguX3R5cGUgPT09IHR5cGVzX0RFUklWQVRJT04pO1xuICAgIH0sXG4gICAgaXNEZXJpdmF0aW9uOiBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIHggJiYgKHguX3R5cGUgPT09IHR5cGVzX0RFUklWQVRJT04gfHwgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUylcbiAgICB9LFxuICAgIGlzTGVuc2VkOiBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIHggJiYgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUztcbiAgICB9LFxuICAgIGlzUmVhY3RvcjogZnVuY3Rpb24gKHgpIHtcbiAgICAgIHJldHVybiB4ICYmIHguX3R5cGUgPT09IHR5cGVzX1JFQUNUSU9OO1xuICAgIH0sXG4gIH07XG5cbiAgdmFyIERlcml2YWJsZSAgPSBkZXJpdmFibGVfY3JlYXRlUHJvdG90eXBlKEQsIGNvbmZpZyk7XG4gIHZhciBNdXRhYmxlICAgID0gbXV0YWJsZV9jcmVhdGVQcm90b3R5cGUoRCwgY29uZmlnKTtcblxuICB2YXIgQXRvbSAgICAgICA9IHV0aWxfZXh0ZW5kKHt9LCBNdXRhYmxlLCBEZXJpdmFibGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXRvbV9jcmVhdGVQcm90b3R5cGUoRCwgY29uZmlnKSk7XG5cbiAgdmFyIERlcml2YXRpb24gPSB1dGlsX2V4dGVuZCh7fSwgRGVyaXZhYmxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcml2YXRpb25fY3JlYXRlUHJvdG90eXBlKEQsIGNvbmZpZykpO1xuXG4gIHZhciBMZW5zICAgICAgID0gdXRpbF9leHRlbmQoe30sIE11dGFibGUsIERlcml2YXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5zX2NyZWF0ZVByb3RvdHlwZShELCBjb25maWcpKTtcblxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgbmV3IGF0b20gd2hvc2Ugc3RhdGUgaXMgdGhlIGdpdmVuIHZhbHVlXG4gICAqL1xuICBELmF0b20gPSBmdW5jdGlvbiAodmFsKSB7XG4gICAgcmV0dXJuIGF0b21fY29uc3RydWN0KE9iamVjdC5jcmVhdGUoQXRvbSksIHZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb3B5IG9mIGYgd2hpY2ggcnVucyBhdG9taWNhbGx5XG4gICAqL1xuICBELmF0b21pYyA9IGZ1bmN0aW9uIChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIEQuYXRvbWljYWxseShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc3VsdCA9IGYuYXBwbHkodGhhdCwgYXJncyk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9O1xuXG4gIEQuYXRvbWljYWxseSA9IGZ1bmN0aW9uIChmKSB7XG4gICAgaWYgKGF0b21faW5UeG4oKSkge1xuICAgICAgZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBELnRyYW5zYWN0KGYpO1xuICAgIH1cbiAgfTtcblxuICBELmRlcml2YXRpb24gPSBmdW5jdGlvbiAoZikge1xuICAgIHJldHVybiBkZXJpdmF0aW9uX2NvbnN0cnVjdChPYmplY3QuY3JlYXRlKERlcml2YXRpb24pLCBmKTtcbiAgfTtcblxuICAvKipcbiAgICogVGVtcGxhdGUgc3RyaW5nIHRhZyBmb3IgZGVyaXZhYmxlIHN0cmluZ3NcbiAgICovXG4gIEQuZGVyaXZlID0gZnVuY3Rpb24gKHBhcnRzKSB7XG4gICAgdmFyIGFyZ3MgPSB1dGlsX3NsaWNlKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIEQuZGVyaXZhdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgcyA9IFwiXCI7XG4gICAgICBmb3IgKHZhciBpPTA7IGk8cGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcyArPSBwYXJ0c1tpXTtcbiAgICAgICAgaWYgKGkgPCBhcmdzLmxlbmd0aCkge1xuICAgICAgICAgIHMgKz0gRC51bnBhY2soYXJnc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzO1xuICAgIH0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgbmV3IGxlbnNcbiAgICovXG4gIEQubGVucyA9IGZ1bmN0aW9uIChkZXNjcmlwdG9yKSB7XG4gICAgcmV0dXJuIGxlbnNfY29uc3RydWN0KFxuICAgICAgZGVyaXZhdGlvbl9jb25zdHJ1Y3QoT2JqZWN0LmNyZWF0ZShMZW5zKSwgZGVzY3JpcHRvci5nZXQpLFxuICAgICAgZGVzY3JpcHRvclxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIGRlcmVmZXJlbmNlcyBhIHRoaW5nIGlmIGl0IGlzIGRlcmVmZXJlbmNhYmxlLCBvdGhlcndpc2UganVzdCByZXR1cm5zIGl0LlxuICAgKi9cbiAgRC51bnBhY2sgPSBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoRC5pc0Rlcml2YWJsZSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZy5nZXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogbGlmdHMgYSBub24tbW9uYWRpYyBmdW5jdGlvbiB0byB3b3JrIG9uIGRlcml2YWJsZXNcbiAgICovXG4gIEQubGlmdCA9IGZ1bmN0aW9uIChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgcmV0dXJuIEQuZGVyaXZhdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmLmFwcGx5KHRoYXQsIEFycmF5LnByb3RvdHlwZS5tYXAuY2FsbChhcmdzLCBELnVucGFjaykpO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIGRlZXBVbnBhY2sgKHRoaW5nKSB7XG4gICAgaWYgKEQuaXNEZXJpdmFibGUodGhpbmcpKSB7XG4gICAgICByZXR1cm4gdGhpbmcuZ2V0KCk7XG4gICAgfSBlbHNlIGlmICh0aGluZyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICByZXR1cm4gdGhpbmcubWFwKGRlZXBVbnBhY2spO1xuICAgIH0gZWxzZSBpZiAodGhpbmcuY29uc3RydWN0b3IgPT09IE9iamVjdCkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgdmFyIGtleXMgPSB1dGlsX2tleXModGhpbmcpO1xuICAgICAgZm9yICh2YXIgaSA9IGtleXMubGVuZ3RoOyBpLS07KSB7XG4gICAgICAgIHZhciBwcm9wID0ga2V5c1tpXTtcbiAgICAgICAgcmVzdWx0W3Byb3BdID0gZGVlcFVucGFjayh0aGluZ1twcm9wXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpbmc7XG4gICAgfVxuICB9XG5cbiAgRC5zdHJ1Y3QgPSBmdW5jdGlvbiAoYXJnKSB7XG4gICAgaWYgKGFyZy5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0IHx8IGFyZyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRlZXBVbnBhY2soYXJnKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJgc3RydWN0YCBleHBlY3RzIHBsYWluIE9iamVjdCBvciBBcnJheVwiKTtcbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gYW5kT3JGbiAoYnJlYWtPbikge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmFsO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YWwgPSBELnVucGFjayhhcmdzW2ldKTtcbiAgICAgICAgICBpZiAoYnJlYWtPbih2YWwpKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBpZGVudGl0eSAoeCkgeyByZXR1cm4geDsgfVxuICBmdW5jdGlvbiBjb21wbGVtZW50IChmKSB7IHJldHVybiBmdW5jdGlvbiAoeCkgeyByZXR1cm4gIWYoeCk7IH19XG4gIEQub3IgPSBhbmRPckZuKGlkZW50aXR5KTtcbiAgRC5tT3IgPSBhbmRPckZuKHV0aWxfc29tZSk7XG4gIEQuYW5kID0gYW5kT3JGbihjb21wbGVtZW50KGlkZW50aXR5KSk7XG4gIEQubUFuZCA9IGFuZE9yRm4oY29tcGxlbWVudCh1dGlsX3NvbWUpKTtcblxuICByZXR1cm4gRDtcbn1cblxudXRpbF9leHRlbmQoZXhwb3J0cywgY29uc3RydWN0TW9kdWxlKCkpO1xuZXhwb3J0cy53aXRoRXF1YWxpdHkgPSBmdW5jdGlvbiAoZXF1YWxzKSB7XG4gIHJldHVybiBjb25zdHJ1Y3RNb2R1bGUoe2VxdWFsczogZXF1YWxzfSk7XG59O1xuZXhwb3J0c1snZGVmYXVsdCddID0gZXhwb3J0cztcblxufSk7XG5cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRlcml2YWJsZS5qcy5tYXAiXX0= | |
const d = require("derivable") | |
const name = d.atom("World"); // the name of the user | |
const countryCode = d.atom("en"); // for i18n | |
// static constants don't need to be wrapped | |
const greetings = { | |
en: "Hello", | |
de: "Hallo", | |
es: "Hola", | |
cn: "您好", | |
fr: "Bonjour", | |
}; | |
// derive a greeting message based on the user's name and country. | |
const greeting = countryCode.derive(cc => greetings[cc]); | |
const message = d.derive`${greeting}, ${name}!`; // es6 tagged template strings! | |
// set up a Reactor to print the message every time it changes | |
message.react(msg => console.log(msg)); | |
// $> Hello, World! | |
countryCode.set("de"); | |
// $> Hallo, World! | |
name.set("Dagmar"); | |
// $> Hallo, Dagmar! | |
// we can avoid unwanted intermediate reactions by using transactions | |
d.transact(() => { | |
countryCode.set("fr"); | |
name.set("Étienne"); | |
}); | |
;}, 0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "requirebin-sketch", | |
"version": "1.0.0", | |
"dependencies": { | |
"derivable": "0.12.1" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <body> --> | |
<div></div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <head> --> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment