@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
485 lines (385 loc) • 43.8 kB
JavaScript
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=