@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
555 lines (441 loc) • 53.6 kB
JavaScript
"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