UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

515 lines (398 loc) 43.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clientBuilder = clientBuilder; exports.LiveBlockList = exports.UpdatableBlockImpl = exports.RemoteLiveBlock = exports.SimpleLiveBlock = exports.NewElementBuilder = exports.CURSOR_STACK = exports.Fragment = void 0; var _util = require("@glimmer/util"); var _bounds2 = require("../bounds"); var _destroyable = require("@glimmer/destroyable"); var _dynamic = require("./attributes/dynamic"); var _a; class First { constructor(node) { this.node = node; } firstNode() { return this.node; } } class Last { constructor(node) { this.node = node; } lastNode() { return this.node; } } class Fragment { constructor(bounds) { this.bounds = bounds; } parentElement() { return this.bounds.parentElement(); } firstNode() { return this.bounds.firstNode(); } lastNode() { return this.bounds.lastNode(); } } exports.Fragment = Fragment; const CURSOR_STACK = (0, _util.symbol)('CURSOR_STACK'); exports.CURSOR_STACK = CURSOR_STACK; class NewElementBuilder { constructor(env, parentNode, nextSibling) { this.constructing = null; this.operations = null; this[_a] = new _util.Stack(); this.modifierStack = new _util.Stack(); this.blockStack = new _util.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 _bounds2.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 _bounds2.ConcreteBounds(this.element, first, fragment.lastChild); this.dom.insertBefore(this.element, fragment, this.nextSibling); return ret; } else { return new _bounds2.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 _bounds2.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 = (0, _dynamic.dynamicAttribute)(element, name, namespace, trusting); attribute.set(this, value, this.env); return attribute; } } exports.NewElementBuilder = NewElementBuilder; _a = CURSOR_STACK; 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(''); } } } exports.SimpleLiveBlock = SimpleLiveBlock; class RemoteLiveBlock extends SimpleLiveBlock { constructor(parent) { super(parent); (0, _destroyable.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) { (0, _bounds2.clear)(this); } }); } } exports.RemoteLiveBlock = RemoteLiveBlock; class UpdatableBlockImpl extends SimpleLiveBlock { reset() { (0, _destroyable.destroy)(this); let nextSibling = (0, _bounds2.clear)(this); this.first = null; this.last = null; this.nesting = 0; return nextSibling; } } // FIXME: All the noops in here indicate a modelling problem exports.UpdatableBlockImpl = UpdatableBlockImpl; 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 && (0, _util.assert)(false, 'Cannot openElement directly inside a block list'); } closeElement() { false && (0, _util.assert)(false, 'Cannot closeElement directly inside a block list'); } didAppendNode(_node) { false && (0, _util.assert)(false, 'Cannot create a new node directly inside a block list'); } didAppendBounds(_bounds) {} finalize(_stack) { false && (0, _util.assert)(this.boundList.length > 0, 'boundsList cannot be empty'); } } exports.LiveBlockList = LiveBlockList; function clientBuilder(env, cursor) { return NewElementBuilder.forInitialRender(env, cursor); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL2VsZW1lbnQtYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQWVBOztBQVNBOztBQUNBOztBQUNBOzs7O0FBVUEsTUFBQSxLQUFBLENBQVc7QUFDVCxFQUFBLFdBQUEsQ0FBQSxJQUFBLEVBQW9DO0FBQWhCLFNBQUEsSUFBQSxHQUFBLElBQUE7QUFBb0I7O0FBRXhDLEVBQUEsU0FBUyxHQUFBO0FBQ1AsV0FBTyxLQUFQLElBQUE7QUFDRDs7QUFMUTs7QUFRWCxNQUFBLElBQUEsQ0FBVTtBQUNSLEVBQUEsV0FBQSxDQUFBLElBQUEsRUFBb0M7QUFBaEIsU0FBQSxJQUFBLEdBQUEsSUFBQTtBQUFvQjs7QUFFeEMsRUFBQSxRQUFRLEdBQUE7QUFDTixXQUFPLEtBQVAsSUFBQTtBQUNEOztBQUxPOztBQVFKLE1BQUEsUUFBQSxDQUFlO0FBR25CLEVBQUEsV0FBQSxDQUFBLE1BQUEsRUFBMEI7QUFDeEIsU0FBQSxNQUFBLEdBQUEsTUFBQTtBQUNEOztBQUVELEVBQUEsYUFBYSxHQUFBO0FBQ1gsV0FBTyxLQUFBLE1BQUEsQ0FBUCxhQUFPLEVBQVA7QUFDRDs7QUFFRCxFQUFBLFNBQVMsR0FBQTtBQUNQLFdBQU8sS0FBQSxNQUFBLENBQVAsU0FBTyxFQUFQO0FBQ0Q7O0FBRUQsRUFBQSxRQUFRLEdBQUE7QUFDTixXQUFPLEtBQUEsTUFBQSxDQUFQLFFBQU8sRUFBUDtBQUNEOztBQWpCa0I7OztBQW9CZCxNQUFNLFlBQVksR0FBc0Isa0JBQXhDLGNBQXdDLENBQXhDOzs7QUFFRCxNQUFBLGlCQUFBLENBQXdCO0FBeUI1QixFQUFBLFdBQUEsQ0FBQSxHQUFBLEVBQUEsVUFBQSxFQUFBLFdBQUEsRUFBd0Y7QUF0QmpGLFNBQUEsWUFBQSxHQUFBLElBQUE7QUFDQSxTQUFBLFVBQUEsR0FBQSxJQUFBO0FBR1AsU0FBQSxFQUFBLElBQWlCLElBQWpCLFdB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QUVELEVBQUEsV0FBVyxDQUFBLFFBQUEsRUFBd0I7QUFBQSxhQUNqQyxrQkFBTSxLQUFOLEVBRGlDLGlEQUNqQyxDQURpQztBQUVsQzs7QUFFRCxFQUFBLFlBQVksR0FBQTtBQUFBLGFBQ1Ysa0JBQU0sS0FBTixFQURVLGtEQUNWLENBRFU7QUFFWDs7QUFFRCxFQUFBLGFBQWEsQ0FBQSxLQUFBLEVBQWtCO0FBQUEsYUFDN0Isa0JBQU0sS0FBTixFQUQ2Qix1REFDN0IsQ0FENkI7QUFFOUI7O0FBRUQsRUFBQSxlQUFlLENBQUEsT0FBQSxFQUFnQixDQUFJOztBQUVuQyxFQUFBLFFBQVEsQ0FBQSxNQUFBLEVBQXVCO0FBQUEsYUFDN0Isa0JBQU8sS0FBQSxTQUFBLENBQUEsTUFBQSxHQUFELENBQU4sRUFENkIsNEJBQzdCLENBRDZCO0FBRTlCOztBQTlDdUI7Ozs7QUFpRHBCLFNBQUEsYUFBQSxDQUFBLEdBQUEsRUFBQSxNQUFBLEVBQTREO0FBQ2hFLFNBQU8saUJBQWlCLENBQWpCLGdCQUFBLENBQUEsR0FBQSxFQUFQLE1BQU8sQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQm91bmRzLFxuICBDdXJzb3IsXG4gIEN1cnNvclN0YWNrU3ltYm9sLFxuICBFbGVtZW50QnVpbGRlcixcbiAgRWxlbWVudE9wZXJhdGlvbnMsXG4gIEVudmlyb25tZW50LFxuICBHbGltbWVyVHJlZUNoYW5nZXMsXG4gIEdsaW1tZXJUcmVlQ29uc3RydWN0aW9uLFxuICBMaXZlQmxvY2ssXG4gIE1heWJlLFxuICBPcHRpb24sXG4gIFVwZGF0YWJsZUJsb2NrLFxuICBNb2RpZmllckluc3RhbmNlLFxufSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IGFzc2VydCwgZXhwZWN0LCBTdGFjaywgc3ltYm9sIH0gZnJvbSAnQGdsaW1tZXIvdXRpbCc7XG5pbXBvcnQge1xuICBBdHRyTmFtZXNwYWNlLFxuICBTaW1wbGVDb21tZW50LFxuICBTaW1wbGVEb2N1bWVudEZyYWdtZW50LFxuICBTaW1wbGVFbGVtZW50LFxuICBTaW1wbGVOb2RlLFxuICBTaW1wbGVUZXh0LFxufSBmcm9tICdAc2ltcGxlLWRvbS9pbnRlcmZhY2UnO1xuaW1wb3J0IHsgY2xlYXIsIENvbmNyZXRlQm91bmRzLCBDdXJzb3JJbXBsLCBTaW5nbGVOb2RlQm91bmRzIH0gZnJvbSAnLi4vYm91bmRzJztcbmltcG9ydCB7IGRlc3Ryb3ksIHJlZ2lzdGVyRGVzdHJ1Y3RvciB9IGZyb20gJ0BnbGltbWVyL2Rlc3Ryb3lhYmxlJztcbmltcG9ydCB7IER5bmFtaWNBdHRyaWJ1dGUsIGR5bmFtaWNBdHRyaWJ1dGUgfSBmcm9tICcuL2F0dHJpYnV0ZXMvZHluYW1pYyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlyc3ROb2RlIHtcbiAgZmlyc3ROb2RlKCk6IFNpbXBsZU5vZGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGFzdE5vZGUge1xuICBsYXN0Tm9kZSgpOiBTaW1wbGVOb2RlO1xufVxuXG5jbGFzcyBGaXJzdCB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgbm9kZTogU2ltcGxlTm9kZSkge31cblxuICBmaXJzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMubm9kZTtcbiAgfVxufVxuXG5jbGFzcyBMYXN0IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBub2RlOiBTaW1wbGVOb2RlKSB7fVxuXG4gIGxhc3ROb2RlKCk6IFNpbXBsZU5vZGUge1xuICAgIHJldHVybiB0aGlzLm5vZGU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEZyYWdtZW50IGltcGxlbWVudHMgQm91bmRzIHtcbiAgcHJpdmF0ZSBib3VuZHM6IEJvdW5kcztcblxuICBjb25zdHJ1Y3Rvcihib3VuZHM6IEJvdW5kcykge1xuICAgIHRoaXMuYm91bmRzID0gYm91bmRzO1xuICB9XG5cbiAgcGFyZW50RWxlbWVudCgpOiBTaW1wbGVFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5ib3VuZHMucGFyZW50RWxlbWVudCgpO1xuICB9XG5cbiAgZmlyc3ROb2RlKCk6IFNpbXBsZU5vZGUge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5maXJzdE5vZGUoKTtcbiAgfVxuXG4gIGxhc3ROb2RlKCk6IFNpbXBsZU5vZGUge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5sYXN0Tm9kZSgpO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBDVVJTT1JfU1RBQ0s6IEN1cnNvclN0YWNrU3ltYm9sID0gc3ltYm9sKCdDVVJTT1JfU1RBQ0snKTtcblxuZXhwb3J0IGNsYXNzIE5ld0VsZW1lbnRCdWlsZGVyIGltcGxlbWVudHMgRWxlbWVudEJ1aWxkZXIge1xuICBwdWJsaWMgZG9tOiBHbGltbWVyVHJlZUNvbnN0cnVjdGlvbjtcbiAgcHVibGljIHVwZGF0ZU9wZXJhdGlvbnM6IEdsaW1tZXJUcmVlQ2hhbmdlcztcbiAgcHVibGljIGNvbnN0cnVjdGluZzogT3B0aW9uPFNpbXBsZUVsZW1lbnQ+ID0gbnVsbDtcbiAgcHVibGljIG9wZXJhdGlvbnM6IE9wdGlvbjxFbGVtZW50T3BlcmF0aW9ucz4gPSBudWxsO1xuICBwcml2YXRlIGVudjogRW52aXJvbm1lbnQ7XG5cbiAgW0NVUlNPUl9TVEFDS10gPSBuZXcgU3RhY2s8Q3Vyc29yPigpO1xuICBwcml2YXRlIG1vZGlmaWVyU3RhY2sgPSBuZXcgU3RhY2s8T3B0aW9uPE1vZGlmaWVySW5zdGFuY2VbXT4+KCk7XG4gIHByaXZhdGUgYmxvY2tTdGFjayA9IG5ldyBTdGFjazxMaXZlQmxvY2s+KCk7XG5cbiAgc3RhdGljIGZvckluaXRpYWxSZW5kZXIoZW52OiBFbnZpcm9ubWVudCwgY3Vyc29yOiBDdXJzb3JJbXBsKSB7XG4gICAgcmV0dXJuIG5ldyB0aGlzKGVudiwgY3Vyc29yLmVsZW1lbnQsIGN1cnNvci5uZXh0U2libGluZykuaW5pdGlhbGl6ZSgpO1xuICB9XG5cbiAgc3RhdGljIHJlc3VtZShlbnY6IEVudmlyb25tZW50LCBibG9jazogVXBkYXRhYmxlQmxvY2spOiBOZXdFbGVtZW50QnVpbGRlciB7XG4gICAgbGV0IHBhcmVudE5vZGUgPSBibG9jay5wYXJlbnRFbGVtZW50KCk7XG4gICAgbGV0IG5leHRTaWJsaW5nID0gYmxvY2sucmVzZXQoZW52KTtcblxuICAgIGxldCBzdGFjayA9IG5ldyB0aGlzKGVudiwgcGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpLmluaXRpYWxpemUoKTtcbiAgICBzdGFjay5wdXNoTGl2ZUJsb2NrKGJsb2NrKTtcblxuICAgIHJldHVybiBzdGFjaztcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKGVudjogRW52aXJvbm1lbnQsIHBhcmVudE5vZGU6IFNpbXBsZUVsZW1lbnQsIG5leHRTaWJsaW5nOiBPcHRpb248U2ltcGxlTm9kZT4pIHtcbiAgICB0aGlzLnB1c2hFbGVtZW50KHBhcmVudE5vZGUsIG5leHRTaWJsaW5nKTtcblxuICAgIHRoaXMuZW52ID0gZW52O1xuICAgIHRoaXMuZG9tID0gZW52LmdldEFwcGVuZE9wZXJhdGlvbnMoKTtcbiAgICB0aGlzLnVwZGF0ZU9wZXJhdGlvbnMgPSBlbnYuZ2V0RE9NKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaW5pdGlhbGl6ZSgpOiB0aGlzIHtcbiAgICB0aGlzLnB1c2hTaW1wbGVCbG9jaygpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgZGVidWdCbG9ja3MoKTogTGl2ZUJsb2NrW10ge1xuICAgIHJldHVybiB0aGlzLmJsb2NrU3RhY2sudG9BcnJheSgpO1xuICB9XG5cbiAgZ2V0IGVsZW1lbnQoKTogU2ltcGxlRWxlbWVudCB7XG4gICAgcmV0dXJuIHRoaXNbQ1VSU09SX1NUQUNLXS5jdXJyZW50IS5lbGVtZW50O1xuICB9XG5cbiAgZ2V0IG5leHRTaWJsaW5nKCk6IE9wdGlvbjxTaW1wbGVOb2RlPiB7XG4gICAgcmV0dXJuIHRoaXNbQ1VSU09SX1NUQUNLXS5jdXJyZW50IS5uZXh0U2libGluZztcbiAgfVxuXG4gIGdldCBoYXNCbG9ja3MoKSB7XG4gICAgcmV0dXJuIHRoaXMuYmxvY2tTdGFjay5zaXplID4gMDtcbiAgfVxuXG4gIHByb3RlY3RlZCBibG9jaygpOiBMaXZlQmxvY2sge1xuICAgIHJldHVybiBleHBlY3QodGhpcy5ibG9ja1N0YWNrLmN1cnJlbnQsICdFeHBlY3RlZCBhIGN1cnJlbnQgbGl2ZSBibG9jaycpO1xuICB9XG5cbiAgcG9wRWxlbWVudCgpIHtcbiAgICB0aGlzW0NVUlNPUl9TVEFDS10ucG9wKCk7XG4gICAgZXhwZWN0KHRoaXNbQ1VSU09SX1NUQUNLXS5jdXJyZW50LCBcImNhbid0IHBvcCBwYXN0IHRoZSBsYXN0IGVsZW1lbnRcIik7XG4gIH1cblxuICBwdXNoU2ltcGxlQmxvY2soKTogTGl2ZUJsb2NrIHtcbiAgICByZXR1cm4gdGhpcy5wdXNoTGl2ZUJsb2NrKG5ldyBTaW1wbGVMaXZlQmxvY2sodGhpcy5lbGVtZW50KSk7XG4gIH1cblxuICBwdXNoVXBkYXRhYmxlQmxvY2soKTogVXBkYXRhYmxlQmxvY2tJbXBsIHtcbiAgICByZXR1cm4gdGhpcy5wdXNoTGl2ZUJsb2NrKG5ldyBVcGRhdGFibGVCbG9ja0ltcGwodGhpcy5lbGVtZW50KSk7XG4gIH1cblxuICBwdXNoQmxvY2tMaXN0KGxpc3Q6IExpdmVCbG9ja1tdKTogTGl2ZUJsb2NrTGlzdCB7XG4gICAgcmV0dXJuIHRoaXMucHVzaExpdmVCbG9jayhuZXcgTGl2ZUJsb2NrTGlzdCh0aGlzLmVsZW1lbnQsIGxpc3QpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBwdXNoTGl2ZUJsb2NrPFQgZXh0ZW5kcyBMaXZlQmxvY2s+KGJsb2NrOiBULCBpc1JlbW90ZSA9IGZhbHNlKTogVCB7XG4gICAgbGV0IGN1cnJlbnQgPSB0aGlzLmJsb2NrU3RhY2suY3VycmVudDtcblxuICAgIGlmIChjdXJyZW50ICE9PSBudWxsKSB7XG4gICAgICBpZiAoIWlzUmVtb3RlKSB7XG4gICAgICAgIGN1cnJlbnQuZGlkQXBwZW5kQm91bmRzKGJsb2NrKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl9fb3BlbkJsb2NrKCk7XG4gICAgdGhpcy5ibG9ja1N0YWNrLnB1c2goYmxvY2spO1xuICAgIHJldHVybiBibG9jaztcbiAgfVxuXG4gIHBvcEJsb2NrKCk6IExpdmVCbG9jayB7XG4gICAgdGhpcy5ibG9jaygpLmZpbmFsaXplKHRoaXMpO1xuICAgIHRoaXMuX19jbG9zZUJsb2NrKCk7XG4gICAgcmV0dXJuIGV4cGVjdCh0aGlzLmJsb2NrU3RhY2sucG9wKCksICdFeHBlY3RlZCBwb3BCbG9jayB0byByZXR1cm4gYSBibG9jaycpO1xuICB9XG5cbiAgX19vcGVuQmxvY2soKTogdm9pZCB7fVxuICBfX2Nsb3NlQmxvY2soKTogdm9pZCB7fVxuXG4gIC8vIHRvZG8gcmV0dXJuIHNlZW1zIHVudXNlZFxuICBvcGVuRWxlbWVudCh0YWc6IHN0cmluZyk6IFNpbXBsZUVsZW1lbnQge1xuICAgIGxldCBlbGVtZW50ID0gdGhpcy5fX29wZW5FbGVtZW50KHRhZyk7XG4gICAgdGhpcy5jb25zdHJ1Y3RpbmcgPSBlbGVtZW50O1xuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICBfX29wZW5FbGVtZW50KHRhZzogc3RyaW5nKTogU2ltcGxlRWxlbWVudCB7XG4gICAgcmV0dXJuIHRoaXMuZG9tLmNyZWF0ZUVsZW1lbnQodGFnLCB0aGlzLmVsZW1lbnQpO1xuICB9XG5cbiAgZmx1c2hFbGVtZW50KG1vZGlmaWVyczogT3B0aW9uPE1vZGlmaWVySW5zdGFuY2VbXT4pIHtcbiAgICBsZXQgcGFyZW50ID0gdGhpcy5lbGVtZW50O1xuICAgIGxldCBlbGVtZW50ID0gZXhwZWN0KFxuICAgICAgdGhpcy5jb25zdHJ1Y3RpbmcsXG4gICAgICBgZmx1c2hFbGVtZW50IHNob3VsZCBvbmx5IGJlIGNhbGxlZCB3aGVuIGNvbnN0cnVjdGluZyBhbiBlbGVtZW50YFxuICAgICk7XG5cbiAgICB0aGlzLl9fZmx1c2hFbGVtZW50KHBhcmVudCwgZWxlbWVudCk7XG5cbiAgICB0aGlzLmNvbnN0cnVjdGluZyA9IG51bGw7XG4gICAgdGhpcy5vcGVyYXRpb25zID0gbnVsbDtcblxuICAgIHRoaXMucHVzaE1vZGlmaWVycyhtb2RpZmllcnMpO1xuICAgIHRoaXMucHVzaEVsZW1lbnQoZWxlbWVudCwgbnVsbCk7XG4gICAgdGhpcy5kaWRPcGVuRWxlbWVudChlbGVtZW50KTtcbiAgfVxuXG4gIF9fZmx1c2hFbGVtZW50KHBhcmVudDogU2ltcGxlRWxlbWVudCwgY29uc3RydWN0aW5nOiBTaW1wbGVFbGVtZW50KSB7XG4gICAgdGhpcy5kb20uaW5zZXJ0QmVmb3JlKHBhcmVudCwgY29uc3RydWN0aW5nLCB0aGlzLm5leHRTaWJsaW5nKTtcbiAgfVxuXG4gIGNsb3NlRWxlbWVudCgpOiBPcHRpb248TW9kaWZpZXJJbnN0YW5jZVtdPiB7XG4gICAgdGhpcy53aWxsQ2xvc2VFbGVtZW50KCk7XG4gICAgdGhpcy5wb3BFbGVtZW50KCk7XG4gICAgcmV0dXJuIHRoaXMucG9wTW9kaWZpZXJzKCk7XG4gIH1cblxuICBwdXNoUmVtb3RlRWxlbWVudChcbiAgICBlbGVtZW50OiBTaW1wbGVFbGVtZW50LFxuICAgIGd1aWQ6IHN0cmluZyxcbiAgICBpbnNlcnRCZWZvcmU6IE1heWJlPFNpbXBsZU5vZGU+XG4gICk6IE9wdGlvbjxSZW1vdGVMaXZlQmxvY2s+IHtcbiAgICByZXR1cm4gdGhpcy5fX3B1c2hSZW1vdGVFbGVtZW50KGVsZW1lbnQsIGd1aWQsIGluc2VydEJlZm9yZSk7XG4gIH1cblxuICBfX3B1c2hSZW1vdGVFbGVtZW50KFxuICAgIGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQsXG4gICAgX2d1aWQ6IHN0cmluZyxcbiAgICBpbnNlcnRCZWZvcmU6IE1heWJlPFNpbXBsZU5vZGU+XG4gICk6IE9wdGlvbjxSZW1vdGVMaXZlQmxvY2s+IHtcbiAgICB0aGlzLnB1c2hFbGVtZW50KGVsZW1lbnQsIGluc2VydEJlZm9yZSk7XG5cbiAgICBpZiAoaW5zZXJ0QmVmb3JlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHdoaWxlIChlbGVtZW50Lmxhc3RDaGlsZCkge1xuICAgICAgICBlbGVtZW50LnJlbW92ZUNoaWxkKGVsZW1lbnQubGFzdENoaWxkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgYmxvY2sgPSBuZXcgUmVtb3RlTGl2ZUJsb2NrKGVsZW1lbnQpO1xuXG4gICAgcmV0dXJuIHRoaXMucHVzaExpdmVCbG9jayhibG9jaywgdHJ1ZSk7XG4gIH1cblxuICBwb3BSZW1vdGVFbGVtZW50KCkge1xuICAgIHRoaXMucG9wQmxvY2soKTtcbiAgICB0aGlzLnBvcEVsZW1lbnQoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBwdXNoRWxlbWVudChlbGVtZW50OiBTaW1wbGVFbGVtZW50LCBuZXh0U2libGluZzogTWF5YmU8U2ltcGxlTm9kZT4gPSBudWxsKSB7XG4gICAgdGhpc1tDVVJTT1JfU1RBQ0tdLnB1c2gobmV3IEN1cnNvckltcGwoZWxlbWVudCwgbmV4dFNpYmxpbmcpKTtcbiAgfVxuXG4gIHByaXZhdGUgcHVzaE1vZGlmaWVycyhtb2RpZmllcnM6IE9wdGlvbjxNb2RpZmllckluc3RhbmNlW10+KTogdm9pZCB7XG4gICAgdGhpcy5tb2RpZmllclN0YWNrLnB1c2gobW9kaWZpZXJzKTtcbiAgfVxuXG4gIHByaXZhdGUgcG9wTW9kaWZpZXJzKCk6IE9wdGlvbjxNb2RpZmllckluc3RhbmNlW10+IHtcbiAgICByZXR1cm4gdGhpcy5tb2RpZmllclN0YWNrLnBvcCgpO1xuICB9XG5cbiAgZGlkQXBwZW5kQm91bmRzKGJvdW5kczogQm91bmRzKTogQm91bmRzIHtcbiAgICB0aGlzLmJsb2NrKCkuZGlkQXBwZW5kQm91bmRzKGJvdW5kcyk7XG4gICAgcmV0dXJuIGJvdW5kcztcbiAgfVxuXG4gIGRpZEFwcGVuZE5vZGU8VCBleHRlbmRzIFNpbXBsZU5vZGU+KG5vZGU6IFQpOiBUIHtcbiAgICB0aGlzLmJsb2NrKCkuZGlkQXBwZW5kTm9kZShub2RlKTtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIGRpZE9wZW5FbGVtZW50KGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQpOiBTaW1wbGVFbGVtZW50IHtcbiAgICB0aGlzLmJsb2NrKCkub3BlbkVsZW1lbnQoZWxlbWVudCk7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICB3aWxsQ2xvc2VFbGVtZW50KCkge1xuICAgIHRoaXMuYmxvY2soKS5jbG9zZUVsZW1lbnQoKTtcbiAgfVxuXG4gIGFwcGVuZFRleHQoc3RyaW5nOiBzdHJpbmcpOiBTaW1wbGVUZXh0IHtcbiAgICByZXR1cm4gdGhpcy5kaWRBcHBlbmROb2RlKHRoaXMuX19hcHBlbmRUZXh0KHN0cmluZykpO1xuICB9XG5cbiAgX19hcHBlbmRUZXh0KHRleHQ6IHN0cmluZyk6IFNpbXBsZVRleHQge1xuICAgIGxldCB7IGRvbSwgZWxlbWVudCwgbmV4dFNpYmxpbmcgfSA9IHRoaXM7XG4gICAgbGV0IG5vZGUgPSBkb20uY3JlYXRlVGV4dE5vZGUodGV4dCk7XG4gICAgZG9tLmluc2VydEJlZm9yZShlbGVtZW50LCBub2RlLCBuZXh0U2libGluZyk7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICBfX2FwcGVuZE5vZGUobm9kZTogU2ltcGxlTm9kZSk6IFNpbXBsZU5vZGUge1xuICAgIHRoaXMuZG9tLmluc2VydEJlZm9yZSh0aGlzLmVsZW1lbnQsIG5vZGUsIHRoaXMubmV4dFNpYmxpbmcpO1xuICAgIHJldHVybiBub2RlO1xuICB9XG5cbiAgX19hcHBlbmRGcmFnbWVudChmcmFnbWVudDogU2ltcGxlRG9jdW1lbnRGcmFnbWVudCk6IEJvdW5kcyB7XG4gICAgbGV0IGZpcnN0ID0gZnJhZ21lbnQuZmlyc3RDaGlsZDtcblxuICAgIGlmIChmaXJzdCkge1xuICAgICAgbGV0IHJldCA9IG5ldyBDb25jcmV0ZUJvdW5kcyh0aGlzLmVsZW1lbnQsIGZpcnN0LCBmcmFnbWVudC5sYXN0Q2hpbGQhKTtcbiAgICAgIHRoaXMuZG9tLmluc2VydEJlZm9yZSh0aGlzLmVsZW1lbnQsIGZyYWdtZW50LCB0aGlzLm5leHRTaWJsaW5nKTtcbiAgICAgIHJldHVybiByZXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgU2luZ2xlTm9kZUJvdW5kcyh0aGlzLmVsZW1lbnQsIHRoaXMuX19hcHBlbmRDb21tZW50KCcnKSk7XG4gICAgfVxuICB9XG5cbiAgX19hcHBlbmRIVE1MKGh0bWw6IHN0cmluZyk6IEJvdW5kcyB7XG4gICAgcmV0dXJuIHRoaXMuZG9tLmluc2VydEhUTUxCZWZvcmUodGhpcy5lbGVtZW50LCB0aGlzLm5leHRTaWJsaW5nLCBodG1sKTtcbiAgfVxuXG4gIGFwcGVuZER5bmFtaWNIVE1MKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBsZXQgYm91bmRzID0gdGhpcy50cnVzdGVkQ29udGVudCh2YWx1ZSk7XG4gICAgdGhpcy5kaWRBcHBlbmRCb3VuZHMoYm91bmRzKTtcbiAgfVxuXG4gIGFwcGVuZER5bmFtaWNUZXh0KHZhbHVlOiBzdHJpbmcpOiBTaW1wbGVUZXh0IHtcbiAgICBsZXQgbm9kZSA9IHRoaXMudW50cnVzdGVkQ29udGVudCh2YWx1ZSk7XG4gICAgdGhpcy5kaWRBcHBlbmROb2RlKG5vZGUpO1xuICAgIHJldHVybiBub2RlO1xuICB9XG5cbiAgYXBwZW5kRHluYW1pY0ZyYWdtZW50KHZhbHVlOiBTaW1wbGVEb2N1bWVudEZyYWdtZW50KTogdm9pZCB7XG4gICAgbGV0IGJvdW5kcyA9IHRoaXMuX19hcHBlbmRGcmFnbWVudCh2YWx1ZSk7XG4gICAgdGhpcy5kaWRBcHBlbmRCb3VuZHMoYm91bmRzKTtcbiAgfVxuXG4gIGFwcGVuZER5bmFtaWNOb2RlKHZhbHVlOiBTaW1wbGVOb2RlKTogdm9pZCB7XG4gICAgbGV0IG5vZGUgPSB0aGlzLl9fYXBwZW5kTm9kZSh2YWx1ZSk7XG4gICAgbGV0IGJvdW5kcyA9IG5ldyBTaW5nbGVOb2RlQm91bmRzKHRoaXMuZWxlbWVudCwgbm9kZSk7XG4gICAgdGhpcy5kaWRBcHBlbmRCb3VuZHMoYm91bmRzKTtcbiAgfVxuXG4gIHByaXZhdGUgdHJ1c3RlZENvbnRlbnQodmFsdWU6IHN0cmluZyk6IEJvdW5kcyB7XG4gICAgcmV0dXJuIHRoaXMuX19hcHBlbmRIVE1MKHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgdW50cnVzdGVkQ29udGVudCh2YWx1ZTogc3RyaW5nKTogU2ltcGxlVGV4dCB7XG4gICAgcmV0dXJuIHRoaXMuX19hcHBlbmRUZXh0KHZhbHVlKTtcbiAgfVxuXG4gIGFwcGVuZENvbW1lbnQoc3RyaW5nOiBzdHJpbmcpOiBTaW1wbGVDb21tZW50IHtcbiAgICByZXR1cm4gdGhpcy5kaWRBcHBlbmROb2RlKHRoaXMuX19hcHBlbmRDb21tZW50KHN0cmluZykpO1xuICB9XG5cbiAgX19hcHBlbmRDb21tZW50KHN0cmluZzogc3RyaW5nKTogU2ltcGxlQ29tbWVudCB7XG4gICAgbGV0IHsgZG9tLCBlbGVtZW50LCBuZXh0U2libGluZyB9ID0gdGhpcztcbiAgICBsZXQgbm9kZSA9IGRvbS5jcmVhdGVDb21tZW50KHN0cmluZyk7XG4gICAgZG9tLmluc2VydEJlZm9yZShlbGVtZW50LCBub2RlLCBuZXh0U2libGluZyk7XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICBfX3NldEF0dHJpYnV0ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIG5hbWVzcGFjZTogT3B0aW9uPEF0dHJOYW1lc3BhY2U+KTogdm9pZCB7XG4gICAgdGhpcy5kb20uc2V0QXR0cmlidXRlKHRoaXMuY29uc3RydWN0aW5nISwgbmFtZSwgdmFsdWUsIG5hbWVzcGFjZSk7XG4gIH1cblxuICBfX3NldFByb3BlcnR5KG5hbWU6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgICAodGhpcy5jb25zdHJ1Y3RpbmchIGFzIGFueSlbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIHNldFN0YXRpY0F0dHJpYnV0ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIG5hbWVzcGFjZTogT3B0aW9uPEF0dHJOYW1lc3BhY2U+KTogdm9pZCB7XG4gICAgdGhpcy5fX3NldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSwgbmFtZXNwYWNlKTtcbiAgfVxuXG4gIHNldER5bmFtaWNBdHRyaWJ1dGUoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHZhbHVlOiB1bmtub3duLFxuICAgIHRydXN0aW5nOiBib29sZWFuLFxuICAgIG5hbWVzcGFjZTogT3B0aW9uPEF0dHJOYW1lc3BhY2U+XG4gICk6IER5bmFtaWNBdHRyaWJ1dGUge1xuICAgIGxldCBlbGVtZW50ID0gdGhpcy5jb25zdHJ1Y3RpbmchO1xuICAgIGxldCBhdHRyaWJ1dGUgPSBkeW5hbWljQXR0cmlidXRlKGVsZW1lbnQsIG5hbWUsIG5hbWVzcGFjZSwgdHJ1c3RpbmcpO1xuICAgIGF0dHJpYnV0ZS5zZXQodGhpcywgdmFsdWUsIHRoaXMuZW52KTtcbiAgICByZXR1cm4gYXR0cmlidXRlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTaW1wbGVMaXZlQmxvY2sgaW1wbGVtZW50cyBMaXZlQmxvY2sge1xuICBwcm90ZWN0ZWQgZmlyc3Q6IE9wdGlvbjxGaXJzdE5vZGU+ID0gbnVsbDtcbiAgcHJvdGVjdGVkIGxhc3Q6IE9wdGlvbjxMYXN0Tm9kZT4gPSBudWxsO1xuICBwcm90ZWN0ZWQgbmVzdGluZyA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBwYXJlbnQ6IFNpbXBsZUVsZW1lbnQpIHt9XG5cbiAgcGFyZW50RWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnQ7XG4gIH1cblxuICBmaXJzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgbGV0IGZpcnN0ID0gZXhwZWN0KFxuICAgICAgdGhpcy5maXJzdCxcbiAgICAgICdjYW5ub3QgY2FsbCBgZmlyc3ROb2RlKClgIHdoaWxlIGBTaW1wbGVMaXZlQmxvY2tgIGlzIHN0aWxsIGluaXRpYWxpemluZydcbiAgICApO1xuXG4gICAgcmV0dXJuIGZpcnN0LmZpcnN0Tm9kZSgpO1xuICB9XG5cbiAgbGFzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgbGV0IGxhc3QgPSBleHBlY3QoXG4gICAgICB0aGlzLmxhc3QsXG4gICAgICAnY2Fubm90IGNhbGwgYGxhc3ROb2RlKClgIHdoaWxlIGBTaW1wbGVMaXZlQmxvY2tgIGlzIHN0aWxsIGluaXRpYWxpemluZydcbiAgICApO1xuXG4gICAgcmV0dXJuIGxhc3QubGFzdE5vZGUoKTtcbiAgfVxuXG4gIG9wZW5FbGVtZW50KGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQpIHtcbiAgICB0aGlzLmRpZEFwcGVuZE5vZGUoZWxlbWVudCk7XG4gICAgdGhpcy5uZXN0aW5nKys7XG4gIH1cblxuICBjbG9zZUVsZW1lbnQoKSB7XG4gICAgdGhpcy5uZXN0aW5nLS07XG4gIH1cblxuICBkaWRBcHBlbmROb2RlKG5vZGU6IFNpbXBsZU5vZGUpIHtcbiAgICBpZiAodGhpcy5uZXN0aW5nICE9PSAwKSByZXR1cm47XG5cbiAgICBpZiAoIXRoaXMuZmlyc3QpIHtcbiAgICAgIHRoaXMuZmlyc3QgPSBuZXcgRmlyc3Qobm9kZSk7XG4gICAgfVxuXG4gICAgdGhpcy5sYXN0ID0gbmV3IExhc3Qobm9kZSk7XG4gIH1cblxuICBkaWRBcHBlbmRCb3VuZHMoYm91bmRzOiBCb3VuZHMpIHtcbiAgICBpZiAodGhpcy5uZXN0aW5nICE9PSAwKSByZXR1cm47XG5cbiAgICBpZiAoIXRoaXMuZmlyc3QpIHtcbiAgICAgIHRoaXMuZmlyc3QgPSBib3VuZHM7XG4gICAgfVxuXG4gICAgdGhpcy5sYXN0ID0gYm91bmRzO1xuICB9XG5cbiAgZmluYWxpemUoc3RhY2s6IEVsZW1lbnRCdWlsZGVyKSB7XG4gICAgaWYgKHRoaXMuZmlyc3QgPT09IG51bGwpIHtcbiAgICAgIHN0YWNrLmFwcGVuZENvbW1lbnQoJycpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUmVtb3RlTGl2ZUJsb2NrIGV4dGVuZHMgU2ltcGxlTGl2ZUJsb2NrIHtcbiAgY29uc3RydWN0b3IocGFyZW50OiBTaW1wbGVFbGVtZW50KSB7XG4gICAgc3VwZXIocGFyZW50KTtcblxuICAgIHJlZ2lzdGVyRGVzdHJ1Y3Rvcih0aGlzLCAoKSA9PiB7XG4gICAgICAvLyBJbiBnZW5lcmFsLCB5b3Ugb25seSBuZWVkIHRvIGNsZWFyIHRoZSByb290IG9mIGEgaGllcmFyY2h5LCBhbmQgc2hvdWxkIG5ldmVyXG4gICAgICAvLyBuZWVkIHRvIGNsZWFyIGFueSBjaGlsZCBub2Rlcy4gVGhpcyBpcyBhbiBpbXBvcnRhbnQgY29uc3RyYWludCB0aGF0IGdpdmVzIHVzXG4gICAgICAvLyBhIHN0cm9uZyBndWFyYW50ZWUgdGhhdCBjbGVhcmluZyBhIHN1YnRyZWUgaXMgYSBzaW5nbGUgRE9NIG9wZXJhdGlvbi5cbiAgICAgIC8vXG4gICAgICAvLyBCZWNhdXNlIHJlbW90ZSBibG9ja3MgYXJlIG5vdCBub3JtYWxseSBwaHlzaWNhbGx5IG5lc3RlZCBpbnNpZGUgb2YgdGhlIHRyZWVcbiAgICAgIC8vIHRoYXQgdGhleSBhcmUgbG9naWNhbGx5IG5lc3RlZCBpbnNpZGUsIHdlIG1hbnVhbGx5IGNsZWFyIHJlbW90ZSBibG9ja3Mgd2hlblxuICAgICAgLy8gYSBsb2dpY2FsIHBhcmVudCBpcyBjbGVhcmVkLlxuICAgICAgLy9cbiAgICAgIC8vIEhPV0VWRVIsIGl0IGlzIGN1cnJlbnRseSBwb3NzaWJsZSBmb3IgYSByZW1vdGUgYmxvY2sgdG8gYmUgcGh5c2ljYWxseSBuZXN0ZWRcbiAgICAgIC8vIGluc2lkZSBvZiB0aGUgYmxvY2sgaXQgaXMgbG9naWNhbGx5IGNvbnRhaW5lZCBpbnNpZGUgb2YuIFRoaXMgaGFwcGVucyB3aGVuXG4gICAgICAvLyB0aGUgcmVtb3RlIGJsb2NrIGlzIGFwcGVuZGVkIHRvIHRoZSBlbmQgb2YgdGhlIGFwcGxpY2F0aW9uJ3MgZW50aXJlIGVsZW1lbnQuXG4gICAgICAvL1xuICAgICAgLy8gVGhlIHByb2JsZW0gd2l0aCB0aGF0IHNjZW5hcmlvIGlzIHRoYXQgR2xpbW1lciBiZWxpZXZlcyB0aGF0IGl0IG93bnMgbW9yZSBvZlxuICAgICAgLy8gdGhlIERPTSB0aGFuIGl0IGFjdHVhbGx5IGRvZXMuIFRoZSBjb2RlIGlzIGF0dGVtcHRpbmcgdG8gd3JpdGUgcGFzdCB0aGUgZW5kXG4gICAgICAvLyBvZiB0aGUgR2xpbW1lci1tYW5hZ2VkIHJvb3QsIGJ1dCBHbGltbWVyIGlzbid0IGF3YXJlIG9mIHRoYXQuXG4gICAgICAvL1xuICAgICAgLy8gVGhlIGNvcnJlY3Qgc29sdXRpb24gdG8gdGhhdCBwcm9ibGVtIGlzIGZvciBHbGltbWVyIHRvIGJlIGF3YXJlIG9mIHRoZSBlbmRcbiAgICAgIC8vIG9mIHRoZSBib3VuZHMgdGhhdCBpdCBvd25zLCBhbmQgb25jZSB3ZSBtYWtlIHRoYXQgY2hhbmdlLCB0aGlzIGNoZWNrIGNvdWxkXG4gICAgICAvLyBiZSByZW1vdmVkLlxuICAgICAgLy9cbiAgICAgIC8vIEZvciBub3csIGEgbW9yZSB0YXJnZXRlZCBmaXggaXMgdG8gY2hlY2sgd2hldGhlciB0aGUgbm9kZSB3YXMgYWxyZWFkeSByZW1vdmVkXG4gICAgICAvLyBhbmQgYXZvaWQgY2xlYXJpbmcgdGhlIG5vZGUgaWYgaXQgd2FzLiBJbiBtb3N0IGNhc2VzIHRoaXMgc2hvdWxkbid0IGhhcHBlbixcbiAgICAgIC8vIHNvIHRoaXMgbWlnaHQgaGlkZSBidWdzIHdoZXJlIHRoZSBjb2RlIGNsZWFycyBuZXN0ZWQgbm9kZXMgdW5uZWNlc3NhcmlseSxcbiAgICAgIC8vIHNvIHdlIHNob3VsZCBldmVudHVhbGx5IHRyeSB0byBkbyB0aGUgY29ycmVjdCBmaXguXG4gICAgICBpZiAodGhpcy5wYXJlbnRFbGVtZW50KCkgPT09IHRoaXMuZmlyc3ROb2RlKCkucGFyZW50Tm9kZSkge1xuICAgICAgICBjbGVhcih0aGlzKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgVXBkYXRhYmxlQmxvY2tJbXBsIGV4dGVuZHMgU2ltcGxlTGl2ZUJsb2NrIGltcGxlbWVudHMgVXBkYXRhYmxlQmxvY2sge1xuICByZXNldCgpOiBPcHRpb248U2ltcGxlTm9kZT4ge1xuICAgIGRlc3Ryb3kodGhpcyk7XG4gICAgbGV0IG5leHRTaWJsaW5nID0gY2xlYXIodGhpcyk7XG5cbiAgICB0aGlzLmZpcnN0ID0gbnVsbDtcbiAgICB0aGlzLmxhc3QgPSBudWxsO1xuICAgIHRoaXMubmVzdGluZyA9IDA7XG5cbiAgICByZXR1cm4gbmV4dFNpYmxpbmc7XG4gIH1cbn1cblxuLy8gRklYTUU6IEFsbCB0aGUgbm9vcHMgaW4gaGVyZSBpbmRpY2F0ZSBhIG1vZGVsbGluZyBwcm9ibGVtXG5leHBvcnQgY2xhc3MgTGl2ZUJsb2NrTGlzdCBpbXBsZW1lbnRzIExpdmVCbG9jayB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcGFyZW50OiBTaW1wbGVFbGVtZW50LCBwdWJsaWMgYm91bmRMaXN0OiBMaXZlQmxvY2tbXSkge1xuICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgIHRoaXMuYm91bmRMaXN0ID0gYm91bmRMaXN0O1xuICB9XG5cbiAgcGFyZW50RWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnQ7XG4gIH1cblxuICBmaXJzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgbGV0IGhlYWQgPSBleHBlY3QoXG4gICAgICB0aGlzLmJvdW5kTGlzdFswXSxcbiAgICAgICdjYW5ub3QgY2FsbCBgZmlyc3ROb2RlKClgIHdoaWxlIGBMaXZlQmxvY2tMaXN0YCBpcyBzdGlsbCBpbml0aWFsaXppbmcnXG4gICAgKTtcblxuICAgIHJldHVybiBoZWFkLmZpcnN0Tm9kZSgpO1xuICB9XG5cbiAgbGFzdE5vZGUoKTogU2ltcGxlTm9kZSB7XG4gICAgbGV0IGJvdW5kTGlzdCA9IHRoaXMuYm91bmRMaXN0O1xuXG4gICAgbGV0IHRhaWwgPSBleHBlY3QoXG4gICAgICBib3VuZExpc3RbYm91bmRMaXN0Lmxlbmd0aCAtIDFdLFxuICAgICAgJ2Nhbm5vdCBjYWxsIGBsYXN0Tm9kZSgpYCB3aGlsZSBgTGl2ZUJsb2NrTGlzdGAgaXMgc3RpbGwgaW5pdGlhbGl6aW5nJ1xuICAgICk7XG5cbiAgICByZXR1cm4gdGFpbC5sYXN0Tm9kZSgpO1xuICB9XG5cbiAgb3BlbkVsZW1lbnQoX2VsZW1lbnQ6IFNpbXBsZUVsZW1lbnQpIHtcbiAgICBhc3NlcnQoZmFsc2UsICdDYW5ub3Qgb3BlbkVsZW1lbnQgZGlyZWN0bHkgaW5zaWRlIGEgYmxvY2sgbGlzdCcpO1xuICB9XG5cbiAgY2xvc2VFbGVtZW50KCkge1xuICAgIGFzc2VydChmYWxzZSwgJ0Nhbm5vdCBjbG9zZUVsZW1lbnQgZGlyZWN0bHkgaW5zaWRlIGEgYmxvY2sgbGlzdCcpO1xuICB9XG5cbiAgZGlkQXBwZW5kTm9kZShfbm9kZTogU2ltcGxlTm9kZSkge1xuICAgIGFzc2VydChmYWxzZSwgJ0Nhbm5vdCBjcmVhdGUgYSBuZXcgbm9kZSBkaXJlY3RseSBpbnNpZGUgYSBibG9jayBsaXN0Jyk7XG4gIH1cblxuICBkaWRBcHBlbmRCb3VuZHMoX2JvdW5kczogQm91bmRzKSB7fVxuXG4gIGZpbmFsaXplKF9zdGFjazogRWxlbWVudEJ1aWxkZXIpIHtcbiAgICBhc3NlcnQodGhpcy5ib3VuZExpc3QubGVuZ3RoID4gMCwgJ2JvdW5kc0xpc3QgY2Fubm90IGJlIGVtcHR5Jyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudEJ1aWxkZXIoZW52OiBFbnZpcm9ubWVudCwgY3Vyc29yOiBDdXJzb3JJbXBsKTogRWxlbWVudEJ1aWxkZXIge1xuICByZXR1cm4gTmV3RWxlbWVudEJ1aWxkZXIuZm9ySW5pdGlhbFJlbmRlcihlbnYsIGN1cnNvcik7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9