UNPKG

@wikipathways/cxml

Version:

Advanced schema-aware streaming XML parser

427 lines 59.4 kB
"use strict"; // This file is part of cxml, copyright (c) 2016-2017 BusFaster Ltd. // Released under the MIT license, see LICENSE. Object.defineProperty(exports, "__esModule", { value: true }); var lodash_1 = require("lodash"); var Promise = require("bluebird"); var sax = require("sax"); var State_1 = require("./State"); var JS_1 = require("../importer/JS"); var xpath_1 = require("../spinoffs/xpath"); function findInMapIter( // TODO why can't I mark this as BTree<T> instead of any? mapIter, compare) { var _a = mapIter.next(), value = _a.value, done = _a.done; if (!value) { return; } var itemParsed = value[0], childMap = value[1]; if (!compare(itemParsed)) { if (done) { return; } return findInMapIter(mapIter, compare); } else { return childMap; } } var opHandlers = { // equal "=": function (item, left, right) { return item[left] === right; }, // not equal "!=": function (item, left, right) { return item[left] !== right; }, // less than "&lt;": function (item, left, right) { return item[left] < right; }, // less than or equal to "&lt;=": function (item, left, right) { return item[left] < right; }, // greater than "&gt;": function (item, left, right) { return item[left] > right; }, // greater than or equal to "&gt;=": function (item, left, right) { return item[left] > right; } }; opHandlers[">"] = opHandlers["&gt;"]; opHandlers[">="] = opHandlers["&gt;="]; /* opHandlers["&gt;"]({} as HandlerInstance, "CenterX", 2); opHandlers["&gt;"]({} as HandlerInstance, "CenterX", "b"); opHandlers["&gt;"]({} as HandlerInstance, "a", "b"); opHandlers[">"]({} as HandlerInstance, "CenterX", 2); opHandlers[">"]({} as HandlerInstance, "a", 2); opHandlers[">="]({} as HandlerInstance, 1, 2); opHandlers[">="]({} as HandlerInstance, "a", 2); opHandlers["="]({} as HandlerInstance, "a", 2); //*/ function findEntry(mapIter, compare) { var _a = mapIter.next(), value = _a.value, done = _a.done; if (!value) { return; } var itemParsed = value[0], childMap = value[1]; if (!compare(itemParsed)) { if (done) { return; } return findEntry(mapIter, compare); } else { return [childMap, itemParsed]; } } function getAttachmentMethod(state, bTree, attachmentMethodName) { var member = (!!state.memberRef && state.memberRef.member) || {}; // TODO should we use state.memberRef.safeName here? var memberName = !!member && member.name; var memberNamespace = !!member && !!member.namespace && member.namespace.name; if (!memberName) { var attachmentMethod = bTree.get(attachmentMethodName); if (attachmentMethod) { return attachmentMethod; } else { throw new Error("getAttachmentMethod failed to find " + attachmentMethodName + " function"); } } var item = state.item || {}; /*{ left: string; op: keyof NonBinaryOpHandlers; right: string } { left: number; op: keyof BinaryOpHandlers; right: number } | { left: string | number; op: keyof NonBinaryOpHandlers; right: string | number; } //*/ var value = findInMapIter(bTree.entries(), function (_a) { var axis = _a.axis, namespace = _a.namespace, name = _a.name, predicates = _a.predicates, attribute = _a.attribute; return (["", memberNamespace].indexOf(namespace) > -1 && name === memberName && (!predicates || predicates.reduce(function (acc, _a) { var left = _a.left, op = _a.op, right = _a.right; return acc && opHandlers[op](item, left, right); }, true))); }); if (!value) { // NOTE: we can end up here because there is no direct connection between // a Parser instance's attach and _parse methods. They actually just // connect via the rule.handler prototype. So it's possible for one // attachment method to set something on the rule.handler prototype, meaning it // appears to exist when we look at item._before or item._after in _parser, // but it doesn't actually exist for this xpath when we match the // state and bTree, level by level, up to the point where there should be // a _before or _after. return; } var parent = state.parent; if (!!parent) { return getAttachmentMethod(parent, value, attachmentMethodName); } else { return value.get(attachmentMethodName); } } var converterTbl = { Date: function (item) { var dateParts = item.match(/([0-9]+)-([0-9]+)-([0-9]+)(?:T([0-9]+):([0-9]+):([0-9]+)(\.[0-9]+)?)?(?:Z|([+-][0-9]+):([0-9]+))?/); if (!dateParts) return null; var offsetMinutes = +(dateParts[9] || "0"); var offset = +(dateParts[8] || "0") * 60; if (offset < 0) offsetMinutes = -offsetMinutes; offset += offsetMinutes; var date = new Date(+dateParts[1], +dateParts[2] - 1, +dateParts[3], +(dateParts[4] || "0"), +(dateParts[5] || "0"), +(dateParts[6] || "0"), +(dateParts[7] || "0") * 1000); date.setTime(date.getTime() - (offset + date.getTimezoneOffset()) * 60000); date.cxmlTimezoneOffset = offset; return date; }, boolean: function (item) { return item == "true"; }, string: function (item) { return item; }, number: function (item) { return +item; } }; function convertPrimitive(text, type) { var converter = converterTbl[type.primitiveType]; if (converter) { if (type.isList) { return text .trim() .split(/\s+/) .map(converter); } else { return converter(text.trim()); } } return null; } var Parser = /** @class */ (function () { function Parser(xpathNamespaceTbl) { if (xpathNamespaceTbl === void 0) { xpathNamespaceTbl = { "": "" }; } // TODO why do I need to use BTree<any> here? // I should be able to use BTree<T> this.bTree = new Map(); // TODO there is probably a better way to do this. // It appears the context param in the parser.parser // method may have be intended for the same purpose. this.xpathNamespaceTbl = xpathNamespaceTbl; } Parser.prototype.attach = function (handler, xpath) { var xpathNamespaceTbl = this.xpathNamespaceTbl; var proto = handler.prototype; var realHandler = handler.rule.handler; var realProto = realHandler.prototype; var customHandlerKeys = Object.keys(proto); for (var _i = 0, customHandlerKeys_1 = customHandlerKeys; _i < customHandlerKeys_1.length; _i++) { var customHandlerKey = customHandlerKeys_1[_i]; var timeBasedKeys = ["_before", "_after"]; if (timeBasedKeys.indexOf(customHandlerKey) === -1) { realProto[customHandlerKey] = proto[customHandlerKey]; } } // TODO is this really the best way to do this? var _before = proto._before, _after = proto._after; if (xpath) { if (_before || _after) { // TODO we are mutating reversedXPathElMatchers for xpath // expressions with attributes, such as // "/Pathway/@GraphId" // or // "/Pathway/@*" // because we need to first just match the element(s), and // then afterwards match any attribute. var reversedXPathElMatchers = xpath_1.parse(xpath, xpathNamespaceTbl).reverse(); var xpathAttrMatcher_1; if (reversedXPathElMatchers[0].attribute !== null) { xpathAttrMatcher_1 = reversedXPathElMatchers.shift(); } var finalItem = reversedXPathElMatchers.reduce(function (parentMap, xpathElMatcher) { var xpathElMatcherPairs = lodash_1.toPairs(xpathElMatcher); var _a = findEntry(parentMap.entries(), function (candidateItemParsed) { return xpathElMatcherPairs.reduce(function (isRunningMatch, _a) { var xpathElMatcherKey = _a[0], xpathElMatcherValue = _a[1]; return (isRunningMatch && candidateItemParsed[xpathElMatcherKey] === xpathElMatcherValue); }, true); }) || [new Map(), xpathElMatcher], currentMap = _a[0], currentItemParsed = _a[1]; parentMap.set(currentItemParsed, currentMap); return currentMap; }, this.bTree); if (_before) { finalItem.set("_before", !xpathAttrMatcher_1 || xpathAttrMatcher_1.attribute === "*" ? _before : function () { var picked = lodash_1.pick(this, xpathAttrMatcher_1.attribute); _before.call(picked); }); } if (_after) { finalItem.set("_after", _after); } } } realHandler._custom = true; }; Parser.prototype.parse = function (stream, output, context) { var _this = this; return new Promise(function (resolve, reject) { return _this._parse(stream, output, context || JS_1.defaultContext, resolve, reject); }); }; Parser.prototype._parse = function (stream, output, context, resolve, reject) { var bTree = this.bTree; var xml = sax.createStream(true, { position: true }); var rule = output.constructor.rule; var xmlSpace = context.registerNamespace("http://www.w3.org/XML/1998/namespace"); var namespaceTbl = { "": [rule.namespace, rule.namespace.getPrefix()], xml: [xmlSpace, xmlSpace.getPrefix()] }; var state = new State_1.State(null, null, rule, new rule.handler(), namespaceTbl); var rootState = state; var parentItem; /** Add a new xmlns prefix recognized inside current tag and its children. */ function addNamespace(short, namespace) { if (namespaceTbl[short] && namespaceTbl[short][0] == namespace) return; if (namespaceTbl == state.namespaceTbl) { // Copy parent namespace table on first write. namespaceTbl = {}; for (var _i = 0, _a = Object.keys(state.namespaceTbl); _i < _a.length; _i++) { var key = _a[_i]; namespaceTbl[key] = state.namespaceTbl[key]; } } namespaceTbl[short] = [namespace, namespace.getPrefix()]; } xml.on("opentag", function (node) { var attrTbl = node.attributes; var attr; var nodePrefix = ""; var name = node.name; var splitter = name.indexOf(":"); var item = null; namespaceTbl = state.namespaceTbl; // Read xmlns namespace prefix definitions before parsing node name. for (var _i = 0, _a = Object.keys(attrTbl); _i < _a.length; _i++) { var key = _a[_i]; if (key.substr(0, 5) == "xmlns") { var nsParts = key.match(/^xmlns(:(.+))?$/); if (nsParts) { addNamespace(nsParts[2] || "", context.registerNamespace(attrTbl[key])); } } } // Parse node name and possible namespace prefix. if (splitter >= 0) { nodePrefix = name.substr(0, splitter); name = name.substr(splitter + 1); } // Add internal surrogate key namespace prefix to node name. var nodeNamespace = namespaceTbl[nodePrefix]; name = nodeNamespace[1] + name; var child; var rule; if (state.rule) { child = state.rule.childTbl[name]; if (child) { if (child.proxy) { rule = child.proxy.member.rule; state = new State_1.State(state, child.proxy, rule, new rule.handler(), namespaceTbl); } rule = child.member.rule; } } if (rule && !rule.isPlainPrimitive) { item = new rule.handler(); // Parse all attributes. for (var _b = 0, _c = Object.keys(attrTbl); _b < _c.length; _b++) { var key = _c[_b]; splitter = key.indexOf(":"); if (splitter >= 0) { var attrPrefix = key.substr(0, splitter); if (attrPrefix == "xmlns") continue; var attrNamespace = namespaceTbl[attrPrefix]; if (attrNamespace) { attr = attrNamespace[1] + key.substr(splitter + 1); } else { console.warn("Namespace not found for " + key); continue; } } else { attr = nodeNamespace[1] + key; } var ref = rule.attributeTbl[attr]; if (ref && ref.member.rule.isPlainPrimitive) { item[ref.safeName] = convertPrimitive(attrTbl[key], ref.member.rule); } } if (state.parent) { Object.defineProperty(item, "_parent", { enumerable: false, value: state.parent.item }); } Object.defineProperty(item, "_name", { enumerable: false, value: node.name }); } state = new State_1.State(state, child, rule, item, namespaceTbl); // TODO why did the previous version of this lib check // (rule && !rule.isPlainPrimitive) before running _before? // I'm keeping the check for now, until I figure out why. // TODO also, why did it run '_before' prior to re-setting state // (re-setting in the line above)? if (rule && !rule.isPlainPrimitive) { var thisBefore = getAttachmentMethod(state, bTree, "_before"); if (!!thisBefore) { thisBefore.call(item); } } }); xml.on("text", function (text) { if (state.rule && state.rule.isPrimitive) { if (!state.textList) state.textList = []; state.textList.push(text); } }); xml.on("closetag", function (name) { var member = state.memberRef; var obj = state.item; var item = obj; var text; if (state.rule && state.rule.isPrimitive) { text = (state.textList || []).join("").trim(); } if (text) { var content = convertPrimitive(text, state.rule); if (state.rule.isPlainPrimitive) { item = content; } else { obj.content = content; } } if (obj) { var thisAfter = getAttachmentMethod(state, bTree, "_after"); if (!!thisAfter) { thisAfter.call(obj); } } state = state.parent; if (member && member.proxy) { if (item) state.item[member.safeName] = item; item = state.item; state = state.parent; member = member.proxy; } if (item) { var parent_1 = state.item; if (parent_1) { if (member.max > 1) { if (!parent_1.hasOwnProperty(member.safeName)) { parent_1[member.safeName] = []; } parent_1[member.safeName].push(item); } else { parent_1[member.safeName] = item; } } } }); xml.on("end", function () { resolve(rootState.item); }); xml.on("error", function (err) { console.error(err); }); if (typeof stream == "string") { xml.write(stream); xml.end(); } else stream.pipe(xml); }; return Parser; }()); exports.Parser = Parser; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BhcnNlci9QYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLG9FQUFvRTtBQUNwRSwrQ0FBK0M7O0FBRS9DLGlDQUF1QztBQUV2QyxrQ0FBb0M7QUFDcEMseUJBQTJCO0FBTTNCLGlDQUFnQztBQUNoQyxxQ0FBZ0Q7QUFDaEQsMkNBQXNEO0FBMkJ0RCxTQUFTLGFBQWE7QUFDcEIseURBQXlEO0FBQ3pELE9BQW9DLEVBQ3BDLE9BQW1DO0lBRTdCLElBQUEsbUJBQWdDLEVBQTlCLGdCQUFLLEVBQUUsY0FBdUIsQ0FBQztJQUN2QyxJQUFJLENBQUMsS0FBSyxFQUFFO1FBQ1YsT0FBTztLQUNSO0lBQ00sSUFBQSxxQkFBVSxFQUFFLG1CQUFRLENBQVU7SUFDckMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRTtRQUN4QixJQUFJLElBQUksRUFBRTtZQUNSLE9BQU87U0FDUjtRQUNELE9BQU8sYUFBYSxDQUFJLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztLQUMzQztTQUFNO1FBQ0wsT0FBTyxRQUFRLENBQUM7S0FDakI7QUFDSCxDQUFDO0FBc0JELElBQUksVUFBVSxHQUFHO0lBQ2YsUUFBUTtJQUNSLEdBQUcsRUFBRSxVQUFTLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSztRQUM3QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLENBQUM7SUFDOUIsQ0FBQztJQUNELFlBQVk7SUFDWixJQUFJLEVBQUUsVUFBUyxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUs7UUFDOUIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxDQUFDO0lBQzlCLENBQUM7SUFDRCxZQUFZO0lBQ1osTUFBTSxFQUFFLFVBQVMsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLO1FBQ2hDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUss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QUFDLENBQUM7UUFFSCxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxVQUFTLEdBQVU7WUFDakMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyQixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksT0FBTyxNQUFNLElBQUksUUFBUSxFQUFFO1lBQzdCLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBZ0IsQ0FBQyxDQUFDO1lBQzVCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNYOztZQUFPLE1BQTBCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDSCxhQUFDO0FBQUQsQ0FBQyxBQTFWRCxJQTBWQztBQTFWWSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIGN4bWwsIGNvcHlyaWdodCAoYykgMjAxNi0yMDE3IEJ1c0Zhc3RlciBMdGQuXG4vLyBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UsIHNlZSBMSUNFTlNFLlxuXG5pbXBvcnQgeyBwaWNrLCB0b1BhaXJzIH0gZnJvbSBcImxvZGFzaFwiO1xuaW1wb3J0ICogYXMgc3RyZWFtIGZyb20gXCJzdHJlYW1cIjtcbmltcG9ydCAqIGFzIFByb21pc2UgZnJvbSBcImJsdWViaXJkXCI7XG5pbXBvcnQgKiBhcyBzYXggZnJvbSBcInNheFwiO1xuXG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3htbC9Db250ZXh0XCI7XG5pbXBvcnQgeyBOYW1lc3BhY2UgfSBmcm9tIFwiLi4veG1sL05hbWVzcGFjZVwiO1xuaW1wb3J0IHsgUnVsZSwgUnVsZUNsYXNzLCBIYW5kbGVySW5zdGFuY2UgfSBmcm9tIFwiLi9SdWxlXCI7XG5pbXBvcnQgeyBNZW1iZXJSZWYgfSBmcm9tIFwiLi4veG1sL01lbWJlclJlZlwiO1xuaW1wb3J0IHsgU3RhdGUgfSBmcm9tIFwiLi9TdGF0ZVwiO1xuaW1wb3J0IHsgZGVmYXVsdENvbnRleHQgfSBmcm9tIFwiLi4vaW1wb3J0ZXIvSlNcIjtcbmltcG9ydCB7IHBhcnNlLCBJdGVtUGFyc2VkIH0gZnJvbSBcIi4uL3NwaW5vZmZzL3hwYXRoXCI7XG5cbmV4cG9ydCB0eXBlIEl0ZW1QYXJzZWRLZXkgPSBrZXlvZiBJdGVtUGFyc2VkO1xuZXhwb3J0IHR5cGUgSXRlbVBhcnNlZFZhbHVlID0gSXRlbVBhcnNlZFtJdGVtUGFyc2VkS2V5XTtcblxuLy8gVE9ETyBjYW4gdGhpcyB0eXBlIGRlZmluaXRpb24gYmUgaW1wcm92ZWQ/XG4vKlxue1xuXHR4cGF0aEVsTWF0Y2hlcihvYmopOiB7XG4gXHQgIF9iZWZvcmU6IEZ1bmN0aW9uLFxuIFx0ICBfYWZ0ZXI6IEZ1bmN0aW9uLFxuXHRcdHhwYXRoRWxNYXRjaGVyKG9iaik6IHtcblx0XHRcdF9iZWZvcmU6IEZ1bmN0aW9uLFxuXHRcdFx0X2FmdGVyOiBGdW5jdGlvbixcblx0XHR9KE1hcCksXG5cdH0oTWFwKVxufShNYXApXG4vLyovXG5leHBvcnQgdHlwZSBBdHRhY2htZW50TWV0aG9kTmFtZXMgPSBcIl9hZnRlclwiIHwgXCJfYmVmb3JlXCI7XG5leHBvcnQgdHlwZSBCVHJlZUZpbmFsID0gTWFwPEF0dGFjaG1lbnRNZXRob2ROYW1lcywgRnVuY3Rpb24+O1xuZXhwb3J0IHR5cGUgQlRyZWVJbnRlcm1lZGlhdGU8VD4gPSBNYXA8SXRlbVBhcnNlZCwgVCB8IEJUcmVlRmluYWw+O1xuZXhwb3J0IHR5cGUgQlRyZWU8VD4gPSBCVHJlZUludGVybWVkaWF0ZTxUPiAmIEJUcmVlRmluYWw7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3htbERhdGUgZXh0ZW5kcyBEYXRlIHtcbiAgY3htbFRpbWV6b25lT2Zmc2V0OiBudW1iZXI7XG59XG5cbmZ1bmN0aW9uIGZpbmRJbk1hcEl0ZXI8VD4oXG4gIC8vIFRPRE8gd2h5IGNhbid0IEkgbWFyayB0aGlzIGFzIEJUcmVlPFQ+IGluc3RlYWQgb2YgYW55P1xuICBtYXBJdGVyOiBJdGVyYXRvcjxbSXRlbVBhcnNlZCwgYW55XT4sXG4gIGNvbXBhcmU6ICh4OiBJdGVtUGFyc2VkKSA9PiBib29sZWFuXG4pOiBCVHJlZTxUPiB7XG4gIGNvbnN0IHsgdmFsdWUsIGRvbmUgfSA9IG1hcEl0ZXIubmV4dCgpO1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IFtpdGVtUGFyc2VkLCBjaGlsZE1hcF0gPSB2YWx1ZTtcbiAgaWYgKCFjb21wYXJlKGl0ZW1QYXJzZWQpKSB7XG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcmV0dXJuIGZpbmRJbk1hcEl0ZXI8VD4obWFwSXRlciwgY29tcGFyZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNoaWxkTWFwO1xuICB9XG59XG5cbmV4cG9ydCB0eXBlIE5vbkJpbmFyeU9wVG9SaWdodHMgPSB7IFtLIGluIFwiPVwiIHwgXCIhPVwiXTogc3RyaW5nIHwgbnVtYmVyIH07XG5leHBvcnQgdHlwZSBCaW5hcnlPcFRvUmlnaHRzID0ge1xuICBbSyBpbiBcIiZsdDtcIiB8IFwiJmx0Oz1cIiB8IFwiJmd0O1wiIHwgXCI+XCIgfCBcIiZndDs9XCIgfCBcIj49XCJdOiBudW1iZXJcbn07XG4vLyBUT0RPIGxvb2sgYXQgbW92aW5nIHNvbWUgb2YgdGhlc2UgdHlwZSBkZWZpbml0aW9ucyBpbnRvIHhwYXRoLnRzXG5leHBvcnQgdHlwZSBPcFRvUmlnaHRzID0gTm9uQmluYXJ5T3BUb1JpZ2h0cyAmIEJpbmFyeU9wVG9SaWdodHM7XG5leHBvcnQgdHlwZSBPcEhhbmRsZXJJbnB1dEdlbmVyaWM8VCwgSyBleHRlbmRzIGtleW9mIFQ+ID0ge1xuICBsZWZ0OiBzdHJpbmc7XG4gIG9wOiBLO1xuICByaWdodDogVFtLXTtcbn07XG5leHBvcnQgdHlwZSBPcEhhbmRsZXJJbnB1dCA9IE9wSGFuZGxlcklucHV0R2VuZXJpYzxcbiAgT3BUb1JpZ2h0cyxcbiAga2V5b2YgT3BUb1JpZ2h0c1xuPjtcbmV4cG9ydCB0eXBlIE9wSGFuZGxlcnNHZW5lcmljPFQsIEsgZXh0ZW5kcyBrZXlvZiBUPiA9IHtcbiAgW0s6IHN0cmluZ106IChpdGVtOiBIYW5kbGVySW5zdGFuY2UsIGxlZnQ6IHN0cmluZywgcmlnaHQ6IFRbS10pID0+IGJvb2xlYW47XG59O1xuZXhwb3J0IHR5cGUgT3BIYW5kbGVycyA9IE9wSGFuZGxlcnNHZW5lcmljPE9wVG9SaWdodHMsIGtleW9mIE9wVG9SaWdodHM+O1xuXG5sZXQgb3BIYW5kbGVycyA9IHtcbiAgLy8gZXF1YWxcbiAgXCI9XCI6IGZ1bmN0aW9uKGl0ZW0sIGxlZnQsIHJpZ2h0KSB7XG4gICAgcmV0dXJuIGl0ZW1bbGVmdF0gPT09IHJpZ2h0O1xuICB9LFxuICAvLyBub3QgZXF1YWxcbiAgXCIhPVwiOiBmdW5jdGlvbihpdGVtLCBsZWZ0LCByaWdodCkge1xuICAgIHJldHVybiBpdGVtW2xlZnRdICE9PSByaWdodDtcbiAgfSxcbiAgLy8gbGVzcyB0aGFuXG4gIFwiJmx0O1wiOiBmdW5jdGlvbihpdGVtLCBsZWZ0LCByaWdodCkge1xuICAgIHJldHVybiBpdGVtW2xlZnRdIDwgcmlnaHQ7XG4gIH0sXG4gIC8vIGxlc3MgdGhhbiBvciBlcXVhbCB0b1xuICBcIiZsdDs9XCI6IGZ1bmN0aW9uKGl0ZW0sIGxlZnQsIHJpZ2h0KSB7XG4gICAgcmV0dXJuIGl0ZW1bbGVmdF0gPCByaWdodDtcbiAgfSxcbiAgLy8gZ3JlYXRlciB0aGFuXG4gIFwiJmd0O1wiOiBmdW5jdGlvbihpdGVtLCBsZWZ0LCByaWdodCkge1xuICAgIHJldHVybiBpdGVtW2xlZnRdID4gcmlnaHQ7XG4gIH0sXG4gIC8vIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0b1xuICBcIiZndDs9XCI6IGZ1bmN0aW9uKGl0ZW0sIGxlZnQsIHJpZ2h0KSB7XG4gICAgcmV0dXJuIGl0ZW1bbGVmdF0gPiByaWdodDtcbiAgfVxufSBhcyBPcEhhbmRsZXJzO1xuXG5vcEhhbmRsZXJzW1wiPlwiXSA9IG9wSGFuZGxlcnNbXCImZ3Q7XCJdO1xub3BIYW5kbGVyc1tcIj49XCJdID0gb3BIYW5kbGVyc1tcIiZndDs9XCJdO1xuXG4vKlxub3BIYW5kbGVyc1tcIiZndDtcIl0oe30gYXMgSGFuZGxlckluc3RhbmNlLCBcIkNlbnRlclhcIiwgMik7XG5vcEhhbmRsZXJzW1wiJmd0O1wiXSh7fSBhcyBIYW5kbGVySW5zdGFuY2UsIFwiQ2VudGVyWFwiLCBcImJcIik7XG5vcEhhbmRsZXJzW1wiJmd0O1wiXSh7fSBhcyBIYW5kbGVySW5zdGFuY2UsIFwiYVwiLCBcImJcIik7XG5vcEhhbmRsZXJzW1wiPlwiXSh7fSBhcyBIYW5kbGVySW5zdGFuY2UsIFwiQ2VudGVyWFwiLCAyKTtcbm9wSGFuZGxlcnNbXCI+XCJdKHt9IGFzIEhhbmRsZXJJbnN0YW5jZSwgXCJhXCIsIDIpO1xub3BIYW5kbGVyc1tcIj49XCJdKHt9IGFzIEhhbmRsZXJJbnN0YW5jZSwgMSwgMik7XG5vcEhhbmRsZXJzW1wiPj1cIl0oe30gYXMgSGFuZGxlckluc3RhbmNlLCBcImFcIiwgMik7XG5vcEhhbmRsZXJzW1wiPVwiXSh7fSBhcyBIYW5kbGVySW5zdGFuY2UsIFwiYVwiLCAyKTtcbi8vKi9cblxuZnVuY3Rpb24gZmluZEVudHJ5PFQ+KFxuICBtYXBJdGVyOiBJdGVyYXRvcjxbSXRlbVBhcnNlZCwgQlRyZWU8VD5dPixcbiAgY29tcGFyZTogKHg6IEl0ZW1QYXJzZWQpID0+IGJvb2xlYW5cbik6IFtCVHJlZTxUPiwgSXRlbVBhcnNlZF0ge1xuICBjb25zdCB7IHZhbHVlLCBkb25lIH0gPSBtYXBJdGVyLm5leHQoKTtcbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBbaXRlbVBhcnNlZCwgY2hpbGRNYXBdID0gdmFsdWU7XG4gIGlmICghY29tcGFyZShpdGVtUGFyc2VkKSkge1xuICAgIGlmIChkb25lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJldHVybiBmaW5kRW50cnkobWFwSXRlciwgY29tcGFyZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFtjaGlsZE1hcCwgaXRlbVBhcnNlZF07XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0QXR0YWNobWVudE1ldGhvZDxUPihcbiAgc3RhdGU6IFN0YXRlLFxuICBiVHJlZTogQlRyZWU8VD4sXG4gIGF0dGFjaG1lbnRNZXRob2ROYW1lOiBBdHRhY2htZW50TWV0aG9kTmFtZXNcbik6IEZ1bmN0aW9uIHtcbiAgY29uc3QgbWVtYmVyID1cbiAgICAoISFzdGF0ZS5tZW1iZXJSZWYgJiYgc3RhdGUubWVtYmVyUmVmLm1lbWJlcikgfHxcbiAgICAoe30gYXMgdHlwZW9mIE1lbWJlclJlZi5wcm90b3R5cGUubWVtYmVyKTtcbiAgLy8gVE9ETyBzaG91bGQgd2UgdXNlIHN0YXRlLm1lbWJlclJlZi5zYWZlTmFtZSBoZXJlP1xuICBjb25zdCBtZW1iZXJOYW1lID0gISFtZW1iZXIgJiYgbWVtYmVyLm5hbWU7XG4gIGNvbnN0IG1lbWJlck5hbWVzcGFjZSA9XG4gICAgISFtZW1iZXIgJiYgISFtZW1iZXIubmFtZXNwYWNlICYmIG1lbWJlci5uYW1lc3BhY2UubmFtZTtcblxuICBpZiAoIW1lbWJlck5hbWUpIHtcbiAgICBjb25zdCBhdHRhY2htZW50TWV0aG9kID0gYlRyZWUuZ2V0KGF0dGFjaG1lbnRNZXRob2ROYW1lKTtcbiAgICBpZiAoYXR0YWNobWVudE1ldGhvZCkge1xuICAgICAgcmV0dXJuIGF0dGFjaG1lbnRNZXRob2Q7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYGdldEF0dGFjaG1lbnRNZXRob2QgZmFpbGVkIHRvIGZpbmQgJHthdHRhY2htZW50TWV0aG9kTmFtZX0gZnVuY3Rpb25gXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBjb25zdCBpdGVtID0gc3RhdGUuaXRlbSB8fCAoe30gYXMgSGFuZGxlckluc3RhbmNlKTtcblxuICAvKnsgbGVmdDogc3RyaW5nOyBvcDoga2V5b2YgTm9uQmluYXJ5T3BIYW5kbGVyczsgcmlnaHQ6IHN0cmluZyB9XG4gICAgICAgICAgICB7IGxlZnQ6IG51bWJlcjsgb3A6IGtleW9mIEJpbmFyeU9wSGFuZGxlcnM7IHJpZ2h0OiBudW1iZXIgfVxuICAgICAgICAgICAgfCB7XG4gICAgICAgICAgICAgICAgbGVmdDogc3RyaW5nIHwgbnVtYmVyO1xuICAgICAgICAgICAgICAgIG9wOiBrZXlvZiBOb25CaW5hcnlPcEhhbmRsZXJzO1xuICAgICAgICAgICAgICAgIHJpZ2h0OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgICAgICAgICAgIH1cblx0XHRcdFx0XHRcdFx0Ly8qL1xuXG4gIGNvbnN0IHZhbHVlID0gZmluZEluTWFwSXRlcihiVHJlZS5lbnRyaWVzKCksIGZ1bmN0aW9uKHtcbiAgICBheGlzLFxuICAgIG5hbWVzcGFjZSxcbiAgICBuYW1lLFxuICAgIHByZWRpY2F0ZXMsXG4gICAgYXR0cmlidXRlXG4gIH06IEl0ZW1QYXJzZWQpIHtcbiAgICByZXR1cm4gKFxuICAgICAgW1wiXCIsIG1lbWJlck5hbWVzcGFjZV0uaW5kZXhPZihuYW1lc3BhY2UpID4gLTEgJiZcbiAgICAgIG5hbWUgPT09IG1lbWJlck5hbWUgJiZcbiAgICAgICghcHJlZGljYXRlcyB8fFxuICAgICAgICBwcmVkaWNhdGVzLnJlZHVjZShmdW5jdGlvbihhY2MsIHsgbGVmdCwgb3AsIHJpZ2h0IH06IE9wSGFuZGxlcklucHV0KSB7XG4gICAgICAgICAgcmV0dXJuIGFjYyAmJiBvcEhhbmRsZXJzW29wXShpdGVtLCBsZWZ0LCByaWdodCk7XG4gICAgICAgIH0sIHRydWUpKVxuICAgICk7XG4gIH0pO1xuXG4gIGlmICghdmFsdWUpIHtcbiAgICAvLyBOT1RFOiB3ZSBjYW4gZW5kIHVwIGhlcmUgYmVjYXVzZSB0aGVyZSBpcyBubyBkaXJlY3QgY29ubmVjdGlvbiBiZXR3ZWVuXG4gICAgLy8gYSBQYXJzZXIgaW5zdGFuY2UncyBhdHRhY2ggYW5kIF9wYXJzZSBtZXRob2RzLiBUaGV5IGFjdHVhbGx5IGp1c3RcbiAgICAvLyBjb25uZWN0IHZpYSB0aGUgcnVsZS5oYW5kbGVyIHByb3RvdHlwZS4gU28gaXQncyBwb3NzaWJsZSBmb3Igb25lXG4gICAgLy8gYXR0YWNobWVudCBtZXRob2QgdG8gc2V0IHNvbWV0aGluZyBvbiB0aGUgcnVsZS5oYW5kbGVyIHByb3RvdHlwZSwgbWVhbmluZyBpdFxuICAgIC8vIGFwcGVhcnMgdG8gZXhpc3Qgd2hlbiB3ZSBsb29rIGF0IGl0ZW0uX2JlZm9yZSBvciBpdGVtLl9hZnRlciBpbiBfcGFyc2VyLFxuICAgIC8vIGJ1dCBpdCBkb2Vzbid0IGFjdHVhbGx5IGV4aXN0IGZvciB0aGlzIHhwYXRoIHdoZW4gd2UgbWF0Y2ggdGhlXG4gICAgLy8gc3RhdGUgYW5kIGJUcmVlLCBsZXZlbCBieSBsZXZlbCwgdXAgdG8gdGhlIHBvaW50IHdoZXJlIHRoZXJlIHNob3VsZCBiZVxuICAgIC8vIGEgX2JlZm9yZSBvciBfYWZ0ZXIuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgcGFyZW50ID0gc3RhdGUucGFyZW50O1xuICBpZiAoISFwYXJlbnQpIHtcbiAgICByZXR1cm4gZ2V0QXR0YWNobWVudE1ldGhvZChwYXJlbnQsIHZhbHVlLCBhdHRhY2htZW50TWV0aG9kTmFtZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHZhbHVlLmdldChhdHRhY2htZW50TWV0aG9kTmFtZSk7XG4gIH1cbn1cblxuY29uc3QgY29udmVydGVyVGJsOiB7IFt0eXBlOiBzdHJpbmddOiAoaXRlbTogc3RyaW5nKSA9PiBhbnkgfSA9IHtcbiAgRGF0ZTogKGl0ZW06IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IGRhdGVQYXJ0cyA9IGl0ZW0ubWF0Y2goXG4gICAgICAvKFswLTldKyktKFswLTldKyktKFswLTldKykoPzpUKFswLTldKyk6KFswLTldKyk6KFswLTldKykoXFwuWzAtOV0rKT8pPyg/Olp8KFsrLV1bMC05XSspOihbMC05XSspKT8vXG4gICAgKTtcblxuICAgIGlmICghZGF0ZVBhcnRzKSByZXR1cm4gbnVsbDtcblxuICAgIGxldCBvZmZzZXRNaW51dGVzID0gKyhkYXRlUGFydHNbOV0gfHwgXCIwXCIpO1xuICAgIGxldCBvZmZzZXQgPSArKGRhdGVQYXJ0c1s4XSB8fCBcIjBcIikgKiA2MDtcblxuICAgIGlmIChvZmZzZXQgPCAwKSBvZmZzZXRNaW51dGVzID0gLW9mZnNldE1pbnV0ZXM7XG5cbiAgICBvZmZzZXQgKz0gb2Zmc2V0TWludXRlcztcblxuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShcbiAgICAgICtkYXRlUGFydHNbMV0sXG4gICAgICArZGF0ZVBhcnRzWzJdIC0gMSxcbiAgICAgICtkYXRlUGFydHNbM10sXG4gICAgICArKGRhdGVQYXJ0c1s0XSB8fCBcIjBcIiksXG4gICAgICArKGRhdGVQYXJ0c1s1XSB8fCBcIjBcIiksXG4gICAgICArKGRhdGVQYXJ0c1s2XSB8fCBcIjBcIiksXG4gICAgICArKGRhdGVQYXJ0c1s3XSB8fCBcIjBcIikgKiAxMDAwXG4gICAgKSBhcyBDeG1sRGF0ZTtcblxuICAgIGRhdGUuc2V0VGltZShkYXRlLmdldFRpbWUoKSAtIChvZmZzZXQgKyBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkpICogNjAwMDApO1xuICAgIGRhdGUuY3htbFRpbWV6b25lT2Zmc2V0ID0gb2Zmc2V0O1xuXG4gICAgcmV0dXJuIGRhdGU7XG4gIH0sXG4gIGJvb2xlYW46IChpdGVtOiBzdHJpbmcpID0+IGl0ZW0gPT0gXCJ0cnVlXCIsXG4gIHN0cmluZzogKGl0ZW06IHN0cmluZykgPT4gaXRlbSxcbiAgbnVtYmVyOiAoaXRlbTogc3RyaW5nKSA9PiAraXRlbVxufTtcblxuZnVuY3Rpb24gY29udmVydFByaW1pdGl2ZSh0ZXh0OiBzdHJpbmcsIHR5cGU6IFJ1bGUpIHtcbiAgY29uc3QgY29udmVydGVyID0gY29udmVydGVyVGJsW3R5cGUucHJpbWl0aXZlVHlwZV07XG5cbiAgaWYgKGNvbnZlcnRlcikge1xuICAgIGlmICh0eXBlLmlzTGlzdCkge1xuICAgICAgcmV0dXJuIHRleHRcbiAgICAgICAgLnRyaW0oKVxuICAgICAgICAuc3BsaXQoL1xccysvKVxuICAgICAgICAubWFwKGNvbnZlcnRlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb252ZXJ0ZXIodGV4dC50cmltKCkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgY2xhc3MgUGFyc2VyPFQ+IHtcbiAgeHBhdGhOYW1lc3BhY2VUYmw6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGNvbnN0cnVjdG9yKHhwYXRoTmFtZXNwYWNlVGJsOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0geyBcIlwiOiBcIlwiIH0pIHtcbiAgICAvLyBUT0RPIHRoZXJlIGlzIHByb2JhYmx5IGEgYmV0dGVyIHdheSB0byBkbyB0aGlzLlxuICAgIC8vIEl0IGFwcGVhcnMgdGhlIGNvbnRleHQgcGFyYW0gaW4gdGhlIHBhcnNlci5wYXJzZXJcbiAgICAvLyBtZXRob2QgbWF5IGhhdmUgYmUgaW50ZW5kZWQgZm9yIHRoZSBzYW1lIHB1cnBvc2UuXG4gICAgdGhpcy54cGF0aE5hbWVzcGFjZVRibCA9IHhwYXRoTmFtZXNwYWNlVGJsO1xuICB9XG4gIC8vIFRPRE8gd2h5IGRvIEkgbmVlZCB0byB1c2UgQlRyZWU8YW55PiBoZXJlP1xuICAvLyBJIHNob3VsZCBiZSBhYmxlIHRvIHVzZSBCVHJlZTxUPlxuICBiVHJlZTogQlRyZWU8YW55PiAmIEJUcmVlPFQ+ID0gbmV3IE1hcCgpO1xuICBhdHRhY2g8Q3VzdG9tSGFuZGxlciBleHRlbmRzIEhhbmRsZXJJbnN0YW5jZT4oXG4gICAgaGFuZGxlcjoge1xuICAgICAgbmV3ICgpOiBDdXN0b21IYW5kbGVyO1xuICAgIH0sXG4gICAgeHBhdGg6IHN0cmluZ1xuICApIHtcbiAgICBjb25zdCB7IHhwYXRoTmFtZXNwYWNlVGJsIH0gPSB0aGlzO1xuICAgIGNvbnN0IHByb3RvID0gaGFuZGxlci5wcm90b3R5cGUgYXMgQ3VzdG9tSGFuZGxlcjtcbiAgICBjb25zdCByZWFsSGFuZGxlciA9IChoYW5kbGVyIGFzIFJ1bGVDbGFzcykucnVsZS5oYW5kbGVyO1xuICAgIGNvbnN0IHJlYWxQcm90byA9IHJlYWxIYW5kbGVyLnByb3RvdHlwZSBhcyBDdXN0b21IYW5kbGVyO1xuXG4gICAgdHlwZSBDdXN0b21IYW5kbGVyS2V5ID0ga2V5b2YgQ3VzdG9tSGFuZGxlcjtcbiAgICBjb25zdCBjdXN0b21IYW5kbGVyS2V5czogQ3VzdG9tSGFuZGxlcktleVtdID0gT2JqZWN0LmtleXMocHJvdG8pO1xuXG4gICAgZm9yIChjb25zdCBjdXN0b21IYW5kbGVyS2V5IG9mIGN1c3RvbUhhbmRsZXJLZXlzKSB7XG4gICAgICBjb25zdCB0aW1lQmFzZWRLZXlzOiBDdXN0b21IYW5kbGVyS2V5W10gPSBbXCJfYmVmb3JlXCIsIFwiX2FmdGVyXCJdO1xuICAgICAgaWYgKHRpbWVCYXNlZEtleXMuaW5kZXhPZihjdXN0b21IYW5kbGVyS2V5KSA9PT0gLTEpIHtcbiAgICAgICAgcmVhbFByb3RvW2N1c3RvbUhhbmRsZXJLZXldID0gcHJvdG9bY3VzdG9tSGFuZGxlcktleV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETyBpcyB0aGlzIHJlYWxseSB0aGUgYmVzdCB3YXkgdG8gZG8gdGhpcz9cbiAgICBjb25zdCB7IF9iZWZvcmUsIF9hZnRlciB9ID0gcHJvdG87XG4gICAgaWYgKHhwYXRoKSB7XG4gICAgICBpZiAoX2JlZm9yZSB8fCBfYWZ0ZXIpIHtcbiAgICAgICAgLy8gVE9ETyB3ZSBhcmUgbXV0YXRpbmcgcmV2ZXJzZWRYUGF0aEVsTWF0Y2hlcnMgZm9yIHhwYXRoXG4gICAgICAgIC8vIGV4cHJlc3Npb25zIHdpdGggYXR0cmlidXRlcywgc3VjaCBhc1xuICAgICAgICAvLyBcIi9QYXRod2F5L0BHcmFwaElkXCJcbiAgICAgICAgLy8gb3JcbiAgICAgICAgLy8gXCIvUGF0aHdheS9AKlwiXG4gICAgICAgIC8vIGJlY2F1c2Ugd2UgbmVlZCB0byBmaXJzdCBqdXN0IG1hdGNoIHRoZSBlbGVtZW50KHMpLCBhbmRcbiAgICAgICAgLy8gdGhlbiBhZnRlcndhcmRzIG1hdGNoIGFueSBhdHRyaWJ1dGUuXG4gICAgICAgIGxldCByZXZlcnNlZFhQYXRoRWxNYXRjaGVycyA9IHBhcnNlKHhwYXRoLCB4cGF0aE5hbWVzcGFjZVRibCkucmV2ZXJzZSgpO1xuICAgICAgICBsZXQgeHBhdGhBdHRyTWF0Y2hlcjogeyBhdHRyaWJ1dGU6IHN0cmluZyB9O1xuICAgICAgICBpZiAocmV2ZXJzZWRYUGF0aEVsTWF0Y2hlcnNbMF0uYXR0cmlidXRlICE9PSBudWxsKSB7XG4gICAgICAgICAgeHBhdGhBdHRyTWF0Y2hlciA9IHJldmVyc2VkWFBhdGhFbE1hdGNoZXJzLnNoaWZ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZmluYWxJdGVtID0gcmV2ZXJzZWRYUGF0aEVsTWF0Y2hlcnMucmVkdWNlKGZ1bmN0aW9uKFxuICAgICAgICAgIHBhcmVudE1hcCxcbiAgICAgICAgICB4cGF0aEVsTWF0Y2hlcjogSXRlbVBhcnNlZFxuICAgICAgICApIHtcbiAgICAgICAgICBjb25zdCB4cGF0aEVsTWF0Y2hlclBhaXJzID0gdG9QYWlycyh4cGF0aEVsTWF0Y2hlcik7XG4gICAgICAgICAgbGV0IFtjdXJyZW50TWFwLCBjdXJyZW50SXRlbVBhcnNlZF06IFtcbiAgICAgICAgICAgIEJUcmVlPFQ+LFxuICAgICAgICAgICAgSXRlbVBhcnNlZFxuICAgICAgICAgIF0gPSBmaW5kRW50cnkocGFyZW50TWFwLmVudHJpZXMoKSwgZnVuY3Rpb24oY2FuZGlkYXRlSXRlbVBhcnNlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHhwYXRoRWxNYXRjaGVyUGFpcnMucmVkdWNlKGZ1bmN0aW9uKFxuICAgICAgICAgICAgICBpc1J1bm5pbmdNYXRjaDogYm9vbGVhbixcbiAgICAgICAgICAgICAgW3hwYXRoRWxNYXRjaGVyS2V5LCB4cGF0aEVsTWF0Y2hlclZhbHVlXTogW1xuICAgICAgICAgICAgICAgIEl0ZW1QYXJzZWRLZXksXG4gICAgICAgICAgICAgICAgSXRlbVBhcnNlZFZhbHVlXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIGlzUnVubmluZ01hdGNoICYmXG4gICAgICAgICAgICAgICAgY2FuZGlkYXRlSXRlbVBhcnNlZFt4cGF0aEVsTWF0Y2hlcktleV0gPT09IHhwYXRoRWxNYXRjaGVyVmFsdWVcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0cnVlKTtcbiAgICAgICAgICB9KSB8fCBbbmV3IE1hcCgpLCB4cGF0aEVsTWF0Y2hlcl07XG4gICAgICAgICAgcGFyZW50TWFwLnNldChjdXJyZW50SXRlbVBhcnNlZCwgY3VycmVudE1hcCk7XG4gICAgICAgICAgcmV0dXJuIGN1cnJlbnRNYXA7XG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMuYlRyZWUpO1xuXG4gICAgICAgIGlmIChfYmVmb3JlKSB7XG4gICAgICAgICAgZmluYWxJdGVtLnNldChcbiAgICAgICAgICAgIFwiX2JlZm9yZVwiLFxuICAgICAgICAgICAgIXhwYXRoQXR0ck1hdGNoZXIgfHwgeHBhdGhBdHRyTWF0Y2hlci5hdHRyaWJ1dGUgPT09IFwiKlwiXG4gICAgICAgICAgICAgID8gX2JlZm9yZVxuICAgICAgICAgICAgICA6IGZ1bmN0aW9uKHRoaXM6IE1hcDxzdHJpbmcsIHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBcIlwiPikge1xuICAgICAgICAgICAgICAgICAgY29uc3QgcGlja2VkID0gcGljayh0aGlzLCB4cGF0aEF0dHJNYXRjaGVyLmF0dHJpYnV0ZSk7XG4gICAgICAgICAgICAgICAgICBfYmVmb3JlLmNhbGwocGlja2VkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoX2FmdGVyKSB7XG4gICAgICAgICAgZmluYWxJdGVtLnNldChcIl9hZnRlclwiLCBfYWZ0ZXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmVhbEhhbmRsZXIuX2N1c3RvbSA9IHRydWU7XG4gIH1cblxuICBwYXJzZTxPdXRwdXQgZXh0ZW5kcyBIYW5kbGVySW5zdGFuY2U+KFxuICAgIHN0cmVhbTogc3RyaW5nIHwgc3RyZWFtLlJlYWRhYmxlIHwgTm9kZUpTLlJlYWRhYmxlU3RyZWFtLFxuICAgIG91dHB1dDogT3V0cHV0LFxuICAgIGN