UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

485 lines (385 loc) 43.8 kB
var _a; import { assert, Stack, symbol } from '@glimmer/util'; import { clear, ConcreteBounds, CursorImpl, SingleNodeBounds } from '../bounds'; import { destroy, registerDestructor } from '@glimmer/destroyable'; import { dynamicAttribute } from './attributes/dynamic'; class First { constructor(node) { this.node = node; } firstNode() { return this.node; } } class Last { constructor(node) { this.node = node; } lastNode() { return this.node; } } export class Fragment { constructor(bounds) { this.bounds = bounds; } parentElement() { return this.bounds.parentElement(); } firstNode() { return this.bounds.firstNode(); } lastNode() { return this.bounds.lastNode(); } } export const CURSOR_STACK = symbol('CURSOR_STACK'); export class NewElementBuilder { constructor(env, parentNode, nextSibling) { this.constructing = null; this.operations = null; this[_a] = new Stack(); this.modifierStack = new Stack(); this.blockStack = new Stack(); this.pushElement(parentNode, nextSibling); this.env = env; this.dom = env.getAppendOperations(); this.updateOperations = env.getDOM(); } static forInitialRender(env, cursor) { return new this(env, cursor.element, cursor.nextSibling).initialize(); } static resume(env, block) { let parentNode = block.parentElement(); let nextSibling = block.reset(env); let stack = new this(env, parentNode, nextSibling).initialize(); stack.pushLiveBlock(block); return stack; } initialize() { this.pushSimpleBlock(); return this; } debugBlocks() { return this.blockStack.toArray(); } get element() { return this[CURSOR_STACK].current.element; } get nextSibling() { return this[CURSOR_STACK].current.nextSibling; } get hasBlocks() { return this.blockStack.size > 0; } block() { return this.blockStack.current; } popElement() { this[CURSOR_STACK].pop(); this[CURSOR_STACK].current; } pushSimpleBlock() { return this.pushLiveBlock(new SimpleLiveBlock(this.element)); } pushUpdatableBlock() { return this.pushLiveBlock(new UpdatableBlockImpl(this.element)); } pushBlockList(list) { return this.pushLiveBlock(new LiveBlockList(this.element, list)); } pushLiveBlock(block, isRemote = false) { let current = this.blockStack.current; if (current !== null) { if (!isRemote) { current.didAppendBounds(block); } } this.__openBlock(); this.blockStack.push(block); return block; } popBlock() { this.block().finalize(this); this.__closeBlock(); return this.blockStack.pop(); } __openBlock() {} __closeBlock() {} // todo return seems unused openElement(tag) { let element = this.__openElement(tag); this.constructing = element; return element; } __openElement(tag) { return this.dom.createElement(tag, this.element); } flushElement(modifiers) { let parent = this.element; let element = this.constructing; this.__flushElement(parent, element); this.constructing = null; this.operations = null; this.pushModifiers(modifiers); this.pushElement(element, null); this.didOpenElement(element); } __flushElement(parent, constructing) { this.dom.insertBefore(parent, constructing, this.nextSibling); } closeElement() { this.willCloseElement(); this.popElement(); return this.popModifiers(); } pushRemoteElement(element, guid, insertBefore) { return this.__pushRemoteElement(element, guid, insertBefore); } __pushRemoteElement(element, _guid, insertBefore) { this.pushElement(element, insertBefore); if (insertBefore === undefined) { while (element.lastChild) { element.removeChild(element.lastChild); } } let block = new RemoteLiveBlock(element); return this.pushLiveBlock(block, true); } popRemoteElement() { this.popBlock(); this.popElement(); } pushElement(element, nextSibling = null) { this[CURSOR_STACK].push(new CursorImpl(element, nextSibling)); } pushModifiers(modifiers) { this.modifierStack.push(modifiers); } popModifiers() { return this.modifierStack.pop(); } didAppendBounds(bounds) { this.block().didAppendBounds(bounds); return bounds; } didAppendNode(node) { this.block().didAppendNode(node); return node; } didOpenElement(element) { this.block().openElement(element); return element; } willCloseElement() { this.block().closeElement(); } appendText(string) { return this.didAppendNode(this.__appendText(string)); } __appendText(text) { let { dom, element, nextSibling } = this; let node = dom.createTextNode(text); dom.insertBefore(element, node, nextSibling); return node; } __appendNode(node) { this.dom.insertBefore(this.element, node, this.nextSibling); return node; } __appendFragment(fragment) { let first = fragment.firstChild; if (first) { let ret = new ConcreteBounds(this.element, first, fragment.lastChild); this.dom.insertBefore(this.element, fragment, this.nextSibling); return ret; } else { return new SingleNodeBounds(this.element, this.__appendComment('')); } } __appendHTML(html) { return this.dom.insertHTMLBefore(this.element, this.nextSibling, html); } appendDynamicHTML(value) { let bounds = this.trustedContent(value); this.didAppendBounds(bounds); } appendDynamicText(value) { let node = this.untrustedContent(value); this.didAppendNode(node); return node; } appendDynamicFragment(value) { let bounds = this.__appendFragment(value); this.didAppendBounds(bounds); } appendDynamicNode(value) { let node = this.__appendNode(value); let bounds = new SingleNodeBounds(this.element, node); this.didAppendBounds(bounds); } trustedContent(value) { return this.__appendHTML(value); } untrustedContent(value) { return this.__appendText(value); } appendComment(string) { return this.didAppendNode(this.__appendComment(string)); } __appendComment(string) { let { dom, element, nextSibling } = this; let node = dom.createComment(string); dom.insertBefore(element, node, nextSibling); return node; } __setAttribute(name, value, namespace) { this.dom.setAttribute(this.constructing, name, value, namespace); } __setProperty(name, value) { this.constructing[name] = value; } setStaticAttribute(name, value, namespace) { this.__setAttribute(name, value, namespace); } setDynamicAttribute(name, value, trusting, namespace) { let element = this.constructing; let attribute = dynamicAttribute(element, name, namespace, trusting); attribute.set(this, value, this.env); return attribute; } } _a = CURSOR_STACK; export class SimpleLiveBlock { constructor(parent) { this.parent = parent; this.first = null; this.last = null; this.nesting = 0; } parentElement() { return this.parent; } firstNode() { let first = this.first; return first.firstNode(); } lastNode() { let last = this.last; return last.lastNode(); } openElement(element) { this.didAppendNode(element); this.nesting++; } closeElement() { this.nesting--; } didAppendNode(node) { if (this.nesting !== 0) return; if (!this.first) { this.first = new First(node); } this.last = new Last(node); } didAppendBounds(bounds) { if (this.nesting !== 0) return; if (!this.first) { this.first = bounds; } this.last = bounds; } finalize(stack) { if (this.first === null) { stack.appendComment(''); } } } export class RemoteLiveBlock extends SimpleLiveBlock { constructor(parent) { super(parent); registerDestructor(this, () => { // In general, you only need to clear the root of a hierarchy, and should never // need to clear any child nodes. This is an important constraint that gives us // a strong guarantee that clearing a subtree is a single DOM operation. // // Because remote blocks are not normally physically nested inside of the tree // that they are logically nested inside, we manually clear remote blocks when // a logical parent is cleared. // // HOWEVER, it is currently possible for a remote block to be physically nested // inside of the block it is logically contained inside of. This happens when // the remote block is appended to the end of the application's entire element. // // The problem with that scenario is that Glimmer believes that it owns more of // the DOM than it actually does. The code is attempting to write past the end // of the Glimmer-managed root, but Glimmer isn't aware of that. // // The correct solution to that problem is for Glimmer to be aware of the end // of the bounds that it owns, and once we make that change, this check could // be removed. // // For now, a more targeted fix is to check whether the node was already removed // and avoid clearing the node if it was. In most cases this shouldn't happen, // so this might hide bugs where the code clears nested nodes unnecessarily, // so we should eventually try to do the correct fix. if (this.parentElement() === this.firstNode().parentNode) { clear(this); } }); } } export class UpdatableBlockImpl extends SimpleLiveBlock { reset() { destroy(this); let nextSibling = clear(this); this.first = null; this.last = null; this.nesting = 0; return nextSibling; } } // FIXME: All the noops in here indicate a modelling problem export class LiveBlockList { constructor(parent, boundList) { this.parent = parent; this.boundList = boundList; this.parent = parent; this.boundList = boundList; } parentElement() { return this.parent; } firstNode() { let head = this.boundList[0]; return head.firstNode(); } lastNode() { let boundList = this.boundList; let tail = boundList[boundList.length - 1]; return tail.lastNode(); } openElement(_element) { (false && assert(false, 'Cannot openElement directly inside a block list')); } closeElement() { (false && assert(false, 'Cannot closeElement directly inside a block list')); } didAppendNode(_node) { (false && assert(false, 'Cannot create a new node directly inside a block list')); } didAppendBounds(_bounds) {} finalize(_stack) { (false && assert(this.boundList.length > 0, 'boundsList cannot be empty')); } } export function clientBuilder(env, cursor) { return NewElementBuilder.forInitialRender(env, cursor); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL2VsZW1lbnQtYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWVBLFNBQVMsTUFBVCxFQUF5QixLQUF6QixFQUFnQyxNQUFoQyxRQUE4QyxlQUE5QztBQVNBLFNBQVMsS0FBVCxFQUFnQixjQUFoQixFQUFnQyxVQUFoQyxFQUE0QyxnQkFBNUMsUUFBb0UsV0FBcEU7QUFDQSxTQUFTLE9BQVQsRUFBa0Isa0JBQWxCLFFBQTRDLHNCQUE1QztBQUNBLFNBQTJCLGdCQUEzQixRQUFtRCxzQkFBbkQ7O0FBVUEsTUFBTSxLQUFOLENBQVc7QUFDVCxFQUFBLFdBQUEsQ0FBb0IsSUFBcEIsRUFBb0M7QUFBaEIsU0FBQSxJQUFBLEdBQUEsSUFBQTtBQUFvQjs7QUFFeEMsRUFBQSxTQUFTLEdBQUE7QUFDUCxXQUFPLEtBQUssSUFBWjtBQUNEOztBQUxROztBQVFYLE1BQU0sSUFBTixDQUFVO0FBQ1IsRUFBQSxXQUFBLENBQW9CLElBQXBCLEVBQW9DO0FBQWhCLFNBQUEsSUFBQSxHQUFBLElBQUE7QUFBb0I7O0FBRXhDLEVBQUEsUUFBUSxHQUFBO0FBQ04sV0FBTyxLQUFLLElBQVo7QUFDRDs7QUFMTzs7QUFRVixPQUFNLE1BQU8sUUFBUCxDQUFlO0FBR25CLEVBQUEsV0FBQSxDQUFZLE1BQVosRUFBMEI7QUFDeEIsU0FBSyxNQUFMLEdBQWMsTUFBZDtBQUNEOztBQUVELEVBQUEsYUFBYSxHQUFBO0FBQ1gsV0FBTyxLQUFLLE1BQUwsQ0FBWSxhQUFaLEVBQVA7QUFDRDs7QUFFRCxFQUFBLFNBQVMsR0FBQTtBQUNQLFdBQU8sS0FBSyxNQUFMLENBQVksU0FBWixFQUFQO0FBQ0Q7O0FBRUQsRUFBQSxRQUFRLEdBQUE7QUFDTixXQUFPLEtBQUssTUFBTCxDQUFZLFFBQVosRUFBUDtBQUNEOztBQWpCa0I7QUFvQnJCLE9BQU8sTUFBTSxZQUFZLEdBQXNCLE1BQU0sQ0FB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QUFpQixDQUFDLGdCQUFsQixDQUFtQyxHQUFuQyxFQUF3QyxNQUF4QyxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBCb3VuZHMsXG4gIEN1cnNvcixcbiAgQ3Vyc29yU3RhY2tTeW1ib2wsXG4gIEVsZW1lbnRCdWlsZGVyLFxuICBFbGVtZW50T3BlcmF0aW9ucyxcbiAgRW52aXJvbm1lbnQsXG4gIEdsaW1tZXJUcmVlQ2hhbmdlcyxcbiAgR2xpbW1lclRyZWVDb25zdHJ1Y3Rpb24sXG4gIExpdmVCbG9jayxcbiAgTWF5YmUsXG4gIE9wdGlvbixcbiAgVXBkYXRhYmxlQmxvY2ssXG4gIE1vZGlmaWVySW5zdGFuY2UsXG59IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgYXNzZXJ0LCBleHBlY3QsIFN0YWNrLCBzeW1ib2wgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7XG4gIEF0dHJOYW1lc3BhY2UsXG4gIFNpbXBsZUNvbW1lbnQsXG4gIFNpbXBsZURvY3VtZW50RnJhZ21lbnQsXG4gIFNpbXBsZUVsZW1lbnQsXG4gIFNpbXBsZU5vZGUsXG4gIFNpbXBsZVRleHQsXG59IGZyb20gJ0BzaW1wbGUtZG9tL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBjbGVhciwgQ29uY3JldGVCb3VuZHMsIEN1cnNvckltcGwsIFNpbmdsZU5vZGVCb3VuZHMgfSBmcm9tICcuLi9ib3VuZHMnO1xuaW1wb3J0IHsgZGVzdHJveSwgcmVnaXN0ZXJEZXN0cnVjdG9yIH0gZnJvbSAnQGdsaW1tZXIvZGVzdHJveWFibGUnO1xuaW1wb3J0IHsgRHluYW1pY0F0dHJpYnV0ZSwgZHluYW1pY0F0dHJpYnV0ZSB9IGZyb20gJy4vYXR0cmlidXRlcy9keW5hbWljJztcblxuZXhwb3J0IGludGVyZmFjZSBGaXJzdE5vZGUge1xuICBmaXJzdE5vZGUoKTogU2ltcGxlTm9kZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMYXN0Tm9kZSB7XG4gIGxhc3ROb2RlKCk6IFNpbXBsZU5vZGU7XG59XG5cbmNsYXNzIEZpcnN0IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBub2RlOiBTaW1wbGVOb2RlKSB7fVxuXG4gIGZpcnN0Tm9kZSgpOiBTaW1wbGVOb2RlIHtcbiAgICByZXR1cm4gdGhpcy5ub2RlO1xuICB9XG59XG5cbmNsYXNzIExhc3Qge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5vZGU6IFNpbXBsZU5vZGUpIHt9XG5cbiAgbGFzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMubm9kZTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRnJhZ21lbnQgaW1wbGVtZW50cyBCb3VuZHMge1xuICBwcml2YXRlIGJvdW5kczogQm91bmRzO1xuXG4gIGNvbnN0cnVjdG9yKGJvdW5kczogQm91bmRzKSB7XG4gICAgdGhpcy5ib3VuZHMgPSBib3VuZHM7XG4gIH1cblxuICBwYXJlbnRFbGVtZW50KCk6IFNpbXBsZUVsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5wYXJlbnRFbGVtZW50KCk7XG4gIH1cblxuICBmaXJzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMuYm91bmRzLmZpcnN0Tm9kZSgpO1xuICB9XG5cbiAgbGFzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMuYm91bmRzLmxhc3ROb2RlKCk7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IENVUlNPUl9TVEFDSzogQ3Vyc29yU3RhY2tTeW1ib2wgPSBzeW1ib2woJ0NVUlNPUl9TVEFDSycpO1xuXG5leHBvcnQgY2xhc3MgTmV3RWxlbWVudEJ1aWxkZXIgaW1wbGVtZW50cyBFbGVtZW50QnVpbGRlciB7XG4gIHB1YmxpYyBkb206IEdsaW1tZXJUcmVlQ29uc3RydWN0aW9uO1xuICBwdWJsaWMgdXBkYXRlT3BlcmF0aW9uczogR2xpbW1lclRyZWVDaGFuZ2VzO1xuICBwdWJsaWMgY29uc3RydWN0aW5nOiBPcHRpb248U2ltcGxlRWxlbWVudD4gPSBudWxsO1xuICBwdWJsaWMgb3BlcmF0aW9uczogT3B0aW9uPEVsZW1lbnRPcGVyYXRpb25zPiA9IG51bGw7XG4gIHByaXZhdGUgZW52OiBFbnZpcm9ubWVudDtcblxuICBbQ1VSU09SX1NUQUNLXSA9IG5ldyBTdGFjazxDdXJzb3I+KCk7XG4gIHByaXZhdGUgbW9kaWZpZXJTdGFjayA9IG5ldyBTdGFjazxPcHRpb248TW9kaWZpZXJJbnN0YW5jZVtdPj4oKTtcbiAgcHJpdmF0ZSBibG9ja1N0YWNrID0gbmV3IFN0YWNrPExpdmVCbG9jaz4oKTtcblxuICBzdGF0aWMgZm9ySW5pdGlhbFJlbmRlcihlbnY6IEVudmlyb25tZW50LCBjdXJzb3I6IEN1cnNvckltcGwpIHtcbiAgICByZXR1cm4gbmV3IHRoaXMoZW52LCBjdXJzb3IuZWxlbWVudCwgY3Vyc29yLm5leHRTaWJsaW5nKS5pbml0aWFsaXplKCk7XG4gIH1cblxuICBzdGF0aWMgcmVzdW1lKGVudjogRW52aXJvbm1lbnQsIGJsb2NrOiBVcGRhdGFibGVCbG9jayk6IE5ld0VsZW1lbnRCdWlsZGVyIHtcbiAgICBsZXQgcGFyZW50Tm9kZSA9IGJsb2NrLnBhcmVudEVsZW1lbnQoKTtcbiAgICBsZXQgbmV4dFNpYmxpbmcgPSBibG9jay5yZXNldChlbnYpO1xuXG4gICAgbGV0IHN0YWNrID0gbmV3IHRoaXMoZW52LCBwYXJlbnROb2RlLCBuZXh0U2libGluZykuaW5pdGlhbGl6ZSgpO1xuICAgIHN0YWNrLnB1c2hMaXZlQmxvY2soYmxvY2spO1xuXG4gICAgcmV0dXJuIHN0YWNrO1xuICB9XG5cbiAgY29uc3RydWN0b3IoZW52OiBFbnZpcm9ubWVudCwgcGFyZW50Tm9kZTogU2ltcGxlRWxlbWVudCwgbmV4dFNpYmxpbmc6IE9wdGlvbjxTaW1wbGVOb2RlPikge1xuICAgIHRoaXMucHVzaEVsZW1lbnQocGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpO1xuXG4gICAgdGhpcy5lbnYgPSBlbnY7XG4gICAgdGhpcy5kb20gPSBlbnYuZ2V0QXBwZW5kT3BlcmF0aW9ucygpO1xuICAgIHRoaXMudXBkYXRlT3BlcmF0aW9ucyA9IGVudi5nZXRET00oKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBpbml0aWFsaXplKCk6IHRoaXMge1xuICAgIHRoaXMucHVzaFNpbXBsZUJsb2NrKCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBkZWJ1Z0Jsb2NrcygpOiBMaXZlQmxvY2tbXSB7XG4gICAgcmV0dXJuIHRoaXMuYmxvY2tTdGFjay50b0FycmF5KCk7XG4gIH1cblxuICBnZXQgZWxlbWVudCgpOiBTaW1wbGVFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpc1tDVVJTT1JfU1RBQ0tdLmN1cnJlbnQhLmVsZW1lbnQ7XG4gIH1cblxuICBnZXQgbmV4dFNpYmxpbmcoKTogT3B0aW9uPFNpbXBsZU5vZGU+IHtcbiAgICByZXR1cm4gdGhpc1tDVVJTT1JfU1RBQ0tdLmN1cnJlbnQhLm5leHRTaWJsaW5nO1xuICB9XG5cbiAgZ2V0IGhhc0Jsb2NrcygpIHtcbiAgICByZXR1cm4gdGhpcy5ibG9ja1N0YWNrLnNpemUgPiAwO1xuICB9XG5cbiAgcHJvdGVjdGVkIGJsb2NrKCk6IExpdmVCbG9jayB7XG4gICAgcmV0dXJuIGV4cGVjdCh0aGlzLmJsb2NrU3RhY2suY3VycmVudCwgJ0V4cGVjdGVkIGEgY3VycmVudCBsaXZlIGJsb2NrJyk7XG4gIH1cblxuICBwb3BFbGVtZW50KCkge1xuICAgIHRoaXNbQ1VSU09SX1NUQUNLXS5wb3AoKTtcbiAgICBleHBlY3QodGhpc1tDVVJTT1JfU1RBQ0tdLmN1cnJlbnQsIFwiY2FuJ3QgcG9wIHBhc3QgdGhlIGxhc3QgZWxlbWVudFwiKTtcbiAgfVxuXG4gIHB1c2hTaW1wbGVCbG9jaygpOiBMaXZlQmxvY2sge1xuICAgIHJldHVybiB0aGlzLnB1c2hMaXZlQmxvY2sobmV3IFNpbXBsZUxpdmVCbG9jayh0aGlzLmVsZW1lbnQpKTtcbiAgfVxuXG4gIHB1c2hVcGRhdGFibGVCbG9jaygpOiBVcGRhdGFibGVCbG9ja0ltcGwge1xuICAgIHJldHVybiB0aGlzLnB1c2hMaXZlQmxvY2sobmV3IFVwZGF0YWJsZUJsb2NrSW1wbCh0aGlzLmVsZW1lbnQpKTtcbiAgfVxuXG4gIHB1c2hCbG9ja0xpc3QobGlzdDogTGl2ZUJsb2NrW10pOiBMaXZlQmxvY2tMaXN0IHtcbiAgICByZXR1cm4gdGhpcy5wdXNoTGl2ZUJsb2NrKG5ldyBMaXZlQmxvY2tMaXN0KHRoaXMuZWxlbWVudCwgbGlzdCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHB1c2hMaXZlQmxvY2s8VCBleHRlbmRzIExpdmVCbG9jaz4oYmxvY2s6IFQsIGlzUmVtb3RlID0gZmFsc2UpOiBUIHtcbiAgICBsZXQgY3VycmVudCA9IHRoaXMuYmxvY2tTdGFjay5jdXJyZW50O1xuXG4gICAgaWYgKGN1cnJlbnQgIT09IG51bGwpIHtcbiAgICAgIGlmICghaXNSZW1vdGUpIHtcbiAgICAgICAgY3VycmVudC5kaWRBcHBlbmRCb3VuZHMoYmxvY2spO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX19vcGVuQmxvY2soKTtcbiAgICB0aGlzLmJsb2NrU3RhY2sucHVzaChibG9jayk7XG4gICAgcmV0dXJuIGJsb2NrO1xuICB9XG5cbiAgcG9wQmxvY2soKTogTGl2ZUJsb2NrIHtcbiAgICB0aGlzLmJsb2NrKCkuZmluYWxpemUodGhpcyk7XG4gICAgdGhpcy5fX2Nsb3NlQmxvY2soKTtcbiAgICByZXR1cm4gZXhwZWN0KHRoaXMuYmxvY2tTdGFjay5wb3AoKSwgJ0V4cGVjdGVkIHBvcEJsb2NrIHRvIHJldHVybiBhIGJsb2NrJyk7XG4gIH1cblxuICBfX29wZW5CbG9jaygpOiB2b2lkIHt9XG4gIF9fY2xvc2VCbG9jaygpOiB2b2lkIHt9XG5cbiAgLy8gdG9kbyByZXR1cm4gc2VlbXMgdW51c2VkXG4gIG9wZW5FbGVtZW50KHRhZzogc3RyaW5nKTogU2ltcGxlRWxlbWVudCB7XG4gICAgbGV0IGVsZW1lbnQgPSB0aGlzLl9fb3BlbkVsZW1lbnQodGFnKTtcbiAgICB0aGlzLmNvbnN0cnVjdGluZyA9IGVsZW1lbnQ7XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIF9fb3BlbkVsZW1lbnQodGFnOiBzdHJpbmcpOiBTaW1wbGVFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5kb20uY3JlYXRlRWxlbWVudCh0YWcsIHRoaXMuZWxlbWVudCk7XG4gIH1cblxuICBmbHVzaEVsZW1lbnQobW9kaWZpZXJzOiBPcHRpb248TW9kaWZpZXJJbnN0YW5jZVtdPikge1xuICAgIGxldCBwYXJlbnQgPSB0aGlzLmVsZW1lbnQ7XG4gICAgbGV0IGVsZW1lbnQgPSBleHBlY3QoXG4gICAgICB0aGlzLmNvbnN0cnVjdGluZyxcbiAgICAgIGBmbHVzaEVsZW1lbnQgc2hvdWxkIG9ubHkgYmUgY2FsbGVkIHdoZW4gY29uc3RydWN0aW5nIGFuIGVsZW1lbnRgXG4gICAgKTtcblxuICAgIHRoaXMuX19mbHVzaEVsZW1lbnQocGFyZW50LCBlbGVtZW50KTtcblxuICAgIHRoaXMuY29uc3RydWN0aW5nID0gbnVsbDtcbiAgICB0aGlzLm9wZXJhdGlvbnMgPSBudWxsO1xuXG4gICAgdGhpcy5wdXNoTW9kaWZpZXJzKG1vZGlmaWVycyk7XG4gICAgdGhpcy5wdXNoRWxlbWVudChlbGVtZW50LCBudWxsKTtcbiAgICB0aGlzLmRpZE9wZW5FbGVtZW50KGVsZW1lbnQpO1xuICB9XG5cbiAgX19mbHVzaEVsZW1lbnQocGFyZW50OiBTaW1wbGVFbGVtZW50LCBjb25zdHJ1Y3Rpbmc6IFNpbXBsZUVsZW1lbnQpIHtcbiAgICB0aGlzLmRvbS5pbnNlcnRCZWZvcmUocGFyZW50LCBjb25zdHJ1Y3RpbmcsIHRoaXMubmV4dFNpYmxpbmcpO1xuICB9XG5cbiAgY2xvc2VFbGVtZW50KCk6IE9wdGlvbjxNb2RpZmllckluc3RhbmNlW10+IHtcbiAgICB0aGlzLndpbGxDbG9zZUVsZW1lbnQoKTtcbiAgICB0aGlzLnBvcEVsZW1lbnQoKTtcbiAgICByZXR1cm4gdGhpcy5wb3BNb2RpZmllcnMoKTtcbiAgfVxuXG4gIHB1c2hSZW1vdGVFbGVtZW50KFxuICAgIGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQsXG4gICAgZ3VpZDogc3RyaW5nLFxuICAgIGluc2VydEJlZm9yZTogTWF5YmU8U2ltcGxlTm9kZT5cbiAgKTogT3B0aW9uPFJlbW90ZUxpdmVCbG9jaz4ge1xuICAgIHJldHVybiB0aGlzLl9fcHVzaFJlbW90ZUVsZW1lbnQoZWxlbWVudCwgZ3VpZCwgaW5zZXJ0QmVmb3JlKTtcbiAgfVxuXG4gIF9fcHVzaFJlbW90ZUVsZW1lbnQoXG4gICAgZWxlbWVudDogU2ltcGxlRWxlbWVudCxcbiAgICBfZ3VpZDogc3RyaW5nLFxuICAgIGluc2VydEJlZm9yZTogTWF5YmU8U2ltcGxlTm9kZT5cbiAgKTogT3B0aW9uPFJlbW90ZUxpdmVCbG9jaz4ge1xuICAgIHRoaXMucHVzaEVsZW1lbnQoZWxlbWVudCwgaW5zZXJ0QmVmb3JlKTtcblxuICAgIGlmIChpbnNlcnRCZWZvcmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgd2hpbGUgKGVsZW1lbnQubGFzdENoaWxkKSB7XG4gICAgICAgIGVsZW1lbnQucmVtb3ZlQ2hpbGQoZWxlbWVudC5sYXN0Q2hpbGQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBibG9jayA9IG5ldyBSZW1vdGVMaXZlQmxvY2soZWxlbWVudCk7XG5cbiAgICByZXR1cm4gdGhpcy5wdXNoTGl2ZUJsb2NrKGJsb2NrLCB0cnVlKTtcbiAgfVxuXG4gIHBvcFJlbW90ZUVsZW1lbnQoKSB7XG4gICAgdGhpcy5wb3BCbG9jaygpO1xuICAgIHRoaXMucG9wRWxlbWVudCgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHB1c2hFbGVtZW50KGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQsIG5leHRTaWJsaW5nOiBNYXliZTxTaW1wbGVOb2RlPiA9IG51bGwpIHtcbiAgICB0aGlzW0NVUlNPUl9TVEFDS10ucHVzaChuZXcgQ3Vyc29ySW1wbChlbGVtZW50LCBuZXh0U2libGluZykpO1xuICB9XG5cbiAgcHJpdmF0ZSBwdXNoTW9kaWZpZXJzKG1vZGlmaWVyczogT3B0aW9uPE1vZGlmaWVySW5zdGFuY2VbXT4pOiB2b2lkIHtcbiAgICB0aGlzLm1vZGlmaWVyU3RhY2sucHVzaChtb2RpZmllcnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBwb3BNb2RpZmllcnMoKTogT3B0aW9uPE1vZGlmaWVySW5zdGFuY2VbXT4ge1xuICAgIHJldHVybiB0aGlzLm1vZGlmaWVyU3RhY2sucG9wKCk7XG4gIH1cblxuICBkaWRBcHBlbmRCb3VuZHMoYm91bmRzOiBCb3VuZHMpOiBCb3VuZHMge1xuICAgIHRoaXMuYmxvY2soKS5kaWRBcHBlbmRCb3VuZHMoYm91bmRzKTtcbiAgICByZXR1cm4gYm91bmRzO1xuICB9XG5cbiAgZGlkQXBwZW5kTm9kZTxUIGV4dGVuZHMgU2ltcGxlTm9kZT4obm9kZTogVCk6IFQge1xuICAgIHRoaXMuYmxvY2soKS5kaWRBcHBlbmROb2RlKG5vZGUpO1xuICAgIHJldHVybiBub2RlO1xuICB9XG5cbiAgZGlkT3BlbkVsZW1lbnQoZWxlbWVudDogU2ltcGxlRWxlbWVudCk6IFNpbXBsZUVsZW1lbnQge1xuICAgIHRoaXMuYmxvY2soKS5vcGVuRWxlbWVudChlbGVtZW50KTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIHdpbGxDbG9zZUVsZW1lbnQoKSB7XG4gICAgdGhpcy5ibG9jaygpLmNsb3NlRWxlbWVudCgpO1xuICB9XG5cbiAgYXBwZW5kVGV4dChzdHJpbmc6IHN0cmluZyk6IFNpbXBsZVRleHQge1xuICAgIHJldHVybiB0aGlzLmRpZEFwcGVuZE5vZGUodGhpcy5fX2FwcGVuZFRleHQoc3RyaW5nKSk7XG4gIH1cblxuICBfX2FwcGVuZFRleHQodGV4dDogc3RyaW5nKTogU2ltcGxlVGV4dCB7XG4gICAgbGV0IHsgZG9tLCBlbGVtZW50LCBuZXh0U2libGluZyB9ID0gdGhpcztcbiAgICBsZXQgbm9kZSA9IGRvbS5jcmVhdGVUZXh0Tm9kZSh0ZXh0KTtcbiAgICBkb20uaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIG5vZGUsIG5leHRTaWJsaW5nKTtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIF9fYXBwZW5kTm9kZShub2RlOiBTaW1wbGVOb2RlKTogU2ltcGxlTm9kZSB7XG4gICAgdGhpcy5kb20uaW5zZXJ0QmVmb3JlKHRoaXMuZWxlbWVudCwgbm9kZSwgdGhpcy5uZXh0U2libGluZyk7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICBfX2FwcGVuZEZyYWdtZW50KGZyYWdtZW50OiBTaW1wbGVEb2N1bWVudEZyYWdtZW50KTogQm91bmRzIHtcbiAgICBsZXQgZmlyc3QgPSBmcmFnbWVudC5maXJzdENoaWxkO1xuXG4gICAgaWYgKGZpcnN0KSB7XG4gICAgICBsZXQgcmV0ID0gbmV3IENvbmNyZXRlQm91bmRzKHRoaXMuZWxlbWVudCwgZmlyc3QsIGZyYWdtZW50Lmxhc3RDaGlsZCEpO1xuICAgICAgdGhpcy5kb20uaW5zZXJ0QmVmb3JlKHRoaXMuZWxlbWVudCwgZnJhZ21lbnQsIHRoaXMubmV4dFNpYmxpbmcpO1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG5ldyBTaW5nbGVOb2RlQm91bmRzKHRoaXMuZWxlbWVudCwgdGhpcy5fX2FwcGVuZENvbW1lbnQoJycpKTtcbiAgICB9XG4gIH1cblxuICBfX2FwcGVuZEhUTUwoaHRtbDogc3RyaW5nKTogQm91bmRzIHtcbiAgICByZXR1cm4gdGhpcy5kb20uaW5zZXJ0SFRNTEJlZm9yZSh0aGlzLmVsZW1lbnQsIHRoaXMubmV4dFNpYmxpbmcsIGh0bWwpO1xuICB9XG5cbiAgYXBwZW5kRHluYW1pY0hUTUwodmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGxldCBib3VuZHMgPSB0aGlzLnRydXN0ZWRDb250ZW50KHZhbHVlKTtcbiAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpO1xuICB9XG5cbiAgYXBwZW5kRHluYW1pY1RleHQodmFsdWU6IHN0cmluZyk6IFNpbXBsZVRleHQge1xuICAgIGxldCBub2RlID0gdGhpcy51bnRydXN0ZWRDb250ZW50KHZhbHVlKTtcbiAgICB0aGlzLmRpZEFwcGVuZE5vZGUobm9kZSk7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICBhcHBlbmREeW5hbWljRnJhZ21lbnQodmFsdWU6IFNpbXBsZURvY3VtZW50RnJhZ21lbnQpOiB2b2lkIHtcbiAgICBsZXQgYm91bmRzID0gdGhpcy5fX2FwcGVuZEZyYWdtZW50KHZhbHVlKTtcbiAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpO1xuICB9XG5cbiAgYXBwZW5kRHluYW1pY05vZGUodmFsdWU6IFNpbXBsZU5vZGUpOiB2b2lkIHtcbiAgICBsZXQgbm9kZSA9IHRoaXMuX19hcHBlbmROb2RlKHZhbHVlKTtcbiAgICBsZXQgYm91bmRzID0gbmV3IFNpbmdsZU5vZGVCb3VuZHModGhpcy5lbGVtZW50LCBub2RlKTtcbiAgICB0aGlzLmRpZEFwcGVuZEJvdW5kcyhib3VuZHMpO1xuICB9XG5cbiAgcHJpdmF0ZSB0cnVzdGVkQ29udGVudCh2YWx1ZTogc3RyaW5nKTogQm91bmRzIHtcbiAgICByZXR1cm4gdGhpcy5fX2FwcGVuZEhUTUwodmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSB1bnRydXN0ZWRDb250ZW50KHZhbHVlOiBzdHJpbmcpOiBTaW1wbGVUZXh0IHtcbiAgICByZXR1cm4gdGhpcy5fX2FwcGVuZFRleHQodmFsdWUpO1xuICB9XG5cbiAgYXBwZW5kQ29tbWVudChzdHJpbmc6IHN0cmluZyk6IFNpbXBsZUNvbW1lbnQge1xuICAgIHJldHVybiB0aGlzLmRpZEFwcGVuZE5vZGUodGhpcy5fX2FwcGVuZENvbW1lbnQoc3RyaW5nKSk7XG4gIH1cblxuICBfX2FwcGVuZENvbW1lbnQoc3RyaW5nOiBzdHJpbmcpOiBTaW1wbGVDb21tZW50IHtcbiAgICBsZXQgeyBkb20sIGVsZW1lbnQsIG5leHRTaWJsaW5nIH0gPSB0aGlzO1xuICAgIGxldCBub2RlID0gZG9tLmNyZWF0ZUNvbW1lbnQoc3RyaW5nKTtcbiAgICBkb20uaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIG5vZGUsIG5leHRTaWJsaW5nKTtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIF9fc2V0QXR0cmlidXRlKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZywgbmFtZXNwYWNlOiBPcHRpb248QXR0ck5hbWVzcGFjZT4pOiB2b2lkIHtcbiAgICB0aGlzLmRvbS5zZXRBdHRyaWJ1dGUodGhpcy5jb25zdHJ1Y3RpbmchLCBuYW1lLCB2YWx1ZSwgbmFtZXNwYWNlKTtcbiAgfVxuXG4gIF9fc2V0UHJvcGVydHkobmFtZTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgICh0aGlzLmNvbnN0cnVjdGluZyEgYXMgYW55KVtuYW1lXSA9IHZhbHVlO1xuICB9XG5cbiAgc2V0U3RhdGljQXR0cmlidXRlKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZywgbmFtZXNwYWNlOiBPcHRpb248QXR0ck5hbWVzcGFjZT4pOiB2b2lkIHtcbiAgICB0aGlzLl9fc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlLCBuYW1lc3BhY2UpO1xuICB9XG5cbiAgc2V0RHluYW1pY0F0dHJpYnV0ZShcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdmFsdWU6IHVua25vd24sXG4gICAgdHJ1c3Rpbmc6IGJvb2xlYW4sXG4gICAgbmFtZXNwYWNlOiBPcHRpb248QXR0ck5hbWVzcGFjZT5cbiAgKTogRHluYW1pY0F0dHJpYnV0ZSB7XG4gICAgbGV0IGVsZW1lbnQgPSB0aGlzLmNvbnN0cnVjdGluZyE7XG4gICAgbGV0IGF0dHJpYnV0ZSA9IGR5bmFtaWNBdHRyaWJ1dGUoZWxlbWVudCwgbmFtZSwgbmFtZXNwYWNlLCB0cnVzdGluZyk7XG4gICAgYXR0cmlidXRlLnNldCh0aGlzLCB2YWx1ZSwgdGhpcy5lbnYpO1xuICAgIHJldHVybiBhdHRyaWJ1dGU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNpbXBsZUxpdmVCbG9jayBpbXBsZW1lbnRzIExpdmVCbG9jayB7XG4gIHByb3RlY3RlZCBmaXJzdDogT3B0aW9uPEZpcnN0Tm9kZT4gPSBudWxsO1xuICBwcm90ZWN0ZWQgbGFzdDogT3B0aW9uPExhc3ROb2RlPiA9IG51bGw7XG4gIHByb3RlY3RlZCBuZXN0aW5nID0gMDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHBhcmVudDogU2ltcGxlRWxlbWVudCkge31cblxuICBwYXJlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB0aGlzLnBhcmVudDtcbiAgfVxuXG4gIGZpcnN0Tm9kZSgpOiBTaW1wbGVOb2RlIHtcbiAgICBsZXQgZmlyc3QgPSBleHBlY3QoXG4gICAgICB0aGlzLmZpcnN0LFxuICAgICAgJ2Nhbm5vdCBjYWxsIGBmaXJzdE5vZGUoKWAgd2hpbGUgYFNpbXBsZUxpdmVCbG9ja2AgaXMgc3RpbGwgaW5pdGlhbGl6aW5nJ1xuICAgICk7XG5cbiAgICByZXR1cm4gZmlyc3QuZmlyc3ROb2RlKCk7XG4gIH1cblxuICBsYXN0Tm9kZSgpOiBTaW1wbGVOb2RlIHtcbiAgICBsZXQgbGFzdCA9IGV4cGVjdChcbiAgICAgIHRoaXMubGFzdCxcbiAgICAgICdjYW5ub3QgY2FsbCBgbGFzdE5vZGUoKWAgd2hpbGUgYFNpbXBsZUxpdmVCbG9ja2AgaXMgc3RpbGwgaW5pdGlhbGl6aW5nJ1xuICAgICk7XG5cbiAgICByZXR1cm4gbGFzdC5sYXN0Tm9kZSgpO1xuICB9XG5cbiAgb3BlbkVsZW1lbnQoZWxlbWVudDogU2ltcGxlRWxlbWVudCkge1xuICAgIHRoaXMuZGlkQXBwZW5kTm9kZShlbGVtZW50KTtcbiAgICB0aGlzLm5lc3RpbmcrKztcbiAgfVxuXG4gIGNsb3NlRWxlbWVudCgpIHtcbiAgICB0aGlzLm5lc3RpbmctLTtcbiAgfVxuXG4gIGRpZEFwcGVuZE5vZGUobm9kZTogU2ltcGxlTm9kZSkge1xuICAgIGlmICh0aGlzLm5lc3RpbmcgIT09IDApIHJldHVybjtcblxuICAgIGlmICghdGhpcy5maXJzdCkge1xuICAgICAgdGhpcy5maXJzdCA9IG5ldyBGaXJzdChub2RlKTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3QgPSBuZXcgTGFzdChub2RlKTtcbiAgfVxuXG4gIGRpZEFwcGVuZEJvdW5kcyhib3VuZHM6IEJvdW5kcykge1xuICAgIGlmICh0aGlzLm5lc3RpbmcgIT09IDApIHJldHVybjtcblxuICAgIGlmICghdGhpcy5maXJzdCkge1xuICAgICAgdGhpcy5maXJzdCA9IGJvdW5kcztcbiAgICB9XG5cbiAgICB0aGlzLmxhc3QgPSBib3VuZHM7XG4gIH1cblxuICBmaW5hbGl6ZShzdGFjazogRWxlbWVudEJ1aWxkZXIpIHtcbiAgICBpZiAodGhpcy5maXJzdCA9PT0gbnVsbCkge1xuICAgICAgc3RhY2suYXBwZW5kQ29tbWVudCgnJyk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBSZW1vdGVMaXZlQmxvY2sgZXh0ZW5kcyBTaW1wbGVMaXZlQmxvY2sge1xuICBjb25zdHJ1Y3RvcihwYXJlbnQ6IFNpbXBsZUVsZW1lbnQpIHtcbiAgICBzdXBlcihwYXJlbnQpO1xuXG4gICAgcmVnaXN0ZXJEZXN0cnVjdG9yKHRoaXMsICgpID0+IHtcbiAgICAgIC8vIEluIGdlbmVyYWwsIHlvdSBvbmx5IG5lZWQgdG8gY2xlYXIgdGhlIHJvb3Qgb2YgYSBoaWVyYXJjaHksIGFuZCBzaG91bGQgbmV2ZXJcbiAgICAgIC8vIG5lZWQgdG8gY2xlYXIgYW55IGNoaWxkIG5vZGVzLiBUaGlzIGlzIGFuIGltcG9ydGFudCBjb25zdHJhaW50IHRoYXQgZ2l2ZXMgdXNcbiAgICAgIC8vIGEgc3Ryb25nIGd1YXJhbnRlZSB0aGF0IGNsZWFyaW5nIGEgc3VidHJlZSBpcyBhIHNpbmdsZSBET00gb3BlcmF0aW9uLlxuICAgICAgLy9cbiAgICAgIC8vIEJlY2F1c2UgcmVtb3RlIGJsb2NrcyBhcmUgbm90IG5vcm1hbGx5IHBoeXNpY2FsbHkgbmVzdGVkIGluc2lkZSBvZiB0aGUgdHJlZVxuICAgICAgLy8gdGhhdCB0aGV5IGFyZSBsb2dpY2FsbHkgbmVzdGVkIGluc2lkZSwgd2UgbWFudWFsbHkgY2xlYXIgcmVtb3RlIGJsb2NrcyB3aGVuXG4gICAgICAvLyBhIGxvZ2ljYWwgcGFyZW50IGlzIGNsZWFyZWQuXG4gICAgICAvL1xuICAgICAgLy8gSE9XRVZFUiwgaXQgaXMgY3VycmVudGx5IHBvc3NpYmxlIGZvciBhIHJlbW90ZSBibG9jayB0byBiZSBwaHlzaWNhbGx5IG5lc3RlZFxuICAgICAgLy8gaW5zaWRlIG9mIHRoZSBibG9jayBpdCBpcyBsb2dpY2FsbHkgY29udGFpbmVkIGluc2lkZSBvZi4gVGhpcyBoYXBwZW5zIHdoZW5cbiAgICAgIC8vIHRoZSByZW1vdGUgYmxvY2sgaXMgYXBwZW5kZWQgdG8gdGhlIGVuZCBvZiB0aGUgYXBwbGljYXRpb24ncyBlbnRpcmUgZWxlbWVudC5cbiAgICAgIC8vXG4gICAgICAvLyBUaGUgcHJvYmxlbSB3aXRoIHRoYXQgc2NlbmFyaW8gaXMgdGhhdCBHbGltbWVyIGJlbGlldmVzIHRoYXQgaXQgb3ducyBtb3JlIG9mXG4gICAgICAvLyB0aGUgRE9NIHRoYW4gaXQgYWN0dWFsbHkgZG9lcy4gVGhlIGNvZGUgaXMgYXR0ZW1wdGluZyB0byB3cml0ZSBwYXN0IHRoZSBlbmRcbiAgICAgIC8vIG9mIHRoZSBHbGltbWVyLW1hbmFnZWQgcm9vdCwgYnV0IEdsaW1tZXIgaXNuJ3QgYXdhcmUgb2YgdGhhdC5cbiAgICAgIC8vXG4gICAgICAvLyBUaGUgY29ycmVjdCBzb2x1dGlvbiB0byB0aGF0IHByb2JsZW0gaXMgZm9yIEdsaW1tZXIgdG8gYmUgYXdhcmUgb2YgdGhlIGVuZFxuICAgICAgLy8gb2YgdGhlIGJvdW5kcyB0aGF0IGl0IG93bnMsIGFuZCBvbmNlIHdlIG1ha2UgdGhhdCBjaGFuZ2UsIHRoaXMgY2hlY2sgY291bGRcbiAgICAgIC8vIGJlIHJlbW92ZWQuXG4gICAgICAvL1xuICAgICAgLy8gRm9yIG5vdywgYSBtb3JlIHRhcmdldGVkIGZpeCBpcyB0byBjaGVjayB3aGV0aGVyIHRoZSBub2RlIHdhcyBhbHJlYWR5IHJlbW92ZWRcbiAgICAgIC8vIGFuZCBhdm9pZCBjbGVhcmluZyB0aGUgbm9kZSBpZiBpdCB3YXMuIEluIG1vc3QgY2FzZXMgdGhpcyBzaG91bGRuJ3QgaGFwcGVuLFxuICAgICAgLy8gc28gdGhpcyBtaWdodCBoaWRlIGJ1Z3Mgd2hlcmUgdGhlIGNvZGUgY2xlYXJzIG5lc3RlZCBub2RlcyB1bm5lY2Vzc2FyaWx5LFxuICAgICAgLy8gc28gd2Ugc2hvdWxkIGV2ZW50dWFsbHkgdHJ5IHRvIGRvIHRoZSBjb3JyZWN0IGZpeC5cbiAgICAgIGlmICh0aGlzLnBhcmVudEVsZW1lbnQoKSA9PT0gdGhpcy5maXJzdE5vZGUoKS5wYXJlbnROb2RlKSB7XG4gICAgICAgIGNsZWFyKHRoaXMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBVcGRhdGFibGVCbG9ja0ltcGwgZXh0ZW5kcyBTaW1wbGVMaXZlQmxvY2sgaW1wbGVtZW50cyBVcGRhdGFibGVCbG9jayB7XG4gIHJlc2V0KCk6IE9wdGlvbjxTaW1wbGVOb2RlPiB7XG4gICAgZGVzdHJveSh0aGlzKTtcbiAgICBsZXQgbmV4dFNpYmxpbmcgPSBjbGVhcih0aGlzKTtcblxuICAgIHRoaXMuZmlyc3QgPSBudWxsO1xuICAgIHRoaXMubGFzdCA9IG51bGw7XG4gICAgdGhpcy5uZXN0aW5nID0gMDtcblxuICAgIHJldHVybiBuZXh0U2libGluZztcbiAgfVxufVxuXG4vLyBGSVhNRTogQWxsIHRoZSBub29wcyBpbiBoZXJlIGluZGljYXRlIGEgbW9kZWxsaW5nIHByb2JsZW1cbmV4cG9ydCBjbGFzcyBMaXZlQmxvY2tMaXN0IGltcGxlbWVudHMgTGl2ZUJsb2NrIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwYXJlbnQ6IFNpbXBsZUVsZW1lbnQsIHB1YmxpYyBib3VuZExpc3Q6IExpdmVCbG9ja1tdKSB7XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5ib3VuZExpc3QgPSBib3VuZExpc3Q7XG4gIH1cblxuICBwYXJlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB0aGlzLnBhcmVudDtcbiAgfVxuXG4gIGZpcnN0Tm9kZSgpOiBTaW1wbGVOb2RlIHtcbiAgICBsZXQgaGVhZCA9IGV4cGVjdChcbiAgICAgIHRoaXMuYm91bmRMaXN0WzBdLFxuICAgICAgJ2Nhbm5vdCBjYWxsIGBmaXJzdE5vZGUoKWAgd2hpbGUgYExpdmVCbG9ja0xpc3RgIGlzIHN0aWxsIGluaXRpYWxpemluZydcbiAgICApO1xuXG4gICAgcmV0dXJuIGhlYWQuZmlyc3ROb2RlKCk7XG4gIH1cblxuICBsYXN0Tm9kZSgpOiBTaW1wbGVOb2RlIHtcbiAgICBsZXQgYm91bmRMaXN0ID0gdGhpcy5ib3VuZExpc3Q7XG5cbiAgICBsZXQgdGFpbCA9IGV4cGVjdChcbiAgICAgIGJvdW5kTGlzdFtib3VuZExpc3QubGVuZ3RoIC0gMV0sXG4gICAgICAnY2Fubm90IGNhbGwgYGxhc3ROb2RlKClgIHdoaWxlIGBMaXZlQmxvY2tMaXN0YCBpcyBzdGlsbCBpbml0aWFsaXppbmcnXG4gICAgKTtcblxuICAgIHJldHVybiB0YWlsLmxhc3ROb2RlKCk7XG4gIH1cblxuICBvcGVuRWxlbWVudChfZWxlbWVudDogU2ltcGxlRWxlbWVudCkge1xuICAgIGFzc2VydChmYWxzZSwgJ0Nhbm5vdCBvcGVuRWxlbWVudCBkaXJlY3RseSBpbnNpZGUgYSBibG9jayBsaXN0Jyk7XG4gIH1cblxuICBjbG9zZUVsZW1lbnQoKSB7XG4gICAgYXNzZXJ0KGZhbHNlLCAnQ2Fubm90IGNsb3NlRWxlbWVudCBkaXJlY3RseSBpbnNpZGUgYSBibG9jayBsaXN0Jyk7XG4gIH1cblxuICBkaWRBcHBlbmROb2RlKF9ub2RlOiBTaW1wbGVOb2RlKSB7XG4gICAgYXNzZXJ0KGZhbHNlLCAnQ2Fubm90IGNyZWF0ZSBhIG5ldyBub2RlIGRpcmVjdGx5IGluc2lkZSBhIGJsb2NrIGxpc3QnKTtcbiAgfVxuXG4gIGRpZEFwcGVuZEJvdW5kcyhfYm91bmRzOiBCb3VuZHMpIHt9XG5cbiAgZmluYWxpemUoX3N0YWNrOiBFbGVtZW50QnVpbGRlcikge1xuICAgIGFzc2VydCh0aGlzLmJvdW5kTGlzdC5sZW5ndGggPiAwLCAnYm91bmRzTGlzdCBjYW5ub3QgYmUgZW1wdHknKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xpZW50QnVpbGRlcihlbnY6IEVudmlyb25tZW50LCBjdXJzb3I6IEN1cnNvckltcGwpOiBFbGVtZW50QnVpbGRlciB7XG4gIHJldHVybiBOZXdFbGVtZW50QnVpbGRlci5mb3JJbml0aWFsUmVuZGVyKGVudiwgY3Vyc29yKTtcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=