made with requirebin
Created
October 22, 2017 10:36
-
-
Save joshski/b6fdb8131c9c8d451863b41a6558d727 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
var hyperdom = require('hyperdom') | |
var h = hyperdom.html | |
class App { | |
render() { | |
return h('.container', | |
h('#example', | |
h('div.foo div', h('input[type=submit]')) | |
), | |
h.component({ | |
onadd: function(pre) { | |
pre.innerText = document.querySelector('#example').innerHTML | |
} | |
}, h('pre')) | |
) | |
} | |
} | |
hyperdom.append(document.body, new App()) |
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})({1:[function(require,module,exports){ | |
},{}],2:[function(require,module,exports){ | |
var VText = require("virtual-dom/vnode/vtext.js") | |
var domComponent = require('./domComponent'); | |
var hyperdom = require('.'); | |
var deprecations = require('./deprecations'); | |
function ComponentWidget(state, vdom) { | |
if (!vdom) { | |
throw new Error('hyperdom.html.component([options], vdom) expects a vdom argument'); | |
} | |
this.state = state; | |
this.key = state.key; | |
var currentRender = hyperdom.currentRender(); | |
if (typeof vdom === 'function') { | |
this.render = function () { | |
if (currentRender) { | |
currentRender.eventHandlerWrapper = state.on; | |
} | |
return vdom.apply(this.state, arguments); | |
}; | |
this.canRefresh = true; | |
} else { | |
vdom = vdom || new VText(''); | |
this.render = function () { | |
return vdom; | |
} | |
} | |
this.cacheKey = state.cacheKey; | |
this.component = domComponent(); | |
var renderFinished = currentRender && currentRender.finished; | |
if (renderFinished) { | |
this.afterRender = function (fn) { | |
renderFinished.then(fn); | |
}; | |
} else { | |
this.afterRender = function () {}; | |
} | |
} | |
ComponentWidget.prototype.type = 'Widget'; | |
ComponentWidget.prototype.init = function () { | |
var self = this; | |
if (self.state.onbeforeadd) { | |
self.state.onbeforeadd(); | |
} | |
var vdom = this.render(this); | |
if (vdom instanceof Array) { | |
throw new Error('vdom returned from component cannot be an array'); | |
} | |
var element = this.component.create(vdom); | |
if (self.state.onadd) { | |
this.afterRender(function () { | |
self.state.onadd(element); | |
}); | |
} | |
if (self.state.detached) { | |
return document.createTextNode(''); | |
} else { | |
return element; | |
} | |
}; | |
ComponentWidget.prototype.update = function (previous) { | |
var self = this; | |
var refresh = !this.cacheKey || this.cacheKey !== previous.cacheKey; | |
if (refresh) { | |
if (self.state.onupdate) { | |
this.afterRender(function () { | |
self.state.onupdate(self.component.element); | |
}); | |
} | |
} | |
this.component = previous.component; | |
if (previous.state && this.state) { | |
var keys = Object.keys(this.state); | |
for(var n = 0; n < keys.length; n++) { | |
var key = keys[n]; | |
previous.state[key] = self.state[key]; | |
} | |
this.state = previous.state; | |
} | |
if (refresh) { | |
var element = this.component.update(this.render(this)); | |
if (self.state.detached) { | |
return document.createTextNode(''); | |
} else { | |
return element; | |
} | |
} | |
}; | |
ComponentWidget.prototype.refresh = function () { | |
this.component.update(this.render(this)); | |
if (this.state.onupdate) { | |
this.state.onupdate(this.component.element); | |
} | |
}; | |
ComponentWidget.prototype.rerender = ComponentWidget.prototype.refresh; | |
ComponentWidget.prototype.destroy = function (element) { | |
var self = this; | |
if (self.state.onremove) { | |
this.afterRender(function () { | |
self.state.onremove(element); | |
}); | |
} | |
this.component.destroy(); | |
}; | |
module.exports = function (state, vdom) { | |
deprecations.component('hyperdom.html.component is deprecated, please use ViewModels'); | |
if (typeof state === 'function') { | |
return new ComponentWidget({}, state); | |
} else if (state.constructor === Object) { | |
return new ComponentWidget(state, vdom); | |
} else { | |
return new ComponentWidget({}, state); | |
} | |
}; | |
module.exports.ComponentWidget = ComponentWidget; | |
},{".":"hyperdom","./deprecations":3,"./domComponent":4,"virtual-dom/vnode/vtext.js":32}],3:[function(require,module,exports){ | |
function deprecationWarning() { | |
var warningIssued = false; | |
return function (arg) { | |
if (!warningIssued) { | |
console.warn(arg); | |
warningIssued = true; | |
} | |
}; | |
} | |
module.exports = { | |
refresh: deprecationWarning(), | |
currentRender: deprecationWarning(), | |
window: deprecationWarning(), | |
component: deprecationWarning(), | |
renderFunction: deprecationWarning(), | |
refreshAfter: deprecationWarning(), | |
norefresh: deprecationWarning() | |
}; | |
},{}],4:[function(require,module,exports){ | |
var createElement = require('virtual-dom/create-element'); | |
var diff = require('virtual-dom/diff'); | |
var patch = require('virtual-dom/patch'); | |
var toVdom = require('./toVdom'); | |
var isVdom = require('./isVdom'); | |
function DomComponent(options) { | |
this.document = options && options.document; | |
} | |
function prepareVdom(object) { | |
var vdom = toVdom(object); | |
if (!isVdom(vdom)) { | |
throw new Error('expected render to return vdom'); | |
} else { | |
return vdom; | |
} | |
} | |
DomComponent.prototype.create = function (vdom) { | |
this.vdom = prepareVdom(vdom); | |
return this.element = createElement(this.vdom, {document: this.document}); | |
}; | |
DomComponent.prototype.merge = function (vdom, element) { | |
this.vdom = prepareVdom(vdom); | |
return this.element = element; | |
}; | |
DomComponent.prototype.update = function (vdom) { | |
var oldVdom = this.vdom; | |
this.vdom = prepareVdom(vdom); | |
var patches = diff(oldVdom, this.vdom); | |
return this.element = patch(this.element, patches); | |
}; | |
DomComponent.prototype.destroy = function (options) { | |
function destroyWidgets(vdom) { | |
if (vdom.type === 'Widget') { | |
vdom.destroy(); | |
} else if (vdom.children) { | |
vdom.children.forEach(destroyWidgets); | |
} | |
} | |
destroyWidgets(this.vdom); | |
if (options && options.removeElement && this.element.parentNode) { | |
this.element.parentNode.removeChild(this.element); | |
} | |
}; | |
function domComponent(options) { | |
return new DomComponent(options); | |
} | |
module.exports = domComponent; | |
},{"./isVdom":5,"./toVdom":40,"virtual-dom/create-element":8,"virtual-dom/diff":9,"virtual-dom/patch":14}],5:[function(require,module,exports){ | |
var virtualDomVersion = require("virtual-dom/vnode/version") | |
module.exports = function(x) { | |
var type = x.type; | |
if (type == 'VirtualNode' || type == 'VirtualText') { | |
return x.version == virtualDomVersion; | |
} else { | |
return type == 'Widget' || type == 'Thunk'; | |
} | |
}; | |
},{"virtual-dom/vnode/version":29}],6:[function(require,module,exports){ | |
module.exports = function (model, property) { | |
var hyperdomMeta = model._hyperdomMeta; | |
if (!hyperdomMeta) { | |
hyperdomMeta = {}; | |
Object.defineProperty(model, '_hyperdomMeta', {value: hyperdomMeta}); | |
} | |
if (property) { | |
var meta = hyperdomMeta[property]; | |
if (!meta) { | |
meta = hyperdomMeta[property] = {}; | |
} | |
return meta; | |
} else { | |
return hyperdomMeta; | |
} | |
}; | |
},{}],7:[function(require,module,exports){ | |
var hyperdomMeta = require('./meta'); | |
var runRender = require('./runRender'); | |
var hyperdom = require('.'); | |
var Set = require('./set'); | |
var lastId = 0; | |
function Mount(model, options) { | |
var win = (options && options.window) || window; | |
this.requestRender = (options && options.requestRender) || win.requestAnimationFrame || win.setTimeout; | |
this.model = model; | |
this.renderQueued = false; | |
this.mountRenderRequested = false; | |
this.widgetRendersRequested = undefined; | |
this.id = ++lastId; | |
this.mounted = true; | |
} | |
Mount.prototype.queueRender = function () { | |
if (!this.renderQueued) { | |
var requestRender = this.requestRender; | |
var self = this; | |
requestRender(function () { | |
self.renderQueued = false; | |
if (self.mounted) { | |
runRender(self, function () { | |
if (self.mountRenderRequested) { | |
var vdom = self.render(); | |
self.component.update(vdom); | |
self.mountRenderRequested = false; | |
} else if (self.widgetRendersRequested && self.widgetRendersRequested.length) { | |
for (var i = 0, l = self.widgetRendersRequested.length; i < l; i++) { | |
var w = self.widgetRendersRequested[i]; | |
w.rerender(); | |
} | |
self.widgetRendersRequested = undefined; | |
} | |
}); | |
} | |
}); | |
this.renderQueued = true; | |
} | |
}; | |
Mount.prototype.render = function() { | |
return this.renderViewModel(this.model); | |
}; | |
Mount.prototype.rerender = function () { | |
this.mountRenderRequested = true; | |
this.queueRender(); | |
}; | |
Mount.prototype.rerenderWidget = function (widget) { | |
if (!this.widgetRendersRequested) { | |
this.widgetRendersRequested = []; | |
} | |
this.widgetRendersRequested.push(widget); | |
this.queueRender(); | |
}; | |
Mount.prototype._renderViewModel = function(model) { | |
var self = this; | |
model.rerender = function () { | |
self.rerender(); | |
}; | |
model.rerenderViewModel = function() { | |
var meta = hyperdomMeta(this); | |
meta.widgets.forEach(function (w) { | |
self.rerenderWidget(w); | |
}); | |
}; | |
var meta = hyperdomMeta(model); | |
if (!meta.mount) { | |
meta.mount = this; | |
} | |
if (!meta.widgets) { | |
meta.widgets = new Set(); | |
} | |
if (typeof model.onload == 'function') { | |
if (!meta.loaded) { | |
meta.loaded = true; | |
hyperdom.refreshify(function () { return model.onload(); }, {refresh: 'promise'})(); | |
} | |
} | |
var vdom = model.render(); | |
if (vdom instanceof Array) { | |
throw new Error('vdom returned from component cannot be an array'); | |
} | |
if (vdom && vdom.properties) { | |
vdom.properties._hyperdomViewModel = model; | |
} | |
return vdom; | |
} | |
Mount.prototype.renderViewModel = function(model) { | |
if (typeof model.renderCacheKey === 'function') { | |
var meta = hyperdomMeta(model); | |
var key = model.renderCacheKey(); | |
if (key !== undefined && meta.cacheKey === key && meta.cachedVdom) { | |
return meta.cachedVdom; | |
} else { | |
meta.cacheKey = key; | |
return meta.cachedVdom = this._renderViewModel(model); | |
} | |
} else { | |
return this._renderViewModel(model); | |
} | |
}; | |
Mount.prototype.detach = function () { | |
this.mounted = false; | |
}; | |
Mount.prototype.remove = function () { | |
this.component.destroy({removeElement: true}); | |
this.mounted = false; | |
}; | |
module.exports = Mount; | |
},{".":"hyperdom","./meta":6,"./runRender":37,"./set":38}],8:[function(require,module,exports){ | |
var createElement = require("./vdom/create-element.js") | |
module.exports = createElement | |
},{"./vdom/create-element.js":16}],9:[function(require,module,exports){ | |
var diff = require("./vtree/diff.js") | |
module.exports = diff | |
},{"./vtree/diff.js":34}],10:[function(require,module,exports){ | |
/*! | |
* Cross-Browser Split 1.1.1 | |
* Copyright 2007-2012 Steven Levithan <stevenlevithan.com> | |
* Available under the MIT License | |
* ECMAScript compliant, uniform cross-browser split method | |
*/ | |
/** | |
* Splits a string into an array of strings using a regex or string separator. Matches of the | |
* separator are not included in the result array. However, if `separator` is a regex that contains | |
* capturing groups, backreferences are spliced into the result each time `separator` is matched. | |
* Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably | |
* cross-browser. | |
* @param {String} str String to split. | |
* @param {RegExp|String} separator Regex or string to use for separating the string. | |
* @param {Number} [limit] Maximum number of items to include in the result array. | |
* @returns {Array} Array of substrings. | |
* @example | |
* | |
* // Basic use | |
* split('a b c d', ' '); | |
* // -> ['a', 'b', 'c', 'd'] | |
* | |
* // With limit | |
* split('a b c d', ' ', 2); | |
* // -> ['a', 'b'] | |
* | |
* // Backreferences in result array | |
* split('..word1 word2..', /([a-z]+)(\d+)/i); | |
* // -> ['..', 'word', '1', ' ', 'word', '2', '..'] | |
*/ | |
module.exports = (function split(undef) { | |
var nativeSplit = String.prototype.split, | |
compliantExecNpcg = /()??/.exec("")[1] === undef, | |
// NPCG: nonparticipating capturing group | |
self; | |
self = function(str, separator, limit) { | |
// If `separator` is not a regex, use `nativeSplit` | |
if (Object.prototype.toString.call(separator) !== "[object RegExp]") { | |
return nativeSplit.call(str, separator, limit); | |
} | |
var output = [], | |
flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6 | |
(separator.sticky ? "y" : ""), | |
// Firefox 3+ | |
lastLastIndex = 0, | |
// Make `global` and avoid `lastIndex` issues by working with a copy | |
separator = new RegExp(separator.source, flags + "g"), | |
separator2, match, lastIndex, lastLength; | |
str += ""; // Type-convert | |
if (!compliantExecNpcg) { | |
// Doesn't need flags gy, but they don't hurt | |
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); | |
} | |
/* Values for `limit`, per the spec: | |
* If undefined: 4294967295 // Math.pow(2, 32) - 1 | |
* If 0, Infinity, or NaN: 0 | |
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; | |
* If negative number: 4294967296 - Math.floor(Math.abs(limit)) | |
* If other: Type-convert, then use the above rules | |
*/ | |
limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 | |
limit >>> 0; // ToUint32(limit) | |
while (match = separator.exec(str)) { | |
// `separator.lastIndex` is not reliable cross-browser | |
lastIndex = match.index + match[0].length; | |
if (lastIndex > lastLastIndex) { | |
output.push(str.slice(lastLastIndex, match.index)); | |
// Fix browsers whose `exec` methods don't consistently return `undefined` for | |
// nonparticipating capturing groups | |
if (!compliantExecNpcg && match.length > 1) { | |
match[0].replace(separator2, function() { | |
for (var i = 1; i < arguments.length - 2; i++) { | |
if (arguments[i] === undef) { | |
match[i] = undef; | |
} | |
} | |
}); | |
} | |
if (match.length > 1 && match.index < str.length) { | |
Array.prototype.push.apply(output, match.slice(1)); | |
} | |
lastLength = match[0].length; | |
lastLastIndex = lastIndex; | |
if (output.length >= limit) { | |
break; | |
} | |
} | |
if (separator.lastIndex === match.index) { | |
separator.lastIndex++; // Avoid an infinite loop | |
} | |
} | |
if (lastLastIndex === str.length) { | |
if (lastLength || !separator.test("")) { | |
output.push(""); | |
} | |
} else { | |
output.push(str.slice(lastLastIndex)); | |
} | |
return output.length > limit ? output.slice(0, limit) : output; | |
}; | |
return self; | |
})(); | |
},{}],11:[function(require,module,exports){ | |
(function (global){ | |
var topLevel = typeof global !== 'undefined' ? global : | |
typeof window !== 'undefined' ? window : {} | |
var minDoc = require('min-document'); | |
if (typeof document !== 'undefined') { | |
module.exports = document; | |
} else { | |
var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; | |
if (!doccy) { | |
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; | |
} | |
module.exports = doccy; | |
} | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"min-document":1}],12:[function(require,module,exports){ | |
"use strict"; | |
module.exports = function isObject(x) { | |
return typeof x === "object" && x !== null; | |
}; | |
},{}],13:[function(require,module,exports){ | |
var nativeIsArray = Array.isArray | |
var toString = Object.prototype.toString | |
module.exports = nativeIsArray || isArray | |
function isArray(obj) { | |
return toString.call(obj) === "[object Array]" | |
} | |
},{}],14:[function(require,module,exports){ | |
var patch = require("./vdom/patch.js") | |
module.exports = patch | |
},{"./vdom/patch.js":19}],15:[function(require,module,exports){ | |
var isObject = require("is-object") | |
var isHook = require("../vnode/is-vhook.js") | |
module.exports = applyProperties | |
function applyProperties(node, props, previous) { | |
for (var propName in props) { | |
var propValue = props[propName] | |
if (propValue === undefined) { | |
removeProperty(node, propName, propValue, previous); | |
} else if (isHook(propValue)) { | |
removeProperty(node, propName, propValue, previous) | |
if (propValue.hook) { | |
propValue.hook(node, | |
propName, | |
previous ? previous[propName] : undefined) | |
} | |
} else { | |
if (isObject(propValue)) { | |
patchObject(node, props, previous, propName, propValue); | |
} else { | |
node[propName] = propValue | |
} | |
} | |
} | |
} | |
function removeProperty(node, propName, propValue, previous) { | |
if (previous) { | |
var previousValue = previous[propName] | |
if (!isHook(previousValue)) { | |
if (propName === "attributes") { | |
for (var attrName in previousValue) { | |
node.removeAttribute(attrName) | |
} | |
} else if (propName === "style") { | |
for (var i in previousValue) { | |
node.style[i] = "" | |
} | |
} else if (typeof previousValue === "string") { | |
node[propName] = "" | |
} else { | |
node[propName] = null | |
} | |
} else if (previousValue.unhook) { | |
previousValue.unhook(node, propName, propValue) | |
} | |
} | |
} | |
function patchObject(node, props, previous, propName, propValue) { | |
var previousValue = previous ? previous[propName] : undefined | |
// Set attributes | |
if (propName === "attributes") { | |
for (var attrName in propValue) { | |
var attrValue = propValue[attrName] | |
if (attrValue === undefined) { | |
node.removeAttribute(attrName) | |
} else { | |
node.setAttribute(attrName, attrValue) | |
} | |
} | |
return | |
} | |
if(previousValue && isObject(previousValue) && | |
getPrototype(previousValue) !== getPrototype(propValue)) { | |
node[propName] = propValue | |
return | |
} | |
if (!isObject(node[propName])) { | |
node[propName] = {} | |
} | |
var replacer = propName === "style" ? "" : undefined | |
for (var k in propValue) { | |
var value = propValue[k] | |
node[propName][k] = (value === undefined) ? replacer : value | |
} | |
} | |
function getPrototype(value) { | |
if (Object.getPrototypeOf) { | |
return Object.getPrototypeOf(value) | |
} else if (value.__proto__) { | |
return value.__proto__ | |
} else if (value.constructor) { | |
return value.constructor.prototype | |
} | |
} | |
},{"../vnode/is-vhook.js":25,"is-object":12}],16:[function(require,module,exports){ | |
var document = require("global/document") | |
var applyProperties = require("./apply-properties") | |
var isVNode = require("../vnode/is-vnode.js") | |
var isVText = require("../vnode/is-vtext.js") | |
var isWidget = require("../vnode/is-widget.js") | |
var handleThunk = require("../vnode/handle-thunk.js") | |
module.exports = createElement | |
function createElement(vnode, opts) { | |
var doc = opts ? opts.document || document : document | |
var warn = opts ? opts.warn : null | |
vnode = handleThunk(vnode).a | |
if (isWidget(vnode)) { | |
return vnode.init() | |
} else if (isVText(vnode)) { | |
return doc.createTextNode(vnode.text) | |
} else if (!isVNode(vnode)) { | |
if (warn) { | |
warn("Item is not a valid virtual dom node", vnode) | |
} | |
return null | |
} | |
var node = (vnode.namespace === null) ? | |
doc.createElement(vnode.tagName) : | |
doc.createElementNS(vnode.namespace, vnode.tagName) | |
var props = vnode.properties | |
applyProperties(node, props) | |
var children = vnode.children | |
for (var i = 0; i < children.length; i++) { | |
var childNode = createElement(children[i], opts) | |
if (childNode) { | |
node.appendChild(childNode) | |
} | |
} | |
return node | |
} | |
},{"../vnode/handle-thunk.js":23,"../vnode/is-vnode.js":26,"../vnode/is-vtext.js":27,"../vnode/is-widget.js":28,"./apply-properties":15,"global/document":11}],17:[function(require,module,exports){ | |
// Maps a virtual DOM tree onto a real DOM tree in an efficient manner. | |
// We don't want to read all of the DOM nodes in the tree so we use | |
// the in-order tree indexing to eliminate recursion down certain branches. | |
// We only recurse into a DOM node if we know that it contains a child of | |
// interest. | |
var noChild = {} | |
module.exports = domIndex | |
function domIndex(rootNode, tree, indices, nodes) { | |
if (!indices || indices.length === 0) { | |
return {} | |
} else { | |
indices.sort(ascending) | |
return recurse(rootNode, tree, indices, nodes, 0) | |
} | |
} | |
function recurse(rootNode, tree, indices, nodes, rootIndex) { | |
nodes = nodes || {} | |
if (rootNode) { | |
if (indexInRange(indices, rootIndex, rootIndex)) { | |
nodes[rootIndex] = rootNode | |
} | |
var vChildren = tree.children | |
if (vChildren) { | |
var childNodes = rootNode.childNodes | |
for (var i = 0; i < tree.children.length; i++) { | |
rootIndex += 1 | |
var vChild = vChildren[i] || noChild | |
var nextIndex = rootIndex + (vChild.count || 0) | |
// skip recursion down the tree if there are no nodes down here | |
if (indexInRange(indices, rootIndex, nextIndex)) { | |
recurse(childNodes[i], vChild, indices, nodes, rootIndex) | |
} | |
rootIndex = nextIndex | |
} | |
} | |
} | |
return nodes | |
} | |
// Binary search for an index in the interval [left, right] | |
function indexInRange(indices, left, right) { | |
if (indices.length === 0) { | |
return false | |
} | |
var minIndex = 0 | |
var maxIndex = indices.length - 1 | |
var currentIndex | |
var currentItem | |
while (minIndex <= maxIndex) { | |
currentIndex = ((maxIndex + minIndex) / 2) >> 0 | |
currentItem = indices[currentIndex] | |
if (minIndex === maxIndex) { | |
return currentItem >= left && currentItem <= right | |
} else if (currentItem < left) { | |
minIndex = currentIndex + 1 | |
} else if (currentItem > right) { | |
maxIndex = currentIndex - 1 | |
} else { | |
return true | |
} | |
} | |
return false; | |
} | |
function ascending(a, b) { | |
return a > b ? 1 : -1 | |
} | |
},{}],18:[function(require,module,exports){ | |
var applyProperties = require("./apply-properties") | |
var isWidget = require("../vnode/is-widget.js") | |
var VPatch = require("../vnode/vpatch.js") | |
var updateWidget = require("./update-widget") | |
module.exports = applyPatch | |
function applyPatch(vpatch, domNode, renderOptions) { | |
var type = vpatch.type | |
var vNode = vpatch.vNode | |
var patch = vpatch.patch | |
switch (type) { | |
case VPatch.REMOVE: | |
return removeNode(domNode, vNode) | |
case VPatch.INSERT: | |
return insertNode(domNode, patch, renderOptions) | |
case VPatch.VTEXT: | |
return stringPatch(domNode, vNode, patch, renderOptions) | |
case VPatch.WIDGET: | |
return widgetPatch(domNode, vNode, patch, renderOptions) | |
case VPatch.VNODE: | |
return vNodePatch(domNode, vNode, patch, renderOptions) | |
case VPatch.ORDER: | |
reorderChildren(domNode, patch) | |
return domNode | |
case VPatch.PROPS: | |
applyProperties(domNode, patch, vNode.properties) | |
return domNode | |
case VPatch.THUNK: | |
return replaceRoot(domNode, | |
renderOptions.patch(domNode, patch, renderOptions)) | |
default: | |
return domNode | |
} | |
} | |
function removeNode(domNode, vNode) { | |
var parentNode = domNode.parentNode | |
if (parentNode) { | |
parentNode.removeChild(domNode) | |
} | |
destroyWidget(domNode, vNode); | |
return null | |
} | |
function insertNode(parentNode, vNode, renderOptions) { | |
var newNode = renderOptions.render(vNode, renderOptions) | |
if (parentNode) { | |
parentNode.appendChild(newNode) | |
} | |
return parentNode | |
} | |
function stringPatch(domNode, leftVNode, vText, renderOptions) { | |
var newNode | |
if (domNode.nodeType === 3) { | |
domNode.replaceData(0, domNode.length, vText.text) | |
newNode = domNode | |
} else { | |
var parentNode = domNode.parentNode | |
newNode = renderOptions.render(vText, renderOptions) | |
if (parentNode && newNode !== domNode) { | |
parentNode.replaceChild(newNode, domNode) | |
} | |
} | |
return newNode | |
} | |
function widgetPatch(domNode, leftVNode, widget, renderOptions) { | |
var updating = updateWidget(leftVNode, widget) | |
var newNode | |
if (updating) { | |
newNode = widget.update(leftVNode, domNode) || domNode | |
} else { | |
newNode = renderOptions.render(widget, renderOptions) | |
} | |
var parentNode = domNode.parentNode | |
if (parentNode && newNode !== domNode) { | |
parentNode.replaceChild(newNode, domNode) | |
} | |
if (!updating) { | |
destroyWidget(domNode, leftVNode) | |
} | |
return newNode | |
} | |
function vNodePatch(domNode, leftVNode, vNode, renderOptions) { | |
var parentNode = domNode.parentNode | |
var newNode = renderOptions.render(vNode, renderOptions) | |
if (parentNode && newNode !== domNode) { | |
parentNode.replaceChild(newNode, domNode) | |
} | |
return newNode | |
} | |
function destroyWidget(domNode, w) { | |
if (typeof w.destroy === "function" && isWidget(w)) { | |
w.destroy(domNode) | |
} | |
} | |
function reorderChildren(domNode, moves) { | |
var childNodes = domNode.childNodes | |
var keyMap = {} | |
var node | |
var remove | |
var insert | |
for (var i = 0; i < moves.removes.length; i++) { | |
remove = moves.removes[i] | |
node = childNodes[remove.from] | |
if (remove.key) { | |
keyMap[remove.key] = node | |
} | |
domNode.removeChild(node) | |
} | |
var length = childNodes.length | |
for (var j = 0; j < moves.inserts.length; j++) { | |
insert = moves.inserts[j] | |
node = keyMap[insert.key] | |
// this is the weirdest bug i've ever seen in webkit | |
domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]) | |
} | |
} | |
function replaceRoot(oldRoot, newRoot) { | |
if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { | |
oldRoot.parentNode.replaceChild(newRoot, oldRoot) | |
} | |
return newRoot; | |
} | |
},{"../vnode/is-widget.js":28,"../vnode/vpatch.js":31,"./apply-properties":15,"./update-widget":20}],19:[function(require,module,exports){ | |
var document = require("global/document") | |
var isArray = require("x-is-array") | |
var render = require("./create-element") | |
var domIndex = require("./dom-index") | |
var patchOp = require("./patch-op") | |
module.exports = patch | |
function patch(rootNode, patches, renderOptions) { | |
renderOptions = renderOptions || {} | |
renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch | |
? renderOptions.patch | |
: patchRecursive | |
renderOptions.render = renderOptions.render || render | |
return renderOptions.patch(rootNode, patches, renderOptions) | |
} | |
function patchRecursive(rootNode, patches, renderOptions) { | |
var indices = patchIndices(patches) | |
if (indices.length === 0) { | |
return rootNode | |
} | |
var index = domIndex(rootNode, patches.a, indices) | |
var ownerDocument = rootNode.ownerDocument | |
if (!renderOptions.document && ownerDocument !== document) { | |
renderOptions.document = ownerDocument | |
} | |
for (var i = 0; i < indices.length; i++) { | |
var nodeIndex = indices[i] | |
rootNode = applyPatch(rootNode, | |
index[nodeIndex], | |
patches[nodeIndex], | |
renderOptions) | |
} | |
return rootNode | |
} | |
function applyPatch(rootNode, domNode, patchList, renderOptions) { | |
if (!domNode) { | |
return rootNode | |
} | |
var newNode | |
if (isArray(patchList)) { | |
for (var i = 0; i < patchList.length; i++) { | |
newNode = patchOp(patchList[i], domNode, renderOptions) | |
if (domNode === rootNode) { | |
rootNode = newNode | |
} | |
} | |
} else { | |
newNode = patchOp(patchList, domNode, renderOptions) | |
if (domNode === rootNode) { | |
rootNode = newNode | |
} | |
} | |
return rootNode | |
} | |
function patchIndices(patches) { | |
var indices = [] | |
for (var key in patches) { | |
if (key !== "a") { | |
indices.push(Number(key)) | |
} | |
} | |
return indices | |
} | |
},{"./create-element":16,"./dom-index":17,"./patch-op":18,"global/document":11,"x-is-array":13}],20:[function(require,module,exports){ | |
var isWidget = require("../vnode/is-widget.js") | |
module.exports = updateWidget | |
function updateWidget(a, b) { | |
if (isWidget(a) && isWidget(b)) { | |
if ("name" in a && "name" in b) { | |
return a.id === b.id | |
} else { | |
return a.init === b.init | |
} | |
} | |
return false | |
} | |
},{"../vnode/is-widget.js":28}],21:[function(require,module,exports){ | |
'use strict'; | |
module.exports = SoftSetHook; | |
function SoftSetHook(value) { | |
if (!(this instanceof SoftSetHook)) { | |
return new SoftSetHook(value); | |
} | |
this.value = value; | |
} | |
SoftSetHook.prototype.hook = function (node, propertyName) { | |
if (node[propertyName] !== this.value) { | |
node[propertyName] = this.value; | |
} | |
}; | |
},{}],22:[function(require,module,exports){ | |
'use strict'; | |
var split = require('browser-split'); | |
var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; | |
var notClassId = /^\.|#/; | |
module.exports = parseTag; | |
function parseTag(tag, props) { | |
if (!tag) { | |
return 'DIV'; | |
} | |
var noId = !(props.hasOwnProperty('id')); | |
var tagParts = split(tag, classIdSplit); | |
var tagName = null; | |
if (notClassId.test(tagParts[1])) { | |
tagName = 'DIV'; | |
} | |
var classes, part, type, i; | |
for (i = 0; i < tagParts.length; i++) { | |
part = tagParts[i]; | |
if (!part) { | |
continue; | |
} | |
type = part.charAt(0); | |
if (!tagName) { | |
tagName = part; | |
} else if (type === '.') { | |
classes = classes || []; | |
classes.push(part.substring(1, part.length)); | |
} else if (type === '#' && noId) { | |
props.id = part.substring(1, part.length); | |
} | |
} | |
if (classes) { | |
if (props.className) { | |
classes.push(props.className); | |
} | |
props.className = classes.join(' '); | |
} | |
return props.namespace ? tagName : tagName.toUpperCase(); | |
} | |
},{"browser-split":10}],23:[function(require,module,exports){ | |
var isVNode = require("./is-vnode") | |
var isVText = require("./is-vtext") | |
var isWidget = require("./is-widget") | |
var isThunk = require("./is-thunk") | |
module.exports = handleThunk | |
function handleThunk(a, b) { | |
var renderedA = a | |
var renderedB = b | |
if (isThunk(b)) { | |
renderedB = renderThunk(b, a) | |
} | |
if (isThunk(a)) { | |
renderedA = renderThunk(a, null) | |
} | |
return { | |
a: renderedA, | |
b: renderedB | |
} | |
} | |
function renderThunk(thunk, previous) { | |
var renderedThunk = thunk.vnode | |
if (!renderedThunk) { | |
renderedThunk = thunk.vnode = thunk.render(previous) | |
} | |
if (!(isVNode(renderedThunk) || | |
isVText(renderedThunk) || | |
isWidget(renderedThunk))) { | |
throw new Error("thunk did not return a valid node"); | |
} | |
return renderedThunk | |
} | |
},{"./is-thunk":24,"./is-vnode":26,"./is-vtext":27,"./is-widget":28}],24:[function(require,module,exports){ | |
module.exports = isThunk | |
function isThunk(t) { | |
return t && t.type === "Thunk" | |
} | |
},{}],25:[function(require,module,exports){ | |
module.exports = isHook | |
function isHook(hook) { | |
return hook && | |
(typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || | |
typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")) | |
} | |
},{}],26:[function(require,module,exports){ | |
var version = require("./version") | |
module.exports = isVirtualNode | |
function isVirtualNode(x) { | |
return x && x.type === "VirtualNode" && x.version === version | |
} | |
},{"./version":29}],27:[function(require,module,exports){ | |
var version = require("./version") | |
module.exports = isVirtualText | |
function isVirtualText(x) { | |
return x && x.type === "VirtualText" && x.version === version | |
} | |
},{"./version":29}],28:[function(require,module,exports){ | |
module.exports = isWidget | |
function isWidget(w) { | |
return w && w.type === "Widget" | |
} | |
},{}],29:[function(require,module,exports){ | |
module.exports = "2" | |
},{}],30:[function(require,module,exports){ | |
var version = require("./version") | |
var isVNode = require("./is-vnode") | |
var isWidget = require("./is-widget") | |
var isThunk = require("./is-thunk") | |
var isVHook = require("./is-vhook") | |
module.exports = VirtualNode | |
var noProperties = {} | |
var noChildren = [] | |
function VirtualNode(tagName, properties, children, key, namespace) { | |
this.tagName = tagName | |
this.properties = properties || noProperties | |
this.children = children || noChildren | |
this.key = key != null ? String(key) : undefined | |
this.namespace = (typeof namespace === "string") ? namespace : null | |
var count = (children && children.length) || 0 | |
var descendants = 0 | |
var hasWidgets = false | |
var hasThunks = false | |
var descendantHooks = false | |
var hooks | |
for (var propName in properties) { | |
if (properties.hasOwnProperty(propName)) { | |
var property = properties[propName] | |
if (isVHook(property) && property.unhook) { | |
if (!hooks) { | |
hooks = {} | |
} | |
hooks[propName] = property | |
} | |
} | |
} | |
for (var i = 0; i < count; i++) { | |
var child = children[i] | |
if (isVNode(child)) { | |
descendants += child.count || 0 | |
if (!hasWidgets && child.hasWidgets) { | |
hasWidgets = true | |
} | |
if (!hasThunks && child.hasThunks) { | |
hasThunks = true | |
} | |
if (!descendantHooks && (child.hooks || child.descendantHooks)) { | |
descendantHooks = true | |
} | |
} else if (!hasWidgets && isWidget(child)) { | |
if (typeof child.destroy === "function") { | |
hasWidgets = true | |
} | |
} else if (!hasThunks && isThunk(child)) { | |
hasThunks = true; | |
} | |
} | |
this.count = count + descendants | |
this.hasWidgets = hasWidgets | |
this.hasThunks = hasThunks | |
this.hooks = hooks | |
this.descendantHooks = descendantHooks | |
} | |
VirtualNode.prototype.version = version | |
VirtualNode.prototype.type = "VirtualNode" | |
},{"./is-thunk":24,"./is-vhook":25,"./is-vnode":26,"./is-widget":28,"./version":29}],31:[function(require,module,exports){ | |
var version = require("./version") | |
VirtualPatch.NONE = 0 | |
VirtualPatch.VTEXT = 1 | |
VirtualPatch.VNODE = 2 | |
VirtualPatch.WIDGET = 3 | |
VirtualPatch.PROPS = 4 | |
VirtualPatch.ORDER = 5 | |
VirtualPatch.INSERT = 6 | |
VirtualPatch.REMOVE = 7 | |
VirtualPatch.THUNK = 8 | |
module.exports = VirtualPatch | |
function VirtualPatch(type, vNode, patch) { | |
this.type = Number(type) | |
this.vNode = vNode | |
this.patch = patch | |
} | |
VirtualPatch.prototype.version = version | |
VirtualPatch.prototype.type = "VirtualPatch" | |
},{"./version":29}],32:[function(require,module,exports){ | |
var version = require("./version") | |
module.exports = VirtualText | |
function VirtualText(text) { | |
this.text = String(text) | |
} | |
VirtualText.prototype.version = version | |
VirtualText.prototype.type = "VirtualText" | |
},{"./version":29}],33:[function(require,module,exports){ | |
var isObject = require("is-object") | |
var isHook = require("../vnode/is-vhook") | |
module.exports = diffProps | |
function diffProps(a, b) { | |
var diff | |
for (var aKey in a) { | |
if (!(aKey in b)) { | |
diff = diff || {} | |
diff[aKey] = undefined | |
} | |
var aValue = a[aKey] | |
var bValue = b[aKey] | |
if (aValue === bValue) { | |
continue | |
} else if (isObject(aValue) && isObject(bValue)) { | |
if (getPrototype(bValue) !== getPrototype(aValue)) { | |
diff = diff || {} | |
diff[aKey] = bValue | |
} else if (isHook(bValue)) { | |
diff = diff || {} | |
diff[aKey] = bValue | |
} else { | |
var objectDiff = diffProps(aValue, bValue) | |
if (objectDiff) { | |
diff = diff || {} | |
diff[aKey] = objectDiff | |
} | |
} | |
} else { | |
diff = diff || {} | |
diff[aKey] = bValue | |
} | |
} | |
for (var bKey in b) { | |
if (!(bKey in a)) { | |
diff = diff || {} | |
diff[bKey] = b[bKey] | |
} | |
} | |
return diff | |
} | |
function getPrototype(value) { | |
if (Object.getPrototypeOf) { | |
return Object.getPrototypeOf(value) | |
} else if (value.__proto__) { | |
return value.__proto__ | |
} else if (value.constructor) { | |
return value.constructor.prototype | |
} | |
} | |
},{"../vnode/is-vhook":25,"is-object":12}],34:[function(require,module,exports){ | |
var isArray = require("x-is-array") | |
var VPatch = require("../vnode/vpatch") | |
var isVNode = require("../vnode/is-vnode") | |
var isVText = require("../vnode/is-vtext") | |
var isWidget = require("../vnode/is-widget") | |
var isThunk = require("../vnode/is-thunk") | |
var handleThunk = require("../vnode/handle-thunk") | |
var diffProps = require("./diff-props") | |
module.exports = diff | |
function diff(a, b) { | |
var patch = { a: a } | |
walk(a, b, patch, 0) | |
return patch | |
} | |
function walk(a, b, patch, index) { | |
if (a === b) { | |
return | |
} | |
var apply = patch[index] | |
var applyClear = false | |
if (isThunk(a) || isThunk(b)) { | |
thunks(a, b, patch, index) | |
} else if (b == null) { | |
// If a is a widget we will add a remove patch for it | |
// Otherwise any child widgets/hooks must be destroyed. | |
// This prevents adding two remove patches for a widget. | |
if (!isWidget(a)) { | |
clearState(a, patch, index) | |
apply = patch[index] | |
} | |
apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)) | |
} else if (isVNode(b)) { | |
if (isVNode(a)) { | |
if (a.tagName === b.tagName && | |
a.namespace === b.namespace && | |
a.key === b.key) { | |
var propsPatch = diffProps(a.properties, b.properties) | |
if (propsPatch) { | |
apply = appendPatch(apply, | |
new VPatch(VPatch.PROPS, a, propsPatch)) | |
} | |
apply = diffChildren(a, b, patch, apply, index) | |
} else { | |
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) | |
applyClear = true | |
} | |
} else { | |
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) | |
applyClear = true | |
} | |
} else if (isVText(b)) { | |
if (!isVText(a)) { | |
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) | |
applyClear = true | |
} else if (a.text !== b.text) { | |
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) | |
} | |
} else if (isWidget(b)) { | |
if (!isWidget(a)) { | |
applyClear = true | |
} | |
apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)) | |
} | |
if (apply) { | |
patch[index] = apply | |
} | |
if (applyClear) { | |
clearState(a, patch, index) | |
} | |
} | |
function diffChildren(a, b, patch, apply, index) { | |
var aChildren = a.children | |
var orderedSet = reorder(aChildren, b.children) | |
var bChildren = orderedSet.children | |
var aLen = aChildren.length | |
var bLen = bChildren.length | |
var len = aLen > bLen ? aLen : bLen | |
for (var i = 0; i < len; i++) { | |
var leftNode = aChildren[i] | |
var rightNode = bChildren[i] | |
index += 1 | |
if (!leftNode) { | |
if (rightNode) { | |
// Excess nodes in b need to be added | |
apply = appendPatch(apply, | |
new VPatch(VPatch.INSERT, null, rightNode)) | |
} | |
} else { | |
walk(leftNode, rightNode, patch, index) | |
} | |
if (isVNode(leftNode) && leftNode.count) { | |
index += leftNode.count | |
} | |
} | |
if (orderedSet.moves) { | |
// Reorder nodes last | |
apply = appendPatch(apply, new VPatch( | |
VPatch.ORDER, | |
a, | |
orderedSet.moves | |
)) | |
} | |
return apply | |
} | |
function clearState(vNode, patch, index) { | |
// TODO: Make this a single walk, not two | |
unhook(vNode, patch, index) | |
destroyWidgets(vNode, patch, index) | |
} | |
// Patch records for all destroyed widgets must be added because we need | |
// a DOM node reference for the destroy function | |
function destroyWidgets(vNode, patch, index) { | |
if (isWidget(vNode)) { | |
if (typeof vNode.destroy === "function") { | |
patch[index] = appendPatch( | |
patch[index], | |
new VPatch(VPatch.REMOVE, vNode, null) | |
) | |
} | |
} else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { | |
var children = vNode.children | |
var len = children.length | |
for (var i = 0; i < len; i++) { | |
var child = children[i] | |
index += 1 | |
destroyWidgets(child, patch, index) | |
if (isVNode(child) && child.count) { | |
index += child.count | |
} | |
} | |
} else if (isThunk(vNode)) { | |
thunks(vNode, null, patch, index) | |
} | |
} | |
// Create a sub-patch for thunks | |
function thunks(a, b, patch, index) { | |
var nodes = handleThunk(a, b) | |
var thunkPatch = diff(nodes.a, nodes.b) | |
if (hasPatches(thunkPatch)) { | |
patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch) | |
} | |
} | |
function hasPatches(patch) { | |
for (var index in patch) { | |
if (index !== "a") { | |
return true | |
} | |
} | |
return false | |
} | |
// Execute hooks when two nodes are identical | |
function unhook(vNode, patch, index) { | |
if (isVNode(vNode)) { | |
if (vNode.hooks) { | |
patch[index] = appendPatch( | |
patch[index], | |
new VPatch( | |
VPatch.PROPS, | |
vNode, | |
undefinedKeys(vNode.hooks) | |
) | |
) | |
} | |
if (vNode.descendantHooks || vNode.hasThunks) { | |
var children = vNode.children | |
var len = children.length | |
for (var i = 0; i < len; i++) { | |
var child = children[i] | |
index += 1 | |
unhook(child, patch, index) | |
if (isVNode(child) && child.count) { | |
index += child.count | |
} | |
} | |
} | |
} else if (isThunk(vNode)) { | |
thunks(vNode, null, patch, index) | |
} | |
} | |
function undefinedKeys(obj) { | |
var result = {} | |
for (var key in obj) { | |
result[key] = undefined | |
} | |
return result | |
} | |
// List diff, naive left to right reordering | |
function reorder(aChildren, bChildren) { | |
// O(M) time, O(M) memory | |
var bChildIndex = keyIndex(bChildren) | |
var bKeys = bChildIndex.keys | |
var bFree = bChildIndex.free | |
if (bFree.length === bChildren.length) { | |
return { | |
children: bChildren, | |
moves: null | |
} | |
} | |
// O(N) time, O(N) memory | |
var aChildIndex = keyIndex(aChildren) | |
var aKeys = aChildIndex.keys | |
var aFree = aChildIndex.free | |
if (aFree.length === aChildren.length) { | |
return { | |
children: bChildren, | |
moves: null | |
} | |
} | |
// O(MAX(N, M)) memory | |
var newChildren = [] | |
var freeIndex = 0 | |
var freeCount = bFree.length | |
var deletedItems = 0 | |
// Iterate through a and match a node in b | |
// O(N) time, | |
for (var i = 0 ; i < aChildren.length; i++) { | |
var aItem = aChildren[i] | |
var itemIndex | |
if (aItem.key) { | |
if (bKeys.hasOwnProperty(aItem.key)) { | |
// Match up the old keys | |
itemIndex = bKeys[aItem.key] | |
newChildren.push(bChildren[itemIndex]) | |
} else { | |
// Remove old keyed items | |
itemIndex = i - deletedItems++ | |
newChildren.push(null) | |
} | |
} else { | |
// Match the item in a with the next free item in b | |
if (freeIndex < freeCount) { | |
itemIndex = bFree[freeIndex++] | |
newChildren.push(bChildren[itemIndex]) | |
} else { | |
// There are no free items in b to match with | |
// the free items in a, so the extra free nodes | |
// are deleted. | |
itemIndex = i - deletedItems++ | |
newChildren.push(null) | |
} | |
} | |
} | |
var lastFreeIndex = freeIndex >= bFree.length ? | |
bChildren.length : | |
bFree[freeIndex] | |
// Iterate through b and append any new keys | |
// O(M) time | |
for (var j = 0; j < bChildren.length; j++) { | |
var newItem = bChildren[j] | |
if (newItem.key) { | |
if (!aKeys.hasOwnProperty(newItem.key)) { | |
// Add any new keyed items | |
// We are adding new items to the end and then sorting them | |
// in place. In future we should insert new items in place. | |
newChildren.push(newItem) | |
} | |
} else if (j >= lastFreeIndex) { | |
// Add any leftover non-keyed items | |
newChildren.push(newItem) | |
} | |
} | |
var simulate = newChildren.slice() | |
var simulateIndex = 0 | |
var removes = [] | |
var inserts = [] | |
var simulateItem | |
for (var k = 0; k < bChildren.length;) { | |
var wantedItem = bChildren[k] | |
simulateItem = simulate[simulateIndex] | |
// remove items | |
while (simulateItem === null && simulate.length) { | |
removes.push(remove(simulate, simulateIndex, null)) | |
simulateItem = simulate[simulateIndex] | |
} | |
if (!simulateItem || simulateItem.key !== wantedItem.key) { | |
// if we need a key in this position... | |
if (wantedItem.key) { | |
if (simulateItem && simulateItem.key) { | |
// if an insert doesn't put this key in place, it needs to move | |
if (bKeys[simulateItem.key] !== k + 1) { | |
removes.push(remove(simulate, simulateIndex, simulateItem.key)) | |
simulateItem = simulate[simulateIndex] | |
// if the remove didn't put the wanted item in place, we need to insert it | |
if (!simulateItem || simulateItem.key !== wantedItem.key) { | |
inserts.push({key: wantedItem.key, to: k}) | |
} | |
// items are matching, so skip ahead | |
else { | |
simulateIndex++ | |
} | |
} | |
else { | |
inserts.push({key: wantedItem.key, to: k}) | |
} | |
} | |
else { | |
inserts.push({key: wantedItem.key, to: k}) | |
} | |
k++ | |
} | |
// a key in simulate has no matching wanted key, remove it | |
else if (simulateItem && simulateItem.key) { | |
removes.push(remove(simulate, simulateIndex, simulateItem.key)) | |
} | |
} | |
else { | |
simulateIndex++ | |
k++ | |
} | |
} | |
// remove all the remaining nodes from simulate | |
while(simulateIndex < simulate.length) { | |
simulateItem = simulate[simulateIndex] | |
removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)) | |
} | |
// If the only moves we have are deletes then we can just | |
// let the delete patch remove these items. | |
if (removes.length === deletedItems && !inserts.length) { | |
return { | |
children: newChildren, | |
moves: null | |
} | |
} | |
return { | |
children: newChildren, | |
moves: { | |
removes: removes, | |
inserts: inserts | |
} | |
} | |
} | |
function remove(arr, index, key) { | |
arr.splice(index, 1) | |
return { | |
from: index, | |
key: key | |
} | |
} | |
function keyIndex(children) { | |
var keys = {} | |
var free = [] | |
var length = children.length | |
for (var i = 0; i < length; i++) { | |
var child = children[i] | |
if (child.key) { | |
keys[child.key] = i | |
} else { | |
free.push(i) | |
} | |
} | |
return { | |
keys: keys, // A hash of key name to index | |
free: free // An array of unkeyed item indices | |
} | |
} | |
function appendPatch(apply, patch) { | |
if (apply) { | |
if (isArray(apply)) { | |
apply.push(patch) | |
} else { | |
apply = [apply, patch] | |
} | |
return apply | |
} else { | |
return patch | |
} | |
} | |
},{"../vnode/handle-thunk":23,"../vnode/is-thunk":24,"../vnode/is-vnode":26,"../vnode/is-vtext":27,"../vnode/is-widget":28,"../vnode/vpatch":31,"./diff-props":33,"x-is-array":13}],35:[function(require,module,exports){ | |
var simplePromise = require('./simplePromise'); | |
function Render(mount) { | |
this.finished = simplePromise(); | |
this.mount = mount; | |
this.attachment = mount; | |
} | |
module.exports = Render; | |
},{"./simplePromise":39}],36:[function(require,module,exports){ | |
(function (global){ | |
var h = require('./vhtml'); | |
var domComponent = require('./domComponent'); | |
var bindingMeta = require('./meta'); | |
var toVdom = require('./toVdom'); | |
var parseTag = require('virtual-dom/virtual-hyperscript/parse-tag'); | |
var ViewModel = require('./viewModel'); | |
var Mount = require('./mount'); | |
var runRender = require('./runRender'); | |
var deprecations = require('./deprecations'); | |
var hyperdom = require('.'); | |
function isViewModelOrComponent(component) { | |
return component | |
&& ((typeof component.init === 'function' | |
&& typeof component.update === 'function' | |
&& typeof component.destroy === 'function') || (typeof component.renderViewModel === 'function')); | |
} | |
exports.merge = function (element, render, model, options) { | |
var mount = startAttachment(render, model, options, function(mount, domComponentOptions) { | |
var component = domComponent(domComponentOptions); | |
var currentRender = hyperdom.currentRender; | |
currentRender.eventHandlerWrapper = function() { | |
return null; | |
}; | |
var vdom = mount.render(); | |
component.merge(vdom, element); | |
return component; | |
}); | |
mount.rerender(); | |
return mount; | |
}; | |
exports.append = function (element, render, model, options) { | |
return startAttachment(render, model, options, function(mount, domComponentOptions) { | |
var component = domComponent(domComponentOptions); | |
var vdom = mount.render(); | |
element.appendChild(component.create(vdom)); | |
return component; | |
}); | |
}; | |
exports.replace = function (element, render, model, options) { | |
return startAttachment(render, model, options, function(mount, domComponentOptions) { | |
var component = domComponent(domComponentOptions); | |
var vdom = mount.render(); | |
element.parentNode.replaceChild(component.create(vdom), element); | |
return component; | |
}); | |
}; | |
exports.appendVDom = function (vdom, render, model, options) { | |
return startAttachment(render, model, options, function(mount) { | |
var component = { | |
create: function(newVDom) { | |
vdom.children = []; | |
if (newVDom) { | |
vdom.children.push(newVDom); | |
} | |
}, | |
update: function(newVDom) { | |
vdom.children = []; | |
if (newVDom) { | |
vdom.children.push(newVDom); | |
} | |
} | |
}; | |
component.create(mount.render()); | |
return component; | |
}); | |
}; | |
exports.ViewModel = ViewModel; | |
function startAttachment(render, model, options, attachToDom) { | |
if (typeof render == 'object' && typeof render.render == 'function') { | |
return start(render, attachToDom, model); | |
} else { | |
deprecations.renderFunction('hyperdom.append and hyperdom.replace with render functions are deprecated, please pass a ViewModel'); | |
return start({render: function () { return render(model); }}, attachToDom, options); | |
} | |
} | |
function start(model, attachToDom, options) { | |
var mount = new Mount(model, options); | |
runRender(mount, function () { | |
if (options) { | |
var domComponentOptions = {document: options.document}; | |
} | |
mount.component = attachToDom(mount, domComponentOptions); | |
}); | |
return mount; | |
} | |
var norefresh = {}; | |
function norefreshFunction() { | |
return norefresh; | |
} | |
function refreshify(fn, options) { | |
if (!fn) { | |
return fn; | |
} | |
var currentRender = hyperdom.currentRender(); | |
if (!currentRender) { | |
if (typeof global === 'object') { | |
return fn; | |
} else { | |
throw new Error('You cannot create virtual-dom event handlers outside a render function. See https://github.com/featurist/hyperdom#outside-render-cycle'); | |
} | |
} | |
var mount = currentRender.mount; | |
var handleEventResult = exports.createEventResultHandler(mount, options); | |
if (options && (options.norefresh == true || options.refresh == false)) { | |
return fn; | |
} | |
return function () { | |
var result = fn.apply(this, arguments); | |
return handleEventResult(result); | |
}; | |
} | |
exports.createEventResultHandler = function(mount, options) { | |
var onlyRefreshAfterPromise = options && options.refresh == 'promise'; | |
var viewModelToRefresh = options && options.viewModel; | |
var componentToRefresh = options && options.component; | |
function handleEventResult(result, promiseResult) { | |
if (result && typeof(result.then) == 'function') { | |
result.then(function (result) { handleEventResult(result, true); }); | |
} | |
if (onlyRefreshAfterPromise && !promiseResult) { | |
return; | |
} | |
if (isViewModelOrComponent(result)) { | |
mount.rerenderWidget(result); | |
} else if (result instanceof Array) { | |
for (var i = 0; i < result.length; i++) { | |
handleEventResult(result[i]); | |
} | |
} else if (viewModelToRefresh) { | |
viewModelToRefresh.rerenderViewModel(); | |
} else if (componentToRefresh) { | |
componentToRefresh.refresh(); | |
} else if (result === norefresh) { | |
// don't refresh; | |
} else if (result === norefreshFunction) { | |
deprecations.norefresh('hyperdom.html.norefresh is deprecated, please use hyperdom.norefresh()'); | |
// don't refresh; | |
} else { | |
mount.rerender(); | |
return result; | |
} | |
} | |
return handleEventResult; | |
}; | |
function bindTextInput(attributes, children, get, set) { | |
var textEventNames = ['onkeyup', 'oninput', 'onpaste', 'textInput']; | |
var bindingValue = get(); | |
if (!(bindingValue instanceof Error)) { | |
attributes.value = bindingValue != undefined? bindingValue: ''; | |
} | |
attachEventHandler(attributes, textEventNames, function (ev) { | |
if (bindingValue != ev.target.value) { | |
set(ev.target.value); | |
} | |
}); | |
} | |
function sequenceFunctions(handler1, handler2) { | |
return function (ev) { | |
handler1(ev); | |
return handler2(ev); | |
}; | |
} | |
function insertEventHandler(attributes, eventName, handler) { | |
var previousHandler = attributes[eventName]; | |
if (previousHandler) { | |
attributes[eventName] = sequenceFunctions(handler, previousHandler); | |
} else { | |
attributes[eventName] = handler; | |
} | |
} | |
function attachEventHandler(attributes, eventNames, handler) { | |
if (eventNames instanceof Array) { | |
for (var n = 0; n < eventNames.length; n++) { | |
insertEventHandler(attributes, eventNames[n], handler); | |
} | |
} else { | |
insertEventHandler(attributes, eventNames, handler); | |
} | |
} | |
function ListenerHook(listener) { | |
this.listener = exports.html.refreshify(listener); | |
} | |
ListenerHook.prototype.hook = function (element, propertyName) { | |
element.addEventListener(propertyName.substring(2), this.listener, false); | |
}; | |
ListenerHook.prototype.unhook = function (element, propertyName) { | |
element.removeEventListener(propertyName.substring(2), this.listener); | |
}; | |
function customEvent(name) { | |
if (typeof Event == 'function') { | |
return new Event(name); | |
} else { | |
var event = document.createEvent('Event'); | |
event.initEvent(name, false, false); | |
return event; | |
} | |
} | |
var inputTypeBindings = { | |
text: bindTextInput, | |
textarea: bindTextInput, | |
checkbox: function (attributes, children, get, set) { | |
attributes.checked = get(); | |
attachEventHandler(attributes, 'onclick', function (ev) { | |
attributes.checked = ev.target.checked; | |
set(ev.target.checked); | |
}); | |
}, | |
radio: function (attributes, children, get, set) { | |
var value = attributes.value; | |
attributes.checked = get() == attributes.value; | |
attributes.on_hyperdomsyncchecked = new ListenerHook(function (event) { | |
attributes.checked = event.target.checked; | |
}); | |
attachEventHandler(attributes, 'onclick', function (event) { | |
var name = event.target.name; | |
if (name) { | |
var inputs = document.getElementsByName(name); | |
for (var i = 0, l = inputs.length; i < l; i++) { | |
inputs[i].dispatchEvent(customEvent('_hyperdomsyncchecked')); | |
} | |
} | |
set(value); | |
}); | |
}, | |
select: function (attributes, children, get, set) { | |
var currentValue = get(); | |
var options = children.filter(function (child) { | |
return child.tagName.toLowerCase() == 'option'; | |
}); | |
var values = []; | |
var selectedIndex; | |
for(var n = 0; n < options.length; n++) { | |
var option = options[n]; | |
var hasValue = option.properties.hasOwnProperty('value'); | |
var value = option.properties.value; | |
var text = option.children.map(function (x) { return x.text; }).join(''); | |
values.push(hasValue? value: text); | |
var selected = value == currentValue || text == currentValue; | |
if (selected) { | |
selectedIndex = n; | |
} | |
option.properties.selected = selected; | |
option.properties.value = n; | |
} | |
if (selectedIndex !== undefined) { | |
attributes.selectedIndex = selectedIndex; | |
} | |
attachEventHandler(attributes, 'onchange', function (ev) { | |
attributes.selectedIndex = ev.target.selectedIndex; | |
set(values[ev.target.value]); | |
}); | |
}, | |
file: function (attributes, children, get, set) { | |
var multiple = attributes.multiple; | |
attachEventHandler(attributes, 'onchange', function (ev) { | |
if (multiple) { | |
set(ev.target.files); | |
} else { | |
set(ev.target.files[0]); | |
} | |
}); | |
} | |
}; | |
function bindModel(attributes, children, type) { | |
var bind = inputTypeBindings[type] || bindTextInput; | |
var bindingAttr = makeBinding(attributes.binding); | |
bind(attributes, children, bindingAttr.get, bindingAttr.set); | |
} | |
function inputType(selector, attributes) { | |
if (/^textarea\b/i.test(selector)) { | |
return 'textarea'; | |
} else if (/^select\b/i.test(selector)) { | |
return 'select'; | |
} else { | |
return attributes.type || 'text'; | |
} | |
} | |
var renames = { | |
for: 'htmlFor', | |
class: 'className', | |
contenteditable: 'contentEditable', | |
tabindex: 'tabIndex', | |
colspan: 'colSpan' | |
}; | |
var dataAttributeRegex = /^data-/; | |
function prepareAttributes(tag, attributes, childElements) { | |
var keys = Object.keys(attributes); | |
var dataset; | |
var currentRender = hyperdom.currentRender(); | |
var eventHandlerWrapper = currentRender && currentRender.eventHandlerWrapper; | |
for (var k = 0; k < keys.length; k++) { | |
var key = keys[k]; | |
var attribute = attributes[key]; | |
if (typeof(attribute) == 'function') { | |
if (eventHandlerWrapper) { | |
var fn = eventHandlerWrapper.call(undefined, key.replace(/^on/, ''), attribute); | |
attributes[key] = typeof fn === 'function'? refreshify(fn): fn; | |
} else { | |
attributes[key] = refreshify(attribute); | |
} | |
} | |
var rename = renames[key]; | |
if (rename) { | |
attributes[rename] = attribute; | |
delete attributes[key]; | |
continue; | |
} | |
if (dataAttributeRegex.test(key)) { | |
if (!dataset) { | |
dataset = attributes.dataset; | |
if (!dataset) { | |
dataset = attributes.dataset = {}; | |
} | |
} | |
var datakey = key | |
.replace(dataAttributeRegex, '') | |
.replace(/-([a-z])/ig, function(_, x) { return x.toUpperCase(); }); | |
dataset[datakey] = attribute; | |
delete attributes[key]; | |
continue; | |
} | |
} | |
if (attributes.className) { | |
attributes.className = generateClassName(attributes.className); | |
} | |
if (attributes.binding) { | |
bindModel(attributes, childElements, inputType(tag, attributes)); | |
delete attributes.binding; | |
} | |
} | |
/** | |
* this function is quite ugly and you may be very tempted | |
* to refactor it into smaller functions, I certainly am. | |
* however, it was written like this for performance | |
* so think of that before refactoring! :) | |
*/ | |
exports.html = function (hierarchySelector) { | |
var hasHierarchy = hierarchySelector.indexOf(' ') >= 0; | |
var selector, selectorElements; | |
if (hasHierarchy) { | |
selectorElements = hierarchySelector.match(/\S+/g); | |
selector = selectorElements[selectorElements.length - 1]; | |
} else { | |
selector = hierarchySelector; | |
} | |
var childElements; | |
var vdom; | |
var tag; | |
var attributes = arguments[1]; | |
if (attributes && attributes.constructor == Object && typeof attributes.render !== 'function') { | |
childElements = toVdom.recursive(Array.prototype.slice.call(arguments, 2)); | |
prepareAttributes(selector, attributes, childElements); | |
tag = parseTag(selector, attributes); | |
vdom = h(tag, attributes, childElements); | |
} else { | |
attributes = {}; | |
childElements = toVdom.recursive(Array.prototype.slice.call(arguments, 1)); | |
tag = parseTag(selector, attributes); | |
vdom = h(tag, attributes, childElements); | |
} | |
if (hasHierarchy) { | |
for(var n = selectorElements.length - 2; n >= 0; n--) { | |
vdom = h(selectorElements[n], {}, [vdom]); | |
} | |
} | |
return vdom; | |
}; | |
exports.jsx = function (tag, attributes) { | |
var childElements = toVdom.recursive(Array.prototype.slice.call(arguments, 2)); | |
if (attributes) { | |
prepareAttributes(tag, attributes, childElements); | |
} | |
return h(tag, attributes || {}, childElements); | |
}; | |
Object.defineProperty(exports.html, 'currentRender', {get: function () { | |
deprecations.currentRender('hyperdom.html.currentRender is deprecated, please use hyperdom.currentRender() instead'); | |
return exports.html._currentRender; | |
}}); | |
Object.defineProperty(exports.html, 'refresh', {get: function () { | |
deprecations.refresh('hyperdom.html.refresh is deprecated, please use viewModel.rerender() instead'); | |
return exports.html._refresh; | |
}}); | |
function refreshAfter(promise) { | |
deprecations.refreshAfter('hyperdom.html.refreshAfter is deprecated'); | |
var refresh = exports.html.refresh; | |
promise.then(refresh); | |
} | |
exports.html.refreshify = refreshify; | |
exports.html.refreshAfter = refreshAfter; | |
exports.html.norefresh = norefresh; | |
function makeBinding(b, options) { | |
var binding = b instanceof Array | |
? bindingObject.apply(undefined, b) | |
: b; | |
binding.set = refreshify(binding.set, options); | |
return binding; | |
} | |
function makeConverter(converter) { | |
if (typeof converter == 'function') { | |
return { | |
view: function (model) { | |
return model; | |
}, | |
model: function (view) { | |
return converter(view); | |
} | |
}; | |
} else { | |
return converter; | |
} | |
} | |
function chainConverters(startIndex, converters) { | |
function makeConverters() { | |
if (!_converters) { | |
_converters = new Array(converters.length - startIndex); | |
for(var n = startIndex; n < converters.length; n++) { | |
_converters[n - startIndex] = makeConverter(converters[n]); | |
} | |
} | |
} | |
if ((converters.length - startIndex) == 1) { | |
return makeConverter(converters[startIndex]); | |
} else { | |
var _converters; | |
return { | |
view: function (model) { | |
makeConverters(); | |
var intermediateValue = model; | |
for(var n = 0; n < _converters.length; n++) { | |
intermediateValue = _converters[n].view(intermediateValue); | |
} | |
return intermediateValue; | |
}, | |
model: function (view) { | |
makeConverters(); | |
var intermediateValue = view; | |
for(var n = _converters.length - 1; n >= 0; n--) { | |
intermediateValue = _converters[n].model(intermediateValue); | |
} | |
return intermediateValue; | |
} | |
}; | |
} | |
} | |
function bindingObject(model, property) { | |
var _meta; | |
function hyperdomMeta() { | |
return _meta || (_meta = bindingMeta(model, property)); | |
} | |
if (arguments.length > 2) { | |
var converter = chainConverters(2, arguments); | |
return { | |
get: function() { | |
var meta = hyperdomMeta(); | |
var modelValue = model[property]; | |
var modelText; | |
if (meta.error) { | |
return meta.view; | |
} else if (meta.view === undefined) { | |
modelText = converter.view(modelValue); | |
meta.view = modelText; | |
return modelText; | |
} else { | |
var previousValue = converter.model(meta.view); | |
modelText = converter.view(modelValue); | |
var normalisedPreviousText = converter.view(previousValue); | |
if (modelText === normalisedPreviousText) { | |
return meta.view; | |
} else { | |
meta.view = modelText; | |
return modelText; | |
} | |
} | |
}, | |
set: function(view) { | |
var meta = hyperdomMeta(); | |
meta.view = view; | |
try { | |
model[property] = converter.model(view, model[property]); | |
delete meta.error; | |
} catch (e) { | |
meta.error = e; | |
} | |
}, | |
meta: function() { | |
return hyperdomMeta(); | |
} | |
}; | |
} else { | |
return { | |
get: function () { | |
return model[property]; | |
}, | |
set: function (value) { | |
model[property] = value; | |
}, | |
meta: function() { | |
return hyperdomMeta(); | |
} | |
}; | |
} | |
} | |
exports.binding = makeBinding; | |
exports.html.binding = makeBinding; | |
exports.html.meta = bindingMeta; | |
function rawHtml() { | |
var selector; | |
var html; | |
var options; | |
if (arguments.length == 2) { | |
selector = arguments[0]; | |
html = arguments[1]; | |
options = {innerHTML: html}; | |
return exports.html(selector, options); | |
} else { | |
selector = arguments[0]; | |
options = arguments[1]; | |
html = arguments[2]; | |
options.innerHTML = html; | |
return exports.html(selector, options); | |
} | |
} | |
exports.html.rawHtml = rawHtml; | |
function generateConditionalClassNames(obj) { | |
return Object.keys(obj).filter(function (key) { | |
return obj[key]; | |
}).join(' ') || undefined; | |
} | |
function generateClassName(obj) { | |
if (typeof(obj) == 'object') { | |
if (obj instanceof Array) { | |
var names = obj.map(function(item) { | |
return generateClassName(item); | |
}); | |
return names.join(' ') || undefined; | |
} else { | |
return generateConditionalClassNames(obj); | |
} | |
} else { | |
return obj; | |
} | |
} | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{".":"hyperdom","./deprecations":3,"./domComponent":4,"./meta":6,"./mount":7,"./runRender":37,"./toVdom":40,"./vhtml":41,"./viewModel":42,"virtual-dom/virtual-hyperscript/parse-tag":22}],37:[function(require,module,exports){ | |
var hyperdom = require('.'); | |
var Render = require('./render'); | |
var rendering = require('./rendering'); | |
function refreshOutOfRender() { | |
throw new Error('Please assign hyperdom.html.refresh during a render cycle if you want to use it in event handlers. See https://github.com/featurist/hyperdom#refresh-outside-render-cycle'); | |
} | |
module.exports = function(mount, fn) { | |
var render = new Render(mount); | |
try { | |
hyperdom._currentRender = render; | |
rendering.html._currentRender = render; | |
rendering.html._refresh = rendering.createEventResultHandler(mount); | |
fn(); | |
} finally { | |
render.finished.fulfill(); | |
hyperdom._currentRender = undefined; | |
rendering.html._refresh = refreshOutOfRender; | |
rendering.html._currentRender = undefined; | |
} | |
}; | |
},{".":"hyperdom","./render":35,"./rendering":36}],38:[function(require,module,exports){ | |
if (typeof Set === 'function') { | |
module.exports = Set; | |
} else { | |
module.exports = function() { | |
this.items = []; | |
}; | |
module.exports.prototype.add = function(widget) { | |
if (this.items.indexOf(widget) == -1) { | |
this.items.push(widget); | |
} | |
}; | |
module.exports.prototype.delete = function(widget) { | |
var i = this.items.indexOf(widget); | |
if (i !== -1) { | |
this.items.splice(i, 1); | |
} | |
}; | |
module.exports.prototype.forEach = function(fn) { | |
for(var n = 0; n < this.items.length; n++) { | |
fn(this.items[n]); | |
} | |
}; | |
} | |
},{}],39:[function(require,module,exports){ | |
function SimplePromise () { | |
this.listeners = []; | |
} | |
SimplePromise.prototype.fulfill = function (value) { | |
if (!this.isFulfilled) { | |
this.isFulfilled = true; | |
this.value = value; | |
this.listeners.forEach(function (listener) { | |
listener(); | |
}); | |
} | |
}; | |
SimplePromise.prototype.then = function (success) { | |
if (this.isFulfilled) { | |
var self = this; | |
setTimeout(function () { | |
success(self.value); | |
}); | |
} else { | |
this.listeners.push(success); | |
} | |
}; | |
module.exports = function () { | |
return new SimplePromise(); | |
}; | |
},{}],40:[function(require,module,exports){ | |
var vtext = require("virtual-dom/vnode/vtext.js") | |
var rendering = require('./rendering'); | |
var isVdom = require('./isVdom'); | |
function toVdom(object) { | |
if (object === undefined || object === null) { | |
return new vtext(''); | |
} else if (typeof(object) != 'object') { | |
return new vtext(String(object)); | |
} else if (object instanceof Date) { | |
return new vtext(String(object)); | |
} else if (object instanceof Error) { | |
return new vtext(object.toString()); | |
} else if (isVdom(object)) { | |
return object; | |
} else if (typeof object.render === 'function') { | |
return new rendering.ViewModel(object); | |
} else { | |
return new vtext(JSON.stringify(object)); | |
} | |
} | |
module.exports = toVdom; | |
function addChild(children, child) { | |
if (child instanceof Array) { | |
for (var n = 0; n < child.length; n++) { | |
addChild(children, child[n]); | |
} | |
} else { | |
children.push(toVdom(child)); | |
} | |
} | |
module.exports.recursive = function (child) { | |
var children = []; | |
addChild(children, child); | |
return children; | |
}; | |
},{"./isVdom":5,"./rendering":36,"virtual-dom/vnode/vtext.js":32}],41:[function(require,module,exports){ | |
'use strict'; | |
var VNode = require('virtual-dom/vnode/vnode.js'); | |
var isHook = require('virtual-dom/vnode/is-vhook'); | |
var softSetHook = require('virtual-dom/virtual-hyperscript/hooks/soft-set-hook.js'); | |
module.exports = h; | |
function h(tagName, props, children) { | |
var tag = tagName; | |
// support keys | |
if (props.hasOwnProperty('key')) { | |
var key = props.key; | |
props.key = undefined; | |
} | |
// support namespace | |
if (props.hasOwnProperty('namespace')) { | |
var namespace = props.namespace; | |
props.namespace = undefined; | |
} | |
// fix cursor bug | |
if (tag.toLowerCase() === 'input' && | |
!namespace && | |
props.hasOwnProperty('value') && | |
props.value !== undefined && | |
!isHook(props.value) | |
) { | |
props.value = softSetHook(props.value); | |
} | |
return new VNode(tag, props, children, key, namespace); | |
} | |
},{"virtual-dom/virtual-hyperscript/hooks/soft-set-hook.js":21,"virtual-dom/vnode/is-vhook":25,"virtual-dom/vnode/vnode.js":30}],42:[function(require,module,exports){ | |
var domComponent = require('./domComponent'); | |
var hyperdomMeta = require('./meta'); | |
var hyperdom = require('.'); | |
function ViewModel(model) { | |
var currentRender = hyperdom.currentRender(); | |
this.currentRender = currentRender; | |
this.model = model; | |
this.key = model.renderKey; | |
this.component = undefined; | |
this.mount = currentRender.mount; | |
} | |
ViewModel.prototype.type = 'Widget'; | |
ViewModel.prototype.init = function () { | |
var self = this; | |
var vdom = this.render(); | |
var meta = hyperdomMeta(this.model); | |
meta.widgets.add(this); | |
this.component = domComponent(); | |
var element = this.component.create(vdom); | |
if (self.model.onadd) { | |
this.currentRender.finished.then(function () { | |
self.model.onadd(element); | |
}); | |
} | |
if (self.model.detached) { | |
return document.createTextNode(''); | |
} else { | |
return element; | |
} | |
}; | |
ViewModel.prototype.update = function (previous) { | |
var self = this; | |
if (self.model.onupdate) { | |
this.currentRender.finished.then(function () { | |
self.model.onupdate(self.component.element); | |
}); | |
} | |
this.component = previous.component; | |
var element = this.component.update(this.render()); | |
if (self.model.detached) { | |
return document.createTextNode(''); | |
} else { | |
return element; | |
} | |
}; | |
ViewModel.prototype.render = function () { | |
return this.mount.renderViewModel(this.model); | |
}; | |
ViewModel.prototype.rerender = function () { | |
this.component.update(this.render()); | |
if (this.model.onupdate) { | |
this.model.onupdate(this.component.element); | |
} | |
}; | |
ViewModel.prototype.destroy = function (element) { | |
var self = this; | |
var meta = hyperdomMeta(this.model); | |
meta.widgets.delete(this); | |
if (self.model.onremove) { | |
this.currentRender.finished.then(function () { | |
self.model.onremove(element); | |
}); | |
} | |
this.component.destroy(); | |
}; | |
module.exports = ViewModel; | |
},{".":"hyperdom","./domComponent":4,"./meta":6}],43:[function(require,module,exports){ | |
var domComponent = require('./domComponent'); | |
var rendering = require('./rendering'); | |
var VText = require("virtual-dom/vnode/vtext.js") | |
function WindowWidget(attributes) { | |
this.attributes = attributes; | |
this.vdom = new VText(''); | |
this.component = domComponent(); | |
var self = this; | |
this.cache = {}; | |
Object.keys(this.attributes).forEach(function (key) { | |
self.cache[key] = rendering.html.refreshify(self.attributes[key]); | |
}); | |
} | |
WindowWidget.prototype.type = 'Widget'; | |
WindowWidget.prototype.init = function () { | |
applyPropertyDiffs(window, {}, this.attributes, {}, this.cache); | |
return this.element = document.createTextNode(''); | |
}; | |
function uniq(array) { | |
var sortedArray = array.slice(); | |
sortedArray.sort(); | |
var last; | |
for(var n = 0; n < sortedArray.length;) { | |
var current = sortedArray[n]; | |
if (last === current) { | |
sortedArray.splice(n, 1); | |
} else { | |
n++; | |
} | |
last = current; | |
} | |
return sortedArray; | |
} | |
function applyPropertyDiffs(element, previous, current, previousCache, currentCache) { | |
uniq(Object.keys(previous).concat(Object.keys(current))).forEach(function (key) { | |
if (/^on/.test(key)) { | |
var event = key.slice(2); | |
var prev = previous[key]; | |
var curr = current[key]; | |
var refreshPrev = previousCache[key]; | |
var refreshCurr = currentCache[key]; | |
if (prev !== undefined && curr === undefined) { | |
element.removeEventListener(event, refreshPrev); | |
} else if (prev !== undefined && curr !== undefined && prev !== curr) { | |
element.removeEventListener(event, refreshPrev); | |
element.addEventListener(event, refreshCurr); | |
} else if (prev === undefined && curr !== undefined) { | |
element.addEventListener(event, refreshCurr); | |
} | |
} | |
}); | |
} | |
WindowWidget.prototype.update = function (previous) { | |
applyPropertyDiffs(window, previous.attributes, this.attributes, previous.cache, this.cache); | |
this.component = previous.component; | |
return this.element; | |
}; | |
WindowWidget.prototype.destroy = function () { | |
applyPropertyDiffs(window, this.attributes, {}, this.cache, {}); | |
}; | |
module.exports = function (attributes) { | |
return new WindowWidget(attributes); | |
}; | |
},{"./domComponent":4,"./rendering":36,"virtual-dom/vnode/vtext.js":32}],"hyperdom":[function(require,module,exports){ | |
if (typeof window === 'object') { | |
console.log('\n\ncreated with \uD83D\uDE80 using https://github.com/featurist/hyperdom\n\n\n'); | |
} | |
var rendering = require('./rendering'); | |
var deprecations = require('./deprecations'); | |
exports.html = rendering.html; | |
exports.jsx = rendering.jsx; | |
exports.attach = rendering.attach; | |
exports.replace = rendering.replace; | |
exports.append = rendering.append; | |
exports.appendVDom = rendering.appendVDom; | |
exports.merge = rendering.merge; | |
exports.binding = rendering.binding; | |
exports.meta = rendering.html.meta; | |
exports.refreshify = rendering.html.refreshify; | |
exports.norefresh = rendering.html.norefresh; | |
var windowEvents = require('./windowEvents'); | |
exports.html.window = function (attributes) { | |
deprecations.window('hyperdom.window is deprecated'); | |
return windowEvents(attributes); | |
}; | |
exports.html.component = require('./component'); | |
exports.currentRender = function () { | |
return exports._currentRender; | |
}; | |
},{"./component":2,"./deprecations":3,"./rendering":36,"./windowEvents":43}]},{},[]) | |
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcmVzb2x2ZS9lbXB0eS5qcyIsImNvbXBvbmVudC5qcyIsImRlcHJlY2F0aW9ucy5qcyIsImRvbUNvbXBvbmVudC5qcyIsImlzVmRvbS5qcyIsIm1ldGEuanMiLCJtb3VudC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9jcmVhdGUtZWxlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9kaWZmLmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL25vZGVfbW9kdWxlcy9icm93c2VyLXNwbGl0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL25vZGVfbW9kdWxlcy9nbG9iYWwvZG9jdW1lbnQuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vbm9kZV9tb2R1bGVzL2lzLW9iamVjdC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9ub2RlX21vZHVsZXMveC1pcy1hcnJheS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9wYXRjaC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92ZG9tL2FwcGx5LXByb3BlcnRpZXMuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdmRvbS9jcmVhdGUtZWxlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92ZG9tL2RvbS1pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92ZG9tL3BhdGNoLW9wLmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Zkb20vcGF0Y2guanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdmRvbS91cGRhdGUtd2lkZ2V0LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaG9va3Mvc29mdC1zZXQtaG9vay5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92aXJ0dWFsLWh5cGVyc2NyaXB0L3BhcnNlLXRhZy5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92bm9kZS9oYW5kbGUtdGh1bmsuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdGh1bmsuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdmhvb2suanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdm5vZGUuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdnRleHQuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtd2lkZ2V0LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Zub2RlL3ZlcnNpb24uanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvdm5vZGUuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvdnBhdGNoLmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Zub2RlL3Z0ZXh0LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Z0cmVlL2RpZmYtcHJvcHMuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdnRyZWUvZGlmZi5qcyIsInJlbmRlci5qcyIsInJlbmRlcmluZy5qcyIsInJ1blJlbmRlci5qcyIsInNldC5qcyIsInNpbXBsZVByb21pc2UuanMiLCJ0b1Zkb20uanMiLCJ2aHRtbC5qcyIsInZpZXdNb2RlbC5qcyIsIndpbmRvd0V2ZW50cy5qcyIsImh5cGVyZG9tIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdElBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDcm9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiIiwidmFyIFZUZXh0ID0gcmVxdWlyZShcInZpcnR1YWwtZG9tL3Zub2RlL3Z0ZXh0LmpzXCIpXG52YXIgZG9tQ29tcG9uZW50ID0gcmVxdWlyZSgnLi9kb21Db21wb25lbnQnKTtcbnZhciBoeXBlcmRvbSA9IHJlcXVpcmUoJy4nKTtcbnZhciBkZXByZWNhdGlvbnMgPSByZXF1aXJlKCcuL2RlcHJlY2F0aW9ucycpO1xuXG5mdW5jdGlvbiBDb21wb25lbnRXaWRnZXQoc3RhdGUsIHZkb20pIHtcbiAgaWYgKCF2ZG9tKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdoeXBlcmRvbS5odG1sLmNvbXBvbmVudChbb3B0aW9uc10sIHZkb20pIGV4cGVjdHMgYSB2ZG9tIGFyZ3VtZW50Jyk7XG4gIH1cblxuICB0aGlzLnN0YXRlID0gc3RhdGU7XG4gIHRoaXMua2V5ID0gc3RhdGUua2V5O1xuICB2YXIgY3VycmVudFJlbmRlciA9IGh5cGVyZG9tLmN1cnJlbnRSZW5kZXIoKTtcblxuICBpZiAodHlwZW9mIHZkb20gPT09ICdmdW5jdGlvbicpIHtcbiAgICB0aGlzLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChjdXJyZW50UmVuZGVyKSB7XG4gICAgICAgIGN1cnJlbnRSZW5kZXIuZXZlbnRIYW5kbGVyV3JhcHBlciA9IHN0YXRlLm9uO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZkb20uYXBwbHkodGhpcy5zdGF0ZSwgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHRoaXMuY2FuUmVmcmVzaCA9IHRydWU7XG4gIH0gZWxzZSB7XG4gICAgdmRvbSA9IHZkb20gfHwgbmV3IFZUZXh0KCcnKTtcbiAgICB0aGlzLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB2ZG9tO1xuICAgIH1cbiAgfVxuICB0aGlzLmNhY2hlS2V5ID0gc3RhdGUuY2FjaGVLZXk7XG4gIHRoaXMuY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KCk7XG5cbiAgdmFyIHJlbmRlckZpbmlzaGVkID0gY3VycmVudFJlbmRlciAmJiBjdXJyZW50UmVuZGVyLmZpbmlzaGVkO1xuICBpZiAocmVuZGVyRmluaXNoZWQpIHtcbiAgICB0aGlzLmFmdGVyUmVuZGVyID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICByZW5kZXJGaW5pc2hlZC50aGVuKGZuKTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHRoaXMuYWZ0ZXJSZW5kZXIgPSBmdW5jdGlvbiAoKSB7fTtcbiAgfVxufVxuXG5Db21wb25lbnRXaWRnZXQucHJvdG90eXBlLnR5cGUgPSAnV2lkZ2V0JztcblxuQ29tcG9uZW50V2lkZ2V0LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYgKHNlbGYuc3RhdGUub25iZWZvcmVhZGQpIHtcbiAgICBzZWxmLnN0YXRlLm9uYmVmb3JlYWRkKCk7XG4gIH1cblxuICB2YXIgdmRvbSA9IHRoaXMucmVuZGVyKHRoaXMpO1xuICBpZiAodmRvbSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd2ZG9tIHJldHVybmVkIGZyb20gY29tcG9uZW50IGNhbm5vdCBiZSBhbiBhcnJheScpO1xuICB9XG5cbiAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC5jcmVhdGUodmRvbSk7XG5cbiAgaWYgKHNlbGYuc3RhdGUub25hZGQpIHtcbiAgICB0aGlzLmFmdGVyUmVuZGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuc3RhdGUub25hZGQoZWxlbWVudCk7XG4gICAgfSk7XG4gIH1cblxuICBpZiAoc2VsZi5zdGF0ZS5kZXRhY2hlZCkge1xuICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cbn07XG5cbkNvbXBvbmVudFdpZGdldC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKHByZXZpb3VzKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICB2YXIgcmVmcmVzaCA9ICF0aGlzLmNhY2hlS2V5IHx8IHRoaXMuY2FjaGVLZXkgIT09IHByZXZpb3VzLmNhY2hlS2V5O1xuXG4gIGlmIChyZWZyZXNoKSB7XG4gICAgaWYgKHNlbGYuc3RhdGUub251cGRhdGUpIHtcbiAgICAgIHRoaXMuYWZ0ZXJSZW5kZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICBzZWxmLnN0YXRlLm9udXBkYXRlKHNlbGYuY29tcG9uZW50LmVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5jb21wb25lbnQgPSBwcmV2aW91cy5jb21wb25lbnQ7XG5cbiAgaWYgKHByZXZpb3VzLnN0YXRlICYmIHRoaXMuc3RhdGUpIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc3RhdGUpO1xuICAgIGZvcih2YXIgbiA9IDA7IG4gPCBrZXlzLmxlbmd0aDsgbisrKSB7XG4gICAgICB2YXIga2V5ID0ga2V5c1tuXTtcbiAgICAgIHByZXZpb3VzLnN0YXRlW2tleV0gPSBzZWxmLnN0YXRlW2tleV07XG4gICAgfVxuICAgIHRoaXMuc3RhdGUgPSBwcmV2aW91cy5zdGF0ZTtcbiAgfVxuXG4gIGlmIChyZWZyZXNoKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC51cGRhdGUodGhpcy5yZW5kZXIodGhpcykpO1xuXG4gICAgaWYgKHNlbGYuc3RhdGUuZGV0YWNoZWQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cbiAgfVxufTtcblxuQ29tcG9uZW50V2lkZ2V0LnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmNvbXBvbmVudC51cGRhdGUodGhpcy5yZW5kZXIodGhpcykpO1xuICBpZiAodGhpcy5zdGF0ZS5vbnVwZGF0ZSkge1xuICAgIHRoaXMuc3RhdGUub251cGRhdGUodGhpcy5jb21wb25lbnQuZWxlbWVudCk7XG4gIH1cbn07XG5cbkNvbXBvbmVudFdpZGdldC5wcm90b3R5cGUucmVyZW5kZXIgPSBDb21wb25lbnRXaWRnZXQucHJvdG90eXBlLnJlZnJlc2g7XG5cbkNvbXBvbmVudFdpZGdldC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICBpZiAoc2VsZi5zdGF0ZS5vbnJlbW92ZSkge1xuICAgIHRoaXMuYWZ0ZXJSZW5kZXIoZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi5zdGF0ZS5vbnJlbW92ZShlbGVtZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHRoaXMuY29tcG9uZW50LmRlc3Ryb3koKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHN0YXRlLCB2ZG9tKSB7XG4gIGRlcHJlY2F0aW9ucy5jb21wb25lbnQoJ2h5cGVyZG9tLmh0bWwuY29tcG9uZW50IGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgVmlld01vZGVscycpO1xuICBpZiAodHlwZW9mIHN0YXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRXaWRnZXQoe30sIHN0YXRlKTtcbiAgfSBlbHNlIGlmIChzdGF0ZS5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0KSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRXaWRnZXQoc3RhdGUsIHZkb20pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgQ29tcG9uZW50V2lkZ2V0KHt9LCBzdGF0ZSk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzLkNvbXBvbmVudFdpZGdldCA9IENvbXBvbmVudFdpZGdldDtcbiIsImZ1bmN0aW9uIGRlcHJlY2F0aW9uV2FybmluZygpIHtcbiAgdmFyIHdhcm5pbmdJc3N1ZWQgPSBmYWxzZTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGFyZykge1xuICAgIGlmICghd2FybmluZ0lzc3VlZCkge1xuICAgICAgY29uc29sZS53YXJuKGFyZyk7XG4gICAgICB3YXJuaW5nSXNzdWVkID0gdHJ1ZTtcbiAgICB9XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICByZWZyZXNoOiBkZXByZWNhdGlvbldhcm5pbmcoKSxcbiAgY3VycmVudFJlbmRlcjogZGVwcmVjYXRpb25XYXJuaW5nKCksXG4gIHdpbmRvdzogZGVwcmVjYXRpb25XYXJuaW5nKCksXG4gIGNvbXBvbmVudDogZGVwcmVjYXRpb25XYXJuaW5nKCksXG4gIHJlbmRlckZ1bmN0aW9uOiBkZXByZWNhdGlvbldhcm5pbmcoKSxcbiAgcmVmcmVzaEFmdGVyOiBkZXByZWNhdGlvbldhcm5pbmcoKSxcbiAgbm9yZWZyZXNoOiBkZXByZWNhdGlvbldhcm5pbmcoKVxufTtcbiIsInZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZSgndmlydHVhbC1kb20vY3JlYXRlLWVsZW1lbnQnKTtcbnZhciBkaWZmID0gcmVxdWlyZSgndmlydHVhbC1kb20vZGlmZicpO1xudmFyIHBhdGNoID0gcmVxdWlyZSgndmlydHVhbC1kb20vcGF0Y2gnKTtcbnZhciB0b1Zkb20gPSByZXF1aXJlKCcuL3RvVmRvbScpO1xudmFyIGlzVmRvbSA9IHJlcXVpcmUoJy4vaXNWZG9tJyk7XG5cbmZ1bmN0aW9uIERvbUNvbXBvbmVudChvcHRpb25zKSB7XG4gIHRoaXMuZG9jdW1lbnQgPSBvcHRpb25zICYmIG9wdGlvbnMuZG9jdW1lbnQ7XG59XG5cbmZ1bmN0aW9uIHByZXBhcmVWZG9tKG9iamVjdCkge1xuICB2YXIgdmRvbSA9IHRvVmRvbShvYmplY3QpO1xuICBpZiAoIWlzVmRvbSh2ZG9tKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0ZWQgcmVuZGVyIHRvIHJldHVybiB2ZG9tJyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHZkb207XG4gIH1cbn1cblxuRG9tQ29tcG9uZW50LnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAodmRvbSkge1xuICB0aGlzLnZkb20gPSBwcmVwYXJlVmRvbSh2ZG9tKTtcbiAgcmV0dXJuIHRoaXMuZWxlbWVudCA9IGNyZWF0ZUVsZW1lbnQodGhpcy52ZG9tLCB7ZG9jdW1lbnQ6IHRoaXMuZG9jdW1lbnR9KTtcbn07XG5cbkRvbUNvbXBvbmVudC5wcm90b3R5cGUubWVyZ2UgPSBmdW5jdGlvbiAodmRvbSwgZWxlbWVudCkge1xuICB0aGlzLnZkb20gPSBwcmVwYXJlVmRvbSh2ZG9tKTtcbiAgcmV0dXJuIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG59O1xuXG5Eb21Db21wb25lbnQucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICh2ZG9tKSB7XG4gIHZhciBvbGRWZG9tID0gdGhpcy52ZG9tO1xuICB0aGlzLnZkb20gPSBwcmVwYXJlVmRvbSh2ZG9tKTtcbiAgdmFyIHBhdGNoZXMgPSBkaWZmKG9sZFZkb20sIHRoaXMudmRvbSk7XG4gIHJldHVybiB0aGlzLmVsZW1lbnQgPSBwYXRjaCh0aGlzLmVsZW1lbnQsIHBhdGNoZXMpO1xufTtcblxuRG9tQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModmRvbSkge1xuICAgIGlmICh2ZG9tLnR5cGUgPT09ICdXaWRnZXQnKSB7XG4gICAgICB2ZG9tLmRlc3Ryb3koKTtcbiAgICB9IGVsc2UgaWYgKHZkb20uY2hpbGRyZW4pIHtcbiAgICAgIHZkb20uY2hpbGRyZW4uZm9yRWFjaChkZXN0cm95V2lkZ2V0cyk7XG4gICAgfVxuICB9XG5cbiAgZGVzdHJveVdpZGdldHModGhpcy52ZG9tKTtcblxuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnJlbW92ZUVsZW1lbnQgJiYgdGhpcy5lbGVtZW50LnBhcmVudE5vZGUpIHtcbiAgICB0aGlzLmVsZW1lbnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmVsZW1lbnQpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBkb21Db21wb25lbnQob3B0aW9ucykge1xuICByZXR1cm4gbmV3IERvbUNvbXBvbmVudChvcHRpb25zKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBkb21Db21wb25lbnQ7XG4iLCJ2YXIgdmlydHVhbERvbVZlcnNpb24gPSByZXF1aXJlKFwidmlydHVhbC1kb20vdm5vZGUvdmVyc2lvblwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIHR5cGUgPSB4LnR5cGU7XG4gIGlmICh0eXBlID09ICdWaXJ0dWFsTm9kZScgfHwgdHlwZSA9PSAnVmlydHVhbFRleHQnKSB7XG4gICAgcmV0dXJuIHgudmVyc2lvbiA9PSB2aXJ0dWFsRG9tVmVyc2lvbjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdHlwZSA9PSAnV2lkZ2V0JyB8fCB0eXBlID09ICdUaHVuayc7XG4gIH1cbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChtb2RlbCwgcHJvcGVydHkpIHtcbiAgdmFyIGh5cGVyZG9tTWV0YSA9IG1vZGVsLl9oeXBlcmRvbU1ldGE7XG5cbiAgaWYgKCFoeXBlcmRvbU1ldGEpIHtcbiAgICBoeXBlcmRvbU1ldGEgPSB7fTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobW9kZWwsICdfaHlwZXJkb21NZXRhJywge3ZhbHVlOiBoeXBlcmRvbU1ldGF9KTtcbiAgfVxuXG4gIGlmIChwcm9wZXJ0eSkge1xuICAgIHZhciBtZXRhID0gaHlwZXJkb21NZXRhW3Byb3BlcnR5XTtcblxuICAgIGlmICghbWV0YSkge1xuICAgICAgbWV0YSA9IGh5cGVyZG9tTWV0YVtwcm9wZXJ0eV0gPSB7fTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWV0YTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaHlwZXJkb21NZXRhO1xuICB9XG59O1xuIiwidmFyIGh5cGVyZG9tTWV0YSA9IHJlcXVpcmUoJy4vbWV0YScpO1xudmFyIHJ1blJlbmRlciA9IHJlcXVpcmUoJy4vcnVuUmVuZGVyJyk7XG52YXIgaHlwZXJkb20gPSByZXF1aXJlKCcuJyk7XG52YXIgU2V0ID0gcmVxdWlyZSgnLi9zZXQnKTtcblxudmFyIGxhc3RJZCA9IDA7XG5cbmZ1bmN0aW9uIE1vdW50KG1vZGVsLCBvcHRpb25zKSB7XG4gIHZhciB3aW4gPSAob3B0aW9ucyAmJiBvcHRpb25zLndpbmRvdykgfHwgd2luZG93O1xuICB0aGlzLnJlcXVlc3RSZW5kZXIgPSAob3B0aW9ucyAmJiBvcHRpb25zLnJlcXVlc3RSZW5kZXIpIHx8IHdpbi5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgd2luLnNldFRpbWVvdXQ7XG5cbiAgdGhpcy5tb2RlbCA9IG1vZGVsO1xuXG4gIHRoaXMucmVuZGVyUXVldWVkID0gZmFsc2U7XG4gIHRoaXMubW91bnRSZW5kZXJSZXF1ZXN0ZWQgPSBmYWxzZTtcbiAgdGhpcy53aWRnZXRSZW5kZXJzUmVxdWVzdGVkID0gdW5kZWZpbmVkO1xuICB0aGlzLmlkID0gKytsYXN0SWQ7XG4gIHRoaXMubW91bnRlZCA9IHRydWU7XG59XG5cbk1vdW50LnByb3RvdHlwZS5xdWV1ZVJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKCF0aGlzLnJlbmRlclF1ZXVlZCkge1xuICAgIHZhciByZXF1ZXN0UmVuZGVyID0gdGhpcy5yZXF1ZXN0UmVuZGVyO1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHJlcXVlc3RSZW5kZXIoZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi5yZW5kZXJRdWV1ZWQgPSBmYWxzZTtcblxuICAgICAgaWYgKHNlbGYubW91bnRlZCkge1xuICAgICAgICBydW5SZW5kZXIoc2VsZiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChzZWxmLm1vdW50UmVuZGVyUmVxdWVzdGVkKSB7XG4gICAgICAgICAgICB2YXIgdmRvbSA9IHNlbGYucmVuZGVyKCk7XG4gICAgICAgICAgICBzZWxmLmNvbXBvbmVudC51cGRhdGUodmRvbSk7XG4gICAgICAgICAgICBzZWxmLm1vdW50UmVuZGVyUmVxdWVzdGVkID0gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIGlmIChzZWxmLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQgJiYgc2VsZi53aWRnZXRSZW5kZXJzUmVxdWVzdGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBzZWxmLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgIHZhciB3ID0gc2VsZi53aWRnZXRSZW5kZXJzUmVxdWVzdGVkW2ldO1xuICAgICAgICAgICAgICB3LnJlcmVuZGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMucmVuZGVyUXVldWVkID0gdHJ1ZTtcbiAgfVxufTtcblxuTW91bnQucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5yZW5kZXJWaWV3TW9kZWwodGhpcy5tb2RlbCk7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUucmVyZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMubW91bnRSZW5kZXJSZXF1ZXN0ZWQgPSB0cnVlO1xuICB0aGlzLnF1ZXVlUmVuZGVyKCk7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUucmVyZW5kZXJXaWRnZXQgPSBmdW5jdGlvbiAod2lkZ2V0KSB7XG4gIGlmICghdGhpcy53aWRnZXRSZW5kZXJzUmVxdWVzdGVkKSB7XG4gICAgdGhpcy53aWRnZXRSZW5kZXJzUmVxdWVzdGVkID0gW107XG4gIH1cblxuICB0aGlzLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQucHVzaCh3aWRnZXQpO1xuICB0aGlzLnF1ZXVlUmVuZGVyKCk7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUuX3JlbmRlclZpZXdNb2RlbCA9IGZ1bmN0aW9uKG1vZGVsKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICBtb2RlbC5yZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICBzZWxmLnJlcmVuZGVyKCk7XG4gIH07XG4gIG1vZGVsLnJlcmVuZGVyVmlld01vZGVsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEodGhpcyk7XG4gICAgbWV0YS53aWRnZXRzLmZvckVhY2goZnVuY3Rpb24gKHcpIHtcbiAgICAgIHNlbGYucmVyZW5kZXJXaWRnZXQodyk7XG4gICAgfSk7XG4gIH07XG5cbiAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEobW9kZWwpO1xuICBpZiAoIW1ldGEubW91bnQpIHtcbiAgICBtZXRhLm1vdW50ID0gdGhpcztcbiAgfVxuXG4gIGlmICghbWV0YS53aWRnZXRzKSB7XG4gICAgbWV0YS53aWRnZXRzID0gbmV3IFNldCgpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBtb2RlbC5vbmxvYWQgPT0gJ2Z1bmN0aW9uJykge1xuICAgIGlmICghbWV0YS5sb2FkZWQpIHtcbiAgICAgIG1ldGEubG9hZGVkID0gdHJ1ZTtcbiAgICAgIGh5cGVyZG9tLnJlZnJlc2hpZnkoZnVuY3Rpb24gKCkgeyByZXR1cm4gbW9kZWwub25sb2FkKCk7IH0sIHtyZWZyZXNoOiAncHJvbWlzZSd9KSgpO1xuICAgIH1cbiAgfVxuXG4gIHZhciB2ZG9tID0gbW9kZWwucmVuZGVyKCk7XG5cbiAgaWYgKHZkb20gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHRocm93IG5ldyBFcnJvcigndmRvbSByZXR1cm5lZCBmcm9tIGNvbXBvbmVudCBjYW5ub3QgYmUgYW4gYXJyYXknKTtcbiAgfVxuXG4gIGlmICh2ZG9tICYmIHZkb20ucHJvcGVydGllcykge1xuICAgIHZkb20ucHJvcGVydGllcy5faHlwZXJkb21WaWV3TW9kZWwgPSBtb2RlbDtcbiAgfVxuXG4gIHJldHVybiB2ZG9tO1xufVxuXG5Nb3VudC5wcm90b3R5cGUucmVuZGVyVmlld01vZGVsID0gZnVuY3Rpb24obW9kZWwpIHtcbiAgaWYgKHR5cGVvZiBtb2RlbC5yZW5kZXJDYWNoZUtleSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHZhciBtZXRhID0gaHlwZXJkb21NZXRhKG1vZGVsKTtcbiAgICB2YXIga2V5ID0gbW9kZWwucmVuZGVyQ2FjaGVLZXkoKTtcbiAgICBpZiAoa2V5ICE9PSB1bmRlZmluZWQgJiYgbWV0YS5jYWNoZUtleSA9PT0ga2V5ICYmIG1ldGEuY2FjaGVkVmRvbSkge1xuICAgICAgcmV0dXJuIG1ldGEuY2FjaGVkVmRvbTtcbiAgICB9IGVsc2Uge1xuICAgICAgbWV0YS5jYWNoZUtleSA9IGtleTtcbiAgICAgIHJldHVybiBtZXRhLmNhY2hlZFZkb20gPSB0aGlzLl9yZW5kZXJWaWV3TW9kZWwobW9kZWwpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdGhpcy5fcmVuZGVyVmlld01vZGVsKG1vZGVsKTtcbiAgfVxufTtcblxuTW91bnQucHJvdG90eXBlLmRldGFjaCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5tb3VudGVkID0gZmFsc2U7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmNvbXBvbmVudC5kZXN0cm95KHtyZW1vdmVFbGVtZW50OiB0cnVlfSk7XG4gIHRoaXMubW91bnRlZCA9IGZhbHNlO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNb3VudDtcbiIsInZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnRcbiIsInZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRpZmZcbiIsIi8qIVxuICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gKi9cblxuLyoqXG4gKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICogY3Jvc3MtYnJvd3Nlci5cbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBCYXNpYyB1c2VcbiAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gKlxuICogLy8gV2l0aCBsaW1pdFxuICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICogLy8gLT4gWydhJywgJ2InXVxuICpcbiAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgc2VsZjtcblxuICBzZWxmID0gZnVuY3Rpb24oc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgIH1cbiAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcbiAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICBzZXBhcmF0b3IyLCBtYXRjaCwgbGFzdEluZGV4LCBsYXN0TGVuZ3RoO1xuICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgfVxuICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgKi9cbiAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICB9O1xuXG4gIHJldHVybiBzZWxmO1xufSkoKTtcbiIsInZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDpcbiAgICB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHt9XG52YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbn0gZWxzZSB7XG4gICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbJ19fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDQnXTtcblxuICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgIH1cblxuICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG59XG4iLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG5cdHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xufTtcbiIsInZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheVxudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheVxuXG5mdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIlxufVxuIiwidmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHBhdGNoXG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpXG52YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzXG5cbmZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdXG5cbiAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKVxuICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSxcbiAgICAgICAgICAgICAgICAgICAgcHJvcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXVxuXG4gICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbFxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkXG5cbiAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXVxuXG4gICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiZcbiAgICAgICAgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZVxuICAgICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9XG4gICAgfVxuXG4gICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWRcblxuICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXVxuICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9ICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSA/IHJlcGxhY2VyIDogdmFsdWVcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSlcbiAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fXG4gICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlXG4gICAgfVxufVxuIiwidmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKVxuXG52YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKVxuXG52YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKVxudmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIilcbnZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIilcbnZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIilcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50XG5cbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudFxuICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGxcblxuICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmFcblxuICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKVxuICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KVxuICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgdmFyIG5vZGUgPSAodm5vZGUubmFtZXNwYWNlID09PSBudWxsKSA/XG4gICAgICAgIGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDpcbiAgICAgICAgZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpXG5cbiAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzXG4gICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKVxuXG4gICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW5cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpXG4gICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vZGVcbn1cbiIsIi8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4vLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4vLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbi8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2Zcbi8vIGludGVyZXN0LlxuXG52YXIgbm9DaGlsZCA9IHt9XG5cbm1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXhcblxuZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB7fVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpXG4gICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICBub2RlcyA9IG5vZGVzIHx8IHt9XG5cblxuICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlblxuXG4gICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzXG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxXG5cbiAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGRcbiAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKVxuXG4gICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZXNcbn1cblxuLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbmZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICB2YXIgbWluSW5kZXggPSAwXG4gICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxXG4gICAgdmFyIGN1cnJlbnRJbmRleFxuICAgIHZhciBjdXJyZW50SXRlbVxuXG4gICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgIGN1cnJlbnRJbmRleCA9ICgobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyKSA+PiAwXG4gICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdXG5cbiAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHRcbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMVxuICAgICAgICB9IGVsc2UgIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xXG59XG4iLCJ2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKVxuXG52YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpXG52YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKVxuXG52YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2hcblxuZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlXG4gICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlXG4gICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoXG5cbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpXG4gICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKVxuICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpXG4gICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpXG4gICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKVxuICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaClcbiAgICAgICAgICAgIHJldHVybiBkb21Ob2RlXG4gICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKVxuICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGVcbiAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSxcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSlcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBkb21Ob2RlXG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGVcblxuICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSlcbiAgICB9XG5cbiAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgIHJldHVybiBudWxsXG59XG5cbmZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKVxuXG4gICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKVxuICAgIH1cblxuICAgIHJldHVybiBwYXJlbnROb2RlXG59XG5cbmZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICB2YXIgbmV3Tm9kZVxuXG4gICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dClcbiAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGVcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZVxuICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpXG5cbiAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXdOb2RlXG59XG5cbmZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KVxuICAgIHZhciBuZXdOb2RlXG5cbiAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlXG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucylcbiAgICB9XG5cbiAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZVxuXG4gICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKVxuICAgIH1cblxuICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld05vZGVcbn1cblxuZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGVcbiAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKVxuXG4gICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKVxuICAgIH1cblxuICAgIHJldHVybiBuZXdOb2RlXG59XG5cbmZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpXG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2Rlc1xuICAgIHZhciBrZXlNYXAgPSB7fVxuICAgIHZhciBub2RlXG4gICAgdmFyIHJlbW92ZVxuICAgIHZhciBpbnNlcnRcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldXG4gICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXVxuICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZVxuICAgICAgICB9XG4gICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSlcbiAgICB9XG5cbiAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGhcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXVxuICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldXG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSlcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdClcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3Um9vdDtcbn1cbiIsInZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIilcbnZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIilcblxudmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpXG52YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIilcbnZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIilcbm1vZHVsZS5leHBvcnRzID0gcGF0Y2hcblxuZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fVxuICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoXG4gICAgICAgID8gcmVuZGVyT3B0aW9ucy5wYXRjaFxuICAgICAgICA6IHBhdGNoUmVjdXJzaXZlXG4gICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXJcblxuICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKVxufVxuXG5mdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpXG5cbiAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJvb3ROb2RlXG4gICAgfVxuXG4gICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcylcbiAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnRcblxuICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudFxuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXVxuICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsXG4gICAgICAgICAgICBpbmRleFtub2RlSW5kZXhdLFxuICAgICAgICAgICAgcGF0Y2hlc1tub2RlSW5kZXhdLFxuICAgICAgICAgICAgcmVuZGVyT3B0aW9ucylcbiAgICB9XG5cbiAgICByZXR1cm4gcm9vdE5vZGVcbn1cblxuZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgIHJldHVybiByb290Tm9kZVxuICAgIH1cblxuICAgIHZhciBuZXdOb2RlXG5cbiAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpXG5cbiAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKVxuXG4gICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcm9vdE5vZGVcbn1cblxuZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICB2YXIgaW5kaWNlcyA9IFtdXG5cbiAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGljZXNcbn1cbiIsInZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIilcblxubW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXRcblxuZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbmZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG59XG5cblNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3BsaXQgPSByZXF1aXJlKCdicm93c2VyLXNwbGl0Jyk7XG5cbnZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbnZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbm1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbmZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICBpZiAoIXRhZykge1xuICAgICAgICByZXR1cm4gJ0RJVic7XG4gICAgfVxuXG4gICAgdmFyIG5vSWQgPSAhKHByb3BzLmhhc093blByb3BlcnR5KCdpZCcpKTtcblxuICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICB0YWdOYW1lID0gJ0RJVic7XG4gICAgfVxuXG4gICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnLicpIHtcbiAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJyMnICYmIG5vSWQpIHtcbiAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oJyAnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbn1cbiIsInZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIilcbnZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIilcbnZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKVxudmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rXG5cbmZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICB2YXIgcmVuZGVyZWRBID0gYVxuICAgIHZhciByZW5kZXJlZEIgPSBiXG5cbiAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKVxuICAgIH1cblxuICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpXG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICBiOiByZW5kZXJlZEJcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGVcblxuICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpXG4gICAgfVxuXG4gICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fFxuICAgICAgICAgICAgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fFxuICAgICAgICAgICAgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVuZGVyZWRUaHVua1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rXHJcblxyXG5mdW5jdGlvbiBpc1RodW5rKHQpIHtcclxuICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiXHJcbn1cclxuIiwibW9kdWxlLmV4cG9ydHMgPSBpc0hvb2tcblxuZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICByZXR1cm4gaG9vayAmJlxuICAgICAgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHxcbiAgICAgICB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSlcbn1cbiIsInZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGVcblxuZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uXG59XG4iLCJ2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIilcblxubW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0XG5cbmZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvblxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldFxuXG5mdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiXG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IFwiMlwiXG4iLCJ2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIilcbnZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIilcbnZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKVxudmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKVxudmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlXG5cbnZhciBub1Byb3BlcnRpZXMgPSB7fVxudmFyIG5vQ2hpbGRyZW4gPSBbXVxuXG5mdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lXG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXNcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlblxuICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZFxuICAgIHRoaXMubmFtZXNwYWNlID0gKHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIpID8gbmFtZXNwYWNlIDogbnVsbFxuXG4gICAgdmFyIGNvdW50ID0gKGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCkgfHwgMFxuICAgIHZhciBkZXNjZW5kYW50cyA9IDBcbiAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlXG4gICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlXG4gICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlXG4gICAgdmFyIGhvb2tzXG5cbiAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV1cbiAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge31cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldXG4gICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMFxuXG4gICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzXG4gICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0c1xuICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzXG4gICAgdGhpcy5ob29rcyA9IGhvb2tzXG4gICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3Ncbn1cblxuVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uXG5WaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIlxuIiwidmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpXG5cblZpcnR1YWxQYXRjaC5OT05FID0gMFxuVmlydHVhbFBhdGNoLlZURVhUID0gMVxuVmlydHVhbFBhdGNoLlZOT0RFID0gMlxuVmlydHVhbFBhdGNoLldJREdFVCA9IDNcblZpcnR1YWxQYXRjaC5QUk9QUyA9IDRcblZpcnR1YWxQYXRjaC5PUkRFUiA9IDVcblZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2XG5WaXJ0dWFsUGF0Y2guUkVNT1ZFID0gN1xuVmlydHVhbFBhdGNoLlRIVU5LID0gOFxuXG5tb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaFxuXG5mdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpXG4gICAgdGhpcy52Tm9kZSA9IHZOb2RlXG4gICAgdGhpcy5wYXRjaCA9IHBhdGNoXG59XG5cblZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb25cblZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCJcbiIsInZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0XG5cbmZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dClcbn1cblxuVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uXG5WaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIlxuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKVxudmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wc1xuXG5mdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgIHZhciBkaWZmXG5cbiAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge31cbiAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWRcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldXG4gICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldXG5cbiAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9XG4gICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZVxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fVxuICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKVxuICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9XG4gICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge31cbiAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWVcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fVxuICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkaWZmXG59XG5cbmZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSlcbiAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICByZXR1cm4gdmFsdWUuX19wcm90b19fXG4gIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlXG4gIH1cbn1cbiIsInZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIilcblxudmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIilcbnZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpXG52YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKVxudmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKVxudmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIilcbnZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIilcblxudmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIilcblxubW9kdWxlLmV4cG9ydHMgPSBkaWZmXG5cbmZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgIHZhciBwYXRjaCA9IHsgYTogYSB9XG4gICAgd2FsayhhLCBiLCBwYXRjaCwgMClcbiAgICByZXR1cm4gcGF0Y2hcbn1cblxuZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF1cbiAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlXG5cbiAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpXG4gICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KVxuICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF1cbiAgICAgICAgfVxuXG4gICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpXG4gICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiZcbiAgICAgICAgICAgICAgICBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiZcbiAgICAgICAgICAgICAgICBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LFxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpXG4gICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSlcbiAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlXG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpXG4gICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpXG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlXG4gICAgICAgIH1cblxuICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKVxuICAgIH1cblxuICAgIGlmIChhcHBseSkge1xuICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseVxuICAgIH1cblxuICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlblxuICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pXG4gICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW5cblxuICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aFxuICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aFxuICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuXG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXVxuICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldXG4gICAgICAgIGluZGV4ICs9IDFcblxuICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goXG4gICAgICAgICAgICBWUGF0Y2guT1JERVIsXG4gICAgICAgICAgICBhLFxuICAgICAgICAgICAgb3JkZXJlZFNldC5tb3Zlc1xuICAgICAgICApKVxuICAgIH1cblxuICAgIHJldHVybiBhcHBseVxufVxuXG5mdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KVxuICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpXG59XG5cbi8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG5mdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2goXG4gICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdLFxuICAgICAgICAgICAgICAgIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpXG4gICAgICAgICAgICApXG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW5cbiAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aFxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXVxuICAgICAgICAgICAgaW5kZXggKz0gMVxuXG4gICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KVxuXG4gICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleClcbiAgICB9XG59XG5cbi8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG5mdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYilcbiAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYilcbiAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG59XG5cbi8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChcbiAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0sXG4gICAgICAgICAgICAgICAgbmV3IFZQYXRjaChcbiAgICAgICAgICAgICAgICAgICAgVlBhdGNoLlBST1BTLFxuICAgICAgICAgICAgICAgICAgICB2Tm9kZSxcbiAgICAgICAgICAgICAgICAgICAgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcylcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW5cbiAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGhcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXVxuICAgICAgICAgICAgICAgIGluZGV4ICs9IDFcblxuICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdFxufVxuXG4vLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pXG4gICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5c1xuICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWVcblxuICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbilcbiAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzXG4gICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZVxuXG4gICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgdmFyIG5ld0NoaWxkcmVuID0gW11cblxuICAgIHZhciBmcmVlSW5kZXggPSAwXG4gICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aFxuICAgIHZhciBkZWxldGVkSXRlbXMgPSAwXG5cbiAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAvLyBPKE4pIHRpbWUsXG4gICAgZm9yICh2YXIgaSA9IDAgOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXVxuICAgICAgICB2YXIgaXRlbUluZGV4XG5cbiAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldXG4gICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSlcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrXG4gICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdXG4gICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKytcbiAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggP1xuICAgICAgICBiQ2hpbGRyZW4ubGVuZ3RoIDpcbiAgICAgICAgYkZyZWVbZnJlZUluZGV4XVxuXG4gICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAvLyBPKE0pIHRpbWVcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXVxuXG4gICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKVxuICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMFxuICAgIHZhciByZW1vdmVzID0gW11cbiAgICB2YXIgaW5zZXJ0cyA9IFtdXG4gICAgdmFyIHNpbXVsYXRlSXRlbVxuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXVxuICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XVxuXG4gICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpXG4gICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goe2tleTogd2FudGVkSXRlbS5rZXksIHRvOiBrfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goe2tleTogd2FudGVkSXRlbS5rZXksIHRvOiBrfSlcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHtrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzoga30pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGsrK1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrK1xuICAgICAgICAgICAgaysrXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgIHdoaWxlKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF1cbiAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKVxuICAgIH1cblxuICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgYXJyLnNwbGljZShpbmRleCwgMSlcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICBrZXk6IGtleVxuICAgIH1cbn1cblxuZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICB2YXIga2V5cyA9IHt9XG4gICAgdmFyIGZyZWUgPSBbXVxuICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGhcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV1cblxuICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcmVlLnB1c2goaSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGtleXM6IGtleXMsICAgICAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgZnJlZTogZnJlZSAgICAgIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgfVxufVxuXG5mdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFwcGx5XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHBhdGNoXG4gICAgfVxufVxuIiwidmFyIHNpbXBsZVByb21pc2UgPSByZXF1aXJlKCcuL3NpbXBsZVByb21pc2UnKTtcblxuZnVuY3Rpb24gUmVuZGVyKG1vdW50KSB7XG4gIHRoaXMuZmluaXNoZWQgPSBzaW1wbGVQcm9taXNlKCk7XG4gIHRoaXMubW91bnQgPSBtb3VudDtcbiAgdGhpcy5hdHRhY2htZW50ID0gbW91bnQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gUmVuZGVyO1xuIiwidmFyIGggPSByZXF1aXJlKCcuL3ZodG1sJyk7XG52YXIgZG9tQ29tcG9uZW50ID0gcmVxdWlyZSgnLi9kb21Db21wb25lbnQnKTtcbnZhciBiaW5kaW5nTWV0YSA9IHJlcXVpcmUoJy4vbWV0YScpO1xudmFyIHRvVmRvbSA9IHJlcXVpcmUoJy4vdG9WZG9tJyk7XG52YXIgcGFyc2VUYWcgPSByZXF1aXJlKCd2aXJ0dWFsLWRvbS92aXJ0dWFsLWh5cGVyc2NyaXB0L3BhcnNlLXRhZycpO1xudmFyIFZpZXdNb2RlbCA9IHJlcXVpcmUoJy4vdmlld01vZGVsJyk7XG52YXIgTW91bnQgPSByZXF1aXJlKCcuL21vdW50Jyk7XG52YXIgcnVuUmVuZGVyID0gcmVxdWlyZSgnLi9ydW5SZW5kZXInKTtcbnZhciBkZXByZWNhdGlvbnMgPSByZXF1aXJlKCcuL2RlcHJlY2F0aW9ucycpO1xudmFyIGh5cGVyZG9tID0gcmVxdWlyZSgnLicpO1xuXG5mdW5jdGlvbiBpc1ZpZXdNb2RlbE9yQ29tcG9uZW50KGNvbXBvbmVudCkge1xuICByZXR1cm4gY29tcG9uZW50XG4gICAgJiYgKCh0eXBlb2YgY29tcG9uZW50LmluaXQgPT09ICdmdW5jdGlvbidcbiAgICAgICAmJiB0eXBlb2YgY29tcG9uZW50LnVwZGF0ZSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICYmIHR5cGVvZiBjb21wb25lbnQuZGVzdHJveSA9PT0gJ2Z1bmN0aW9uJykgfHwgKHR5cGVvZiBjb21wb25lbnQucmVuZGVyVmlld01vZGVsID09PSAnZnVuY3Rpb24nKSk7XG59XG5cbmV4cG9ydHMubWVyZ2UgPSBmdW5jdGlvbiAoZWxlbWVudCwgcmVuZGVyLCBtb2RlbCwgb3B0aW9ucykge1xuICB2YXIgbW91bnQgPSBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICB2YXIgY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICAgIHZhciBjdXJyZW50UmVuZGVyID0gaHlwZXJkb20uY3VycmVudFJlbmRlcjtcbiAgICBjdXJyZW50UmVuZGVyLmV2ZW50SGFuZGxlcldyYXBwZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgdmFyIHZkb20gPSBtb3VudC5yZW5kZXIoKTtcbiAgICBjb21wb25lbnQubWVyZ2UodmRvbSwgZWxlbWVudCk7XG4gICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgfSk7XG5cbiAgbW91bnQucmVyZW5kZXIoKTtcblxuICByZXR1cm4gbW91bnQ7XG59O1xuXG5leHBvcnRzLmFwcGVuZCA9IGZ1bmN0aW9uIChlbGVtZW50LCByZW5kZXIsIG1vZGVsLCBvcHRpb25zKSB7XG4gIHJldHVybiBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICB2YXIgY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICAgIHZhciB2ZG9tID0gbW91bnQucmVuZGVyKCk7XG4gICAgZWxlbWVudC5hcHBlbmRDaGlsZChjb21wb25lbnQuY3JlYXRlKHZkb20pKTtcbiAgICByZXR1cm4gY29tcG9uZW50O1xuICB9KTtcbn07XG5cbmV4cG9ydHMucmVwbGFjZSA9IGZ1bmN0aW9uIChlbGVtZW50LCByZW5kZXIsIG1vZGVsLCBvcHRpb25zKSB7XG4gIHJldHVybiBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICB2YXIgY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICAgIHZhciB2ZG9tID0gbW91bnQucmVuZGVyKCk7XG4gICAgZWxlbWVudC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChjb21wb25lbnQuY3JlYXRlKHZkb20pLCBlbGVtZW50KTtcbiAgICByZXR1cm4gY29tcG9uZW50O1xuICB9KTtcbn07XG5cbmV4cG9ydHMuYXBwZW5kVkRvbSA9IGZ1bmN0aW9uICh2ZG9tLCByZW5kZXIsIG1vZGVsLCBvcHRpb25zKSB7XG4gIHJldHVybiBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQpIHtcbiAgICB2YXIgY29tcG9uZW50ID0ge1xuICAgICAgY3JlYXRlOiBmdW5jdGlvbihuZXdWRG9tKSB7XG4gICAgICAgIHZkb20uY2hpbGRyZW4gPSBbXTtcbiAgICAgICAgaWYgKG5ld1ZEb20pIHtcbiAgICAgICAgICB2ZG9tLmNoaWxkcmVuLnB1c2gobmV3VkRvbSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB1cGRhdGU6IGZ1bmN0aW9uKG5ld1ZEb20pIHtcbiAgICAgICAgdmRvbS5jaGlsZHJlbiA9IFtdO1xuICAgICAgICBpZiAobmV3VkRvbSkge1xuICAgICAgICAgIHZkb20uY2hpbGRyZW4ucHVzaChuZXdWRG9tKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgY29tcG9uZW50LmNyZWF0ZShtb3VudC5yZW5kZXIoKSk7XG4gICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgfSk7XG59O1xuXG5leHBvcnRzLlZpZXdNb2RlbCA9IFZpZXdNb2RlbDtcblxuZnVuY3Rpb24gc3RhcnRBdHRhY2htZW50KHJlbmRlciwgbW9kZWwsIG9wdGlvbnMsIGF0dGFjaFRvRG9tKSB7XG4gIGlmICh0eXBlb2YgcmVuZGVyID09ICdvYmplY3QnICYmIHR5cGVvZiByZW5kZXIucmVuZGVyID09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gc3RhcnQocmVuZGVyLCBhdHRhY2hUb0RvbSwgbW9kZWwpO1xuICB9IGVsc2Uge1xuICAgIGRlcHJlY2F0aW9ucy5yZW5kZXJGdW5jdGlvbignaHlwZXJkb20uYXBwZW5kIGFuZCBoeXBlcmRvbS5yZXBsYWNlIHdpdGggcmVuZGVyIGZ1bmN0aW9ucyBhcmUgZGVwcmVjYXRlZCwgcGxlYXNlIHBhc3MgYSBWaWV3TW9kZWwnKTtcbiAgICByZXR1cm4gc3RhcnQoe3JlbmRlcjogZnVuY3Rpb24gKCkgeyByZXR1cm4gcmVuZGVyKG1vZGVsKTsgfX0sIGF0dGFjaFRvRG9tLCBvcHRpb25zKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzdGFydChtb2RlbCwgYXR0YWNoVG9Eb20sIG9wdGlvbnMpIHtcbiAgdmFyIG1vdW50ID0gbmV3IE1vdW50KG1vZGVsLCBvcHRpb25zKTtcbiAgcnVuUmVuZGVyKG1vdW50LCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgIHZhciBkb21Db21wb25lbnRPcHRpb25zID0ge2RvY3VtZW50OiBvcHRpb25zLmRvY3VtZW50fTtcbiAgICB9XG4gICAgbW91bnQuY29tcG9uZW50ID0gYXR0YWNoVG9Eb20obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICB9KTtcbiAgcmV0dXJuIG1vdW50O1xufVxuXG52YXIgbm9yZWZyZXNoID0ge307XG5cbmZ1bmN0aW9uIG5vcmVmcmVzaEZ1bmN0aW9uKCkge1xuICByZXR1cm4gbm9yZWZyZXNoO1xufVxuXG5mdW5jdGlvbiByZWZyZXNoaWZ5KGZuLCBvcHRpb25zKSB7XG4gIGlmICghZm4pIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgY3VycmVudFJlbmRlciA9IGh5cGVyZG9tLmN1cnJlbnRSZW5kZXIoKTtcblxuICBpZiAoIWN1cnJlbnRSZW5kZXIpIHtcbiAgICBpZiAodHlwZW9mIGdsb2JhbCA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBmbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgY2Fubm90IGNyZWF0ZSB2aXJ0dWFsLWRvbSBldmVudCBoYW5kbGVycyBvdXRzaWRlIGEgcmVuZGVyIGZ1bmN0aW9uLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZlYXR1cmlzdC9oeXBlcmRvbSNvdXRzaWRlLXJlbmRlci1jeWNsZScpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBtb3VudCA9IGN1cnJlbnRSZW5kZXIubW91bnQ7XG4gIHZhciBoYW5kbGVFdmVudFJlc3VsdCA9IGV4cG9ydHMuY3JlYXRlRXZlbnRSZXN1bHRIYW5kbGVyKG1vdW50LCBvcHRpb25zKTtcblxuICBpZiAob3B0aW9ucyAmJiAob3B0aW9ucy5ub3JlZnJlc2ggPT0gdHJ1ZSB8fCBvcHRpb25zLnJlZnJlc2ggPT0gZmFsc2UpKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gaGFuZGxlRXZlbnRSZXN1bHQocmVzdWx0KTtcbiAgfTtcbn1cblxuZXhwb3J0cy5jcmVhdGVFdmVudFJlc3VsdEhhbmRsZXIgPSBmdW5jdGlvbihtb3VudCwgb3B0aW9ucykge1xuICB2YXIgb25seVJlZnJlc2hBZnRlclByb21pc2UgPSBvcHRpb25zICYmIG9wdGlvbnMucmVmcmVzaCA9PSAncHJvbWlzZSc7XG4gIHZhciB2aWV3TW9kZWxUb1JlZnJlc2ggPSBvcHRpb25zICYmIG9wdGlvbnMudmlld01vZGVsO1xuICB2YXIgY29tcG9uZW50VG9SZWZyZXNoID0gb3B0aW9ucyAmJiBvcHRpb25zLmNvbXBvbmVudDtcblxuICBmdW5jdGlvbiBoYW5kbGVFdmVudFJlc3VsdChyZXN1bHQsIHByb21pc2VSZXN1bHQpIHtcbiAgICBpZiAocmVzdWx0ICYmIHR5cGVvZihyZXN1bHQudGhlbikgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmVzdWx0LnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgeyBoYW5kbGVFdmVudFJlc3VsdChyZXN1bHQsIHRydWUpOyB9KTtcbiAgICB9XG5cbiAgICBpZiAob25seVJlZnJlc2hBZnRlclByb21pc2UgJiYgIXByb21pc2VSZXN1bHQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoaXNWaWV3TW9kZWxPckNvbXBvbmVudChyZXN1bHQpKSB7XG4gICAgICBtb3VudC5yZXJlbmRlcldpZGdldChyZXN1bHQpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhhbmRsZUV2ZW50UmVzdWx0KHJlc3VsdFtpXSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2aWV3TW9kZWxUb1JlZnJlc2gpIHtcbiAgICAgIHZpZXdNb2RlbFRvUmVmcmVzaC5yZXJlbmRlclZpZXdNb2RlbCgpO1xuICAgIH0gZWxzZSBpZiAoY29tcG9uZW50VG9SZWZyZXNoKSB7XG4gICAgICBjb21wb25lbnRUb1JlZnJlc2gucmVmcmVzaCgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0ID09PSBub3JlZnJlc2gpIHtcbiAgICAgIC8vIGRvbid0IHJlZnJlc2g7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQgPT09IG5vcmVmcmVzaEZ1bmN0aW9uKSB7XG4gICAgICBkZXByZWNhdGlvbnMubm9yZWZyZXNoKCdoeXBlcmRvbS5odG1sLm5vcmVmcmVzaCBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGh5cGVyZG9tLm5vcmVmcmVzaCgpJyk7XG4gICAgICAvLyBkb24ndCByZWZyZXNoO1xuICAgIH0gZWxzZSB7XG4gICAgICBtb3VudC5yZXJlbmRlcigpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaGFuZGxlRXZlbnRSZXN1bHQ7XG59O1xuXG5mdW5jdGlvbiBiaW5kVGV4dElucHV0KGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBnZXQsIHNldCkge1xuICB2YXIgdGV4dEV2ZW50TmFtZXMgPSBbJ29ua2V5dXAnLCAnb25pbnB1dCcsICdvbnBhc3RlJywgJ3RleHRJbnB1dCddO1xuXG4gIHZhciBiaW5kaW5nVmFsdWUgPSBnZXQoKTtcbiAgaWYgKCEoYmluZGluZ1ZhbHVlIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgYXR0cmlidXRlcy52YWx1ZSA9IGJpbmRpbmdWYWx1ZSAhPSB1bmRlZmluZWQ/IGJpbmRpbmdWYWx1ZTogJyc7XG4gIH1cblxuICBhdHRhY2hFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgdGV4dEV2ZW50TmFtZXMsIGZ1bmN0aW9uIChldikge1xuICAgIGlmIChiaW5kaW5nVmFsdWUgIT0gZXYudGFyZ2V0LnZhbHVlKSB7XG4gICAgICBzZXQoZXYudGFyZ2V0LnZhbHVlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzZXF1ZW5jZUZ1bmN0aW9ucyhoYW5kbGVyMSwgaGFuZGxlcjIpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChldikge1xuICAgIGhhbmRsZXIxKGV2KTtcbiAgICByZXR1cm4gaGFuZGxlcjIoZXYpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBpbnNlcnRFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgZXZlbnROYW1lLCBoYW5kbGVyKSB7XG4gIHZhciBwcmV2aW91c0hhbmRsZXIgPSBhdHRyaWJ1dGVzW2V2ZW50TmFtZV07XG4gIGlmIChwcmV2aW91c0hhbmRsZXIpIHtcbiAgICBhdHRyaWJ1dGVzW2V2ZW50TmFtZV0gPSBzZXF1ZW5jZUZ1bmN0aW9ucyhoYW5kbGVyLCBwcmV2aW91c0hhbmRsZXIpO1xuICB9IGVsc2Uge1xuICAgIGF0dHJpYnV0ZXNbZXZlbnROYW1lXSA9IGhhbmRsZXI7XG4gIH1cbn1cblxuZnVuY3Rpb24gYXR0YWNoRXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsIGV2ZW50TmFtZXMsIGhhbmRsZXIpIHtcbiAgaWYgKGV2ZW50TmFtZXMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIGZvciAodmFyIG4gPSAwOyBuIDwgZXZlbnROYW1lcy5sZW5ndGg7IG4rKykge1xuICAgICAgaW5zZXJ0RXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsIGV2ZW50TmFtZXNbbl0sIGhhbmRsZXIpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpbnNlcnRFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgZXZlbnROYW1lcywgaGFuZGxlcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gTGlzdGVuZXJIb29rKGxpc3RlbmVyKSB7XG4gIHRoaXMubGlzdGVuZXIgPSBleHBvcnRzLmh0bWwucmVmcmVzaGlmeShsaXN0ZW5lcik7XG59XG5cbkxpc3RlbmVySG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChlbGVtZW50LCBwcm9wZXJ0eU5hbWUpIHtcbiAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHByb3BlcnR5TmFtZS5zdWJzdHJpbmcoMiksIHRoaXMubGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkxpc3RlbmVySG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKGVsZW1lbnQsIHByb3BlcnR5TmFtZSkge1xuICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIocHJvcGVydHlOYW1lLnN1YnN0cmluZygyKSwgdGhpcy5saXN0ZW5lcik7XG59O1xuXG5mdW5jdGlvbiBjdXN0b21FdmVudChuYW1lKSB7XG4gIGlmICh0eXBlb2YgRXZlbnQgPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBuZXcgRXZlbnQobmFtZSk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XG4gICAgZXZlbnQuaW5pdEV2ZW50KG5hbWUsIGZhbHNlLCBmYWxzZSk7XG4gICAgcmV0dXJuIGV2ZW50O1xuICB9XG59XG5cbnZhciBpbnB1dFR5cGVCaW5kaW5ncyA9IHtcbiAgdGV4dDogYmluZFRleHRJbnB1dCxcblxuICB0ZXh0YXJlYTogYmluZFRleHRJbnB1dCxcblxuICBjaGVja2JveDogZnVuY3Rpb24gKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBnZXQsIHNldCkge1xuICAgIGF0dHJpYnV0ZXMuY2hlY2tlZCA9IGdldCgpO1xuXG4gICAgYXR0YWNoRXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsICdvbmNsaWNrJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICBhdHRyaWJ1dGVzLmNoZWNrZWQgPSBldi50YXJnZXQuY2hlY2tlZDtcbiAgICAgIHNldChldi50YXJnZXQuY2hlY2tlZCk7XG4gICAgfSk7XG4gIH0sXG5cbiAgcmFkaW86IGZ1bmN0aW9uIChhdHRyaWJ1dGVzLCBjaGlsZHJlbiwgZ2V0LCBzZXQpIHtcbiAgICB2YXIgdmFsdWUgPSBhdHRyaWJ1dGVzLnZhbHVlO1xuICAgIGF0dHJpYnV0ZXMuY2hlY2tlZCA9IGdldCgpID09IGF0dHJpYnV0ZXMudmFsdWU7XG4gICAgYXR0cmlidXRlcy5vbl9oeXBlcmRvbXN5bmNjaGVja2VkID0gbmV3IExpc3RlbmVySG9vayhmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGF0dHJpYnV0ZXMuY2hlY2tlZCA9IGV2ZW50LnRhcmdldC5jaGVja2VkO1xuICAgIH0pO1xuXG4gICAgYXR0YWNoRXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsICdvbmNsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICB2YXIgbmFtZSA9IGV2ZW50LnRhcmdldC5uYW1lO1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgdmFyIGlucHV0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlOYW1lKG5hbWUpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGlucHV0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICBpbnB1dHNbaV0uZGlzcGF0Y2hFdmVudChjdXN0b21FdmVudCgnX2h5cGVyZG9tc3luY2NoZWNrZWQnKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNldCh2YWx1ZSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgc2VsZWN0OiBmdW5jdGlvbiAoYXR0cmlidXRlcywgY2hpbGRyZW4sIGdldCwgc2V0KSB7XG4gICAgdmFyIGN1cnJlbnRWYWx1ZSA9IGdldCgpO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBjaGlsZHJlbi5maWx0ZXIoZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICByZXR1cm4gY2hpbGQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09ICdvcHRpb24nO1xuICAgIH0pO1xuXG4gICAgdmFyIHZhbHVlcyA9IFtdO1xuICAgIHZhciBzZWxlY3RlZEluZGV4O1xuXG4gICAgZm9yKHZhciBuID0gMDsgbiA8IG9wdGlvbnMubGVuZ3RoOyBuKyspIHtcbiAgICAgIHZhciBvcHRpb24gPSBvcHRpb25zW25dO1xuICAgICAgdmFyIGhhc1ZhbHVlID0gb3B0aW9uLnByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJyk7XG4gICAgICB2YXIgdmFsdWUgPSBvcHRpb24ucHJvcGVydGllcy52YWx1ZTtcbiAgICAgIHZhciB0ZXh0ID0gb3B0aW9uLmNoaWxkcmVuLm1hcChmdW5jdGlvbiAoeCkgeyByZXR1cm4geC50ZXh0OyB9KS5qb2luKCcnKTtcblxuICAgICAgdmFsdWVzLnB1c2goaGFzVmFsdWU/IHZhbHVlOiB0ZXh0KTtcblxuICAgICAgdmFyIHNlbGVjdGVkID0gdmFsdWUgPT0gY3VycmVudFZhbHVlIHx8IHRleHQgPT0gY3VycmVudFZhbHVlO1xuXG4gICAgICBpZiAoc2VsZWN0ZWQpIHtcbiAgICAgICAgc2VsZWN0ZWRJbmRleCA9IG47XG4gICAgICB9XG5cbiAgICAgIG9wdGlvbi5wcm9wZXJ0aWVzLnNlbGVjdGVkID0gc2VsZWN0ZWQ7XG4gICAgICBvcHRpb24ucHJvcGVydGllcy52YWx1ZSA9IG47XG4gICAgfVxuXG4gICAgaWYgKHNlbGVjdGVkSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgYXR0cmlidXRlcy5zZWxlY3RlZEluZGV4ID0gc2VsZWN0ZWRJbmRleDtcbiAgICB9XG5cbiAgICBhdHRhY2hFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgJ29uY2hhbmdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICBhdHRyaWJ1dGVzLnNlbGVjdGVkSW5kZXggPSBldi50YXJnZXQuc2VsZWN0ZWRJbmRleDtcbiAgICAgIHNldCh2YWx1ZXNbZXYudGFyZ2V0LnZhbHVlXSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgZmlsZTogZnVuY3Rpb24gKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBnZXQsIHNldCkge1xuICAgIHZhciBtdWx0aXBsZSA9IGF0dHJpYnV0ZXMubXVsdGlwbGU7XG5cbiAgICBhdHRhY2hFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgJ29uY2hhbmdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICBpZiAobXVsdGlwbGUpIHtcbiAgICAgICAgc2V0KGV2LnRhcmdldC5maWxlcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXQoZXYudGFyZ2V0LmZpbGVzWzBdKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufTtcblxuZnVuY3Rpb24gYmluZE1vZGVsKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCB0eXBlKSB7XG4gIHZhciBiaW5kID0gaW5wdXRUeXBlQmluZGluZ3NbdHlwZV0gfHwgYmluZFRleHRJbnB1dDtcblxuICB2YXIgYmluZGluZ0F0dHIgPSBtYWtlQmluZGluZyhhdHRyaWJ1dGVzLmJpbmRpbmcpO1xuICBiaW5kKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBiaW5kaW5nQXR0ci5nZXQsIGJpbmRpbmdBdHRyLnNldCk7XG59XG5cbmZ1bmN0aW9uIGlucHV0VHlwZShzZWxlY3RvciwgYXR0cmlidXRlcykge1xuICBpZiAoL150ZXh0YXJlYVxcYi9pLnRlc3Qoc2VsZWN0b3IpKSB7XG4gICAgcmV0dXJuICd0ZXh0YXJlYSc7XG4gIH0gZWxzZSBpZiAoL15zZWxlY3RcXGIvaS50ZXN0KHNlbGVjdG9yKSkge1xuICAgIHJldHVybiAnc2VsZWN0JztcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYXR0cmlidXRlcy50eXBlIHx8ICd0ZXh0JztcbiAgfVxufVxuXG52YXIgcmVuYW1lcyA9IHtcbiAgZm9yOiAnaHRtbEZvcicsXG4gIGNsYXNzOiAnY2xhc3NOYW1lJyxcbiAgY29udGVudGVkaXRhYmxlOiAnY29udGVudEVkaXRhYmxlJyxcbiAgdGFiaW5kZXg6ICd0YWJJbmRleCcsXG4gIGNvbHNwYW46ICdjb2xTcGFuJ1xufTtcblxudmFyIGRhdGFBdHRyaWJ1dGVSZWdleCA9IC9eZGF0YS0vO1xuXG5mdW5jdGlvbiBwcmVwYXJlQXR0cmlidXRlcyh0YWcsIGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzKTtcbiAgdmFyIGRhdGFzZXQ7XG4gIHZhciBjdXJyZW50UmVuZGVyID0gaHlwZXJkb20uY3VycmVudFJlbmRlcigpO1xuICB2YXIgZXZlbnRIYW5kbGVyV3JhcHBlciA9IGN1cnJlbnRSZW5kZXIgJiYgY3VycmVudFJlbmRlci5ldmVudEhhbmRsZXJXcmFwcGVyO1xuXG4gIGZvciAodmFyIGsgPSAwOyBrIDwga2V5cy5sZW5ndGg7IGsrKykge1xuICAgIHZhciBrZXkgPSBrZXlzW2tdO1xuICAgIHZhciBhdHRyaWJ1dGUgPSBhdHRyaWJ1dGVzW2tleV07XG5cbiAgICBpZiAodHlwZW9mKGF0dHJpYnV0ZSkgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgaWYgKGV2ZW50SGFuZGxlcldyYXBwZXIpIHtcbiAgICAgICAgdmFyIGZuID0gZXZlbnRIYW5kbGVyV3JhcHBlci5jYWxsKHVuZGVmaW5lZCwga2V5LnJlcGxhY2UoL15vbi8sICcnKSwgYXR0cmlidXRlKTtcbiAgICAgICAgYXR0cmlidXRlc1trZXldID0gdHlwZW9mIGZuID09PSAnZnVuY3Rpb24nPyByZWZyZXNoaWZ5KGZuKTogZm47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSByZWZyZXNoaWZ5KGF0dHJpYnV0ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlbmFtZSA9IHJlbmFtZXNba2V5XTtcbiAgICBpZiAocmVuYW1lKSB7XG4gICAgICBhdHRyaWJ1dGVzW3JlbmFtZV0gPSBhdHRyaWJ1dGU7XG4gICAgICBkZWxldGUgYXR0cmlidXRlc1trZXldO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKGRhdGFBdHRyaWJ1dGVSZWdleC50ZXN0KGtleSkpIHtcbiAgICAgIGlmICghZGF0YXNldCkge1xuICAgICAgICBkYXRhc2V0ID0gYXR0cmlidXRlcy5kYXRhc2V0O1xuXG4gICAgICAgIGlmICghZGF0YXNldCkge1xuICAgICAgICAgIGRhdGFzZXQgPSBhdHRyaWJ1dGVzLmRhdGFzZXQgPSB7fTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgZGF0YWtleSA9IGtleVxuICAgICAgICAucmVwbGFjZShkYXRhQXR0cmlidXRlUmVnZXgsICcnKVxuICAgICAgICAucmVwbGFjZSgvLShbYS16XSkvaWcsIGZ1bmN0aW9uKF8sIHgpIHsgcmV0dXJuIHgudG9VcHBlckNhc2UoKTsgfSk7XG5cbiAgICAgIGRhdGFzZXRbZGF0YWtleV0gPSBhdHRyaWJ1dGU7XG4gICAgICBkZWxldGUgYXR0cmlidXRlc1trZXldO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKGF0dHJpYnV0ZXMuY2xhc3NOYW1lKSB7XG4gICAgYXR0cmlidXRlcy5jbGFzc05hbWUgPSBnZW5lcmF0ZUNsYXNzTmFtZShhdHRyaWJ1dGVzLmNsYXNzTmFtZSk7XG4gIH1cblxuICBpZiAoYXR0cmlidXRlcy5iaW5kaW5nKSB7XG4gICAgYmluZE1vZGVsKGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMsIGlucHV0VHlwZSh0YWcsIGF0dHJpYnV0ZXMpKTtcbiAgICBkZWxldGUgYXR0cmlidXRlcy5iaW5kaW5nO1xuICB9XG59XG5cbi8qKlxuICogdGhpcyBmdW5jdGlvbiBpcyBxdWl0ZSB1Z2x5IGFuZCB5b3UgbWF5IGJlIHZlcnkgdGVtcHRlZFxuICogdG8gcmVmYWN0b3IgaXQgaW50byBzbWFsbGVyIGZ1bmN0aW9ucywgSSBjZXJ0YWlubHkgYW0uXG4gKiBob3dldmVyLCBpdCB3YXMgd3JpdHRlbiBsaWtlIHRoaXMgZm9yIHBlcmZvcm1hbmNlXG4gKiBzbyB0aGluayBvZiB0aGF0IGJlZm9yZSByZWZhY3RvcmluZyEgOilcbiAqL1xuZXhwb3J0cy5odG1sID0gZnVuY3Rpb24gKGhpZXJhcmNoeVNlbGVjdG9yKSB7XG4gIHZhciBoYXNIaWVyYXJjaHkgPSBoaWVyYXJjaHlTZWxlY3Rvci5pbmRleE9mKCcgJykgPj0gMDtcbiAgdmFyIHNlbGVjdG9yLCBzZWxlY3RvckVsZW1lbnRzO1xuXG4gIGlmIChoYXNIaWVyYXJjaHkpIHtcbiAgICBzZWxlY3RvckVsZW1lbnRzID0gaGllcmFyY2h5U2VsZWN0b3IubWF0Y2goL1xcUysvZyk7XG4gICAgc2VsZWN0b3IgPSBzZWxlY3RvckVsZW1lbnRzW3NlbGVjdG9yRWxlbWVudHMubGVuZ3RoIC0gMV07XG4gIH0gZWxzZSB7XG4gICAgc2VsZWN0b3IgPSBoaWVyYXJjaHlTZWxlY3RvcjtcbiAgfVxuXG4gIHZhciBjaGlsZEVsZW1lbnRzO1xuICB2YXIgdmRvbTtcbiAgdmFyIHRhZztcbiAgdmFyIGF0dHJpYnV0ZXMgPSBhcmd1bWVudHNbMV07XG5cbiAgaWYgKGF0dHJpYnV0ZXMgJiYgYXR0cmlidXRlcy5jb25zdHJ1Y3RvciA9PSBPYmplY3QgJiYgdHlwZW9mIGF0dHJpYnV0ZXMucmVuZGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgY2hpbGRFbGVtZW50cyA9IHRvVmRvbS5yZWN1cnNpdmUoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKSk7XG4gICAgcHJlcGFyZUF0dHJpYnV0ZXMoc2VsZWN0b3IsIGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMpO1xuICAgIHRhZyA9IHBhcnNlVGFnKHNlbGVjdG9yLCBhdHRyaWJ1dGVzKTtcbiAgICB2ZG9tID0gaCh0YWcsIGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMpO1xuICB9IGVsc2Uge1xuICAgIGF0dHJpYnV0ZXMgPSB7fTtcbiAgICBjaGlsZEVsZW1lbnRzID0gdG9WZG9tLnJlY3Vyc2l2ZShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICB0YWcgPSBwYXJzZVRhZyhzZWxlY3RvciwgYXR0cmlidXRlcyk7XG4gICAgdmRvbSA9IGgodGFnLCBhdHRyaWJ1dGVzLCBjaGlsZEVsZW1lbnRzKTtcbiAgfVxuXG4gIGlmIChoYXNIaWVyYXJjaHkpIHtcbiAgICBmb3IodmFyIG4gPSBzZWxlY3RvckVsZW1lbnRzLmxlbmd0aCAtIDI7IG4gPj0gMDsgbi0tKSB7XG4gICAgICB2ZG9tID0gaChzZWxlY3RvckVsZW1lbnRzW25dLCB7fSwgW3Zkb21dKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdmRvbTtcbn07XG5cbmV4cG9ydHMuanN4ID0gZnVuY3Rpb24gKHRhZywgYXR0cmlidXRlcykge1xuICB2YXIgY2hpbGRFbGVtZW50cyA9IHRvVmRvbS5yZWN1cnNpdmUoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKSk7XG4gIGlmIChhdHRyaWJ1dGVzKSB7XG4gICAgcHJlcGFyZUF0dHJpYnV0ZXModGFnLCBhdHRyaWJ1dGVzLCBjaGlsZEVsZW1lbnRzKTtcbiAgfVxuICByZXR1cm4gaCh0YWcsIGF0dHJpYnV0ZXMgfHwge30sIGNoaWxkRWxlbWVudHMpO1xufTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMuaHRtbCwgJ2N1cnJlbnRSZW5kZXInLCB7Z2V0OiBmdW5jdGlvbiAoKSB7XG4gIGRlcHJlY2F0aW9ucy5jdXJyZW50UmVuZGVyKCdoeXBlcmRvbS5odG1sLmN1cnJlbnRSZW5kZXIgaXMgZGVwcmVjYXRlZCwgcGxlYXNlIHVzZSBoeXBlcmRvbS5jdXJyZW50UmVuZGVyKCkgaW5zdGVhZCcpO1xuICByZXR1cm4gZXhwb3J0cy5odG1sLl9jdXJyZW50UmVuZGVyO1xufX0pO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cy5odG1sLCAncmVmcmVzaCcsIHtnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgZGVwcmVjYXRpb25zLnJlZnJlc2goJ2h5cGVyZG9tLmh0bWwucmVmcmVzaCBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIHZpZXdNb2RlbC5yZXJlbmRlcigpIGluc3RlYWQnKTtcbiAgcmV0dXJuIGV4cG9ydHMuaHRtbC5fcmVmcmVzaDtcbn19KTtcblxuZnVuY3Rpb24gcmVmcmVzaEFmdGVyKHByb21pc2UpIHtcbiAgZGVwcmVjYXRpb25zLnJlZnJlc2hBZnRlcignaHlwZXJkb20uaHRtbC5yZWZyZXNoQWZ0ZXIgaXMgZGVwcmVjYXRlZCcpO1xuICB2YXIgcmVmcmVzaCA9IGV4cG9ydHMuaHRtbC5yZWZyZXNoO1xuXG4gIHByb21pc2UudGhlbihyZWZyZXNoKTtcbn1cblxuZXhwb3J0cy5odG1sLnJlZnJlc2hpZnkgPSByZWZyZXNoaWZ5O1xuZXhwb3J0cy5odG1sLnJlZnJlc2hBZnRlciA9IHJlZnJlc2hBZnRlcjtcbmV4cG9ydHMuaHRtbC5ub3JlZnJlc2ggPSBub3JlZnJlc2g7XG5cbmZ1bmN0aW9uIG1ha2VCaW5kaW5nKGIsIG9wdGlvbnMpIHtcbiAgdmFyIGJpbmRpbmcgPSBiIGluc3RhbmNlb2YgQXJyYXlcbiAgICA/ICBiaW5kaW5nT2JqZWN0LmFwcGx5KHVuZGVmaW5lZCwgYilcbiAgICA6IGI7XG5cbiAgYmluZGluZy5zZXQgPSByZWZyZXNoaWZ5KGJpbmRpbmcuc2V0LCBvcHRpb25zKTtcblxuICByZXR1cm4gYmluZGluZztcbn1cblxuZnVuY3Rpb24gbWFrZUNvbnZlcnRlcihjb252ZXJ0ZXIpIHtcbiAgaWYgKHR5cGVvZiBjb252ZXJ0ZXIgPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiB7XG4gICAgICB2aWV3OiBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgcmV0dXJuIG1vZGVsO1xuICAgICAgfSxcbiAgICAgIG1vZGVsOiBmdW5jdGlvbiAodmlldykge1xuICAgICAgICByZXR1cm4gY29udmVydGVyKHZpZXcpO1xuICAgICAgfVxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvbnZlcnRlcjtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGFpbkNvbnZlcnRlcnMoc3RhcnRJbmRleCwgY29udmVydGVycykge1xuICBmdW5jdGlvbiBtYWtlQ29udmVydGVycygpIHtcbiAgICBpZiAoIV9jb252ZXJ0ZXJzKSB7XG4gICAgICBfY29udmVydGVycyA9IG5ldyBBcnJheShjb252ZXJ0ZXJzLmxlbmd0aCAtIHN0YXJ0SW5kZXgpO1xuXG4gICAgICBmb3IodmFyIG4gPSBzdGFydEluZGV4OyBuIDwgY29udmVydGVycy5sZW5ndGg7IG4rKykge1xuICAgICAgICBfY29udmVydGVyc1tuIC0gc3RhcnRJbmRleF0gPSBtYWtlQ29udmVydGVyKGNvbnZlcnRlcnNbbl0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICgoY29udmVydGVycy5sZW5ndGggLSBzdGFydEluZGV4KSA9PSAxKSB7XG4gICAgcmV0dXJuIG1ha2VDb252ZXJ0ZXIoY29udmVydGVyc1tzdGFydEluZGV4XSk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIF9jb252ZXJ0ZXJzO1xuICAgIHJldHVybiB7XG4gICAgICB2aWV3OiBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgbWFrZUNvbnZlcnRlcnMoKTtcbiAgICAgICAgdmFyIGludGVybWVkaWF0ZVZhbHVlID0gbW9kZWw7XG4gICAgICAgIGZvcih2YXIgbiA9IDA7IG4gPCBfY29udmVydGVycy5sZW5ndGg7IG4rKykge1xuICAgICAgICAgIGludGVybWVkaWF0ZVZhbHVlID0gX2NvbnZlcnRlcnNbbl0udmlldyhpbnRlcm1lZGlhdGVWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludGVybWVkaWF0ZVZhbHVlO1xuICAgICAgfSxcblxuICAgICAgbW9kZWw6IGZ1bmN0aW9uICh2aWV3KSB7XG4gICAgICAgIG1ha2VDb252ZXJ0ZXJzKCk7XG4gICAgICAgIHZhciBpbnRlcm1lZGlhdGVWYWx1ZSA9IHZpZXc7XG4gICAgICAgIGZvcih2YXIgbiA9IF9jb252ZXJ0ZXJzLmxlbmd0aCAtIDE7IG4gPj0gMDsgbi0tKSB7XG4gICAgICAgICAgaW50ZXJtZWRpYXRlVmFsdWUgPSBfY29udmVydGVyc1tuXS5tb2RlbChpbnRlcm1lZGlhdGVWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludGVybWVkaWF0ZVZhbHVlO1xuICAgICAgfVxuICAgIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gYmluZGluZ09iamVjdChtb2RlbCwgcHJvcGVydHkpIHtcbiAgdmFyIF9tZXRhO1xuICBmdW5jdGlvbiBoeXBlcmRvbU1ldGEoKSB7XG4gICAgcmV0dXJuIF9tZXRhIHx8IChfbWV0YSA9IGJpbmRpbmdNZXRhKG1vZGVsLCBwcm9wZXJ0eSkpO1xuICB9XG5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKSB7XG4gICAgdmFyIGNvbnZlcnRlciA9IGNoYWluQ29udmVydGVycygyLCBhcmd1bWVudHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtZXRhID0gaHlwZXJkb21NZXRhKCk7XG4gICAgICAgIHZhciBtb2RlbFZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICB2YXIgbW9kZWxUZXh0O1xuXG4gICAgICAgIGlmIChtZXRhLmVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIG1ldGEudmlldztcbiAgICAgICAgfSBlbHNlIGlmIChtZXRhLnZpZXcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG1vZGVsVGV4dCA9IGNvbnZlcnRlci52aWV3KG1vZGVsVmFsdWUpO1xuICAgICAgICAgIG1ldGEudmlldyA9IG1vZGVsVGV4dDtcbiAgICAgICAgICByZXR1cm4gbW9kZWxUZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gY29udmVydGVyLm1vZGVsKG1ldGEudmlldyk7XG4gICAgICAgICAgbW9kZWxUZXh0ID0gY29udmVydGVyLnZpZXcobW9kZWxWYWx1ZSk7XG4gICAgICAgICAgdmFyIG5vcm1hbGlzZWRQcmV2aW91c1RleHQgPSBjb252ZXJ0ZXIudmlldyhwcmV2aW91c1ZhbHVlKTtcblxuICAgICAgICAgIGlmIChtb2RlbFRleHQgPT09IG5vcm1hbGlzZWRQcmV2aW91c1RleHQpIHtcbiAgICAgICAgICAgIHJldHVybiBtZXRhLnZpZXc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1ldGEudmlldyA9IG1vZGVsVGV4dDtcbiAgICAgICAgICAgIHJldHVybiBtb2RlbFRleHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuXG4gICAgICBzZXQ6IGZ1bmN0aW9uKHZpZXcpIHtcbiAgICAgICAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEoKTtcbiAgICAgICAgbWV0YS52aWV3ID0gdmlldztcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IGNvbnZlcnRlci5tb2RlbCh2aWV3LCBtb2RlbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgIGRlbGV0ZSBtZXRhLmVycm9yO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgbWV0YS5lcnJvciA9IGU7XG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIG1ldGE6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gaHlwZXJkb21NZXRhKCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4ge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICB9LFxuXG4gICAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgICAgIH0sXG5cbiAgICAgIG1ldGE6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gaHlwZXJkb21NZXRhKCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnRzLmJpbmRpbmcgPSBtYWtlQmluZGluZztcbmV4cG9ydHMuaHRtbC5iaW5kaW5nID0gbWFrZUJpbmRpbmc7XG5leHBvcnRzLmh0bWwubWV0YSA9IGJpbmRpbmdNZXRhO1xuXG5mdW5jdGlvbiByYXdIdG1sKCkge1xuICB2YXIgc2VsZWN0b3I7XG4gIHZhciBodG1sO1xuICB2YXIgb3B0aW9ucztcblxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAyKSB7XG4gICAgc2VsZWN0b3IgPSBhcmd1bWVudHNbMF07XG4gICAgaHRtbCA9IGFyZ3VtZW50c1sxXTtcbiAgICBvcHRpb25zID0ge2lubmVySFRNTDogaHRtbH07XG4gICAgcmV0dXJuIGV4cG9ydHMuaHRtbChzZWxlY3Rvciwgb3B0aW9ucyk7XG4gIH0gZWxzZSB7XG4gICAgc2VsZWN0b3IgPSBhcmd1bWVudHNbMF07XG4gICAgb3B0aW9ucyA9IGFyZ3VtZW50c1sxXTtcbiAgICBodG1sID0gYXJndW1lbnRzWzJdO1xuICAgIG9wdGlvbnMuaW5uZXJIVE1MID0gaHRtbDtcbiAgICByZXR1cm4gZXhwb3J0cy5odG1sKHNlbGVjdG9yLCBvcHRpb25zKTtcbiAgfVxufVxuXG5leHBvcnRzLmh0bWwucmF3SHRtbCA9IHJhd0h0bWw7XG5cblxuZnVuY3Rpb24gZ2VuZXJhdGVDb25kaXRpb25hbENsYXNzTmFtZXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmZpbHRlcihmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIG9ialtrZXldO1xuICB9KS5qb2luKCcgJykgfHwgdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUNsYXNzTmFtZShvYmopIHtcbiAgaWYgKHR5cGVvZihvYmopID09ICdvYmplY3QnKSB7XG4gICAgaWYgKG9iaiBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICB2YXIgbmFtZXMgPSBvYmoubWFwKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgcmV0dXJuIGdlbmVyYXRlQ2xhc3NOYW1lKGl0ZW0pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmFtZXMuam9pbignICcpIHx8IHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGdlbmVyYXRlQ29uZGl0aW9uYWxDbGFzc05hbWVzKG9iaik7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBvYmo7XG4gIH1cbn1cbiIsInZhciBoeXBlcmRvbSA9IHJlcXVpcmUoJy4nKTtcbnZhciBSZW5kZXIgPSByZXF1aXJlKCcuL3JlbmRlcicpO1xudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG5cbmZ1bmN0aW9uIHJlZnJlc2hPdXRPZlJlbmRlcigpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdQbGVhc2UgYXNzaWduIGh5cGVyZG9tLmh0bWwucmVmcmVzaCBkdXJpbmcgYSByZW5kZXIgY3ljbGUgaWYgeW91IHdhbnQgdG8gdXNlIGl0IGluIGV2ZW50IGhhbmRsZXJzLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZlYXR1cmlzdC9oeXBlcmRvbSNyZWZyZXNoLW91dHNpZGUtcmVuZGVyLWN5Y2xlJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obW91bnQsIGZuKSB7XG4gIHZhciByZW5kZXIgPSBuZXcgUmVuZGVyKG1vdW50KTtcblxuICB0cnkge1xuICAgIGh5cGVyZG9tLl9jdXJyZW50UmVuZGVyID0gcmVuZGVyO1xuXG4gICAgcmVuZGVyaW5nLmh0bWwuX2N1cnJlbnRSZW5kZXIgPSByZW5kZXI7XG4gICAgcmVuZGVyaW5nLmh0bWwuX3JlZnJlc2ggPSByZW5kZXJpbmcuY3JlYXRlRXZlbnRSZXN1bHRIYW5kbGVyKG1vdW50KTtcblxuICAgIGZuKCk7XG4gIH0gZmluYWxseSB7XG4gICAgcmVuZGVyLmZpbmlzaGVkLmZ1bGZpbGwoKTtcbiAgICBoeXBlcmRvbS5fY3VycmVudFJlbmRlciA9IHVuZGVmaW5lZDtcblxuICAgIHJlbmRlcmluZy5odG1sLl9yZWZyZXNoID0gcmVmcmVzaE91dE9mUmVuZGVyO1xuICAgIHJlbmRlcmluZy5odG1sLl9jdXJyZW50UmVuZGVyID0gdW5kZWZpbmVkO1xuICB9XG59O1xuIiwiaWYgKHR5cGVvZiBTZXQgPT09ICdmdW5jdGlvbicpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBTZXQ7XG59IGVsc2Uge1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuaXRlbXMgPSBbXTtcbiAgfTtcblxuICBtb2R1bGUuZXhwb3J0cy5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24od2lkZ2V0KSB7XG4gICAgaWYgKHRoaXMuaXRlbXMuaW5kZXhPZih3aWRnZXQpID09IC0xKSB7XG4gICAgICB0aGlzLml0ZW1zLnB1c2god2lkZ2V0KTtcbiAgICB9XG4gIH07XG5cbiAgbW9kdWxlLmV4cG9ydHMucHJvdG90eXBlLmRlbGV0ZSA9IGZ1bmN0aW9uKHdpZGdldCkge1xuICAgIHZhciBpID0gdGhpcy5pdGVtcy5pbmRleE9mKHdpZGdldCk7XG4gICAgaWYgKGkgIT09IC0xKSB7XG4gICAgICB0aGlzLml0ZW1zLnNwbGljZShpLCAxKTtcbiAgICB9XG4gIH07XG5cbiAgbW9kdWxlLmV4cG9ydHMucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbihmbikge1xuICAgIGZvcih2YXIgbiA9IDA7IG4gPCB0aGlzLml0ZW1zLmxlbmd0aDsgbisrKSB7XG4gICAgICBmbih0aGlzLml0ZW1zW25dKTtcbiAgICB9XG4gIH07XG59XG4iLCJmdW5jdGlvbiBTaW1wbGVQcm9taXNlICgpIHtcbiAgdGhpcy5saXN0ZW5lcnMgPSBbXTtcbn1cblxuU2ltcGxlUHJvbWlzZS5wcm90b3R5cGUuZnVsZmlsbCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICBpZiAoIXRoaXMuaXNGdWxmaWxsZWQpIHtcbiAgICB0aGlzLmlzRnVsZmlsbGVkID0gdHJ1ZTtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5saXN0ZW5lcnMuZm9yRWFjaChmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgIGxpc3RlbmVyKCk7XG4gICAgfSk7XG4gIH1cbn07XG5cblNpbXBsZVByb21pc2UucHJvdG90eXBlLnRoZW4gPSBmdW5jdGlvbiAoc3VjY2Vzcykge1xuICBpZiAodGhpcy5pc0Z1bGZpbGxlZCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHN1Y2Nlc3Moc2VsZi52YWx1ZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5saXN0ZW5lcnMucHVzaChzdWNjZXNzKTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBuZXcgU2ltcGxlUHJvbWlzZSgpO1xufTtcbiIsInZhciB2dGV4dCA9IHJlcXVpcmUoXCJ2aXJ0dWFsLWRvbS92bm9kZS92dGV4dC5qc1wiKVxudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG52YXIgaXNWZG9tID0gcmVxdWlyZSgnLi9pc1Zkb20nKTtcblxuZnVuY3Rpb24gdG9WZG9tKG9iamVjdCkge1xuICBpZiAob2JqZWN0ID09PSB1bmRlZmluZWQgfHwgb2JqZWN0ID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG5ldyB2dGV4dCgnJyk7XG4gIH0gZWxzZSBpZiAodHlwZW9mKG9iamVjdCkgIT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gbmV3IHZ0ZXh0KFN0cmluZyhvYmplY3QpKTtcbiAgfSBlbHNlIGlmIChvYmplY3QgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIG5ldyB2dGV4dChTdHJpbmcob2JqZWN0KSk7XG4gIH0gZWxzZSBpZiAob2JqZWN0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICByZXR1cm4gbmV3IHZ0ZXh0KG9iamVjdC50b1N0cmluZygpKTtcbiAgfSBlbHNlIGlmIChpc1Zkb20ob2JqZWN0KSkge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9iamVjdC5yZW5kZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gbmV3IHJlbmRlcmluZy5WaWV3TW9kZWwob2JqZWN0KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbmV3IHZ0ZXh0KEpTT04uc3RyaW5naWZ5KG9iamVjdCkpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdG9WZG9tO1xuXG5mdW5jdGlvbiBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGQpIHtcbiAgaWYgKGNoaWxkIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICBmb3IgKHZhciBuID0gMDsgbiA8IGNoaWxkLmxlbmd0aDsgbisrKSB7XG4gICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGRbbl0pO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjaGlsZHJlbi5wdXNoKHRvVmRvbShjaGlsZCkpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzLnJlY3Vyc2l2ZSA9IGZ1bmN0aW9uIChjaGlsZCkge1xuICB2YXIgY2hpbGRyZW4gPSBbXTtcbiAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkKTtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFZOb2RlID0gcmVxdWlyZSgndmlydHVhbC1kb20vdm5vZGUvdm5vZGUuanMnKTtcbnZhciBpc0hvb2sgPSByZXF1aXJlKCd2aXJ0dWFsLWRvbS92bm9kZS9pcy12aG9vaycpO1xuXG52YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKCd2aXJ0dWFsLWRvbS92aXJ0dWFsLWh5cGVyc2NyaXB0L2hvb2tzL3NvZnQtc2V0LWhvb2suanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBoO1xuXG5mdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BzLCBjaGlsZHJlbikge1xuICB2YXIgdGFnID0gdGFnTmFtZTtcblxuICAvLyBzdXBwb3J0IGtleXNcbiAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgIHZhciBrZXkgPSBwcm9wcy5rZXk7XG4gICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCduYW1lc3BhY2UnKSkge1xuICAgIHZhciBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gZml4IGN1cnNvciBidWdcbiAgaWYgKHRhZy50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnICYmXG4gICAgIW5hbWVzcGFjZSAmJlxuICAgIHByb3BzLmhhc093blByb3BlcnR5KCd2YWx1ZScpICYmXG4gICAgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJlxuICAgICFpc0hvb2socHJvcHMudmFsdWUpXG4gICkge1xuICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpO1xufVxuIiwidmFyIGRvbUNvbXBvbmVudCA9IHJlcXVpcmUoJy4vZG9tQ29tcG9uZW50Jyk7XG52YXIgaHlwZXJkb21NZXRhID0gcmVxdWlyZSgnLi9tZXRhJyk7XG52YXIgaHlwZXJkb20gPSByZXF1aXJlKCcuJyk7XG5cbmZ1bmN0aW9uIFZpZXdNb2RlbChtb2RlbCkge1xuICB2YXIgY3VycmVudFJlbmRlciA9IGh5cGVyZG9tLmN1cnJlbnRSZW5kZXIoKTtcblxuICB0aGlzLmN1cnJlbnRSZW5kZXIgPSBjdXJyZW50UmVuZGVyO1xuICB0aGlzLm1vZGVsID0gbW9kZWw7XG4gIHRoaXMua2V5ID0gbW9kZWwucmVuZGVyS2V5O1xuICB0aGlzLmNvbXBvbmVudCA9IHVuZGVmaW5lZDtcbiAgdGhpcy5tb3VudCA9IGN1cnJlbnRSZW5kZXIubW91bnQ7XG59XG5cblZpZXdNb2RlbC5wcm90b3R5cGUudHlwZSA9ICdXaWRnZXQnO1xuXG5WaWV3TW9kZWwucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICB2YXIgdmRvbSA9IHRoaXMucmVuZGVyKCk7XG5cbiAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEodGhpcy5tb2RlbCk7XG4gIG1ldGEud2lkZ2V0cy5hZGQodGhpcyk7XG5cbiAgdGhpcy5jb21wb25lbnQgPSBkb21Db21wb25lbnQoKTtcbiAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC5jcmVhdGUodmRvbSk7XG5cbiAgaWYgKHNlbGYubW9kZWwub25hZGQpIHtcbiAgICB0aGlzLmN1cnJlbnRSZW5kZXIuZmluaXNoZWQudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLm1vZGVsLm9uYWRkKGVsZW1lbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKHNlbGYubW9kZWwuZGV0YWNoZWQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG59O1xuXG5WaWV3TW9kZWwucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChwcmV2aW91cykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYgKHNlbGYubW9kZWwub251cGRhdGUpIHtcbiAgICB0aGlzLmN1cnJlbnRSZW5kZXIuZmluaXNoZWQudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLm1vZGVsLm9udXBkYXRlKHNlbGYuY29tcG9uZW50LmVsZW1lbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgdGhpcy5jb21wb25lbnQgPSBwcmV2aW91cy5jb21wb25lbnQ7XG5cbiAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC51cGRhdGUodGhpcy5yZW5kZXIoKSk7XG5cbiAgaWYgKHNlbGYubW9kZWwuZGV0YWNoZWQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG59O1xuXG5WaWV3TW9kZWwucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMubW91bnQucmVuZGVyVmlld01vZGVsKHRoaXMubW9kZWwpO1xufTtcblxuVmlld01vZGVsLnByb3RvdHlwZS5yZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5jb21wb25lbnQudXBkYXRlKHRoaXMucmVuZGVyKCkpO1xuICBpZiAodGhpcy5tb2RlbC5vbnVwZGF0ZSkge1xuICAgIHRoaXMubW9kZWwub251cGRhdGUodGhpcy5jb21wb25lbnQuZWxlbWVudCk7XG4gIH1cbn07XG5cblZpZXdNb2RlbC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICB2YXIgbWV0YSA9IGh5cGVyZG9tTWV0YSh0aGlzLm1vZGVsKTtcbiAgbWV0YS53aWRnZXRzLmRlbGV0ZSh0aGlzKTtcblxuICBpZiAoc2VsZi5tb2RlbC5vbnJlbW92ZSkge1xuICAgIHRoaXMuY3VycmVudFJlbmRlci5maW5pc2hlZC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYubW9kZWwub25yZW1vdmUoZWxlbWVudCk7XG4gICAgfSk7XG4gIH1cblxuICB0aGlzLmNvbXBvbmVudC5kZXN0cm95KCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFZpZXdNb2RlbDtcbiIsInZhciBkb21Db21wb25lbnQgPSByZXF1aXJlKCcuL2RvbUNvbXBvbmVudCcpO1xudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG52YXIgVlRleHQgPSByZXF1aXJlKFwidmlydHVhbC1kb20vdm5vZGUvdnRleHQuanNcIilcblxuZnVuY3Rpb24gV2luZG93V2lkZ2V0KGF0dHJpYnV0ZXMpIHtcbiAgdGhpcy5hdHRyaWJ1dGVzID0gYXR0cmlidXRlcztcbiAgdGhpcy52ZG9tID0gbmV3IFZUZXh0KCcnKTtcbiAgdGhpcy5jb21wb25lbnQgPSBkb21Db21wb25lbnQoKTtcblxuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHRoaXMuY2FjaGUgPSB7fTtcbiAgT2JqZWN0LmtleXModGhpcy5hdHRyaWJ1dGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICBzZWxmLmNhY2hlW2tleV0gPSByZW5kZXJpbmcuaHRtbC5yZWZyZXNoaWZ5KHNlbGYuYXR0cmlidXRlc1trZXldKTtcbiAgfSk7XG59XG5cbldpbmRvd1dpZGdldC5wcm90b3R5cGUudHlwZSA9ICdXaWRnZXQnO1xuXG5XaW5kb3dXaWRnZXQucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gIGFwcGx5UHJvcGVydHlEaWZmcyh3aW5kb3csIHt9LCB0aGlzLmF0dHJpYnV0ZXMsIHt9LCB0aGlzLmNhY2hlKTtcbiAgcmV0dXJuIHRoaXMuZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKTtcbn07XG5cbmZ1bmN0aW9uIHVuaXEoYXJyYXkpIHtcbiAgdmFyIHNvcnRlZEFycmF5ID0gYXJyYXkuc2xpY2UoKTtcbiAgc29ydGVkQXJyYXkuc29ydCgpO1xuXG4gIHZhciBsYXN0O1xuXG4gIGZvcih2YXIgbiA9IDA7IG4gPCBzb3J0ZWRBcnJheS5sZW5ndGg7KSB7XG4gICAgdmFyIGN1cnJlbnQgPSBzb3J0ZWRBcnJheVtuXTtcblxuICAgIGlmIChsYXN0ID09PSBjdXJyZW50KSB7XG4gICAgICBzb3J0ZWRBcnJheS5zcGxpY2UobiwgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG4rKztcbiAgICB9XG4gICAgbGFzdCA9IGN1cnJlbnQ7XG4gIH1cblxuICByZXR1cm4gc29ydGVkQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGFwcGx5UHJvcGVydHlEaWZmcyhlbGVtZW50LCBwcmV2aW91cywgY3VycmVudCwgcHJldmlvdXNDYWNoZSwgY3VycmVudENhY2hlKSB7XG4gIHVuaXEoT2JqZWN0LmtleXMocHJldmlvdXMpLmNvbmNhdChPYmplY3Qua2V5cyhjdXJyZW50KSkpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIGlmICgvXm9uLy50ZXN0KGtleSkpIHtcbiAgICAgIHZhciBldmVudCA9IGtleS5zbGljZSgyKTtcblxuICAgICAgdmFyIHByZXYgPSBwcmV2aW91c1trZXldO1xuICAgICAgdmFyIGN1cnIgPSBjdXJyZW50W2tleV07XG4gICAgICB2YXIgcmVmcmVzaFByZXYgPSBwcmV2aW91c0NhY2hlW2tleV07XG4gICAgICB2YXIgcmVmcmVzaEN1cnIgPSBjdXJyZW50Q2FjaGVba2V5XTtcblxuICAgICAgaWYgKHByZXYgIT09IHVuZGVmaW5lZCAmJiBjdXJyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCByZWZyZXNoUHJldik7XG4gICAgICB9IGVsc2UgaWYgKHByZXYgIT09IHVuZGVmaW5lZCAmJiBjdXJyICE9PSB1bmRlZmluZWQgJiYgcHJldiAhPT0gY3Vycikge1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIHJlZnJlc2hQcmV2KTtcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCByZWZyZXNoQ3Vycik7XG4gICAgICB9IGVsc2UgaWYgKHByZXYgPT09IHVuZGVmaW5lZCAmJiBjdXJyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCByZWZyZXNoQ3Vycik7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuV2luZG93V2lkZ2V0LnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAocHJldmlvdXMpIHtcbiAgYXBwbHlQcm9wZXJ0eURpZmZzKHdpbmRvdywgcHJldmlvdXMuYXR0cmlidXRlcywgdGhpcy5hdHRyaWJ1dGVzLCBwcmV2aW91cy5jYWNoZSwgdGhpcy5jYWNoZSk7XG4gIHRoaXMuY29tcG9uZW50ID0gcHJldmlvdXMuY29tcG9uZW50O1xuICByZXR1cm4gdGhpcy5lbGVtZW50O1xufTtcblxuV2luZG93V2lkZ2V0LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICBhcHBseVByb3BlcnR5RGlmZnMod2luZG93LCB0aGlzLmF0dHJpYnV0ZXMsIHt9LCB0aGlzLmNhY2hlLCB7fSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhdHRyaWJ1dGVzKSB7XG4gIHJldHVybiBuZXcgV2luZG93V2lkZ2V0KGF0dHJpYnV0ZXMpO1xufTtcbiIsImlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0Jykge1xuICBjb25zb2xlLmxvZygnXFxuXFxuY3JlYXRlZCB3aXRoIFxcdUQ4M0RcXHVERTgwIHVzaW5nIGh0dHBzOi8vZ2l0aHViLmNvbS9mZWF0dXJpc3QvaHlwZXJkb21cXG5cXG5cXG4nKTtcbn1cblxudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG52YXIgZGVwcmVjYXRpb25zID0gcmVxdWlyZSgnLi9kZXByZWNhdGlvbnMnKTtcblxuZXhwb3J0cy5odG1sID0gcmVuZGVyaW5nLmh0bWw7XG5leHBvcnRzLmpzeCA9IHJlbmRlcmluZy5qc3g7XG5leHBvcnRzLmF0dGFjaCA9IHJlbmRlcmluZy5hdHRhY2g7XG5leHBvcnRzLnJlcGxhY2UgPSByZW5kZXJpbmcucmVwbGFjZTtcbmV4cG9ydHMuYXBwZW5kID0gcmVuZGVyaW5nLmFwcGVuZDtcbmV4cG9ydHMuYXBwZW5kVkRvbSA9IHJlbmRlcmluZy5hcHBlbmRWRG9tO1xuZXhwb3J0cy5tZXJnZSA9IHJlbmRlcmluZy5tZXJnZTtcbmV4cG9ydHMuYmluZGluZyA9IHJlbmRlcmluZy5iaW5kaW5nO1xuZXhwb3J0cy5tZXRhID0gcmVuZGVyaW5nLmh0bWwubWV0YTtcbmV4cG9ydHMucmVmcmVzaGlmeSA9IHJlbmRlcmluZy5odG1sLnJlZnJlc2hpZnk7XG5leHBvcnRzLm5vcmVmcmVzaCA9IHJlbmRlcmluZy5odG1sLm5vcmVmcmVzaDtcblxudmFyIHdpbmRvd0V2ZW50cyA9IHJlcXVpcmUoJy4vd2luZG93RXZlbnRzJyk7XG5cbmV4cG9ydHMuaHRtbC53aW5kb3cgPSBmdW5jdGlvbiAoYXR0cmlidXRlcykge1xuICBkZXByZWNhdGlvbnMud2luZG93KCdoeXBlcmRvbS53aW5kb3cgaXMgZGVwcmVjYXRlZCcpO1xuICByZXR1cm4gd2luZG93RXZlbnRzKGF0dHJpYnV0ZXMpO1xufTtcblxuZXhwb3J0cy5odG1sLmNvbXBvbmVudCA9IHJlcXVpcmUoJy4vY29tcG9uZW50Jyk7XG5cbmV4cG9ydHMuY3VycmVudFJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGV4cG9ydHMuX2N1cnJlbnRSZW5kZXI7XG59O1xuIl19 | |
var hyperdom = require('hyperdom') | |
var h = hyperdom.html | |
class App { | |
render() { | |
return h('.container', | |
h('#example', | |
h('div.foo div', h('input[type=submit]')) | |
), | |
h.component({ | |
onadd: function(pre) { | |
pre.innerText = document.querySelector('#example').innerHTML | |
} | |
}, h('pre')) | |
) | |
} | |
} | |
hyperdom.append(document.body, new App()) | |
;}, 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": { | |
"hyperdom": "0.2.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
<!-- contents of this file will be placed inside the <body> --> |
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