UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

555 lines (441 loc) 53.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSerializationFirstNode = isSerializationFirstNode; exports.rehydrationBuilder = rehydrationBuilder; exports.RehydrateBuilder = exports.RehydratingCursor = exports.SERIALIZATION_FIRST_NODE_STRING = void 0; var _util = require("@glimmer/util"); var _bounds = require("../bounds"); var _elementBuilder = require("./element-builder"); const SERIALIZATION_FIRST_NODE_STRING = '%+b:0%'; exports.SERIALIZATION_FIRST_NODE_STRING = SERIALIZATION_FIRST_NODE_STRING; function isSerializationFirstNode(node) { return node.nodeValue === SERIALIZATION_FIRST_NODE_STRING; } class RehydratingCursor extends _bounds.CursorImpl { constructor(element, nextSibling, startingBlockDepth) { super(element, nextSibling); this.startingBlockDepth = startingBlockDepth; this.candidate = null; this.injectedOmittedNode = false; this.openBlockDepth = startingBlockDepth - 1; } } exports.RehydratingCursor = RehydratingCursor; class RehydrateBuilder extends _elementBuilder.NewElementBuilder { constructor(env, parentNode, nextSibling) { super(env, parentNode, nextSibling); this.unmatchedAttributes = null; this.blockDepth = 0; if (nextSibling) throw new Error('Rehydration with nextSibling not supported'); let node = this.currentCursor.element.firstChild; while (node !== null) { if (isOpenBlock(node)) { break; } node = node.nextSibling; } false && (0, _util.assert)(node, 'Must have opening comment for rehydration.'); this.candidate = node; const startingBlockOffset = getBlockDepth(node); if (startingBlockOffset !== 0) { // We are rehydrating from a partial tree and not the root component // We need to add an extra block before the first block to rehydrate correctly // The extra block is needed since the renderComponent API creates a synthetic component invocation which generates the extra block const newBlockDepth = startingBlockOffset - 1; const newCandidate = this.dom.createComment(`%+b:${newBlockDepth}%`); node.parentNode.insertBefore(newCandidate, this.candidate); let closingNode = node.nextSibling; while (closingNode !== null) { if (isCloseBlock(closingNode) && getBlockDepth(closingNode) === startingBlockOffset) { break; } closingNode = closingNode.nextSibling; } false && (0, _util.assert)(closingNode, 'Must have closing comment for starting block comment'); const newClosingBlock = this.dom.createComment(`%-b:${newBlockDepth}%`); node.parentNode.insertBefore(newClosingBlock, closingNode.nextSibling); this.candidate = newCandidate; this.startingBlockOffset = newBlockDepth; } else { this.startingBlockOffset = 0; } } get currentCursor() { return this[_elementBuilder.CURSOR_STACK].current; } get candidate() { if (this.currentCursor) { return this.currentCursor.candidate; } return null; } set candidate(node) { let currentCursor = this.currentCursor; currentCursor.candidate = node; } disableRehydration(nextSibling) { let currentCursor = this.currentCursor; // rehydration will be disabled until we either: // * hit popElement (and return to using the parent elements cursor) // * hit closeBlock and the next sibling is a close block comment // matching the expected openBlockDepth currentCursor.candidate = null; currentCursor.nextSibling = nextSibling; } enableRehydration(candidate) { let currentCursor = this.currentCursor; currentCursor.candidate = candidate; currentCursor.nextSibling = null; } pushElement(element, nextSibling = null) { let cursor = new RehydratingCursor(element, nextSibling, this.blockDepth || 0); /** * <div> <--------------- currentCursor.element * <!--%+b:1%--> <------- would have been removed during openBlock * <div> <--------------- currentCursor.candidate -> cursor.element * <!--%+b:2%--> <----- currentCursor.candidate.firstChild -> cursor.candidate * Foo * <!--%-b:2%--> * </div> * <!--%-b:1%--> <------ becomes currentCursor.candidate */ if (this.candidate !== null) { cursor.candidate = element.firstChild; this.candidate = element.nextSibling; } this[_elementBuilder.CURSOR_STACK].push(cursor); } // clears until the end of the current container // either the current open block or higher clearMismatch(candidate) { let current = candidate; let currentCursor = this.currentCursor; if (currentCursor !== null) { let openBlockDepth = currentCursor.openBlockDepth; if (openBlockDepth >= currentCursor.startingBlockDepth) { while (current) { if (isCloseBlock(current)) { let closeBlockDepth = getBlockDepthWithOffset(current, this.startingBlockOffset); if (openBlockDepth >= closeBlockDepth) { break; } } current = this.remove(current); } } else { while (current !== null) { current = this.remove(current); } } // current cursor parentNode should be openCandidate if element // or openCandidate.parentNode if comment this.disableRehydration(current); } } __openBlock() { let { currentCursor } = this; if (currentCursor === null) return; let blockDepth = this.blockDepth; this.blockDepth++; let { candidate } = currentCursor; if (candidate === null) return; let { tagName } = currentCursor.element; if (isOpenBlock(candidate) && getBlockDepthWithOffset(candidate, this.startingBlockOffset) === blockDepth) { this.candidate = this.remove(candidate); currentCursor.openBlockDepth = blockDepth; } else if (tagName !== 'TITLE' && tagName !== 'SCRIPT' && tagName !== 'STYLE') { this.clearMismatch(candidate); } } __closeBlock() { let { currentCursor } = this; if (currentCursor === null) return; // openBlock is the last rehydrated open block let openBlockDepth = currentCursor.openBlockDepth; // this currently is the expected next open block depth this.blockDepth--; let { candidate } = currentCursor; let isRehydrating = false; if (candidate !== null) { isRehydrating = true; //assert( // openBlockDepth === this.blockDepth, // 'when rehydrating, openBlockDepth should match this.blockDepth here' //); if (isCloseBlock(candidate) && getBlockDepthWithOffset(candidate, this.startingBlockOffset) === openBlockDepth) { let nextSibling = this.remove(candidate); this.candidate = nextSibling; currentCursor.openBlockDepth--; } else { // close the block and clear mismatch in parent container // we will be either at the end of the element // or at the end of our containing block this.clearMismatch(candidate); isRehydrating = false; } } if (isRehydrating === false) { // check if nextSibling matches our expected close block // if so, we remove the close block comment and // restore rehydration after clearMismatch disabled let nextSibling = currentCursor.nextSibling; if (nextSibling !== null && isCloseBlock(nextSibling) && getBlockDepthWithOffset(nextSibling, this.startingBlockOffset) === this.blockDepth) { // restore rehydration state let candidate = this.remove(nextSibling); this.enableRehydration(candidate); currentCursor.openBlockDepth--; } } } __appendNode(node) { let { candidate } = this; // This code path is only used when inserting precisely one node. It needs more // comparison logic, but we can probably lean on the cases where this code path // is actually used. if (candidate) { return candidate; } else { return super.__appendNode(node); } } __appendHTML(html) { let candidateBounds = this.markerBounds(); if (candidateBounds) { let first = candidateBounds.firstNode(); let last = candidateBounds.lastNode(); let newBounds = new _bounds.ConcreteBounds(this.element, first.nextSibling, last.previousSibling); let possibleEmptyMarker = this.remove(first); this.remove(last); if (possibleEmptyMarker !== null && isEmpty(possibleEmptyMarker)) { this.candidate = this.remove(possibleEmptyMarker); if (this.candidate !== null) { this.clearMismatch(this.candidate); } } return newBounds; } else { return super.__appendHTML(html); } } remove(node) { let element = node.parentNode; let next = node.nextSibling; element.removeChild(node); return next; } markerBounds() { let _candidate = this.candidate; if (_candidate && isMarker(_candidate)) { let first = _candidate; let last = first.nextSibling; while (last && !isMarker(last)) { last = last.nextSibling; } return new _bounds.ConcreteBounds(this.element, first, last); } else { return null; } } __appendText(string) { let { candidate } = this; if (candidate) { if (isTextNode(candidate)) { if (candidate.nodeValue !== string) { candidate.nodeValue = string; } this.candidate = candidate.nextSibling; return candidate; } else if (isSeparator(candidate)) { this.candidate = this.remove(candidate); return this.__appendText(string); } else if (isEmpty(candidate) && string === '') { this.candidate = this.remove(candidate); return this.__appendText(string); } else { this.clearMismatch(candidate); return super.__appendText(string); } } else { return super.__appendText(string); } } __appendComment(string) { let _candidate = this.candidate; if (_candidate && isComment(_candidate)) { if (_candidate.nodeValue !== string) { _candidate.nodeValue = string; } this.candidate = _candidate.nextSibling; return _candidate; } else if (_candidate) { this.clearMismatch(_candidate); } return super.__appendComment(string); } __openElement(tag) { let _candidate = this.candidate; if (_candidate && isElement(_candidate) && isSameNodeType(_candidate, tag)) { this.unmatchedAttributes = [].slice.call(_candidate.attributes); return _candidate; } else if (_candidate) { if (isElement(_candidate) && _candidate.tagName === 'TBODY') { this.pushElement(_candidate, null); this.currentCursor.injectedOmittedNode = true; return this.__openElement(tag); } this.clearMismatch(_candidate); } return super.__openElement(tag); } __setAttribute(name, value, namespace) { let unmatched = this.unmatchedAttributes; if (unmatched) { let attr = findByName(unmatched, name); if (attr) { if (attr.value !== value) { attr.value = value; } unmatched.splice(unmatched.indexOf(attr), 1); return; } } return super.__setAttribute(name, value, namespace); } __setProperty(name, value) { let unmatched = this.unmatchedAttributes; if (unmatched) { let attr = findByName(unmatched, name); if (attr) { if (attr.value !== value) { attr.value = value; } unmatched.splice(unmatched.indexOf(attr), 1); return; } } return super.__setProperty(name, value); } __flushElement(parent, constructing) { let { unmatchedAttributes: unmatched } = this; if (unmatched) { for (let i = 0; i < unmatched.length; i++) { this.constructing.removeAttribute(unmatched[i].name); } this.unmatchedAttributes = null; } else { super.__flushElement(parent, constructing); } } willCloseElement() { let { candidate, currentCursor } = this; if (candidate !== null) { this.clearMismatch(candidate); } if (currentCursor && currentCursor.injectedOmittedNode) { this.popElement(); } super.willCloseElement(); } getMarker(element, guid) { let marker = element.querySelector(`script[glmr="${guid}"]`); if (marker) { return marker; } return null; } __pushRemoteElement(element, cursorId, insertBefore) { let marker = this.getMarker(element, cursorId); false && (0, _util.assert)(!marker || marker.parentNode === element, `expected remote element marker's parent node to match remote element`); // when insertBefore is not present, we clear the element if (insertBefore === undefined) { while (element.firstChild !== null && element.firstChild !== marker) { this.remove(element.firstChild); } insertBefore = null; } let cursor = new RehydratingCursor(element, null, this.blockDepth); this[_elementBuilder.CURSOR_STACK].push(cursor); if (marker === null) { this.disableRehydration(insertBefore); } else { this.candidate = this.remove(marker); } let block = new _elementBuilder.RemoteLiveBlock(element); return this.pushLiveBlock(block, true); } didAppendBounds(bounds) { super.didAppendBounds(bounds); if (this.candidate) { let last = bounds.lastNode(); this.candidate = last && last.nextSibling; } return bounds; } } exports.RehydrateBuilder = RehydrateBuilder; function isTextNode(node) { return node.nodeType === 3; } function isComment(node) { return node.nodeType === 8; } function isOpenBlock(node) { return node.nodeType === 8 /* COMMENT_NODE */ && node.nodeValue.lastIndexOf('%+b:', 0) === 0; } function isCloseBlock(node) { return node.nodeType === 8 /* COMMENT_NODE */ && node.nodeValue.lastIndexOf('%-b:', 0) === 0; } function getBlockDepth(node) { return parseInt(node.nodeValue.slice(4), 10); } function getBlockDepthWithOffset(node, offset) { return getBlockDepth(node) - offset; } function isElement(node) { return node.nodeType === 1; } function isMarker(node) { return node.nodeType === 8 && node.nodeValue === '%glmr%'; } function isSeparator(node) { return node.nodeType === 8 && node.nodeValue === '%|%'; } function isEmpty(node) { return node.nodeType === 8 && node.nodeValue === '% %'; } function isSameNodeType(candidate, tag) { if (candidate.namespaceURI === "http://www.w3.org/2000/svg" /* SVG */ ) { return candidate.tagName === tag; } return candidate.tagName === tag.toUpperCase(); } function findByName(array, name) { for (let i = 0; i < array.length; i++) { let attr = array[i]; if (attr.name === name) return attr; } return undefined; } function rehydrationBuilder(env, cursor) { return RehydrateBuilder.forInitialRender(env, cursor); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL3JlaHlkcmF0ZS1idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUNBOztBQVdBOztBQUNBOztBQUVPLE1BQU0sK0JBQStCLEdBQXJDLFFBQUE7OztBQUVELFNBQUEsd0JBQUEsQ0FBQSxJQUFBLEVBQW1EO0FBQ3ZELFNBQU8sSUFBSSxDQUFKLFNBQUEsS0FBUCwrQkFBQTtBQUNEOztBQUVLLE1BQUEsaUJBQUEsU0FBQSxrQkFBQSxDQUEyQztBQUkvQyxFQUFBLFdBQUEsQ0FBQSxPQUFBLEVBQUEsV0FBQSxFQUFBLGtCQUFBLEVBRzRDO0FBRTFDLFVBQUEsT0FBQSxFQUFBLFdBQUE7QUFGZ0IsU0FBQSxrQkFBQSxHQUFBLGtCQUFBO0FBTmxCLFNBQUEsU0FBQSxHQUFBLElBQUE7QUFFQSxTQUFBLG1CQUFBLEdBQUEsS0FBQTtBQU9FLFNBQUEsY0FBQSxHQUFzQixrQkFBa0IsR0FBeEMsQ0FBQTtBQUNEOztBQVg4Qzs7OztBQWMzQyxNQUFBLGdCQUFBLFNBQUEsaUNBQUEsQ0FBaUQ7QUFNckQsRUFBQSxXQUFBLENBQUEsR0FBQSxFQUFBLFVBQUEsRUFBQSxXQUFBLEVBQXdGO0FBQ3RGLFVBQUEsR0FBQSxFQUFBLFVBQUEsRUFBQSxXQUFBO0FBTk0sU0FBQSxtQkFBQSxHQUFBLElBQUE7QUFFUixTQUFBLFVBQUEsR0FBQSxDQUFBO0FBS0UsUUFBQSxXQUFBLEVBQWlCLE1BQU0sSUFBQSxLQUFBLENBQU4sNENBQU0sQ0FBTjtBQUVqQixRQUFJLElBQUksR0FBRyxLQUFBLGFBQUEsQ0FBQSxPQUFBLENBQVgsVUFBQTs7QUFFQSxXQUFPLElBQUksS0FBWCxJQUFBLEVBQXNCO0FBQ3BCLFVBQUksV0FBVyxDQUFmLElBQWUsQ0FBZixFQUF1QjtBQUNyQjtBQUNEOztBQUNELE1BQUEsSUFBSSxHQUFHLElBQUksQ0FBWCxXQUFBO0FBQ0Q7O0FBWHFG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S0FBQSxDQUFBLElBQXVCLElBQUksQ0FBSixTQUFBLEtBQTlCLFFBQUE7QUFDRDs7QUFFRCxTQUFBLFdBQUEsQ0FBQSxJQUFBLEVBQXFDO0FBQ25DLFNBQU8sSUFBSSxDQUFKLFFBQUEsS0FBQSxDQUFBLElBQXVCLElBQUksQ0FBSixTQUFBLEtBQTlCLEtBQUE7QUFDRDs7QUFFRCxTQUFBLE9BQUEsQ0FBQSxJQUFBLEVBQWlDO0FBQy9CLFNBQU8sSUFBSSxDQUFKLFFBQUEsS0FBQSxDQUFBLElBQXVCLElBQUksQ0FBSixTQUFBLEtBQTlCLEtBQUE7QUFDRDs7QUFFRCxTQUFBLGNBQUEsQ0FBQSxTQUFBLEVBQUEsR0FBQSxFQUE2RDtBQUMzRCxNQUFJLFNBQVMsQ0FBVCxZQUFBLEtBQXNCO0FBQUE7QUFBMUIsSUFBOEM7QUFDNUMsYUFBTyxTQUFTLENBQVQsT0FBQSxLQUFQLEdBQUE7QUFDRDs7QUFDRCxTQUFPLFNBQVMsQ0FBVCxPQUFBLEtBQXNCLEdBQUcsQ0FBaEMsV0FBNkIsRUFBN0I7QUFDRDs7QUFFRCxTQUFBLFVBQUEsQ0FBQSxLQUFBLEVBQUEsSUFBQSxFQUFxRDtBQUNuRCxPQUFLLElBQUksQ0FBQyxHQUFWLENBQUEsRUFBZ0IsQ0FBQyxHQUFHLEtBQUssQ0FBekIsTUFBQSxFQUFrQyxDQUFsQyxFQUFBLEVBQXVDO0FBQ3JDLFFBQUksSUFBSSxHQUFHLEtBQUssQ0FBaEIsQ0FBZ0IsQ0FBaEI7QUFDQSxRQUFJLElBQUksQ0FBSixJQUFBLEtBQUosSUFBQSxFQUF3QixPQUFBLElBQUE7QUFDekI7O0FBRUQsU0FBQSxTQUFBO0FBQ0Q7O0FBRUssU0FBQSxrQkFBQSxDQUFBLEdBQUEsRUFBQSxNQUFBLEVBQWlFO0FBQ3JFLFNBQU8sZ0JBQWdCLENBQWhCLGdCQUFBLENBQUEsR0FBQSxFQUFQLE1BQU8sQ0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQm91bmRzLCBFbGVtZW50QnVpbGRlciwgRW52aXJvbm1lbnQsIE9wdGlvbiwgTWF5YmUgfSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IGFzc2VydCwgY2FzdFRvQnJvd3NlciwgY2FzdFRvU2ltcGxlLCBleHBlY3QsIFN0YWNrIH0gZnJvbSAnQGdsaW1tZXIvdXRpbCc7XG5pbXBvcnQge1xuICBBdHRyTmFtZXNwYWNlLFxuICBOYW1lc3BhY2UsXG4gIE5vZGVUeXBlLFxuICBTaW1wbGVBdHRyLFxuICBTaW1wbGVDb21tZW50LFxuICBTaW1wbGVFbGVtZW50LFxuICBTaW1wbGVOb2RlLFxuICBTaW1wbGVUZXh0LFxufSBmcm9tICdAc2ltcGxlLWRvbS9pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ29uY3JldGVCb3VuZHMsIEN1cnNvckltcGwgfSBmcm9tICcuLi9ib3VuZHMnO1xuaW1wb3J0IHsgQ1VSU09SX1NUQUNLLCBOZXdFbGVtZW50QnVpbGRlciwgUmVtb3RlTGl2ZUJsb2NrIH0gZnJvbSAnLi9lbGVtZW50LWJ1aWxkZXInO1xuXG5leHBvcnQgY29uc3QgU0VSSUFMSVpBVElPTl9GSVJTVF9OT0RFX1NUUklORyA9ICclK2I6MCUnO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlKG5vZGU6IFNpbXBsZU5vZGUpOiBib29sZWFuIHtcbiAgcmV0dXJuIG5vZGUubm9kZVZhbHVlID09PSBTRVJJQUxJWkFUSU9OX0ZJUlNUX05PREVfU1RSSU5HO1xufVxuXG5leHBvcnQgY2xhc3MgUmVoeWRyYXRpbmdDdXJzb3IgZXh0ZW5kcyBDdXJzb3JJbXBsIHtcbiAgY2FuZGlkYXRlOiBPcHRpb248U2ltcGxlTm9kZT4gPSBudWxsO1xuICBvcGVuQmxvY2tEZXB0aDogbnVtYmVyO1xuICBpbmplY3RlZE9taXR0ZWROb2RlID0gZmFsc2U7XG4gIGNvbnN0cnVjdG9yKFxuICAgIGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQsXG4gICAgbmV4dFNpYmxpbmc6IE9wdGlvbjxTaW1wbGVOb2RlPixcbiAgICBwdWJsaWMgcmVhZG9ubHkgc3RhcnRpbmdCbG9ja0RlcHRoOiBudW1iZXJcbiAgKSB7XG4gICAgc3VwZXIoZWxlbWVudCwgbmV4dFNpYmxpbmcpO1xuICAgIHRoaXMub3BlbkJsb2NrRGVwdGggPSBzdGFydGluZ0Jsb2NrRGVwdGggLSAxO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBSZWh5ZHJhdGVCdWlsZGVyIGV4dGVuZHMgTmV3RWxlbWVudEJ1aWxkZXIgaW1wbGVtZW50cyBFbGVtZW50QnVpbGRlciB7XG4gIHByaXZhdGUgdW5tYXRjaGVkQXR0cmlidXRlczogT3B0aW9uPFNpbXBsZUF0dHJbXT4gPSBudWxsO1xuICBbQ1VSU09SX1NUQUNLXSE6IFN0YWNrPFJlaHlkcmF0aW5nQ3Vyc29yPjsgLy8gSGlkZXMgcHJvcGVydHkgb24gYmFzZSBjbGFzc1xuICBibG9ja0RlcHRoID0gMDtcbiAgc3RhcnRpbmdCbG9ja09mZnNldDogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGVudjogRW52aXJvbm1lbnQsIHBhcmVudE5vZGU6IFNpbXBsZUVsZW1lbnQsIG5leHRTaWJsaW5nOiBPcHRpb248U2ltcGxlTm9kZT4pIHtcbiAgICBzdXBlcihlbnYsIHBhcmVudE5vZGUsIG5leHRTaWJsaW5nKTtcbiAgICBpZiAobmV4dFNpYmxpbmcpIHRocm93IG5ldyBFcnJvcignUmVoeWRyYXRpb24gd2l0aCBuZXh0U2libGluZyBub3Qgc3VwcG9ydGVkJyk7XG5cbiAgICBsZXQgbm9kZSA9IHRoaXMuY3VycmVudEN1cnNvciEuZWxlbWVudC5maXJzdENoaWxkO1xuXG4gICAgd2hpbGUgKG5vZGUgIT09IG51bGwpIHtcbiAgICAgIGlmIChpc09wZW5CbG9jayhub2RlKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIG5vZGUgPSBub2RlLm5leHRTaWJsaW5nO1xuICAgIH1cblxuICAgIGFzc2VydChub2RlLCAnTXVzdCBoYXZlIG9wZW5pbmcgY29tbWVudCBmb3IgcmVoeWRyYXRpb24uJyk7XG4gICAgdGhpcy5jYW5kaWRhdGUgPSBub2RlO1xuICAgIGNvbnN0IHN0YXJ0aW5nQmxvY2tPZmZzZXQgPSBnZXRCbG9ja0RlcHRoKG5vZGUgYXMgU2ltcGxlQ29tbWVudCk7XG4gICAgaWYgKHN0YXJ0aW5nQmxvY2tPZmZzZXQgIT09IDApIHtcbiAgICAgIC8vIFdlIGFyZSByZWh5ZHJhdGluZyBmcm9tIGEgcGFydGlhbCB0cmVlIGFuZCBub3QgdGhlIHJvb3QgY29tcG9uZW50XG4gICAgICAvLyBXZSBuZWVkIHRvIGFkZCBhbiBleHRyYSBibG9jayBiZWZvcmUgdGhlIGZpcnN0IGJsb2NrIHRvIHJlaHlkcmF0ZSBjb3JyZWN0bHlcbiAgICAgIC8vIFRoZSBleHRyYSBibG9jayBpcyBuZWVkZWQgc2luY2UgdGhlIHJlbmRlckNvbXBvbmVudCBBUEkgY3JlYXRlcyBhIHN5bnRoZXRpYyBjb21wb25lbnQgaW52b2NhdGlvbiB3aGljaCBnZW5lcmF0ZXMgdGhlIGV4dHJhIGJsb2NrXG4gICAgICBjb25zdCBuZXdCbG9ja0RlcHRoID0gc3RhcnRpbmdCbG9ja09mZnNldCAtIDE7XG4gICAgICBjb25zdCBuZXdDYW5kaWRhdGUgPSB0aGlzLmRvbS5jcmVhdGVDb21tZW50KGAlK2I6JHtuZXdCbG9ja0RlcHRofSVgKTtcblxuICAgICAgbm9kZSEucGFyZW50Tm9kZSEuaW5zZXJ0QmVmb3JlKG5ld0NhbmRpZGF0ZSwgdGhpcy5jYW5kaWRhdGUpO1xuICAgICAgbGV0IGNsb3NpbmdOb2RlID0gbm9kZSEubmV4dFNpYmxpbmc7XG4gICAgICB3aGlsZSAoY2xvc2luZ05vZGUgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKGlzQ2xvc2VCbG9jayhjbG9zaW5nTm9kZSkgJiYgZ2V0QmxvY2tEZXB0aChjbG9zaW5nTm9kZSkgPT09IHN0YXJ0aW5nQmxvY2tPZmZzZXQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjbG9zaW5nTm9kZSA9IGNsb3NpbmdOb2RlLm5leHRTaWJsaW5nO1xuICAgICAgfVxuXG4gICAgICBhc3NlcnQoY2xvc2luZ05vZGUsICdNdXN0IGhhdmUgY2xvc2luZyBjb21tZW50IGZvciBzdGFydGluZyBibG9jayBjb21tZW50Jyk7XG4gICAgICBjb25zdCBuZXdDbG9zaW5nQmxvY2sgPSB0aGlzLmRvbS5jcmVhdGVDb21tZW50KGAlLWI6JHtuZXdCbG9ja0RlcHRofSVgKTtcbiAgICAgIG5vZGUhLnBhcmVudE5vZGUhLmluc2VydEJlZm9yZShuZXdDbG9zaW5nQmxvY2ssIGNsb3NpbmdOb2RlIS5uZXh0U2libGluZyk7XG4gICAgICB0aGlzLmNhbmRpZGF0ZSA9IG5ld0NhbmRpZGF0ZTtcbiAgICAgIHRoaXMuc3RhcnRpbmdCbG9ja09mZnNldCA9IG5ld0Jsb2NrRGVwdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3RhcnRpbmdCbG9ja09mZnNldCA9IDA7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGN1cnJlbnRDdXJzb3IoKTogT3B0aW9uPFJlaHlkcmF0aW5nQ3Vyc29yPiB7XG4gICAgcmV0dXJuIHRoaXNbQ1VSU09SX1NUQUNLXS5jdXJyZW50O1xuICB9XG5cbiAgZ2V0IGNhbmRpZGF0ZSgpOiBPcHRpb248U2ltcGxlTm9kZT4ge1xuICAgIGlmICh0aGlzLmN1cnJlbnRDdXJzb3IpIHtcbiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlITtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHNldCBjYW5kaWRhdGUobm9kZTogT3B0aW9uPFNpbXBsZU5vZGU+KSB7XG4gICAgbGV0IGN1cnJlbnRDdXJzb3IgPSB0aGlzLmN1cnJlbnRDdXJzb3IhO1xuXG4gICAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUgPSBub2RlO1xuICB9XG5cbiAgZGlzYWJsZVJlaHlkcmF0aW9uKG5leHRTaWJsaW5nOiBPcHRpb248U2ltcGxlTm9kZT4pIHtcbiAgICBsZXQgY3VycmVudEN1cnNvciA9IHRoaXMuY3VycmVudEN1cnNvciE7XG5cbiAgICAvLyByZWh5ZHJhdGlvbiB3aWxsIGJlIGRpc2FibGVkIHVudGlsIHdlIGVpdGhlcjpcbiAgICAvLyAqIGhpdCBwb3BFbGVtZW50IChhbmQgcmV0dXJuIHRvIHVzaW5nIHRoZSBwYXJlbnQgZWxlbWVudHMgY3Vyc29yKVxuICAgIC8vICogaGl0IGNsb3NlQmxvY2sgYW5kIHRoZSBuZXh0IHNpYmxpbmcgaXMgYSBjbG9zZSBibG9jayBjb21tZW50XG4gICAgLy8gICBtYXRjaGluZyB0aGUgZXhwZWN0ZWQgb3BlbkJsb2NrRGVwdGhcbiAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IG51bGw7XG4gICAgY3VycmVudEN1cnNvci5uZXh0U2libGluZyA9IG5leHRTaWJsaW5nO1xuICB9XG5cbiAgZW5hYmxlUmVoeWRyYXRpb24oY2FuZGlkYXRlOiBPcHRpb248U2ltcGxlTm9kZT4pIHtcbiAgICBsZXQgY3VycmVudEN1cnNvciA9IHRoaXMuY3VycmVudEN1cnNvciE7XG5cbiAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IGNhbmRpZGF0ZTtcbiAgICBjdXJyZW50Q3Vyc29yLm5leHRTaWJsaW5nID0gbnVsbDtcbiAgfVxuXG4gIHB1c2hFbGVtZW50KFxuICAgIC8qKiBjYWxsZWQgZnJvbSBwYXJlbnQgY29uc3RydWN0b3IgYmVmb3JlIHdlIGluaXRpYWxpemUgdGhpcyAqL1xuICAgIHRoaXM6XG4gICAgICB8IFJlaHlkcmF0ZUJ1aWxkZXJcbiAgICAgIHwgKE5ld0VsZW1lbnRCdWlsZGVyICYgUGFydGlhbDxQaWNrPFJlaHlkcmF0ZUJ1aWxkZXIsICdibG9ja0RlcHRoJyB8ICdjYW5kaWRhdGUnPj4pLFxuICAgIGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQsXG4gICAgbmV4dFNpYmxpbmc6IE1heWJlPFNpbXBsZU5vZGU+ID0gbnVsbFxuICApIHtcbiAgICBsZXQgY3Vyc29yID0gbmV3IFJlaHlkcmF0aW5nQ3Vyc29yKGVsZW1lbnQsIG5leHRTaWJsaW5nLCB0aGlzLmJsb2NrRGVwdGggfHwgMCk7XG5cbiAgICAvKipcbiAgICAgKiA8ZGl2PiAgIDwtLS0tLS0tLS0tLS0tLS0gIGN1cnJlbnRDdXJzb3IuZWxlbWVudFxuICAgICAqICAgPCEtLSUrYjoxJS0tPiA8LS0tLS0tLSAgd291bGQgaGF2ZSBiZWVuIHJlbW92ZWQgZHVyaW5nIG9wZW5CbG9ja1xuICAgICAqICAgPGRpdj4gPC0tLS0tLS0tLS0tLS0tLSAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUgLT4gY3Vyc29yLmVsZW1lbnRcbiAgICAgKiAgICAgPCEtLSUrYjoyJS0tPiA8LS0tLS0gIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlLmZpcnN0Q2hpbGQgLT4gY3Vyc29yLmNhbmRpZGF0ZVxuICAgICAqICAgICBGb29cbiAgICAgKiAgICAgPCEtLSUtYjoyJS0tPlxuICAgICAqICAgPC9kaXY+XG4gICAgICogICA8IS0tJS1iOjElLS0+ICA8LS0tLS0tICBiZWNvbWVzIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlXG4gICAgICovXG4gICAgaWYgKHRoaXMuY2FuZGlkYXRlICE9PSBudWxsKSB7XG4gICAgICBjdXJzb3IuY2FuZGlkYXRlID0gZWxlbWVudC5maXJzdENoaWxkO1xuICAgICAgdGhpcy5jYW5kaWRhdGUgPSBlbGVtZW50Lm5leHRTaWJsaW5nO1xuICAgIH1cblxuICAgIHRoaXNbQ1VSU09SX1NUQUNLXS5wdXNoKGN1cnNvcik7XG4gIH1cblxuICAvLyBjbGVhcnMgdW50aWwgdGhlIGVuZCBvZiB0aGUgY3VycmVudCBjb250YWluZXJcbiAgLy8gZWl0aGVyIHRoZSBjdXJyZW50IG9wZW4gYmxvY2sgb3IgaGlnaGVyXG4gIHByaXZhdGUgY2xlYXJNaXNtYXRjaChjYW5kaWRhdGU6IFNpbXBsZU5vZGUpIHtcbiAgICBsZXQgY3VycmVudDogT3B0aW9uPFNpbXBsZU5vZGU+ID0gY2FuZGlkYXRlO1xuICAgIGxldCBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yO1xuICAgIGlmIChjdXJyZW50Q3Vyc29yICE9PSBudWxsKSB7XG4gICAgICBsZXQgb3BlbkJsb2NrRGVwdGggPSBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoO1xuICAgICAgaWYgKG9wZW5CbG9ja0RlcHRoID49IGN1cnJlbnRDdXJzb3Iuc3RhcnRpbmdCbG9ja0RlcHRoKSB7XG4gICAgICAgIHdoaWxlIChjdXJyZW50KSB7XG4gICAgICAgICAgaWYgKGlzQ2xvc2VCbG9jayhjdXJyZW50KSkge1xuICAgICAgICAgICAgbGV0IGNsb3NlQmxvY2tEZXB0aCA9IGdldEJsb2NrRGVwdGhXaXRoT2Zmc2V0KGN1cnJlbnQsIHRoaXMuc3RhcnRpbmdCbG9ja09mZnNldCk7XG4gICAgICAgICAgICBpZiAob3BlbkJsb2NrRGVwdGggPj0gY2xvc2VCbG9ja0RlcHRoKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjdXJyZW50ID0gdGhpcy5yZW1vdmUoY3VycmVudCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdoaWxlIChjdXJyZW50ICE9PSBudWxsKSB7XG4gICAgICAgICAgY3VycmVudCA9IHRoaXMucmVtb3ZlKGN1cnJlbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBjdXJyZW50IGN1cnNvciBwYXJlbnROb2RlIHNob3VsZCBiZSBvcGVuQ2FuZGlkYXRlIGlmIGVsZW1lbnRcbiAgICAgIC8vIG9yIG9wZW5DYW5kaWRhdGUucGFyZW50Tm9kZSBpZiBjb21tZW50XG4gICAgICB0aGlzLmRpc2FibGVSZWh5ZHJhdGlvbihjdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICBfX29wZW5CbG9jaygpOiB2b2lkIHtcbiAgICBsZXQgeyBjdXJyZW50Q3Vyc29yIH0gPSB0aGlzO1xuICAgIGlmIChjdXJyZW50Q3Vyc29yID09PSBudWxsKSByZXR1cm47XG5cbiAgICBsZXQgYmxvY2tEZXB0aCA9IHRoaXMuYmxvY2tEZXB0aDtcblxuICAgIHRoaXMuYmxvY2tEZXB0aCsrO1xuXG4gICAgbGV0IHsgY2FuZGlkYXRlIH0gPSBjdXJyZW50Q3Vyc29yO1xuICAgIGlmIChjYW5kaWRhdGUgPT09IG51bGwpIHJldHVybjtcblxuICAgIGxldCB7IHRhZ05hbWUgfSA9IGN1cnJlbnRDdXJzb3IuZWxlbWVudDtcblxuICAgIGlmIChcbiAgICAgIGlzT3BlbkJsb2NrKGNhbmRpZGF0ZSkgJiZcbiAgICAgIGdldEJsb2NrRGVwdGhXaXRoT2Zmc2V0KGNhbmRpZGF0ZSwgdGhpcy5zdGFydGluZ0Jsb2NrT2Zmc2V0KSA9PT0gYmxvY2tEZXB0aFxuICAgICkge1xuICAgICAgdGhpcy5jYW5kaWRhdGUgPSB0aGlzLnJlbW92ZShjYW5kaWRhdGUpO1xuICAgICAgY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aCA9IGJsb2NrRGVwdGg7XG4gICAgfSBlbHNlIGlmICh0YWdOYW1lICE9PSAnVElUTEUnICYmIHRhZ05hbWUgIT09ICdTQ1JJUFQnICYmIHRhZ05hbWUgIT09ICdTVFlMRScpIHtcbiAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpO1xuICAgIH1cbiAgfVxuXG4gIF9fY2xvc2VCbG9jaygpOiB2b2lkIHtcbiAgICBsZXQgeyBjdXJyZW50Q3Vyc29yIH0gPSB0aGlzO1xuICAgIGlmIChjdXJyZW50Q3Vyc29yID09PSBudWxsKSByZXR1cm47XG5cbiAgICAvLyBvcGVuQmxvY2sgaXMgdGhlIGxhc3QgcmVoeWRyYXRlZCBvcGVuIGJsb2NrXG4gICAgbGV0IG9wZW5CbG9ja0RlcHRoID0gY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aDtcblxuICAgIC8vIHRoaXMgY3VycmVudGx5IGlzIHRoZSBleHBlY3RlZCBuZXh0IG9wZW4gYmxvY2sgZGVwdGhcbiAgICB0aGlzLmJsb2NrRGVwdGgtLTtcblxuICAgIGxldCB7IGNhbmRpZGF0ZSB9ID0gY3VycmVudEN1cnNvcjtcblxuICAgIGxldCBpc1JlaHlkcmF0aW5nID0gZmFsc2U7XG5cbiAgICBpZiAoY2FuZGlkYXRlICE9PSBudWxsKSB7XG4gICAgICBpc1JlaHlkcmF0aW5nID0gdHJ1ZTtcbiAgICAgIC8vYXNzZXJ0KFxuICAgICAgLy8gIG9wZW5CbG9ja0RlcHRoID09PSB0aGlzLmJsb2NrRGVwdGgsXG4gICAgICAvLyAgJ3doZW4gcmVoeWRyYXRpbmcsIG9wZW5CbG9ja0RlcHRoIHNob3VsZCBtYXRjaCB0aGlzLmJsb2NrRGVwdGggaGVyZSdcbiAgICAgIC8vKTtcblxuICAgICAgaWYgKFxuICAgICAgICBpc0Nsb3NlQmxvY2soY2FuZGlkYXRlKSAmJlxuICAgICAgICBnZXRCbG9ja0RlcHRoV2l0aE9mZnNldChjYW5kaWRhdGUsIHRoaXMuc3RhcnRpbmdCbG9ja09mZnNldCkgPT09IG9wZW5CbG9ja0RlcHRoXG4gICAgICApIHtcbiAgICAgICAgbGV0IG5leHRTaWJsaW5nID0gdGhpcy5yZW1vdmUoY2FuZGlkYXRlKTtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBuZXh0U2libGluZztcbiAgICAgICAgY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aC0tO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gY2xvc2UgdGhlIGJsb2NrIGFuZCBjbGVhciBtaXNtYXRjaCBpbiBwYXJlbnQgY29udGFpbmVyXG4gICAgICAgIC8vIHdlIHdpbGwgYmUgZWl0aGVyIGF0IHRoZSBlbmQgb2YgdGhlIGVsZW1lbnRcbiAgICAgICAgLy8gb3IgYXQgdGhlIGVuZCBvZiBvdXIgY29udGFpbmluZyBibG9ja1xuICAgICAgICB0aGlzLmNsZWFyTWlzbWF0Y2goY2FuZGlkYXRlKTtcbiAgICAgICAgaXNSZWh5ZHJhdGluZyA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpc1JlaHlkcmF0aW5nID09PSBmYWxzZSkge1xuICAgICAgLy8gY2hlY2sgaWYgbmV4dFNpYmxpbmcgbWF0Y2hlcyBvdXIgZXhwZWN0ZWQgY2xvc2UgYmxvY2tcbiAgICAgIC8vIGlmIHNvLCB3ZSByZW1vdmUgdGhlIGNsb3NlIGJsb2NrIGNvbW1lbnQgYW5kXG4gICAgICAvLyByZXN0b3JlIHJlaHlkcmF0aW9uIGFmdGVyIGNsZWFyTWlzbWF0Y2ggZGlzYWJsZWRcbiAgICAgIGxldCBuZXh0U2libGluZyA9IGN1cnJlbnRDdXJzb3IubmV4dFNpYmxpbmc7XG4gICAgICBpZiAoXG4gICAgICAgIG5leHRTaWJsaW5nICE9PSBudWxsICYmXG4gICAgICAgIGlzQ2xvc2VCbG9jayhuZXh0U2libGluZykgJiZcbiAgICAgICAgZ2V0QmxvY2tEZXB0aFdpdGhPZmZzZXQobmV4dFNpYmxpbmcsIHRoaXMuc3RhcnRpbmdCbG9ja09mZnNldCkgPT09IHRoaXMuYmxvY2tEZXB0aFxuICAgICAgKSB7XG4gICAgICAgIC8vIHJlc3RvcmUgcmVoeWRyYXRpb24gc3RhdGVcbiAgICAgICAgbGV0IGNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKG5leHRTaWJsaW5nKTtcbiAgICAgICAgdGhpcy5lbmFibGVSZWh5ZHJhdGlvbihjYW5kaWRhdGUpO1xuXG4gICAgICAgIGN1cnJlbnRDdXJzb3Iub3BlbkJsb2NrRGVwdGgtLTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfX2FwcGVuZE5vZGUobm9kZTogU2ltcGxlTm9kZSk6IFNpbXBsZU5vZGUge1xuICAgIGxldCB7IGNhbmRpZGF0ZSB9ID0gdGhpcztcblxuICAgIC8vIFRoaXMgY29kZSBwYXRoIGlzIG9ubHkgdXNlZCB3aGVuIGluc2VydGluZyBwcmVjaXNlbHkgb25lIG5vZGUuIEl0IG5lZWRzIG1vcmVcbiAgICAvLyBjb21wYXJpc29uIGxvZ2ljLCBidXQgd2UgY2FuIHByb2JhYmx5IGxlYW4gb24gdGhlIGNhc2VzIHdoZXJlIHRoaXMgY29kZSBwYXRoXG4gICAgLy8gaXMgYWN0dWFsbHkgdXNlZC5cbiAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICByZXR1cm4gY2FuZGlkYXRlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc3VwZXIuX19hcHBlbmROb2RlKG5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIF9fYXBwZW5kSFRNTChodG1sOiBzdHJpbmcpOiBCb3VuZHMge1xuICAgIGxldCBjYW5kaWRhdGVCb3VuZHMgPSB0aGlzLm1hcmtlckJvdW5kcygpO1xuXG4gICAgaWYgKGNhbmRpZGF0ZUJvdW5kcykge1xuICAgICAgbGV0IGZpcnN0ID0gY2FuZGlkYXRlQm91bmRzLmZpcnN0Tm9kZSgpITtcbiAgICAgIGxldCBsYXN0ID0gY2FuZGlkYXRlQm91bmRzLmxhc3ROb2RlKCkhO1xuXG4gICAgICBsZXQgbmV3Qm91bmRzID0gbmV3IENvbmNyZXRlQm91bmRzKHRoaXMuZWxlbWVudCwgZmlyc3QubmV4dFNpYmxpbmchLCBsYXN0LnByZXZpb3VzU2libGluZyEpO1xuXG4gICAgICBsZXQgcG9zc2libGVFbXB0eU1hcmtlciA9IHRoaXMucmVtb3ZlKGZpcnN0KTtcbiAgICAgIHRoaXMucmVtb3ZlKGxhc3QpO1xuXG4gICAgICBpZiAocG9zc2libGVFbXB0eU1hcmtlciAhPT0gbnVsbCAmJiBpc0VtcHR5KHBvc3NpYmxlRW1wdHlNYXJrZXIpKSB7XG4gICAgICAgIHRoaXMuY2FuZGlkYXRlID0gdGhpcy5yZW1vdmUocG9zc2libGVFbXB0eU1hcmtlcik7XG5cbiAgICAgICAgaWYgKHRoaXMuY2FuZGlkYXRlICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5jbGVhck1pc21hdGNoKHRoaXMuY2FuZGlkYXRlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3Qm91bmRzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc3VwZXIuX19hcHBlbmRIVE1MKGh0bWwpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCByZW1vdmUobm9kZTogU2ltcGxlTm9kZSk6IE9wdGlvbjxTaW1wbGVOb2RlPiB7XG4gICAgbGV0IGVsZW1lbnQgPSBleHBlY3Qobm9kZS5wYXJlbnROb2RlLCBgY2Fubm90IHJlbW92ZSBhIGRldGFjaGVkIG5vZGVgKSBhcyBTaW1wbGVFbGVtZW50O1xuICAgIGxldCBuZXh0ID0gbm9kZS5uZXh0U2libGluZztcbiAgICBlbGVtZW50LnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgIHJldHVybiBuZXh0O1xuICB9XG5cbiAgcHJpdmF0ZSBtYXJrZXJCb3VuZHMoKTogT3B0aW9uPEJvdW5kcz4ge1xuICAgIGxldCBfY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGU7XG5cbiAgICBpZiAoX2NhbmRpZGF0ZSAmJiBpc01hcmtlcihfY2FuZGlkYXRlKSkge1xuICAgICAgbGV0IGZpcnN0ID0gX2NhbmRpZGF0ZTtcbiAgICAgIGxldCBsYXN0ID0gZXhwZWN0KGZpcnN0Lm5leHRTaWJsaW5nLCBgQlVHOiBzZXJpYWxpemF0aW9uIG1hcmtlcnMgbXVzdCBiZSBwYWlyZWRgKTtcblxuICAgICAgd2hpbGUgKGxhc3QgJiYgIWlzTWFya2VyKGxhc3QpKSB7XG4gICAgICAgIGxhc3QgPSBleHBlY3QobGFzdC5uZXh0U2libGluZywgYEJVRzogc2VyaWFsaXphdGlvbiBtYXJrZXJzIG11c3QgYmUgcGFpcmVkYCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgQ29uY3JldGVCb3VuZHModGhpcy5lbGVtZW50LCBmaXJzdCwgbGFzdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIF9fYXBwZW5kVGV4dChzdHJpbmc6IHN0cmluZyk6IFNpbXBsZVRleHQge1xuICAgIGxldCB7IGNhbmRpZGF0ZSB9ID0gdGhpcztcblxuICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgIGlmIChpc1RleHROb2RlKGNhbmRpZGF0ZSkpIHtcbiAgICAgICAgaWYgKGNhbmRpZGF0ZS5ub2RlVmFsdWUgIT09IHN0cmluZykge1xuICAgICAgICAgIGNhbmRpZGF0ZS5ub2RlVmFsdWUgPSBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSBjYW5kaWRhdGUubmV4dFNpYmxpbmc7XG5cbiAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZTtcbiAgICAgIH0gZWxzZSBpZiAoaXNTZXBhcmF0b3IoY2FuZGlkYXRlKSkge1xuICAgICAgICB0aGlzLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGNhbmRpZGF0ZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX19hcHBlbmRUZXh0KHN0cmluZyk7XG4gICAgICB9IGVsc2UgaWYgKGlzRW1wdHkoY2FuZGlkYXRlKSAmJiBzdHJpbmcgPT09ICcnKSB7XG4gICAgICAgIHRoaXMuY2FuZGlkYXRlID0gdGhpcy5yZW1vdmUoY2FuZGlkYXRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fX2FwcGVuZFRleHQoc3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpO1xuXG4gICAgICAgIHJldHVybiBzdXBlci5fX2FwcGVuZFRleHQoc3RyaW5nKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHN1cGVyLl9fYXBwZW5kVGV4dChzdHJpbmcpO1xuICAgIH1cbiAgfVxuXG4gIF9fYXBwZW5kQ29tbWVudChzdHJpbmc6IHN0cmluZyk6IFNpbXBsZUNvbW1lbnQge1xuICAgIGxldCBfY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGU7XG4gICAgaWYgKF9jYW5kaWRhdGUgJiYgaXNDb21tZW50KF9jYW5kaWRhdGUpKSB7XG4gICAgICBpZiAoX2NhbmRpZGF0ZS5ub2RlVmFsdWUgIT09IHN0cmluZykge1xuICAgICAgICBfY2FuZGlkYXRlLm5vZGVWYWx1ZSA9IHN0cmluZztcbiAgICAgIH1cblxuICAgICAgdGhpcy5jYW5kaWRhdGUgPSBfY2FuZGlkYXRlLm5leHRTaWJsaW5nO1xuICAgICAgcmV0dXJuIF9jYW5kaWRhdGU7XG4gICAgfSBlbHNlIGlmIChfY2FuZGlkYXRlKSB7XG4gICAgICB0aGlzLmNsZWFyTWlzbWF0Y2goX2NhbmRpZGF0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLl9fYXBwZW5kQ29tbWVudChzdHJpbmcpO1xuICB9XG5cbiAgX19vcGVuRWxlbWVudCh0YWc6IHN0cmluZyk6IFNpbXBsZUVsZW1lbnQge1xuICAgIGxldCBfY2FuZGlkYXRlID0gdGhpcy5jYW5kaWRhdGU7XG5cbiAgICBpZiAoX2NhbmRpZGF0ZSAmJiBpc0VsZW1lbnQoX2NhbmRpZGF0ZSkgJiYgaXNTYW1lTm9kZVR5cGUoX2NhbmRpZGF0ZSwgdGFnKSkge1xuICAgICAgdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzID0gW10uc2xpY2UuY2FsbChfY2FuZGlkYXRlLmF0dHJpYnV0ZXMpO1xuICAgICAgcmV0dXJuIF9jYW5kaWRhdGU7XG4gICAgfSBlbHNlIGlmIChfY2FuZGlkYXRlKSB7XG4gICAgICBpZiAoaXNFbGVtZW50KF9jYW5kaWRhdGUpICYmIF9jYW5kaWRhdGUudGFnTmFtZSA9PT0gJ1RCT0RZJykge1xuICAgICAgICB0aGlzLnB1c2hFbGVtZW50KF9jYW5kaWRhdGUsIG51bGwpO1xuICAgICAgICB0aGlzLmN1cnJlbnRDdXJzb3IhLmluamVjdGVkT21pdHRlZE5vZGUgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdGhpcy5fX29wZW5FbGVtZW50KHRhZyk7XG4gICAgICB9XG4gICAgICB0aGlzLmNsZWFyTWlzbWF0Y2goX2NhbmRpZGF0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLl9fb3BlbkVsZW1lbnQodGFnKTtcbiAgfVxuXG4gIF9fc2V0QXR0cmlidXRlKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZywgbmFtZXNwYWNlOiBPcHRpb248QXR0ck5hbWVzcGFjZT4pOiB2b2lkIHtcbiAgICBsZXQgdW5tYXRjaGVkID0gdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzO1xuXG4gICAgaWYgKHVubWF0Y2hlZCkge1xuICAgICAgbGV0IGF0dHIgPSBmaW5kQnlOYW1lKHVubWF0Y2hlZCwgbmFtZSk7XG4gICAgICBpZiAoYXR0cikge1xuICAgICAgICBpZiAoYXR0ci52YWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICBhdHRyLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdW5tYXRjaGVkLnNwbGljZSh1bm1hdGNoZWQuaW5kZXhPZihhdHRyKSwgMSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3VwZXIuX19zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUsIG5hbWVzcGFjZSk7XG4gIH1cblxuICBfX3NldFByb3BlcnR5KG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGxldCB1bm1hdGNoZWQgPSB0aGlzLnVubWF0Y2hlZEF0dHJpYnV0ZXM7XG5cbiAgICBpZiAodW5tYXRjaGVkKSB7XG4gICAgICBsZXQgYXR0ciA9IGZpbmRCeU5hbWUodW5tYXRjaGVkLCBuYW1lKTtcbiAgICAgIGlmIChhdHRyKSB7XG4gICAgICAgIGlmIChhdHRyLnZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgIGF0dHIudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICB1bm1hdGNoZWQuc3BsaWNlKHVubWF0Y2hlZC5pbmRleE9mKGF0dHIpLCAxKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzdXBlci5fX3NldFByb3BlcnR5KG5hbWUsIHZhbHVlKTtcbiAgfVxuXG4gIF9fZmx1c2hFbGVtZW50KHBhcmVudDogU2ltcGxlRWxlbWVudCwgY29uc3RydWN0aW5nOiBTaW1wbGVFbGVtZW50KTogdm9pZCB7XG4gICAgbGV0IHsgdW5tYXRjaGVkQXR0cmlidXRlczogdW5tYXRjaGVkIH0gPSB0aGlzO1xuICAgIGlmICh1bm1hdGNoZWQpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdW5tYXRjaGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuY29uc3RydWN0aW5nIS5yZW1vdmVBdHRyaWJ1dGUodW5tYXRjaGVkW2ldLm5hbWUpO1xuICAgICAgfVxuICAgICAgdGhpcy51bm1hdGNoZWRBdHRyaWJ1dGVzID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgc3VwZXIuX19mbHVzaEVsZW1lbnQocGFyZW50LCBjb25zdHJ1Y3RpbmcpO1xuICAgIH1cbiAgfVxuXG4gIHdpbGxDbG9zZUVsZW1lbnQoKSB7XG4gICAgbGV0IHsgY2FuZGlkYXRlLCBjdXJyZW50Q3Vyc29yIH0gPSB0aGlzO1xuXG4gICAgaWYgKGNhbmRpZGF0ZSAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jbGVhck1pc21hdGNoKGNhbmRpZGF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKGN1cnJlbnRDdXJzb3IgJiYgY3VycmVudEN1cnNvci5pbmplY3RlZE9taXR0ZWROb2RlKSB7XG4gICAgICB0aGlzLnBvcEVsZW1lbnQoKTtcbiAgICB9XG5cbiAgICBzdXBlci53aWxsQ2xvc2VFbGVtZW50KCk7XG4gIH1cblxuICBnZXRNYXJrZXIoZWxlbWVudDogSFRNTEVsZW1lbnQsIGd1aWQ6IHN0cmluZyk6IE9wdGlvbjxTaW1wbGVOb2RlPiB7XG4gICAgbGV0IG1hcmtlciA9IGVsZW1lbnQucXVlcnlTZWxlY3Rvcihgc2NyaXB0W2dsbXI9XCIke2d1aWR9XCJdYCk7XG4gICAgaWYgKG1hcmtlcikge1xuICAgICAgcmV0dXJuIGNhc3RUb1NpbXBsZShtYXJrZXIpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIF9fcHVzaFJlbW90ZUVsZW1lbnQoXG4gICAgZWxlbWVudDogU2ltcGxlRWxlbWVudCxcbiAgICBjdXJzb3JJZDogc3RyaW5nLFxuICAgIGluc2VydEJlZm9yZTogTWF5YmU8U2ltcGxlTm9kZT5cbiAgKTogT3B0aW9uPFJlbW90ZUxpdmVCbG9jaz4ge1xuICAgIGxldCBtYXJrZXIgPSB0aGlzLmdldE1hcmtlcihjYXN0VG9Ccm93c2VyKGVsZW1lbnQsICdIVE1MJyksIGN1cnNvcklkKTtcblxuICAgIGFzc2VydChcbiAgICAgICFtYXJrZXIgfHwgbWFya2VyLnBhcmVudE5vZGUgPT09IGVsZW1lbnQsXG4gICAgICBgZXhwZWN0ZWQgcmVtb3RlIGVsZW1lbnQgbWFya2VyJ3MgcGFyZW50IG5vZGUgdG8gbWF