UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

586 lines (460 loc) 58.5 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"); function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var 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; } var RehydratingCursor = /*#__PURE__*/function (_CursorImpl) { _inheritsLoose(RehydratingCursor, _CursorImpl); function RehydratingCursor(element, nextSibling, startingBlockDepth) { var _this; _this = _CursorImpl.call(this, element, nextSibling) || this; _this.startingBlockDepth = startingBlockDepth; _this.candidate = null; _this.injectedOmittedNode = false; _this.openBlockDepth = startingBlockDepth - 1; return _this; } return RehydratingCursor; }(_bounds.CursorImpl); exports.RehydratingCursor = RehydratingCursor; var RehydrateBuilder = /*#__PURE__*/function (_NewElementBuilder) { _inheritsLoose(RehydrateBuilder, _NewElementBuilder); function RehydrateBuilder(env, parentNode, nextSibling) { var _this2; _this2 = _NewElementBuilder.call(this, env, parentNode, nextSibling) || this; _this2.unmatchedAttributes = null; _this2.blockDepth = 0; if (nextSibling) throw new Error('Rehydration with nextSibling not supported'); var node = _this2.currentCursor.element.firstChild; while (node !== null) { if (isOpenBlock(node)) { break; } node = node.nextSibling; } false && (0, _util.assert)(node, 'Must have opening comment for rehydration.'); _this2.candidate = node; var 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 var newBlockDepth = startingBlockOffset - 1; var newCandidate = _this2.dom.createComment("%+b:" + newBlockDepth + "%"); node.parentNode.insertBefore(newCandidate, _this2.candidate); var 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'); var newClosingBlock = _this2.dom.createComment("%-b:" + newBlockDepth + "%"); node.parentNode.insertBefore(newClosingBlock, closingNode.nextSibling); _this2.candidate = newCandidate; _this2.startingBlockOffset = newBlockDepth; } else { _this2.startingBlockOffset = 0; } return _this2; } var _proto = RehydrateBuilder.prototype; _proto.disableRehydration = function disableRehydration(nextSibling) { var 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; }; _proto.enableRehydration = function enableRehydration(candidate) { var currentCursor = this.currentCursor; currentCursor.candidate = candidate; currentCursor.nextSibling = null; }; _proto.pushElement = function pushElement(element, nextSibling) { if (nextSibling === void 0) { nextSibling = null; } var 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 ; _proto.clearMismatch = function clearMismatch(candidate) { var current = candidate; var currentCursor = this.currentCursor; if (currentCursor !== null) { var openBlockDepth = currentCursor.openBlockDepth; if (openBlockDepth >= currentCursor.startingBlockDepth) { while (current) { if (isCloseBlock(current)) { var 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); } }; _proto.__openBlock = function __openBlock() { var currentCursor = this.currentCursor; if (currentCursor === null) return; var blockDepth = this.blockDepth; this.blockDepth++; var candidate = currentCursor.candidate; if (candidate === null) return; var tagName = currentCursor.element.tagName; 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); } }; _proto.__closeBlock = function __closeBlock() { var currentCursor = this.currentCursor; if (currentCursor === null) return; // openBlock is the last rehydrated open block var openBlockDepth = currentCursor.openBlockDepth; // this currently is the expected next open block depth this.blockDepth--; var candidate = currentCursor.candidate; var 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) { var 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 var _nextSibling = currentCursor.nextSibling; if (_nextSibling !== null && isCloseBlock(_nextSibling) && getBlockDepthWithOffset(_nextSibling, this.startingBlockOffset) === this.blockDepth) { // restore rehydration state var _candidate2 = this.remove(_nextSibling); this.enableRehydration(_candidate2); currentCursor.openBlockDepth--; } } }; _proto.__appendNode = function __appendNode(node) { var candidate = this.candidate; // 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 _NewElementBuilder.prototype.__appendNode.call(this, node); } }; _proto.__appendHTML = function __appendHTML(html) { var candidateBounds = this.markerBounds(); if (candidateBounds) { var first = candidateBounds.firstNode(); var last = candidateBounds.lastNode(); var newBounds = new _bounds.ConcreteBounds(this.element, first.nextSibling, last.previousSibling); var 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 _NewElementBuilder.prototype.__appendHTML.call(this, html); } }; _proto.remove = function remove(node) { var element = node.parentNode; var next = node.nextSibling; element.removeChild(node); return next; }; _proto.markerBounds = function markerBounds() { var _candidate = this.candidate; if (_candidate && isMarker(_candidate)) { var first = _candidate; var last = first.nextSibling; while (last && !isMarker(last)) { last = last.nextSibling; } return new _bounds.ConcreteBounds(this.element, first, last); } else { return null; } }; _proto.__appendText = function __appendText(string) { var candidate = this.candidate; 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 _NewElementBuilder.prototype.__appendText.call(this, string); } } else { return _NewElementBuilder.prototype.__appendText.call(this, string); } }; _proto.__appendComment = function __appendComment(string) { var _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 _NewElementBuilder.prototype.__appendComment.call(this, string); }; _proto.__openElement = function __openElement(tag) { var _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 _NewElementBuilder.prototype.__openElement.call(this, tag); }; _proto.__setAttribute = function __setAttribute(name, value, namespace) { var unmatched = this.unmatchedAttributes; if (unmatched) { var attr = findByName(unmatched, name); if (attr) { if (attr.value !== value) { attr.value = value; } unmatched.splice(unmatched.indexOf(attr), 1); return; } } return _NewElementBuilder.prototype.__setAttribute.call(this, name, value, namespace); }; _proto.__setProperty = function __setProperty(name, value) { var unmatched = this.unmatchedAttributes; if (unmatched) { var attr = findByName(unmatched, name); if (attr) { if (attr.value !== value) { attr.value = value; } unmatched.splice(unmatched.indexOf(attr), 1); return; } } return _NewElementBuilder.prototype.__setProperty.call(this, name, value); }; _proto.__flushElement = function __flushElement(parent, constructing) { var unmatched = this.unmatchedAttributes; if (unmatched) { for (var i = 0; i < unmatched.length; i++) { this.constructing.removeAttribute(unmatched[i].name); } this.unmatchedAttributes = null; } else { _NewElementBuilder.prototype.__flushElement.call(this, parent, constructing); } }; _proto.willCloseElement = function willCloseElement() { var candidate = this.candidate, currentCursor = this.currentCursor; if (candidate !== null) { this.clearMismatch(candidate); } if (currentCursor && currentCursor.injectedOmittedNode) { this.popElement(); } _NewElementBuilder.prototype.willCloseElement.call(this); }; _proto.getMarker = function getMarker(element, guid) { var marker = element.querySelector("script[glmr=\"" + guid + "\"]"); if (marker) { return marker; } return null; }; _proto.__pushRemoteElement = function __pushRemoteElement(element, cursorId, insertBefore) { var 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; } var 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); } var block = new _elementBuilder.RemoteLiveBlock(element); return this.pushLiveBlock(block, true); }; _proto.didAppendBounds = function didAppendBounds(bounds) { _NewElementBuilder.prototype.didAppendBounds.call(this, bounds); if (this.candidate) { var last = bounds.lastNode(); this.candidate = last && last.nextSibling; } return bounds; }; _createClass(RehydrateBuilder, [{ key: "currentCursor", get: function get() { return this[_elementBuilder.CURSOR_STACK].current; } }, { key: "candidate", get: function get() { if (this.currentCursor) { return this.currentCursor.candidate; } return null; }, set: function set(node) { var currentCursor = this.currentCursor; currentCursor.candidate = node; } }]); return RehydrateBuilder; }(_elementBuilder.NewElementBuilder); 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 (var i = 0; i < array.length; i++) { var 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL3JlaHlkcmF0ZS1idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUNBOztBQVdBOztBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFTyxJQUFNLCtCQUErQixHQUFyQyxRQUFBOzs7QUFFRCxTQUFBLHdCQUFBLENBQUEsSUFBQSxFQUFtRDtBQUN2RCxTQUFPLElBQUksQ0FBSixTQUFBLEtBQVAsK0JBQUE7QUFDRDs7QUFFRCxJQUFNLGlCQUFOLEdBQUEsYUFBQSxVQUFBLFdBQUEsRUFBQTtBQUFBLEVBQUEsY0FBQSxDQUFBLGlCQUFBLEVBQUEsV0FBQSxDQUFBOztBQUlFLFdBQUEsaUJBQUEsQ0FBQSxPQUFBLEVBQUEsV0FBQSxFQUFBLGtCQUFBLEVBRzRDO0FBQUEsUUFBQSxLQUFBOztBQUUxQyxJQUFBLEtBQUEsR0FBQSxXQUFBLENBQUEsSUFBQSxDQUFBLElBQUEsRUFBQSxPQUFBLEVBQUEsV0FBQSxLQUFBLElBQUE7QUFGZ0IsSUFBQSxLQUFBLENBQUEsa0JBQUEsR0FBQSxrQkFBQTtBQU5sQixJQUFBLEtBQUEsQ0FBQSxTQUFBLEdBQUEsSUFBQTtBQUVBLElBQUEsS0FBQSxDQUFBLG1CQUFBLEdBQUEsS0FBQTtBQU9FLElBQUEsS0FBQSxDQUFBLGNBQUEsR0FBc0Isa0JBQWtCLEdBQXhDLENBQUE7QUFIMEMsV0FBQSxLQUFBO0FBSTNDOztBQVhILFNBQUEsaUJBQUE7QUFBQSxDQUFBLENBQUEsa0JBQUEsQ0FBQTs7OztBQWNBLElBQU0sZ0JBQU4sR0FBQSxhQUFBLFVBQUEsa0JBQUEsRUFBQTtBQUFBLEVBQUEsY0FBQSxDQUFBLGdCQUFBLEVBQUEsa0JBQUEsQ0FBQTs7QUFNRSxXQUFBLGdCQUFBLENBQUEsR0FBQSxFQUFBLFVBQUEsRUFBQSxXQUFBLEVBQXdGO0FBQUEsUUFBQSxNQUFBOztBQUN0RixJQUFBLE1BQUEsR0FB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QUosUUFBQSxLQUFBLENBQUEsSUFBdUIsSUFBSSxDQUFKLFNBQUEsS0FBOUIsUUFBQTtBQUNEOztBQUVELFNBQUEsV0FBQSxDQUFBLElBQUEsRUFBcUM7QUFDbkMsU0FBTyxJQUFJLENBQUosUUFBQSxLQUFBLENBQUEsSUFBdUIsSUFBSSxDQUFKLFNBQUEsS0FBOUIsS0FBQTtBQUNEOztBQUVELFNBQUEsT0FBQSxDQUFBLElBQUEsRUFBaUM7QUFDL0IsU0FBTyxJQUFJLENBQUosUUFBQSxLQUFBLENBQUEsSUFBdUIsSUFBSSxDQUFKLFNBQUEsS0FBOUIsS0FBQTtBQUNEOztBQUVELFNBQUEsY0FBQSxDQUFBLFNBQUEsRUFBQSxHQUFBLEVBQTZEO0FBQzNELE1BQUksU0FBUyxDQUFULFlBQUEsS0FBc0I7QUFBQTtBQUExQixJQUE4QztBQUM1QyxhQUFPLFNBQVMsQ0FBVCxPQUFBLEtBQVAsR0FBQTtBQUNEOztBQUNELFNBQU8sU0FBUyxDQUFULE9BQUEsS0FBc0IsR0FBRyxDQUFoQyxXQUE2QixFQUE3QjtBQUNEOztBQUVELFNBQUEsVUFBQSxDQUFBLEtBQUEsRUFBQSxJQUFBLEVBQXFEO0FBQ25ELE9BQUssSUFBSSxDQUFDLEdBQVYsQ0FBQSxFQUFnQixDQUFDLEdBQUcsS0FBSyxDQUF6QixNQUFBLEVBQWtDLENBQWxDLEVBQUEsRUFBdUM7QUFDckMsUUFBSSxJQUFJLEdBQUcsS0FBSyxDQUFoQixDQUFnQixDQUFoQjtBQUNBLFFBQUksSUFBSSxDQUFKLElBQUEsS0FBSixJQUFBLEVBQXdCLE9BQUEsSUFBQTtBQUN6Qjs7QUFFRCxTQUFBLFNBQUE7QUFDRDs7QUFFSyxTQUFBLGtCQUFBLENBQUEsR0FBQSxFQUFBLE1BQUEsRUFBaUU7QUFDckUsU0FBTyxnQkFBZ0IsQ0FBaEIsZ0JBQUEsQ0FBQSxHQUFBLEVBQVAsTUFBTyxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCb3VuZHMsIEVsZW1lbnRCdWlsZGVyLCBFbnZpcm9ubWVudCwgT3B0aW9uLCBNYXliZSB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgYXNzZXJ0LCBjYXN0VG9Ccm93c2VyLCBjYXN0VG9TaW1wbGUsIGV4cGVjdCwgU3RhY2sgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7XG4gIEF0dHJOYW1lc3BhY2UsXG4gIE5hbWVzcGFjZSxcbiAgTm9kZVR5cGUsXG4gIFNpbXBsZUF0dHIsXG4gIFNpbXBsZUNvbW1lbnQsXG4gIFNpbXBsZUVsZW1lbnQsXG4gIFNpbXBsZU5vZGUsXG4gIFNpbXBsZVRleHQsXG59IGZyb20gJ0BzaW1wbGUtZG9tL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBDb25jcmV0ZUJvdW5kcywgQ3Vyc29ySW1wbCB9IGZyb20gJy4uL2JvdW5kcyc7XG5pbXBvcnQgeyBDVVJTT1JfU1RBQ0ssIE5ld0VsZW1lbnRCdWlsZGVyLCBSZW1vdGVMaXZlQmxvY2sgfSBmcm9tICcuL2VsZW1lbnQtYnVpbGRlcic7XG5cbmV4cG9ydCBjb25zdCBTRVJJQUxJWkFUSU9OX0ZJUlNUX05PREVfU1RSSU5HID0gJyUrYjowJSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1NlcmlhbGl6YXRpb25GaXJzdE5vZGUobm9kZTogU2ltcGxlTm9kZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gbm9kZS5ub2RlVmFsdWUgPT09IFNFUklBTElaQVRJT05fRklSU1RfTk9ERV9TVFJJTkc7XG59XG5cbmV4cG9ydCBjbGFzcyBSZWh5ZHJhdGluZ0N1cnNvciBleHRlbmRzIEN1cnNvckltcGwge1xuICBjYW5kaWRhdGU6IE9wdGlvbjxTaW1wbGVOb2RlPiA9IG51bGw7XG4gIG9wZW5CbG9ja0RlcHRoOiBudW1iZXI7XG4gIGluamVjdGVkT21pdHRlZE5vZGUgPSBmYWxzZTtcbiAgY29uc3RydWN0b3IoXG4gICAgZWxlbWVudDogU2ltcGxlRWxlbWVudCxcbiAgICBuZXh0U2libGluZzogT3B0aW9uPFNpbXBsZU5vZGU+LFxuICAgIHB1YmxpYyByZWFkb25seSBzdGFydGluZ0Jsb2NrRGVwdGg6IG51bWJlclxuICApIHtcbiAgICBzdXBlcihlbGVtZW50LCBuZXh0U2libGluZyk7XG4gICAgdGhpcy5vcGVuQmxvY2tEZXB0aCA9IHN0YXJ0aW5nQmxvY2tEZXB0aCAtIDE7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFJlaHlkcmF0ZUJ1aWxkZXIgZXh0ZW5kcyBOZXdFbGVtZW50QnVpbGRlciBpbXBsZW1lbnRzIEVsZW1lbnRCdWlsZGVyIHtcbiAgcHJpdmF0ZSB1bm1hdGNoZWRBdHRyaWJ1dGVzOiBPcHRpb248U2ltcGxlQXR0cltdPiA9IG51bGw7XG4gIFtDVVJTT1JfU1RBQ0tdITogU3RhY2s8UmVoeWRyYXRpbmdDdXJzb3I+OyAvLyBIaWRlcyBwcm9wZXJ0eSBvbiBiYXNlIGNsYXNzXG4gIGJsb2NrRGVwdGggPSAwO1xuICBzdGFydGluZ0Jsb2NrT2Zmc2V0OiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoZW52OiBFbnZpcm9ubWVudCwgcGFyZW50Tm9kZTogU2ltcGxlRWxlbWVudCwgbmV4dFNpYmxpbmc6IE9wdGlvbjxTaW1wbGVOb2RlPikge1xuICAgIHN1cGVyKGVudiwgcGFyZW50Tm9kZSwgbmV4dFNpYmxpbmcpO1xuICAgIGlmIChuZXh0U2libGluZykgdGhyb3cgbmV3IEVycm9yKCdSZWh5ZHJhdGlvbiB3aXRoIG5leHRTaWJsaW5nIG5vdCBzdXBwb3J0ZWQnKTtcblxuICAgIGxldCBub2RlID0gdGhpcy5jdXJyZW50Q3Vyc29yIS5lbGVtZW50LmZpcnN0Q2hpbGQ7XG5cbiAgICB3aGlsZSAobm9kZSAhPT0gbnVsbCkge1xuICAgICAgaWYgKGlzT3BlbkJsb2NrKG5vZGUpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgbm9kZSA9IG5vZGUubmV4dFNpYmxpbmc7XG4gICAgfVxuXG4gICAgYXNzZXJ0KG5vZGUsICdNdXN0IGhhdmUgb3BlbmluZyBjb21tZW50IGZvciByZWh5ZHJhdGlvbi4nKTtcbiAgICB0aGlzLmNhbmRpZGF0ZSA9IG5vZGU7XG4gICAgY29uc3Qgc3RhcnRpbmdCbG9ja09mZnNldCA9IGdldEJsb2NrRGVwdGgobm9kZSBhcyBTaW1wbGVDb21tZW50KTtcbiAgICBpZiAoc3RhcnRpbmdCbG9ja09mZnNldCAhPT0gMCkge1xuICAgICAgLy8gV2UgYXJlIHJlaHlkcmF0aW5nIGZyb20gYSBwYXJ0aWFsIHRyZWUgYW5kIG5vdCB0aGUgcm9vdCBjb21wb25lbnRcbiAgICAgIC8vIFdlIG5lZWQgdG8gYWRkIGFuIGV4dHJhIGJsb2NrIGJlZm9yZSB0aGUgZmlyc3QgYmxvY2sgdG8gcmVoeWRyYXRlIGNvcnJlY3RseVxuICAgICAgLy8gVGhlIGV4dHJhIGJsb2NrIGlzIG5lZWRlZCBzaW5jZSB0aGUgcmVuZGVyQ29tcG9uZW50IEFQSSBjcmVhdGVzIGEgc3ludGhldGljIGNvbXBvbmVudCBpbnZvY2F0aW9uIHdoaWNoIGdlbmVyYXRlcyB0aGUgZXh0cmEgYmxvY2tcbiAgICAgIGNvbnN0IG5ld0Jsb2NrRGVwdGggPSBzdGFydGluZ0Jsb2NrT2Zmc2V0IC0gMTtcbiAgICAgIGNvbnN0IG5ld0NhbmRpZGF0ZSA9IHRoaXMuZG9tLmNyZWF0ZUNvbW1lbnQoYCUrYjoke25ld0Jsb2NrRGVwdGh9JWApO1xuXG4gICAgICBub2RlIS5wYXJlbnROb2RlIS5pbnNlcnRCZWZvcmUobmV3Q2FuZGlkYXRlLCB0aGlzLmNhbmRpZGF0ZSk7XG4gICAgICBsZXQgY2xvc2luZ05vZGUgPSBub2RlIS5uZXh0U2libGluZztcbiAgICAgIHdoaWxlIChjbG9zaW5nTm9kZSAhPT0gbnVsbCkge1xuICAgICAgICBpZiAoaXNDbG9zZUJsb2NrKGNsb3NpbmdOb2RlKSAmJiBnZXRCbG9ja0RlcHRoKGNsb3NpbmdOb2RlKSA9PT0gc3RhcnRpbmdCbG9ja09mZnNldCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNsb3NpbmdOb2RlID0gY2xvc2luZ05vZGUubmV4dFNpYmxpbmc7XG4gICAgICB9XG5cbiAgICAgIGFzc2VydChjbG9zaW5nTm9kZSwgJ011c3QgaGF2ZSBjbG9zaW5nIGNvbW1lbnQgZm9yIHN0YXJ0aW5nIGJsb2NrIGNvbW1lbnQnKTtcbiAgICAgIGNvbnN0IG5ld0Nsb3NpbmdCbG9jayA9IHRoaXMuZG9tLmNyZWF0ZUNvbW1lbnQoYCUtYjoke25ld0Jsb2NrRGVwdGh9JWApO1xuICAgICAgbm9kZSEucGFyZW50Tm9kZSEuaW5zZXJ0QmVmb3JlKG5ld0Nsb3NpbmdCbG9jaywgY2xvc2luZ05vZGUhLm5leHRTaWJsaW5nKTtcbiAgICAgIHRoaXMuY2FuZGlkYXRlID0gbmV3Q2FuZGlkYXRlO1xuICAgICAgdGhpcy5zdGFydGluZ0Jsb2NrT2Zmc2V0ID0gbmV3QmxvY2tEZXB0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGFydGluZ0Jsb2NrT2Zmc2V0ID0gMDtcbiAgICB9XG4gIH1cblxuICBnZXQgY3VycmVudEN1cnNvcigpOiBPcHRpb248UmVoeWRyYXRpbmdDdXJzb3I+IHtcbiAgICByZXR1cm4gdGhpc1tDVVJTT1JfU1RBQ0tdLmN1cnJlbnQ7XG4gIH1cblxuICBnZXQgY2FuZGlkYXRlKCk6IE9wdGlvbjxTaW1wbGVOb2RlPiB7XG4gICAgaWYgKHRoaXMuY3VycmVudEN1cnNvcikge1xuICAgICAgcmV0dXJuIHRoaXMuY3VycmVudEN1cnNvci5jYW5kaWRhdGUhO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgc2V0IGNhbmRpZGF0ZShub2RlOiBPcHRpb248U2ltcGxlTm9kZT4pIHtcbiAgICBsZXQgY3VycmVudEN1cnNvciA9IHRoaXMuY3VycmVudEN1cnNvciE7XG5cbiAgICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSA9IG5vZGU7XG4gIH1cblxuICBkaXNhYmxlUmVoeWRyYXRpb24obmV4dFNpYmxpbmc6IE9wdGlvbjxTaW1wbGVOb2RlPikge1xuICAgIGxldCBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yITtcblxuICAgIC8vIHJlaHlkcmF0aW9uIHdpbGwgYmUgZGlzYWJsZWQgdW50aWwgd2UgZWl0aGVyOlxuICAgIC8vICogaGl0IHBvcEVsZW1lbnQgKGFuZCByZXR1cm4gdG8gdXNpbmcgdGhlIHBhcmVudCBlbGVtZW50cyBjdXJzb3IpXG4gICAgLy8gKiBoaXQgY2xvc2VCbG9jayBhbmQgdGhlIG5leHQgc2libGluZyBpcyBhIGNsb3NlIGJsb2NrIGNvbW1lbnRcbiAgICAvLyAgIG1hdGNoaW5nIHRoZSBleHBlY3RlZCBvcGVuQmxvY2tEZXB0aFxuICAgIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlID0gbnVsbDtcbiAgICBjdXJyZW50Q3Vyc29yLm5leHRTaWJsaW5nID0gbmV4dFNpYmxpbmc7XG4gIH1cblxuICBlbmFibGVSZWh5ZHJhdGlvbihjYW5kaWRhdGU6IE9wdGlvbjxTaW1wbGVOb2RlPikge1xuICAgIGxldCBjdXJyZW50Q3Vyc29yID0gdGhpcy5jdXJyZW50Q3Vyc29yITtcblxuICAgIGN1cnJlbnRDdXJzb3IuY2FuZGlkYXRlID0gY2FuZGlkYXRlO1xuICAgIGN1cnJlbnRDdXJzb3IubmV4dFNpYmxpbmcgPSBudWxsO1xuICB9XG5cbiAgcHVzaEVsZW1lbnQoXG4gICAgLyoqIGNhbGxlZCBmcm9tIHBhcmVudCBjb25zdHJ1Y3RvciBiZWZvcmUgd2UgaW5pdGlhbGl6ZSB0aGlzICovXG4gICAgdGhpczpcbiAgICAgIHwgUmVoeWRyYXRlQnVpbGRlclxuICAgICAgfCAoTmV3RWxlbWVudEJ1aWxkZXIgJiBQYXJ0aWFsPFBpY2s8UmVoeWRyYXRlQnVpbGRlciwgJ2Jsb2NrRGVwdGgnIHwgJ2NhbmRpZGF0ZSc+PiksXG4gICAgZWxlbWVudDogU2ltcGxlRWxlbWVudCxcbiAgICBuZXh0U2libGluZzogTWF5YmU8U2ltcGxlTm9kZT4gPSBudWxsXG4gICkge1xuICAgIGxldCBjdXJzb3IgPSBuZXcgUmVoeWRyYXRpbmdDdXJzb3IoZWxlbWVudCwgbmV4dFNpYmxpbmcsIHRoaXMuYmxvY2tEZXB0aCB8fCAwKTtcblxuICAgIC8qKlxuICAgICAqIDxkaXY+ICAgPC0tLS0tLS0tLS0tLS0tLSAgY3VycmVudEN1cnNvci5lbGVtZW50XG4gICAgICogICA8IS0tJStiOjElLS0+IDwtLS0tLS0tICB3b3VsZCBoYXZlIGJlZW4gcmVtb3ZlZCBkdXJpbmcgb3BlbkJsb2NrXG4gICAgICogICA8ZGl2PiA8LS0tLS0tLS0tLS0tLS0tICBjdXJyZW50Q3Vyc29yLmNhbmRpZGF0ZSAtPiBjdXJzb3IuZWxlbWVudFxuICAgICAqICAgICA8IS0tJStiOjIlLS0+IDwtLS0tLSAgY3VycmVudEN1cnNvci5jYW5kaWRhdGUuZmlyc3RDaGlsZCAtPiBjdXJzb3IuY2FuZGlkYXRlXG4gICAgICogICAgIEZvb1xuICAgICAqICAgICA8IS0tJS1iOjIlLS0+XG4gICAgICogICA8L2Rpdj5cbiAgICAgKiAgIDwhLS0lLWI6MSUtLT4gIDwtLS0tLS0gIGJlY29tZXMgY3VycmVudEN1cnNvci5jYW5kaWRhdGVcbiAgICAgKi9cbiAgICBpZiAodGhpcy5jYW5kaWRhdGUgIT09IG51bGwpIHtcbiAgICAgIGN1cnNvci5jYW5kaWRhdGUgPSBlbGVtZW50LmZpcnN0Q2hpbGQ7XG4gICAgICB0aGlzLmNhbmRpZGF0ZSA9IGVsZW1lbnQubmV4dFNpYmxpbmc7XG4gICAgfVxuXG4gICAgdGhpc1tDVVJTT1JfU1RBQ0tdLnB1c2goY3Vyc29yKTtcbiAgfVxuXG4gIC8vIGNsZWFycyB1bnRpbCB0aGUgZW5kIG9mIHRoZSBjdXJyZW50IGNvbnRhaW5lclxuICAvLyBlaXRoZXIgdGhlIGN1cnJlbnQgb3BlbiBibG9jayBvciBoaWdoZXJcbiAgcHJpdmF0ZSBjbGVhck1pc21hdGNoKGNhbmRpZGF0ZTogU2ltcGxlTm9kZSkge1xuICAgIGxldCBjdXJyZW50OiBPcHRpb248U2ltcGxlTm9kZT4gPSBjYW5kaWRhdGU7XG4gICAgbGV0IGN1cnJlbnRDdXJzb3IgPSB0aGlzLmN1cnJlbnRDdXJzb3I7XG4gICAgaWYgKGN1cnJlbnRDdXJzb3IgIT09IG51bGwpIHtcbiAgICAgIGxldCBvcGVuQmxvY2tEZXB0aCA9IGN1cnJlbnRDdXJzb3Iub3BlbkJsb2NrRGVwdGg7XG4gICAgICBpZiAob3BlbkJsb2NrRGVwdGggPj0gY3VycmVudEN1cnNvci5zdGFydGluZ0Jsb2NrRGVwdGgpIHtcbiAgICAgICAgd2hpbGUgKGN1cnJlbnQpIHtcbiAgICAgICAgICBpZiAoaXNDbG9zZUJsb2NrKGN1cnJlbnQpKSB7XG4gICAgICAgICAgICBsZXQgY2xvc2VCbG9ja0RlcHRoID0gZ2V0QmxvY2tEZXB0aFdpdGhPZmZzZXQoY3VycmVudCwgdGhpcy5zdGFydGluZ0Jsb2NrT2Zmc2V0KTtcbiAgICAgICAgICAgIGlmIChvcGVuQmxvY2tEZXB0aCA+PSBjbG9zZUJsb2NrRGVwdGgpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLnJlbW92ZShjdXJyZW50KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2hpbGUgKGN1cnJlbnQgIT09IG51bGwpIHtcbiAgICAgICAgICBjdXJyZW50ID0gdGhpcy5yZW1vdmUoY3VycmVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIGN1cnJlbnQgY3Vyc29yIHBhcmVudE5vZGUgc2hvdWxkIGJlIG9wZW5DYW5kaWRhdGUgaWYgZWxlbWVudFxuICAgICAgLy8gb3Igb3BlbkNhbmRpZGF0ZS5wYXJlbnROb2RlIGlmIGNvbW1lbnRcbiAgICAgIHRoaXMuZGlzYWJsZVJlaHlkcmF0aW9uKGN1cnJlbnQpO1xuICAgIH1cbiAgfVxuXG4gIF9fb3BlbkJsb2NrKCk6IHZvaWQge1xuICAgIGxldCB7IGN1cnJlbnRDdXJzb3IgfSA9IHRoaXM7XG4gICAgaWYgKGN1cnJlbnRDdXJzb3IgPT09IG51bGwpIHJldHVybjtcblxuICAgIGxldCBibG9ja0RlcHRoID0gdGhpcy5ibG9ja0RlcHRoO1xuXG4gICAgdGhpcy5ibG9ja0RlcHRoKys7XG5cbiAgICBsZXQgeyBjYW5kaWRhdGUgfSA9IGN1cnJlbnRDdXJzb3I7XG4gICAgaWYgKGNhbmRpZGF0ZSA9PT0gbnVsbCkgcmV0dXJuO1xuXG4gICAgbGV0IHsgdGFnTmFtZSB9ID0gY3VycmVudEN1cnNvci5lbGVtZW50O1xuXG4gICAgaWYgKFxuICAgICAgaXNPcGVuQmxvY2soY2FuZGlkYXRlKSAmJlxuICAgICAgZ2V0QmxvY2tEZXB0aFdpdGhPZmZzZXQoY2FuZGlkYXRlLCB0aGlzLnN0YXJ0aW5nQmxvY2tPZmZzZXQpID09PSBibG9ja0RlcHRoXG4gICAgKSB7XG4gICAgICB0aGlzLmNhbmRpZGF0ZSA9IHRoaXMucmVtb3ZlKGNhbmRpZGF0ZSk7XG4gICAgICBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoID0gYmxvY2tEZXB0aDtcbiAgICB9IGVsc2UgaWYgKHRhZ05hbWUgIT09ICdUSVRMRScgJiYgdGFnTmFtZSAhPT0gJ1NDUklQVCcgJiYgdGFnTmFtZSAhPT0gJ1NUWUxFJykge1xuICAgICAgdGhpcy5jbGVhck1pc21hdGNoKGNhbmRpZGF0ZSk7XG4gICAgfVxuICB9XG5cbiAgX19jbG9zZUJsb2NrKCk6IHZvaWQge1xuICAgIGxldCB7IGN1cnJlbnRDdXJzb3IgfSA9IHRoaXM7XG4gICAgaWYgKGN1cnJlbnRDdXJzb3IgPT09IG51bGwpIHJldHVybjtcblxuICAgIC8vIG9wZW5CbG9jayBpcyB0aGUgbGFzdCByZWh5ZHJhdGVkIG9wZW4gYmxvY2tcbiAgICBsZXQgb3BlbkJsb2NrRGVwdGggPSBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoO1xuXG4gICAgLy8gdGhpcyBjdXJyZW50bHkgaXMgdGhlIGV4cGVjdGVkIG5leHQgb3BlbiBibG9jayBkZXB0aFxuICAgIHRoaXMuYmxvY2tEZXB0aC0tO1xuXG4gICAgbGV0IHsgY2FuZGlkYXRlIH0gPSBjdXJyZW50Q3Vyc29yO1xuXG4gICAgbGV0IGlzUmVoeWRyYXRpbmcgPSBmYWxzZTtcblxuICAgIGlmIChjYW5kaWRhdGUgIT09IG51bGwpIHtcbiAgICAgIGlzUmVoeWRyYXRpbmcgPSB0cnVlO1xuICAgICAgLy9hc3NlcnQoXG4gICAgICAvLyAgb3BlbkJsb2NrRGVwdGggPT09IHRoaXMuYmxvY2tEZXB0aCxcbiAgICAgIC8vICAnd2hlbiByZWh5ZHJhdGluZywgb3BlbkJsb2NrRGVwdGggc2hvdWxkIG1hdGNoIHRoaXMuYmxvY2tEZXB0aCBoZXJlJ1xuICAgICAgLy8pO1xuXG4gICAgICBpZiAoXG4gICAgICAgIGlzQ2xvc2VCbG9jayhjYW5kaWRhdGUpICYmXG4gICAgICAgIGdldEJsb2NrRGVwdGhXaXRoT2Zmc2V0KGNhbmRpZGF0ZSwgdGhpcy5zdGFydGluZ0Jsb2NrT2Zmc2V0KSA9PT0gb3BlbkJsb2NrRGVwdGhcbiAgICAgICkge1xuICAgICAgICBsZXQgbmV4dFNpYmxpbmcgPSB0aGlzLnJlbW92ZShjYW5kaWRhdGUpO1xuICAgICAgICB0aGlzLmNhbmRpZGF0ZSA9IG5leHRTaWJsaW5nO1xuICAgICAgICBjdXJyZW50Q3Vyc29yLm9wZW5CbG9ja0RlcHRoLS07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjbG9zZSB0aGUgYmxvY2sgYW5kIGNsZWFyIG1pc21hdGNoIGluIHBhcmVudCBjb250YWluZXJcbiAgICAgICAgLy8gd2Ugd2lsbCBiZSBlaXRoZXIgYXQgdGhlIGVuZCBvZiB0aGUgZWxlbWVudFxuICAgICAgICAvLyBvciBhdCB0aGUgZW5kIG9mIG91ciBjb250YWluaW5nIGJsb2NrXG4gICAgICAgIHRoaXMuY2xlYXJNaXNtYXRjaChjYW5kaWRhdGUpO1xuICAgICAgICBpc1JlaHlkcmF0aW5nID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzUmVoeWRyYXRpbmcgPT09IGZhbHNlKSB7XG4gICAgICAvLyBjaGVjayBpZiBuZXh0U2libGluZyBtYXRjaGVzIG91ciBleHBlY3RlZCBjbG9zZSBibG9ja1xuICAgICAgLy8gaWYgc28sIHdlIHJlbW92ZSB0aGUgY2xvc2UgYmxvY2sgY29tbWVudCBhbmRcbiAgICAgIC8vIHJlc3RvcmUgcmVoeWRyYXRpb24gYWZ0ZXIgY2xlYXJNaXNtYXRjaCBkaXNhYmxlZFxuICAgICAgbGV0IG5leHRTaWJsaW5nID0gY3VycmVudEN1cnNvci5uZXh0U2libGluZztcbiAgICAgIGlmIChcbiAgICAgICAgbmV4dFNpYmxpbmcgIT09IG51bGwgJiZcbiAgICAgICAgaXNDbG9zZUJsb2NrKG5leHRTaWJsaW5nKSAmJlxuICAgICAgICBnZXRCbG9ja0RlcHRoV2l0aE9mZnNldChuZXh0U2libGluZywgdGhpcy5zdGFydGluZ0Jsb2NrT2Zmc2V0KSA9PT0gdGhpcy5ibG9ja0RlcHRoXG4gICAgICApIHtcbiAgICAgICAgLy8gcmVzdG9yZSByZWh5ZHJhdGlvbiBzdGF0ZVxuICAgICAgICBsZXQgY2FuZGlkYXRlID0gdGhpcy5yZW1vdmUobmV4dFNpYmxpbmcpO1xuICAgICAgICB0aGlzLmVuYWJsZVJlaHlkcmF0aW9uKGNhbmRpZGF0ZSk7XG5cbiAgICAgICAgY3VycmVudEN1cnNvci5vcGVuQmxvY2tEZXB0aC0tO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9fYXBwZW5kTm9kZShub2RlOiBTaW1wbGVOb2RlKTogU2ltcGxlTm9kZSB7XG4gICAgbGV0IHsgY2FuZGlkYXRlIH0gPSB0aGlzO1xuXG4gICAgLy8gVGhpcyBjb2RlIHBhdGggaXMgb25seSB1c2VkIHdoZW4gaW5zZXJ0aW5nIHByZWNpc2VseSBvbmUgbm9kZS4gSXQgbmVlZHMgbW9yZVxuICAgIC8vIGNvbXBhcmlzb24gbG9naWMsIGJ1dCB3ZSBjYW4gcHJvYmFibHkgbGVhbiBvbiB0aGUgY2FzZXMgd2hlcmUgdGhpcyBjb2RlIHBhdGhcbiAgICAvLyBpcyBhY3R1YWxseSB1c2VkLlxuICAgIGlmIChjYW5kaWRhdGUpIHtcbiAgICAgIHJldHVybiBjYW5kaWRhdGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdXBlci5fX2FwcGVuZE5vZGUobm9kZSk7XG4gICAgfVxuICB9XG5cbiAgX19hcHBlbmRIVE1MKGh0bWw6IHN0cmluZyk6IEJvdW5kcyB7XG4gICAgbGV0IGNhbmRpZGF0ZUJvdW5kcyA9IHRoaXMubWFya2VyQm91bmRzKCk7XG5cbiAgICBpZiAoY2FuZGlkYXRlQm91bmRzKSB7XG4gICAgICBsZXQgZmlyc3QgPSBjYW5kaWRhdGVCb3VuZHMuZmlyc3ROb2RlKCkhO1xuICAgICAgbGV0IGxhc3QgPSBjYW5kaWRhdGVCb3VuZHMubGFzdE5vZGUoKSE7XG5cbiAgICAgIGxldCBuZXdCb3VuZHMgPSBuZXcgQ29uY3JldGVCb3VuZHModGhpcy5lbGVtZW50LCBmaXJzdC5uZXh0U2libGluZyEsIGxhc3QucHJldmlvdXNTaWJsaW5nISk7XG5cbiAgICAgIGxldCBwb3NzaWJsZUVtcHR5TWFya2VyID0gdGhpcy5yZW1vdmUoZmlyc3QpO1xuICAgICAgdGhpcy5yZW1vdmUobGFzdCk7XG5cbiAgICAgIGlmIChwb3NzaWJsZUVtcHR5TWFya2VyICE9PSBudWxsICYmIGlzRW1wdHkocG9zc2libGVFbXB0eU1hcmtlcikpIHtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGUgPSB0aGlzLnJlbW92ZShwb3NzaWJsZUVtcHR5TWFya2VyKTtcblxuICAgICAgICBpZiAodGhpcy5jYW5kaWRhdGUgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLmNsZWFyTWlzbWF0Y2godGhpcy5jYW5kaWRhdGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXdCb3VuZHM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdXBlci5fX2FwcGVuZEhUTUwoaHRtbCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIHJlbW92ZShub2RlOiBTaW1wbGVOb2RlKTogT3B0aW9uPFNpbXBsZU5vZGU+IHtcbiAgICBsZXQgZWxlbWVudCA9IGV4cGVjdChub2RlLnBhcmVudE5vZGUsIGBjYW5ub3QgcmVtb3ZlIGEgZGV0YWNoZWQgbm9kZWApIGFzIFNpbXBsZUVsZW1lbnQ7XG4gICAgbGV0IG5leHQgPSBub2RlLm5leHRTaWJsaW5nO1xuICAgIGVsZW1lbnQucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgcmV0dXJuIG5leHQ7XG4gIH1cblxuICBwcml2YXRlIG1hcmtlckJvdW5kcygpOiBPcHRpb248Qm91bmRzPiB7XG4gICAgbGV0IF9jYW5kaWRhdGUgPSB0aGlzLmNhbmRpZGF0ZTtcblxuICAgIGlmIChfY2FuZGlkYXRlICYmIGlzTWFya2VyKF9jYW5kaWRhdGUpKSB7XG4gICAgICBsZXQgZmlyc3QgPSBfY2FuZGlkYXRlO1xuICAgICAgbGV0IGxhc3QgPSBleHBlY3QoZmlyc3QubmV4dFNpYmxpbmcsIGBCVUc6IHNlcmlhbGl6YXRpb24gbWFya2VycyBtdXN0IGJlIHBhaXJlZGApO1xuXG4gICAgICB3aGlsZSAobGFzdCAmJiAhaXNNYXJrZXIobGFzdCkpIHtcbiAgICAgICAgbGFzdCA9IGV4cGVjdChsYXN0Lm5leHRTaWJsaW5nLCBgQlVHOiBzZXJpYWxpemF0aW9uIG1hcmtlcnMgbXVzdCBiZSBwYWlyZWRgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBDb25jcmV0ZUJvdW5kcyh0aGlzLmVsZW1lbnQsIGZpcnN0LCBsYXN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgX19hcHBlbmRUZXh0KHN0cmluZzogc3RyaW5nKTogU2ltcGxlVGV4dCB7XG4gICAgbGV0IHsgY2FuZGlkYXRlIH0gPSB0aGlzO1xuXG4gICAgaWYgKGNhbmRpZGF0ZSkge1xuICAgICAgaWYgKGlzVGV4dE5vZGUoY2FuZGlkYXRlKSkge1xuICAgICAgICBpZiAoY2FuZGlkYXRlLm5vZGVWYWx1ZSAhPT0gc3RyaW5nKSB7XG4gICAgICAgICAgY2FuZGlkYXRlLm5vZGVWYWx1ZSA9IHN0cmluZztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbmRpZGF0ZSA9IGNhbmRpZGF0ZS5uZXh0U2libGluZztcblxuICAgICAgICByZXR1cm4gY2FuZG