// ==UserScript==
// @name watcher
// @version 0.0.1
// @description Watch for added and removed elements and changes to attributes or text content
// ==/UserScript==
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Watcher = factory());
}(this, (function () { 'use strict';
// ----------------------------------------------------
var Css;
(function (Css) {
Css.Inverse = 'color: white; background: black';
Css.Error = 'font-weight: bold; color: #f4f';
Css.Link = 'color: #05f; font-weight: normal; text-decoration: underline';
Css.Bold = 'font-weight: bold';
Css.Blue = 'color: #05f';
Css.Kw = 'color: #35b; font-weight: bold; font-style: normal; text-decoration: none';
Css.Attr = 'color: #563; font-weight: normal; font-style: italic; text-decoration: none';
Css.Val = 'color: #c36; font-weight: normal; font-style: normal; text-decoration: none';
})(Css || (Css = {}));
//# sourceMappingURL=interfaces.js.map
// ----------------------------------------------------------
function _log(collapsed, title, objs) {
if (collapsed) {
console.groupCollapsed(`%c${title}`, Css.Kw);
}
else {
console.group(`%c${title}`, Css.Kw);
}
for (const obj of objs) {
console.dir(obj);
}
console.groupEnd();
}
function log(title, ...objs) {
_log(false, title, objs);
}
function logc(title, ...objs) {
_log(true, title, objs);
}
//# sourceMappingURL=l.js.map
// ----------------------------------------------------
// ----------------------------------------------------
var WatchEvents;
(function (WatchEvents) {
WatchEvents[WatchEvents["ElementsAdded"] = 1] = "ElementsAdded";
WatchEvents[WatchEvents["ElementsRemoved"] = 2] = "ElementsRemoved";
WatchEvents[WatchEvents["AttributesChanged"] = 4] = "AttributesChanged";
WatchEvents[WatchEvents["TextChanged"] = 8] = "TextChanged";
WatchEvents[WatchEvents["ElementsChanged"] = 3] = "ElementsChanged";
WatchEvents[WatchEvents["AllChanges"] = 15] = "AllChanges";
})(WatchEvents || (WatchEvents = {}));
//# sourceMappingURL=watch-options.js.map
// ----------------------------------------------------
class AttributeChange {
constructor(element, name, value, oldValue) {
this.element = element;
this.name = name;
this.value = value;
this.oldValue = oldValue;
}
}
// ----------------------------------------------------
class TextChange {
constructor(element, value, oldValue) {
this.element = element;
this.value = value;
this.oldValue = oldValue;
}
}
// ----------------------------------------------------
class WatchResult {
constructor(parent, added, removed = [], attributeChanges = [], textChanges = []) {
this.parent = parent;
this.added = added;
this.removed = removed;
this.attributeChanges = attributeChanges;
this.textChanges = textChanges;
}
}
//# sourceMappingURL=watch-result.js.map
class ElementSet extends Set {
// get [Symbol.toStringTag]: string () {
// return 'ElementSet'
// }
// ----------------------------------------------------
addAll(elements) {
for (const element of elements) {
super.add(element);
}
return this;
}
// ----------------------------------------------------
toArray() {
return Array.from(this);
}
}
//# sourceMappingURL=element-set.js.map
// ----------------------------------------------------
class Matcher {
constructor(root, selector = '*') {
this.root = root;
this.selector = selector;
}
// ----------------------------------------------------
matchesElement(element) {
return element.matches(this.selector);
}
// ----------------------------------------------------
findAllMatchesInSubTree(element) {
const matches = Array.from(element.querySelectorAll(this.selector));
if (this.matchesElement(element)) {
matches.unshift(element);
}
return matches;
}
}
//# sourceMappingURL=matcher.js.map
// ----------------------------------------------------
// ----------------------------------------------------
function getElementNodesFromNodeList(nodes) {
return getNodesByType(nodes, 1);
}
// ----------------------------------------------------
function getTextNodesFromNodeList(nodes) {
return getNodesByType(nodes, 3);
}
// ----------------------------------------------------
function getNodesByType(nodes, nodeType) {
return Array.from(nodes).filter(node => node.nodeType === nodeType);
}
//# sourceMappingURL=dom.js.map
// ----------------------------------------------------------
class Watch {
// ----------------------------------------------------
constructor(parent, options, callback) {
this.parent = parent;
this.options = options;
this.callback = callback;
this.attributes = new Set();
this.allAttributes = false;
this.addedElementSet = new ElementSet();
this.removedElementSet = new ElementSet();
this.attributeChanges = [];
this.textChanges = [];
this.findExisting = typeof options.findExisting === 'boolean'
? options.findExisting
: true;
this.events = options.events || WatchEvents.ElementsChanged;
if (options.attributes) {
this.attributes = new Set(options.attributes);
}
else if (options.attribute) {
this.attributes.add(options.attribute);
}
else {
this.allAttributes = true;
}
this.matcher = new Matcher(this.parent.root, this.options.selector);
}
// ----------------------------------------------------
get [Symbol.toStringTag]() {
return 'Watch';
}
// ----------------------------------------------------
get selector() {
return this.matcher.selector;
}
// ----------------------------------------------------
processExistingElements() {
if (this.findExisting && this.events & WatchEvents.ElementsAdded) {
const matchingElements = this.matcher.findAllMatchesInSubTree(this.parent.root);
if (matchingElements.length > 0) {
this.addedElementSet.addAll(matchingElements);
this.doResultCallback();
}
}
}
// ----------------------------------------------------
initialise() {
this.addedElementSet.clear();
this.removedElementSet.clear();
this.attributeChanges = [];
this.textChanges = [];
if (this.parent.debug) {
logc(`Watch.initialise()`, this);
}
}
// ----------------------------------------------------
doResultCallback() {
if (this.parent.debug) {
logc(`Watch.processResult(): addedElementSet, removedElementSet, attributeChanges, textChanges`, this.addedElementSet, this.removedElementSet, this.attributeChanges, this.textChanges);
}
if (this.addedElementSet.size > 0 ||
this.removedElementSet.size > 0 ||
this.attributeChanges.length > 0 ||
this.textChanges.length > 0) {
const result = new WatchResult(this.parent, [...this.addedElementSet], [...this.removedElementSet], [...this.attributeChanges], [...this.textChanges]);
this.callback(result);
this.initialise();
}
}
// ----------------------------------------------------
processRecords(records) {
for (const [idx, record] of records.entries()) {
if (this.parent.debug) {
log(`Watch.processRecords(${idx}, type: ${record.type})`, record);
}
switch (record.type) {
case 'childList':
this.onNodeMutation(record);
break;
case 'attributes':
if (this.events & WatchEvents.AttributesChanged) {
this.onAttrMutation(record);
}
break;
case 'characterData':
if (this.events & WatchEvents.TextChanged) {
this.onTextMutation(record);
}
break;
default:
throw new Error('Unknown mutation type "${record.type}"');
}
}
this.doResultCallback();
}
// ----------------------------------------------------
onNodeMutation(summary) {
if (this.events & WatchEvents.ElementsAdded && summary.addedNodes.length > 0) {
for (const element of getElementNodesFromNodeList(summary.addedNodes)) {
this.addedElementSet.addAll(this.matcher.findAllMatchesInSubTree(element));
}
}
if (this.events & WatchEvents.ElementsRemoved && summary.removedNodes.length > 0) {
for (const element of getElementNodesFromNodeList(summary.removedNodes)) {
this.removedElementSet.addAll(this.matcher.findAllMatchesInSubTree(element));
}
}
if (this.events & WatchEvents.TextChanged) {
const addedTextNodes = getTextNodesFromNodeList(summary.addedNodes);
if (addedTextNodes.length > 0) {
const removedTextNodes = getTextNodesFromNodeList(summary.removedNodes);
const oldValue = removedTextNodes.length > 0
? removedTextNodes[0].textContent
: null;
const value = addedTextNodes[addedTextNodes.length - 1].textContent;
const change = new TextChange(summary.target, value, oldValue);
this.textChanges.push(change);
}
}
}
// ----------------------------------------------------
onAttrMutation(summary) {
const { target, attributeName, oldValue } = summary;
if (this.allAttributes || this.attributes.has(attributeName)) {
const element = target;
const value = element.getAttribute(attributeName);
const change = new AttributeChange(element, attributeName, value, oldValue);
this.attributeChanges.push(change);
}
}
// ----------------------------------------------------
onTextMutation(summary) {
const { target, oldValue } = summary;
const element = target.parentElement;
const change = new TextChange(element, element.textContent, oldValue);
this.textChanges.push(change);
}
// ----------------------------------------------------
dump() {
console.groupCollapsed(`%cWatch(%cselector: %c"${this.options.selector}"%c)`, Css.Kw, Css.Attr, Css.Link, Css.Kw);
console.dir(this.options);
console.log(this.callback.toString());
console.groupEnd();
}
}
//# sourceMappingURL=watch.js.map
// ----------------------------------------------------------
class Watcher {
// ----------------------------------------------------
constructor(root = document.body, debug = false) {
this.root = root;
this.debug = debug;
this.observer = null;
this.watches = [];
if (!(root instanceof HTMLElement)) {
throw new TypeError('Watch root is not a valid HTML element!');
}
}
// ----------------------------------------------------
get [Symbol.toStringTag]() {
return 'Watcher';
}
add(options, callback) {
if (typeof options === 'string') {
options = {
selector: options
};
}
else if (typeof options === 'function') {
callback = options;
options = {};
}
if (!callback) {
throw new Error('No callback function specified when calling Watcher.add()');
}
if (this.debug) {
console.groupCollapsed(`%cWatcher.add(selector: %c${options.selector}%c, %c${this.watchCount} watches%c)`, Css.Kw, Css.Link, Css.Kw, Css.Val, Css.Kw);
console.log(callback.toString());
if (options) {
console.dir(options);
}
console.groupEnd();
}
const watch = new Watch(this, options, callback);
if (this.observing) {
watch.processExistingElements();
}
this.watches.push(watch);
return watch;
}
// ----------------------------------------------------
get observing() {
return !!this.observer;
}
// ----------------------------------------------------
get watchCount() {
return this.watches.length;
}
// ----------------------------------------------------
start() {
if (!this.watchCount) {
throw new Error('Cannot start Watcher without any watches!');
}
if (this.debug) {
console.info(`%cWatcher.start(%cenabled = %c${this.observing ? 'true' : 'false'}%c, %c${this.watchCount} watches%c)`, Css.Kw, Css.Attr, Css.Val, Css.Kw, Css.Val, Css.Kw);
}
if (!this.observer) {
// Check for existing elements, pass to callback
for (const watch of this.watches) {
watch.processExistingElements();
}
this.observer = new MutationObserver(summaries => {
for (const watch of this.watches) {
watch.processRecords(summaries);
}
});
this.observer.observe(this.root, {
childList: true,
subtree: true,
attributes: true,
attributeOldValue: true,
characterData: true,
characterDataOldValue: true
});
}
return this;
}
// ----------------------------------------------------
stop() {
if (this.observer) {
const records = this.observer.takeRecords();
this.observer.disconnect();
for (const watch of this.watches) {
watch.processRecords(records);
}
this.observer = null;
}
return this;
}
}
//# sourceMappingURL=index.js.map
return Watcher;
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2hlci51bWQuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbnRlcmZhY2VzLnRzIiwiLi4vc3JjL3V0aWxzL2wudHMiLCIuLi9zcmMvd2F0Y2gtb3B0aW9ucy50cyIsIi4uL3NyYy93YXRjaC1yZXN1bHQudHMiLCIuLi9zcmMvZWxlbWVudC1zZXQudHMiLCIuLi9zcmMvbWF0Y2hlci50cyIsIi4uL3NyYy91dGlscy9kb20udHMiLCIuLi9zcmMvd2F0Y2gudHMiLCIuLi9zcmMvd2F0Y2hlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJcbmludGVyZmFjZSBDb25zb2xlIHtcbiAgZ3JvdXAgKGdyb3VwVGl0bGU/OiBzdHJpbmcsIC4uLm9wdGlvbmFsUGFyYW1zOiBhbnlbXSk6IHZvaWRcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgbmFtZXNwYWNlIENzcyB7XG4gIGV4cG9ydCBjb25zdCBJbnZlcnNlID0gJ2NvbG9yOiB3aGl0ZTsgYmFja2dyb3VuZDogYmxhY2snXG4gIGV4cG9ydCBjb25zdCBFcnJvciA9ICdmb250LXdlaWdodDogYm9sZDsgY29sb3I6ICNmNGYnXG4gIGV4cG9ydCBjb25zdCBMaW5rID0gJ2NvbG9yOiAjMDVmOyBmb250LXdlaWdodDogbm9ybWFsOyB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZSdcbiAgZXhwb3J0IGNvbnN0IEJvbGQgPSAnZm9udC13ZWlnaHQ6IGJvbGQnXG4gIGV4cG9ydCBjb25zdCBCbHVlID0gJ2NvbG9yOiAjMDVmJ1xuICBleHBvcnQgY29uc3QgS3cgPSAnY29sb3I6ICMzNWI7IGZvbnQtd2VpZ2h0OiBib2xkOyBmb250LXN0eWxlOiBub3JtYWw7IHRleHQtZGVjb3JhdGlvbjogbm9uZSdcbiAgZXhwb3J0IGNvbnN0IEF0dHIgPSAnY29sb3I6ICM1NjM7IGZvbnQtd2VpZ2h0OiBub3JtYWw7IGZvbnQtc3R5bGU6IGl0YWxpYzsgdGV4dC1kZWNvcmF0aW9uOiBub25lJ1xuICBleHBvcnQgY29uc3QgVmFsID0gJ2NvbG9yOiAjYzM2OyBmb250LXdlaWdodDogbm9ybWFsOyBmb250LXN0eWxlOiBub3JtYWw7IHRleHQtZGVjb3JhdGlvbjogbm9uZSdcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgaW50ZXJmYWNlIElOb2RlIHtcbiAgbm9kZXM/OiBJTm9kZVtdXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGludGVyZmFjZSBOb2RlTXV0YXRpb25SZWNvcmQge1xuICB0eXBlOiAnY2hpbGRMaXN0J1xuICB0YXJnZXQ6IE5vZGVcbiAgYWRkZWROb2RlczogTm9kZUxpc3RcbiAgcmVtb3ZlZE5vZGVzOiBOb2RlTGlzdFxuICBwcmV2aW91c1NpYmxpbmc6IE5vZGUgfCBudWxsXG4gIG5leHRTaWJsaW5nOiBOb2RlIHwgbnVsbFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dHJNdXRhdGlvblJlY29yZCB7XG4gIHR5cGU6ICdhdHRyaWJ1dGVzJ1xuICB0YXJnZXQ6IE5vZGVcbiAgYXR0cmlidXRlTmFtZTogc3RyaW5nXG4gIGF0dHJpYnV0ZU5hbWVzcGFjZTogc3RyaW5nXG4gIG9sZFZhbHVlOiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUZXh0TXV0YXRpb25SZWNvcmQge1xuICB0eXBlOiAnY2hhcmFjdGVyRGF0YSdcbiAgdGFyZ2V0OiBOb2RlXG4gIG9sZFZhbHVlOiBzdHJpbmdcbn1cblxuZXhwb3J0IHR5cGUgTXV0YXRpb25SZWNvcmRzID0gTm9kZU11dGF0aW9uUmVjb3JkIHwgQXR0ck11dGF0aW9uUmVjb3JkIHwgVGV4dE11dGF0aW9uUmVjb3JkXG4iLCJpbXBvcnQgeyBDc3MgfSBmcm9tICcuLi9pbnRlcmZhY2VzJ1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCBmdW5jdGlvbiBsb2dFbGVtZW50ICh0YWc6IHN0cmluZywgYXR0cnM6IGFueSwgY2hpbGRyZW46IGFueVtdKSB7XG4gIGNvbnNvbGUuZ3JvdXAoYCVjJHt0YWd9YCwgQ3NzLkJvbGQpXG4gIGNvbnNvbGUuaW5mbyhgJWNhdHRycyA9ICR7SlNPTi5zdHJpbmdpZnkoYXR0cnMsIG51bGwsIDIpfWAsIENzcy5JbnZlcnNlKVxuICAvLyBjb25zb2xlLmluZm8oYCVjZGF0YSA9ICR7SlNPTi5zdHJpbmdpZnkoZGF0YSwgbnVsbCwgMil9YCwgQ3NzLkludmVyc2UpXG4gIGlmIChjaGlsZHJlbikge1xuICAgIGNvbnNvbGUudGFibGUoY2hpbGRyZW4pXG4gIH1cbiAgY29uc29sZS5ncm91cEVuZCgpXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZnVuY3Rpb24gX2xvZyAoY29sbGFwc2VkOiBib29sZWFuLCB0aXRsZTogc3RyaW5nLCBvYmpzOiBhbnlbXSkge1xuICBpZiAoY29sbGFwc2VkKSB7XG4gICAgY29uc29sZS5ncm91cENvbGxhcHNlZChgJWMke3RpdGxlfWAsIENzcy5LdylcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmdyb3VwKGAlYyR7dGl0bGV9YCwgQ3NzLkt3KVxuICB9XG5cbiAgZm9yIChjb25zdCBvYmogb2Ygb2Jqcykge1xuICAgIGNvbnNvbGUuZGlyKG9iailcbiAgfVxuXG4gIGNvbnNvbGUuZ3JvdXBFbmQoKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9nICh0aXRsZTogc3RyaW5nLCAuLi5vYmpzOiBhbnlbXSkge1xuICBfbG9nKGZhbHNlLCB0aXRsZSwgb2Jqcylcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvZ2MgKHRpdGxlOiBzdHJpbmcsIC4uLm9ianM6IGFueVtdKSB7XG4gIF9sb2codHJ1ZSwgdGl0bGUsIG9ianMpXG59XG4iLCJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGludGVyZmFjZSBXYXRjaE9wdGlvbnMge1xuICBzZWxlY3Rvcj86IHN0cmluZ1xuICBmaW5kRXhpc3Rpbmc/OiBib29sZWFuXG4gIGV2ZW50cz86IFdhdGNoRXZlbnRzXG4gIGF0dHJpYnV0ZT86IHN0cmluZ1xuICBhdHRyaWJ1dGVzPzogc3RyaW5nW11cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgZW51bSBXYXRjaEV2ZW50cyB7XG4gIEVsZW1lbnRzQWRkZWQgPSAxLFxuICBFbGVtZW50c1JlbW92ZWQgPSAyLFxuICBBdHRyaWJ1dGVzQ2hhbmdlZCA9IDQsXG4gIFRleHRDaGFuZ2VkID0gOCxcblxuICBFbGVtZW50c0NoYW5nZWQgPSBFbGVtZW50c0FkZGVkIHwgRWxlbWVudHNSZW1vdmVkLFxuICBBbGxDaGFuZ2VzID0gRWxlbWVudHNBZGRlZCB8IEVsZW1lbnRzUmVtb3ZlZCB8IEF0dHJpYnV0ZXNDaGFuZ2VkIHwgVGV4dENoYW5nZWRcbn1cbiIsImltcG9ydCBXYXRjaGVyIGZyb20gJy4vd2F0Y2hlcidcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgY2xhc3MgQXR0cmlidXRlQ2hhbmdlIHtcbiAgY29uc3RydWN0b3IgKFxuICAgIHB1YmxpYyBlbGVtZW50OiBFbGVtZW50LFxuICAgIHB1YmxpYyBuYW1lOiBzdHJpbmcsXG4gICAgcHVibGljIHZhbHVlOiBzdHJpbmcgfCBudWxsLFxuICAgIHB1YmxpYyBvbGRWYWx1ZTogc3RyaW5nIHwgbnVsbFxuICApIHt9XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGNsYXNzIFRleHRDaGFuZ2Uge1xuICBjb25zdHJ1Y3RvciAoXG4gICAgcHVibGljIGVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcHVibGljIHZhbHVlOiBzdHJpbmcgfCBudWxsLFxuICAgIHB1YmxpYyBvbGRWYWx1ZTogc3RyaW5nIHwgbnVsbFxuICApIHt9XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGNsYXNzIFdhdGNoUmVzdWx0IHtcbiAgY29uc3RydWN0b3IgKFxuICAgIHByaXZhdGUgcGFyZW50OiBXYXRjaGVyLFxuICAgIHB1YmxpYyBhZGRlZDogRWxlbWVudFtdLFxuICAgIHB1YmxpYyByZW1vdmVkOiBFbGVtZW50W10gPSBbXSxcbiAgICBwdWJsaWMgYXR0cmlidXRlQ2hhbmdlczogQXR0cmlidXRlQ2hhbmdlW10gPSBbXSxcbiAgICBwdWJsaWMgdGV4dENoYW5nZXM6IFRleHRDaGFuZ2VbXSA9IFtdXG4gICkge31cbn1cbiIsIlxuZXhwb3J0IGNsYXNzIEVsZW1lbnRTZXQgZXh0ZW5kcyBTZXQ8RWxlbWVudD4ge1xuICAvLyBnZXQgW1N5bWJvbC50b1N0cmluZ1RhZ106IHN0cmluZyAoKSB7XG4gIC8vICAgcmV0dXJuICdFbGVtZW50U2V0J1xuICAvLyB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGFkZEFsbCAoZWxlbWVudHM6IEVsZW1lbnRbXSB8IEVsZW1lbnRTZXQpOiB0aGlzIHtcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcbiAgICAgIHN1cGVyLmFkZChlbGVtZW50KVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgdG9BcnJheSAoKTogRWxlbWVudFtdIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzKVxuICB9XG59XG4iLCJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGNsYXNzIE1hdGNoZXIge1xuICBjb25zdHJ1Y3RvciAoXG4gICAgcHVibGljIHJlYWRvbmx5IHJvb3Q6IEVsZW1lbnQsXG4gICAgcHVibGljIHJlYWRvbmx5IHNlbGVjdG9yOiBzdHJpbmcgPSAnKidcbiAgKSB7fVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBtYXRjaGVzRWxlbWVudCAoZWxlbWVudDogRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50Lm1hdGNoZXModGhpcy5zZWxlY3RvcilcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBmaW5kQWxsTWF0Y2hlc0luU3ViVHJlZSAoZWxlbWVudDogRWxlbWVudCk6IEVsZW1lbnRbXSB7XG4gICAgY29uc3QgbWF0Y2hlczogRWxlbWVudFtdID0gQXJyYXkuZnJvbShlbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5zZWxlY3RvcikpXG5cbiAgICBpZiAodGhpcy5tYXRjaGVzRWxlbWVudChlbGVtZW50KSkge1xuICAgICAgbWF0Y2hlcy51bnNoaWZ0KGVsZW1lbnQpXG4gICAgfVxuXG4gICAgcmV0dXJuIG1hdGNoZXNcbiAgfVxufVxuIiwiaW1wb3J0IHsgU2VsZWN0b3JGdW5jIH0gZnJvbSAnLi4vd2F0Y2gnXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNlbGVjdG9yRnVuY3Rpb24gKHNlbGVjdG9yOiBzdHJpbmcpOiBTZWxlY3RvckZ1bmMge1xuICByZXR1cm4gZnVuY3Rpb24gKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRbXSB7XG4gICAgY29uc3QgbWF0Y2hlczogSFRNTEVsZW1lbnRbXSA9IFtdXG5cbiAgICBpZiAoZWxlbWVudC5tYXRjaGVzKHNlbGVjdG9yKSkge1xuICAgICAgbWF0Y2hlcy5wdXNoKGVsZW1lbnQpXG4gICAgfVxuXG4gICAgcmV0dXJuIG1hdGNoZXMuY29uY2F0KEFycmF5LmZyb20oZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKSkpXG4gIH1cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWxlbWVudE5vZGVzRnJvbU5vZGVMaXN0IChub2RlczogTm9kZUxpc3QpOiBIVE1MRWxlbWVudFtdIHtcbiAgcmV0dXJuIGdldE5vZGVzQnlUeXBlPEhUTUxFbGVtZW50Pihub2RlcywgMSlcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGV4dE5vZGVzRnJvbU5vZGVMaXN0IChub2RlczogTm9kZUxpc3QpOiBUZXh0W10ge1xuICByZXR1cm4gZ2V0Tm9kZXNCeVR5cGU8VGV4dD4obm9kZXMsIDMpXG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE5vZGVzQnlUeXBlPFQgZXh0ZW5kcyBOb2RlPiAobm9kZXM6IE5vZGVMaXN0LCBub2RlVHlwZTogbnVtYmVyKTogVFtdIHtcbiAgcmV0dXJuIEFycmF5LmZyb20obm9kZXMpLmZpbHRlcihub2RlID0+IG5vZGUubm9kZVR5cGUgPT09IG5vZGVUeXBlKSBhcyBUW11cbn1cbiIsImltcG9ydCB7IENzcywgTXV0YXRpb25SZWNvcmRzLCBOb2RlTXV0YXRpb25SZWNvcmQsIEF0dHJNdXRhdGlvblJlY29yZCwgVGV4dE11dGF0aW9uUmVjb3JkIH0gZnJvbSAnLi9pbnRlcmZhY2VzJ1xuaW1wb3J0IHsgbG9nLCBsb2djIH0gZnJvbSAnLi91dGlscy9sJ1xuXG5pbXBvcnQgV2F0Y2hlciBmcm9tICcuL3dhdGNoZXInXG5pbXBvcnQgeyBXYXRjaE9wdGlvbnMsIFdhdGNoRXZlbnRzIH0gZnJvbSAnLi93YXRjaC1vcHRpb25zJ1xuaW1wb3J0IHsgV2F0Y2hSZXN1bHQsIEF0dHJpYnV0ZUNoYW5nZSwgVGV4dENoYW5nZSB9IGZyb20gJy4vd2F0Y2gtcmVzdWx0J1xuaW1wb3J0IHsgRWxlbWVudFNldCB9IGZyb20gJy4vZWxlbWVudC1zZXQnXG5pbXBvcnQgeyBNYXRjaGVyIH0gZnJvbSAnLi9tYXRjaGVyJ1xuXG5pbXBvcnQgeyBnZXRFbGVtZW50Tm9kZXNGcm9tTm9kZUxpc3QsIGdldFRleHROb2Rlc0Zyb21Ob2RlTGlzdCB9IGZyb20gJy4vdXRpbHMvZG9tJ1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCB0eXBlIFNlbGVjdG9yRnVuYyA9IChlbGVtZW50OiBIVE1MRWxlbWVudCkgPT4gSFRNTEVsZW1lbnRbXVxuXG5leHBvcnQgdHlwZSBXYXRjaENhbGxiYWNrID0gKHJlc3VsdDogV2F0Y2hSZXN1bHQpID0+IHZvaWRcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgY2xhc3MgV2F0Y2gge1xuICBwdWJsaWMgZmluZEV4aXN0aW5nOiBib29sZWFuXG5cbiAgcHVibGljIGV2ZW50czogV2F0Y2hFdmVudHNcblxuICBwdWJsaWMgYXR0cmlidXRlczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KClcbiAgcHVibGljIGFsbEF0dHJpYnV0ZXM6IGJvb2xlYW4gPSBmYWxzZVxuXG4gIG1hdGNoZXI6IE1hdGNoZXJcblxuICBhZGRlZEVsZW1lbnRTZXQ6IEVsZW1lbnRTZXQgPSBuZXcgRWxlbWVudFNldCgpXG4gIHJlbW92ZWRFbGVtZW50U2V0OiBFbGVtZW50U2V0ID0gbmV3IEVsZW1lbnRTZXQoKVxuXG4gIGF0dHJpYnV0ZUNoYW5nZXM6IEF0dHJpYnV0ZUNoYW5nZVtdID0gW11cbiAgdGV4dENoYW5nZXM6IFRleHRDaGFuZ2VbXSA9IFtdXG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGdldCBbU3ltYm9sLnRvU3RyaW5nVGFnXSAoKSB7XG4gICAgcmV0dXJuICdXYXRjaCdcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBjb25zdHJ1Y3RvciAoXG4gICAgcHJpdmF0ZSBwYXJlbnQ6IFdhdGNoZXIsXG4gICAgcHVibGljIHJlYWRvbmx5IG9wdGlvbnM6IFdhdGNoT3B0aW9ucyxcbiAgICBwdWJsaWMgcmVhZG9ubHkgY2FsbGJhY2s6IFdhdGNoQ2FsbGJhY2tcbiAgKSB7XG4gICAgdGhpcy5maW5kRXhpc3RpbmcgPSB0eXBlb2Ygb3B0aW9ucy5maW5kRXhpc3RpbmcgPT09ICdib29sZWFuJ1xuICAgICAgPyBvcHRpb25zLmZpbmRFeGlzdGluZ1xuICAgICAgOiB0cnVlXG5cbiAgICB0aGlzLmV2ZW50cyA9IG9wdGlvbnMuZXZlbnRzIHx8IFdhdGNoRXZlbnRzLkVsZW1lbnRzQ2hhbmdlZFxuXG4gICAgaWYgKG9wdGlvbnMuYXR0cmlidXRlcykge1xuICAgICAgdGhpcy5hdHRyaWJ1dGVzID0gbmV3IFNldChvcHRpb25zLmF0dHJpYnV0ZXMpXG4gICAgfSBlbHNlIGlmIChvcHRpb25zLmF0dHJpYnV0ZSkge1xuICAgICAgdGhpcy5hdHRyaWJ1dGVzLmFkZChvcHRpb25zLmF0dHJpYnV0ZSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hbGxBdHRyaWJ1dGVzID0gdHJ1ZVxuICAgIH1cblxuICAgIHRoaXMubWF0Y2hlciA9IG5ldyBNYXRjaGVyKHRoaXMucGFyZW50LnJvb3QsIHRoaXMub3B0aW9ucy5zZWxlY3RvcilcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBnZXQgc2VsZWN0b3IgKCkge1xuICAgIHJldHVybiB0aGlzLm1hdGNoZXIuc2VsZWN0b3JcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcm9jZXNzRXhpc3RpbmdFbGVtZW50cyAoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmluZEV4aXN0aW5nICYmIHRoaXMuZXZlbnRzICYgV2F0Y2hFdmVudHMuRWxlbWVudHNBZGRlZCkge1xuICAgICAgY29uc3QgbWF0Y2hpbmdFbGVtZW50cyA9IHRoaXMubWF0Y2hlci5maW5kQWxsTWF0Y2hlc0luU3ViVHJlZSh0aGlzLnBhcmVudC5yb290KVxuXG4gICAgICBpZiAobWF0Y2hpbmdFbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMuYWRkZWRFbGVtZW50U2V0LmFkZEFsbChtYXRjaGluZ0VsZW1lbnRzKVxuXG4gICAgICAgIHRoaXMuZG9SZXN1bHRDYWxsYmFjaygpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGluaXRpYWxpc2UgKCkge1xuICAgIHRoaXMuYWRkZWRFbGVtZW50U2V0LmNsZWFyKClcbiAgICB0aGlzLnJlbW92ZWRFbGVtZW50U2V0LmNsZWFyKClcblxuICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlcyA9IFtdXG4gICAgdGhpcy50ZXh0Q2hhbmdlcyA9IFtdXG5cbiAgICBpZiAodGhpcy5wYXJlbnQuZGVidWcpIHtcbiAgICAgIGxvZ2MoYFdhdGNoLmluaXRpYWxpc2UoKWAsIHRoaXMpXG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGRvUmVzdWx0Q2FsbGJhY2sgKCkge1xuICAgIGlmICh0aGlzLnBhcmVudC5kZWJ1Zykge1xuICAgICAgbG9nYyhgV2F0Y2gucHJvY2Vzc1Jlc3VsdCgpOiBhZGRlZEVsZW1lbnRTZXQsIHJlbW92ZWRFbGVtZW50U2V0LCBhdHRyaWJ1dGVDaGFuZ2VzLCB0ZXh0Q2hhbmdlc2AsIHRoaXMuYWRkZWRFbGVtZW50U2V0LCB0aGlzLnJlbW92ZWRFbGVtZW50U2V0LCB0aGlzLmF0dHJpYnV0ZUNoYW5nZXMsIHRoaXMudGV4dENoYW5nZXMpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYWRkZWRFbGVtZW50U2V0LnNpemUgPiAwIHx8XG4gICAgICAgIHRoaXMucmVtb3ZlZEVsZW1lbnRTZXQuc2l6ZSA+IDAgfHxcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVDaGFuZ2VzLmxlbmd0aCA+IDAgfHxcbiAgICAgICAgdGhpcy50ZXh0Q2hhbmdlcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBuZXcgV2F0Y2hSZXN1bHQoXG4gICAgICAgIHRoaXMucGFyZW50LFxuICAgICAgICBbIC4uLnRoaXMuYWRkZWRFbGVtZW50U2V0IF0sXG4gICAgICAgIFsgLi4udGhpcy5yZW1vdmVkRWxlbWVudFNldCBdLFxuICAgICAgICBbIC4uLnRoaXMuYXR0cmlidXRlQ2hhbmdlcyBdLFxuICAgICAgICBbIC4uLnRoaXMudGV4dENoYW5nZXMgXVxuICAgICAgKVxuXG4gICAgICB0aGlzLmNhbGxiYWNrKHJlc3VsdClcblxuICAgICAgdGhpcy5pbml0aWFsaXNlKClcbiAgICB9XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgcHJvY2Vzc1JlY29yZHMgKHJlY29yZHM6IE11dGF0aW9uUmVjb3JkW10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IFsgaWR4LCByZWNvcmQgXSBvZiByZWNvcmRzLmVudHJpZXMoKSkge1xuICAgICAgaWYgKHRoaXMucGFyZW50LmRlYnVnKSB7XG4gICAgICAgIGxvZyhgV2F0Y2gucHJvY2Vzc1JlY29yZHMoJHtpZHh9LCB0eXBlOiAke3JlY29yZC50eXBlfSlgLCByZWNvcmQpXG4gICAgICB9XG5cbiAgICAgIHN3aXRjaCAocmVjb3JkLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnY2hpbGRMaXN0JzpcbiAgICAgICAgICB0aGlzLm9uTm9kZU11dGF0aW9uKHJlY29yZCBhcyBOb2RlTXV0YXRpb25SZWNvcmQpXG4gICAgICAgICAgYnJlYWtcblxuICAgICAgICBjYXNlICdhdHRyaWJ1dGVzJzpcbiAgICAgICAgICBpZiAodGhpcy5ldmVudHMgJiBXYXRjaEV2ZW50cy5BdHRyaWJ1dGVzQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5vbkF0dHJNdXRhdGlvbihyZWNvcmQgYXMgQXR0ck11dGF0aW9uUmVjb3JkKVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgJ2NoYXJhY3RlckRhdGEnOlxuICAgICAgICAgIGlmICh0aGlzLmV2ZW50cyAmIFdhdGNoRXZlbnRzLlRleHRDaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLm9uVGV4dE11dGF0aW9uKHJlY29yZCBhcyBUZXh0TXV0YXRpb25SZWNvcmQpXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gbXV0YXRpb24gdHlwZSBcIiR7cmVjb3JkLnR5cGV9XCInKVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZG9SZXN1bHRDYWxsYmFjaygpXG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgb25Ob2RlTXV0YXRpb24gKHN1bW1hcnk6IE5vZGVNdXRhdGlvblJlY29yZCkge1xuICAgIGlmICh0aGlzLmV2ZW50cyAmIFdhdGNoRXZlbnRzLkVsZW1lbnRzQWRkZWQgJiYgc3VtbWFyeS5hZGRlZE5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBnZXRFbGVtZW50Tm9kZXNGcm9tTm9kZUxpc3Qoc3VtbWFyeS5hZGRlZE5vZGVzKSkge1xuICAgICAgICB0aGlzLmFkZGVkRWxlbWVudFNldC5hZGRBbGwodGhpcy5tYXRjaGVyLmZpbmRBbGxNYXRjaGVzSW5TdWJUcmVlKGVsZW1lbnQpKVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmV2ZW50cyAmIFdhdGNoRXZlbnRzLkVsZW1lbnRzUmVtb3ZlZCAmJiBzdW1tYXJ5LnJlbW92ZWROb2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZ2V0RWxlbWVudE5vZGVzRnJvbU5vZGVMaXN0KHN1bW1hcnkucmVtb3ZlZE5vZGVzKSkge1xuICAgICAgICB0aGlzLnJlbW92ZWRFbGVtZW50U2V0LmFkZEFsbCh0aGlzLm1hdGNoZXIuZmluZEFsbE1hdGNoZXNJblN1YlRyZWUoZWxlbWVudCkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZXZlbnRzICYgV2F0Y2hFdmVudHMuVGV4dENoYW5nZWQpIHtcbiAgICAgIGNvbnN0IGFkZGVkVGV4dE5vZGVzID0gZ2V0VGV4dE5vZGVzRnJvbU5vZGVMaXN0KHN1bW1hcnkuYWRkZWROb2RlcylcblxuICAgICAgaWYgKGFkZGVkVGV4dE5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgcmVtb3ZlZFRleHROb2RlcyA9IGdldFRleHROb2Rlc0Zyb21Ob2RlTGlzdChzdW1tYXJ5LnJlbW92ZWROb2RlcylcblxuICAgICAgICBjb25zdCBvbGRWYWx1ZSA9IHJlbW92ZWRUZXh0Tm9kZXMubGVuZ3RoID4gMFxuICAgICAgICAgID8gcmVtb3ZlZFRleHROb2Rlc1sgMCBdLnRleHRDb250ZW50XG4gICAgICAgICAgOiBudWxsXG5cbiAgICAgICAgY29uc3QgdmFsdWUgPSBhZGRlZFRleHROb2Rlc1sgYWRkZWRUZXh0Tm9kZXMubGVuZ3RoIC0gMSBdLnRleHRDb250ZW50XG5cbiAgICAgICAgY29uc3QgY2hhbmdlID0gbmV3IFRleHRDaGFuZ2Uoc3VtbWFyeS50YXJnZXQgYXMgRWxlbWVudCwgdmFsdWUsIG9sZFZhbHVlKVxuICAgICAgICB0aGlzLnRleHRDaGFuZ2VzLnB1c2goY2hhbmdlKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBvbkF0dHJNdXRhdGlvbiAoc3VtbWFyeTogQXR0ck11dGF0aW9uUmVjb3JkKSB7XG4gICAgY29uc3QgeyB0YXJnZXQsIGF0dHJpYnV0ZU5hbWUsIG9sZFZhbHVlIH0gPSBzdW1tYXJ5XG5cbiAgICBpZiAodGhpcy5hbGxBdHRyaWJ1dGVzIHx8IHRoaXMuYXR0cmlidXRlcy5oYXMoYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0YXJnZXQgYXMgRWxlbWVudFxuICAgICAgY29uc3QgdmFsdWUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lKVxuXG4gICAgICBjb25zdCBjaGFuZ2UgPSBuZXcgQXR0cmlidXRlQ2hhbmdlKGVsZW1lbnQsIGF0dHJpYnV0ZU5hbWUsIHZhbHVlLCBvbGRWYWx1ZSlcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlcy5wdXNoKGNoYW5nZSlcbiAgICB9XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgb25UZXh0TXV0YXRpb24gKHN1bW1hcnk6IFRleHRNdXRhdGlvblJlY29yZCkge1xuICAgIGNvbnN0IHsgdGFyZ2V0LCBvbGRWYWx1ZSB9ID0gc3VtbWFyeVxuICAgIGNvbnN0IGVsZW1lbnQgPSB0YXJnZXQucGFyZW50RWxlbWVudCBhcyBFbGVtZW50XG5cbiAgICBjb25zdCBjaGFuZ2UgPSBuZXcgVGV4dENoYW5nZShlbGVtZW50LCBlbGVtZW50LnRleHRDb250ZW50LCBvbGRWYWx1ZSlcbiAgICB0aGlzLnRleHRDaGFuZ2VzLnB1c2goY2hhbmdlKVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGR1bXAgKCkge1xuICAgIGNvbnNvbGUuZ3JvdXBDb2xsYXBzZWQoYCVjV2F0Y2goJWNzZWxlY3RvcjogJWNcIiR7dGhpcy5vcHRpb25zLnNlbGVjdG9yfVwiJWMpYCwgQ3NzLkt3LCBDc3MuQXR0ciwgQ3NzLkxpbmssIENzcy5LdylcbiAgICBjb25zb2xlLmRpcih0aGlzLm9wdGlvbnMpXG4gICAgY29uc29sZS5sb2codGhpcy5jYWxsYmFjay50b1N0cmluZygpKVxuICAgIGNvbnNvbGUuZ3JvdXBFbmQoKVxuICB9XG59XG4iLCJpbXBvcnQgeyBDc3MgfSBmcm9tICcuL2ludGVyZmFjZXMnXG5cbmltcG9ydCB7IFdhdGNoQ2FsbGJhY2ssIFdhdGNoIH0gZnJvbSAnLi93YXRjaCdcbmltcG9ydCB7IFdhdGNoT3B0aW9ucyB9IGZyb20gJy4vd2F0Y2gtb3B0aW9ucydcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXYXRjaGVyIHtcblxuICBvYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlciB8IG51bGwgPSBudWxsXG5cbiAgcmVhZG9ubHkgd2F0Y2hlczogV2F0Y2hbXSA9IFtdXG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGdldCBbU3ltYm9sLnRvU3RyaW5nVGFnXSAoKSB7XG4gICAgcmV0dXJuICdXYXRjaGVyJ1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGNvbnN0cnVjdG9yIChcbiAgICBwdWJsaWMgcmVhZG9ubHkgcm9vdDogSFRNTEVsZW1lbnQgPSBkb2N1bWVudC5ib2R5LFxuICAgIHB1YmxpYyByZWFkb25seSBkZWJ1ZzogYm9vbGVhbiA9IGZhbHNlXG4gICkge1xuICAgIGlmICghKHJvb3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1dhdGNoIHJvb3QgaXMgbm90IGEgdmFsaWQgSFRNTCBlbGVtZW50IScpXG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGFkZCAoY2FsbGJhY2s6IFdhdGNoQ2FsbGJhY2spOiBXYXRjaFxuICBhZGQgKG9wdGlvbnM6IHN0cmluZyB8IFdhdGNoT3B0aW9ucywgY2FsbGJhY2s6IFdhdGNoQ2FsbGJhY2spOiBXYXRjaFxuXG4gIGFkZCAob3B0aW9uczogc3RyaW5nIHwgV2F0Y2hPcHRpb25zIHwgV2F0Y2hDYWxsYmFjaywgY2FsbGJhY2s/OiBXYXRjaENhbGxiYWNrKTogV2F0Y2gge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgIHNlbGVjdG9yOiBvcHRpb25zXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRpb25zXG4gICAgICBvcHRpb25zID0ge31cbiAgICB9XG5cbiAgICBpZiAoIWNhbGxiYWNrKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNhbGxiYWNrIGZ1bmN0aW9uIHNwZWNpZmllZCB3aGVuIGNhbGxpbmcgV2F0Y2hlci5hZGQoKScpXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZGVidWcpIHtcbiAgICAgIGNvbnNvbGUuZ3JvdXBDb2xsYXBzZWQoYCVjV2F0Y2hlci5hZGQoc2VsZWN0b3I6ICVjJHtvcHRpb25zLnNlbGVjdG9yfSVjLCAlYyR7dGhpcy53YXRjaENvdW50fSB3YXRjaGVzJWMpYCwgQ3NzLkt3LCBDc3MuTGluaywgQ3NzLkt3LCBDc3MuVmFsLCBDc3MuS3cpXG4gICAgICBjb25zb2xlLmxvZyhjYWxsYmFjay50b1N0cmluZygpKVxuICAgICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgICAgY29uc29sZS5kaXIob3B0aW9ucylcbiAgICAgIH1cbiAgICAgIGNvbnNvbGUuZ3JvdXBFbmQoKVxuICAgIH1cblxuICAgIGNvbnN0IHdhdGNoID0gbmV3IFdhdGNoKHRoaXMsIG9wdGlvbnMsIGNhbGxiYWNrKVxuXG4gICAgaWYgKHRoaXMub2JzZXJ2aW5nKSB7XG4gICAgICB3YXRjaC5wcm9jZXNzRXhpc3RpbmdFbGVtZW50cygpXG4gICAgfVxuXG4gICAgdGhpcy53YXRjaGVzLnB1c2god2F0Y2gpXG5cbiAgICByZXR1cm4gd2F0Y2hcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBnZXQgb2JzZXJ2aW5nICgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLm9ic2VydmVyXG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgZ2V0IHdhdGNoQ291bnQgKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMud2F0Y2hlcy5sZW5ndGhcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBzdGFydCAoKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLndhdGNoQ291bnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHN0YXJ0IFdhdGNoZXIgd2l0aG91dCBhbnkgd2F0Y2hlcyEnKVxuICAgIH1cblxuICAgIGlmICh0aGlzLmRlYnVnKSB7XG4gICAgICBjb25zb2xlLmluZm8oYCVjV2F0Y2hlci5zdGFydCglY2VuYWJsZWQgPSAlYyR7dGhpcy5vYnNlcnZpbmcgPyAndHJ1ZScgOiAnZmFsc2UnfSVjLCAlYyR7dGhpcy53YXRjaENvdW50fSB3YXRjaGVzJWMpYCwgQ3NzLkt3LCBDc3MuQXR0ciwgQ3NzLlZhbCwgQ3NzLkt3LCBDc3MuVmFsLCBDc3MuS3cpXG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLm9ic2VydmVyKSB7XG4gICAgICAvLyBDaGVjayBmb3IgZXhpc3RpbmcgZWxlbWVudHMsIHBhc3MgdG8gY2FsbGJhY2tcbiAgICAgIGZvciAoY29uc3Qgd2F0Y2ggb2YgdGhpcy53YXRjaGVzKSB7XG4gICAgICAgIHdhdGNoLnByb2Nlc3NFeGlzdGluZ0VsZW1lbnRzKClcbiAgICAgIH1cblxuICAgICAgdGhpcy5vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKHN1bW1hcmllcyA9PiB7XG4gICAgICAgIGZvciAoY29uc3Qgd2F0Y2ggb2YgdGhpcy53YXRjaGVzKSB7XG4gICAgICAgICAgd2F0Y2gucHJvY2Vzc1JlY29yZHMoc3VtbWFyaWVzKVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICB0aGlzLm9ic2VydmVyLm9ic2VydmUodGhpcy5yb290LCB7XG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgYXR0cmlidXRlT2xkVmFsdWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGFPbGRWYWx1ZTogdHJ1ZVxuICAgICAgfSlcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHN0b3AgKCk6IHRoaXMge1xuICAgIGlmICh0aGlzLm9ic2VydmVyKSB7XG4gICAgICBjb25zdCByZWNvcmRzID0gdGhpcy5vYnNlcnZlci50YWtlUmVjb3JkcygpXG4gICAgICB0aGlzLm9ic2VydmVyLmRpc2Nvbm5lY3QoKVxuXG4gICAgICBmb3IgKGNvbnN0IHdhdGNoIG9mIHRoaXMud2F0Y2hlcykge1xuICAgICAgICB3YXRjaC5wcm9jZXNzUmVjb3JkcyhyZWNvcmRzKVxuICAgICAgfVxuXG4gICAgICB0aGlzLm9ic2VydmVyID0gbnVsbFxuICAgIH1cblxuICAgIHJldHVybiB0aGlzXG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFLQTtBQUVBLElBQWlCLEdBQUcsQ0FTbkI7QUFURCxXQUFpQixHQUFHO0lBQ0wsV0FBTyxHQUFHLGlDQUFpQyxDQUFBO0lBQzNDLFNBQUssR0FBRyxnQ0FBZ0MsQ0FBQTtJQUN4QyxRQUFJLEdBQUcsOERBQThELENBQUE7SUFDckUsUUFBSSxHQUFHLG1CQUFtQixDQUFBO0lBQzFCLFFBQUksR0FBRyxhQUFhLENBQUE7SUFDcEIsTUFBRSxHQUFHLDJFQUEyRSxDQUFBO0lBQ2hGLFFBQUksR0FBRyw2RUFBNkUsQ0FBQTtJQUNwRixPQUFHLEdBQUcsNkVBQTZFLENBQUE7Q0FDakcsRUFUZ0IsR0FBRyxLQUFILEdBQUcsUUFTbkI7OztBQ0ZEO0FBRUEsY0FBZSxTQUFrQixFQUFFLEtBQWEsRUFBRSxJQUFXO0lBQzNELElBQUksU0FBUyxFQUFFO1FBQ2IsT0FBTyxDQUFDLGNBQWMsQ0FBQyxLQUFLLEtBQUssRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQTtLQUM3QztTQUFNO1FBQ0wsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQTtLQUNwQztJQUVELEtBQUssTUFB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