@mml-io/networked-dom-web-runner 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +13 -39
- package/build/index.js.map +2 -2
- package/package.json +9 -8
package/build/index.js
CHANGED
|
@@ -1,35 +1,8 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
1
|
// src/index.ts
|
|
21
|
-
|
|
22
|
-
__export(src_exports, {
|
|
23
|
-
FakeWebsocket: () => FakeWebsocket,
|
|
24
|
-
IframeObservableDOMFactory: () => IframeObservableDOMFactory,
|
|
25
|
-
NetworkedDOMWebRunnerClient: () => NetworkedDOMWebRunnerClient,
|
|
26
|
-
RunnerIframe: () => RunnerIframe
|
|
27
|
-
});
|
|
28
|
-
module.exports = __toCommonJS(src_exports);
|
|
29
|
-
__reExport(src_exports, require("@mml-io/networked-dom-document"), module.exports);
|
|
2
|
+
export * from "@mml-io/networked-dom-document";
|
|
30
3
|
|
|
31
4
|
// runner-iframe-js-text-namespace:/home/runner/work/mml/mml/packages/networked-dom-web-runner/networked-dom-web-runner-iframe/build/index.js
|
|
32
|
-
var build_default = 'var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === "object" || typeof from === "function") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. "__esModule" has not been set), then set\n // "default" to the CommonJS "module.exports" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,\n mod\n));\n\n// ../../observable-dom-common/build/index.js\nvar require_build = __commonJS({\n "../../observable-dom-common/build/index.js"(exports, module2) {\n var __defProp2 = Object.defineProperty;\n var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;\n var __getOwnPropNames2 = Object.getOwnPropertyNames;\n var __hasOwnProp2 = Object.prototype.hasOwnProperty;\n var __export = (target, all) => {\n for (var name in all)\n __defProp2(target, name, { get: all[name], enumerable: true });\n };\n var __copyProps2 = (to, from, except, desc) => {\n if (from && typeof from === "object" || typeof from === "function") {\n for (let key of __getOwnPropNames2(from))\n if (!__hasOwnProp2.call(to, key) && key !== except)\n __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });\n }\n return to;\n };\n var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);\n var src_exports = {};\n __export(src_exports, {\n ADD_CONNECTED_USER_ID_MESSAGE_TYPE: () => ADD_CONNECTED_USER_ID_MESSAGE_TYPE2,\n DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE: () => DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2,\n DOM_MESSAGE_TYPE: () => DOM_MESSAGE_TYPE2,\n REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE: () => REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2,\n applyMessageToObservableDOMInstance: () => applyMessageToObservableDOMInstance,\n observableDOMInterfaceToMessageSender: () => observableDOMInterfaceToMessageSender\n });\n module2.exports = __toCommonJS(src_exports);\n var ADD_CONNECTED_USER_ID_MESSAGE_TYPE2 = "addConnectedUserId";\n var REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2 = "removeConnectedUserId";\n var DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2 = "dispatchRemoteEventFromConnectionId";\n var DOM_MESSAGE_TYPE2 = "dom";\n function applyMessageToObservableDOMInstance(message, instance) {\n if (message.type === ADD_CONNECTED_USER_ID_MESSAGE_TYPE2) {\n instance.addConnectedUserId(message.connectionId);\n } else if (message.type === REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2) {\n instance.removeConnectedUserId(message.connectionId);\n } else if (message.type === DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2) {\n instance.dispatchRemoteEventFromConnectionId(message.connectionId, message.event);\n } else {\n console.error("Unknown message type", message);\n }\n }\n function observableDOMInterfaceToMessageSender(sender, dispose) {\n const remoteObservableDOM = {\n addConnectedUserId(connectionId) {\n sender({\n type: ADD_CONNECTED_USER_ID_MESSAGE_TYPE2,\n connectionId\n });\n },\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n sender({\n type: DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2,\n connectionId,\n event: remoteEvent\n });\n },\n dispose() {\n dispose();\n },\n removeConnectedUserId(connectionId) {\n sender({\n type: REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2,\n connectionId\n });\n }\n };\n return remoteObservableDOM;\n }\n }\n});\n\n// ../../observable-dom/src/utils.ts\nfunction virtualDOMElementToStatic(el) {\n return {\n nodeId: el.nodeId,\n tag: el.tag,\n attributes: el.attributes,\n childNodes: el.childNodes.map((child) => virtualDOMElementToStatic(child)),\n textContent: el.textContent\n };\n}\n\n// ../../observable-dom/src/ObservableDOM.ts\nvar ObservableDOM = class {\n constructor(observableDOMParameters, callback, runnerFactory) {\n this.nodeToNodeId = /* @__PURE__ */ new Map();\n this.nodeIdToNode = /* @__PURE__ */ new Map();\n this.realElementToVirtualElement = /* @__PURE__ */ new Map();\n this.ignoreTextNodes = true;\n this.nextNodeId = 1;\n this.htmlPath = observableDOMParameters.htmlPath;\n this.ignoreTextNodes = observableDOMParameters.ignoreTextNodes;\n this.callback = callback;\n this.documentTimeIntervalTimer = setInterval(() => {\n this.callback(\n {\n documentTime: this.getDocumentTime()\n },\n this\n );\n }, observableDOMParameters.pingIntervalMilliseconds || 5e3);\n this.domRunner = runnerFactory(\n observableDOMParameters.htmlPath,\n observableDOMParameters.htmlContents,\n observableDOMParameters.params,\n (domRunnerMessage) => {\n if (domRunnerMessage.loaded) {\n this.createVirtualDOMElementWithChildren(\n this.domRunner.getDocument(),\n null\n );\n const snapshot = virtualDOMElementToStatic(\n this.getVirtualDOMElementForRealElementOrThrow(\n this.domRunner.getDocument()\n )\n );\n this.callback(\n {\n snapshot,\n documentTime: this.getDocumentTime()\n },\n this\n );\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n this.callback(\n {\n logMessage: domRunnerMessage.logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n }\n );\n }\n addConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent("connected", {\n detail: { connectionId }\n })\n );\n }\n removeConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent("disconnected", {\n detail: { connectionId }\n })\n );\n }\n processModificationList(mutationList) {\n const documentEl = this.domRunner.getDocument();\n const documentVirtualDOMElement = this.realElementToVirtualElement.get(documentEl);\n if (!documentVirtualDOMElement) {\n throw new Error(`document not created in processModificationList`);\n }\n if (mutationList.length > 1) {\n }\n for (const mutation of mutationList) {\n if (this.isIgnoredElement(mutation.target)) {\n continue;\n }\n if (mutation.type === "attributes" && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.isIgnoredAttribute(mutation.target, mutation.attributeName)) {\n continue;\n }\n this.addKnownNodesInMutation(mutation);\n const firstNonIgnoredPreviousSibling = mutation.previousSibling ? this.getFirstNonIgnoredPreviousSibling(mutation.previousSibling) : null;\n const targetElement = this.getVirtualDOMElementForRealElementOrThrow(\n mutation.target\n );\n const addedNodes = [];\n for (const node of mutation.addedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n addedNodes.push(virtualDOMElementToStatic(virtualDOMElement));\n }\n const removedNodeIds = [];\n for (const node of mutation.removedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n removedNodeIds.push(virtualDOMElement.nodeId);\n }\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: firstNonIgnoredPreviousSibling !== null ? this.getVirtualDOMElementForRealElementOrThrow(firstNonIgnoredPreviousSibling).nodeId : null,\n attribute: mutation.attributeName ? {\n attributeName: mutation.attributeName,\n value: mutation.target.getAttribute(mutation.attributeName)\n } : null\n };\n this.callback(\n {\n mutation: mutationRecord,\n documentTime: this.getDocumentTime()\n },\n this\n );\n this.removeKnownNodesInMutation(mutation);\n }\n }\n addKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error(\n "Unknown node in addKnownNodesInMutation:" + targetNode + "," + mutation.type\n );\n }\n if (mutation.type === "childList") {\n let previousSibling = mutation.previousSibling;\n let index = 0;\n while (previousSibling && this.isIgnoredElement(previousSibling)) {\n previousSibling = previousSibling.previousSibling;\n }\n if (previousSibling) {\n const previousSiblingElement = this.realElementToVirtualElement.get(\n previousSibling\n );\n if (!previousSiblingElement) {\n throw new Error("Unknown previous sibling");\n }\n index = virtualDOMElement.childNodes.indexOf(previousSiblingElement);\n if (index === -1) {\n throw new Error("Previous sibling is not currently a child of the parent element");\n }\n index += 1;\n }\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n virtualDOMElement\n );\n if (childVirtualDOMElement) {\n if (virtualDOMElement.childNodes.indexOf(childVirtualDOMElement) === -1) {\n virtualDOMElement.childNodes.splice(index, 0, childVirtualDOMElement);\n index++;\n }\n }\n });\n } else if (mutation.type === "attributes") {\n const attributeName = mutation.attributeName;\n if (this.isIgnoredAttribute(targetNode, attributeName)) {\n return;\n }\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete virtualDOMElement.attributes[attributeName];\n } else {\n virtualDOMElement.attributes[attributeName] = attributeValue;\n }\n } else if (mutation.type === "characterData") {\n virtualDOMElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n }\n removeKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error("Unknown node in mutation list:" + targetNode + ", " + mutation.type);\n }\n if (mutation.type === "childList") {\n for (const node of mutation.removedNodes) {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n continue;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n console.warn(this.htmlPath, "Unknown node in removeKnownNodesInMutation");\n continue;\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n const index = virtualDOMElement.childNodes.indexOf(childDOMElement);\n virtualDOMElement.childNodes.splice(index, 1);\n }\n }\n return;\n }\n }\n removeVirtualDOMElement(virtualDOMElement) {\n this.nodeIdToNode.delete(virtualDOMElement.nodeId);\n this.nodeToNodeId.delete(virtualDOMElement);\n this.realElementToVirtualElement.delete(virtualDOMElement.realElement);\n for (const child of virtualDOMElement.childNodes) {\n this.removeVirtualDOMElement(child);\n }\n }\n createVirtualDOMElementWithChildren(node, parent) {\n const virtualElement = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i];\n const childVirtualElement = this.createVirtualDOMElementWithChildren(\n child,\n virtualElement\n );\n if (childVirtualElement) {\n virtualElement.childNodes.push(childVirtualElement);\n }\n }\n }\n return virtualElement;\n }\n createVirtualDOMElement(node, parent) {\n if (this.isIgnoredElement(node)) {\n return null;\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n throw new Error("Node already has a virtual element: " + node.nodeName);\n }\n if (!node) {\n throw new Error("Cannot assign node id to null");\n }\n const attributes = {};\n if (node.attributes) {\n const asHTMLElement = node;\n for (const key of asHTMLElement.getAttributeNames()) {\n const value = asHTMLElement.getAttribute(key);\n if (value === null) {\n throw new Error("Null attribute value for key: " + key);\n }\n if (!this.isIgnoredAttribute(node, key)) {\n attributes[key] = value;\n }\n }\n }\n const nodeId = this.nextNodeId++;\n const virtualElement = {\n nodeId,\n tag: node.nodeName,\n attributes,\n childNodes: [],\n realElement: node,\n parent\n };\n if (node instanceof this.domRunner.getWindow().Text && node.textContent) {\n virtualElement.textContent = node.textContent;\n }\n this.nodeToNodeId.set(virtualElement, nodeId);\n this.nodeIdToNode.set(nodeId, virtualElement);\n this.realElementToVirtualElement.set(node, virtualElement);\n return virtualElement;\n }\n getFirstNonIgnoredPreviousSibling(node) {\n let currentNode = node;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n while (currentNode && currentNode.previousSibling) {\n currentNode = currentNode.previousSibling;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n }\n return null;\n }\n getVirtualDOMElementForRealElementOrThrow(realElement) {\n const virtualElement = this.realElementToVirtualElement.get(realElement);\n if (!virtualElement) {\n throw new Error(`Virtual element not found for real element`);\n }\n return virtualElement;\n }\n isIgnoredElement(node) {\n if (this.ignoreTextNodes && node instanceof this.domRunner.getWindow().Text) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().HTMLScriptElement) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().Comment) {\n return true;\n }\n return false;\n }\n isIgnoredAttribute(node, attributeName) {\n return attributeName.startsWith("on");\n }\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n const domNode = this.nodeIdToNode.get(remoteEvent.nodeId);\n if (!domNode) {\n console.error("Unknown node ID in remote event: " + remoteEvent.nodeId);\n return;\n }\n if (domNode instanceof this.domRunner.getWindow().Text) {\n console.warn("Cannot dispatch remote event to text node");\n return;\n }\n this.domRunner.dispatchRemoteEventFromConnectionId(\n connectionId,\n domNode.realElement,\n remoteEvent\n );\n }\n dispose() {\n clearInterval(this.documentTimeIntervalTimer);\n this.domRunner.dispose();\n }\n getDocumentTime() {\n return this.domRunner.getDocumentTime();\n }\n};\n\n// src/IframeWebRunner.ts\nvar import_observable_dom_common = __toESM(require_build());\n\n// src/WebBrowserDOMRunner.ts\nvar WebBrowserDOMRunnerFactory = (htmlPath, htmlContents, params, callback) => {\n return new WebBrowserDOMRunner(htmlPath, htmlContents, params, callback);\n};\nvar documentLoadTime = Date.now();\nvar WebBrowserDOMRunner = class {\n constructor(htmlPath, htmlContents, params, callback) {\n this.htmlPath = htmlPath;\n this.callback = callback;\n for (const level of ["error", "warn", "info", "log"]) {\n const defaultFn = window.console[level];\n window.console[level] = (...args2) => {\n callback({\n logMessage: {\n level,\n content: args2\n }\n });\n defaultFn(...args2);\n };\n }\n window.onerror = (message, source, line, column, error) => {\n callback({\n logMessage: {\n level: "system",\n content: [\n {\n message,\n type: error?.name,\n line,\n column\n }\n ]\n }\n });\n return false;\n };\n let didSendLoad = false;\n this.mutationObserver = new window.MutationObserver((mutationList) => {\n if (!document) {\n return;\n }\n if (!didSendLoad) {\n throw new Error("MutationObserver called before load");\n }\n this.callback({\n mutationList\n });\n });\n window.params = params;\n const finishLoad = () => {\n if (didSendLoad) {\n throw new Error("finishLoad called twice");\n }\n didSendLoad = true;\n this.callback({\n loaded: true\n });\n this.mutationObserver.observe(window.document, {\n attributes: true,\n childList: true,\n subtree: true,\n characterData: true\n });\n };\n if (document.body) {\n setTimeout(finishLoad, 0);\n } else {\n window.addEventListener("DOMContentLoaded", finishLoad);\n }\n }\n dispatchRemoteEventFromConnectionId(connectionId, realElement, remoteEvent) {\n const bubbles = remoteEvent.bubbles || false;\n const remoteEventObject = new CustomEvent(remoteEvent.name, {\n bubbles,\n detail: { ...remoteEvent.params, connectionId }\n });\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log("WebBrowserDOMRunner.dispose");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n if (document.timeline && document.timeline.currentTime) {\n return document.timeline.currentTime;\n }\n return Date.now() - documentLoadTime;\n }\n // TODO - resolve types (Window needs to expose classes such as CustomEvent as properties)\n getWindow() {\n return window;\n }\n};\n\n// src/IframeWebRunner.ts\nfunction setupIframeWebRunner(argsString) {\n const observableDOMParams = JSON.parse(atob(argsString));\n const sendMessageToHandler = (message) => {\n window.parent.postMessage(JSON.stringify(message), "*");\n };\n const observableDOM = new ObservableDOM(\n {\n ...observableDOMParams,\n htmlContents: ""\n // This must be empty as the contents are assumed to be provided by the srcdoc\n },\n (observableDOMMessage) => {\n sendMessageToHandler({\n type: import_observable_dom_common.DOM_MESSAGE_TYPE,\n message: observableDOMMessage\n });\n },\n WebBrowserDOMRunnerFactory\n );\n window.addEventListener("message", (e) => {\n const parsed = JSON.parse(e.data);\n switch (parsed.type) {\n case import_observable_dom_common.DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE:\n observableDOM.dispatchRemoteEventFromConnectionId(parsed.connectionId, parsed.event);\n break;\n case import_observable_dom_common.ADD_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.addConnectedUserId(parsed.connectionId);\n break;\n case import_observable_dom_common.REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.removeConnectedUserId(parsed.connectionId);\n break;\n default:\n console.error("Unknown message type", parsed);\n }\n });\n}\n\n// src/index.ts\nvar args = window.args;\nsetupIframeWebRunner(args);\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20tY29tbW9uL3NyYy9pbmRleC50cyIsICIuLi8uLi8uLi9vYnNlcnZhYmxlLWRvbS1jb21tb24vc3JjL21lc3NhZ2VzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy91dGlscy50cyIsICIuLi8uLi8uLi9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTS50cyIsICIuLi9zcmMvSWZyYW1lV2ViUnVubmVyLnRzIiwgIi4uL3NyYy9XZWJCcm93c2VyRE9NUnVubmVyLnRzIiwgIi4uL3NyYy9pbmRleC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0IHR5cGUgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcblxuZXhwb3J0ICogZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbWVzc2FnZXNcIjtcbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZURPTUludGVyZmFjZSwgT2JzZXJ2YWJsZURPTU1lc3NhZ2UgfSBmcm9tIFwiLi9PYnNlcnZhYmxlRE9NSW50ZXJmYWNlXCI7XG5cbmV4cG9ydCBjb25zdCBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFID0gXCJhZGRDb25uZWN0ZWRVc2VySWRcIjtcbmV4cG9ydCBjb25zdCBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFID0gXCJyZW1vdmVDb25uZWN0ZWRVc2VySWRcIjtcbmV4cG9ydCBjb25zdCBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSA9XG4gIFwiZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRcIjtcbmV4cG9ydCBjb25zdCBET01fTUVTU0FHRV9UWVBFID0gXCJkb21cIjtcblxuZXhwb3J0IHR5cGUgQWRkQ29ubmVjdGVkVXNlcklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgRGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xuICBldmVudDogUmVtb3RlRXZlbnQ7XG59O1xuXG5leHBvcnQgdHlwZSBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UgPVxuICB8IEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2VcbiAgfCBSZW1vdmVDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgRGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRNZXNzYWdlO1xuXG50eXBlIERPTU1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBET01fTUVTU0FHRV9UWVBFO1xuICBtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZTtcbn07XG5cbmV4cG9ydCB0eXBlIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID0gRE9NTWVzc2FnZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5TWVzc2FnZVRvT2JzZXJ2YWJsZURPTUluc3RhbmNlKFxuICBtZXNzYWdlOiBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG4gIGluc3RhbmNlOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuKSB7XG4gIGlmIChtZXNzYWdlLnR5cGUgPT09IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5hZGRDb25uZWN0ZWRVc2VySWQobWVzc2FnZS5jb25uZWN0aW9uSWQpO1xuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLnJlbW92ZUNvbm5lY3RlZFVzZXJJZChtZXNzYWdlLmNvbm5lY3Rpb25JZCk7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLmRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKG1lc3NhZ2UuY29ubmVjdGlvbklkLCBtZXNzYWdlLmV2ZW50KTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBtZXNzYWdlIHR5cGVcIiwgbWVzc2FnZSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9ic2VydmFibGVET01JbnRlcmZhY2VUb01lc3NhZ2VTZW5kZXIoXG4gIHNlbmRlcjogKG1lc3NhZ2U6IFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4gdm9pZCxcbiAgZGlzcG9zZTogKCkgPT4gdm9pZCxcbikge1xuICBjb25zdCByZW1vdGVPYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlID0ge1xuICAgIGFkZENvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChjb25uZWN0aW9uSWQ6IG51bWJlciwgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50KTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgICBldmVudDogcmVtb3RlRXZlbnQsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICBkaXNwb3NlKCk7XG4gICAgfSxcbiAgICByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG4gIHJldHVybiByZW1vdGVPYnNlcnZhYmxlRE9NO1xufVxuIiwgImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSB2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKFxuICAgICAgICAgICAgdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzbmFwc2hvdCxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGxvZ01lc3NhZ2U6IGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGFkZENvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImNvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQgfSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiZGlzY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QobXV0YXRpb25MaXN0OiBBcnJheTxNdXRhdGlvblJlY29yZD4pOiB2b2lkIHtcbiAgICBjb25zdCBkb2N1bWVudEVsID0gdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQ7XG4gICAgY29uc3QgZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChkb2N1bWVudEVsKTtcbiAgICBpZiAoIWRvY3VtZW50VmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZG9jdW1lbnQgbm90IGNyZWF0ZWQgaW4gcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3RgKTtcbiAgICB9XG5cbiAgICBpZiAobXV0YXRpb25MaXN0Lmxlbmd0aCA+IDEpIHtcbiAgICAgIC8vIFRPRE8gKGh0dHBzOi8vZ2l0aHViLmNvbS9tbWwtaW8vbW1sL2lzc3Vlcy8xMDApIC0gd2FsayBiYWNrIHRocm91Z2ggdGhlIHJlY29yZHMgdG8gZGVyaXZlIHRoZSBpbnRlcm1lZGlhdGVcbiAgICAgIC8vICBzdGF0ZXMgKGUuZy4gaWYgYW4gYXR0cmlidXRlIGlzIGxhdGVyIGFkZGVkIHRvIGFuIGVsZW1lbnQgY3JlYXRlZCBpbiBhbiBlYXJsaWVyIHJlY29yZCB0aGVuIGl0IHNob3VsZCBub3RcbiAgICAgIC8vICBoYXZlIHRoYXQgYXR0cmlidXRlIHdoZW4gdGhlIGVsZW1lbnQgaXMgYWRkZWQuIFRoaXMgaXMgaW1wb3J0YW50IGFzIGluY29ycmVjdCBhdHRyaWJ1dGUgc2V0cyBjYW4gYWZmZWN0XG4gICAgICAvLyAgdmlzaWJpbGl0eSBhbmQgZXhwZWN0ZWQgY2xpZW50IHBlcmZvcm1hbmNlLlxuICAgIH1cblxuICAgIGZvciAoY29uc3QgbXV0YXRpb24gb2YgbXV0YXRpb25MaXN0KSB7XG4gICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgbXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIgJiZcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0LCBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lISlcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hZGRLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbik7XG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcbiAgICAgIGNvbnN0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZ1xuICAgICAgICA/IHRoaXMuZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG11dGF0aW9uLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dClcbiAgICAgICAgOiBudWxsO1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgIG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICk7XG4gICAgICBjb25zdCBhZGRlZE5vZGVzOiBBcnJheTxTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudD4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5hZGRlZE5vZGVzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2aXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgbm9kZSBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgKTtcbiAgICAgICAgYWRkZWROb2Rlcy5wdXNoKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWModmlydHVhbERPTUVsZW1lbnQpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5yZW1vdmVkTm9kZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChub2RlIGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICBub2RlIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG11dGF0aW9uUmVjb3JkOiBTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQgPSB7XG4gICAgICAgIHR5cGU6IG11dGF0aW9uLnR5cGUsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgYWRkZWROb2RlcyxcbiAgICAgICAgcmVtb3ZlZE5vZGVJZHMsXG4gICAgICAgIHByZXZpb3VzU2libGluZ0lkOlxuICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyAhPT0gbnVsbFxuICAgICAgICAgICAgPyB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZykubm9kZUlkXG4gICAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuXG4gICAgICB0aGlzLnJlbW92ZUtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZEtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uOiBNdXRhdGlvblJlY29yZCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldE5vZGUgPSBtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgY29uc3QgdmlydHVhbERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQodGFyZ2V0Tm9kZSk7XG4gICAgaWYgKCF2aXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlVua25vd24gbm9kZSBpbiBhZGRLbm93bk5vZGVzSW5NdXRhdGlvbjpcIiArIHRhcmdldE5vZGUgKyBcIixcIiArIG11dGF0aW9uLnR5cGUsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgbGV0IHByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZztcbiAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICB3aGlsZSAocHJldmlvdXNTaWJsaW5nICYmIHRoaXMuaXNJZ25vcmVkRWxlbWVudChwcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQpKSB7XG4gICAgICAgIHByZXZpb3VzU2libGluZyA9IHByZXZpb3VzU2libGluZy5wcmV2aW91c1NpYmxpbmc7XG4gICAgICB9XG4gICAgICBpZiAocHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZ0VsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoXG4gICAgICAgICAgcHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHByZXZpb3VzIHNpYmxpbmdcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSB2aXJ0dWFsRE9NRWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YocHJldmlvdXNTaWJsaW5nRWxlbWVudCk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcmV2aW91cyBzaWJsaW5nIGlzIG5vdCBjdXJyZW50bHkgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICBhc0VsZW1lbnRPclRleHQsXG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgaWYgKHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihjaGlsZFZpcnR1YWxET01FbGVtZW50KSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluZGV4LCAwLCBjaGlsZFZpcnR1YWxET01FbGVtZW50KTtcbiAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKHRhcmdldE5vZGUsIGF0dHJpYnV0ZU5hbWUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZVZhbHVlID0gKHRhcmdldE5vZGUgYXMgRWxlbWVudCkuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIGRlbGV0ZSB2aXJ0dWFsRE9NRWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGFyYWN0ZXJEYXRhXCIpIHtcbiAgICAgIHZpcnR1YWxET01FbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbjogTXV0YXRpb25SZWNvcmQpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KHRhcmdldE5vZGUpO1xuICAgIGlmICghdmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gbm9kZSBpbiBtdXRhdGlvbiBsaXN0OlwiICsgdGFyZ2V0Tm9kZSArIFwiLCBcIiArIG11dGF0aW9uLnR5cGUpO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgZm9yIChjb25zdCBub2RlIG9mIG11dGF0aW9uLnJlbW92ZWROb2Rlcykge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KGFzRWxlbWVudE9yVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoYXNFbGVtZW50T3JUZXh0KTtcbiAgICAgICAgaWYgKCFjaGlsZERPTUVsZW1lbnQpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4odGhpcy5odG1sUGF0aCwgXCJVbmtub3duIG5vZGUgaW4gcmVtb3ZlS25vd25Ob2Rlc0luTXV0YXRpb25cIik7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVWaXJ0dWFsRE9NRWxlbWVudCh2aXJ0dWFsRE9NRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQucmVhbEVsZW1lbnQpO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcykge1xuICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChub2RlLCBwYXJlbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgY2hpbGQgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxFbGVtZW50KSB7XG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQuY2hpbGROb2Rlcy5wdXNoKGNoaWxkVmlydHVhbEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KG5vZGUpO1xuICAgIGlmIChleGlzdGluZ1ZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vZGUgYWxyZWFkeSBoYXMgYSB2aXJ0dWFsIGVsZW1lbnQ6IFwiICsgbm9kZS5ub2RlTmFtZSk7XG4gICAgfVxuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFzc2lnbiBub2RlIGlkIHRvIG51bGxcIik7XG4gICAgfVxuXG4gICAgY29uc3QgYXR0cmlidXRlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGlmICgobm9kZSBhcyBhbnkpLmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IGFzSFRNTEVsZW1lbnQgPSBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGVOYW1lcygpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVsbCBhdHRyaWJ1dGUgdmFsdWUgZm9yIGtleTogXCIgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobm9kZSwga2V5KSkge1xuICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUlkID0gdGhpcy5uZXh0Tm9kZUlkKys7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IHtcbiAgICAgIG5vZGVJZCxcbiAgICAgIHRhZzogbm9kZS5ub2RlTmFtZSxcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBjaGlsZE5vZGVzOiBbXSxcbiAgICAgIHJlYWxFbGVtZW50OiBub2RlLFxuICAgICAgcGFyZW50LFxuICAgIH07XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0ICYmIG5vZGUudGV4dENvbnRlbnQpIHtcbiAgICAgIHZpcnR1YWxFbGVtZW50LnRleHRDb250ZW50ID0gbm9kZS50ZXh0Q29udGVudDtcbiAgICB9XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuc2V0KHZpcnR1YWxFbGVtZW50LCBub2RlSWQpO1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLnNldChub2RlSWQsIHZpcnR1YWxFbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5zZXQobm9kZSwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogRWxlbWVudCB8IFRleHQgfCBudWxsIHtcbiAgICBsZXQgY3VycmVudE5vZGUgPSBub2RlO1xuICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgcmV0dXJuIGN1cnJlbnROb2RlO1xuICAgIH1cbiAgICB3aGlsZSAoY3VycmVudE5vZGUgJiYgY3VycmVudE5vZGUucHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgICByZXR1cm4gY3VycmVudE5vZGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBkb21Ob2RlID0gdGhpcy5ub2RlSWRUb05vZGUuZ2V0KHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBub2RlIElEIGluIHJlbW90ZSBldmVudDogXCIgKyByZW1vdGVFdmVudC5ub2RlSWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkb21Ob2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgY29uc29sZS53YXJuKFwiQ2Fubm90IGRpc3BhdGNoIHJlbW90ZSBldmVudCB0byB0ZXh0IG5vZGVcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgICBjb25uZWN0aW9uSWQsXG4gICAgICBkb21Ob2RlLnJlYWxFbGVtZW50IGFzIEVsZW1lbnQsXG4gICAgICByZW1vdGVFdmVudCxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGRpc3Bvc2UoKSB7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIpO1xuICAgIHRoaXMuZG9tUnVubmVyLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RG9jdW1lbnRUaW1lKCkge1xuICAgIHJldHVybiB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudFRpbWUoKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IE9ic2VydmFibGVET00gfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTVwiO1xuaW1wb3J0IHtcbiAgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gIERPTV9NRVNTQUdFX1RZUEUsXG4gIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5IH0gZnJvbSBcIi4vV2ViQnJvd3NlckRPTVJ1bm5lclwiO1xuXG4vLyBUaGlzIHJ1bnMgaW4gdGhlIGlmcmFtZSB0aGF0IHdpbGwgZXhlY3V0ZSB0aGUgZG9jdW1lbnQgc2NyaXB0IHRvIHNldHVwIHRoZSBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBtZXNzYWdlc1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcbmltcG9ydCB7IERPTVJ1bm5lckZhY3RvcnksIERPTVJ1bm5lckludGVyZmFjZSwgRE9NUnVubmVyTWVzc2FnZSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihodG1sUGF0aCwgaHRtbENvbnRlbnRzLCBwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmNvbnN0IGRvY3VtZW50TG9hZFRpbWUgPSBEYXRlLm5vdygpO1xuXG5leHBvcnQgY2xhc3MgV2ViQnJvd3NlckRPTVJ1bm5lciBpbXBsZW1lbnRzIERPTVJ1bm5lckludGVyZmFjZSB7XG4gIHByaXZhdGUgbXV0YXRpb25PYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlcjtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBodG1sUGF0aDogc3RyaW5nLFxuICAgIGh0bWxDb250ZW50czogc3RyaW5nLFxuICAgIHBhcmFtczogb2JqZWN0LFxuICAgIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IGh0bWxQYXRoO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIC8vIEZvcndhcmQgY29uc29sZSBtZXNzYWdlc1xuICAgIGZvciAoY29uc3QgbGV2ZWwgb2YgW1wiZXJyb3JcIiwgXCJ3YXJuXCIsIFwiaW5mb1wiLCBcImxvZ1wiXSBhcyBjb25zdCkge1xuICAgICAgY29uc3QgZGVmYXVsdEZuID0gd2luZG93LmNvbnNvbGVbbGV2ZWxdO1xuXG4gICAgICB3aW5kb3cuY29uc29sZVtsZXZlbF0gPSAoLi4uYXJncykgPT4ge1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgICAgbGV2ZWwsXG4gICAgICAgICAgICBjb250ZW50OiBhcmdzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBkZWZhdWx0Rm4oLi4uYXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZvcndhcmQgdW5jYXVnaHQgZXJyb3JzXG4gICAgd2luZG93Lm9uZXJyb3IgPSAobWVzc2FnZSwgc291cmNlLCBsaW5lLCBjb2x1bW4sIGVycm9yKSA9PiB7XG4gICAgICBjYWxsYmFjayh7XG4gICAgICAgIGxvZ01lc3NhZ2U6IHtcbiAgICAgICAgICBsZXZlbDogXCJzeXN0ZW1cIixcbiAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgIHR5cGU6IGVycm9yPy5uYW1lLFxuICAgICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgICBjb2x1bW4sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgbGV0IGRpZFNlbmRMb2FkID0gZmFsc2U7XG5cbiAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIgPSBuZXcgd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9uTGlzdCkgPT4ge1xuICAgICAgaWYgKCFkb2N1bWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWRpZFNlbmRMb2FkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk11dGF0aW9uT2JzZXJ2ZXIgY2FsbGVkIGJlZm9yZSBsb2FkXCIpO1xuICAgICAgfVxuICAgICAgdGhpcy5jYWxsYmFjayh7XG4gICAgICAgIG11dGF0aW9uTGlzdCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgKHdpbmRvdyBhcyBhbnkpLnBhcmFtcyA9IHBhcmFtcztcblxuICAgIGNvbnN0IGZpbmlzaExvYWQgPSAoKSA9PiB7XG4gICAgICBpZiAoZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmluaXNoTG9hZCBjYWxsZWQgdHdpY2VcIik7XG4gICAgICB9XG4gICAgICBkaWRTZW5kTG9hZCA9IHRydWU7XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbG9hZGVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIub2JzZXJ2ZSh3aW5kb3cuZG9jdW1lbnQsIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfTtcbiAgICBpZiAoZG9jdW1lbnQuYm9keSkge1xuICAgICAgc2V0VGltZW91dChmaW5pc2hMb2FkLCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGZpbmlzaExvYWQpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgYnViYmxlcyA9IHJlbW90ZUV2ZW50LmJ1YmJsZXMgfHwgZmFsc2U7XG4gICAgY29uc3QgcmVtb3RlRXZlbnRPYmplY3QgPSBuZXcgQ3VzdG9tRXZlbnQocmVtb3RlRXZlbnQubmFtZSwge1xuICAgICAgYnViYmxlcyxcbiAgICAgIGRldGFpbDogeyAuLi5yZW1vdGVFdmVudC5wYXJhbXMsIGNvbm5lY3Rpb25JZCB9LFxuICAgIH0pO1xuXG4gICAgLy8gRGlzcGF0Y2ggdGhlIGV2ZW50IHZpYSBKYXZhU2NyaXB0LlxuICAgIHJlYWxFbGVtZW50LmRpc3BhdGNoRXZlbnQocmVtb3RlRXZlbnRPYmplY3QpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAvLyBUT0RPIC0gaGFuZGxlIGRpc3Bvc2VcbiAgICBjb25zb2xlLmxvZyhcIldlYkJyb3dzZXJET01SdW5uZXIuZGlzcG9zZVwiKTtcbiAgfVxuXG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50IHtcbiAgICByZXR1cm4gZG9jdW1lbnQ7XG4gIH1cblxuICBnZXREb2N1bWVudFRpbWUoKTogbnVtYmVyIHtcbiAgICBpZiAoZG9jdW1lbnQudGltZWxpbmUgJiYgZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXI7XG4gICAgfVxuICAgIHJldHVybiBEYXRlLm5vdygpIC0gZG9jdW1lbnRMb2FkVGltZTtcbiAgfVxuXG4gIC8vIFRPRE8gLSByZXNvbHZlIHR5cGVzIChXaW5kb3cgbmVlZHMgdG8gZXhwb3NlIGNsYXNzZXMgc3VjaCBhcyBDdXN0b21FdmVudCBhcyBwcm9wZXJ0aWVzKVxuICBnZXRXaW5kb3coKTogYW55IHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9XG59XG4iLCAiaW1wb3J0IHsgc2V0dXBJZnJhbWVXZWJSdW5uZXIgfSBmcm9tIFwiLi9JZnJhbWVXZWJSdW5uZXJcIjtcblxuY29uc3QgYXJncyA9ICh3aW5kb3cgYXMgYW55KS5hcmdzO1xuc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJncyk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsUUFBQSxjQUFBLENBQUE7QUFBQSxhQUFBLGFBQUE7TUFBQSxvQ0FBQSxNQUFBQTtNQUFBLHVEQUFBLE1BQUFDO01BQUEsa0JBQUEsTUFBQUM7TUFBQSx1Q0FBQSxNQUFBQztNQUFBLHFDQUFBLE1BQUE7TUFBQSx1Q0FBQSxNQUFBO0lBQUEsQ0FBQTtBQUFBLElBQUFDLFFBQUEsVUFBQSxhQUFBLFdBQUE7QUNJTyxRQUFNSixzQ0FBcUM7QUFDM0MsUUFBTUcseUNBQXdDO0FBQzlDLFFBQU1GLHlEQUNYO0FBQ0ssUUFBTUMsb0JBQW1CO0FBOEJ6QixhQUFTLG9DQUNkLFNBQ0EsVUFDQTtBQUNBLFVBQUksUUFBUSxTQUFTRixxQ0FBb0M7QUFDdkQsaUJBQVMsbUJBQW1CLFFBQVEsWUFBWTtNQUNsRCxXQUFXLFFBQVEsU0FBU0csd0NBQXVDO0FBQ2pFLGlCQUFTLHNCQUFzQixRQUFRLFlBQVk7TUFDckQsV0FBVyxRQUFRLFNBQVNGLHdEQUF1RDtBQUNqRixpQkFBUyxvQ0FBb0MsUUFBUSxjQUFjLFFBQVEsS0FBSztNQUNsRixPQUFPO0FBQ0wsZ0JBQVEsTUFBTSx3QkFBd0IsT0FBTztNQUMvQztJQUNGO0FBRU8sYUFBUyxzQ0FDZCxRQUNBLFNBQ0E7QUFDQSxZQUFNLHNCQUE4QztRQUNsRCxtQkFBbUIsY0FBNEI7QUFDN0MsaUJBQU87WUFDTCxN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QUFnQixJQUFJO0FBQUEsSUFDeEI7QUFBQSxNQUNFLEdBQUc7QUFBQSxNQUNILGNBQWM7QUFBQTtBQUFBLElBQ2hCO0FBQUEsSUFDQSxDQUFDLHlCQUErQztBQUM5QywyQkFBcUI7QUFBQSxRQUNuQixNQUFNO0FBQUEsUUFDTixTQUFTO0FBQUEsTUFDWCxDQUFDO0FBQUEsSUFDSDtBQUFBLElBQ0E7QUFBQSxFQUNGO0FBRUEsU0FBTyxpQkFBaUIsV0FBVyxDQUFDLE1BQU07QUFDeEMsVUFBTSxTQUFTLEtBQUssTUFBTSxFQUFFLElBQUk7QUFDaEMsWUFBUSxPQUFPLE1BQU07QUFBQSxNQUNuQixLQUFLO0FBQ0gsc0JBQWMsb0NBQW9DLE9BQU8sY0FBYyxPQUFPLEtBQUs7QUFDbkY7QUFBQSxNQUNGLEtBQUs7QUFDSCxzQkFBYyxtQkFBbUIsT0FBTyxZQUFZO0FBQ3BEO0FBQUEsTUFDRixLQUFLO0FBQ0gsc0JBQWMsc0JBQXNCLE9BQU8sWUFBWTtBQUN2RDtBQUFBLE1BQ0Y7QUFDRSxnQkFBUSxNQUFNLHdCQUF3QixNQUFNO0FBQUEsSUFDaEQ7QUFBQSxFQUNGLENBQUM7QUFDSDs7O0FFbERBLElBQU0sT0FBUSxPQUFlO0FBQzdCLHFCQUFxQixJQUFJOyIsCiAgIm5hbWVzIjogWyJBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFIiwgIkRJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFIiwgIkRPTV9NRVNTQUdFX1RZUEUiLCAiUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSIsICJtb2R1bGUiLCAiYXJncyJdCn0K\n';
|
|
5
|
+
var build_default = '// ../../observable-dom/src/utils.ts\nfunction virtualDOMElementToStatic(el) {\n return {\n nodeId: el.nodeId,\n tag: el.tag,\n attributes: el.attributes,\n childNodes: el.childNodes.map((child) => virtualDOMElementToStatic(child)),\n textContent: el.textContent\n };\n}\n\n// ../../observable-dom/src/ObservableDOM.ts\nvar ObservableDOM = class {\n constructor(observableDOMParameters, callback, runnerFactory) {\n this.nodeToNodeId = /* @__PURE__ */ new Map();\n this.nodeIdToNode = /* @__PURE__ */ new Map();\n this.realElementToVirtualElement = /* @__PURE__ */ new Map();\n this.ignoreTextNodes = true;\n this.nextNodeId = 1;\n this.htmlPath = observableDOMParameters.htmlPath;\n this.ignoreTextNodes = observableDOMParameters.ignoreTextNodes;\n this.callback = callback;\n this.documentTimeIntervalTimer = setInterval(() => {\n this.callback(\n {\n documentTime: this.getDocumentTime()\n },\n this\n );\n }, observableDOMParameters.pingIntervalMilliseconds || 5e3);\n this.domRunner = runnerFactory(\n observableDOMParameters.htmlPath,\n observableDOMParameters.htmlContents,\n observableDOMParameters.params,\n (domRunnerMessage) => {\n if (domRunnerMessage.loaded) {\n this.createVirtualDOMElementWithChildren(\n this.domRunner.getDocument(),\n null\n );\n const snapshot = virtualDOMElementToStatic(\n this.getVirtualDOMElementForRealElementOrThrow(\n this.domRunner.getDocument()\n )\n );\n this.callback(\n {\n snapshot,\n documentTime: this.getDocumentTime()\n },\n this\n );\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n this.callback(\n {\n logMessage: domRunnerMessage.logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n }\n );\n }\n addConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent("connected", {\n detail: { connectionId }\n })\n );\n }\n removeConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent("disconnected", {\n detail: { connectionId }\n })\n );\n }\n processModificationList(mutationList) {\n const documentEl = this.domRunner.getDocument();\n const documentVirtualDOMElement = this.realElementToVirtualElement.get(documentEl);\n if (!documentVirtualDOMElement) {\n throw new Error(`document not created in processModificationList`);\n }\n if (mutationList.length > 1) {\n }\n for (const mutation of mutationList) {\n if (this.isIgnoredElement(mutation.target)) {\n continue;\n }\n if (mutation.type === "attributes" && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.isIgnoredAttribute(mutation.target, mutation.attributeName)) {\n continue;\n }\n this.addKnownNodesInMutation(mutation);\n const firstNonIgnoredPreviousSibling = mutation.previousSibling ? this.getFirstNonIgnoredPreviousSibling(mutation.previousSibling) : null;\n const targetElement = this.getVirtualDOMElementForRealElementOrThrow(\n mutation.target\n );\n const addedNodes = [];\n for (const node of mutation.addedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n addedNodes.push(virtualDOMElementToStatic(virtualDOMElement));\n }\n const removedNodeIds = [];\n for (const node of mutation.removedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n removedNodeIds.push(virtualDOMElement.nodeId);\n }\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: firstNonIgnoredPreviousSibling !== null ? this.getVirtualDOMElementForRealElementOrThrow(firstNonIgnoredPreviousSibling).nodeId : null,\n attribute: mutation.attributeName ? {\n attributeName: mutation.attributeName,\n value: mutation.target.getAttribute(mutation.attributeName)\n } : null\n };\n this.callback(\n {\n mutation: mutationRecord,\n documentTime: this.getDocumentTime()\n },\n this\n );\n this.removeKnownNodesInMutation(mutation);\n }\n }\n addKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error(\n "Unknown node in addKnownNodesInMutation:" + targetNode + "," + mutation.type\n );\n }\n if (mutation.type === "childList") {\n let previousSibling = mutation.previousSibling;\n let index = 0;\n while (previousSibling && this.isIgnoredElement(previousSibling)) {\n previousSibling = previousSibling.previousSibling;\n }\n if (previousSibling) {\n const previousSiblingElement = this.realElementToVirtualElement.get(\n previousSibling\n );\n if (!previousSiblingElement) {\n throw new Error("Unknown previous sibling");\n }\n index = virtualDOMElement.childNodes.indexOf(previousSiblingElement);\n if (index === -1) {\n throw new Error("Previous sibling is not currently a child of the parent element");\n }\n index += 1;\n }\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n virtualDOMElement\n );\n if (childVirtualDOMElement) {\n if (virtualDOMElement.childNodes.indexOf(childVirtualDOMElement) === -1) {\n virtualDOMElement.childNodes.splice(index, 0, childVirtualDOMElement);\n index++;\n }\n }\n });\n } else if (mutation.type === "attributes") {\n const attributeName = mutation.attributeName;\n if (this.isIgnoredAttribute(targetNode, attributeName)) {\n return;\n }\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete virtualDOMElement.attributes[attributeName];\n } else {\n virtualDOMElement.attributes[attributeName] = attributeValue;\n }\n } else if (mutation.type === "characterData") {\n virtualDOMElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n }\n removeKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error("Unknown node in mutation list:" + targetNode + ", " + mutation.type);\n }\n if (mutation.type === "childList") {\n for (const node of mutation.removedNodes) {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n continue;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n console.warn(this.htmlPath, "Unknown node in removeKnownNodesInMutation");\n continue;\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n const index = virtualDOMElement.childNodes.indexOf(childDOMElement);\n virtualDOMElement.childNodes.splice(index, 1);\n }\n }\n return;\n }\n }\n removeVirtualDOMElement(virtualDOMElement) {\n this.nodeIdToNode.delete(virtualDOMElement.nodeId);\n this.nodeToNodeId.delete(virtualDOMElement);\n this.realElementToVirtualElement.delete(virtualDOMElement.realElement);\n for (const child of virtualDOMElement.childNodes) {\n this.removeVirtualDOMElement(child);\n }\n }\n createVirtualDOMElementWithChildren(node, parent) {\n const virtualElement = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i];\n const childVirtualElement = this.createVirtualDOMElementWithChildren(\n child,\n virtualElement\n );\n if (childVirtualElement) {\n virtualElement.childNodes.push(childVirtualElement);\n }\n }\n }\n return virtualElement;\n }\n createVirtualDOMElement(node, parent) {\n if (this.isIgnoredElement(node)) {\n return null;\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n throw new Error("Node already has a virtual element: " + node.nodeName);\n }\n if (!node) {\n throw new Error("Cannot assign node id to null");\n }\n const attributes = {};\n if (node.attributes) {\n const asHTMLElement = node;\n for (const key of asHTMLElement.getAttributeNames()) {\n const value = asHTMLElement.getAttribute(key);\n if (value === null) {\n throw new Error("Null attribute value for key: " + key);\n }\n if (!this.isIgnoredAttribute(node, key)) {\n attributes[key] = value;\n }\n }\n }\n const nodeId = this.nextNodeId++;\n const virtualElement = {\n nodeId,\n tag: node.nodeName,\n attributes,\n childNodes: [],\n realElement: node,\n parent\n };\n if (node instanceof this.domRunner.getWindow().Text && node.textContent) {\n virtualElement.textContent = node.textContent;\n }\n this.nodeToNodeId.set(virtualElement, nodeId);\n this.nodeIdToNode.set(nodeId, virtualElement);\n this.realElementToVirtualElement.set(node, virtualElement);\n return virtualElement;\n }\n getFirstNonIgnoredPreviousSibling(node) {\n let currentNode = node;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n while (currentNode && currentNode.previousSibling) {\n currentNode = currentNode.previousSibling;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n }\n return null;\n }\n getVirtualDOMElementForRealElementOrThrow(realElement) {\n const virtualElement = this.realElementToVirtualElement.get(realElement);\n if (!virtualElement) {\n throw new Error(`Virtual element not found for real element`);\n }\n return virtualElement;\n }\n isIgnoredElement(node) {\n if (this.ignoreTextNodes && node instanceof this.domRunner.getWindow().Text) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().HTMLScriptElement) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().Comment) {\n return true;\n }\n return false;\n }\n isIgnoredAttribute(node, attributeName) {\n return attributeName.startsWith("on");\n }\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n const domNode = this.nodeIdToNode.get(remoteEvent.nodeId);\n if (!domNode) {\n console.error("Unknown node ID in remote event: " + remoteEvent.nodeId);\n return;\n }\n if (domNode instanceof this.domRunner.getWindow().Text) {\n console.warn("Cannot dispatch remote event to text node");\n return;\n }\n this.domRunner.dispatchRemoteEventFromConnectionId(\n connectionId,\n domNode.realElement,\n remoteEvent\n );\n }\n dispose() {\n clearInterval(this.documentTimeIntervalTimer);\n this.domRunner.dispose();\n }\n getDocumentTime() {\n return this.domRunner.getDocumentTime();\n }\n};\n\n// ../../observable-dom-common/build/index.js\nvar ADD_CONNECTED_USER_ID_MESSAGE_TYPE = "addConnectedUserId";\nvar REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE = "removeConnectedUserId";\nvar DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE = "dispatchRemoteEventFromConnectionId";\nvar DOM_MESSAGE_TYPE = "dom";\n\n// src/WebBrowserDOMRunner.ts\nvar WebBrowserDOMRunnerFactory = (htmlPath, htmlContents, params, callback) => {\n return new WebBrowserDOMRunner(htmlPath, htmlContents, params, callback);\n};\nvar documentLoadTime = Date.now();\nvar WebBrowserDOMRunner = class {\n constructor(htmlPath, htmlContents, params, callback) {\n this.htmlPath = htmlPath;\n this.callback = callback;\n for (const level of ["error", "warn", "info", "log"]) {\n const defaultFn = window.console[level];\n window.console[level] = (...args2) => {\n callback({\n logMessage: {\n level,\n content: args2\n }\n });\n defaultFn(...args2);\n };\n }\n window.onerror = (message, source, line, column, error) => {\n callback({\n logMessage: {\n level: "system",\n content: [\n {\n message,\n type: error?.name,\n line,\n column\n }\n ]\n }\n });\n return false;\n };\n let didSendLoad = false;\n this.mutationObserver = new window.MutationObserver((mutationList) => {\n if (!document) {\n return;\n }\n if (!didSendLoad) {\n throw new Error("MutationObserver called before load");\n }\n this.callback({\n mutationList\n });\n });\n window.params = params;\n const finishLoad = () => {\n if (didSendLoad) {\n throw new Error("finishLoad called twice");\n }\n didSendLoad = true;\n this.callback({\n loaded: true\n });\n this.mutationObserver.observe(window.document, {\n attributes: true,\n childList: true,\n subtree: true,\n characterData: true\n });\n };\n if (document.body) {\n setTimeout(finishLoad, 0);\n } else {\n window.addEventListener("DOMContentLoaded", finishLoad);\n }\n }\n dispatchRemoteEventFromConnectionId(connectionId, realElement, remoteEvent) {\n const bubbles = remoteEvent.bubbles || false;\n const remoteEventObject = new CustomEvent(remoteEvent.name, {\n bubbles,\n detail: { ...remoteEvent.params, connectionId }\n });\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log("WebBrowserDOMRunner.dispose");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n if (document.timeline && document.timeline.currentTime) {\n return document.timeline.currentTime;\n }\n return Date.now() - documentLoadTime;\n }\n // TODO - resolve types (Window needs to expose classes such as CustomEvent as properties)\n getWindow() {\n return window;\n }\n};\n\n// src/IframeWebRunner.ts\nfunction setupIframeWebRunner(argsString) {\n const observableDOMParams = JSON.parse(atob(argsString));\n const sendMessageToHandler = (message) => {\n window.parent.postMessage(JSON.stringify(message), "*");\n };\n const observableDOM = new ObservableDOM(\n {\n ...observableDOMParams,\n htmlContents: ""\n // This must be empty as the contents are assumed to be provided by the srcdoc\n },\n (observableDOMMessage) => {\n sendMessageToHandler({\n type: DOM_MESSAGE_TYPE,\n message: observableDOMMessage\n });\n },\n WebBrowserDOMRunnerFactory\n );\n window.addEventListener("message", (e) => {\n const parsed = JSON.parse(e.data);\n switch (parsed.type) {\n case DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE:\n observableDOM.dispatchRemoteEventFromConnectionId(parsed.connectionId, parsed.event);\n break;\n case ADD_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.addConnectedUserId(parsed.connectionId);\n break;\n case REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.removeConnectedUserId(parsed.connectionId);\n break;\n default:\n console.error("Unknown message type", parsed);\n }\n });\n}\n\n// src/index.ts\nvar args = window.args;\nsetupIframeWebRunner(args);\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSB2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKFxuICAgICAgICAgICAgdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzbmFwc2hvdCxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGxvZ01lc3NhZ2U6IGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGFkZENvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImNvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQgfSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiZGlzY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QobXV0YXRpb25MaXN0OiBBcnJheTxNdXRhdGlvblJlY29yZD4pOiB2b2lkIHtcbiAgICBjb25zdCBkb2N1bWVudEVsID0gdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQ7XG4gICAgY29uc3QgZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChkb2N1bWVudEVsKTtcbiAgICBpZiAoIWRvY3VtZW50VmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZG9jdW1lbnQgbm90IGNyZWF0ZWQgaW4gcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3RgKTtcbiAgICB9XG5cbiAgICBpZiAobXV0YXRpb25MaXN0Lmxlbmd0aCA+IDEpIHtcbiAgICAgIC8vIFRPRE8gKGh0dHBzOi8vZ2l0aHViLmNvbS9tbWwtaW8vbW1sL2lzc3Vlcy8xMDApIC0gd2FsayBiYWNrIHRocm91Z2ggdGhlIHJlY29yZHMgdG8gZGVyaXZlIHRoZSBpbnRlcm1lZGlhdGVcbiAgICAgIC8vICBzdGF0ZXMgKGUuZy4gaWYgYW4gYXR0cmlidXRlIGlzIGxhdGVyIGFkZGVkIHRvIGFuIGVsZW1lbnQgY3JlYXRlZCBpbiBhbiBlYXJsaWVyIHJlY29yZCB0aGVuIGl0IHNob3VsZCBub3RcbiAgICAgIC8vICBoYXZlIHRoYXQgYXR0cmlidXRlIHdoZW4gdGhlIGVsZW1lbnQgaXMgYWRkZWQuIFRoaXMgaXMgaW1wb3J0YW50IGFzIGluY29ycmVjdCBhdHRyaWJ1dGUgc2V0cyBjYW4gYWZmZWN0XG4gICAgICAvLyAgdmlzaWJpbGl0eSBhbmQgZXhwZWN0ZWQgY2xpZW50IHBlcmZvcm1hbmNlLlxuICAgIH1cblxuICAgIGZvciAoY29uc3QgbXV0YXRpb24gb2YgbXV0YXRpb25MaXN0KSB7XG4gICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgbXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIgJiZcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0LCBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lISlcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hZGRLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbik7XG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcbiAgICAgIGNvbnN0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZ1xuICAgICAgICA/IHRoaXMuZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG11dGF0aW9uLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dClcbiAgICAgICAgOiBudWxsO1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgIG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICk7XG4gICAgICBjb25zdCBhZGRlZE5vZGVzOiBBcnJheTxTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudD4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5hZGRlZE5vZGVzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2aXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgbm9kZSBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgKTtcbiAgICAgICAgYWRkZWROb2Rlcy5wdXNoKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWModmlydHVhbERPTUVsZW1lbnQpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5yZW1vdmVkTm9kZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChub2RlIGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICBub2RlIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG11dGF0aW9uUmVjb3JkOiBTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQgPSB7XG4gICAgICAgIHR5cGU6IG11dGF0aW9uLnR5cGUsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgYWRkZWROb2RlcyxcbiAgICAgICAgcmVtb3ZlZE5vZGVJZHMsXG4gICAgICAgIHByZXZpb3VzU2libGluZ0lkOlxuICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyAhPT0gbnVsbFxuICAgICAgICAgICAgPyB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZykubm9kZUlkXG4gICAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuXG4gICAgICB0aGlzLnJlbW92ZUtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZEtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uOiBNdXRhdGlvblJlY29yZCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldE5vZGUgPSBtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgY29uc3QgdmlydHVhbERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQodGFyZ2V0Tm9kZSk7XG4gICAgaWYgKCF2aXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlVua25vd24gbm9kZSBpbiBhZGRLbm93bk5vZGVzSW5NdXRhdGlvbjpcIiArIHRhcmdldE5vZGUgKyBcIixcIiArIG11dGF0aW9uLnR5cGUsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgbGV0IHByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZztcbiAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICB3aGlsZSAocHJldmlvdXNTaWJsaW5nICYmIHRoaXMuaXNJZ25vcmVkRWxlbWVudChwcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQpKSB7XG4gICAgICAgIHByZXZpb3VzU2libGluZyA9IHByZXZpb3VzU2libGluZy5wcmV2aW91c1NpYmxpbmc7XG4gICAgICB9XG4gICAgICBpZiAocHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZ0VsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoXG4gICAgICAgICAgcHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHByZXZpb3VzIHNpYmxpbmdcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSB2aXJ0dWFsRE9NRWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YocHJldmlvdXNTaWJsaW5nRWxlbWVudCk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcmV2aW91cyBzaWJsaW5nIGlzIG5vdCBjdXJyZW50bHkgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICBhc0VsZW1lbnRPclRleHQsXG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgaWYgKHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihjaGlsZFZpcnR1YWxET01FbGVtZW50KSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluZGV4LCAwLCBjaGlsZFZpcnR1YWxET01FbGVtZW50KTtcbiAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKHRhcmdldE5vZGUsIGF0dHJpYnV0ZU5hbWUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZVZhbHVlID0gKHRhcmdldE5vZGUgYXMgRWxlbWVudCkuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIGRlbGV0ZSB2aXJ0dWFsRE9NRWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGFyYWN0ZXJEYXRhXCIpIHtcbiAgICAgIHZpcnR1YWxET01FbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbjogTXV0YXRpb25SZWNvcmQpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KHRhcmdldE5vZGUpO1xuICAgIGlmICghdmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gbm9kZSBpbiBtdXRhdGlvbiBsaXN0OlwiICsgdGFyZ2V0Tm9kZSArIFwiLCBcIiArIG11dGF0aW9uLnR5cGUpO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgZm9yIChjb25zdCBub2RlIG9mIG11dGF0aW9uLnJlbW92ZWROb2Rlcykge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KGFzRWxlbWVudE9yVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoYXNFbGVtZW50T3JUZXh0KTtcbiAgICAgICAgaWYgKCFjaGlsZERPTUVsZW1lbnQpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4odGhpcy5odG1sUGF0aCwgXCJVbmtub3duIG5vZGUgaW4gcmVtb3ZlS25vd25Ob2Rlc0luTXV0YXRpb25cIik7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVWaXJ0dWFsRE9NRWxlbWVudCh2aXJ0dWFsRE9NRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQucmVhbEVsZW1lbnQpO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcykge1xuICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChub2RlLCBwYXJlbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgY2hpbGQgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxFbGVtZW50KSB7XG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQuY2hpbGROb2Rlcy5wdXNoKGNoaWxkVmlydHVhbEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KG5vZGUpO1xuICAgIGlmIChleGlzdGluZ1ZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vZGUgYWxyZWFkeSBoYXMgYSB2aXJ0dWFsIGVsZW1lbnQ6IFwiICsgbm9kZS5ub2RlTmFtZSk7XG4gICAgfVxuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFzc2lnbiBub2RlIGlkIHRvIG51bGxcIik7XG4gICAgfVxuXG4gICAgY29uc3QgYXR0cmlidXRlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGlmICgobm9kZSBhcyBhbnkpLmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IGFzSFRNTEVsZW1lbnQgPSBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGVOYW1lcygpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVsbCBhdHRyaWJ1dGUgdmFsdWUgZm9yIGtleTogXCIgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobm9kZSwga2V5KSkge1xuICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUlkID0gdGhpcy5uZXh0Tm9kZUlkKys7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IHtcbiAgICAgIG5vZGVJZCxcbiAgICAgIHRhZzogbm9kZS5ub2RlTmFtZSxcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBjaGlsZE5vZGVzOiBbXSxcbiAgICAgIHJlYWxFbGVtZW50OiBub2RlLFxuICAgICAgcGFyZW50LFxuICAgIH07XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0ICYmIG5vZGUudGV4dENvbnRlbnQpIHtcbiAgICAgIHZpcnR1YWxFbGVtZW50LnRleHRDb250ZW50ID0gbm9kZS50ZXh0Q29udGVudDtcbiAgICB9XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuc2V0KHZpcnR1YWxFbGVtZW50LCBub2RlSWQpO1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLnNldChub2RlSWQsIHZpcnR1YWxFbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5zZXQobm9kZSwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogRWxlbWVudCB8IFRleHQgfCBudWxsIHtcbiAgICBsZXQgY3VycmVudE5vZGUgPSBub2RlO1xuICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgcmV0dXJuIGN1cnJlbnROb2RlO1xuICAgIH1cbiAgICB3aGlsZSAoY3VycmVudE5vZGUgJiYgY3VycmVudE5vZGUucHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgICByZXR1cm4gY3VycmVudE5vZGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBkb21Ob2RlID0gdGhpcy5ub2RlSWRUb05vZGUuZ2V0KHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBub2RlIElEIGluIHJlbW90ZSBldmVudDogXCIgKyByZW1vdGVFdmVudC5ub2RlSWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkb21Ob2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgY29uc29sZS53YXJuKFwiQ2Fubm90IGRpc3BhdGNoIHJlbW90ZSBldmVudCB0byB0ZXh0IG5vZGVcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgICBjb25uZWN0aW9uSWQsXG4gICAgICBkb21Ob2RlLnJlYWxFbGVtZW50IGFzIEVsZW1lbnQsXG4gICAgICByZW1vdGVFdmVudCxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGRpc3Bvc2UoKSB7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIpO1xuICAgIHRoaXMuZG9tUnVubmVyLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RG9jdW1lbnRUaW1lKCkge1xuICAgIHJldHVybiB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudFRpbWUoKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IFJlbW90ZUV2ZW50IH0gZnJvbSBcIkBtbWwtaW8vbmV0d29ya2VkLWRvbS1wcm90b2NvbFwiO1xuXG5pbXBvcnQgeyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLCBPYnNlcnZhYmxlRE9NTWVzc2FnZSB9IGZyb20gXCIuL09ic2VydmFibGVET01JbnRlcmZhY2VcIjtcblxuZXhwb3J0IGNvbnN0IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUgPSBcImFkZENvbm5lY3RlZFVzZXJJZFwiO1xuZXhwb3J0IGNvbnN0IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUgPSBcInJlbW92ZUNvbm5lY3RlZFVzZXJJZFwiO1xuZXhwb3J0IGNvbnN0IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFID1cbiAgXCJkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZFwiO1xuZXhwb3J0IGNvbnN0IERPTV9NRVNTQUdFX1RZUEUgPSBcImRvbVwiO1xuXG5leHBvcnQgdHlwZSBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTtcbiAgY29ubmVjdGlvbklkOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBSZW1vdmVDb25uZWN0ZWRVc2VySWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTtcbiAgY29ubmVjdGlvbklkOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBEaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRTtcbiAgY29ubmVjdGlvbklkOiBudW1iZXI7XG4gIGV2ZW50OiBSZW1vdGVFdmVudDtcbn07XG5cbmV4cG9ydCB0eXBlIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9XG4gIHwgQWRkQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2VcbiAgfCBEaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZE1lc3NhZ2U7XG5cbnR5cGUgRE9NTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERPTV9NRVNTQUdFX1RZUEU7XG4gIG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UgPSBET01NZXNzYWdlO1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlNZXNzYWdlVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2UoXG4gIG1lc3NhZ2U6IFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgaW5zdGFuY2U6IE9ic2VydmFibGVET01JbnRlcmZhY2UsXG4pIHtcbiAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLmFkZENvbm5lY3RlZFVzZXJJZChtZXNzYWdlLmNvbm5lY3Rpb25JZCk7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UucmVtb3ZlQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQobWVzc2FnZS5jb25uZWN0aW9uSWQsIG1lc3NhZ2UuZXZlbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2YWJsZURPTUludGVyZmFjZVRvTWVzc2FnZVNlbmRlcihcbiAgc2VuZGVyOiAobWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB2b2lkLFxuICBkaXNwb3NlOiAoKSA9PiB2b2lkLFxuKSB7XG4gIGNvbnN0IHJlbW90ZU9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UgPSB7XG4gICAgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICAgIGV2ZW50OiByZW1vdGVFdmVudCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgIGRpc3Bvc2UoKTtcbiAgICB9LFxuICAgIHJlbW92ZUNvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbiAgcmV0dXJuIHJlbW90ZU9ic2VydmFibGVET007XG59XG4iLCAiaW1wb3J0IHsgUmVtb3RlRXZlbnQgfSBmcm9tIFwiQG1tbC1pby9uZXR3b3JrZWQtZG9tLXByb3RvY29sXCI7XG5pbXBvcnQgeyBET01SdW5uZXJGYWN0b3J5LCBET01SdW5uZXJJbnRlcmZhY2UsIERPTVJ1bm5lck1lc3NhZ2UgfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbVwiO1xuXG5leHBvcnQgY29uc3QgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChtdXRhdGlvbkxpc3Q6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQsXG4pOiBET01SdW5uZXJJbnRlcmZhY2UgPT4ge1xuICByZXR1cm4gbmV3IFdlYkJyb3dzZXJET01SdW5uZXIoaHRtbFBhdGgsIGh0bWxDb250ZW50cywgcGFyYW1zLCBjYWxsYmFjayk7XG59O1xuXG5jb25zdCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcblxuZXhwb3J0IGNsYXNzIFdlYkJyb3dzZXJET01SdW5uZXIgaW1wbGVtZW50cyBET01SdW5uZXJJbnRlcmZhY2Uge1xuICBwcml2YXRlIG11dGF0aW9uT2JzZXJ2ZXI6IE11dGF0aW9uT2JzZXJ2ZXI7XG4gIHByaXZhdGUgaHRtbFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSBjYWxsYmFjazogKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaHRtbFBhdGg6IHN0cmluZyxcbiAgICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgICBwYXJhbXM6IG9iamVjdCxcbiAgICBjYWxsYmFjazogKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQsXG4gICkge1xuICAgIHRoaXMuaHRtbFBhdGggPSBodG1sUGF0aDtcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICAvLyBGb3J3YXJkIGNvbnNvbGUgbWVzc2FnZXNcbiAgICBmb3IgKGNvbnN0IGxldmVsIG9mIFtcImVycm9yXCIsIFwid2FyblwiLCBcImluZm9cIiwgXCJsb2dcIl0gYXMgY29uc3QpIHtcbiAgICAgIGNvbnN0IGRlZmF1bHRGbiA9IHdpbmRvdy5jb25zb2xlW2xldmVsXTtcblxuICAgICAgd2luZG93LmNvbnNvbGVbbGV2ZWxdID0gKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgY2FsbGJhY2soe1xuICAgICAgICAgIGxvZ01lc3NhZ2U6IHtcbiAgICAgICAgICAgIGxldmVsLFxuICAgICAgICAgICAgY29udGVudDogYXJncyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgZGVmYXVsdEZuKC4uLmFyZ3MpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGb3J3YXJkIHVuY2F1Z2h0IGVycm9yc1xuICAgIHdpbmRvdy5vbmVycm9yID0gKG1lc3NhZ2UsIHNvdXJjZSwgbGluZSwgY29sdW1uLCBlcnJvcikgPT4ge1xuICAgICAgY2FsbGJhY2soe1xuICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgbGV2ZWw6IFwic3lzdGVtXCIsXG4gICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgICB0eXBlOiBlcnJvcj8ubmFtZSxcbiAgICAgICAgICAgICAgbGluZSxcbiAgICAgICAgICAgICAgY29sdW1uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIGxldCBkaWRTZW5kTG9hZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5tdXRhdGlvbk9ic2VydmVyID0gbmV3IHdpbmRvdy5NdXRhdGlvbk9ic2VydmVyKChtdXRhdGlvbkxpc3QpID0+IHtcbiAgICAgIGlmICghZG9jdW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCFkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNdXRhdGlvbk9ic2VydmVyIGNhbGxlZCBiZWZvcmUgbG9hZFwiKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBtdXRhdGlvbkxpc3QsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgICh3aW5kb3cgYXMgYW55KS5wYXJhbXMgPSBwYXJhbXM7XG5cbiAgICBjb25zdCBmaW5pc2hMb2FkID0gKCkgPT4ge1xuICAgICAgaWYgKGRpZFNlbmRMb2FkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImZpbmlzaExvYWQgY2FsbGVkIHR3aWNlXCIpO1xuICAgICAgfVxuICAgICAgZGlkU2VuZExvYWQgPSB0cnVlO1xuICAgICAgdGhpcy5jYWxsYmFjayh7XG4gICAgICAgIGxvYWRlZDogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5tdXRhdGlvbk9ic2VydmVyLm9ic2VydmUod2luZG93LmRvY3VtZW50LCB7XG4gICAgICAgIGF0dHJpYnV0ZXM6IHRydWUsXG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgY2hhcmFjdGVyRGF0YTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgaWYgKGRvY3VtZW50LmJvZHkpIHtcbiAgICAgIHNldFRpbWVvdXQoZmluaXNoTG9hZCwgMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBmaW5pc2hMb2FkKTtcbiAgICB9XG4gIH1cblxuICBkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICBjb25uZWN0aW9uSWQ6IG51bWJlcixcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCxcbiAgICByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGJ1YmJsZXMgPSByZW1vdGVFdmVudC5idWJibGVzIHx8IGZhbHNlO1xuICAgIGNvbnN0IHJlbW90ZUV2ZW50T2JqZWN0ID0gbmV3IEN1c3RvbUV2ZW50KHJlbW90ZUV2ZW50Lm5hbWUsIHtcbiAgICAgIGJ1YmJsZXMsXG4gICAgICBkZXRhaWw6IHsgLi4ucmVtb3RlRXZlbnQucGFyYW1zLCBjb25uZWN0aW9uSWQgfSxcbiAgICB9KTtcblxuICAgIC8vIERpc3BhdGNoIHRoZSBldmVudCB2aWEgSmF2YVNjcmlwdC5cbiAgICByZWFsRWxlbWVudC5kaXNwYXRjaEV2ZW50KHJlbW90ZUV2ZW50T2JqZWN0KTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgLy8gVE9ETyAtIGhhbmRsZSBkaXNwb3NlXG4gICAgY29uc29sZS5sb2coXCJXZWJCcm93c2VyRE9NUnVubmVyLmRpc3Bvc2VcIik7XG4gIH1cblxuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudCB7XG4gICAgcmV0dXJuIGRvY3VtZW50O1xuICB9XG5cbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlciB7XG4gICAgaWYgKGRvY3VtZW50LnRpbWVsaW5lICYmIGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lKSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUgYXMgbnVtYmVyO1xuICAgIH1cbiAgICByZXR1cm4gRGF0ZS5ub3coKSAtIGRvY3VtZW50TG9hZFRpbWU7XG4gIH1cblxuICAvLyBUT0RPIC0gcmVzb2x2ZSB0eXBlcyAoV2luZG93IG5lZWRzIHRvIGV4cG9zZSBjbGFzc2VzIHN1Y2ggYXMgQ3VzdG9tRXZlbnQgYXMgcHJvcGVydGllcylcbiAgZ2V0V2luZG93KCk6IGFueSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfVxufVxuIiwgImltcG9ydCB7IE9ic2VydmFibGVET00gfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTVwiO1xuaW1wb3J0IHtcbiAgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gIERPTV9NRVNTQUdFX1RZUEUsXG4gIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5IH0gZnJvbSBcIi4vV2ViQnJvd3NlckRPTVJ1bm5lclwiO1xuXG4vLyBUaGlzIHJ1bnMgaW4gdGhlIGlmcmFtZSB0aGF0IHdpbGwgZXhlY3V0ZSB0aGUgZG9jdW1lbnQgc2NyaXB0IHRvIHNldHVwIHRoZSBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBtZXNzYWdlc1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBzZXR1cElmcmFtZVdlYlJ1bm5lciB9IGZyb20gXCIuL0lmcmFtZVdlYlJ1bm5lclwiO1xuXG5jb25zdCBhcmdzID0gKHdpbmRv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\n';
|
|
33
6
|
|
|
34
7
|
// src/RunnerIframe.ts
|
|
35
8
|
var RunnerIframe = class {
|
|
@@ -90,7 +63,7 @@ var RunnerIframe = class {
|
|
|
90
63
|
};
|
|
91
64
|
|
|
92
65
|
// src/NetworkedDOMWebRunnerClient.ts
|
|
93
|
-
|
|
66
|
+
import { NetworkedDOMWebsocket } from "@mml-io/networked-dom-web";
|
|
94
67
|
|
|
95
68
|
// src/FakeWebsocket.ts
|
|
96
69
|
var WebsocketEnd = class extends EventTarget {
|
|
@@ -178,7 +151,7 @@ var NetworkedDOMWebRunnerClient = class {
|
|
|
178
151
|
return false;
|
|
179
152
|
});
|
|
180
153
|
}
|
|
181
|
-
const domWebsocket = new
|
|
154
|
+
const domWebsocket = new NetworkedDOMWebsocket(
|
|
182
155
|
"ws://localhost",
|
|
183
156
|
() => fakeWebsocket.clientSideWebsocket,
|
|
184
157
|
this.remoteDocumentHolder,
|
|
@@ -197,13 +170,16 @@ var NetworkedDOMWebRunnerClient = class {
|
|
|
197
170
|
};
|
|
198
171
|
|
|
199
172
|
// src/IframeObservableDOMFactory.ts
|
|
200
|
-
|
|
173
|
+
import {
|
|
174
|
+
DOM_MESSAGE_TYPE,
|
|
175
|
+
observableDOMInterfaceToMessageSender
|
|
176
|
+
} from "@mml-io/observable-dom-common";
|
|
201
177
|
var IframeObservableDOMFactory = (observableDOMParameters, callback) => {
|
|
202
178
|
const runnerIframe = new RunnerIframe(
|
|
203
179
|
observableDOMParameters,
|
|
204
180
|
(message) => {
|
|
205
181
|
switch (message.type) {
|
|
206
|
-
case
|
|
182
|
+
case DOM_MESSAGE_TYPE:
|
|
207
183
|
callback(message.message, remoteObservableDOM);
|
|
208
184
|
break;
|
|
209
185
|
default:
|
|
@@ -211,7 +187,7 @@ var IframeObservableDOMFactory = (observableDOMParameters, callback) => {
|
|
|
211
187
|
}
|
|
212
188
|
}
|
|
213
189
|
);
|
|
214
|
-
const remoteObservableDOM =
|
|
190
|
+
const remoteObservableDOM = observableDOMInterfaceToMessageSender(
|
|
215
191
|
(message) => {
|
|
216
192
|
runnerIframe.sendMessageToRunner(message);
|
|
217
193
|
},
|
|
@@ -221,12 +197,10 @@ var IframeObservableDOMFactory = (observableDOMParameters, callback) => {
|
|
|
221
197
|
);
|
|
222
198
|
return remoteObservableDOM;
|
|
223
199
|
};
|
|
224
|
-
|
|
225
|
-
0 && (module.exports = {
|
|
200
|
+
export {
|
|
226
201
|
FakeWebsocket,
|
|
227
202
|
IframeObservableDOMFactory,
|
|
228
203
|
NetworkedDOMWebRunnerClient,
|
|
229
|
-
RunnerIframe
|
|
230
|
-
|
|
231
|
-
});
|
|
204
|
+
RunnerIframe
|
|
205
|
+
};
|
|
232
206
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "runner-iframe-js-text-namespace:/home/runner/work/mml/mml/packages/networked-dom-web-runner/networked-dom-web-runner-iframe/build/index.js", "../src/RunnerIframe.ts", "../src/NetworkedDOMWebRunnerClient.ts", "../src/FakeWebsocket.ts", "../src/IframeObservableDOMFactory.ts"],
|
|
4
|
-
"sourcesContent": ["export * from \"@mml-io/networked-dom-document\";\nexport * from \"./RunnerIframe\";\nexport * from \"./NetworkedDOMWebRunnerClient\";\nexport * from \"./FakeWebsocket\";\nexport * from \"./IframeObservableDOMFactory\";\n", "var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\n\n// ../../observable-dom-common/build/index.js\nvar require_build = __commonJS({\n \"../../observable-dom-common/build/index.js\"(exports, module2) {\n var __defProp2 = Object.defineProperty;\n var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;\n var __getOwnPropNames2 = Object.getOwnPropertyNames;\n var __hasOwnProp2 = Object.prototype.hasOwnProperty;\n var __export = (target, all) => {\n for (var name in all)\n __defProp2(target, name, { get: all[name], enumerable: true });\n };\n var __copyProps2 = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames2(from))\n if (!__hasOwnProp2.call(to, key) && key !== except)\n __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });\n }\n return to;\n };\n var __toCommonJS = (mod) => __copyProps2(__defProp2({}, \"__esModule\", { value: true }), mod);\n var src_exports = {};\n __export(src_exports, {\n ADD_CONNECTED_USER_ID_MESSAGE_TYPE: () => ADD_CONNECTED_USER_ID_MESSAGE_TYPE2,\n DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE: () => DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2,\n DOM_MESSAGE_TYPE: () => DOM_MESSAGE_TYPE2,\n REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE: () => REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2,\n applyMessageToObservableDOMInstance: () => applyMessageToObservableDOMInstance,\n observableDOMInterfaceToMessageSender: () => observableDOMInterfaceToMessageSender\n });\n module2.exports = __toCommonJS(src_exports);\n var ADD_CONNECTED_USER_ID_MESSAGE_TYPE2 = \"addConnectedUserId\";\n var REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2 = \"removeConnectedUserId\";\n var DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2 = \"dispatchRemoteEventFromConnectionId\";\n var DOM_MESSAGE_TYPE2 = \"dom\";\n function applyMessageToObservableDOMInstance(message, instance) {\n if (message.type === ADD_CONNECTED_USER_ID_MESSAGE_TYPE2) {\n instance.addConnectedUserId(message.connectionId);\n } else if (message.type === REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2) {\n instance.removeConnectedUserId(message.connectionId);\n } else if (message.type === DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2) {\n instance.dispatchRemoteEventFromConnectionId(message.connectionId, message.event);\n } else {\n console.error(\"Unknown message type\", message);\n }\n }\n function observableDOMInterfaceToMessageSender(sender, dispose) {\n const remoteObservableDOM = {\n addConnectedUserId(connectionId) {\n sender({\n type: ADD_CONNECTED_USER_ID_MESSAGE_TYPE2,\n connectionId\n });\n },\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n sender({\n type: DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE2,\n connectionId,\n event: remoteEvent\n });\n },\n dispose() {\n dispose();\n },\n removeConnectedUserId(connectionId) {\n sender({\n type: REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE2,\n connectionId\n });\n }\n };\n return remoteObservableDOM;\n }\n }\n});\n\n// ../../observable-dom/src/utils.ts\nfunction virtualDOMElementToStatic(el) {\n return {\n nodeId: el.nodeId,\n tag: el.tag,\n attributes: el.attributes,\n childNodes: el.childNodes.map((child) => virtualDOMElementToStatic(child)),\n textContent: el.textContent\n };\n}\n\n// ../../observable-dom/src/ObservableDOM.ts\nvar ObservableDOM = class {\n constructor(observableDOMParameters, callback, runnerFactory) {\n this.nodeToNodeId = /* @__PURE__ */ new Map();\n this.nodeIdToNode = /* @__PURE__ */ new Map();\n this.realElementToVirtualElement = /* @__PURE__ */ new Map();\n this.ignoreTextNodes = true;\n this.nextNodeId = 1;\n this.htmlPath = observableDOMParameters.htmlPath;\n this.ignoreTextNodes = observableDOMParameters.ignoreTextNodes;\n this.callback = callback;\n this.documentTimeIntervalTimer = setInterval(() => {\n this.callback(\n {\n documentTime: this.getDocumentTime()\n },\n this\n );\n }, observableDOMParameters.pingIntervalMilliseconds || 5e3);\n this.domRunner = runnerFactory(\n observableDOMParameters.htmlPath,\n observableDOMParameters.htmlContents,\n observableDOMParameters.params,\n (domRunnerMessage) => {\n if (domRunnerMessage.loaded) {\n this.createVirtualDOMElementWithChildren(\n this.domRunner.getDocument(),\n null\n );\n const snapshot = virtualDOMElementToStatic(\n this.getVirtualDOMElementForRealElementOrThrow(\n this.domRunner.getDocument()\n )\n );\n this.callback(\n {\n snapshot,\n documentTime: this.getDocumentTime()\n },\n this\n );\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n this.callback(\n {\n logMessage: domRunnerMessage.logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n }\n );\n }\n addConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"connected\", {\n detail: { connectionId }\n })\n );\n }\n removeConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"disconnected\", {\n detail: { connectionId }\n })\n );\n }\n processModificationList(mutationList) {\n const documentEl = this.domRunner.getDocument();\n const documentVirtualDOMElement = this.realElementToVirtualElement.get(documentEl);\n if (!documentVirtualDOMElement) {\n throw new Error(`document not created in processModificationList`);\n }\n if (mutationList.length > 1) {\n }\n for (const mutation of mutationList) {\n if (this.isIgnoredElement(mutation.target)) {\n continue;\n }\n if (mutation.type === \"attributes\" && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.isIgnoredAttribute(mutation.target, mutation.attributeName)) {\n continue;\n }\n this.addKnownNodesInMutation(mutation);\n const firstNonIgnoredPreviousSibling = mutation.previousSibling ? this.getFirstNonIgnoredPreviousSibling(mutation.previousSibling) : null;\n const targetElement = this.getVirtualDOMElementForRealElementOrThrow(\n mutation.target\n );\n const addedNodes = [];\n for (const node of mutation.addedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n addedNodes.push(virtualDOMElementToStatic(virtualDOMElement));\n }\n const removedNodeIds = [];\n for (const node of mutation.removedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n removedNodeIds.push(virtualDOMElement.nodeId);\n }\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: firstNonIgnoredPreviousSibling !== null ? this.getVirtualDOMElementForRealElementOrThrow(firstNonIgnoredPreviousSibling).nodeId : null,\n attribute: mutation.attributeName ? {\n attributeName: mutation.attributeName,\n value: mutation.target.getAttribute(mutation.attributeName)\n } : null\n };\n this.callback(\n {\n mutation: mutationRecord,\n documentTime: this.getDocumentTime()\n },\n this\n );\n this.removeKnownNodesInMutation(mutation);\n }\n }\n addKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error(\n \"Unknown node in addKnownNodesInMutation:\" + targetNode + \",\" + mutation.type\n );\n }\n if (mutation.type === \"childList\") {\n let previousSibling = mutation.previousSibling;\n let index = 0;\n while (previousSibling && this.isIgnoredElement(previousSibling)) {\n previousSibling = previousSibling.previousSibling;\n }\n if (previousSibling) {\n const previousSiblingElement = this.realElementToVirtualElement.get(\n previousSibling\n );\n if (!previousSiblingElement) {\n throw new Error(\"Unknown previous sibling\");\n }\n index = virtualDOMElement.childNodes.indexOf(previousSiblingElement);\n if (index === -1) {\n throw new Error(\"Previous sibling is not currently a child of the parent element\");\n }\n index += 1;\n }\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n virtualDOMElement\n );\n if (childVirtualDOMElement) {\n if (virtualDOMElement.childNodes.indexOf(childVirtualDOMElement) === -1) {\n virtualDOMElement.childNodes.splice(index, 0, childVirtualDOMElement);\n index++;\n }\n }\n });\n } else if (mutation.type === \"attributes\") {\n const attributeName = mutation.attributeName;\n if (this.isIgnoredAttribute(targetNode, attributeName)) {\n return;\n }\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete virtualDOMElement.attributes[attributeName];\n } else {\n virtualDOMElement.attributes[attributeName] = attributeValue;\n }\n } else if (mutation.type === \"characterData\") {\n virtualDOMElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n }\n removeKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error(\"Unknown node in mutation list:\" + targetNode + \", \" + mutation.type);\n }\n if (mutation.type === \"childList\") {\n for (const node of mutation.removedNodes) {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n continue;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n console.warn(this.htmlPath, \"Unknown node in removeKnownNodesInMutation\");\n continue;\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n const index = virtualDOMElement.childNodes.indexOf(childDOMElement);\n virtualDOMElement.childNodes.splice(index, 1);\n }\n }\n return;\n }\n }\n removeVirtualDOMElement(virtualDOMElement) {\n this.nodeIdToNode.delete(virtualDOMElement.nodeId);\n this.nodeToNodeId.delete(virtualDOMElement);\n this.realElementToVirtualElement.delete(virtualDOMElement.realElement);\n for (const child of virtualDOMElement.childNodes) {\n this.removeVirtualDOMElement(child);\n }\n }\n createVirtualDOMElementWithChildren(node, parent) {\n const virtualElement = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i];\n const childVirtualElement = this.createVirtualDOMElementWithChildren(\n child,\n virtualElement\n );\n if (childVirtualElement) {\n virtualElement.childNodes.push(childVirtualElement);\n }\n }\n }\n return virtualElement;\n }\n createVirtualDOMElement(node, parent) {\n if (this.isIgnoredElement(node)) {\n return null;\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n throw new Error(\"Node already has a virtual element: \" + node.nodeName);\n }\n if (!node) {\n throw new Error(\"Cannot assign node id to null\");\n }\n const attributes = {};\n if (node.attributes) {\n const asHTMLElement = node;\n for (const key of asHTMLElement.getAttributeNames()) {\n const value = asHTMLElement.getAttribute(key);\n if (value === null) {\n throw new Error(\"Null attribute value for key: \" + key);\n }\n if (!this.isIgnoredAttribute(node, key)) {\n attributes[key] = value;\n }\n }\n }\n const nodeId = this.nextNodeId++;\n const virtualElement = {\n nodeId,\n tag: node.nodeName,\n attributes,\n childNodes: [],\n realElement: node,\n parent\n };\n if (node instanceof this.domRunner.getWindow().Text && node.textContent) {\n virtualElement.textContent = node.textContent;\n }\n this.nodeToNodeId.set(virtualElement, nodeId);\n this.nodeIdToNode.set(nodeId, virtualElement);\n this.realElementToVirtualElement.set(node, virtualElement);\n return virtualElement;\n }\n getFirstNonIgnoredPreviousSibling(node) {\n let currentNode = node;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n while (currentNode && currentNode.previousSibling) {\n currentNode = currentNode.previousSibling;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n }\n return null;\n }\n getVirtualDOMElementForRealElementOrThrow(realElement) {\n const virtualElement = this.realElementToVirtualElement.get(realElement);\n if (!virtualElement) {\n throw new Error(`Virtual element not found for real element`);\n }\n return virtualElement;\n }\n isIgnoredElement(node) {\n if (this.ignoreTextNodes && node instanceof this.domRunner.getWindow().Text) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().HTMLScriptElement) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().Comment) {\n return true;\n }\n return false;\n }\n isIgnoredAttribute(node, attributeName) {\n return attributeName.startsWith(\"on\");\n }\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n const domNode = this.nodeIdToNode.get(remoteEvent.nodeId);\n if (!domNode) {\n console.error(\"Unknown node ID in remote event: \" + remoteEvent.nodeId);\n return;\n }\n if (domNode instanceof this.domRunner.getWindow().Text) {\n console.warn(\"Cannot dispatch remote event to text node\");\n return;\n }\n this.domRunner.dispatchRemoteEventFromConnectionId(\n connectionId,\n domNode.realElement,\n remoteEvent\n );\n }\n dispose() {\n clearInterval(this.documentTimeIntervalTimer);\n this.domRunner.dispose();\n }\n getDocumentTime() {\n return this.domRunner.getDocumentTime();\n }\n};\n\n// src/IframeWebRunner.ts\nvar import_observable_dom_common = __toESM(require_build());\n\n// src/WebBrowserDOMRunner.ts\nvar WebBrowserDOMRunnerFactory = (htmlPath, htmlContents, params, callback) => {\n return new WebBrowserDOMRunner(htmlPath, htmlContents, params, callback);\n};\nvar documentLoadTime = Date.now();\nvar WebBrowserDOMRunner = class {\n constructor(htmlPath, htmlContents, params, callback) {\n this.htmlPath = htmlPath;\n this.callback = callback;\n for (const level of [\"error\", \"warn\", \"info\", \"log\"]) {\n const defaultFn = window.console[level];\n window.console[level] = (...args2) => {\n callback({\n logMessage: {\n level,\n content: args2\n }\n });\n defaultFn(...args2);\n };\n }\n window.onerror = (message, source, line, column, error) => {\n callback({\n logMessage: {\n level: \"system\",\n content: [\n {\n message,\n type: error?.name,\n line,\n column\n }\n ]\n }\n });\n return false;\n };\n let didSendLoad = false;\n this.mutationObserver = new window.MutationObserver((mutationList) => {\n if (!document) {\n return;\n }\n if (!didSendLoad) {\n throw new Error(\"MutationObserver called before load\");\n }\n this.callback({\n mutationList\n });\n });\n window.params = params;\n const finishLoad = () => {\n if (didSendLoad) {\n throw new Error(\"finishLoad called twice\");\n }\n didSendLoad = true;\n this.callback({\n loaded: true\n });\n this.mutationObserver.observe(window.document, {\n attributes: true,\n childList: true,\n subtree: true,\n characterData: true\n });\n };\n if (document.body) {\n setTimeout(finishLoad, 0);\n } else {\n window.addEventListener(\"DOMContentLoaded\", finishLoad);\n }\n }\n dispatchRemoteEventFromConnectionId(connectionId, realElement, remoteEvent) {\n const bubbles = remoteEvent.bubbles || false;\n const remoteEventObject = new CustomEvent(remoteEvent.name, {\n bubbles,\n detail: { ...remoteEvent.params, connectionId }\n });\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log(\"WebBrowserDOMRunner.dispose\");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n if (document.timeline && document.timeline.currentTime) {\n return document.timeline.currentTime;\n }\n return Date.now() - documentLoadTime;\n }\n // TODO - resolve types (Window needs to expose classes such as CustomEvent as properties)\n getWindow() {\n return window;\n }\n};\n\n// src/IframeWebRunner.ts\nfunction setupIframeWebRunner(argsString) {\n const observableDOMParams = JSON.parse(atob(argsString));\n const sendMessageToHandler = (message) => {\n window.parent.postMessage(JSON.stringify(message), \"*\");\n };\n const observableDOM = new ObservableDOM(\n {\n ...observableDOMParams,\n htmlContents: \"\"\n // This must be empty as the contents are assumed to be provided by the srcdoc\n },\n (observableDOMMessage) => {\n sendMessageToHandler({\n type: import_observable_dom_common.DOM_MESSAGE_TYPE,\n message: observableDOMMessage\n });\n },\n WebBrowserDOMRunnerFactory\n );\n window.addEventListener(\"message\", (e) => {\n const parsed = JSON.parse(e.data);\n switch (parsed.type) {\n case import_observable_dom_common.DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE:\n observableDOM.dispatchRemoteEventFromConnectionId(parsed.connectionId, parsed.event);\n break;\n case import_observable_dom_common.ADD_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.addConnectedUserId(parsed.connectionId);\n break;\n case import_observable_dom_common.REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.removeConnectedUserId(parsed.connectionId);\n break;\n default:\n console.error(\"Unknown message type\", parsed);\n }\n });\n}\n\n// src/index.ts\nvar args = window.args;\nsetupIframeWebRunner(args);\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20tY29tbW9uL3NyYy9pbmRleC50cyIsICIuLi8uLi8uLi9vYnNlcnZhYmxlLWRvbS1jb21tb24vc3JjL21lc3NhZ2VzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy91dGlscy50cyIsICIuLi8uLi8uLi9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTS50cyIsICIuLi9zcmMvSWZyYW1lV2ViUnVubmVyLnRzIiwgIi4uL3NyYy9XZWJCcm93c2VyRE9NUnVubmVyLnRzIiwgIi4uL3NyYy9pbmRleC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0IHR5cGUgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcblxuZXhwb3J0ICogZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbWVzc2FnZXNcIjtcbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZURPTUludGVyZmFjZSwgT2JzZXJ2YWJsZURPTU1lc3NhZ2UgfSBmcm9tIFwiLi9PYnNlcnZhYmxlRE9NSW50ZXJmYWNlXCI7XG5cbmV4cG9ydCBjb25zdCBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFID0gXCJhZGRDb25uZWN0ZWRVc2VySWRcIjtcbmV4cG9ydCBjb25zdCBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFID0gXCJyZW1vdmVDb25uZWN0ZWRVc2VySWRcIjtcbmV4cG9ydCBjb25zdCBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSA9XG4gIFwiZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRcIjtcbmV4cG9ydCBjb25zdCBET01fTUVTU0FHRV9UWVBFID0gXCJkb21cIjtcblxuZXhwb3J0IHR5cGUgQWRkQ29ubmVjdGVkVXNlcklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgRGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xuICBldmVudDogUmVtb3RlRXZlbnQ7XG59O1xuXG5leHBvcnQgdHlwZSBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UgPVxuICB8IEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2VcbiAgfCBSZW1vdmVDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgRGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRNZXNzYWdlO1xuXG50eXBlIERPTU1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBET01fTUVTU0FHRV9UWVBFO1xuICBtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZTtcbn07XG5cbmV4cG9ydCB0eXBlIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID0gRE9NTWVzc2FnZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5TWVzc2FnZVRvT2JzZXJ2YWJsZURPTUluc3RhbmNlKFxuICBtZXNzYWdlOiBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG4gIGluc3RhbmNlOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuKSB7XG4gIGlmIChtZXNzYWdlLnR5cGUgPT09IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5hZGRDb25uZWN0ZWRVc2VySWQobWVzc2FnZS5jb25uZWN0aW9uSWQpO1xuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLnJlbW92ZUNvbm5lY3RlZFVzZXJJZChtZXNzYWdlLmNvbm5lY3Rpb25JZCk7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLmRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKG1lc3NhZ2UuY29ubmVjdGlvbklkLCBtZXNzYWdlLmV2ZW50KTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBtZXNzYWdlIHR5cGVcIiwgbWVzc2FnZSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9ic2VydmFibGVET01JbnRlcmZhY2VUb01lc3NhZ2VTZW5kZXIoXG4gIHNlbmRlcjogKG1lc3NhZ2U6IFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4gdm9pZCxcbiAgZGlzcG9zZTogKCkgPT4gdm9pZCxcbikge1xuICBjb25zdCByZW1vdGVPYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlID0ge1xuICAgIGFkZENvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChjb25uZWN0aW9uSWQ6IG51bWJlciwgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50KTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgICBldmVudDogcmVtb3RlRXZlbnQsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgICBkaXNwb3NlKCk7XG4gICAgfSxcbiAgICByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG4gIHJldHVybiByZW1vdGVPYnNlcnZhYmxlRE9NO1xufVxuIiwgImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSB2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKFxuICAgICAgICAgICAgdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzbmFwc2hvdCxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGxvZ01lc3NhZ2U6IGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGFkZENvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImNvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQgfSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiZGlzY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QobXV0YXRpb25MaXN0OiBBcnJheTxNdXRhdGlvblJlY29yZD4pOiB2b2lkIHtcbiAgICBjb25zdCBkb2N1bWVudEVsID0gdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQ7XG4gICAgY29uc3QgZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChkb2N1bWVudEVsKTtcbiAgICBpZiAoIWRvY3VtZW50VmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZG9jdW1lbnQgbm90IGNyZWF0ZWQgaW4gcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3RgKTtcbiAgICB9XG5cbiAgICBpZiAobXV0YXRpb25MaXN0Lmxlbmd0aCA+IDEpIHtcbiAgICAgIC8vIFRPRE8gKGh0dHBzOi8vZ2l0aHViLmNvbS9tbWwtaW8vbW1sL2lzc3Vlcy8xMDApIC0gd2FsayBiYWNrIHRocm91Z2ggdGhlIHJlY29yZHMgdG8gZGVyaXZlIHRoZSBpbnRlcm1lZGlhdGVcbiAgICAgIC8vICBzdGF0ZXMgKGUuZy4gaWYgYW4gYXR0cmlidXRlIGlzIGxhdGVyIGFkZGVkIHRvIGFuIGVsZW1lbnQgY3JlYXRlZCBpbiBhbiBlYXJsaWVyIHJlY29yZCB0aGVuIGl0IHNob3VsZCBub3RcbiAgICAgIC8vICBoYXZlIHRoYXQgYXR0cmlidXRlIHdoZW4gdGhlIGVsZW1lbnQgaXMgYWRkZWQuIFRoaXMgaXMgaW1wb3J0YW50IGFzIGluY29ycmVjdCBhdHRyaWJ1dGUgc2V0cyBjYW4gYWZmZWN0XG4gICAgICAvLyAgdmlzaWJpbGl0eSBhbmQgZXhwZWN0ZWQgY2xpZW50IHBlcmZvcm1hbmNlLlxuICAgIH1cblxuICAgIGZvciAoY29uc3QgbXV0YXRpb24gb2YgbXV0YXRpb25MaXN0KSB7XG4gICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgbXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIgJiZcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0LCBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lISlcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hZGRLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbik7XG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcbiAgICAgIGNvbnN0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZ1xuICAgICAgICA/IHRoaXMuZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG11dGF0aW9uLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dClcbiAgICAgICAgOiBudWxsO1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgIG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICk7XG4gICAgICBjb25zdCBhZGRlZE5vZGVzOiBBcnJheTxTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudD4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5hZGRlZE5vZGVzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2aXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgbm9kZSBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgKTtcbiAgICAgICAgYWRkZWROb2Rlcy5wdXNoKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWModmlydHVhbERPTUVsZW1lbnQpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5yZW1vdmVkTm9kZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChub2RlIGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICBub2RlIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG11dGF0aW9uUmVjb3JkOiBTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQgPSB7XG4gICAgICAgIHR5cGU6IG11dGF0aW9uLnR5cGUsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgYWRkZWROb2RlcyxcbiAgICAgICAgcmVtb3ZlZE5vZGVJZHMsXG4gICAgICAgIHByZXZpb3VzU2libGluZ0lkOlxuICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyAhPT0gbnVsbFxuICAgICAgICAgICAgPyB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZykubm9kZUlkXG4gICAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuXG4gICAgICB0aGlzLnJlbW92ZUtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZEtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uOiBNdXRhdGlvblJlY29yZCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldE5vZGUgPSBtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgY29uc3QgdmlydHVhbERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQodGFyZ2V0Tm9kZSk7XG4gICAgaWYgKCF2aXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlVua25vd24gbm9kZSBpbiBhZGRLbm93bk5vZGVzSW5NdXRhdGlvbjpcIiArIHRhcmdldE5vZGUgKyBcIixcIiArIG11dGF0aW9uLnR5cGUsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgbGV0IHByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZztcbiAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICB3aGlsZSAocHJldmlvdXNTaWJsaW5nICYmIHRoaXMuaXNJZ25vcmVkRWxlbWVudChwcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQpKSB7XG4gICAgICAgIHByZXZpb3VzU2libGluZyA9IHByZXZpb3VzU2libGluZy5wcmV2aW91c1NpYmxpbmc7XG4gICAgICB9XG4gICAgICBpZiAocHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZ0VsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoXG4gICAgICAgICAgcHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHByZXZpb3VzIHNpYmxpbmdcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSB2aXJ0dWFsRE9NRWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YocHJldmlvdXNTaWJsaW5nRWxlbWVudCk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcmV2aW91cyBzaWJsaW5nIGlzIG5vdCBjdXJyZW50bHkgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICBhc0VsZW1lbnRPclRleHQsXG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgaWYgKHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihjaGlsZFZpcnR1YWxET01FbGVtZW50KSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluZGV4LCAwLCBjaGlsZFZpcnR1YWxET01FbGVtZW50KTtcbiAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKHRhcmdldE5vZGUsIGF0dHJpYnV0ZU5hbWUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZVZhbHVlID0gKHRhcmdldE5vZGUgYXMgRWxlbWVudCkuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIGRlbGV0ZSB2aXJ0dWFsRE9NRWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGFyYWN0ZXJEYXRhXCIpIHtcbiAgICAgIHZpcnR1YWxET01FbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbjogTXV0YXRpb25SZWNvcmQpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KHRhcmdldE5vZGUpO1xuICAgIGlmICghdmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gbm9kZSBpbiBtdXRhdGlvbiBsaXN0OlwiICsgdGFyZ2V0Tm9kZSArIFwiLCBcIiArIG11dGF0aW9uLnR5cGUpO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgZm9yIChjb25zdCBub2RlIG9mIG11dGF0aW9uLnJlbW92ZWROb2Rlcykge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KGFzRWxlbWVudE9yVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoYXNFbGVtZW50T3JUZXh0KTtcbiAgICAgICAgaWYgKCFjaGlsZERPTUVsZW1lbnQpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4odGhpcy5odG1sUGF0aCwgXCJVbmtub3duIG5vZGUgaW4gcmVtb3ZlS25vd25Ob2Rlc0luTXV0YXRpb25cIik7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVWaXJ0dWFsRE9NRWxlbWVudCh2aXJ0dWFsRE9NRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQucmVhbEVsZW1lbnQpO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcykge1xuICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChub2RlLCBwYXJlbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgY2hpbGQgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxFbGVtZW50KSB7XG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQuY2hpbGROb2Rlcy5wdXNoKGNoaWxkVmlydHVhbEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KG5vZGUpO1xuICAgIGlmIChleGlzdGluZ1ZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vZGUgYWxyZWFkeSBoYXMgYSB2aXJ0dWFsIGVsZW1lbnQ6IFwiICsgbm9kZS5ub2RlTmFtZSk7XG4gICAgfVxuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFzc2lnbiBub2RlIGlkIHRvIG51bGxcIik7XG4gICAgfVxuXG4gICAgY29uc3QgYXR0cmlidXRlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGlmICgobm9kZSBhcyBhbnkpLmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IGFzSFRNTEVsZW1lbnQgPSBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGVOYW1lcygpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVsbCBhdHRyaWJ1dGUgdmFsdWUgZm9yIGtleTogXCIgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobm9kZSwga2V5KSkge1xuICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUlkID0gdGhpcy5uZXh0Tm9kZUlkKys7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IHtcbiAgICAgIG5vZGVJZCxcbiAgICAgIHRhZzogbm9kZS5ub2RlTmFtZSxcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBjaGlsZE5vZGVzOiBbXSxcbiAgICAgIHJlYWxFbGVtZW50OiBub2RlLFxuICAgICAgcGFyZW50LFxuICAgIH07XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0ICYmIG5vZGUudGV4dENvbnRlbnQpIHtcbiAgICAgIHZpcnR1YWxFbGVtZW50LnRleHRDb250ZW50ID0gbm9kZS50ZXh0Q29udGVudDtcbiAgICB9XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuc2V0KHZpcnR1YWxFbGVtZW50LCBub2RlSWQpO1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLnNldChub2RlSWQsIHZpcnR1YWxFbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5zZXQobm9kZSwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogRWxlbWVudCB8IFRleHQgfCBudWxsIHtcbiAgICBsZXQgY3VycmVudE5vZGUgPSBub2RlO1xuICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgcmV0dXJuIGN1cnJlbnROb2RlO1xuICAgIH1cbiAgICB3aGlsZSAoY3VycmVudE5vZGUgJiYgY3VycmVudE5vZGUucHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgICByZXR1cm4gY3VycmVudE5vZGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBkb21Ob2RlID0gdGhpcy5ub2RlSWRUb05vZGUuZ2V0KHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBub2RlIElEIGluIHJlbW90ZSBldmVudDogXCIgKyByZW1vdGVFdmVudC5ub2RlSWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkb21Ob2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgY29uc29sZS53YXJuKFwiQ2Fubm90IGRpc3BhdGNoIHJlbW90ZSBldmVudCB0byB0ZXh0IG5vZGVcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgICBjb25uZWN0aW9uSWQsXG4gICAgICBkb21Ob2RlLnJlYWxFbGVtZW50IGFzIEVsZW1lbnQsXG4gICAgICByZW1vdGVFdmVudCxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGRpc3Bvc2UoKSB7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIpO1xuICAgIHRoaXMuZG9tUnVubmVyLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RG9jdW1lbnRUaW1lKCkge1xuICAgIHJldHVybiB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudFRpbWUoKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IE9ic2VydmFibGVET00gfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTVwiO1xuaW1wb3J0IHtcbiAgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gIERPTV9NRVNTQUdFX1RZUEUsXG4gIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5IH0gZnJvbSBcIi4vV2ViQnJvd3NlckRPTVJ1bm5lclwiO1xuXG4vLyBUaGlzIHJ1bnMgaW4gdGhlIGlmcmFtZSB0aGF0IHdpbGwgZXhlY3V0ZSB0aGUgZG9jdW1lbnQgc2NyaXB0IHRvIHNldHVwIHRoZSBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBtZXNzYWdlc1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcbmltcG9ydCB7IERPTVJ1bm5lckZhY3RvcnksIERPTVJ1bm5lckludGVyZmFjZSwgRE9NUnVubmVyTWVzc2FnZSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihodG1sUGF0aCwgaHRtbENvbnRlbnRzLCBwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmNvbnN0IGRvY3VtZW50TG9hZFRpbWUgPSBEYXRlLm5vdygpO1xuXG5leHBvcnQgY2xhc3MgV2ViQnJvd3NlckRPTVJ1bm5lciBpbXBsZW1lbnRzIERPTVJ1bm5lckludGVyZmFjZSB7XG4gIHByaXZhdGUgbXV0YXRpb25PYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlcjtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBodG1sUGF0aDogc3RyaW5nLFxuICAgIGh0bWxDb250ZW50czogc3RyaW5nLFxuICAgIHBhcmFtczogb2JqZWN0LFxuICAgIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IGh0bWxQYXRoO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIC8vIEZvcndhcmQgY29uc29sZSBtZXNzYWdlc1xuICAgIGZvciAoY29uc3QgbGV2ZWwgb2YgW1wiZXJyb3JcIiwgXCJ3YXJuXCIsIFwiaW5mb1wiLCBcImxvZ1wiXSBhcyBjb25zdCkge1xuICAgICAgY29uc3QgZGVmYXVsdEZuID0gd2luZG93LmNvbnNvbGVbbGV2ZWxdO1xuXG4gICAgICB3aW5kb3cuY29uc29sZVtsZXZlbF0gPSAoLi4uYXJncykgPT4ge1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgICAgbGV2ZWwsXG4gICAgICAgICAgICBjb250ZW50OiBhcmdzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBkZWZhdWx0Rm4oLi4uYXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZvcndhcmQgdW5jYXVnaHQgZXJyb3JzXG4gICAgd2luZG93Lm9uZXJyb3IgPSAobWVzc2FnZSwgc291cmNlLCBsaW5lLCBjb2x1bW4sIGVycm9yKSA9PiB7XG4gICAgICBjYWxsYmFjayh7XG4gICAgICAgIGxvZ01lc3NhZ2U6IHtcbiAgICAgICAgICBsZXZlbDogXCJzeXN0ZW1cIixcbiAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgIHR5cGU6IGVycm9yPy5uYW1lLFxuICAgICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgICBjb2x1bW4sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgbGV0IGRpZFNlbmRMb2FkID0gZmFsc2U7XG5cbiAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIgPSBuZXcgd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9uTGlzdCkgPT4ge1xuICAgICAgaWYgKCFkb2N1bWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWRpZFNlbmRMb2FkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk11dGF0aW9uT2JzZXJ2ZXIgY2FsbGVkIGJlZm9yZSBsb2FkXCIpO1xuICAgICAgfVxuICAgICAgdGhpcy5jYWxsYmFjayh7XG4gICAgICAgIG11dGF0aW9uTGlzdCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgKHdpbmRvdyBhcyBhbnkpLnBhcmFtcyA9IHBhcmFtcztcblxuICAgIGNvbnN0IGZpbmlzaExvYWQgPSAoKSA9PiB7XG4gICAgICBpZiAoZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmluaXNoTG9hZCBjYWxsZWQgdHdpY2VcIik7XG4gICAgICB9XG4gICAgICBkaWRTZW5kTG9hZCA9IHRydWU7XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbG9hZGVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIub2JzZXJ2ZSh3aW5kb3cuZG9jdW1lbnQsIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfTtcbiAgICBpZiAoZG9jdW1lbnQuYm9keSkge1xuICAgICAgc2V0VGltZW91dChmaW5pc2hMb2FkLCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGZpbmlzaExvYWQpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgYnViYmxlcyA9IHJlbW90ZUV2ZW50LmJ1YmJsZXMgfHwgZmFsc2U7XG4gICAgY29uc3QgcmVtb3RlRXZlbnRPYmplY3QgPSBuZXcgQ3VzdG9tRXZlbnQocmVtb3RlRXZlbnQubmFtZSwge1xuICAgICAgYnViYmxlcyxcbiAgICAgIGRldGFpbDogeyAuLi5yZW1vdGVFdmVudC5wYXJhbXMsIGNvbm5lY3Rpb25JZCB9LFxuICAgIH0pO1xuXG4gICAgLy8gRGlzcGF0Y2ggdGhlIGV2ZW50IHZpYSBKYXZhU2NyaXB0LlxuICAgIHJlYWxFbGVtZW50LmRpc3BhdGNoRXZlbnQocmVtb3RlRXZlbnRPYmplY3QpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAvLyBUT0RPIC0gaGFuZGxlIGRpc3Bvc2VcbiAgICBjb25zb2xlLmxvZyhcIldlYkJyb3dzZXJET01SdW5uZXIuZGlzcG9zZVwiKTtcbiAgfVxuXG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50IHtcbiAgICByZXR1cm4gZG9jdW1lbnQ7XG4gIH1cblxuICBnZXREb2N1bWVudFRpbWUoKTogbnVtYmVyIHtcbiAgICBpZiAoZG9jdW1lbnQudGltZWxpbmUgJiYgZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXI7XG4gICAgfVxuICAgIHJldHVybiBEYXRlLm5vdygpIC0gZG9jdW1lbnRMb2FkVGltZTtcbiAgfVxuXG4gIC8vIFRPRE8gLSByZXNvbHZlIHR5cGVzIChXaW5kb3cgbmVlZHMgdG8gZXhwb3NlIGNsYXNzZXMgc3VjaCBhcyBDdXN0b21FdmVudCBhcyBwcm9wZXJ0aWVzKVxuICBnZXRXaW5kb3coKTogYW55IHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9XG59XG4iLCAiaW1wb3J0IHsgc2V0dXBJZnJhbWVXZWJSdW5uZXIgfSBmcm9tIFwiLi9JZnJhbWVXZWJSdW5uZXJcIjtcblxuY29uc3QgYXJncyA9ICh3aW5kb3cgYXMgYW55KS5hcmdzO1xuc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJncyk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsUUFBQSxjQUFBLENBQUE7QUFBQSxhQUFBLGFBQUE7TUFBQSxvQ0FBQSxNQUFBQTtNQUFBLHVEQUFBLE1BQUFDO01BQUEsa0JBQUEsTUFBQUM7TUFBQSx1Q0FBQSxNQUFBQztNQUFBLHFDQUFBLE1BQUE7TUFBQSx1Q0FBQSxNQUFBO0lBQUEsQ0FBQTtBQUFBLElBQUFDLFFBQUEsVUFBQSxhQUFBLFdBQUE7QUNJTyxRQUFNSixzQ0FBcUM7QUFDM0MsUUFBTUcseUNBQXdDO0FBQzlDLFFBQU1GLHlEQUNYO0FBQ0ssUUFBTUMsb0JBQW1CO0FBOEJ6QixhQUFTLG9DQUNkLFNBQ0EsVUFDQTtBQUNBLFVBQUksUUFBUSxTQUFTRixxQ0FBb0M7QUFDdkQsaUJBQVMsbUJBQW1CLFFBQVEsWUFBWTtNQUNsRCxXQUFXLFFBQVEsU0FBU0csd0NBQXVDO0FBQ2pFLGlCQUFTLHNCQUFzQixRQUFRLFlBQVk7TUFDckQsV0FBVyxRQUFRLFNBQVNGLHdEQUF1RDtBQUNqRixpQkFBUyxvQ0FBb0MsUUFBUSxjQUFjLFFBQVEsS0FBSztNQUNsRixPQUFPO0FBQ0wsZ0JBQVEsTUFBTSx3QkFBd0IsT0FBTztNQUMvQztJQUNGO0FBRU8sYUFBUyxzQ0FDZCxRQUNBLFNBQ0E7QUFDQSxZQUFNLHNCQUE4QztRQUNsRCxtQkFBbUIsY0FBNEI7QUFDN0MsaUJBQU87WUFDTCxNQUFNRDtZQUNOO1VBQ0YsQ0FBQztRQUNIO1FBQ0Esb0NBQW9DLGNBQXNCLGFBQWdDO0FBQ3hGLGlCQUFPO1lBQ0wsTUFBTUM7WUFDTjtZQUNBLE9BQU87VUFDVCxDQUFDO1FBQ0g7UUFDQSxVQUFnQjtBQUNkLGtCQUFRO1FBQ1Y7UUFDQSxzQkFBc0IsY0FBNEI7QUFDaEQsaUJBQU87WUFDTCxNQUFNRTtZQUNOO1VBQ0YsQ0FBQztRQUNIO01BQ0Y7QUFDQSxhQUFPO0lBQ1Q7Ozs7O0FDOUVPLFNBQVMsMEJBQTBCLElBQW9EO0FBQzVGLFNBQU87QUFBQSxJQUNMLFFBQVEsR0FBRztBQUFBLElBQ1gsS0FBSyxHQUFHO0FBQUEsSUFDUixZQUFZLEdBQUc7QUFBQSxJQUNmLFlBQVksR0FBRyxXQUFXLElBQUksQ0FBQyxVQUFVLDBCQUEwQixLQUFLLENBQUM7QUFBQSxJQUN6RSxhQUFhLEdBQUc7QUFBQSxFQUNsQjtBQUNGOzs7QUNvQ08sSUFBTSxnQkFBTixNQUFzRDtBQUFBLEVBWTNELFlBQ0UseUJBQ0EsVUFDQSxlQUNBO0FBZkYsU0FBUSxlQUFlLG9CQUFJLElBQW1DO0FBQzlELFNBQVEsZUFBZSxvQkFBSSxJQUFtQztBQUM5RCxTQUFRLDhCQUE4QixvQkFBSSxJQUEyQztBQUNyRixTQUFRLGtCQUFrQjtBQUUxQixTQUFRLGFBQWE7QUFXbkIsU0FBSyxXQUFXLHdCQUF3QjtBQUN4QyxTQUFLLGtCQUFrQix3QkFBd0I7QUFDL0MsU0FBSyxXQUFXO0FBRWhCLFNBQUssNEJBQTRCLFlBQVksTUFBTTtBQUNqRCxXQUFLO0FBQUEsUUFDSDtBQUFBLFVBQ0UsY0FBYyxLQUFLLGdCQUFnQjtBQUFBLFFBQ3JDO0FBQUEsUUFDQTtBQUFBLE1BQ0Y7QUFBQSxJQUNGLEdBQUcsd0JBQXdCLDRCQUE0QixHQUFJO0FBRTNELFNBQUssWUFBWTtBQUFBLE1BQ2Ysd0JBQXdCO0FBQUEsTUFDeEIsd0JBQXdCO0FBQUEsTUFDeEIsd0JBQXdCO0FBQUEsTUFDeEIsQ0FBQyxxQkFBdUM7QUFDdEMsWUFBSSxpQkFBaUIsUUFBUTtBQUMzQixlQUFLO0FBQUEsWUFDSCxLQUFLLFVBQVUsWUFBWTtBQUFBLFlBQzNCO0FBQUEsVUFDRjtBQUVBLGdCQUFNLFdBQVc7QUFBQSxZQUNmLEtBQUs7QUFBQSxjQUNILEtBQUssVUFBVSxZQUFZO0FBQUEsWUFDN0I7QUFBQSxVQUNGO0FBRUEsZUFBSztBQUFBLFlBQ0g7QUFBQSxjQUNFO0FBQUEsY0FDQSxjQUFjLEtBQUssZ0JBQWdCO0FBQUEsWUFDckM7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFFBQ0YsV0FBVyxpQkFBaUIsY0FBYztBQUN4QyxlQUFLLHdCQUF3QixpQkFBaUIsWUFBWTtBQUFBLFFBQzVELFdBQVcsaUJBQWlCLFlBQVk7QUFDdEMsZUFBSztBQUFBLFlBQ0g7QUFBQSxjQUNFLFlBQVksaUJBQWlCO0FBQUEsY0FDN0IsY0FBYyxLQUFLLGdCQUFnQjtBQUFBLFlBQ3JDO0FBQUEsWUFDQTtBQUFBLFVBQ0Y7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFFTyxtQkFBbUIsY0FBNEI7QUFDcEQsU0FBSyxVQUFVLFVBQVUsRUFBRTtBQUFBLE1BQ3pCLEtBQUssS0FBSyxVQUFVLFVBQVUsR0FBRSxZQUFhLGFBQWE7QUFBQSxRQUN4RCxRQUFRLEVBQUUsYUFBYTtBQUFBLE1BQ3pCLENBQUM7QUFBQSxJQUNIO0FBQUEsRUFDRjtBQUFBLEVBRU8sc0JBQXNCLGNBQTRCO0FBQ3ZELFNBQUssVUFBVSxVQUFVLEVBQUU7QUFBQSxNQUN6QixLQUFLLEtBQUssVUFBVSxVQUFVLEdBQUUsWUFBYSxnQkFBZ0I7QUFBQSxRQUMzRCxRQUFRLEVBQUUsYUFBYTtBQUFBLE1BQ3pCLENBQUM7QUFBQSxJQUNIO0FBQUEsRUFDRjtBQUFBLEVBRVEsd0JBQXdCLGNBQTJDO0FBQ3pFLFVBQU0sYUFBYSxLQUFLLFVBQVUsWUFBWTtBQUM5QyxVQUFNLDRCQUE0QixLQUFLLDRCQUE0QixJQUFJLFVBQVU7QUFDakYsUUFBSSxDQUFDLDJCQUEyQjtBQUM5QixZQUFNLElBQUksTUFBTSxpREFBaUQ7QUFBQSxJQUNuRTtBQUVBLFFBQUksYUFBYSxTQUFTLEdBQUc7QUFBQSxJQUs3QjtBQUVBLGVBQVcsWUFBWSxjQUFjO0FBQ25DLFVBQUksS0FBSyxpQkFBaUIsU0FBUyxNQUF3QixHQUFHO0FBQzVEO0FBQUEsTUFDRjtBQUVBLFVBQ0UsU0FBUyxTQUFTO0FBQUEsTUFFbEIsS0FBSyxtQkFBbUIsU0FBUyxRQUEwQixTQUFTLGFBQWMsR0FDbEY7QUFDQTtBQUFBLE1BQ0Y7QUFFQSxXQUFLLHdCQUF3QixRQUFRO0FBS3JDLFlBQU0saUNBQWlDLFNBQVMsa0JBQzVDLEtBQUssa0NBQWtDLFNBQVMsZUFBaUMsSUFDakY7QUFDSixZQUFNLGdCQUFnQixLQUFLO0FBQUEsUUFDekIsU0FBUztBQUFBLE1BQ1g7QUFDQSxZQUFNLGFBQTZDLENBQUM7QUFDcEQsaUJBQVcsUUFBUSxTQUFTLFlBQVk7QUFDdEMsWUFBSSxLQUFLLGlCQUFpQixJQUFzQixHQUFHO0FBQ2pEO0FBQUEsUUFDRjtBQUNBLGNBQU0sb0JBQW9CLEtBQUs7QUFBQSxVQUM3QjtBQUFBLFFBQ0Y7QUFDQSxtQkFBVyxLQUFLLDBCQUEwQixpQkFBaUIsQ0FBQztBQUFBLE1BQzlEO0FBRUEsWUFBTSxpQkFBZ0MsQ0FBQztBQUN2QyxpQkFBVyxRQUFRLFNBQVMsY0FBYztBQUN4QyxZQUFJLEtBQUssaUJBQWlCLElBQXNCLEdBQUc7QUFDakQ7QUFBQSxRQUNGO0FBQ0EsY0FBTSxvQkFBb0IsS0FBSztBQUFBLFVBQzdCO0FBQUEsUUFDRjtBQUNBLHVCQUFlLEtBQUssa0JBQWtCLE1BQU07QUFBQSxNQUM5QztBQUVBLFlBQU0saUJBQW9EO0FBQUEsUUFDeEQsTUFBTSxTQUFTO0FBQUEsUUFDZixVQUFVLGNBQWM7QUFBQSxRQUN4QjtBQUFBLFFBQ0E7QUFBQSxRQUNBLG1CQUNFLG1DQUFtQyxPQUMvQixLQUFLLDBDQUEwQyw4QkFBOEIsRUFBRSxTQUMvRTtBQUFBLFFBQ04sV0FBVyxTQUFTLGdCQUNoQjtBQUFBLFVBQ0UsZUFBZSxTQUFTO0FBQUEsVUFDeEIsT0FBUSxTQUFTLE9BQW1CLGFBQWEsU0FBUyxhQUFhO0FBQUEsUUFDekUsSUFDQTtBQUFBLE1BQ047QUFFQSxXQUFLO0FBQUEsUUFDSDtBQUFBLFVBQ0UsVUFBVTtBQUFBLFVBQ1YsY0FBYyxLQUFLLGdCQUFnQjtBQUFBLFFBQ3JDO0FBQUEsUUFDQTtBQUFBLE1BQ0Y7QUFFQSxXQUFLLDJCQUEyQixRQUFRO0FBQUEsSUFDMUM7QUFBQSxFQUNGO0FBQUEsRUFFUSx3QkFBd0IsVUFBZ0M7QUFDOUQsVUFBTSxhQUFhLFNBQVM7QUFDNUIsVUFBTSxvQkFBb0IsS0FBSyw0QkFBNEIsSUFBSSxVQUFVO0FBQ3pFLFFBQUksQ0FBQyxtQkFBbUI7QUFDdEIsWUFBTSxJQUFJO0FBQUEsUUFDUiw2Q0FBNkMsYUFBYSxNQUFNLFNBQVM7QUFBQSxNQUMzRTtBQUFBLElBQ0Y7QUFDQSxRQUFJLFNBQVMsU0FBUyxhQUFhO0FBQ2pDLFVBQUksa0JBQWtCLFNBQVM7QUFDL0IsVUFBSSxRQUFRO0FBQ1osYUFBTyxtQkFBbUIsS0FBSyxpQkFBaUIsZUFBaUMsR0FBRztBQUNsRiwwQkFBa0IsZ0JBQWdCO0FBQUEsTUFDcEM7QUFDQSxVQUFJLGlCQUFpQjtBQUNuQixjQUFNLHlCQUF5QixLQUFLLDRCQUE0QjtBQUFBLFVBQzlEO0FBQUEsUUFDRjtBQUNBLFlBQUksQ0FBQyx3QkFBd0I7QUFDM0IsZ0JBQU0sSUFBSSxNQUFNLDBCQUEwQjtBQUFBLFFBQzVDO0FBQ0EsZ0JBQVEsa0JBQWtCLFdBQVcsUUFBUSxzQkFBc0I7QUFDbkUsWUFBSSxVQUFVLElBQUk7QUFDaEIsZ0JBQU0sSUFBSSxNQUFNLGlFQUFpRTtBQUFBLFFBQ25GO0FBQ0EsaUJBQVM7QUFBQSxNQUNYO0FBQ0EsZUFBUyxXQUFXLFFBQVEsQ0FBQyxTQUFlO0FBQzFDLGNBQU0sa0JBQWtCO0FBQ3hCLGNBQU0seUJBQXlCLEtBQUs7QUFBQSxVQUNsQztBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQ0EsWUFBSSx3QkFBd0I7QUFDMUIsY0FBSSxrQkFBa0IsV0FBVyxRQUFRLHNCQUFzQixNQUFNLElBQUk7QUFDdkUsOEJBQWtCLFdBQVcsT0FBTyxPQUFPLEdBQUcsc0JBQXNCO0FBQ3BFO0FBQUEsVUFDRjtBQUFBLFFBQ0Y7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNILFdBQVcsU0FBUyxTQUFTLGNBQWM7QUFFekMsWUFBTSxnQkFBZ0IsU0FBUztBQUMvQixVQUFJLEtBQUssbUJBQW1CLFlBQVksYUFBYSxHQUFHO0FBQ3REO0FBQUEsTUFDRjtBQUNBLFlBQU0saUJBQWtCLFdBQXVCLGFBQWEsYUFBYTtBQUN6RSxVQUFJLG1CQUFtQixNQUFNO0FBQzNCLGVBQU8sa0JBQWtCLFdBQVcsYUFBYTtBQUFBLE1BQ25ELE9BQU87QUFDTCwwQkFBa0IsV0FBVyxhQUFhLElBQUk7QUFBQSxNQUNoRDtBQUFBLElBQ0YsV0FBVyxTQUFTLFNBQVMsaUJBQWlCO0FBQzVDLHdCQUFrQixjQUFjLFdBQVcsY0FBYyxXQUFXLGNBQWM7QUFBQSxJQUNwRjtBQUFBLEVBQ0Y7QUFBQSxFQUVRLDJCQUEyQixVQUFnQztBQUNqRSxVQUFNLGFBQWEsU0FBUztBQUM1QixVQUFNLG9CQUFvQixLQUFLLDRCQUE0QixJQUFJLFVBQVU7QUFDekUsUUFBSSxDQUFDLG1CQUFtQjtBQUN0QixZQUFNLElBQUksTUFBTSxtQ0FBbUMsYUFBYSxPQUFPLFNBQVMsSUFBSTtBQUFBLElBQ3RGO0FBQ0EsUUFBSSxTQUFTLFNBQVMsYUFBYTtBQUNqQyxpQkFBVyxRQUFRLFNBQVMsY0FBYztBQUN4QyxjQUFNLGtCQUFrQjtBQUN4QixZQUFJLEtBQUssaUJBQWlCLGVBQWUsR0FBRztBQUMxQztBQUFBLFFBQ0Y7QUFDQSxjQUFNLGtCQUFrQixLQUFLLDRCQUE0QixJQUFJLGVBQWU7QUFDNUUsWUFBSSxDQUFDLGlCQUFpQjtBQUNwQixrQkFBUSxLQUFLLEtBQUssVUFBVSw0Q0FBNEM7QUFDeEU7QUFBQSxRQUNGLE9BQU87QUFDTCxlQUFLLHdCQUF3QixlQUFlO0FBQzVDLGdCQUFNLFFBQVEsa0JBQWtCLFdBQVcsUUFBUSxlQUFlO0FBQ2xFLDRCQUFrQixXQUFXLE9BQU8sT0FBTyxDQUFDO0FBQUEsUUFDOUM7QUFBQSxNQUNGO0FBQ0E7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUFBLEVBRVEsd0JBQXdCLG1CQUFnRDtBQUM5RSxTQUFLLGFBQWEsT0FBTyxrQkFBa0IsTUFBTTtBQUNqRCxTQUFLLGFBQWEsT0FBTyxpQkFBaUI7QUFDMUMsU0FBSyw0QkFBNEIsT0FBTyxrQkFBa0IsV0FBVztBQUNyRSxlQUFXLFNBQVMsa0JBQWtCLFlBQVk7QUFDaEQsV0FBSyx3QkFBd0IsS0FBSztBQUFBLElBQ3BDO0FBQUEsRUFDRjtBQUFBLEVBRVEsb0NBQ04sTUFDQSxRQUM4QjtBQUM5QixVQUFNLGlCQUFpQixLQUFLLHdCQUF3QixNQUFNLE1BQU07QUFDaEUsUUFBSSxDQUFDLGdCQUFnQjtBQUNuQixhQUFPO0FBQUEsSUFDVDtBQUNBLFFBQUssS0FBaUIsWUFBWTtBQUNoQyxlQUFTLElBQUksR0FBRyxJQUFLLEtBQWlCLFdBQVcsUUFBUSxLQUFLO0FBQzVELGNBQU0sUUFBUyxLQUFpQixXQUFXLENBQUM7QUFDNUMsY0FBTSxzQkFBc0IsS0FBSztBQUFBLFVBQy9CO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFDQSxZQUFJLHFCQUFxQjtBQUN2Qix5QkFBZSxXQUFXLEtBQUssbUJBQW1CO0FBQUEsUUFDcEQ7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUVBLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFUSx3QkFDTixNQUNBLFFBQzhCO0FBQzlCLFFBQUksS0FBSyxpQkFBaUIsSUFBSSxHQUFHO0FBQy9CLGFBQU87QUFBQSxJQUNUO0FBQ0EsVUFBTSxnQkFBZ0IsS0FBSyw0QkFBNEIsSUFBSSxJQUFJO0FBQy9ELFFBQUksa0JBQWtCLFFBQVc7QUFDL0IsWUFBTSxJQUFJLE1BQU0seUNBQXlDLEtBQUssUUFBUTtBQUFBLElBQ3hFO0FBQ0EsUUFBSSxDQUFDLE1BQU07QUFDVCxZQUFNLElBQUksTUFBTSwrQkFBK0I7QUFBQSxJQUNqRDtBQUVBLFVBQU0sYUFBd0MsQ0FBQztBQUMvQyxRQUFLLEtBQWEsWUFBWTtBQUM1QixZQUFNLGdCQUFnQjtBQUN0QixpQkFBVyxPQUFPLGNBQWMsa0JBQWtCLEdBQUc7QUFDbkQsY0FBTSxRQUFRLGNBQWMsYUFBYSxHQUFHO0FBQzVDLFlBQUksVUFBVSxNQUFNO0FBQ2xCLGdCQUFNLElBQUksTUFBTSxtQ0FBbUMsR0FBRztBQUFBLFFBQ3hEO0FBQ0EsWUFBSSxDQUFDLEtBQUssbUJBQW1CLE1BQU0sR0FBRyxHQUFHO0FBQ3ZDLHFCQUFXLEdBQUcsSUFBSTtBQUFBLFFBQ3BCO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFFQSxVQUFNLFNBQVMsS0FBSztBQUNwQixVQUFNLGlCQUF3QztBQUFBLE1BQzVDO0FBQUEsTUFDQSxLQUFLLEtBQUs7QUFBQSxNQUNWO0FBQUEsTUFDQSxZQUFZLENBQUM7QUFBQSxNQUNiLGFBQWE7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUNBLFFBQUksZ0JBQWdCLEtBQUssVUFBVSxVQUFVLEVBQUUsUUFBUSxLQUFLLGFBQWE7QUFDdkUscUJBQWUsY0FBYyxLQUFLO0FBQUEsSUFDcEM7QUFDQSxTQUFLLGFBQWEsSUFBSSxnQkFBZ0IsTUFBTTtBQUM1QyxTQUFLLGFBQWEsSUFBSSxRQUFRLGNBQWM7QUFDNUMsU0FBSyw0QkFBNEIsSUFBSSxNQUFNLGNBQWM7QUFDekQsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVRLGtDQUFrQyxNQUE2QztBQUNyRixRQUFJLGNBQWM7QUFDbEIsUUFBSSxDQUFDLEtBQUssaUJBQWlCLFdBQVcsR0FBRztBQUN2QyxhQUFPO0FBQUEsSUFDVDtBQUNBLFdBQU8sZUFBZSxZQUFZLGlCQUFpQjtBQUNqRCxvQkFBYyxZQUFZO0FBQzFCLFVBQUksQ0FBQyxLQUFLLGlCQUFpQixXQUFXLEdBQUc7QUFDdkMsZUFBTztBQUFBLE1BQ1Q7QUFBQSxJQUNGO0FBQ0EsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVRLDBDQUNOLGFBQ3VCO0FBQ3ZCLFVBQU0saUJBQWlCLEtBQUssNEJBQTRCLElBQUksV0FBVztBQUN2RSxRQUFJLENBQUMsZ0JBQWdCO0FBQ25CLFlBQU0sSUFBSSxNQUFNLDRDQUE0QztBQUFBLElBQzlEO0FBQ0EsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVRLGlCQUFpQixNQUErQjtBQUN0RCxRQUFJLEtBQUssbUJBQW1CLGdCQUFnQixLQUFLLFVBQVUsVUFBVSxFQUFFLE1BQU07QUFDM0UsYUFBTztBQUFBLElBQ1QsV0FBVyxnQkFBZ0IsS0FBSyxVQUFVLFVBQVUsRUFBRSxtQkFBbUI7QUFDdkUsYUFBTztBQUFBLElBQ1QsV0FBVyxnQkFBZ0IsS0FBSyxVQUFVLFVBQVUsRUFBRSxTQUFTO0FBQzdELGFBQU87QUFBQSxJQUNUO0FBQ0EsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVRLG1CQUFtQixNQUFzQixlQUFnQztBQUMvRSxXQUFPLGNBQWMsV0FBVyxJQUFJO0FBQUEsRUFDdEM7QUFBQSxFQUVPLG9DQUFvQyxjQUFzQixhQUFnQztBQUMvRixVQUFNLFVBQVUsS0FBSyxhQUFhLElBQUksWUFBWSxNQUFNO0FBQ3hELFFBQUksQ0FBQyxTQUFTO0FBQ1osY0FBUSxNQUFNLHNDQUFzQyxZQUFZLE1BQU07QUFDdEU7QUFBQSxJQUNGO0FBRUEsUUFBSSxtQkFBbUIsS0FBSyxVQUFVLFVBQVUsRUFBRSxNQUFNO0FBQ3RELGNBQVEsS0FBSywyQ0FBMkM7QUFDeEQ7QUFBQSxJQUNGO0FBRUEsU0FBSyxVQUFVO0FBQUEsTUFDYjtBQUFBLE1BQ0EsUUFBUTtBQUFBLE1BQ1I7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUFBLEVBRU8sVUFBVTtBQUNmLGtCQUFjLEtBQUsseUJBQXlCO0FBQzVDLFNBQUssVUFBVSxRQUFRO0FBQUEsRUFDekI7QUFBQSxFQUVRLGtCQUFrQjtBQUN4QixXQUFPLEtBQUssVUFBVSxnQkFBZ0I7QUFBQSxFQUN4QztBQUNGOzs7QUNsY0EsbUNBU087OztBQ1BBLElBQU0sNkJBQStDLENBQzFELFVBQ0EsY0FDQSxRQUNBLGFBQ3VCO0FBQ3ZCLFNBQU8sSUFBSSxvQkFBb0IsVUFBVSxjQUFjLFFBQVEsUUFBUTtBQUN6RTtBQUVBLElBQU0sbUJBQW1CLEtBQUssSUFBSTtBQUUzQixJQUFNLHNCQUFOLE1BQXdEO0FBQUEsRUFLN0QsWUFDRSxVQUNBLGNBQ0EsUUFDQSxVQUNBO0FBQ0EsU0FBSyxXQUFXO0FBQ2hCLFNBQUssV0FBVztBQUdoQixlQUFXLFNBQVMsQ0FBQyxTQUFTLFFBQVEsUUFBUSxLQUFLLEdBQVk7QUFDN0QsWUFBTSxZQUFZLE9BQU8sUUFBUSxLQUFLO0FBRXRDLGFBQU8sUUFBUSxLQUFLLElBQUksSUFBSUUsVUFBUztBQUNuQyxpQkFBUztBQUFBLFVBQ1AsWUFBWTtBQUFBLFlBQ1Y7QUFBQSxZQUNBLFNBQVNBO0FBQUEsVUFDWDtBQUFBLFFBQ0YsQ0FBQztBQUNELGtCQUFVLEdBQUdBLEtBQUk7QUFBQSxNQUNuQjtBQUFBLElBQ0Y7QUFHQSxXQUFPLFVBQVUsQ0FBQyxTQUFTLFFBQVEsTUFBTSxRQUFRLFVBQVU7QUFDekQsZUFBUztBQUFBLFFBQ1AsWUFBWTtBQUFBLFVBQ1YsT0FBTztBQUFBLFVBQ1AsU0FBUztBQUFBLFlBQ1A7QUFBQSxjQUNFO0FBQUEsY0FDQSxNQUFNLE9BQU87QUFBQSxjQUNiO0FBQUEsY0FDQTtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0YsQ0FBQztBQUNELGFBQU87QUFBQSxJQUNUO0FBRUEsUUFBSSxjQUFjO0FBRWxCLFNBQUssbUJBQW1CLElBQUksT0FBTyxpQkFBaUIsQ0FBQyxpQkFBaUI7QUFDcEUsVUFBSSxDQUFDLFVBQVU7QUFDYjtBQUFBLE1BQ0Y7QUFDQSxVQUFJLENBQUMsYUFBYTtBQUNoQixjQUFNLElBQUksTUFBTSxxQ0FBcUM7QUFBQSxNQUN2RDtBQUNBLFdBQUssU0FBUztBQUFBLFFBQ1o7QUFBQSxNQUNGLENBQUM7QUFBQSxJQUNILENBQUM7QUFFRCxJQUFDLE9BQWUsU0FBUztBQUV6QixVQUFNLGFBQWEsTUFBTTtBQUN2QixVQUFJLGFBQWE7QUFDZixjQUFNLElBQUksTUFBTSx5QkFBeUI7QUFBQSxNQUMzQztBQUNBLG9CQUFjO0FBQ2QsV0FBSyxTQUFTO0FBQUEsUUFDWixRQUFRO0FBQUEsTUFDVixDQUFDO0FBQ0QsV0FBSyxpQkFBaUIsUUFBUSxPQUFPLFVBQVU7QUFBQSxRQUM3QyxZQUFZO0FBQUEsUUFDWixXQUFXO0FBQUEsUUFDWCxTQUFTO0FBQUEsUUFDVCxlQUFlO0FBQUEsTUFDakIsQ0FBQztBQUFBLElBQ0g7QUFDQSxRQUFJLFNBQVMsTUFBTTtBQUNqQixpQkFBVyxZQUFZLENBQUM7QUFBQSxJQUMxQixPQUFPO0FBQ0wsYUFBTyxpQkFBaUIsb0JBQW9CLFVBQVU7QUFBQSxJQUN4RDtBQUFBLEVBQ0Y7QUFBQSxFQUVBLG9DQUNFLGNBQ0EsYUFDQSxhQUNNO0FBQ04sVUFBTSxVQUFVLFlBQVksV0FBVztBQUN2QyxVQUFNLG9CQUFvQixJQUFJLFlBQVksWUFBWSxNQUFNO0FBQUEsTUFDMUQ7QUFBQSxNQUNBLFFBQVEsRUFBRSxHQUFHLFlBQVksUUFBUSxhQUFhO0FBQUEsSUFDaEQsQ0FBQztBQUdELGdCQUFZLGNBQWMsaUJBQWlCO0FBQUEsRUFDN0M7QUFBQSxFQUVBLFVBQWdCO0FBRWQsWUFBUSxJQUFJLDZCQUE2QjtBQUFBLEVBQzNDO0FBQUEsRUFFQSxjQUF3QjtBQUN0QixXQUFPO0FBQUEsRUFDVDtBQUFBLEVBRUEsa0JBQTBCO0FBQ3hCLFFBQUksU0FBUyxZQUFZLFNBQVMsU0FBUyxhQUFhO0FBQ3RELGFBQU8sU0FBUyxTQUFTO0FBQUEsSUFDM0I7QUFDQSxXQUFPLEtBQUssSUFBSSxJQUFJO0FBQUEsRUFDdEI7QUFBQTtBQUFBLEVBR0EsWUFBaUI7QUFDZixXQUFPO0FBQUEsRUFDVDtBQUNGOzs7QUR2SE8sU0FBUyxxQkFBcUIsWUFBb0I7QUFDdkQsUUFBTSxzQkFBc0IsS0FBSyxNQUFNLEtBQUssVUFBVSxDQUFDO0FBRXZELFFBQU0sdUJBQXVCLENBQUMsWUFBOEM7QUFDMUUsV0FBTyxPQUFPLFlBQVksS0FBSyxVQUFVLE9BQU8sR0FBRyxHQUFHO0FBQUEsRUFDeEQ7QUFFQSxRQUFNLGdCQUFnQixJQUFJO0FBQUEsSUFDeEI7QUFBQSxNQUNFLEdBQUc7QUFBQSxNQUNILGNBQWM7QUFBQTtBQUFBLElBQ2hCO0FBQUEsSUFDQSxDQUFDLHlCQUErQztBQUM5QywyQkFBcUI7QUFBQSxRQUNuQixNQUFNO0FBQUEsUUFDTixTQUFTO0FBQUEsTUFDWCxDQUFDO0FBQUEsSUFDSDtBQUFBLElBQ0E7QUFBQSxFQUNGO0FBRUEsU0FBTyxpQkFBaUIsV0FBVyxDQUFDLE1BQU07QUFDeEMsVUFBTSxTQUFTLEtBQUssTUFBTSxFQUFFLElBQUk7QUFDaEMsWUFBUSxPQUFPLE1BQU07QUFBQSxNQUNuQixLQUFLO0FBQ0gsc0JBQWMsb0NBQW9DLE9BQU8sY0FBYyxPQUFPLEtBQUs7QUFDbkY7QUFBQSxNQUNGLEtBQUs7QUFDSCxzQkFBYyxtQkFBbUIsT0FBTyxZQUFZO0FBQ3BEO0FBQUEsTUFDRixLQUFLO0FBQ0gsc0JBQWMsc0JBQXNCLE9BQU8sWUFBWTtBQUN2RDtBQUFBLE1BQ0Y7QUFDRSxnQkFBUSxNQUFNLHdCQUF3QixNQUFNO0FBQUEsSUFDaEQ7QUFBQSxFQUNGLENBQUM7QUFDSDs7O0FFbERBLElBQU0sT0FBUSxPQUFlO0FBQzdCLHFCQUFxQixJQUFJOyIsCiAgIm5hbWVzIjogWyJBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFIiwgIkRJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFIiwgIkRPTV9NRVNTQUdFX1RZUEUiLCAiUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSIsICJtb2R1bGUiLCAiYXJncyJdCn0K\n", "import {\n FromObservableDOMInstanceMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line import/no-unresolved\nimport runnerText from \"runner-iframe-js-text\";\n\nexport class RunnerIframe {\n private iframe: HTMLIFrameElement;\n private onMessageCallback: (message: FromObservableDOMInstanceMessage) => void;\n private postMessageListener: (messageEvent: MessageEvent) => void;\n\n constructor(\n observableDOMParameters: ObservableDOMParameters,\n onMessageCallback: (message: FromObservableDOMInstanceMessage) => void,\n ) {\n this.iframe = document.createElement(\"iframe\");\n this.iframe.setAttribute(\"sandbox\", \"allow-scripts\");\n this.iframe.style.position = \"fixed\";\n this.iframe.style.top = \"0\";\n this.iframe.style.left = \"0\";\n this.iframe.style.width = \"0\";\n this.iframe.style.height = \"0\";\n this.iframe.style.border = \"none\";\n\n const paramsMinusCode: Partial<ObservableDOMParameters> = {\n ...observableDOMParameters,\n };\n delete paramsMinusCode.htmlContents;\n\n const args = btoa(JSON.stringify(paramsMinusCode));\n\n const isJSDOM = navigator.userAgent.includes(\"jsdom\");\n if (isJSDOM) {\n // srcdoc not supported, so we have to append elements to the iframe's document\n document.body.append(this.iframe);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const iframeBody = this.iframe.contentWindow!.document.body;\n const argsScriptElement = document.createElement(\"script\");\n argsScriptElement.innerHTML = `window.args=\"${args}\";`;\n iframeBody.append(argsScriptElement);\n const runnerScriptElement = document.createElement(\"script\");\n runnerScriptElement.innerHTML = runnerText;\n iframeBody.append(runnerScriptElement);\n const contentHolder = document.createElement(\"div\");\n iframeBody.append(contentHolder);\n contentHolder.innerHTML = observableDOMParameters.htmlContents;\n } else {\n this.iframe.setAttribute(\n \"srcdoc\",\n `\n <script>window.args=\"${args}\";</script>\n <script>${runnerText}</script>\n ${observableDOMParameters.htmlContents}\n `,\n );\n document.body.append(this.iframe);\n }\n\n this.onMessageCallback = onMessageCallback;\n\n this.postMessageListener = (e: MessageEvent) => {\n if (e.source === this.iframe.contentWindow || (isJSDOM && e.source === null)) {\n const parsed = JSON.parse(e.data) as FromObservableDOMInstanceMessage;\n onMessageCallback(parsed);\n }\n };\n window.addEventListener(\"message\", this.postMessageListener);\n }\n\n sendMessageToRunner(message: ToObservableDOMInstanceMessage) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.iframe.contentWindow!.postMessage(JSON.stringify(message), \"*\");\n }\n\n dispose() {\n window.removeEventListener(\"message\", this.postMessageListener);\n this.iframe.remove();\n }\n}\n", "import { EditableNetworkedDOM, NetworkedDOM } from \"@mml-io/networked-dom-document\";\nimport { NetworkedDOMWebsocket } from \"@mml-io/networked-dom-web\";\n\nimport { FakeWebsocket } from \"./FakeWebsocket\";\n\nexport class NetworkedDOMWebRunnerClient {\n public readonly element: HTMLDivElement;\n protected remoteDocumentHolder: HTMLElement;\n\n protected connectedState: {\n document: NetworkedDOM | EditableNetworkedDOM;\n domWebsocket: NetworkedDOMWebsocket;\n fakeWebsocket: FakeWebsocket;\n } | null = null;\n private enableEventHandling: boolean;\n\n constructor(enableEventHandling = true) {\n this.enableEventHandling = enableEventHandling;\n this.element = document.createElement(\"div\");\n this.element.style.position = \"relative\";\n this.element.style.width = \"100%\";\n this.element.style.height = \"100%\";\n\n this.remoteDocumentHolder = document.createElement(\"div\");\n this.element.append(this.remoteDocumentHolder);\n }\n\n public disconnect() {\n if (!this.connectedState) {\n return;\n }\n this.connectedState.document.removeWebSocket(\n this.connectedState.fakeWebsocket.serverSideWebsocket as unknown as WebSocket,\n );\n this.connectedState = null;\n }\n\n public dispose() {\n this.disconnect();\n this.remoteDocumentHolder.remove();\n this.element.remove();\n }\n\n public connect(\n document: NetworkedDOM | EditableNetworkedDOM,\n timeCallback?: (time: number) => void,\n ) {\n if (this.connectedState) {\n this.disconnect();\n }\n const fakeWebsocket = new FakeWebsocket(\"networked-dom-v0.1\");\n let overriddenHandler: ((element: HTMLElement, event: CustomEvent) => void) | null = null;\n const eventHandler = (element: HTMLElement, event: CustomEvent) => {\n if (!overriddenHandler) {\n throw new Error(\"overriddenHandler not set\");\n }\n overriddenHandler(element, event);\n };\n\n if (this.enableEventHandling) {\n this.remoteDocumentHolder.addEventListener(\"click\", (event: Event) => {\n eventHandler(event.target as HTMLElement, event as CustomEvent);\n event.stopPropagation();\n event.preventDefault();\n return false;\n });\n }\n\n const domWebsocket = new NetworkedDOMWebsocket(\n \"ws://localhost\",\n () => fakeWebsocket.clientSideWebsocket as unknown as WebSocket,\n this.remoteDocumentHolder,\n timeCallback,\n );\n overriddenHandler = (element: HTMLElement, event: CustomEvent) => {\n domWebsocket.handleEvent(element, event);\n };\n document.addWebSocket(fakeWebsocket.serverSideWebsocket as unknown as WebSocket);\n this.connectedState = {\n document,\n fakeWebsocket,\n domWebsocket,\n };\n }\n}\n", "class WebsocketEnd extends EventTarget {\n private readonly sendCallback: (data: string | ArrayBufferLike | Blob | ArrayBufferView) => void;\n public readonly protocol: string;\n\n constructor(\n protocol: string,\n sendCallback: (data: string | ArrayBufferLike | Blob | ArrayBufferView) => void,\n ) {\n super();\n this.protocol = protocol;\n this.sendCallback = sendCallback;\n }\n\n public close() {\n this.dispatchEvent(new CloseEvent(\"close\"));\n }\n\n public addEventListener<K extends keyof WebSocketEventMap>(\n type: K,\n listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) {\n if (type === \"open\") {\n listener.bind(this)(new Event(\"open\"));\n return;\n }\n super.addEventListener(type, listener, options);\n }\n\n public send(data: string | ArrayBufferLike | Blob | ArrayBufferView) {\n this.sendCallback(data);\n }\n}\n\nexport class FakeWebsocket {\n public clientSideWebsocket: WebsocketEnd;\n public serverSideWebsocket: WebsocketEnd;\n\n constructor(protocol: string) {\n this.clientSideWebsocket = new WebsocketEnd(protocol, (data) => {\n this.serverSideWebsocket.dispatchEvent(\n new MessageEvent(\"message\", {\n data,\n }),\n );\n });\n\n this.serverSideWebsocket = new WebsocketEnd(protocol, (data) => {\n this.clientSideWebsocket.dispatchEvent(\n new MessageEvent(\"message\", {\n data,\n }),\n );\n });\n }\n}\n", "import { ObservableDOMFactory } from \"@mml-io/networked-dom-document\";\nimport {\n DOM_MESSAGE_TYPE,\n FromObservableDOMInstanceMessage,\n ObservableDOMInterface,\n observableDOMInterfaceToMessageSender,\n ObservableDOMMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n\nimport { RunnerIframe } from \"./RunnerIframe\";\n\nexport const IframeObservableDOMFactory: ObservableDOMFactory = (\n observableDOMParameters: ObservableDOMParameters,\n callback: (message: ObservableDOMMessage, observableDOM: ObservableDOMInterface) => void,\n) => {\n const runnerIframe = new RunnerIframe(\n observableDOMParameters,\n (message: FromObservableDOMInstanceMessage) => {\n switch (message.type) {\n case DOM_MESSAGE_TYPE:\n callback(message.message, remoteObservableDOM);\n break;\n default:\n console.error(\"Unknown message type\", message.type);\n }\n },\n );\n\n const remoteObservableDOM: ObservableDOMInterface = observableDOMInterfaceToMessageSender(\n (message: ToObservableDOMInstanceMessage) => {\n runnerIframe.sendMessageToRunner(message);\n },\n () => {\n runnerIframe.dispose();\n },\n );\n return remoteObservableDOM;\n};\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["export * from \"@mml-io/networked-dom-document\";\nexport * from \"./RunnerIframe\";\nexport * from \"./NetworkedDOMWebRunnerClient\";\nexport * from \"./FakeWebsocket\";\nexport * from \"./IframeObservableDOMFactory\";\n", "// ../../observable-dom/src/utils.ts\nfunction virtualDOMElementToStatic(el) {\n return {\n nodeId: el.nodeId,\n tag: el.tag,\n attributes: el.attributes,\n childNodes: el.childNodes.map((child) => virtualDOMElementToStatic(child)),\n textContent: el.textContent\n };\n}\n\n// ../../observable-dom/src/ObservableDOM.ts\nvar ObservableDOM = class {\n constructor(observableDOMParameters, callback, runnerFactory) {\n this.nodeToNodeId = /* @__PURE__ */ new Map();\n this.nodeIdToNode = /* @__PURE__ */ new Map();\n this.realElementToVirtualElement = /* @__PURE__ */ new Map();\n this.ignoreTextNodes = true;\n this.nextNodeId = 1;\n this.htmlPath = observableDOMParameters.htmlPath;\n this.ignoreTextNodes = observableDOMParameters.ignoreTextNodes;\n this.callback = callback;\n this.documentTimeIntervalTimer = setInterval(() => {\n this.callback(\n {\n documentTime: this.getDocumentTime()\n },\n this\n );\n }, observableDOMParameters.pingIntervalMilliseconds || 5e3);\n this.domRunner = runnerFactory(\n observableDOMParameters.htmlPath,\n observableDOMParameters.htmlContents,\n observableDOMParameters.params,\n (domRunnerMessage) => {\n if (domRunnerMessage.loaded) {\n this.createVirtualDOMElementWithChildren(\n this.domRunner.getDocument(),\n null\n );\n const snapshot = virtualDOMElementToStatic(\n this.getVirtualDOMElementForRealElementOrThrow(\n this.domRunner.getDocument()\n )\n );\n this.callback(\n {\n snapshot,\n documentTime: this.getDocumentTime()\n },\n this\n );\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n this.callback(\n {\n logMessage: domRunnerMessage.logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n }\n );\n }\n addConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"connected\", {\n detail: { connectionId }\n })\n );\n }\n removeConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"disconnected\", {\n detail: { connectionId }\n })\n );\n }\n processModificationList(mutationList) {\n const documentEl = this.domRunner.getDocument();\n const documentVirtualDOMElement = this.realElementToVirtualElement.get(documentEl);\n if (!documentVirtualDOMElement) {\n throw new Error(`document not created in processModificationList`);\n }\n if (mutationList.length > 1) {\n }\n for (const mutation of mutationList) {\n if (this.isIgnoredElement(mutation.target)) {\n continue;\n }\n if (mutation.type === \"attributes\" && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.isIgnoredAttribute(mutation.target, mutation.attributeName)) {\n continue;\n }\n this.addKnownNodesInMutation(mutation);\n const firstNonIgnoredPreviousSibling = mutation.previousSibling ? this.getFirstNonIgnoredPreviousSibling(mutation.previousSibling) : null;\n const targetElement = this.getVirtualDOMElementForRealElementOrThrow(\n mutation.target\n );\n const addedNodes = [];\n for (const node of mutation.addedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n addedNodes.push(virtualDOMElementToStatic(virtualDOMElement));\n }\n const removedNodeIds = [];\n for (const node of mutation.removedNodes) {\n if (this.isIgnoredElement(node)) {\n continue;\n }\n const virtualDOMElement = this.getVirtualDOMElementForRealElementOrThrow(\n node\n );\n removedNodeIds.push(virtualDOMElement.nodeId);\n }\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: firstNonIgnoredPreviousSibling !== null ? this.getVirtualDOMElementForRealElementOrThrow(firstNonIgnoredPreviousSibling).nodeId : null,\n attribute: mutation.attributeName ? {\n attributeName: mutation.attributeName,\n value: mutation.target.getAttribute(mutation.attributeName)\n } : null\n };\n this.callback(\n {\n mutation: mutationRecord,\n documentTime: this.getDocumentTime()\n },\n this\n );\n this.removeKnownNodesInMutation(mutation);\n }\n }\n addKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error(\n \"Unknown node in addKnownNodesInMutation:\" + targetNode + \",\" + mutation.type\n );\n }\n if (mutation.type === \"childList\") {\n let previousSibling = mutation.previousSibling;\n let index = 0;\n while (previousSibling && this.isIgnoredElement(previousSibling)) {\n previousSibling = previousSibling.previousSibling;\n }\n if (previousSibling) {\n const previousSiblingElement = this.realElementToVirtualElement.get(\n previousSibling\n );\n if (!previousSiblingElement) {\n throw new Error(\"Unknown previous sibling\");\n }\n index = virtualDOMElement.childNodes.indexOf(previousSiblingElement);\n if (index === -1) {\n throw new Error(\"Previous sibling is not currently a child of the parent element\");\n }\n index += 1;\n }\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n virtualDOMElement\n );\n if (childVirtualDOMElement) {\n if (virtualDOMElement.childNodes.indexOf(childVirtualDOMElement) === -1) {\n virtualDOMElement.childNodes.splice(index, 0, childVirtualDOMElement);\n index++;\n }\n }\n });\n } else if (mutation.type === \"attributes\") {\n const attributeName = mutation.attributeName;\n if (this.isIgnoredAttribute(targetNode, attributeName)) {\n return;\n }\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete virtualDOMElement.attributes[attributeName];\n } else {\n virtualDOMElement.attributes[attributeName] = attributeValue;\n }\n } else if (mutation.type === \"characterData\") {\n virtualDOMElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n }\n removeKnownNodesInMutation(mutation) {\n const targetNode = mutation.target;\n const virtualDOMElement = this.realElementToVirtualElement.get(targetNode);\n if (!virtualDOMElement) {\n throw new Error(\"Unknown node in mutation list:\" + targetNode + \", \" + mutation.type);\n }\n if (mutation.type === \"childList\") {\n for (const node of mutation.removedNodes) {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n continue;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n console.warn(this.htmlPath, \"Unknown node in removeKnownNodesInMutation\");\n continue;\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n const index = virtualDOMElement.childNodes.indexOf(childDOMElement);\n virtualDOMElement.childNodes.splice(index, 1);\n }\n }\n return;\n }\n }\n removeVirtualDOMElement(virtualDOMElement) {\n this.nodeIdToNode.delete(virtualDOMElement.nodeId);\n this.nodeToNodeId.delete(virtualDOMElement);\n this.realElementToVirtualElement.delete(virtualDOMElement.realElement);\n for (const child of virtualDOMElement.childNodes) {\n this.removeVirtualDOMElement(child);\n }\n }\n createVirtualDOMElementWithChildren(node, parent) {\n const virtualElement = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i];\n const childVirtualElement = this.createVirtualDOMElementWithChildren(\n child,\n virtualElement\n );\n if (childVirtualElement) {\n virtualElement.childNodes.push(childVirtualElement);\n }\n }\n }\n return virtualElement;\n }\n createVirtualDOMElement(node, parent) {\n if (this.isIgnoredElement(node)) {\n return null;\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n throw new Error(\"Node already has a virtual element: \" + node.nodeName);\n }\n if (!node) {\n throw new Error(\"Cannot assign node id to null\");\n }\n const attributes = {};\n if (node.attributes) {\n const asHTMLElement = node;\n for (const key of asHTMLElement.getAttributeNames()) {\n const value = asHTMLElement.getAttribute(key);\n if (value === null) {\n throw new Error(\"Null attribute value for key: \" + key);\n }\n if (!this.isIgnoredAttribute(node, key)) {\n attributes[key] = value;\n }\n }\n }\n const nodeId = this.nextNodeId++;\n const virtualElement = {\n nodeId,\n tag: node.nodeName,\n attributes,\n childNodes: [],\n realElement: node,\n parent\n };\n if (node instanceof this.domRunner.getWindow().Text && node.textContent) {\n virtualElement.textContent = node.textContent;\n }\n this.nodeToNodeId.set(virtualElement, nodeId);\n this.nodeIdToNode.set(nodeId, virtualElement);\n this.realElementToVirtualElement.set(node, virtualElement);\n return virtualElement;\n }\n getFirstNonIgnoredPreviousSibling(node) {\n let currentNode = node;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n while (currentNode && currentNode.previousSibling) {\n currentNode = currentNode.previousSibling;\n if (!this.isIgnoredElement(currentNode)) {\n return currentNode;\n }\n }\n return null;\n }\n getVirtualDOMElementForRealElementOrThrow(realElement) {\n const virtualElement = this.realElementToVirtualElement.get(realElement);\n if (!virtualElement) {\n throw new Error(`Virtual element not found for real element`);\n }\n return virtualElement;\n }\n isIgnoredElement(node) {\n if (this.ignoreTextNodes && node instanceof this.domRunner.getWindow().Text) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().HTMLScriptElement) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().Comment) {\n return true;\n }\n return false;\n }\n isIgnoredAttribute(node, attributeName) {\n return attributeName.startsWith(\"on\");\n }\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n const domNode = this.nodeIdToNode.get(remoteEvent.nodeId);\n if (!domNode) {\n console.error(\"Unknown node ID in remote event: \" + remoteEvent.nodeId);\n return;\n }\n if (domNode instanceof this.domRunner.getWindow().Text) {\n console.warn(\"Cannot dispatch remote event to text node\");\n return;\n }\n this.domRunner.dispatchRemoteEventFromConnectionId(\n connectionId,\n domNode.realElement,\n remoteEvent\n );\n }\n dispose() {\n clearInterval(this.documentTimeIntervalTimer);\n this.domRunner.dispose();\n }\n getDocumentTime() {\n return this.domRunner.getDocumentTime();\n }\n};\n\n// ../../observable-dom-common/build/index.js\nvar ADD_CONNECTED_USER_ID_MESSAGE_TYPE = \"addConnectedUserId\";\nvar REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE = \"removeConnectedUserId\";\nvar DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE = \"dispatchRemoteEventFromConnectionId\";\nvar DOM_MESSAGE_TYPE = \"dom\";\n\n// src/WebBrowserDOMRunner.ts\nvar WebBrowserDOMRunnerFactory = (htmlPath, htmlContents, params, callback) => {\n return new WebBrowserDOMRunner(htmlPath, htmlContents, params, callback);\n};\nvar documentLoadTime = Date.now();\nvar WebBrowserDOMRunner = class {\n constructor(htmlPath, htmlContents, params, callback) {\n this.htmlPath = htmlPath;\n this.callback = callback;\n for (const level of [\"error\", \"warn\", \"info\", \"log\"]) {\n const defaultFn = window.console[level];\n window.console[level] = (...args2) => {\n callback({\n logMessage: {\n level,\n content: args2\n }\n });\n defaultFn(...args2);\n };\n }\n window.onerror = (message, source, line, column, error) => {\n callback({\n logMessage: {\n level: \"system\",\n content: [\n {\n message,\n type: error?.name,\n line,\n column\n }\n ]\n }\n });\n return false;\n };\n let didSendLoad = false;\n this.mutationObserver = new window.MutationObserver((mutationList) => {\n if (!document) {\n return;\n }\n if (!didSendLoad) {\n throw new Error(\"MutationObserver called before load\");\n }\n this.callback({\n mutationList\n });\n });\n window.params = params;\n const finishLoad = () => {\n if (didSendLoad) {\n throw new Error(\"finishLoad called twice\");\n }\n didSendLoad = true;\n this.callback({\n loaded: true\n });\n this.mutationObserver.observe(window.document, {\n attributes: true,\n childList: true,\n subtree: true,\n characterData: true\n });\n };\n if (document.body) {\n setTimeout(finishLoad, 0);\n } else {\n window.addEventListener(\"DOMContentLoaded\", finishLoad);\n }\n }\n dispatchRemoteEventFromConnectionId(connectionId, realElement, remoteEvent) {\n const bubbles = remoteEvent.bubbles || false;\n const remoteEventObject = new CustomEvent(remoteEvent.name, {\n bubbles,\n detail: { ...remoteEvent.params, connectionId }\n });\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log(\"WebBrowserDOMRunner.dispose\");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n if (document.timeline && document.timeline.currentTime) {\n return document.timeline.currentTime;\n }\n return Date.now() - documentLoadTime;\n }\n // TODO - resolve types (Window needs to expose classes such as CustomEvent as properties)\n getWindow() {\n return window;\n }\n};\n\n// src/IframeWebRunner.ts\nfunction setupIframeWebRunner(argsString) {\n const observableDOMParams = JSON.parse(atob(argsString));\n const sendMessageToHandler = (message) => {\n window.parent.postMessage(JSON.stringify(message), \"*\");\n };\n const observableDOM = new ObservableDOM(\n {\n ...observableDOMParams,\n htmlContents: \"\"\n // This must be empty as the contents are assumed to be provided by the srcdoc\n },\n (observableDOMMessage) => {\n sendMessageToHandler({\n type: DOM_MESSAGE_TYPE,\n message: observableDOMMessage\n });\n },\n WebBrowserDOMRunnerFactory\n );\n window.addEventListener(\"message\", (e) => {\n const parsed = JSON.parse(e.data);\n switch (parsed.type) {\n case DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE:\n observableDOM.dispatchRemoteEventFromConnectionId(parsed.connectionId, parsed.event);\n break;\n case ADD_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.addConnectedUserId(parsed.connectionId);\n break;\n case REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.removeConnectedUserId(parsed.connectionId);\n break;\n default:\n console.error(\"Unknown message type\", parsed);\n }\n });\n}\n\n// src/index.ts\nvar args = window.args;\nsetupIframeWebRunner(args);\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSB2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKFxuICAgICAgICAgICAgdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzbmFwc2hvdCxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGxvZ01lc3NhZ2U6IGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGFkZENvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImNvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQgfSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiZGlzY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QobXV0YXRpb25MaXN0OiBBcnJheTxNdXRhdGlvblJlY29yZD4pOiB2b2lkIHtcbiAgICBjb25zdCBkb2N1bWVudEVsID0gdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQ7XG4gICAgY29uc3QgZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChkb2N1bWVudEVsKTtcbiAgICBpZiAoIWRvY3VtZW50VmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZG9jdW1lbnQgbm90IGNyZWF0ZWQgaW4gcHJvY2Vzc01vZGlmaWNhdGlvbkxpc3RgKTtcbiAgICB9XG5cbiAgICBpZiAobXV0YXRpb25MaXN0Lmxlbmd0aCA+IDEpIHtcbiAgICAgIC8vIFRPRE8gKGh0dHBzOi8vZ2l0aHViLmNvbS9tbWwtaW8vbW1sL2lzc3Vlcy8xMDApIC0gd2FsayBiYWNrIHRocm91Z2ggdGhlIHJlY29yZHMgdG8gZGVyaXZlIHRoZSBpbnRlcm1lZGlhdGVcbiAgICAgIC8vICBzdGF0ZXMgKGUuZy4gaWYgYW4gYXR0cmlidXRlIGlzIGxhdGVyIGFkZGVkIHRvIGFuIGVsZW1lbnQgY3JlYXRlZCBpbiBhbiBlYXJsaWVyIHJlY29yZCB0aGVuIGl0IHNob3VsZCBub3RcbiAgICAgIC8vICBoYXZlIHRoYXQgYXR0cmlidXRlIHdoZW4gdGhlIGVsZW1lbnQgaXMgYWRkZWQuIFRoaXMgaXMgaW1wb3J0YW50IGFzIGluY29ycmVjdCBhdHRyaWJ1dGUgc2V0cyBjYW4gYWZmZWN0XG4gICAgICAvLyAgdmlzaWJpbGl0eSBhbmQgZXhwZWN0ZWQgY2xpZW50IHBlcmZvcm1hbmNlLlxuICAgIH1cblxuICAgIGZvciAoY29uc3QgbXV0YXRpb24gb2YgbXV0YXRpb25MaXN0KSB7XG4gICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgbXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIgJiZcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0LCBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lISlcbiAgICAgICkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hZGRLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbik7XG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcbiAgICAgIGNvbnN0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZ1xuICAgICAgICA/IHRoaXMuZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG11dGF0aW9uLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dClcbiAgICAgICAgOiBudWxsO1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgIG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICk7XG4gICAgICBjb25zdCBhZGRlZE5vZGVzOiBBcnJheTxTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudD4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5hZGRlZE5vZGVzKSB7XG4gICAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB2aXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgbm9kZSBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgKTtcbiAgICAgICAgYWRkZWROb2Rlcy5wdXNoKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWModmlydHVhbERPTUVsZW1lbnQpKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcbiAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBtdXRhdGlvbi5yZW1vdmVkTm9kZXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChub2RlIGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5nZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICAgICAgICBub2RlIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG11dGF0aW9uUmVjb3JkOiBTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQgPSB7XG4gICAgICAgIHR5cGU6IG11dGF0aW9uLnR5cGUsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgYWRkZWROb2RlcyxcbiAgICAgICAgcmVtb3ZlZE5vZGVJZHMsXG4gICAgICAgIHByZXZpb3VzU2libGluZ0lkOlxuICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyAhPT0gbnVsbFxuICAgICAgICAgICAgPyB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZykubm9kZUlkXG4gICAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuXG4gICAgICB0aGlzLnJlbW92ZUtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZEtub3duTm9kZXNJbk11dGF0aW9uKG11dGF0aW9uOiBNdXRhdGlvblJlY29yZCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldE5vZGUgPSBtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgY29uc3QgdmlydHVhbERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQodGFyZ2V0Tm9kZSk7XG4gICAgaWYgKCF2aXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlVua25vd24gbm9kZSBpbiBhZGRLbm93bk5vZGVzSW5NdXRhdGlvbjpcIiArIHRhcmdldE5vZGUgKyBcIixcIiArIG11dGF0aW9uLnR5cGUsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgbGV0IHByZXZpb3VzU2libGluZyA9IG11dGF0aW9uLnByZXZpb3VzU2libGluZztcbiAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICB3aGlsZSAocHJldmlvdXNTaWJsaW5nICYmIHRoaXMuaXNJZ25vcmVkRWxlbWVudChwcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQpKSB7XG4gICAgICAgIHByZXZpb3VzU2libGluZyA9IHByZXZpb3VzU2libGluZy5wcmV2aW91c1NpYmxpbmc7XG4gICAgICB9XG4gICAgICBpZiAocHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZ0VsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoXG4gICAgICAgICAgcHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICApO1xuICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHByZXZpb3VzIHNpYmxpbmdcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggPSB2aXJ0dWFsRE9NRWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YocHJldmlvdXNTaWJsaW5nRWxlbWVudCk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcmV2aW91cyBzaWJsaW5nIGlzIG5vdCBjdXJyZW50bHkgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICBhc0VsZW1lbnRPclRleHQsXG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgaWYgKHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihjaGlsZFZpcnR1YWxET01FbGVtZW50KSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluZGV4LCAwLCBjaGlsZFZpcnR1YWxET01FbGVtZW50KTtcbiAgICAgICAgICAgIGluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKHRhcmdldE5vZGUsIGF0dHJpYnV0ZU5hbWUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZVZhbHVlID0gKHRhcmdldE5vZGUgYXMgRWxlbWVudCkuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgIGRlbGV0ZSB2aXJ0dWFsRE9NRWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGFyYWN0ZXJEYXRhXCIpIHtcbiAgICAgIHZpcnR1YWxET01FbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVLbm93bk5vZGVzSW5NdXRhdGlvbihtdXRhdGlvbjogTXV0YXRpb25SZWNvcmQpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgIGNvbnN0IHZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KHRhcmdldE5vZGUpO1xuICAgIGlmICghdmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gbm9kZSBpbiBtdXRhdGlvbiBsaXN0OlwiICsgdGFyZ2V0Tm9kZSArIFwiLCBcIiArIG11dGF0aW9uLnR5cGUpO1xuICAgIH1cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgZm9yIChjb25zdCBub2RlIG9mIG11dGF0aW9uLnJlbW92ZWROb2Rlcykge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KGFzRWxlbWVudE9yVGV4dCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGlsZERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoYXNFbGVtZW50T3JUZXh0KTtcbiAgICAgICAgaWYgKCFjaGlsZERPTUVsZW1lbnQpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4odGhpcy5odG1sUGF0aCwgXCJVbmtub3duIG5vZGUgaW4gcmVtb3ZlS25vd25Ob2Rlc0luTXV0YXRpb25cIik7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVWaXJ0dWFsRE9NRWxlbWVudCh2aXJ0dWFsRE9NRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQucmVhbEVsZW1lbnQpO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcykge1xuICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChub2RlLCBwYXJlbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgY2hpbGQgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxFbGVtZW50KSB7XG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQuY2hpbGROb2Rlcy5wdXNoKGNoaWxkVmlydHVhbEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KG5vZGUpO1xuICAgIGlmIChleGlzdGluZ1ZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vZGUgYWxyZWFkeSBoYXMgYSB2aXJ0dWFsIGVsZW1lbnQ6IFwiICsgbm9kZS5ub2RlTmFtZSk7XG4gICAgfVxuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFzc2lnbiBub2RlIGlkIHRvIG51bGxcIik7XG4gICAgfVxuXG4gICAgY29uc3QgYXR0cmlidXRlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGlmICgobm9kZSBhcyBhbnkpLmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IGFzSFRNTEVsZW1lbnQgPSBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGVOYW1lcygpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVsbCBhdHRyaWJ1dGUgdmFsdWUgZm9yIGtleTogXCIgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobm9kZSwga2V5KSkge1xuICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUlkID0gdGhpcy5uZXh0Tm9kZUlkKys7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IHtcbiAgICAgIG5vZGVJZCxcbiAgICAgIHRhZzogbm9kZS5ub2RlTmFtZSxcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBjaGlsZE5vZGVzOiBbXSxcbiAgICAgIHJlYWxFbGVtZW50OiBub2RlLFxuICAgICAgcGFyZW50LFxuICAgIH07XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0ICYmIG5vZGUudGV4dENvbnRlbnQpIHtcbiAgICAgIHZpcnR1YWxFbGVtZW50LnRleHRDb250ZW50ID0gbm9kZS50ZXh0Q29udGVudDtcbiAgICB9XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuc2V0KHZpcnR1YWxFbGVtZW50LCBub2RlSWQpO1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLnNldChub2RlSWQsIHZpcnR1YWxFbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5zZXQobm9kZSwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Rmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nKG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogRWxlbWVudCB8IFRleHQgfCBudWxsIHtcbiAgICBsZXQgY3VycmVudE5vZGUgPSBub2RlO1xuICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgcmV0dXJuIGN1cnJlbnROb2RlO1xuICAgIH1cbiAgICB3aGlsZSAoY3VycmVudE5vZGUgJiYgY3VycmVudE5vZGUucHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICBjdXJyZW50Tm9kZSA9IGN1cnJlbnROb2RlLnByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRFbGVtZW50KGN1cnJlbnROb2RlKSkge1xuICAgICAgICByZXR1cm4gY3VycmVudE5vZGU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBkb21Ob2RlID0gdGhpcy5ub2RlSWRUb05vZGUuZ2V0KHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiVW5rbm93biBub2RlIElEIGluIHJlbW90ZSBldmVudDogXCIgKyByZW1vdGVFdmVudC5ub2RlSWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChkb21Ob2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgY29uc29sZS53YXJuKFwiQ2Fubm90IGRpc3BhdGNoIHJlbW90ZSBldmVudCB0byB0ZXh0IG5vZGVcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgICBjb25uZWN0aW9uSWQsXG4gICAgICBkb21Ob2RlLnJlYWxFbGVtZW50IGFzIEVsZW1lbnQsXG4gICAgICByZW1vdGVFdmVudCxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGRpc3Bvc2UoKSB7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIpO1xuICAgIHRoaXMuZG9tUnVubmVyLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RG9jdW1lbnRUaW1lKCkge1xuICAgIHJldHVybiB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudFRpbWUoKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IFJlbW90ZUV2ZW50IH0gZnJvbSBcIkBtbWwtaW8vbmV0d29ya2VkLWRvbS1wcm90b2NvbFwiO1xuXG5pbXBvcnQgeyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLCBPYnNlcnZhYmxlRE9NTWVzc2FnZSB9IGZyb20gXCIuL09ic2VydmFibGVET01JbnRlcmZhY2VcIjtcblxuZXhwb3J0IGNvbnN0IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUgPSBcImFkZENvbm5lY3RlZFVzZXJJZFwiO1xuZXhwb3J0IGNvbnN0IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUgPSBcInJlbW92ZUNvbm5lY3RlZFVzZXJJZFwiO1xuZXhwb3J0IGNvbnN0IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFID1cbiAgXCJkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZFwiO1xuZXhwb3J0IGNvbnN0IERPTV9NRVNTQUdFX1RZUEUgPSBcImRvbVwiO1xuXG5leHBvcnQgdHlwZSBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTtcbiAgY29ubmVjdGlvbklkOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBSZW1vdmVDb25uZWN0ZWRVc2VySWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTtcbiAgY29ubmVjdGlvbklkOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBEaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRTtcbiAgY29ubmVjdGlvbklkOiBudW1iZXI7XG4gIGV2ZW50OiBSZW1vdGVFdmVudDtcbn07XG5cbmV4cG9ydCB0eXBlIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9XG4gIHwgQWRkQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2VcbiAgfCBEaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZE1lc3NhZ2U7XG5cbnR5cGUgRE9NTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERPTV9NRVNTQUdFX1RZUEU7XG4gIG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UgPSBET01NZXNzYWdlO1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlNZXNzYWdlVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2UoXG4gIG1lc3NhZ2U6IFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgaW5zdGFuY2U6IE9ic2VydmFibGVET01JbnRlcmZhY2UsXG4pIHtcbiAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLmFkZENvbm5lY3RlZFVzZXJJZChtZXNzYWdlLmNvbm5lY3Rpb25JZCk7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UucmVtb3ZlQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQobWVzc2FnZS5jb25uZWN0aW9uSWQsIG1lc3NhZ2UuZXZlbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2YWJsZURPTUludGVyZmFjZVRvTWVzc2FnZVNlbmRlcihcbiAgc2VuZGVyOiAobWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB2b2lkLFxuICBkaXNwb3NlOiAoKSA9PiB2b2lkLFxuKSB7XG4gIGNvbnN0IHJlbW90ZU9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UgPSB7XG4gICAgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICAgIGV2ZW50OiByZW1vdGVFdmVudCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgIGRpc3Bvc2UoKTtcbiAgICB9LFxuICAgIHJlbW92ZUNvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbiAgcmV0dXJuIHJlbW90ZU9ic2VydmFibGVET007XG59XG4iLCAiaW1wb3J0IHsgUmVtb3RlRXZlbnQgfSBmcm9tIFwiQG1tbC1pby9uZXR3b3JrZWQtZG9tLXByb3RvY29sXCI7XG5pbXBvcnQgeyBET01SdW5uZXJGYWN0b3J5LCBET01SdW5uZXJJbnRlcmZhY2UsIERPTVJ1bm5lck1lc3NhZ2UgfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbVwiO1xuXG5leHBvcnQgY29uc3QgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChtdXRhdGlvbkxpc3Q6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQsXG4pOiBET01SdW5uZXJJbnRlcmZhY2UgPT4ge1xuICByZXR1cm4gbmV3IFdlYkJyb3dzZXJET01SdW5uZXIoaHRtbFBhdGgsIGh0bWxDb250ZW50cywgcGFyYW1zLCBjYWxsYmFjayk7XG59O1xuXG5jb25zdCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcblxuZXhwb3J0IGNsYXNzIFdlYkJyb3dzZXJET01SdW5uZXIgaW1wbGVtZW50cyBET01SdW5uZXJJbnRlcmZhY2Uge1xuICBwcml2YXRlIG11dGF0aW9uT2JzZXJ2ZXI6IE11dGF0aW9uT2JzZXJ2ZXI7XG4gIHByaXZhdGUgaHRtbFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSBjYWxsYmFjazogKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaHRtbFBhdGg6IHN0cmluZyxcbiAgICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgICBwYXJhbXM6IG9iamVjdCxcbiAgICBjYWxsYmFjazogKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQsXG4gICkge1xuICAgIHRoaXMuaHRtbFBhdGggPSBodG1sUGF0aDtcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICAvLyBGb3J3YXJkIGNvbnNvbGUgbWVzc2FnZXNcbiAgICBmb3IgKGNvbnN0IGxldmVsIG9mIFtcImVycm9yXCIsIFwid2FyblwiLCBcImluZm9cIiwgXCJsb2dcIl0gYXMgY29uc3QpIHtcbiAgICAgIGNvbnN0IGRlZmF1bHRGbiA9IHdpbmRvdy5jb25zb2xlW2xldmVsXTtcblxuICAgICAgd2luZG93LmNvbnNvbGVbbGV2ZWxdID0gKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgY2FsbGJhY2soe1xuICAgICAgICAgIGxvZ01lc3NhZ2U6IHtcbiAgICAgICAgICAgIGxldmVsLFxuICAgICAgICAgICAgY29udGVudDogYXJncyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgZGVmYXVsdEZuKC4uLmFyZ3MpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGb3J3YXJkIHVuY2F1Z2h0IGVycm9yc1xuICAgIHdpbmRvdy5vbmVycm9yID0gKG1lc3NhZ2UsIHNvdXJjZSwgbGluZSwgY29sdW1uLCBlcnJvcikgPT4ge1xuICAgICAgY2FsbGJhY2soe1xuICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgbGV2ZWw6IFwic3lzdGVtXCIsXG4gICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgICB0eXBlOiBlcnJvcj8ubmFtZSxcbiAgICAgICAgICAgICAgbGluZSxcbiAgICAgICAgICAgICAgY29sdW1uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIGxldCBkaWRTZW5kTG9hZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5tdXRhdGlvbk9ic2VydmVyID0gbmV3IHdpbmRvdy5NdXRhdGlvbk9ic2VydmVyKChtdXRhdGlvbkxpc3QpID0+IHtcbiAgICAgIGlmICghZG9jdW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCFkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNdXRhdGlvbk9ic2VydmVyIGNhbGxlZCBiZWZvcmUgbG9hZFwiKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBtdXRhdGlvbkxpc3QsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgICh3aW5kb3cgYXMgYW55KS5wYXJhbXMgPSBwYXJhbXM7XG5cbiAgICBjb25zdCBmaW5pc2hMb2FkID0gKCkgPT4ge1xuICAgICAgaWYgKGRpZFNlbmRMb2FkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImZpbmlzaExvYWQgY2FsbGVkIHR3aWNlXCIpO1xuICAgICAgfVxuICAgICAgZGlkU2VuZExvYWQgPSB0cnVlO1xuICAgICAgdGhpcy5jYWxsYmFjayh7XG4gICAgICAgIGxvYWRlZDogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5tdXRhdGlvbk9ic2VydmVyLm9ic2VydmUod2luZG93LmRvY3VtZW50LCB7XG4gICAgICAgIGF0dHJpYnV0ZXM6IHRydWUsXG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgICAgY2hhcmFjdGVyRGF0YTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgaWYgKGRvY3VtZW50LmJvZHkpIHtcbiAgICAgIHNldFRpbWVvdXQoZmluaXNoTG9hZCwgMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBmaW5pc2hMb2FkKTtcbiAgICB9XG4gIH1cblxuICBkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICBjb25uZWN0aW9uSWQ6IG51bWJlcixcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCxcbiAgICByZW1vdGVFdmVudDogUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGJ1YmJsZXMgPSByZW1vdGVFdmVudC5idWJibGVzIHx8IGZhbHNlO1xuICAgIGNvbnN0IHJlbW90ZUV2ZW50T2JqZWN0ID0gbmV3IEN1c3RvbUV2ZW50KHJlbW90ZUV2ZW50Lm5hbWUsIHtcbiAgICAgIGJ1YmJsZXMsXG4gICAgICBkZXRhaWw6IHsgLi4ucmVtb3RlRXZlbnQucGFyYW1zLCBjb25uZWN0aW9uSWQgfSxcbiAgICB9KTtcblxuICAgIC8vIERpc3BhdGNoIHRoZSBldmVudCB2aWEgSmF2YVNjcmlwdC5cbiAgICByZWFsRWxlbWVudC5kaXNwYXRjaEV2ZW50KHJlbW90ZUV2ZW50T2JqZWN0KTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgLy8gVE9ETyAtIGhhbmRsZSBkaXNwb3NlXG4gICAgY29uc29sZS5sb2coXCJXZWJCcm93c2VyRE9NUnVubmVyLmRpc3Bvc2VcIik7XG4gIH1cblxuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudCB7XG4gICAgcmV0dXJuIGRvY3VtZW50O1xuICB9XG5cbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlciB7XG4gICAgaWYgKGRvY3VtZW50LnRpbWVsaW5lICYmIGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lKSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUgYXMgbnVtYmVyO1xuICAgIH1cbiAgICByZXR1cm4gRGF0ZS5ub3coKSAtIGRvY3VtZW50TG9hZFRpbWU7XG4gIH1cblxuICAvLyBUT0RPIC0gcmVzb2x2ZSB0eXBlcyAoV2luZG93IG5lZWRzIHRvIGV4cG9zZSBjbGFzc2VzIHN1Y2ggYXMgQ3VzdG9tRXZlbnQgYXMgcHJvcGVydGllcylcbiAgZ2V0V2luZG93KCk6IGFueSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfVxufVxuIiwgImltcG9ydCB7IE9ic2VydmFibGVET00gfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTVwiO1xuaW1wb3J0IHtcbiAgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gIERPTV9NRVNTQUdFX1RZUEUsXG4gIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5IH0gZnJvbSBcIi4vV2ViQnJvd3NlckRPTVJ1bm5lclwiO1xuXG4vLyBUaGlzIHJ1bnMgaW4gdGhlIGlmcmFtZSB0aGF0IHdpbGwgZXhlY3V0ZSB0aGUgZG9jdW1lbnQgc2NyaXB0IHRvIHNldHVwIHRoZSBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBtZXNzYWdlc1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBzZXR1cElmcmFtZVdlYlJ1bm5lciB9IGZyb20gXCIuL0lmcmFtZVdlYlJ1bm5lclwiO1xuXG5jb25zdCBhcmdzID0gKHdpbmRv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\n", "import {\n FromObservableDOMInstanceMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\n// eslint-disable-next-line import/no-unresolved\nimport runnerText from \"runner-iframe-js-text\";\n\nexport class RunnerIframe {\n private iframe: HTMLIFrameElement;\n private onMessageCallback: (message: FromObservableDOMInstanceMessage) => void;\n private postMessageListener: (messageEvent: MessageEvent) => void;\n\n constructor(\n observableDOMParameters: ObservableDOMParameters,\n onMessageCallback: (message: FromObservableDOMInstanceMessage) => void,\n ) {\n this.iframe = document.createElement(\"iframe\");\n this.iframe.setAttribute(\"sandbox\", \"allow-scripts\");\n this.iframe.style.position = \"fixed\";\n this.iframe.style.top = \"0\";\n this.iframe.style.left = \"0\";\n this.iframe.style.width = \"0\";\n this.iframe.style.height = \"0\";\n this.iframe.style.border = \"none\";\n\n const paramsMinusCode: Partial<ObservableDOMParameters> = {\n ...observableDOMParameters,\n };\n delete paramsMinusCode.htmlContents;\n\n const args = btoa(JSON.stringify(paramsMinusCode));\n\n const isJSDOM = navigator.userAgent.includes(\"jsdom\");\n if (isJSDOM) {\n // srcdoc not supported, so we have to append elements to the iframe's document\n document.body.append(this.iframe);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const iframeBody = this.iframe.contentWindow!.document.body;\n const argsScriptElement = document.createElement(\"script\");\n argsScriptElement.innerHTML = `window.args=\"${args}\";`;\n iframeBody.append(argsScriptElement);\n const runnerScriptElement = document.createElement(\"script\");\n runnerScriptElement.innerHTML = runnerText;\n iframeBody.append(runnerScriptElement);\n const contentHolder = document.createElement(\"div\");\n iframeBody.append(contentHolder);\n contentHolder.innerHTML = observableDOMParameters.htmlContents;\n } else {\n this.iframe.setAttribute(\n \"srcdoc\",\n `\n <script>window.args=\"${args}\";</script>\n <script>${runnerText}</script>\n ${observableDOMParameters.htmlContents}\n `,\n );\n document.body.append(this.iframe);\n }\n\n this.onMessageCallback = onMessageCallback;\n\n this.postMessageListener = (e: MessageEvent) => {\n if (e.source === this.iframe.contentWindow || (isJSDOM && e.source === null)) {\n const parsed = JSON.parse(e.data) as FromObservableDOMInstanceMessage;\n onMessageCallback(parsed);\n }\n };\n window.addEventListener(\"message\", this.postMessageListener);\n }\n\n sendMessageToRunner(message: ToObservableDOMInstanceMessage) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.iframe.contentWindow!.postMessage(JSON.stringify(message), \"*\");\n }\n\n dispose() {\n window.removeEventListener(\"message\", this.postMessageListener);\n this.iframe.remove();\n }\n}\n", "import { EditableNetworkedDOM, NetworkedDOM } from \"@mml-io/networked-dom-document\";\nimport { NetworkedDOMWebsocket } from \"@mml-io/networked-dom-web\";\n\nimport { FakeWebsocket } from \"./FakeWebsocket\";\n\nexport class NetworkedDOMWebRunnerClient {\n public readonly element: HTMLDivElement;\n protected remoteDocumentHolder: HTMLElement;\n\n protected connectedState: {\n document: NetworkedDOM | EditableNetworkedDOM;\n domWebsocket: NetworkedDOMWebsocket;\n fakeWebsocket: FakeWebsocket;\n } | null = null;\n private enableEventHandling: boolean;\n\n constructor(enableEventHandling = true) {\n this.enableEventHandling = enableEventHandling;\n this.element = document.createElement(\"div\");\n this.element.style.position = \"relative\";\n this.element.style.width = \"100%\";\n this.element.style.height = \"100%\";\n\n this.remoteDocumentHolder = document.createElement(\"div\");\n this.element.append(this.remoteDocumentHolder);\n }\n\n public disconnect() {\n if (!this.connectedState) {\n return;\n }\n this.connectedState.document.removeWebSocket(\n this.connectedState.fakeWebsocket.serverSideWebsocket as unknown as WebSocket,\n );\n this.connectedState = null;\n }\n\n public dispose() {\n this.disconnect();\n this.remoteDocumentHolder.remove();\n this.element.remove();\n }\n\n public connect(\n document: NetworkedDOM | EditableNetworkedDOM,\n timeCallback?: (time: number) => void,\n ) {\n if (this.connectedState) {\n this.disconnect();\n }\n const fakeWebsocket = new FakeWebsocket(\"networked-dom-v0.1\");\n let overriddenHandler: ((element: HTMLElement, event: CustomEvent) => void) | null = null;\n const eventHandler = (element: HTMLElement, event: CustomEvent) => {\n if (!overriddenHandler) {\n throw new Error(\"overriddenHandler not set\");\n }\n overriddenHandler(element, event);\n };\n\n if (this.enableEventHandling) {\n this.remoteDocumentHolder.addEventListener(\"click\", (event: Event) => {\n eventHandler(event.target as HTMLElement, event as CustomEvent);\n event.stopPropagation();\n event.preventDefault();\n return false;\n });\n }\n\n const domWebsocket = new NetworkedDOMWebsocket(\n \"ws://localhost\",\n () => fakeWebsocket.clientSideWebsocket as unknown as WebSocket,\n this.remoteDocumentHolder,\n timeCallback,\n );\n overriddenHandler = (element: HTMLElement, event: CustomEvent) => {\n domWebsocket.handleEvent(element, event);\n };\n document.addWebSocket(fakeWebsocket.serverSideWebsocket as unknown as WebSocket);\n this.connectedState = {\n document,\n fakeWebsocket,\n domWebsocket,\n };\n }\n}\n", "class WebsocketEnd extends EventTarget {\n private readonly sendCallback: (data: string | ArrayBufferLike | Blob | ArrayBufferView) => void;\n public readonly protocol: string;\n\n constructor(\n protocol: string,\n sendCallback: (data: string | ArrayBufferLike | Blob | ArrayBufferView) => void,\n ) {\n super();\n this.protocol = protocol;\n this.sendCallback = sendCallback;\n }\n\n public close() {\n this.dispatchEvent(new CloseEvent(\"close\"));\n }\n\n public addEventListener<K extends keyof WebSocketEventMap>(\n type: K,\n listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) {\n if (type === \"open\") {\n listener.bind(this)(new Event(\"open\"));\n return;\n }\n super.addEventListener(type, listener, options);\n }\n\n public send(data: string | ArrayBufferLike | Blob | ArrayBufferView) {\n this.sendCallback(data);\n }\n}\n\nexport class FakeWebsocket {\n public clientSideWebsocket: WebsocketEnd;\n public serverSideWebsocket: WebsocketEnd;\n\n constructor(protocol: string) {\n this.clientSideWebsocket = new WebsocketEnd(protocol, (data) => {\n this.serverSideWebsocket.dispatchEvent(\n new MessageEvent(\"message\", {\n data,\n }),\n );\n });\n\n this.serverSideWebsocket = new WebsocketEnd(protocol, (data) => {\n this.clientSideWebsocket.dispatchEvent(\n new MessageEvent(\"message\", {\n data,\n }),\n );\n });\n }\n}\n", "import { ObservableDOMFactory } from \"@mml-io/networked-dom-document\";\nimport {\n DOM_MESSAGE_TYPE,\n FromObservableDOMInstanceMessage,\n ObservableDOMInterface,\n observableDOMInterfaceToMessageSender,\n ObservableDOMMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n\nimport { RunnerIframe } from \"./RunnerIframe\";\n\nexport const IframeObservableDOMFactory: ObservableDOMFactory = (\n observableDOMParameters: ObservableDOMParameters,\n callback: (message: ObservableDOMMessage, observableDOM: ObservableDOMInterface) => void,\n) => {\n const runnerIframe = new RunnerIframe(\n observableDOMParameters,\n (message: FromObservableDOMInstanceMessage) => {\n switch (message.type) {\n case DOM_MESSAGE_TYPE:\n callback(message.message, remoteObservableDOM);\n break;\n default:\n console.error(\"Unknown message type\", message.type);\n }\n },\n );\n\n const remoteObservableDOM: ObservableDOMInterface = observableDOMInterfaceToMessageSender(\n (message: ToObservableDOMInstanceMessage) => {\n runnerIframe.sendMessageToRunner(message);\n },\n () => {\n runnerIframe.dispose();\n },\n );\n return remoteObservableDOM;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["document"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mml-io/networked-dom-web-runner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"main": "./build/index.js",
|
|
8
8
|
"types": "./build/index.d.ts",
|
|
9
|
+
"type": "module",
|
|
9
10
|
"files": [
|
|
10
11
|
"/build"
|
|
11
12
|
],
|
|
@@ -13,14 +14,14 @@
|
|
|
13
14
|
"type-check": "tsc --noEmit",
|
|
14
15
|
"build": "tsx ./build.ts --build",
|
|
15
16
|
"iterate": "tsx ./build.ts --watch",
|
|
16
|
-
"lint": "eslint \"./src/**/*.{js,jsx,ts,tsx}\" --max-warnings 0",
|
|
17
|
-
"lint-fix": "eslint \"./src/**/*.{js,jsx,ts,tsx}\" --fix",
|
|
18
|
-
"test": "
|
|
19
|
-
"test-iterate": "jest --watch"
|
|
17
|
+
"lint": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --max-warnings 0",
|
|
18
|
+
"lint-fix": "eslint \"./{src,test}/**/*.{js,jsx,ts,tsx}\" --fix",
|
|
19
|
+
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
20
|
+
"test-iterate": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@mml-io/networked-dom-web": "^0.
|
|
23
|
-
"@mml-io/observable-dom-common": "^0.
|
|
23
|
+
"@mml-io/networked-dom-web": "^0.7.0",
|
|
24
|
+
"@mml-io/observable-dom-common": "^0.7.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@mml-io/networked-dom-web-runner-iframe": "file:../networked-dom-web-runner-iframe",
|
|
@@ -28,5 +29,5 @@
|
|
|
28
29
|
"jest-environment-jsdom": "29.6.2",
|
|
29
30
|
"jest-expect-message": "1.1.3"
|
|
30
31
|
},
|
|
31
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "aa75274d1ee99afdb8d5ff7432cb57c23d09186e"
|
|
32
33
|
}
|