made with requirebin
Created
July 23, 2017 03:24
-
-
Save BinaryMuse/270f137a6ecc28aaf0832337b7036b57 to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const etch = require('etch') | |
function toHTMLElement(vdom) { | |
const component = { | |
update() { /* noop */ }, | |
render () { return vdom } | |
} | |
etch.initialize(component) | |
return component.element | |
} | |
const domElement = toHTMLElement(etch.dom.div(null, etch.dom.span(null, 'Hello!'))) | |
document.body.appendChild(domElement) |
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){ | |
const render = require('./render') | |
const patch = require('./patch') | |
const {getScheduler} = require('./scheduler-assignment') | |
const componentsWithPendingUpdates = new WeakSet() | |
let syncUpdatesInProgressCounter = 0 | |
let syncDestructionsInProgressCounter = 0 | |
function isValidVirtualNode (virtualNode) { | |
return virtualNode != null && virtualNode !== false | |
} | |
// This function associates a component object with a DOM element by calling | |
// the components `render` method, assigning an `.element` property on the | |
// object and also returning the element. | |
// | |
// It also assigns a `virtualNode` property based on the return value of the | |
// `render` method. This will be used later by `performElementUpdate` to diff | |
// the new results of `render` with the previous results when updating the | |
// component's element. | |
// | |
// Finally, this function also associates the component with a `refs` object, | |
// which is populated with references to elements based on `ref` properties on | |
// nodes of the `virtual-dom` tree. Before calling into `virtual-dom` to create | |
// the DOM tree, it pushes this `refs` object to a shared stack so it can be | |
// accessed by hooks during the creation of individual elements. | |
function initialize(component) { | |
if (typeof component.update !== 'function') { | |
throw new Error('Etch components must implement `update(props, children)`.') | |
} | |
let virtualNode = component.render() | |
if (!isValidVirtualNode(virtualNode)) { | |
let namePart = component.constructor && component.constructor.name ? ' in ' + component.constructor.name : '' | |
throw new Error('invalid falsy value ' + virtualNode + ' returned from render()' + namePart) | |
} | |
component.refs = {} | |
component.virtualNode = virtualNode | |
component.element = render(component.virtualNode, { | |
refs: component.refs, listenerContext: component | |
}) | |
} | |
// This function receives a component that has already been associated with an | |
// element via a previous call to `initialize` and updates this element by | |
// calling `render` on the component. | |
// | |
// When called in normal circumstances, it uses the scheduler to defer this | |
// update until the next animation frame, and will only perform one update of a | |
// given component in a given frame. This means you can call `update` | |
// repeatedly in a given tick without causing redundant updates. | |
// | |
// If this function called during another synchronous update (for example, as a | |
// result of a call to `update` on a child component), the update is performed | |
// synchronously. | |
// | |
// Returns a promise that will resolve when the requested update has been | |
// completed. | |
function update (component, replaceNode=true) { | |
if (syncUpdatesInProgressCounter > 0) { | |
updateSync(component, replaceNode) | |
return Promise.resolve() | |
} | |
let scheduler = getScheduler() | |
if (!componentsWithPendingUpdates.has(component)) { | |
componentsWithPendingUpdates.add(component) | |
scheduler.updateDocument(function () { | |
componentsWithPendingUpdates.delete(component) | |
updateSync(component, replaceNode) | |
}) | |
} | |
return scheduler.getNextUpdatePromise() | |
} | |
// Synchronsly updates the DOM element associated with a component object. . | |
// This method assumes the presence of `.element` and `.virtualNode` | |
// properties on the component, which are assigned in the `initialize` | |
// function. | |
// | |
// It calls `render` on the component to obtain the desired state of the DOM, | |
// then `diff`s it with the previous state and `patch`es the element based on | |
// the resulting diff. During the patch operation, it pushes the component's | |
// `refs` object to a shared stack so that references to DOM elements can be | |
// updated. | |
// | |
// If `update` is called during the invocation of `updateSync`, | |
// the requests are processed synchronously as well. We track whether this is | |
// the case by incrementing and decrementing `syncUpdatesInProgressCounter` | |
// around the call. | |
// | |
// For now, etch does not allow the root tag of the `render` method to change | |
// between invocations, because we want to preserve a one-to-one relationship | |
// between component objects and DOM elements for simplicity. | |
function updateSync (component, replaceNode=true) { | |
let newVirtualNode = component.render() | |
if (!isValidVirtualNode(newVirtualNode)) { | |
let namePart = component.constructor && component.constructor.name ? ' in ' + component.constructor.name : '' | |
throw new Error('invalid falsy value ' + newVirtualNode + ' returned from render()' + namePart) | |
} | |
syncUpdatesInProgressCounter++ | |
let oldVirtualNode = component.virtualNode | |
let oldDomNode = component.element | |
let newDomNode = patch(oldVirtualNode, newVirtualNode, { | |
refs: component.refs, | |
listenerContext: component | |
}) | |
component.virtualNode = newVirtualNode | |
if (newDomNode !== oldDomNode && !replaceNode) { | |
throw new Error('The root node type changed on update, but the update was performed with the replaceNode option set to false') | |
} else { | |
component.element = newDomNode | |
} | |
// We can safely perform additional writes after a DOM update synchronously, | |
// but any reads need to be deferred until all writes are completed to avoid | |
// DOM thrashing. Requested reads occur at the end of the the current frame | |
// if this method was invoked via the scheduler. Otherwise, if `updateSync` | |
// was invoked outside of the scheduler, the default scheduler will defer | |
// reads until the next animation frame. | |
if (typeof component.writeAfterUpdate === 'function') { | |
component.writeAfterUpdate() | |
} | |
if (typeof component.readAfterUpdate === 'function') { | |
getScheduler().readDocument(function () { | |
component.readAfterUpdate() | |
}) | |
} | |
syncUpdatesInProgressCounter-- | |
} | |
// Removes the component's associated element and calls `destroy` on any child | |
// components. Normally, this function is asynchronous and will perform the | |
// destruction on the next animation frame. If called as the result of another | |
// update or destruction, it calls `destroy` on child components synchronously. | |
// If called as the result of destroying a component higher in the DOM, the | |
// element is not removed to avoid redundant DOM manipulation. Returns a promise | |
// that resolves when the destruction is completed. | |
function destroy (component, removeNode=true) { | |
if (syncUpdatesInProgressCounter > 0 || syncDestructionsInProgressCounter > 0) { | |
destroySync(component, removeNode) | |
return Promise.resolve() | |
} | |
let scheduler = getScheduler() | |
scheduler.updateDocument(function () { | |
destroySync(component, removeNode) | |
}) | |
return scheduler.getNextUpdatePromise() | |
} | |
// A synchronous version of `destroy`. | |
// | |
// Note that we track whether `destroy` calls are in progress and only remove | |
// the element if we are not a nested call. | |
function destroySync (component, removeNode=true) { | |
syncDestructionsInProgressCounter++ | |
destroyChildComponents(component.virtualNode) | |
if (syncDestructionsInProgressCounter === 1 && removeNode) component.element.remove() | |
syncDestructionsInProgressCounter-- | |
} | |
function destroyChildComponents(virtualNode) { | |
if (virtualNode.component && typeof virtualNode.component.destroy === 'function') { | |
virtualNode.component.destroy() | |
} else if (virtualNode.children) { | |
virtualNode.children.forEach(destroyChildComponents) | |
} | |
} | |
module.exports = { | |
initialize, | |
update, updateSync, | |
destroy, destroySync | |
} | |
},{"./patch":5,"./render":6,"./scheduler-assignment":7}],2:[function(require,module,exports){ | |
// If the scheduler is not customized via `etch.setScheduler`, an instance of | |
// this class will be used to schedule updates to the document. The | |
// `updateDocument` method accepts functions to be run at some point in the | |
// future, then runs them on the next animation frame. | |
module.exports = class DefaultScheduler { | |
constructor () { | |
this.updateRequests = [] | |
this.readRequests = [] | |
this.pendingAnimationFrame = null | |
this.performUpdates = this.performUpdates.bind(this) | |
this.performingUpdates = false | |
} | |
// Enqueues functions that write to the DOM to be performed on the next | |
// animation frame. Functions passed to this method should *never* read from | |
// the DOM, because that could cause synchronous reflows. | |
updateDocument (fn) { | |
this.updateRequests.push(fn) | |
if (!this.pendingAnimationFrame) { | |
this.pendingAnimationFrame = window.requestAnimationFrame(this.performUpdates) | |
} | |
} | |
readDocument (fn) { | |
this.readRequests.push(fn) | |
if (!this.pendingAnimationFrame) { | |
this.pendingAnimationFrame = window.requestAnimationFrame(this.performUpdates) | |
} | |
} | |
// Returns a promise that will resolve at the end of the next update cycle, | |
// after all the functions passed to `updateDocument` and `updateDocumentSync` | |
// have been run. | |
getNextUpdatePromise () { | |
if (!this.nextUpdatePromise) { | |
this.nextUpdatePromise = new Promise(resolve => { | |
this.resolveNextUpdatePromise = resolve | |
}) | |
} | |
return this.nextUpdatePromise | |
} | |
// Performs all the pending document updates. If running these update | |
// functions causes *more* updates to be enqueued, they are run synchronously | |
// in this update cycle without waiting for another frame. | |
performUpdates () { | |
while (this.updateRequests.length > 0) { | |
this.updateRequests.shift()() | |
} | |
// We don't clear the pending frame until all update requests are processed. | |
// This ensures updates requested within other updates are processed in the | |
// current frame. | |
this.pendingAnimationFrame = null | |
// Now that updates are processed, we can perform all pending document reads | |
// without the risk of interleaving them with writes and causing layout | |
// thrashing. | |
while (this.readRequests.length > 0) { | |
this.readRequests.shift()() | |
} | |
if (this.nextUpdatePromise) { | |
let resolveNextUpdatePromise = this.resolveNextUpdatePromise | |
this.nextUpdatePromise = null | |
this.resolveNextUpdatePromise = null | |
resolveNextUpdatePromise() | |
} | |
} | |
} | |
},{}],3:[function(require,module,exports){ | |
const EVENT_LISTENER_PROPS = require('./event-listener-props') | |
const SVG_TAGS = require('./svg-tags') | |
function dom (tag, props, ...children) { | |
for (let i = 0; i < children.length;) { | |
const child = children[i] | |
switch (typeof child) { | |
case 'string': | |
case 'number': | |
children[i] = {text: child} | |
i++ | |
break; | |
case 'object': | |
if (Array.isArray(child)) { | |
children.splice(i, 1, ...child) | |
} else if (!child) { | |
children.splice(i, 1) | |
} else { | |
i++ | |
} | |
break; | |
default: | |
throw new Error(`Invalid child node: ${child}`) | |
} | |
} | |
if (props) { | |
for (const propName in props) { | |
const eventName = EVENT_LISTENER_PROPS[propName] | |
if (eventName) { | |
if (!props.on) props.on = {} | |
props.on[eventName] = props[propName] | |
} | |
} | |
if (props.class) { | |
props.className = props.class | |
} | |
} | |
return {tag, props, children} | |
} | |
const HTML_TAGS = [ | |
'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', | |
'blockquote', 'body', 'button', 'canvas', 'caption', 'cite', 'code', | |
'colgroup', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', | |
'dt', 'em', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', | |
'h3', 'h4', 'h5', 'h6', 'head', 'header', 'html', 'i', 'iframe', 'ins', 'kbd', | |
'label', 'legend', 'li', 'main', 'map', 'mark', 'menu', 'meter', 'nav', | |
'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', | |
'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', | |
'select', 'small', 'span', 'strong', 'style', 'sub', 'summary', 'sup', | |
'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', | |
'tr', 'u', 'ul', 'var', 'video', 'area', 'base', 'br', 'col', 'command', | |
'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', | |
'track', 'wbr' | |
] | |
for (const tagName of HTML_TAGS) { | |
dom[tagName] = (props, ...children) => { | |
return dom(tagName, props, ...children) | |
} | |
} | |
for (const tagName of SVG_TAGS) { | |
dom[tagName] = (props, ...children) => { | |
return dom(tagName, props, ...children) | |
} | |
} | |
module.exports = dom | |
},{"./event-listener-props":4,"./svg-tags":9}],4:[function(require,module,exports){ | |
module.exports = { | |
onCopy: 'copy', | |
onCut: 'cut', | |
onPaste: 'paste', | |
onCompositionEnd: 'compositionend', | |
onCompositionStart: 'compositionstart', | |
onCompositionUpdate: 'compositionupdate', | |
onKeyDown: 'keydown', | |
onKeyPress: 'keypress', | |
onKeyUp: 'keyup', | |
onFocus: 'focus', | |
onBlur: 'blur', | |
onChange: 'change', | |
onInput: 'input', | |
onSubmit: 'submit', | |
onClick: 'click', | |
onContextMenu: 'contextmenu', | |
onDoubleClick: 'doubleclick', | |
onDrag: 'drag', | |
onDragEnd: 'dragend', | |
onDragEnter: 'dragenter', | |
onDragExit: 'dragexit', | |
onDragLeave: 'dragleave', | |
onDragOver: 'dragover', | |
onDragStart: 'dragstart', | |
onDrop: 'drop', | |
onMouseDown: 'mousedown', | |
onMouseEnter: 'mousenter', | |
onMouseLeave: 'mouseleave', | |
onMouseMove: 'mousemove', | |
onMouseOut: 'mouseout', | |
onMouseOver: 'mouseover', | |
onMouseUp: 'mouseup', | |
onSelect: 'select', | |
onTouchCancel: 'touchcancel', | |
onTouchEnd: 'touchend', | |
onTouchMove: 'touchmove', | |
onTouchStart: 'touchstart', | |
onScroll: 'scroll', | |
onWheel: 'wheel', | |
onAbort: 'abort', | |
onCanPlay: 'canplay', | |
onCanPlayThrough: 'canplaythrough', | |
onDurationChange: 'durationchange', | |
onEmptied: 'emptied', | |
onEncrypted: 'encrypted', | |
onEnded: 'ended', | |
onError: 'error', | |
onLoadedData: 'loadeddata', | |
onLoadedMetadata: 'loadedmetadat', | |
onLoadStart: 'loadstart', | |
onPause: 'pause', | |
onPlay: 'play', | |
onPlaying: 'playing', | |
onProgress: 'progress', | |
onRateChange: 'ratechange', | |
onSeeked: 'seeked', | |
onSeeking: 'seeking', | |
onStalled: 'stalled', | |
onSuspend: 'suspend', | |
onTimeUpdate: 'timeupdate', | |
onVolumeChange: 'volumechange', | |
onWaiting: 'waiting', | |
onLoad: 'load', | |
onError: 'error', | |
onAnimationStart: 'animationstart', | |
onAnimationEnd: 'animationend', | |
onAnimationIteration: 'animationiteration', | |
onTransitionEnd: 'transitionend' | |
} | |
},{}],5:[function(require,module,exports){ | |
const render = require('./render') | |
const updateProps = require('./update-props') | |
function patch (oldVirtualNode, newVirtualNode, options) { | |
const oldNode = oldVirtualNode.domNode | |
if (virtualNodesAreEqual(oldVirtualNode, newVirtualNode)) { | |
let newNode | |
if (newVirtualNode.text != null) { | |
oldNode.nodeValue = newVirtualNode.text | |
newNode = oldNode | |
} else { | |
if (typeof newVirtualNode.tag === 'function') { | |
newNode = updateComponent(oldVirtualNode, newVirtualNode, options) | |
} else { | |
updateChildren(oldNode, oldVirtualNode.children, newVirtualNode.children, options) | |
updateProps(oldNode, oldVirtualNode, newVirtualNode, options) | |
newNode = oldNode | |
} | |
} | |
newVirtualNode.domNode = newNode | |
if (newNode !== oldNode && oldNode.parentNode) { | |
oldNode.parentNode.replaceChild(newNode, oldNode) | |
} | |
return newNode | |
} else { | |
const parentNode = oldNode.parentNode | |
const nextSibling = oldNode.nextSibling | |
removeVirtualNode(oldVirtualNode, options && options.refs) | |
const newNode = render(newVirtualNode, options) | |
if (parentNode) parentNode.insertBefore(newNode, nextSibling) | |
newVirtualNode.domNode = newNode | |
return newNode | |
} | |
} | |
function updateComponent (oldVirtualNode, newVirtualNode, options) { | |
const {component, props: oldProps} = oldVirtualNode | |
let {props: newProps, children: newChildren} = newVirtualNode | |
newVirtualNode.component = component | |
if (options && options.refs) { | |
const refs = options.refs | |
const oldRefName = oldProps && oldProps.ref | |
const newRefName = newProps && newProps.ref | |
if (newRefName !== oldRefName) { | |
if (oldRefName && refs[oldRefName] === component) delete refs[oldRefName] | |
if (newRefName) refs[newRefName] = component | |
} | |
} | |
component.update(newProps || {}, newChildren) | |
return component.element | |
} | |
function updateChildren (parentElement, oldChildren, newChildren, options) { | |
let oldStartIndex = 0 | |
let oldEndIndex = oldChildren.length - 1 | |
let oldStartChild = oldChildren[0] | |
let oldEndChild = oldChildren[oldEndIndex] | |
let newStartIndex = 0 | |
let newEndIndex = newChildren.length - 1 | |
let newStartChild = newChildren[0] | |
let newEndChild = newChildren[newEndIndex] | |
let oldIndicesByKey | |
while (oldStartIndex <= oldEndIndex && newStartIndex <= newEndIndex) { | |
if (!oldStartChild) { | |
oldStartChild = oldChildren[++oldStartIndex] | |
} else if (!oldEndChild) { | |
oldEndChild = oldChildren[--oldEndIndex] | |
} else if (virtualNodesAreEqual(oldStartChild, newStartChild)) { | |
patch(oldStartChild, newStartChild, options) | |
oldStartChild = oldChildren[++oldStartIndex] | |
newStartChild = newChildren[++newStartIndex] | |
} else if (virtualNodesAreEqual(oldEndChild, newEndChild)) { | |
patch(oldEndChild, newEndChild, options) | |
oldEndChild = oldChildren[--oldEndIndex] | |
newEndChild = newChildren[--newEndIndex] | |
} else if (virtualNodesAreEqual(oldStartChild, newEndChild)) { | |
patch(oldStartChild, newEndChild, options) | |
parentElement.insertBefore(oldStartChild.domNode, oldEndChild.domNode.nextSibling) | |
oldStartChild = oldChildren[++oldStartIndex] | |
newEndChild = newChildren[--newEndIndex] | |
} else if (virtualNodesAreEqual(oldEndChild, newStartChild)) { | |
patch(oldEndChild, newStartChild, options) | |
parentElement.insertBefore(oldEndChild.domNode, oldStartChild.domNode); | |
oldEndChild = oldChildren[--oldEndIndex] | |
newStartChild = newChildren[++newStartIndex] | |
} else { | |
if (!oldIndicesByKey) oldIndicesByKey = mapOldKeysToIndices(oldChildren, oldStartIndex, oldEndIndex) | |
const key = getKey(newStartChild) | |
const oldIndex = key ? oldIndicesByKey.get(key) : null | |
if (oldIndex == null) { | |
parentElement.insertBefore(render(newStartChild, options), oldStartChild.domNode) | |
newStartChild = newChildren[++newStartIndex] | |
} else { | |
const oldChildToMove = oldChildren[oldIndex] | |
patch(oldChildToMove, newStartChild, options) | |
oldChildren[oldIndex] = undefined | |
parentElement.insertBefore(oldChildToMove.domNode, oldStartChild.domNode) | |
newStartChild = newChildren[++newStartIndex] | |
} | |
} | |
} | |
if (oldStartIndex > oldEndIndex) { | |
const subsequentElement = newChildren[newEndIndex + 1] ? newChildren[newEndIndex + 1].domNode : null | |
for (let i = newStartIndex; i <= newEndIndex; i++) { | |
parentElement.insertBefore(render(newChildren[i], options), subsequentElement) | |
} | |
} else if (newStartIndex > newEndIndex) { | |
for (let i = oldStartIndex; i <= oldEndIndex; i++) { | |
const child = oldChildren[i] | |
if (child) removeVirtualNode(child, options && options.refs) | |
} | |
} | |
} | |
function removeVirtualNode (virtualNode, refs, removeDOMNode = true) { | |
const {domNode, props, children, component} = virtualNode | |
const ref = props && props.ref | |
if (component) { | |
if (refs && ref && refs[ref] === component) delete refs[ref] | |
if (typeof component.destroy === 'function') component.destroy() | |
} else { | |
if (refs && ref && refs[ref] === domNode) delete refs[ref] | |
if (children) { | |
for (let i = 0; i < children.length; i++) { | |
removeVirtualNode(children[i], refs, false) | |
} | |
} | |
} | |
if (removeDOMNode) domNode.remove() | |
} | |
function virtualNodesAreEqual (oldVirtualNode, newVirtualNode) { | |
return ( | |
getKey(oldVirtualNode) === getKey(newVirtualNode) | |
&& oldVirtualNode.tag === newVirtualNode.tag | |
) | |
} | |
function getKey (virtualNode) { | |
return virtualNode.props ? virtualNode.props.key : undefined | |
} | |
function mapOldKeysToIndices (children, startIndex, endIndex) { | |
let oldIndicesByKey = new Map() | |
for (let i = startIndex; i <= endIndex; i++) { | |
const key = getKey(children[i]) | |
if (key) oldIndicesByKey.set(key, i) | |
} | |
return oldIndicesByKey | |
} | |
module.exports = patch | |
},{"./render":6,"./update-props":10}],6:[function(require,module,exports){ | |
const updateProps = require('./update-props') | |
const SVG_TAGS = require('./svg-tags') | |
function render (virtualNode, options) { | |
let domNode | |
if (virtualNode.text != null) { | |
domNode = document.createTextNode(virtualNode.text) | |
} else { | |
const {tag, children} = virtualNode | |
let {props} = virtualNode | |
if (typeof tag === 'function') { | |
let ref | |
if (props && props.ref) { | |
ref = props.ref | |
} | |
const component = new tag(props || {}, children) | |
virtualNode.component = component | |
domNode = component.element | |
if (options && options.refs && ref) { | |
options.refs[ref] = component | |
} | |
} else if (SVG_TAGS.has(tag)) { | |
domNode = document.createElementNS("http://www.w3.org/2000/svg", tag); | |
if (children) addChildren(domNode, children, options) | |
if (props) updateProps(domNode, null, virtualNode, options) | |
} else { | |
domNode = document.createElement(tag) | |
if (children) addChildren(domNode, children, options) | |
if (props) updateProps(domNode, null, virtualNode, options) | |
} | |
} | |
virtualNode.domNode = domNode | |
return domNode | |
} | |
function addChildren (parent, children, options) { | |
for (let i = 0; i < children.length; i++) { | |
parent.appendChild(render(children[i], options)) | |
} | |
} | |
module.exports = render | |
},{"./svg-tags":9,"./update-props":10}],7:[function(require,module,exports){ | |
// This file implements getter and setter functions for a scheduler to be used | |
// by this library when updating the DOM. The scheduler's job is to ensure that | |
// DOM interaction is performed efficiently. When using `etch` in Atom, you | |
// should tell `etch` to use Atom's scheduler by calling | |
// `setScheduler(atom.views)`. | |
// | |
// Schedulers should support the following interface: | |
// * `updateDocument(fn)` This method is asynchronous. It enqueues functions to | |
// be executed later. | |
// * `getNextUpdatePromise()` This function should return a promise that | |
// resolves after all pending document update functions have been invoked. | |
// | |
// Schedulers could support the following optional methods, which are supported | |
// by Atom's scheduler. | |
// | |
// * `readDocument` This method can be invoked by clients other than `etch` when | |
// it is necessary to read from the DOM. Functions enqueued via this method | |
// should not be run until all document update functions have been executed. | |
// Batching updates and reads in this way will prevent forced synchronous | |
// reflows. | |
// * `pollDocument` This method is similar to `readDocument`, but it runs the | |
// associated functions repeatedly. Again, they should be scheduled in such a | |
// way so as to avoid synchronous reflows. | |
const DefaultScheduler = require('./default-scheduler') | |
let scheduler = null | |
module.exports.setScheduler = function setScheduler (customScheduler) { | |
scheduler = customScheduler | |
} | |
module.exports.getScheduler = function getScheduler () { | |
if (!scheduler) { | |
scheduler = new DefaultScheduler() | |
} | |
return scheduler | |
} | |
},{"./default-scheduler":2}],8:[function(require,module,exports){ | |
// Based on https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute | |
module.exports = new Map([ | |
['accentHeight', 'accent-height'], | |
['alignmentBaseline', 'alignment-baseline'], | |
['arabicForm', 'arabic-form'], | |
['baselineShift', 'baseline-shift'], | |
['capHeight', 'cap-height'], | |
['className', 'class'], | |
['clipPath', 'clip-path'], | |
['clipRule', 'clip-rule'], | |
['colorInterpolation', 'color-interpolation'], | |
['colorInterpolationFilters', 'color-interpolation-filters'], | |
['colorProfile', 'color-profile'], | |
['colorRendering', 'color-rendering'], | |
['dominantBaseline', 'dominant-baseline'], | |
['enableBackground', 'enable-background'], | |
['fillOpacity', 'fill-opacity'], | |
['fillRule', 'fill-rule'], | |
['floodColor', 'flood-color'], | |
['floodOpacity', 'flood-opacity'], | |
['fontFamily', 'font-family'], | |
['fontSize', 'font-size'], | |
['fontSizeAdjust', 'font-size-adjust'], | |
['fontStretch', 'font-stretch'], | |
['fontStyle', 'font-style'], | |
['fontVariant', 'font-variant'], | |
['fontWeight', 'font-weight'], | |
['glyphName', 'glyph-name'], | |
['glyphOrientationHorizontal', 'glyph-orientation-horizontal'], | |
['glyphOrientationVertical', 'glyph-orientation-vertical'], | |
['horizAdvX', 'horiz-adv-x'], | |
['horizOriginX', 'horiz-origin-x'], | |
['letterSpacing', 'letter-spacing'], | |
['lightingColor', 'lighting-color'], | |
['markerEnd', 'marker-end'], | |
['markerMid', 'marker-mid'], | |
['markerStart', 'marker-start'], | |
['overlinePosition', 'overline-position'], | |
['overlineThickness', 'overline-thickness'], | |
['panose1', 'panose-1'], | |
['paintOrder', 'paint-order'], | |
['pointerEvents', 'pointer-events'], | |
['renderingIntent', 'rendering-intent'], | |
['shapeRendering', 'shape-rendering'], | |
['stopColor', 'stop-color'], | |
['stopOpacity', 'stop-opacity'], | |
['strikethroughPosition', 'strikethrough-position'], | |
['strikethroughThickness', 'strikethrough-thickness'], | |
['strokeDasharray', 'stroke-dasharray'], | |
['strokeDashoffset', 'stroke-dashoffset'], | |
['strokeLinecap', 'stroke-linecap'], | |
['strokeLinejoin', 'stroke-linejoin'], | |
['strokeMiterlimit', 'stroke-miterlimit'], | |
['strokeOpacity', 'stroke-opacity'], | |
['strokeWidth', 'stroke-width'], | |
['textAnchor', 'text-anchor'], | |
['textDecoration', 'text-decoration'], | |
['textRendering', 'text-rendering'], | |
['underlinePosition', 'underline-position'], | |
['underlineThickness', 'underline-thickness'], | |
['unicodeBidi', 'unicode-bidi'], | |
['unicodeRange', 'unicode-range'], | |
['unitsPerEm', 'units-per-em'], | |
['vAlphabetic', 'v-alphabetic'], | |
['vHanging', 'v-hanging'], | |
['vIdeographic', 'v-ideographic'], | |
['vMathematical', 'v-mathematical'], | |
['vertAdvY', 'vert-adv-y'], | |
['vertOriginX', 'vert-origin-x'], | |
['vertOriginY', 'vert-origin-y'], | |
['wordSpacing', 'word-spacing'], | |
['writingMode', 'writing-mode'], | |
['xHeight', 'x-height'], | |
]) | |
},{}],9:[function(require,module,exports){ | |
// taken from https://github.com/facebook/react/blob/67f8524e88abbf1ac0fd86d38a0477d11fbc7b3e/src/isomorphic/classic/element/ReactDOMFactories.js#L153 | |
module.exports = new Set([ | |
'circle', | |
'clipPath', | |
'defs', | |
'ellipse', | |
'g', | |
'image', | |
'line', | |
'linearGradient', | |
'mask', | |
'path', | |
'pattern', | |
'polygon', | |
'polyline', | |
'radialGradient', | |
'rect', | |
'stop', | |
'svg', | |
'text', | |
'tspan' | |
]) | |
},{}],10:[function(require,module,exports){ | |
const EVENT_LISTENER_PROPS = require('./event-listener-props') | |
const SVG_TAGS = require('./svg-tags') | |
const SVG_ATTRIBUTE_TRANSLATIONS = require('./svg-attribute-translations') | |
const EMPTY = '' | |
module.exports = function (domNode, oldVirtualNode, newVirtualNode, options) { | |
const oldProps = oldVirtualNode && oldVirtualNode.props | |
const newProps = newVirtualNode.props | |
let refs, listenerContext | |
if (options) { | |
refs = options.refs | |
listenerContext = options.listenerContext | |
} | |
updateProps(domNode, oldVirtualNode, oldProps, newVirtualNode, newProps) | |
if (refs) updateRef(domNode, oldProps && oldProps.ref, newProps && newProps.ref, refs) | |
updateEventListeners(domNode, oldVirtualNode, newVirtualNode, listenerContext) | |
} | |
function updateProps (domNode, oldVirtualNode, oldProps, newVirtualNode, newProps) { | |
if (oldProps) { | |
const oldPropsNames = Object.keys(oldProps) | |
for (let i = 0; i < oldPropsNames.length; i++) { | |
const name = oldPropsNames[i] | |
if (name === 'ref' || name === 'on') continue | |
if (name in EVENT_LISTENER_PROPS) continue | |
if (!newProps || !(name in newProps)) { | |
if (name === 'dataset') { | |
updateProps(domNode.dataset, null, oldProps && oldProps.dataset, null, null) | |
} else if (name !== 'innerHTML' && oldVirtualNode && SVG_TAGS.has(oldVirtualNode.tag)) { | |
domNode.removeAttribute(SVG_ATTRIBUTE_TRANSLATIONS.get(name) || name) | |
} else { | |
// Clear property for objects that don't support deletion (e.g. style | |
// or className). If we used null instead of an empty string, the DOM | |
// could sometimes stringify the value and mistakenly assign 'null'. | |
domNode[name] = EMPTY | |
delete domNode[name] | |
} | |
} | |
} | |
} | |
if (newProps) { | |
const newPropsNames = Object.keys(newProps) | |
for (let i = 0; i < newPropsNames.length; i++) { | |
const name = newPropsNames[i] | |
if (name === 'ref' || name === 'on') continue | |
if (name in EVENT_LISTENER_PROPS) continue | |
const oldValue = oldProps && oldProps[name] | |
const newValue = newProps[name] | |
if (name === 'dataset') { | |
updateNestedProps(domNode.dataset, oldValue, newValue, false) | |
} else if (name === 'style' && typeof newValue !== 'string') { | |
let oldProps = oldValue | |
if (typeof oldProps === 'string') { | |
domNode.style = '' | |
oldProps = null | |
} | |
updateNestedProps(domNode.style, oldProps, newValue, true) | |
} else if (name === 'attributes') { | |
updateAttributes(domNode, oldValue, newValue) | |
} else { | |
if (newValue !== oldValue) { | |
if (name !== 'innerHTML' && newVirtualNode && SVG_TAGS.has(newVirtualNode.tag)) { | |
domNode.setAttribute(SVG_ATTRIBUTE_TRANSLATIONS.get(name) || name, newValue) | |
} else { | |
domNode[name] = newValue | |
} | |
} | |
} | |
} | |
} | |
} | |
function updateNestedProps (domProps, oldProps, newProps, isStyleObject) { | |
if (oldProps) { | |
const oldPropsNames = Object.keys(oldProps) | |
for (let i = 0; i < oldPropsNames.length; i++) { | |
const name = oldPropsNames[i] | |
if (!newProps || !(name in newProps)) { | |
if (isStyleObject) { | |
domProps[name] = EMPTY | |
} else { | |
delete domProps[name] | |
} | |
} | |
} | |
} | |
if (newProps) { | |
const newPropsNames = Object.keys(newProps) | |
for (let i = 0; i < newPropsNames.length; i++) { | |
const name = newPropsNames[i] | |
const oldValue = oldProps && oldProps[name] | |
const newValue = newProps[name] | |
if (newValue !== oldValue) { | |
domProps[name] = newValue | |
} | |
} | |
} | |
} | |
function updateAttributes (domNode, oldAttributes, newAttributes) { | |
if (oldAttributes) { | |
const oldAttributeNames = Object.keys(oldAttributes) | |
for (let i = 0; i < oldAttributeNames.length; i++) { | |
const name = oldAttributeNames[i] | |
if (!newAttributes || !(name in newAttributes)) { | |
domNode.removeAttribute(name) | |
} | |
} | |
} | |
if (newAttributes) { | |
const newAttributeNames = Object.keys(newAttributes) | |
for (let i = 0; i < newAttributeNames.length; i++) { | |
const name = newAttributeNames[i] | |
const oldValue = oldAttributes && oldAttributes[name] | |
const newValue = newAttributes[name] | |
if (newValue !== oldValue) { | |
domNode.setAttribute(name, newValue) | |
} | |
} | |
} | |
} | |
function updateRef (domNode, oldRefName, newRefName, refs) { | |
if (newRefName !== oldRefName) { | |
if (oldRefName && refs[oldRefName] === domNode) delete refs[oldRefName] | |
if (newRefName) refs[newRefName] = domNode | |
} | |
} | |
function updateEventListeners (domNode, oldVirtualNode, newVirtualNode, listenerContext) { | |
const oldListeners = oldVirtualNode && oldVirtualNode.props && oldVirtualNode.props.on | |
const newListeners = newVirtualNode.props && newVirtualNode.props.on | |
for (const eventName in oldListeners) { | |
if (!(newListeners && eventName in newListeners)) { | |
let listenerToRemove | |
if (oldVirtualNode && oldVirtualNode.boundListeners && oldVirtualNode.boundListeners[eventName]) { | |
listenerToRemove = oldVirtualNode.boundListeners[eventName] | |
} else { | |
listenerToRemove =oldListeners[eventName] | |
} | |
domNode.removeEventListener(eventName, listenerToRemove) | |
} | |
} | |
for (const eventName in newListeners) { | |
const oldListener = oldListeners && oldListeners[eventName] | |
const newListener = newListeners[eventName] | |
if (newListener !== oldListener) { | |
if (oldListener) { | |
let listenerToRemove | |
if (oldVirtualNode && oldVirtualNode.boundListeners && oldVirtualNode.boundListeners[eventName]) { | |
listenerToRemove = oldVirtualNode.boundListeners[eventName] | |
} else { | |
listenerToRemove = oldListener | |
} | |
domNode.removeEventListener(eventName, listenerToRemove) | |
} | |
let listenerToAdd | |
if (listenerContext) { | |
listenerToAdd = newListener.bind(listenerContext) | |
if (!newVirtualNode.boundListeners) newVirtualNode.boundListeners = {} | |
newVirtualNode.boundListeners[eventName] = listenerToAdd | |
} else { | |
listenerToAdd = newListener | |
} | |
domNode.addEventListener(eventName, listenerToAdd) | |
} | |
} | |
} | |
},{"./event-listener-props":4,"./svg-attribute-translations":8,"./svg-tags":9}],"etch":[function(require,module,exports){ | |
const dom = require('./dom') | |
const render = require('./render') | |
const {initialize, update, updateSync, destroy, destroySync} = require('./component-helpers') | |
const {setScheduler, getScheduler} = require('./scheduler-assignment') | |
module.exports = { | |
dom, render, | |
initialize, update, updateSync, destroy, destroySync, | |
setScheduler, getScheduler | |
} | |
},{"./component-helpers":1,"./dom":3,"./render":6,"./scheduler-assignment":7}]},{},[]) | |
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImxpYi9jb21wb25lbnQtaGVscGVycy5qcyIsImxpYi9kZWZhdWx0LXNjaGVkdWxlci5qcyIsImxpYi9kb20uanMiLCJsaWIvZXZlbnQtbGlzdGVuZXItcHJvcHMuanMiLCJsaWIvcGF0Y2guanMiLCJsaWIvcmVuZGVyLmpzIiwibGliL3NjaGVkdWxlci1hc3NpZ25tZW50LmpzIiwibGliL3N2Zy1hdHRyaWJ1dGUtdHJhbnNsYXRpb25zLmpzIiwibGliL3N2Zy10YWdzLmpzIiwibGliL3VwZGF0ZS1wcm9wcy5qcyIsImV0Y2giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsImNvbnN0IHJlbmRlciA9IHJlcXVpcmUoJy4vcmVuZGVyJylcbmNvbnN0IHBhdGNoID0gcmVxdWlyZSgnLi9wYXRjaCcpXG5jb25zdCB7Z2V0U2NoZWR1bGVyfSA9IHJlcXVpcmUoJy4vc2NoZWR1bGVyLWFzc2lnbm1lbnQnKVxuXG5jb25zdCBjb21wb25lbnRzV2l0aFBlbmRpbmdVcGRhdGVzID0gbmV3IFdlYWtTZXQoKVxubGV0IHN5bmNVcGRhdGVzSW5Qcm9ncmVzc0NvdW50ZXIgPSAwXG5sZXQgc3luY0Rlc3RydWN0aW9uc0luUHJvZ3Jlc3NDb3VudGVyID0gMFxuXG5mdW5jdGlvbiBpc1ZhbGlkVmlydHVhbE5vZGUgKHZpcnR1YWxOb2RlKSB7XG4gIHJldHVybiB2aXJ0dWFsTm9kZSAhPSBudWxsICYmIHZpcnR1YWxOb2RlICE9PSBmYWxzZVxufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGFzc29jaWF0ZXMgYSBjb21wb25lbnQgb2JqZWN0IHdpdGggYSBET00gZWxlbWVudCBieSBjYWxsaW5nXG4vLyB0aGUgY29tcG9uZW50cyBgcmVuZGVyYCBtZXRob2QsIGFzc2lnbmluZyBhbiBgLmVsZW1lbnRgIHByb3BlcnR5IG9uIHRoZVxuLy8gb2JqZWN0IGFuZCBhbHNvIHJldHVybmluZyB0aGUgZWxlbWVudC5cbi8vXG4vLyBJdCBhbHNvIGFzc2lnbnMgYSBgdmlydHVhbE5vZGVgIHByb3BlcnR5IGJhc2VkIG9uIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlXG4vLyBgcmVuZGVyYCBtZXRob2QuIFRoaXMgd2lsbCBiZSB1c2VkIGxhdGVyIGJ5IGBwZXJmb3JtRWxlbWVudFVwZGF0ZWAgdG8gZGlmZlxuLy8gdGhlIG5ldyByZXN1bHRzIG9mIGByZW5kZXJgIHdpdGggdGhlIHByZXZpb3VzIHJlc3VsdHMgd2hlbiB1cGRhdGluZyB0aGVcbi8vIGNvbXBvbmVudCdzIGVsZW1lbnQuXG4vL1xuLy8gRmluYWxseSwgdGhpcyBmdW5jdGlvbiBhbHNvIGFzc29jaWF0ZXMgdGhlIGNvbXBvbmVudCB3aXRoIGEgYHJlZnNgIG9iamVjdCxcbi8vIHdoaWNoIGlzIHBvcHVsYXRlZCB3aXRoIHJlZmVyZW5jZXMgdG8gZWxlbWVudHMgYmFzZWQgb24gYHJlZmAgcHJvcGVydGllcyBvblxuLy8gbm9kZXMgb2YgdGhlIGB2aXJ0dWFsLWRvbWAgdHJlZS4gQmVmb3JlIGNhbGxpbmcgaW50byBgdmlydHVhbC1kb21gIHRvIGNyZWF0ZVxuLy8gdGhlIERPTSB0cmVlLCBpdCBwdXNoZXMgdGhpcyBgcmVmc2Agb2JqZWN0IHRvIGEgc2hhcmVkIHN0YWNrIHNvIGl0IGNhbiBiZVxuLy8gYWNjZXNzZWQgYnkgaG9va3MgZHVyaW5nIHRoZSBjcmVhdGlvbiBvZiBpbmRpdmlkdWFsIGVsZW1lbnRzLlxuZnVuY3Rpb24gaW5pdGlhbGl6ZShjb21wb25lbnQpIHtcbiAgaWYgKHR5cGVvZiBjb21wb25lbnQudXBkYXRlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFdGNoIGNvbXBvbmVudHMgbXVzdCBpbXBsZW1lbnQgYHVwZGF0ZShwcm9wcywgY2hpbGRyZW4pYC4nKVxuICB9XG5cbiAgbGV0IHZpcnR1YWxOb2RlID0gY29tcG9uZW50LnJlbmRlcigpXG4gIGlmICghaXNWYWxpZFZpcnR1YWxOb2RlKHZpcnR1YWxOb2RlKSkge1xuICAgIGxldCBuYW1lUGFydCA9IGNvbXBvbmVudC5jb25zdHJ1Y3RvciAmJiBjb21wb25lbnQuY29uc3RydWN0b3IubmFtZSA/ICcgaW4gJyArIGNvbXBvbmVudC5jb25zdHJ1Y3Rvci5uYW1lIDogJydcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgZmFsc3kgdmFsdWUgJyArIHZpcnR1YWxOb2RlICsgJyByZXR1cm5lZCBmcm9tIHJlbmRlcigpJyArIG5hbWVQYXJ0KVxuICB9XG5cbiAgY29tcG9uZW50LnJlZnMgPSB7fVxuICBjb21wb25lbnQudmlydHVhbE5vZGUgPSB2aXJ0dWFsTm9kZVxuICBjb21wb25lbnQuZWxlbWVudCA9IHJlbmRlcihjb21wb25lbnQudmlydHVhbE5vZGUsIHtcbiAgICByZWZzOiBjb21wb25lbnQucmVmcywgbGlzdGVuZXJDb250ZXh0OiBjb21wb25lbnRcbiAgfSlcbn1cblxuLy8gVGhpcyBmdW5jdGlvbiByZWNlaXZlcyBhIGNvbXBvbmVudCB0aGF0IGhhcyBhbHJlYWR5IGJlZW4gYXNzb2NpYXRlZCB3aXRoIGFuXG4vLyBlbGVtZW50IHZpYSBhIHByZXZpb3VzIGNhbGwgdG8gYGluaXRpYWxpemVgIGFuZCB1cGRhdGVzIHRoaXMgZWxlbWVudCBieVxuLy8gY2FsbGluZyBgcmVuZGVyYCBvbiB0aGUgY29tcG9uZW50LlxuLy9cbi8vIFdoZW4gY2FsbGVkIGluIG5vcm1hbCBjaXJjdW1zdGFuY2VzLCBpdCB1c2VzIHRoZSBzY2hlZHVsZXIgdG8gZGVmZXIgdGhpc1xuLy8gdXBkYXRlIHVudGlsIHRoZSBuZXh0IGFuaW1hdGlvbiBmcmFtZSwgYW5kIHdpbGwgb25seSBwZXJmb3JtIG9uZSB1cGRhdGUgb2YgYVxuLy8gZ2l2ZW4gY29tcG9uZW50IGluIGEgZ2l2ZW4gZnJhbWUuIFRoaXMgbWVhbnMgeW91IGNhbiBjYWxsIGB1cGRhdGVgXG4vLyByZXBlYXRlZGx5IGluIGEgZ2l2ZW4gdGljayB3aXRob3V0IGNhdXNpbmcgcmVkdW5kYW50IHVwZGF0ZXMuXG4vL1xuLy8gSWYgdGhpcyBmdW5jdGlvbiBjYWxsZWQgZHVyaW5nIGFub3RoZXIgc3luY2hyb25vdXMgdXBkYXRlIChmb3IgZXhhbXBsZSwgYXMgYVxuLy8gcmVzdWx0IG9mIGEgY2FsbCB0byBgdXBkYXRlYCBvbiBhIGNoaWxkIGNvbXBvbmVudCksIHRoZSB1cGRhdGUgaXMgcGVyZm9ybWVkXG4vLyBzeW5jaHJvbm91c2x5LlxuLy9cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgd2lsbCByZXNvbHZlIHdoZW4gdGhlIHJlcXVlc3RlZCB1cGRhdGUgaGFzIGJlZW5cbi8vIGNvbXBsZXRlZC5cbmZ1bmN0aW9uIHVwZGF0ZSAoY29tcG9uZW50LCByZXBsYWNlTm9kZT10cnVlKSB7XG4gIGlmIChzeW5jVXBkYXRlc0luUHJvZ3Jlc3NDb3VudGVyID4gMCkge1xuICAgIHVwZGF0ZVN5bmMoY29tcG9uZW50LCByZXBsYWNlTm9kZSlcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgfVxuXG4gIGxldCBzY2hlZHVsZXIgPSBnZXRTY2hlZHVsZXIoKVxuXG4gIGlmICghY29tcG9uZW50c1dpdGhQZW5kaW5nVXBkYXRlcy5oYXMoY29tcG9uZW50KSkge1xuICAgIGNvbXBvbmVudHNXaXRoUGVuZGluZ1VwZGF0ZXMuYWRkKGNvbXBvbmVudClcbiAgICBzY2hlZHVsZXIudXBkYXRlRG9jdW1lbnQoZnVuY3Rpb24gKCkge1xuICAgICAgY29tcG9uZW50c1dpdGhQZW5kaW5nVXBkYXRlcy5kZWxldGUoY29tcG9uZW50KVxuICAgICAgdXBkYXRlU3luYyhjb21wb25lbnQsIHJlcGxhY2VOb2RlKVxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gc2NoZWR1bGVyLmdldE5leHRVcGRhdGVQcm9taXNlKClcbn1cblxuLy8gU3luY2hyb25zbHkgdXBkYXRlcyB0aGUgRE9NIGVsZW1lbnQgYXNzb2NpYXRlZCB3aXRoIGEgY29tcG9uZW50IG9iamVjdC4gLlxuLy8gVGhpcyBtZXRob2QgYXNzdW1lcyB0aGUgcHJlc2VuY2Ugb2YgYC5lbGVtZW50YCBhbmQgYC52aXJ0dWFsTm9kZWBcbi8vIHByb3BlcnRpZXMgb24gdGhlIGNvbXBvbmVudCwgd2hpY2ggYXJlIGFzc2lnbmVkIGluIHRoZSBgaW5pdGlhbGl6ZWBcbi8vIGZ1bmN0aW9uLlxuLy9cbi8vIEl0IGNhbGxzIGByZW5kZXJgIG9uIHRoZSBjb21wb25lbnQgdG8gb2J0YWluIHRoZSBkZXNpcmVkIHN0YXRlIG9mIHRoZSBET00sXG4vLyB0aGVuIGBkaWZmYHMgaXQgd2l0aCB0aGUgcHJldmlvdXMgc3RhdGUgYW5kIGBwYXRjaGBlcyB0aGUgZWxlbWVudCBiYXNlZCBvblxuLy8gdGhlIHJlc3VsdGluZyBkaWZmLiBEdXJpbmcgdGhlIHBhdGNoIG9wZXJhdGlvbiwgaXQgcHVzaGVzIHRoZSBjb21wb25lbnQnc1xuLy8gYHJlZnNgIG9iamVjdCB0byBhIHNoYXJlZCBzdGFjayBzbyB0aGF0IHJlZmVyZW5jZXMgdG8gRE9NIGVsZW1lbnRzIGNhbiBiZVxuLy8gdXBkYXRlZC5cbi8vXG4vLyBJZiBgdXBkYXRlYCBpcyBjYWxsZWQgZHVyaW5nIHRoZSBpbnZvY2F0aW9uIG9mIGB1cGRhdGVTeW5jYCxcbi8vIHRoZSByZXF1ZXN0cyBhcmUgcHJvY2Vzc2VkIHN5bmNocm9ub3VzbHkgYXMgd2VsbC4gV2UgdHJhY2sgd2hldGhlciB0aGlzIGlzXG4vLyB0aGUgY2FzZSBieSBpbmNyZW1lbnRpbmcgYW5kIGRlY3JlbWVudGluZyBgc3luY1VwZGF0ZXNJblByb2dyZXNzQ291bnRlcmBcbi8vIGFyb3VuZCB0aGUgY2FsbC5cbi8vXG4vLyBGb3Igbm93LCBldGNoIGRvZXMgbm90IGFsbG93IHRoZSByb290IHRhZyBvZiB0aGUgYHJlbmRlcmAgbWV0aG9kIHRvIGNoYW5nZVxuLy8gYmV0d2VlbiBpbnZvY2F0aW9ucywgYmVjYXVzZSB3ZSB3YW50IHRvIHByZXNlcnZlIGEgb25lLXRvLW9uZSByZWxhdGlvbnNoaXBcbi8vIGJldHdlZW4gY29tcG9uZW50IG9iamVjdHMgYW5kIERPTSBlbGVtZW50cyBmb3Igc2ltcGxpY2l0eS5cbmZ1bmN0aW9uIHVwZGF0ZVN5bmMgKGNvbXBvbmVudCwgcmVwbGFjZU5vZGU9dHJ1ZSkge1xuICBsZXQgbmV3VmlydHVhbE5vZGUgPSBjb21wb25lbnQucmVuZGVyKClcbiAgaWYgKCFpc1ZhbGlkVmlydHVhbE5vZGUobmV3VmlydHVhbE5vZGUpKSB7XG4gICAgbGV0IG5hbWVQYXJ0ID0gY29tcG9uZW50LmNvbnN0cnVjdG9yICYmIGNvbXBvbmVudC5jb25zdHJ1Y3Rvci5uYW1lID8gJyBpbiAnICsgY29tcG9uZW50LmNvbnN0cnVjdG9yLm5hbWUgOiAnJ1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBmYWxzeSB2YWx1ZSAnICsgbmV3VmlydHVhbE5vZGUgKyAnIHJldHVybmVkIGZyb20gcmVuZGVyKCknICsgbmFtZVBhcnQpXG4gIH1cblxuICBzeW5jVXBkYXRlc0luUHJvZ3Jlc3NDb3VudGVyKytcbiAgbGV0IG9sZFZpcnR1YWxOb2RlID0gY29tcG9uZW50LnZpcnR1YWxOb2RlXG4gIGxldCBvbGREb21Ob2RlID0gY29tcG9uZW50LmVsZW1lbnRcbiAgbGV0IG5ld0RvbU5vZGUgPSBwYXRjaChvbGRWaXJ0dWFsTm9kZSwgbmV3VmlydHVhbE5vZGUsIHtcbiAgICByZWZzOiBjb21wb25lbnQucmVmcyxcbiAgICBsaXN0ZW5lckNvbnRleHQ6IGNvbXBvbmVudFxuICB9KVxuICBjb21wb25lbnQudmlydHVhbE5vZGUgPSBuZXdWaXJ0dWFsTm9kZVxuICBpZiAobmV3RG9tTm9kZSAhPT0gb2xkRG9tTm9kZSAmJiAhcmVwbGFjZU5vZGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSByb290IG5vZGUgdHlwZSBjaGFuZ2VkIG9uIHVwZGF0ZSwgYnV0IHRoZSB1cGRhdGUgd2FzIHBlcmZvcm1lZCB3aXRoIHRoZSByZXBsYWNlTm9kZSBvcHRpb24gc2V0IHRvIGZhbHNlJylcbiAgfSBlbHNlIHtcbiAgICBjb21wb25lbnQuZWxlbWVudCA9IG5ld0RvbU5vZGVcbiAgfVxuXG4gIC8vIFdlIGNhbiBzYWZlbHkgcGVyZm9ybSBhZGRpdGlvbmFsIHdyaXRlcyBhZnRlciBhIERPTSB1cGRhdGUgc3luY2hyb25vdXNseSxcbiAgLy8gYnV0IGFueSByZWFkcyBuZWVkIHRvIGJlIGRlZmVycmVkIHVudGlsIGFsbCB3cml0ZXMgYXJlIGNvbXBsZXRlZCB0byBhdm9pZFxuICAvLyBET00gdGhyYXNoaW5nLiBSZXF1ZXN0ZWQgcmVhZHMgb2NjdXIgYXQgdGhlIGVuZCBvZiB0aGUgdGhlIGN1cnJlbnQgZnJhbWVcbiAgLy8gaWYgdGhpcyBtZXRob2Qgd2FzIGludm9rZWQgdmlhIHRoZSBzY2hlZHVsZXIuIE90aGVyd2lzZSwgaWYgYHVwZGF0ZVN5bmNgXG4gIC8vIHdhcyBpbnZva2VkIG91dHNpZGUgb2YgdGhlIHNjaGVkdWxlciwgdGhlIGRlZmF1bHQgc2NoZWR1bGVyIHdpbGwgZGVmZXJcbiAgLy8gcmVhZHMgdW50aWwgdGhlIG5leHQgYW5pbWF0aW9uIGZyYW1lLlxuICBpZiAodHlwZW9mIGNvbXBvbmVudC53cml0ZUFmdGVyVXBkYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29tcG9uZW50LndyaXRlQWZ0ZXJVcGRhdGUoKVxuICB9XG4gIGlmICh0eXBlb2YgY29tcG9uZW50LnJlYWRBZnRlclVwZGF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGdldFNjaGVkdWxlcigpLnJlYWREb2N1bWVudChmdW5jdGlvbiAoKSB7XG4gICAgICBjb21wb25lbnQucmVhZEFmdGVyVXBkYXRlKClcbiAgICB9KVxuICB9XG5cbiAgc3luY1VwZGF0ZXNJblByb2dyZXNzQ291bnRlci0tXG59XG5cbi8vIFJlbW92ZXMgdGhlIGNvbXBvbmVudCdzIGFzc29jaWF0ZWQgZWxlbWVudCBhbmQgY2FsbHMgYGRlc3Ryb3lgIG9uIGFueSBjaGlsZFxuLy8gY29tcG9uZW50cy4gTm9ybWFsbHksIHRoaXMgZnVuY3Rpb24gaXMgYXN5bmNocm9ub3VzIGFuZCB3aWxsIHBlcmZvcm0gdGhlXG4vLyBkZXN0cnVjdGlvbiBvbiB0aGUgbmV4dCBhbmltYXRpb24gZnJhbWUuIElmIGNhbGxlZCBhcyB0aGUgcmVzdWx0IG9mIGFub3RoZXJcbi8vIHVwZGF0ZSBvciBkZXN0cnVjdGlvbiwgaXQgY2FsbHMgYGRlc3Ryb3lgIG9uIGNoaWxkIGNvbXBvbmVudHMgc3luY2hyb25vdXNseS5cbi8vIElmIGNhbGxlZCBhcyB0aGUgcmVzdWx0IG9mIGRlc3Ryb3lpbmcgYSBjb21wb25lbnQgaGlnaGVyIGluIHRoZSBET00sIHRoZVxuLy8gZWxlbWVudCBpcyBub3QgcmVtb3ZlZCB0byBhdm9pZCByZWR1bmRhbnQgRE9NIG1hbmlwdWxhdGlvbi4gUmV0dXJucyBhIHByb21pc2Vcbi8vIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZGVzdHJ1Y3Rpb24gaXMgY29tcGxldGVkLlxuZnVuY3Rpb24gZGVzdHJveSAoY29tcG9uZW50LCByZW1vdmVOb2RlPXRydWUpIHtcbiAgaWYgKHN5bmNVcGRhdGVzSW5Qcm9ncmVzc0NvdW50ZXIgPiAwIHx8IHN5bmNEZXN0cnVjdGlvbnNJblByb2dyZXNzQ291bnRlciA+IDApIHtcbiAgICBkZXN0cm95U3luYyhjb21wb25lbnQsIHJlbW92ZU5vZGUpXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBsZXQgc2NoZWR1bGVyID0gZ2V0U2NoZWR1bGVyKClcbiAgc2NoZWR1bGVyLnVwZGF0ZURvY3VtZW50KGZ1bmN0aW9uICgpIHtcbiAgICBkZXN0cm95U3luYyhjb21wb25lbnQsIHJlbW92ZU5vZGUpXG4gIH0pXG4gIHJldHVybiBzY2hlZHVsZXIuZ2V0TmV4dFVwZGF0ZVByb21pc2UoKVxufVxuXG4vLyBBIHN5bmNocm9ub3VzIHZlcnNpb24gb2YgYGRlc3Ryb3lgLlxuLy9cbi8vIE5vdGUgdGhhdCB3ZSB0cmFjayB3aGV0aGVyIGBkZXN0cm95YCBjYWxscyBhcmUgaW4gcHJvZ3Jlc3MgYW5kIG9ubHkgcmVtb3ZlXG4vLyB0aGUgZWxlbWVudCBpZiB3ZSBhcmUgbm90IGEgbmVzdGVkIGNhbGwuXG5mdW5jdGlvbiBkZXN0cm95U3luYyAoY29tcG9uZW50LCByZW1vdmVOb2RlPXRydWUpIHtcbiAgc3luY0Rlc3RydWN0aW9uc0luUHJvZ3Jlc3NDb3VudGVyKytcbiAgZGVzdHJveUNoaWxkQ29tcG9uZW50cyhjb21wb25lbnQudmlydHVhbE5vZGUpXG4gIGlmIChzeW5jRGVzdHJ1Y3Rpb25zSW5Qcm9ncmVzc0NvdW50ZXIgPT09IDEgJiYgcmVtb3ZlTm9kZSkgY29tcG9uZW50LmVsZW1lbnQucmVtb3ZlKClcbiAgc3luY0Rlc3RydWN0aW9uc0luUHJvZ3Jlc3NDb3VudGVyLS1cbn1cblxuZnVuY3Rpb24gZGVzdHJveUNoaWxkQ29tcG9uZW50cyh2aXJ0dWFsTm9kZSkge1xuICBpZiAodmlydHVhbE5vZGUuY29tcG9uZW50ICYmIHR5cGVvZiB2aXJ0dWFsTm9kZS5jb21wb25lbnQuZGVzdHJveSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHZpcnR1YWxOb2RlLmNvbXBvbmVudC5kZXN0cm95KClcbiAgfSBlbHNlIGlmICh2aXJ0dWFsTm9kZS5jaGlsZHJlbikge1xuICAgIHZpcnR1YWxOb2RlLmNoaWxkcmVuLmZvckVhY2goZGVzdHJveUNoaWxkQ29tcG9uZW50cylcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaW5pdGlhbGl6ZSxcbiAgdXBkYXRlLCB1cGRhdGVTeW5jLFxuICBkZXN0cm95LCBkZXN0cm95U3luY1xufVxuIiwiLy8gSWYgdGhlIHNjaGVkdWxlciBpcyBub3QgY3VzdG9taXplZCB2aWEgYGV0Y2guc2V0U2NoZWR1bGVyYCwgYW4gaW5zdGFuY2Ugb2Zcbi8vIHRoaXMgY2xhc3Mgd2lsbCBiZSB1c2VkIHRvIHNjaGVkdWxlIHVwZGF0ZXMgdG8gdGhlIGRvY3VtZW50LiBUaGVcbi8vIGB1cGRhdGVEb2N1bWVudGAgbWV0aG9kIGFjY2VwdHMgZnVuY3Rpb25zIHRvIGJlIHJ1biBhdCBzb21lIHBvaW50IGluIHRoZVxuLy8gZnV0dXJlLCB0aGVuIHJ1bnMgdGhlbSBvbiB0aGUgbmV4dCBhbmltYXRpb24gZnJhbWUuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIERlZmF1bHRTY2hlZHVsZXIge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgdGhpcy51cGRhdGVSZXF1ZXN0cyA9IFtdXG4gICAgdGhpcy5yZWFkUmVxdWVzdHMgPSBbXVxuICAgIHRoaXMucGVuZGluZ0FuaW1hdGlvbkZyYW1lID0gbnVsbFxuICAgIHRoaXMucGVyZm9ybVVwZGF0ZXMgPSB0aGlzLnBlcmZvcm1VcGRhdGVzLmJpbmQodGhpcylcbiAgICB0aGlzLnBlcmZvcm1pbmdVcGRhdGVzID0gZmFsc2VcbiAgfVxuXG4gIC8vIEVucXVldWVzIGZ1bmN0aW9ucyB0aGF0IHdyaXRlIHRvIHRoZSBET00gdG8gYmUgcGVyZm9ybWVkIG9uIHRoZSBuZXh0XG4gIC8vIGFuaW1hdGlvbiBmcmFtZS4gRnVuY3Rpb25zIHBhc3NlZCB0byB0aGlzIG1ldGhvZCBzaG91bGQgKm5ldmVyKiByZWFkIGZyb21cbiAgLy8gdGhlIERPTSwgYmVjYXVzZSB0aGF0IGNvdWxkIGNhdXNlIHN5bmNocm9ub3VzIHJlZmxvd3MuXG4gIHVwZGF0ZURvY3VtZW50IChmbikge1xuICAgIHRoaXMudXBkYXRlUmVxdWVzdHMucHVzaChmbilcbiAgICBpZiAoIXRoaXMucGVuZGluZ0FuaW1hdGlvbkZyYW1lKSB7XG4gICAgICB0aGlzLnBlbmRpbmdBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5wZXJmb3JtVXBkYXRlcylcbiAgICB9XG4gIH1cblxuICByZWFkRG9jdW1lbnQgKGZuKSB7XG4gICAgdGhpcy5yZWFkUmVxdWVzdHMucHVzaChmbilcbiAgICBpZiAoIXRoaXMucGVuZGluZ0FuaW1hdGlvbkZyYW1lKSB7XG4gICAgICB0aGlzLnBlbmRpbmdBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5wZXJmb3JtVXBkYXRlcylcbiAgICB9XG4gIH1cblxuICAvLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgcmVzb2x2ZSBhdCB0aGUgZW5kIG9mIHRoZSBuZXh0IHVwZGF0ZSBjeWNsZSxcbiAgLy8gYWZ0ZXIgYWxsIHRoZSBmdW5jdGlvbnMgcGFzc2VkIHRvIGB1cGRhdGVEb2N1bWVudGAgYW5kIGB1cGRhdGVEb2N1bWVudFN5bmNgXG4gIC8vIGhhdmUgYmVlbiBydW4uXG4gIGdldE5leHRVcGRhdGVQcm9taXNlICgpIHtcbiAgICBpZiAoIXRoaXMubmV4dFVwZGF0ZVByb21pc2UpIHtcbiAgICAgIHRoaXMubmV4dFVwZGF0ZVByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgdGhpcy5yZXNvbHZlTmV4dFVwZGF0ZVByb21pc2UgPSByZXNvbHZlXG4gICAgICB9KVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5uZXh0VXBkYXRlUHJvbWlzZVxuICB9XG5cbiAgLy8gUGVyZm9ybXMgYWxsIHRoZSBwZW5kaW5nIGRvY3VtZW50IHVwZGF0ZXMuIElmIHJ1bm5pbmcgdGhlc2UgdXBkYXRlXG4gIC8vIGZ1bmN0aW9ucyBjYXVzZXMgKm1vcmUqIHVwZGF0ZXMgdG8gYmUgZW5xdWV1ZWQsIHRoZXkgYXJlIHJ1biBzeW5jaHJvbm91c2x5XG4gIC8vIGluIHRoaXMgdXBkYXRlIGN5Y2xlIHdpdGhvdXQgd2FpdGluZyBmb3IgYW5vdGhlciBmcmFtZS5cbiAgcGVyZm9ybVVwZGF0ZXMgKCkge1xuICAgIHdoaWxlICh0aGlzLnVwZGF0ZVJlcXVlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMudXBkYXRlUmVxdWVzdHMuc2hpZnQoKSgpXG4gICAgfVxuXG4gICAgLy8gV2UgZG9uJ3QgY2xlYXIgdGhlIHBlbmRpbmcgZnJhbWUgdW50aWwgYWxsIHVwZGF0ZSByZXF1ZXN0cyBhcmUgcHJvY2Vzc2VkLlxuICAgIC8vIFRoaXMgZW5zdXJlcyB1cGRhdGVzIHJlcXVlc3RlZCB3aXRoaW4gb3RoZXIgdXBkYXRlcyBhcmUgcHJvY2Vzc2VkIGluIHRoZVxuICAgIC8vIGN1cnJlbnQgZnJhbWUuXG4gICAgdGhpcy5wZW5kaW5nQW5pbWF0aW9uRnJhbWUgPSBudWxsXG5cbiAgICAvLyBOb3cgdGhhdCB1cGRhdGVzIGFyZSBwcm9jZXNzZWQsIHdlIGNhbiBwZXJmb3JtIGFsbCBwZW5kaW5nIGRvY3VtZW50IHJlYWRzXG4gICAgLy8gd2l0aG91dCB0aGUgcmlzayBvZiBpbnRlcmxlYXZpbmcgdGhlbSB3aXRoIHdyaXRlcyBhbmQgY2F1c2luZyBsYXlvdXRcbiAgICAvLyB0aHJhc2hpbmcuXG4gICAgd2hpbGUgKHRoaXMucmVhZFJlcXVlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucmVhZFJlcXVlc3RzLnNoaWZ0KCkoKVxuICAgIH1cblxuICAgIGlmICh0aGlzLm5leHRVcGRhdGVQcm9taXNlKSB7XG4gICAgICBsZXQgcmVzb2x2ZU5leHRVcGRhdGVQcm9taXNlID0gdGhpcy5yZXNvbHZlTmV4dFVwZGF0ZVByb21pc2VcbiAgICAgIHRoaXMubmV4dFVwZGF0ZVByb21pc2UgPSBudWxsXG4gICAgICB0aGlzLnJlc29sdmVOZXh0VXBkYXRlUHJvbWlzZSA9IG51bGxcbiAgICAgIHJlc29sdmVOZXh0VXBkYXRlUHJvbWlzZSgpXG4gICAgfVxuICB9XG59XG4iLCJjb25zdCBFVkVOVF9MSVNURU5FUl9QUk9QUyA9IHJlcXVpcmUoJy4vZXZlbnQtbGlzdGVuZXItcHJvcHMnKVxuY29uc3QgU1ZHX1RBR1MgPSByZXF1aXJlKCcuL3N2Zy10YWdzJylcblxuZnVuY3Rpb24gZG9tICh0YWcsIHByb3BzLCAuLi5jaGlsZHJlbikge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICBjb25zdCBjaGlsZCA9IGNoaWxkcmVuW2ldXG4gICAgc3dpdGNoICh0eXBlb2YgY2hpbGQpIHtcbiAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICBjaGlsZHJlbltpXSA9IHt0ZXh0OiBjaGlsZH1cbiAgICAgICAgaSsrXG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjaGlsZCkpIHtcbiAgICAgICAgICBjaGlsZHJlbi5zcGxpY2UoaSwgMSwgLi4uY2hpbGQpXG4gICAgICAgIH0gZWxzZSBpZiAoIWNoaWxkKSB7XG4gICAgICAgICAgY2hpbGRyZW4uc3BsaWNlKGksIDEpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaSsrXG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBjaGlsZCBub2RlOiAke2NoaWxkfWApXG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3BzKSB7XG4gICAgZm9yIChjb25zdCBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgY29uc3QgZXZlbnROYW1lID0gRVZFTlRfTElTVEVORVJfUFJPUFNbcHJvcE5hbWVdXG4gICAgICBpZiAoZXZlbnROYW1lKSB7XG4gICAgICAgIGlmICghcHJvcHMub24pIHByb3BzLm9uID0ge31cbiAgICAgICAgcHJvcHMub25bZXZlbnROYW1lXSA9IHByb3BzW3Byb3BOYW1lXVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwcm9wcy5jbGFzcykge1xuICAgICAgcHJvcHMuY2xhc3NOYW1lID0gcHJvcHMuY2xhc3NcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge3RhZywgcHJvcHMsIGNoaWxkcmVufVxufVxuXG5jb25zdCBIVE1MX1RBR1MgPSBbXG4gICdhJywgJ2FiYnInLCAnYWRkcmVzcycsICdhcnRpY2xlJywgJ2FzaWRlJywgJ2F1ZGlvJywgJ2InLCAnYmRpJywgJ2JkbycsXG4gICdibG9ja3F1b3RlJywgJ2JvZHknLCAnYnV0dG9uJywgJ2NhbnZhcycsICdjYXB0aW9uJywgJ2NpdGUnLCAnY29kZScsXG4gICdjb2xncm91cCcsICdkYXRhbGlzdCcsICdkZCcsICdkZWwnLCAnZGV0YWlscycsICdkZm4nLCAnZGlhbG9nJywgJ2RpdicsICdkbCcsXG4gICdkdCcsICdlbScsICdmaWVsZHNldCcsICdmaWdjYXB0aW9uJywgJ2ZpZ3VyZScsICdmb290ZXInLCAnZm9ybScsICdoMScsICdoMicsXG4gICdoMycsICdoNCcsICdoNScsICdoNicsICdoZWFkJywgJ2hlYWRlcicsICdodG1sJywgJ2knLCAnaWZyYW1lJywgJ2lucycsICdrYmQnLFxuICAnbGFiZWwnLCAnbGVnZW5kJywgJ2xpJywgJ21haW4nLCAnbWFwJywgJ21hcmsnLCAnbWVudScsICdtZXRlcicsICduYXYnLFxuICAnbm9zY3JpcHQnLCAnb2JqZWN0JywgJ29sJywgJ29wdGdyb3VwJywgJ29wdGlvbicsICdvdXRwdXQnLCAncCcsICdwcmUnLFxuICAncHJvZ3Jlc3MnLCAncScsICdycCcsICdydCcsICdydWJ5JywgJ3MnLCAnc2FtcCcsICdzY3JpcHQnLCAnc2VjdGlvbicsXG4gICdzZWxlY3QnLCAnc21hbGwnLCAnc3BhbicsICdzdHJvbmcnLCAnc3R5bGUnLCAnc3ViJywgJ3N1bW1hcnknLCAnc3VwJyxcbiAgJ3RhYmxlJywgJ3Rib2R5JywgJ3RkJywgJ3RleHRhcmVhJywgJ3Rmb290JywgJ3RoJywgJ3RoZWFkJywgJ3RpbWUnLCAndGl0bGUnLFxuICAndHInLCAndScsICd1bCcsICd2YXInLCAndmlkZW8nLCAnYXJlYScsICdiYXNlJywgJ2JyJywgJ2NvbCcsICdjb21tYW5kJyxcbiAgJ2VtYmVkJywgJ2hyJywgJ2ltZycsICdpbnB1dCcsICdrZXlnZW4nLCAnbGluaycsICdtZXRhJywgJ3BhcmFtJywgJ3NvdXJjZScsXG4gICd0cmFjaycsICd3YnInXG5dXG5cbmZvciAoY29uc3QgdGFnTmFtZSBvZiBIVE1MX1RBR1MpIHtcbiAgZG9tW3RhZ05hbWVdID0gKHByb3BzLCAuLi5jaGlsZHJlbikgPT4ge1xuICAgIHJldHVybiBkb20odGFnTmFtZSwgcHJvcHMsIC4uLmNoaWxkcmVuKVxuICB9XG59XG5cbmZvciAoY29uc3QgdGFnTmFtZSBvZiBTVkdfVEFHUykge1xuICBkb21bdGFnTmFtZV0gPSAocHJvcHMsIC4uLmNoaWxkcmVuKSA9PiB7XG4gICAgcmV0dXJuIGRvbSh0YWdOYW1lLCBwcm9wcywgLi4uY2hpbGRyZW4pXG4gIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGRvbVxuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIG9uQ29weTogJ2NvcHknLFxuICBvbkN1dDogJ2N1dCcsXG4gIG9uUGFzdGU6ICdwYXN0ZScsXG4gIG9uQ29tcG9zaXRpb25FbmQ6ICdjb21wb3NpdGlvbmVuZCcsXG4gIG9uQ29tcG9zaXRpb25TdGFydDogJ2NvbXBvc2l0aW9uc3RhcnQnLFxuICBvbkNvbXBvc2l0aW9uVXBkYXRlOiAnY29tcG9zaXRpb251cGRhdGUnLFxuICBvbktleURvd246ICdrZXlkb3duJyxcbiAgb25LZXlQcmVzczogJ2tleXByZXNzJyxcbiAgb25LZXlVcDogJ2tleXVwJyxcbiAgb25Gb2N1czogJ2ZvY3VzJyxcbiAgb25CbHVyOiAnYmx1cicsXG4gIG9uQ2hhbmdlOiAnY2hhbmdlJyxcbiAgb25JbnB1dDogJ2lucHV0JyxcbiAgb25TdWJtaXQ6ICdzdWJtaXQnLFxuICBvbkNsaWNrOiAnY2xpY2snLFxuICBvbkNvbnRleHRNZW51OiAnY29udGV4dG1lbnUnLFxuICBvbkRvdWJsZUNsaWNrOiAnZG91YmxlY2xpY2snLFxuICBvbkRyYWc6ICdkcmFnJyxcbiAgb25EcmFnRW5kOiAnZHJhZ2VuZCcsXG4gIG9uRHJhZ0VudGVyOiAnZHJhZ2VudGVyJyxcbiAgb25EcmFnRXhpdDogJ2RyYWdleGl0JyxcbiAgb25EcmFnTGVhdmU6ICdkcmFnbGVhdmUnLFxuICBvbkRyYWdPdmVyOiAnZHJhZ292ZXInLFxuICBvbkRyYWdTdGFydDogJ2RyYWdzdGFydCcsXG4gIG9uRHJvcDogJ2Ryb3AnLFxuICBvbk1vdXNlRG93bjogJ21vdXNlZG93bicsXG4gIG9uTW91c2VFbnRlcjogJ21vdXNlbnRlcicsXG4gIG9uTW91c2VMZWF2ZTogJ21vdXNlbGVhdmUnLFxuICBvbk1vdXNlTW92ZTogJ21vdXNlbW92ZScsXG4gIG9uTW91c2VPdXQ6ICdtb3VzZW91dCcsXG4gIG9uTW91c2VPdmVyOiAnbW91c2VvdmVyJyxcbiAgb25Nb3VzZVVwOiAnbW91c2V1cCcsXG4gIG9uU2VsZWN0OiAnc2VsZWN0JyxcbiAgb25Ub3VjaENhbmNlbDogJ3RvdWNoY2FuY2VsJyxcbiAgb25Ub3VjaEVuZDogJ3RvdWNoZW5kJyxcbiAgb25Ub3VjaE1vdmU6ICd0b3VjaG1vdmUnLFxuICBvblRvdWNoU3RhcnQ6ICd0b3VjaHN0YXJ0JyxcbiAgb25TY3JvbGw6ICdzY3JvbGwnLFxuICBvbldoZWVsOiAnd2hlZWwnLFxuICBvbkFib3J0OiAnYWJvcnQnLFxuICBvbkNhblBsYXk6ICdjYW5wbGF5JyxcbiAgb25DYW5QbGF5VGhyb3VnaDogJ2NhbnBsYXl0aHJvdWdoJyxcbiAgb25EdXJhdGlvbkNoYW5nZTogJ2R1cmF0aW9uY2hhbmdlJyxcbiAgb25FbXB0aWVkOiAnZW1wdGllZCcsXG4gIG9uRW5jcnlwdGVkOiAnZW5jcnlwdGVkJyxcbiAgb25FbmRlZDogJ2VuZGVkJyxcbiAgb25FcnJvcjogJ2Vycm9yJyxcbiAgb25Mb2FkZWREYXRhOiAnbG9hZGVkZGF0YScsXG4gIG9uTG9hZGVkTWV0YWRhdGE6ICdsb2FkZWRtZXRhZGF0JyxcbiAgb25Mb2FkU3RhcnQ6ICdsb2Fkc3RhcnQnLFxuICBvblBhdXNlOiAncGF1c2UnLFxuICBvblBsYXk6ICdwbGF5JyxcbiAgb25QbGF5aW5nOiAncGxheWluZycsXG4gIG9uUHJvZ3Jlc3M6ICdwcm9ncmVzcycsXG4gIG9uUmF0ZUNoYW5nZTogJ3JhdGVjaGFuZ2UnLFxuICBvblNlZWtlZDogJ3NlZWtlZCcsXG4gIG9uU2Vla2luZzogJ3NlZWtpbmcnLFxuICBvblN0YWxsZWQ6ICdzdGFsbGVkJyxcbiAgb25TdXNwZW5kOiAnc3VzcGVuZCcsXG4gIG9uVGltZVVwZGF0ZTogJ3RpbWV1cGRhdGUnLFxuICBvblZvbHVtZUNoYW5nZTogJ3ZvbHVtZWNoYW5nZScsXG4gIG9uV2FpdGluZzogJ3dhaXRpbmcnLFxuICBvbkxvYWQ6ICdsb2FkJyxcbiAgb25FcnJvcjogJ2Vycm9yJyxcbiAgb25BbmltYXRpb25TdGFydDogJ2FuaW1hdGlvbnN0YXJ0JyxcbiAgb25BbmltYXRpb25FbmQ6ICdhbmltYXRpb25lbmQnLFxuICBvbkFuaW1hdGlvbkl0ZXJhdGlvbjogJ2FuaW1hdGlvbml0ZXJhdGlvbicsXG4gIG9uVHJhbnNpdGlvbkVuZDogJ3RyYW5zaXRpb25lbmQnXG59XG4iLCJjb25zdCByZW5kZXIgPSByZXF1aXJlKCcuL3JlbmRlcicpXG5jb25zdCB1cGRhdGVQcm9wcyA9IHJlcXVpcmUoJy4vdXBkYXRlLXByb3BzJylcblxuZnVuY3Rpb24gcGF0Y2ggKG9sZFZpcnR1YWxOb2RlLCBuZXdWaXJ0dWFsTm9kZSwgb3B0aW9ucykge1xuICBjb25zdCBvbGROb2RlID0gb2xkVmlydHVhbE5vZGUuZG9tTm9kZVxuICBpZiAodmlydHVhbE5vZGVzQXJlRXF1YWwob2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlKSkge1xuICAgIGxldCBuZXdOb2RlXG4gICAgaWYgKG5ld1ZpcnR1YWxOb2RlLnRleHQgIT0gbnVsbCkge1xuICAgICAgb2xkTm9kZS5ub2RlVmFsdWUgPSBuZXdWaXJ0dWFsTm9kZS50ZXh0XG4gICAgICBuZXdOb2RlID0gb2xkTm9kZVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIG5ld1ZpcnR1YWxOb2RlLnRhZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBuZXdOb2RlID0gdXBkYXRlQ29tcG9uZW50KG9sZFZpcnR1YWxOb2RlLCBuZXdWaXJ0dWFsTm9kZSwgb3B0aW9ucylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHVwZGF0ZUNoaWxkcmVuKG9sZE5vZGUsIG9sZFZpcnR1YWxOb2RlLmNoaWxkcmVuLCBuZXdWaXJ0dWFsTm9kZS5jaGlsZHJlbiwgb3B0aW9ucylcbiAgICAgICAgdXBkYXRlUHJvcHMob2xkTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBvcHRpb25zKVxuICAgICAgICBuZXdOb2RlID0gb2xkTm9kZVxuICAgICAgfVxuICAgIH1cbiAgICBuZXdWaXJ0dWFsTm9kZS5kb21Ob2RlID0gbmV3Tm9kZVxuICAgIGlmIChuZXdOb2RlICE9PSBvbGROb2RlICYmIG9sZE5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgb2xkTm9kZS5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBvbGROb2RlKVxuICAgIH1cbiAgICByZXR1cm4gbmV3Tm9kZVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IHBhcmVudE5vZGUgPSBvbGROb2RlLnBhcmVudE5vZGVcbiAgICBjb25zdCBuZXh0U2libGluZyA9IG9sZE5vZGUubmV4dFNpYmxpbmdcbiAgICByZW1vdmVWaXJ0dWFsTm9kZShvbGRWaXJ0dWFsTm9kZSwgb3B0aW9ucyAmJiBvcHRpb25zLnJlZnMpXG4gICAgY29uc3QgbmV3Tm9kZSA9IHJlbmRlcihuZXdWaXJ0dWFsTm9kZSwgb3B0aW9ucylcbiAgICBpZiAocGFyZW50Tm9kZSkgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobmV3Tm9kZSwgbmV4dFNpYmxpbmcpXG4gICAgbmV3VmlydHVhbE5vZGUuZG9tTm9kZSA9IG5ld05vZGVcbiAgICByZXR1cm4gbmV3Tm9kZVxuICB9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUNvbXBvbmVudCAob2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBvcHRpb25zKSB7XG4gIGNvbnN0IHtjb21wb25lbnQsIHByb3BzOiBvbGRQcm9wc30gPSBvbGRWaXJ0dWFsTm9kZVxuICBsZXQge3Byb3BzOiBuZXdQcm9wcywgY2hpbGRyZW46IG5ld0NoaWxkcmVufSA9IG5ld1ZpcnR1YWxOb2RlXG4gIG5ld1ZpcnR1YWxOb2RlLmNvbXBvbmVudCA9IGNvbXBvbmVudFxuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnJlZnMpIHtcbiAgICBjb25zdCByZWZzID0gb3B0aW9ucy5yZWZzXG4gICAgY29uc3Qgb2xkUmVmTmFtZSA9IG9sZFByb3BzICYmIG9sZFByb3BzLnJlZlxuICAgIGNvbnN0IG5ld1JlZk5hbWUgPSBuZXdQcm9wcyAmJiBuZXdQcm9wcy5yZWZcbiAgICBpZiAobmV3UmVmTmFtZSAhPT0gb2xkUmVmTmFtZSkge1xuICAgICAgaWYgKG9sZFJlZk5hbWUgJiYgcmVmc1tvbGRSZWZOYW1lXSA9PT0gY29tcG9uZW50KSBkZWxldGUgcmVmc1tvbGRSZWZOYW1lXVxuICAgICAgaWYgKG5ld1JlZk5hbWUpIHJlZnNbbmV3UmVmTmFtZV0gPSBjb21wb25lbnRcbiAgICB9XG4gIH1cbiAgY29tcG9uZW50LnVwZGF0ZShuZXdQcm9wcyB8fCB7fSwgbmV3Q2hpbGRyZW4pXG4gIHJldHVybiBjb21wb25lbnQuZWxlbWVudFxufVxuXG5mdW5jdGlvbiB1cGRhdGVDaGlsZHJlbiAocGFyZW50RWxlbWVudCwgb2xkQ2hpbGRyZW4sIG5ld0NoaWxkcmVuLCBvcHRpb25zKSB7XG4gIGxldCBvbGRTdGFydEluZGV4ID0gMFxuICBsZXQgb2xkRW5kSW5kZXggPSBvbGRDaGlsZHJlbi5sZW5ndGggLSAxXG4gIGxldCBvbGRTdGFydENoaWxkID0gb2xkQ2hpbGRyZW5bMF1cbiAgbGV0IG9sZEVuZENoaWxkID0gb2xkQ2hpbGRyZW5bb2xkRW5kSW5kZXhdXG5cbiAgbGV0IG5ld1N0YXJ0SW5kZXggPSAwXG4gIGxldCBuZXdFbmRJbmRleCA9IG5ld0NoaWxkcmVuLmxlbmd0aCAtIDFcbiAgbGV0IG5ld1N0YXJ0Q2hpbGQgPSBuZXdDaGlsZHJlblswXVxuICBsZXQgbmV3RW5kQ2hpbGQgPSBuZXdDaGlsZHJlbltuZXdFbmRJbmRleF1cblxuICBsZXQgb2xkSW5kaWNlc0J5S2V5XG5cbiAgd2hpbGUgKG9sZFN0YXJ0SW5kZXggPD0gb2xkRW5kSW5kZXggJiYgbmV3U3RhcnRJbmRleCA8PSBuZXdFbmRJbmRleCkge1xuICAgIGlmICghb2xkU3RhcnRDaGlsZCkge1xuICAgICAgb2xkU3RhcnRDaGlsZCA9IG9sZENoaWxkcmVuWysrb2xkU3RhcnRJbmRleF1cbiAgICB9IGVsc2UgaWYgKCFvbGRFbmRDaGlsZCkge1xuICAgICAgb2xkRW5kQ2hpbGQgPSBvbGRDaGlsZHJlblstLW9sZEVuZEluZGV4XVxuICAgIH0gZWxzZSBpZiAodmlydHVhbE5vZGVzQXJlRXF1YWwob2xkU3RhcnRDaGlsZCwgbmV3U3RhcnRDaGlsZCkpIHtcbiAgICAgIHBhdGNoKG9sZFN0YXJ0Q2hpbGQsIG5ld1N0YXJ0Q2hpbGQsIG9wdGlvbnMpXG4gICAgICBvbGRTdGFydENoaWxkID0gb2xkQ2hpbGRyZW5bKytvbGRTdGFydEluZGV4XVxuICAgICAgbmV3U3RhcnRDaGlsZCA9IG5ld0NoaWxkcmVuWysrbmV3U3RhcnRJbmRleF1cbiAgICB9IGVsc2UgaWYgKHZpcnR1YWxOb2Rlc0FyZUVxdWFsKG9sZEVuZENoaWxkLCBuZXdFbmRDaGlsZCkpIHtcbiAgICAgIHBhdGNoKG9sZEVuZENoaWxkLCBuZXdFbmRDaGlsZCwgb3B0aW9ucylcbiAgICAgIG9sZEVuZENoaWxkID0gb2xkQ2hpbGRyZW5bLS1vbGRFbmRJbmRleF1cbiAgICAgIG5ld0VuZENoaWxkID0gbmV3Q2hpbGRyZW5bLS1uZXdFbmRJbmRleF1cbiAgICB9IGVsc2UgaWYgKHZpcnR1YWxOb2Rlc0FyZUVxdWFsKG9sZFN0YXJ0Q2hpbGQsIG5ld0VuZENoaWxkKSkge1xuICAgICAgcGF0Y2gob2xkU3RhcnRDaGlsZCwgbmV3RW5kQ2hpbGQsIG9wdGlvbnMpXG4gICAgICBwYXJlbnRFbGVtZW50Lmluc2VydEJlZm9yZShvbGRTdGFydENoaWxkLmRvbU5vZGUsIG9sZEVuZENoaWxkLmRvbU5vZGUubmV4dFNpYmxpbmcpXG4gICAgICBvbGRTdGFydENoaWxkID0gb2xkQ2hpbGRyZW5bKytvbGRTdGFydEluZGV4XVxuICAgICAgbmV3RW5kQ2hpbGQgPSBuZXdDaGlsZHJlblstLW5ld0VuZEluZGV4XVxuICAgIH0gZWxzZSBpZiAodmlydHVhbE5vZGVzQXJlRXF1YWwob2xkRW5kQ2hpbGQsIG5ld1N0YXJ0Q2hpbGQpKSB7XG4gICAgICBwYXRjaChvbGRFbmRDaGlsZCwgbmV3U3RhcnRDaGlsZCwgb3B0aW9ucylcbiAgICAgIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG9sZEVuZENoaWxkLmRvbU5vZGUsIG9sZFN0YXJ0Q2hpbGQuZG9tTm9kZSk7XG4gICAgICBvbGRFbmRDaGlsZCA9IG9sZENoaWxkcmVuWy0tb2xkRW5kSW5kZXhdXG4gICAgICBuZXdTdGFydENoaWxkID0gbmV3Q2hpbGRyZW5bKytuZXdTdGFydEluZGV4XVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIW9sZEluZGljZXNCeUtleSkgb2xkSW5kaWNlc0J5S2V5ID0gbWFwT2xkS2V5c1RvSW5kaWNlcyhvbGRDaGlsZHJlbiwgb2xkU3RhcnRJbmRleCwgb2xkRW5kSW5kZXgpXG4gICAgICBjb25zdCBrZXkgPSBnZXRLZXkobmV3U3RhcnRDaGlsZClcbiAgICAgIGNvbnN0IG9sZEluZGV4ID0ga2V5ID8gb2xkSW5kaWNlc0J5S2V5LmdldChrZXkpIDogbnVsbFxuICAgICAgaWYgKG9sZEluZGV4ID09IG51bGwpIHtcbiAgICAgICAgcGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUocmVuZGVyKG5ld1N0YXJ0Q2hpbGQsIG9wdGlvbnMpLCBvbGRTdGFydENoaWxkLmRvbU5vZGUpXG4gICAgICAgIG5ld1N0YXJ0Q2hpbGQgPSBuZXdDaGlsZHJlblsrK25ld1N0YXJ0SW5kZXhdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBvbGRDaGlsZFRvTW92ZSA9IG9sZENoaWxkcmVuW29sZEluZGV4XVxuICAgICAgICBwYXRjaChvbGRDaGlsZFRvTW92ZSwgbmV3U3RhcnRDaGlsZCwgb3B0aW9ucylcbiAgICAgICAgb2xkQ2hpbGRyZW5bb2xkSW5kZXhdID0gdW5kZWZpbmVkXG4gICAgICAgIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG9sZENoaWxkVG9Nb3ZlLmRvbU5vZGUsIG9sZFN0YXJ0Q2hpbGQuZG9tTm9kZSlcbiAgICAgICAgbmV3U3RhcnRDaGlsZCA9IG5ld0NoaWxkcmVuWysrbmV3U3RhcnRJbmRleF1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAob2xkU3RhcnRJbmRleCA+IG9sZEVuZEluZGV4KSB7XG4gICAgY29uc3Qgc3Vic2VxdWVudEVsZW1lbnQgPSBuZXdDaGlsZHJlbltuZXdFbmRJbmRleCArIDFdID8gbmV3Q2hpbGRyZW5bbmV3RW5kSW5kZXggKyAxXS5kb21Ob2RlIDogbnVsbFxuICAgIGZvciAobGV0IGkgPSBuZXdTdGFydEluZGV4OyBpIDw9IG5ld0VuZEluZGV4OyBpKyspIHtcbiAgICAgIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKHJlbmRlcihuZXdDaGlsZHJlbltpXSwgb3B0aW9ucyksIHN1YnNlcXVlbnRFbGVtZW50KVxuICAgIH1cbiAgfSBlbHNlIGlmIChuZXdTdGFydEluZGV4ID4gbmV3RW5kSW5kZXgpIHtcbiAgICBmb3IgKGxldCBpID0gb2xkU3RhcnRJbmRleDsgaSA8PSBvbGRFbmRJbmRleDsgaSsrKSB7XG4gICAgICBjb25zdCBjaGlsZCA9IG9sZENoaWxkcmVuW2ldXG4gICAgICBpZiAoY2hpbGQpIHJlbW92ZVZpcnR1YWxOb2RlKGNoaWxkLCBvcHRpb25zICYmIG9wdGlvbnMucmVmcylcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlVmlydHVhbE5vZGUgKHZpcnR1YWxOb2RlLCByZWZzLCByZW1vdmVET01Ob2RlID0gdHJ1ZSkge1xuICBjb25zdCB7ZG9tTm9kZSwgcHJvcHMsIGNoaWxkcmVuLCBjb21wb25lbnR9ID0gdmlydHVhbE5vZGVcbiAgY29uc3QgcmVmID0gcHJvcHMgJiYgcHJvcHMucmVmXG4gIGlmIChjb21wb25lbnQpIHtcbiAgICBpZiAocmVmcyAmJiByZWYgJiYgcmVmc1tyZWZdID09PSBjb21wb25lbnQpIGRlbGV0ZSByZWZzW3JlZl1cbiAgICBpZiAodHlwZW9mIGNvbXBvbmVudC5kZXN0cm95ID09PSAnZnVuY3Rpb24nKSBjb21wb25lbnQuZGVzdHJveSgpXG4gIH0gZWxzZSB7XG4gICAgaWYgKHJlZnMgJiYgcmVmICYmIHJlZnNbcmVmXSA9PT0gZG9tTm9kZSkgZGVsZXRlIHJlZnNbcmVmXVxuICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICByZW1vdmVWaXJ0dWFsTm9kZShjaGlsZHJlbltpXSwgcmVmcywgZmFsc2UpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlbW92ZURPTU5vZGUpIGRvbU5vZGUucmVtb3ZlKClcbn1cblxuZnVuY3Rpb24gdmlydHVhbE5vZGVzQXJlRXF1YWwgKG9sZFZpcnR1YWxOb2RlLCBuZXdWaXJ0dWFsTm9kZSkge1xuICByZXR1cm4gKFxuICAgIGdldEtleShvbGRWaXJ0dWFsTm9kZSkgPT09IGdldEtleShuZXdWaXJ0dWFsTm9kZSlcbiAgICAgICYmIG9sZFZpcnR1YWxOb2RlLnRhZyA9PT0gbmV3VmlydHVhbE5vZGUudGFnXG4gIClcbn1cblxuZnVuY3Rpb24gZ2V0S2V5ICh2aXJ0dWFsTm9kZSkge1xuICByZXR1cm4gdmlydHVhbE5vZGUucHJvcHMgPyB2aXJ0dWFsTm9kZS5wcm9wcy5rZXkgOiB1bmRlZmluZWRcbn1cblxuZnVuY3Rpb24gbWFwT2xkS2V5c1RvSW5kaWNlcyAoY2hpbGRyZW4sIHN0YXJ0SW5kZXgsIGVuZEluZGV4KSB7XG4gIGxldCBvbGRJbmRpY2VzQnlLZXkgPSBuZXcgTWFwKClcbiAgZm9yIChsZXQgaSA9IHN0YXJ0SW5kZXg7IGkgPD0gZW5kSW5kZXg7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IGdldEtleShjaGlsZHJlbltpXSlcbiAgICBpZiAoa2V5KSBvbGRJbmRpY2VzQnlLZXkuc2V0KGtleSwgaSlcbiAgfVxuICByZXR1cm4gb2xkSW5kaWNlc0J5S2V5XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcGF0Y2hcbiIsImNvbnN0IHVwZGF0ZVByb3BzID0gcmVxdWlyZSgnLi91cGRhdGUtcHJvcHMnKVxuY29uc3QgU1ZHX1RBR1MgPSByZXF1aXJlKCcuL3N2Zy10YWdzJylcblxuZnVuY3Rpb24gcmVuZGVyICh2aXJ0dWFsTm9kZSwgb3B0aW9ucykge1xuICBsZXQgZG9tTm9kZVxuICBpZiAodmlydHVhbE5vZGUudGV4dCAhPSBudWxsKSB7XG4gICAgZG9tTm9kZSA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHZpcnR1YWxOb2RlLnRleHQpXG4gIH0gZWxzZSB7XG4gICAgY29uc3Qge3RhZywgY2hpbGRyZW59ID0gdmlydHVhbE5vZGVcbiAgICBsZXQge3Byb3BzfSA9IHZpcnR1YWxOb2RlXG5cbiAgICBpZiAodHlwZW9mIHRhZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgbGV0IHJlZlxuICAgICAgaWYgKHByb3BzICYmIHByb3BzLnJlZikge1xuICAgICAgICByZWYgPSBwcm9wcy5yZWZcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbXBvbmVudCA9IG5ldyB0YWcocHJvcHMgfHwge30sIGNoaWxkcmVuKVxuICAgICAgdmlydHVhbE5vZGUuY29tcG9uZW50ID0gY29tcG9uZW50XG4gICAgICBkb21Ob2RlID0gY29tcG9uZW50LmVsZW1lbnRcbiAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMucmVmcyAmJiByZWYpIHtcbiAgICAgICAgb3B0aW9ucy5yZWZzW3JlZl0gPSBjb21wb25lbnRcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKFNWR19UQUdTLmhhcyh0YWcpKSB7XG4gICAgICBkb21Ob2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKTtcbiAgICAgIGlmIChjaGlsZHJlbikgYWRkQ2hpbGRyZW4oZG9tTm9kZSwgY2hpbGRyZW4sIG9wdGlvbnMpXG4gICAgICBpZiAocHJvcHMpIHVwZGF0ZVByb3BzKGRvbU5vZGUsIG51bGwsIHZpcnR1YWxOb2RlLCBvcHRpb25zKVxuICAgIH0gZWxzZSB7XG4gICAgICBkb21Ob2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWcpXG4gICAgICBpZiAoY2hpbGRyZW4pIGFkZENoaWxkcmVuKGRvbU5vZGUsIGNoaWxkcmVuLCBvcHRpb25zKVxuICAgICAgaWYgKHByb3BzKSB1cGRhdGVQcm9wcyhkb21Ob2RlLCBudWxsLCB2aXJ0dWFsTm9kZSwgb3B0aW9ucylcbiAgICB9XG4gIH1cbiAgdmlydHVhbE5vZGUuZG9tTm9kZSA9IGRvbU5vZGVcbiAgcmV0dXJuIGRvbU5vZGVcbn1cblxuZnVuY3Rpb24gYWRkQ2hpbGRyZW4gKHBhcmVudCwgY2hpbGRyZW4sIG9wdGlvbnMpIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgIHBhcmVudC5hcHBlbmRDaGlsZChyZW5kZXIoY2hpbGRyZW5baV0sIG9wdGlvbnMpKVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcmVuZGVyXG4iLCIvLyBUaGlzIGZpbGUgaW1wbGVtZW50cyBnZXR0ZXIgYW5kIHNldHRlciBmdW5jdGlvbnMgZm9yIGEgc2NoZWR1bGVyIHRvIGJlIHVzZWRcbi8vIGJ5IHRoaXMgbGlicmFyeSB3aGVuIHVwZGF0aW5nIHRoZSBET00uIFRoZSBzY2hlZHVsZXIncyBqb2IgaXMgdG8gZW5zdXJlIHRoYXRcbi8vIERPTSBpbnRlcmFjdGlvbiBpcyBwZXJmb3JtZWQgZWZmaWNpZW50bHkuIFdoZW4gdXNpbmcgYGV0Y2hgIGluIEF0b20sIHlvdVxuLy8gc2hvdWxkIHRlbGwgYGV0Y2hgIHRvIHVzZSBBdG9tJ3Mgc2NoZWR1bGVyIGJ5IGNhbGxpbmdcbi8vIGBzZXRTY2hlZHVsZXIoYXRvbS52aWV3cylgLlxuLy9cbi8vIFNjaGVkdWxlcnMgc2hvdWxkIHN1cHBvcnQgdGhlIGZvbGxvd2luZyBpbnRlcmZhY2U6XG4vLyAqIGB1cGRhdGVEb2N1bWVudChmbilgIFRoaXMgbWV0aG9kIGlzIGFzeW5jaHJvbm91cy4gSXQgZW5xdWV1ZXMgZnVuY3Rpb25zIHRvXG4vLyBiZSBleGVjdXRlZCBsYXRlci5cbi8vICogYGdldE5leHRVcGRhdGVQcm9taXNlKClgIFRoaXMgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIHByb21pc2UgdGhhdFxuLy8gcmVzb2x2ZXMgYWZ0ZXIgYWxsIHBlbmRpbmcgZG9jdW1lbnQgdXBkYXRlIGZ1bmN0aW9ucyBoYXZlIGJlZW4gaW52b2tlZC5cbi8vXG4vLyBTY2hlZHVsZXJzIGNvdWxkIHN1cHBvcnQgdGhlIGZvbGxvd2luZyBvcHRpb25hbCBtZXRob2RzLCB3aGljaCBhcmUgc3VwcG9ydGVkXG4vLyBieSBBdG9tJ3Mgc2NoZWR1bGVyLlxuLy9cbi8vICogYHJlYWREb2N1bWVudGAgVGhpcyBtZXRob2QgY2FuIGJlIGludm9rZWQgYnkgY2xpZW50cyBvdGhlciB0aGFuIGBldGNoYCB3aGVuXG4vLyBpdCBpcyBuZWNlc3NhcnkgdG8gcmVhZCBmcm9tIHRoZSBET00uIEZ1bmN0aW9ucyBlbnF1ZXVlZCB2aWEgdGhpcyBtZXRob2Rcbi8vIHNob3VsZCBub3QgYmUgcnVuIHVudGlsIGFsbCBkb2N1bWVudCB1cGRhdGUgZnVuY3Rpb25zIGhhdmUgYmVlbiBleGVjdXRlZC5cbi8vIEJhdGNoaW5nIHVwZGF0ZXMgYW5kIHJlYWRzIGluIHRoaXMgd2F5IHdpbGwgcHJldmVudCBmb3JjZWQgc3luY2hyb25vdXNcbi8vIHJlZmxvd3MuXG4vLyAqIGBwb2xsRG9jdW1lbnRgIFRoaXMgbWV0aG9kIGlzIHNpbWlsYXIgdG8gYHJlYWREb2N1bWVudGAsIGJ1dCBpdCBydW5zIHRoZVxuLy8gYXNzb2NpYXRlZCBmdW5jdGlvbnMgcmVwZWF0ZWRseS4gQWdhaW4sIHRoZXkgc2hvdWxkIGJlIHNjaGVkdWxlZCBpbiBzdWNoIGFcbi8vIHdheSBzbyBhcyB0byBhdm9pZCBzeW5jaHJvbm91cyByZWZsb3dzLlxuXG5jb25zdCBEZWZhdWx0U2NoZWR1bGVyID0gcmVxdWlyZSgnLi9kZWZhdWx0LXNjaGVkdWxlcicpXG5cbmxldCBzY2hlZHVsZXIgPSBudWxsXG5cbm1vZHVsZS5leHBvcnRzLnNldFNjaGVkdWxlciA9IGZ1bmN0aW9uIHNldFNjaGVkdWxlciAoY3VzdG9tU2NoZWR1bGVyKSB7XG4gIHNjaGVkdWxlciA9IGN1c3RvbVNjaGVkdWxlclxufVxuXG5tb2R1bGUuZXhwb3J0cy5nZXRTY2hlZHVsZXIgPSBmdW5jdGlvbiBnZXRTY2hlZHVsZXIgKCkge1xuICBpZiAoIXNjaGVkdWxlcikge1xuICAgIHNjaGVkdWxlciA9IG5ldyBEZWZhdWx0U2NoZWR1bGVyKClcbiAgfVxuICByZXR1cm4gc2NoZWR1bGVyXG59XG4iLCIvLyBCYXNlZCBvbiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBNYXAoW1xuICBbJ2FjY2VudEhlaWdodCcsICdhY2NlbnQtaGVpZ2h0J10sXG4gIFsnYWxpZ25tZW50QmFzZWxpbmUnLCAnYWxpZ25tZW50LWJhc2VsaW5lJ10sXG4gIFsnYXJhYmljRm9ybScsICdhcmFiaWMtZm9ybSddLFxuICBbJ2Jhc2VsaW5lU2hpZnQnLCAnYmFzZWxpbmUtc2hpZnQnXSxcbiAgWydjYXBIZWlnaHQnLCAnY2FwLWhlaWdodCddLFxuICBbJ2NsYXNzTmFtZScsICdjbGFzcyddLFxuICBbJ2NsaXBQYXRoJywgJ2NsaXAtcGF0aCddLFxuICBbJ2NsaXBSdWxlJywgJ2NsaXAtcnVsZSddLFxuICBbJ2NvbG9ySW50ZXJwb2xhdGlvbicsICdjb2xvci1pbnRlcnBvbGF0aW9uJ10sXG4gIFsnY29sb3JJbnRlcnBvbGF0aW9uRmlsdGVycycsICdjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnMnXSxcbiAgWydjb2xvclByb2ZpbGUnLCAnY29sb3ItcHJvZmlsZSddLFxuICBbJ2NvbG9yUmVuZGVyaW5nJywgJ2NvbG9yLXJlbmRlcmluZyddLFxuICBbJ2RvbWluYW50QmFzZWxpbmUnLCAnZG9taW5hbnQtYmFzZWxpbmUnXSxcbiAgWydlbmFibGVCYWNrZ3JvdW5kJywgJ2VuYWJsZS1iYWNrZ3JvdW5kJ10sXG4gIFsnZmlsbE9wYWNpdHknLCAnZmlsbC1vcGFjaXR5J10sXG4gIFsnZmlsbFJ1bGUnLCAnZmlsbC1ydWxlJ10sXG4gIFsnZmxvb2RDb2xvcicsICdmbG9vZC1jb2xvciddLFxuICBbJ2Zsb29kT3BhY2l0eScsICdmbG9vZC1vcGFjaXR5J10sXG4gIFsnZm9udEZhbWlseScsICdmb250LWZhbWlseSddLFxuICBbJ2ZvbnRTaXplJywgJ2ZvbnQtc2l6ZSddLFxuICBbJ2ZvbnRTaXplQWRqdXN0JywgJ2ZvbnQtc2l6ZS1hZGp1c3QnXSxcbiAgWydmb250U3RyZXRjaCcsICdmb250LXN0cmV0Y2gnXSxcbiAgWydmb250U3R5bGUnLCAnZm9udC1zdHlsZSddLFxuICBbJ2ZvbnRWYXJpYW50JywgJ2ZvbnQtdmFyaWFudCddLFxuICBbJ2ZvbnRXZWlnaHQnLCAnZm9udC13ZWlnaHQnXSxcbiAgWydnbHlwaE5hbWUnLCAnZ2x5cGgtbmFtZSddLFxuICBbJ2dseXBoT3JpZW50YXRpb25Ib3Jpem9udGFsJywgJ2dseXBoLW9yaWVudGF0aW9uLWhvcml6b250YWwnXSxcbiAgWydnbHlwaE9yaWVudGF0aW9uVmVydGljYWwnLCAnZ2x5cGgtb3JpZW50YXRpb24tdmVydGljYWwnXSxcbiAgWydob3JpekFkdlgnLCAnaG9yaXotYWR2LXgnXSxcbiAgWydob3Jpek9yaWdpblgnLCAnaG9yaXotb3JpZ2luLXgnXSxcbiAgWydsZXR0ZXJTcGFjaW5nJywgJ2xldHRlci1zcGFjaW5nJ10sXG4gIFsnbGlnaHRpbmdDb2xvcicsICdsaWdodGluZy1jb2xvciddLFxuICBbJ21hcmtlckVuZCcsICdtYXJrZXItZW5kJ10sXG4gIFsnbWFya2VyTWlkJywgJ21hcmtlci1taWQnXSxcbiAgWydtYXJrZXJTdGFydCcsICdtYXJrZXItc3RhcnQnXSxcbiAgWydvdmVybGluZVBvc2l0aW9uJywgJ292ZXJsaW5lLXBvc2l0aW9uJ10sXG4gIFsnb3ZlcmxpbmVUaGlja25lc3MnLCAnb3ZlcmxpbmUtdGhpY2tuZXNzJ10sXG4gIFsncGFub3NlMScsICdwYW5vc2UtMSddLFxuICBbJ3BhaW50T3JkZXInLCAncGFpbnQtb3JkZXInXSxcbiAgWydwb2ludGVyRXZlbnRzJywgJ3BvaW50ZXItZXZlbnRzJ10sXG4gIFsncmVuZGVyaW5nSW50ZW50JywgJ3JlbmRlcmluZy1pbnRlbnQnXSxcbiAgWydzaGFwZVJlbmRlcmluZycsICdzaGFwZS1yZW5kZXJpbmcnXSxcbiAgWydzdG9wQ29sb3InLCAnc3RvcC1jb2xvciddLFxuICBbJ3N0b3BPcGFjaXR5JywgJ3N0b3Atb3BhY2l0eSddLFxuICBbJ3N0cmlrZXRocm91Z2hQb3NpdGlvbicsICdzdHJpa2V0aHJvdWdoLXBvc2l0aW9uJ10sXG4gIFsnc3RyaWtldGhyb3VnaFRoaWNrbmVzcycsICdzdHJpa2V0aHJvdWdoLXRoaWNrbmVzcyddLFxuICBbJ3N0cm9rZURhc2hhcnJheScsICdzdHJva2UtZGFzaGFycmF5J10sXG4gIFsnc3Ryb2tlRGFzaG9mZnNldCcsICdzdHJva2UtZGFzaG9mZnNldCddLFxuICBbJ3N0cm9rZUxpbmVjYXAnLCAnc3Ryb2tlLWxpbmVjYXAnXSxcbiAgWydzdHJva2VMaW5lam9pbicsICdzdHJva2UtbGluZWpvaW4nXSxcbiAgWydzdHJva2VNaXRlcmxpbWl0JywgJ3N0cm9rZS1taXRlcmxpbWl0J10sXG4gIFsnc3Ryb2tlT3BhY2l0eScsICdzdHJva2Utb3BhY2l0eSddLFxuICBbJ3N0cm9rZVdpZHRoJywgJ3N0cm9rZS13aWR0aCddLFxuICBbJ3RleHRBbmNob3InLCAndGV4dC1hbmNob3InXSxcbiAgWyd0ZXh0RGVjb3JhdGlvbicsICd0ZXh0LWRlY29yYXRpb24nXSxcbiAgWyd0ZXh0UmVuZGVyaW5nJywgJ3RleHQtcmVuZGVyaW5nJ10sXG4gIFsndW5kZXJsaW5lUG9zaXRpb24nLCAndW5kZXJsaW5lLXBvc2l0aW9uJ10sXG4gIFsndW5kZXJsaW5lVGhpY2tuZXNzJywgJ3VuZGVybGluZS10aGlja25lc3MnXSxcbiAgWyd1bmljb2RlQmlkaScsICd1bmljb2RlLWJpZGknXSxcbiAgWyd1bmljb2RlUmFuZ2UnLCAndW5pY29kZS1yYW5nZSddLFxuICBbJ3VuaXRzUGVyRW0nLCAndW5pdHMtcGVyLWVtJ10sXG4gIFsndkFscGhhYmV0aWMnLCAndi1hbHBoYWJldGljJ10sXG4gIFsndkhhbmdpbmcnLCAndi1oYW5naW5nJ10sXG4gIFsndklkZW9ncmFwaGljJywgJ3YtaWRlb2dyYXBoaWMnXSxcbiAgWyd2TWF0aGVtYXRpY2FsJywgJ3YtbWF0aGVtYXRpY2FsJ10sXG4gIFsndmVydEFkdlknLCAndmVydC1hZHYteSddLFxuICBbJ3ZlcnRPcmlnaW5YJywgJ3ZlcnQtb3JpZ2luLXgnXSxcbiAgWyd2ZXJ0T3JpZ2luWScsICd2ZXJ0LW9yaWdpbi15J10sXG4gIFsnd29yZFNwYWNpbmcnLCAnd29yZC1zcGFjaW5nJ10sXG4gIFsnd3JpdGluZ01vZGUnLCAnd3JpdGluZy1tb2RlJ10sXG4gIFsneEhlaWdodCcsICd4LWhlaWdodCddLFxuXSlcbiIsIi8vIHRha2VuIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlYWN0L2Jsb2IvNjdmODUyNGU4OGFiYmYxYWMwZmQ4NmQzOGEwNDc3ZDExZmJjN2IzZS9zcmMvaXNvbW9ycGhpYy9jbGFzc2ljL2VsZW1lbnQvUmVhY3RET01GYWN0b3JpZXMuanMjTDE1M1xubW9kdWxlLmV4cG9ydHMgPSBuZXcgU2V0KFtcbiAgJ2NpcmNsZScsXG4gICdjbGlwUGF0aCcsXG4gICdkZWZzJyxcbiAgJ2VsbGlwc2UnLFxuICAnZycsXG4gICdpbWFnZScsXG4gICdsaW5lJyxcbiAgJ2xpbmVhckdyYWRpZW50JyxcbiAgJ21hc2snLFxuICAncGF0aCcsXG4gICdwYXR0ZXJuJyxcbiAgJ3BvbHlnb24nLFxuICAncG9seWxpbmUnLFxuICAncmFkaWFsR3JhZGllbnQnLFxuICAncmVjdCcsXG4gICdzdG9wJyxcbiAgJ3N2ZycsXG4gICd0ZXh0JyxcbiAgJ3RzcGFuJ1xuXSlcbiIsImNvbnN0IEVWRU5UX0xJU1RFTkVSX1BST1BTID0gcmVxdWlyZSgnLi9ldmVudC1saXN0ZW5lci1wcm9wcycpXG5jb25zdCBTVkdfVEFHUyA9IHJlcXVpcmUoJy4vc3ZnLXRhZ3MnKVxuY29uc3QgU1ZHX0FUVFJJQlVURV9UUkFOU0xBVElPTlMgPSByZXF1aXJlKCcuL3N2Zy1hdHRyaWJ1dGUtdHJhbnNsYXRpb25zJylcbmNvbnN0IEVNUFRZID0gJydcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZG9tTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBvcHRpb25zKSB7XG4gIGNvbnN0IG9sZFByb3BzID0gb2xkVmlydHVhbE5vZGUgJiYgb2xkVmlydHVhbE5vZGUucHJvcHNcbiAgY29uc3QgbmV3UHJvcHMgPSBuZXdWaXJ0dWFsTm9kZS5wcm9wc1xuXG4gIGxldCByZWZzLCBsaXN0ZW5lckNvbnRleHRcbiAgaWYgKG9wdGlvbnMpIHtcbiAgICByZWZzID0gb3B0aW9ucy5yZWZzXG4gICAgbGlzdGVuZXJDb250ZXh0ID0gb3B0aW9ucy5saXN0ZW5lckNvbnRleHRcbiAgfVxuICB1cGRhdGVQcm9wcyhkb21Ob2RlLCBvbGRWaXJ0dWFsTm9kZSwgb2xkUHJvcHMsIG5ld1ZpcnR1YWxOb2RlLCBuZXdQcm9wcylcbiAgaWYgKHJlZnMpIHVwZGF0ZVJlZihkb21Ob2RlLCBvbGRQcm9wcyAmJiBvbGRQcm9wcy5yZWYsIG5ld1Byb3BzICYmIG5ld1Byb3BzLnJlZiwgcmVmcylcbiAgdXBkYXRlRXZlbnRMaXN0ZW5lcnMoZG9tTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBsaXN0ZW5lckNvbnRleHQpXG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVByb3BzIChkb21Ob2RlLCBvbGRWaXJ0dWFsTm9kZSwgb2xkUHJvcHMsIG5ld1ZpcnR1YWxOb2RlLCBuZXdQcm9wcykge1xuICBpZiAob2xkUHJvcHMpIHtcbiAgICBjb25zdCBvbGRQcm9wc05hbWVzID0gT2JqZWN0LmtleXMob2xkUHJvcHMpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRQcm9wc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBuYW1lID0gb2xkUHJvcHNOYW1lc1tpXVxuICAgICAgaWYgKG5hbWUgPT09ICdyZWYnIHx8IG5hbWUgPT09ICdvbicpIGNvbnRpbnVlXG4gICAgICBpZiAobmFtZSBpbiBFVkVOVF9MSVNURU5FUl9QUk9QUykgY29udGludWVcbiAgICAgIGlmICghbmV3UHJvcHMgfHwgIShuYW1lIGluIG5ld1Byb3BzKSkge1xuICAgICAgICBpZiAobmFtZSA9PT0gJ2RhdGFzZXQnKSB7XG4gICAgICAgICAgdXBkYXRlUHJvcHMoZG9tTm9kZS5kYXRhc2V0LCBudWxsLCBvbGRQcm9wcyAmJiBvbGRQcm9wcy5kYXRhc2V0LCBudWxsLCBudWxsKVxuICAgICAgICB9IGVsc2UgaWYgKG5hbWUgIT09ICdpbm5lckhUTUwnICYmIG9sZFZpcnR1YWxOb2RlICYmIFNWR19UQUdTLmhhcyhvbGRWaXJ0dWFsTm9kZS50YWcpKSB7XG4gICAgICAgICAgZG9tTm9kZS5yZW1vdmVBdHRyaWJ1dGUoU1ZHX0FUVFJJQlVURV9UUkFOU0xBVElPTlMuZ2V0KG5hbWUpIHx8IG5hbWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gQ2xlYXIgcHJvcGVydHkgZm9yIG9iamVjdHMgdGhhdCBkb24ndCBzdXBwb3J0IGRlbGV0aW9uIChlLmcuIHN0eWxlXG4gICAgICAgICAgLy8gb3IgY2xhc3NOYW1lKS4gSWYgd2UgdXNlZCBudWxsIGluc3RlYWQgb2YgYW4gZW1wdHkgc3RyaW5nLCB0aGUgRE9NXG4gICAgICAgICAgLy8gY291bGQgc29tZXRpbWVzIHN0cmluZ2lmeSB0aGUgdmFsdWUgYW5kIG1pc3Rha2VubHkgYXNzaWduICdudWxsJy5cbiAgICAgICAgICBkb21Ob2RlW25hbWVdID0gRU1QVFlcbiAgICAgICAgICBkZWxldGUgZG9tTm9kZVtuYW1lXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld1Byb3BzKSB7XG4gICAgY29uc3QgbmV3UHJvcHNOYW1lcyA9IE9iamVjdC5rZXlzKG5ld1Byb3BzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3UHJvcHNOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbmFtZSA9IG5ld1Byb3BzTmFtZXNbaV1cbiAgICAgIGlmIChuYW1lID09PSAncmVmJyB8fCBuYW1lID09PSAnb24nKSBjb250aW51ZVxuICAgICAgaWYgKG5hbWUgaW4gRVZFTlRfTElTVEVORVJfUFJPUFMpIGNvbnRpbnVlXG4gICAgICBjb25zdCBvbGRWYWx1ZSA9IG9sZFByb3BzICYmIG9sZFByb3BzW25hbWVdXG4gICAgICBjb25zdCBuZXdWYWx1ZSA9IG5ld1Byb3BzW25hbWVdXG4gICAgICBpZiAobmFtZSA9PT0gJ2RhdGFzZXQnKSB7XG4gICAgICAgIHVwZGF0ZU5lc3RlZFByb3BzKGRvbU5vZGUuZGF0YXNldCwgb2xkVmFsdWUsIG5ld1ZhbHVlLCBmYWxzZSlcbiAgICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3N0eWxlJyAmJiB0eXBlb2YgbmV3VmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGxldCBvbGRQcm9wcyA9IG9sZFZhbHVlXG4gICAgICAgIGlmICh0eXBlb2Ygb2xkUHJvcHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgZG9tTm9kZS5zdHlsZSA9ICcnXG4gICAgICAgICAgb2xkUHJvcHMgPSBudWxsXG4gICAgICAgIH1cbiAgICAgICAgdXBkYXRlTmVzdGVkUHJvcHMoZG9tTm9kZS5zdHlsZSwgb2xkUHJvcHMsIG5ld1ZhbHVlLCB0cnVlKVxuICAgICAgfSBlbHNlIGlmIChuYW1lID09PSAnYXR0cmlidXRlcycpIHtcbiAgICAgICAgdXBkYXRlQXR0cmlidXRlcyhkb21Ob2RlLCBvbGRWYWx1ZSwgbmV3VmFsdWUpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAobmV3VmFsdWUgIT09IG9sZFZhbHVlKSB7XG4gICAgICAgICAgaWYgKG5hbWUgIT09ICdpbm5lckhUTUwnICYmIG5ld1ZpcnR1YWxOb2RlICYmIFNWR19UQUdTLmhhcyhuZXdWaXJ0dWFsTm9kZS50YWcpKSB7XG4gICAgICAgICAgICBkb21Ob2RlLnNldEF0dHJpYnV0ZShTVkdfQVRUUklCVVRFX1RSQU5TTEFUSU9OUy5nZXQobmFtZSkgfHwgbmFtZSwgbmV3VmFsdWUpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRvbU5vZGVbbmFtZV0gPSBuZXdWYWx1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVOZXN0ZWRQcm9wcyAoZG9tUHJvcHMsIG9sZFByb3BzLCBuZXdQcm9wcywgaXNTdHlsZU9iamVjdCkge1xuICBpZiAob2xkUHJvcHMpIHtcbiAgICBjb25zdCBvbGRQcm9wc05hbWVzID0gT2JqZWN0LmtleXMob2xkUHJvcHMpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvbGRQcm9wc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBuYW1lID0gb2xkUHJvcHNOYW1lc1tpXVxuICAgICAgaWYgKCFuZXdQcm9wcyB8fCAhKG5hbWUgaW4gbmV3UHJvcHMpKSB7XG4gICAgICAgIGlmIChpc1N0eWxlT2JqZWN0KSB7XG4gICAgICAgICAgZG9tUHJvcHNbbmFtZV0gPSBFTVBUWVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBkb21Qcm9wc1tuYW1lXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld1Byb3BzKSB7XG4gICAgY29uc3QgbmV3UHJvcHNOYW1lcyA9IE9iamVjdC5rZXlzKG5ld1Byb3BzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3UHJvcHNOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbmFtZSA9IG5ld1Byb3BzTmFtZXNbaV1cbiAgICAgIGNvbnN0IG9sZFZhbHVlID0gb2xkUHJvcHMgJiYgb2xkUHJvcHNbbmFtZV1cbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gbmV3UHJvcHNbbmFtZV1cbiAgICAgIGlmIChuZXdWYWx1ZSAhPT0gb2xkVmFsdWUpIHtcbiAgICAgICAgZG9tUHJvcHNbbmFtZV0gPSBuZXdWYWx1ZVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVBdHRyaWJ1dGVzIChkb21Ob2RlLCBvbGRBdHRyaWJ1dGVzLCBuZXdBdHRyaWJ1dGVzKSB7XG4gIGlmIChvbGRBdHRyaWJ1dGVzKSB7XG4gICAgY29uc3Qgb2xkQXR0cmlidXRlTmFtZXMgPSBPYmplY3Qua2V5cyhvbGRBdHRyaWJ1dGVzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2xkQXR0cmlidXRlTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5hbWUgPSBvbGRBdHRyaWJ1dGVOYW1lc1tpXVxuICAgICAgaWYgKCFuZXdBdHRyaWJ1dGVzIHx8ICEobmFtZSBpbiBuZXdBdHRyaWJ1dGVzKSkge1xuICAgICAgICBkb21Ob2RlLnJlbW92ZUF0dHJpYnV0ZShuYW1lKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChuZXdBdHRyaWJ1dGVzKSB7XG4gICAgY29uc3QgbmV3QXR0cmlidXRlTmFtZXMgPSBPYmplY3Qua2V5cyhuZXdBdHRyaWJ1dGVzKVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbmV3QXR0cmlidXRlTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5hbWUgPSBuZXdBdHRyaWJ1dGVOYW1lc1tpXVxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBvbGRBdHRyaWJ1dGVzICYmIG9sZEF0dHJpYnV0ZXNbbmFtZV1cbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gbmV3QXR0cmlidXRlc1tuYW1lXVxuICAgICAgaWYgKG5ld1ZhbHVlICE9PSBvbGRWYWx1ZSkge1xuICAgICAgICBkb21Ob2RlLnNldEF0dHJpYnV0ZShuYW1lLCBuZXdWYWx1ZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlUmVmIChkb21Ob2RlLCBvbGRSZWZOYW1lLCBuZXdSZWZOYW1lLCByZWZzKSB7XG4gIGlmIChuZXdSZWZOYW1lICE9PSBvbGRSZWZOYW1lKSB7XG4gICAgaWYgKG9sZFJlZk5hbWUgJiYgcmVmc1tvbGRSZWZOYW1lXSA9PT0gZG9tTm9kZSkgZGVsZXRlIHJlZnNbb2xkUmVmTmFtZV1cbiAgICBpZiAobmV3UmVmTmFtZSkgcmVmc1tuZXdSZWZOYW1lXSA9IGRvbU5vZGVcbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVFdmVudExpc3RlbmVycyAoZG9tTm9kZSwgb2xkVmlydHVhbE5vZGUsIG5ld1ZpcnR1YWxOb2RlLCBsaXN0ZW5lckNvbnRleHQpIHtcbiAgY29uc3Qgb2xkTGlzdGVuZXJzID0gb2xkVmlydHVhbE5vZGUgJiYgb2xkVmlydHVhbE5vZGUucHJvcHMgJiYgb2xkVmlydHVhbE5vZGUucHJvcHMub25cbiAgY29uc3QgbmV3TGlzdGVuZXJzID0gbmV3VmlydHVhbE5vZGUucHJvcHMgJiYgbmV3VmlydHVhbE5vZGUucHJvcHMub25cblxuICBmb3IgKGNvbnN0IGV2ZW50TmFtZSBpbiBvbGRMaXN0ZW5lcnMpIHtcbiAgICBpZiAoIShuZXdMaXN0ZW5lcnMgJiYgZXZlbnROYW1lIGluIG5ld0xpc3RlbmVycykpIHtcbiAgICAgIGxldCBsaXN0ZW5lclRvUmVtb3ZlXG4gICAgICBpZiAob2xkVmlydHVhbE5vZGUgJiYgb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnMgJiYgb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xuICAgICAgICBsaXN0ZW5lclRvUmVtb3ZlID0gb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGlzdGVuZXJUb1JlbW92ZSA9b2xkTGlzdGVuZXJzW2V2ZW50TmFtZV1cbiAgICAgIH1cbiAgICAgIGRvbU5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyVG9SZW1vdmUpXG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBldmVudE5hbWUgaW4gbmV3TGlzdGVuZXJzKSB7XG4gICAgY29uc3Qgb2xkTGlzdGVuZXIgPSBvbGRMaXN0ZW5lcnMgJiYgb2xkTGlzdGVuZXJzW2V2ZW50TmFtZV1cbiAgICBjb25zdCBuZXdMaXN0ZW5lciA9IG5ld0xpc3RlbmVyc1tldmVudE5hbWVdXG5cbiAgICBpZiAobmV3TGlzdGVuZXIgIT09IG9sZExpc3RlbmVyKSB7XG4gICAgICBpZiAob2xkTGlzdGVuZXIpIHtcbiAgICAgICAgbGV0IGxpc3RlbmVyVG9SZW1vdmVcbiAgICAgICAgaWYgKG9sZFZpcnR1YWxOb2RlICYmIG9sZFZpcnR1YWxOb2RlLmJvdW5kTGlzdGVuZXJzICYmIG9sZFZpcnR1YWxOb2RlLmJvdW5kTGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcbiAgICAgICAgICBsaXN0ZW5lclRvUmVtb3ZlID0gb2xkVmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxpc3RlbmVyVG9SZW1vdmUgPSBvbGRMaXN0ZW5lclxuICAgICAgICB9XG4gICAgICAgIGRvbU5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyVG9SZW1vdmUpXG4gICAgICB9XG4gICAgICBsZXQgbGlzdGVuZXJUb0FkZFxuICAgICAgaWYgKGxpc3RlbmVyQ29udGV4dCkge1xuICAgICAgICBsaXN0ZW5lclRvQWRkID0gbmV3TGlzdGVuZXIuYmluZChsaXN0ZW5lckNvbnRleHQpXG4gICAgICAgIGlmICghbmV3VmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnMpIG5ld1ZpcnR1YWxOb2RlLmJvdW5kTGlzdGVuZXJzID0ge31cbiAgICAgICAgbmV3VmlydHVhbE5vZGUuYm91bmRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGxpc3RlbmVyVG9BZGRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxpc3RlbmVyVG9BZGQgPSBuZXdMaXN0ZW5lclxuICAgICAgfVxuICAgICAgZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXJUb0FkZClcbiAgICB9XG4gIH1cbn1cbiIsImNvbnN0IGRvbSA9IHJlcXVpcmUoJy4vZG9tJylcbmNvbnN0IHJlbmRlciA9IHJlcXVpcmUoJy4vcmVuZGVyJylcbmNvbnN0IHtpbml0aWFsaXplLCB1cGRhdGUsIHVwZGF0ZVN5bmMsIGRlc3Ryb3ksIGRlc3Ryb3lTeW5jfSA9IHJlcXVpcmUoJy4vY29tcG9uZW50LWhlbHBlcnMnKVxuY29uc3Qge3NldFNjaGVkdWxlciwgZ2V0U2NoZWR1bGVyfSA9IHJlcXVpcmUoJy4vc2NoZWR1bGVyLWFzc2lnbm1lbnQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZG9tLCByZW5kZXIsXG4gIGluaXRpYWxpemUsIHVwZGF0ZSwgdXBkYXRlU3luYywgZGVzdHJveSwgZGVzdHJveVN5bmMsXG4gIHNldFNjaGVkdWxlciwgZ2V0U2NoZWR1bGVyXG59XG4iXX0= | |
const etch = require('etch') | |
function toHTMLElement(vdom) { | |
const component = { | |
update() { /* noop */ }, | |
render () { return vdom } | |
} | |
etch.initialize(component) | |
return component.element | |
} | |
const domElement = toHTMLElement(etch.dom.div(null, etch.dom.span(null, 'Hello!'))) | |
document.body.appendChild(domElement) | |
;}, 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": { | |
"etch": "0.11.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