@mml-io/networked-dom-web-runner 0.17.1 → 0.18.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 CHANGED
@@ -2,7 +2,7 @@
2
2
  export * from "@mml-io/networked-dom-document";
3
3
 
4
4
  // runner-iframe-js-text-namespace:/home/runner/work/mml/mml/packages/networked-dom-web-runner/networked-dom-web-runner-iframe/build/index.js
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.loaded = false;\n this.preLoadLogMessages = [];\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.loaded = true;\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 for (const logMessage of this.preLoadLogMessages) {\n this.callback(\n {\n logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n this.preLoadLogMessages = [];\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n if (!this.loaded) {\n this.preLoadLogMessages.push(domRunnerMessage.logMessage);\n return;\n }\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 const targetNode = mutation.target;\n const targetElement = this.realElementToVirtualElement.get(targetNode);\n if (!targetElement) {\n throw new Error("Unknown node:" + targetNode + "," + mutation.type);\n }\n let firstNonIgnoredPreviousSibling = mutation.previousSibling;\n let insertionIndex = 0;\n while (firstNonIgnoredPreviousSibling && this.isIgnoredElement(firstNonIgnoredPreviousSibling)) {\n firstNonIgnoredPreviousSibling = firstNonIgnoredPreviousSibling.previousSibling;\n }\n let previousSiblingElement = void 0;\n if (firstNonIgnoredPreviousSibling) {\n previousSiblingElement = this.realElementToVirtualElement.get(\n firstNonIgnoredPreviousSibling\n );\n if (!previousSiblingElement) {\n throw new Error("Unknown previous sibling");\n }\n insertionIndex = targetElement.childNodes.indexOf(previousSiblingElement);\n if (insertionIndex === -1) {\n throw new Error("Previous sibling is not currently a child of the parent element");\n }\n insertionIndex += 1;\n }\n const toAdd = [];\n const removedNodeIds = [];\n if (mutation.type === "childList") {\n mutation.removedNodes.forEach((node) => {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n return;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n return;\n } else {\n const index = targetElement.childNodes.indexOf(childDOMElement);\n if (index === -1) {\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n removedNodeIds.push(childDOMElement.nodeId);\n const removal = targetElement.childNodes.splice(index, 1);\n if (removal.length !== 1) {\n throw new Error("Removal length not 1");\n } else {\n if (removal[0].nodeId !== childDOMElement.nodeId) {\n throw new Error("Removal node id mismatch");\n }\n }\n }\n }\n });\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n if (asElementOrText.parentNode !== targetNode) {\n } else {\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n targetElement\n );\n if (childVirtualDOMElement) {\n toAdd.push(childVirtualDOMElement);\n }\n }\n });\n targetElement.childNodes.splice(insertionIndex, 0, ...toAdd);\n } else if (mutation.type === "attributes") {\n const attributeName = mutation.attributeName;\n if (!this.isIgnoredAttribute(targetNode, attributeName)) {\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete targetElement.attributes[attributeName];\n } else {\n targetElement.attributes[attributeName] = attributeValue;\n }\n }\n } else if (mutation.type === "characterData") {\n targetElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n const addedNodes = toAdd.map(virtualDOMElementToStatic);\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: previousSiblingElement ? previousSiblingElement.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 }\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, existing] = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (existing) {\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, false];\n }\n if (!node) {\n throw new Error("Cannot assign node id to null");\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n return [existingValue, true];\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, false];\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(params, callback);\n};\nvar documentLoadTime = Date.now();\nif (document.timeline && document.timeline.currentTime) {\n documentLoadTime = Date.now() - document.timeline.currentTime;\n}\nvar WebBrowserDOMRunner = class {\n constructor(params, callback) {\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 const eventTypeLowerCase = remoteEvent.name.toLowerCase();\n if (eventTypeLowerCase !== "click") {\n const handlerAttributeName = "on" + eventTypeLowerCase;\n const handlerAttributeValue = realElement.getAttribute(handlerAttributeName);\n if (handlerAttributeValue) {\n try {\n const fn = Function("event", handlerAttributeValue);\n fn.apply(realElement, [remoteEventObject]);\n } catch (e) {\n console.error("Error running event handler:", e);\n }\n }\n }\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log("WebBrowserDOMRunner.dispose");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n const dateBasedDocumentTime = Date.now() - documentLoadTime;\n if (document.timeline && document.timeline.currentTime) {\n const time = document.timeline.currentTime;\n if (dateBasedDocumentTime > time + 500) {\n return dateBasedDocumentTime;\n }\n return time;\n }\n return dateBasedDocumentTime;\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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuLyoqXG4gKiBUaGUgT2JzZXJ2YWJsZURPTSBjbGFzcyBoYW5kbGVzIHRoZSBydW5uaW5nIG9mIGFuIEhUTUwgZG9jdW1lbnQgdXNpbmcgYSBwcm92aWRlZCBET01SdW5uZXJGYWN0b3J5IGFuZCBjb252ZXJ0aW5nIHRoZVxuICogbXV0YXRpb25zIHRoYXQgYXJlIHN0cnVjdHVyZWQgYXMgcmVmZXJlbmNlcyB0byBsaXZlIERPTSBlbGVtZW50cyBpbnRvIG1lc3NhZ2VzIHRoYXQgcmVmZXIgdG8gZWxlbWVudHMgYnkgbm9kZUlkcy5cbiAqL1xuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuICBwcml2YXRlIGxvYWRlZCA9IGZhbHNlO1xuICBwcml2YXRlIHByZUxvYWRMb2dNZXNzYWdlczogQXJyYXk8TG9nTWVzc2FnZT4gPSBbXTtcblxuICBwcml2YXRlIGRvY3VtZW50VGltZUludGVydmFsVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzOiBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycyxcbiAgICBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkLFxuICAgIHJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnksXG4gICkge1xuICAgIHRoaXMuaHRtbFBhdGggPSBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aDtcbiAgICB0aGlzLmlnbm9yZVRleHROb2RlcyA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmlnbm9yZVRleHROb2RlcztcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICB0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICB7XG4gICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLFxuICAgICAgKTtcbiAgICB9LCBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5waW5nSW50ZXJ2YWxNaWxsaXNlY29uZHMgfHwgNTAwMCk7XG5cbiAgICB0aGlzLmRvbVJ1bm5lciA9IHJ1bm5lckZhY3RvcnkoXG4gICAgICBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aCxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxDb250ZW50cyxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBhcmFtcyxcbiAgICAgIChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChkb21SdW5uZXJNZXNzYWdlLmxvYWRlZCkge1xuICAgICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoXG4gICAgICAgICAgICB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNuYXBzaG90LFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICAgIGZvciAoY29uc3QgbG9nTWVzc2FnZSBvZiB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcykge1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIGlmICghdGhpcy5sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzLnB1c2goZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbG9nTWVzc2FnZTogZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlLFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJkaXNjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChtdXRhdGlvbkxpc3Q6IEFycmF5PE11dGF0aW9uUmVjb3JkPik6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudDtcbiAgICBjb25zdCBkb2N1bWVudFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KGRvY3VtZW50RWwpO1xuICAgIGlmICghZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBkb2N1bWVudCBub3QgY3JlYXRlZCBpbiBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdGApO1xuICAgIH1cblxuICAgIGlmIChtdXRhdGlvbkxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy8gVE9ETyAoaHR0cHM6Ly9naXRodWIuY29tL21tbC1pby9tbWwvaXNzdWVzLzEwMCkgLSB3YWxrIGJhY2sgdGhyb3VnaCB0aGUgcmVjb3JkcyB0byBkZXJpdmUgdGhlIGludGVybWVkaWF0ZVxuICAgICAgLy8gIHN0YXRlcyAoZS5nLiBpZiBhbiBhdHRyaWJ1dGUgaXMgbGF0ZXIgYWRkZWQgdG8gYW4gZWxlbWVudCBjcmVhdGVkIGluIGFuIGVhcmxpZXIgcmVjb3JkIHRoZW4gaXQgc2hvdWxkIG5vdFxuICAgICAgLy8gIGhhdmUgdGhhdCBhdHRyaWJ1dGUgd2hlbiB0aGUgZWxlbWVudCBpcyBhZGRlZC4gVGhpcyBpcyBpbXBvcnRhbnQgYXMgaW5jb3JyZWN0IGF0dHJpYnV0ZSBzZXRzIGNhbiBhZmZlY3RcbiAgICAgIC8vICB2aXNpYmlsaXR5IGFuZCBleHBlY3RlZCBjbGllbnQgcGVyZm9ybWFuY2UuXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIiAmJlxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICB0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQsIG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldCh0YXJnZXROb2RlKTtcbiAgICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIG5vZGU6XCIgKyB0YXJnZXROb2RlICsgXCIsXCIgKyBtdXRhdGlvbi50eXBlKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZzogRWxlbWVudCB8IFRleHQgfCBudWxsID0gbXV0YXRpb24ucHJldmlvdXNTaWJsaW5nIGFzXG4gICAgICAgIHwgRWxlbWVudFxuICAgICAgICB8IFRleHQ7XG4gICAgICBsZXQgaW5zZXJ0aW9uSW5kZXggPSAwO1xuICAgICAgd2hpbGUgKFxuICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgJiZcbiAgICAgICAgdGhpcy5pc0lnbm9yZWRFbGVtZW50KGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dClcbiAgICAgICkge1xuICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgPSBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcucHJldmlvdXNTaWJsaW5nIGFzXG4gICAgICAgICAgfCBFbGVtZW50XG4gICAgICAgICAgfCBUZXh0XG4gICAgICAgICAgfCBudWxsO1xuICAgICAgfVxuICAgICAgbGV0IHByZXZpb3VzU2libGluZ0VsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICAgIGlmIChmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcpIHtcbiAgICAgICAgcHJldmlvdXNTaWJsaW5nRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChcbiAgICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICk7XG4gICAgICAgIGlmICghcHJldmlvdXNTaWJsaW5nRWxlbWVudCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gcHJldmlvdXMgc2libGluZ1wiKTtcbiAgICAgICAgfVxuICAgICAgICBpbnNlcnRpb25JbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKHByZXZpb3VzU2libGluZ0VsZW1lbnQpO1xuICAgICAgICBpZiAoaW5zZXJ0aW9uSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUHJldmlvdXMgc2libGluZyBpcyBub3QgY3VycmVudGx5IGEgY2hpbGQgb2YgdGhlIHBhcmVudCBlbGVtZW50XCIpO1xuICAgICAgICB9XG4gICAgICAgIGluc2VydGlvbkluZGV4ICs9IDE7XG4gICAgICB9XG4gICAgICBjb25zdCB0b0FkZDogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PiA9IFtdO1xuICAgICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcblxuICAgICAgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiY2hpbGRMaXN0XCIpIHtcbiAgICAgICAgbXV0YXRpb24ucmVtb3ZlZE5vZGVzLmZvckVhY2goKG5vZGU6IE5vZGUpID0+IHtcbiAgICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQoYXNFbGVtZW50T3JUZXh0KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBjaGlsZERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoYXNFbGVtZW50T3JUZXh0KTtcbiAgICAgICAgICBpZiAoIWNoaWxkRE9NRWxlbWVudCkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICBUaGlzIGNhbiBoYXBwZW4gaWYgZWxlbWVudCB3YXMgYSBjaGlsZCBvZiBhIHBhcmVudCBlbGVtZW50LCBidXQgd2FzIG1vdmVkIHRvIGEgbmV3IHBhcmVudCBpbiB0aGUgc2FtZSBiYXRjaCBvZiBtdXRhdGlvbnMuXG4gICAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgVGhpcyBjYW4gaGFwcGVuIGlmIGVsZW1lbnQgd2FzIGEgY2hpbGQgb2YgYSBwYXJlbnQgZWxlbWVudCwgYnV0IHdhcyBtb3ZlZCB0byBhIG5ldyBwYXJlbnQgaW4gdGhlIHNhbWUgYmF0Y2ggb2YgbXV0YXRpb25zLlxuICAgICAgICAgICAgIFdlIGNhbiBpZ25vcmUgdGhpcyByZW1vdmFsIGFzIHRoZSBlbGVtZW50IHdpbGwgYmUgaW4gdGhlIGNvcnJlY3QgcGxhY2UgaW4gdGhlIGhpZXJhcmNoeSBhbHJlYWR5LlxuICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMucmVtb3ZlVmlydHVhbERPTUVsZW1lbnQoY2hpbGRET01FbGVtZW50KTtcbiAgICAgICAgICAgICAgcmVtb3ZlZE5vZGVJZHMucHVzaChjaGlsZERPTUVsZW1lbnQubm9kZUlkKTtcbiAgICAgICAgICAgICAgY29uc3QgcmVtb3ZhbCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICBpZiAocmVtb3ZhbC5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZW1vdmFsIGxlbmd0aCBub3QgMVwiKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAocmVtb3ZhbFswXS5ub2RlSWQgIT09IGNoaWxkRE9NRWxlbWVudC5ub2RlSWQpIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbm9kZSBpZCBtaXNtYXRjaFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGFzRWxlbWVudE9yVGV4dCA9IG5vZGUgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgICAgaWYgKGFzRWxlbWVudE9yVGV4dC5wYXJlbnROb2RlICE9PSB0YXJnZXROb2RlKSB7XG4gICAgICAgICAgICAvLyBJZ25vcmUgdGhpcyBhZGRpdGlvbiAtIGl0IGlzIGxpa2VseSBvdmVycmlkZGVuIGJ5IGFuIGVhcmxpZXIgYWRkaXRpb24gb2YgdGhpcyBlbGVtZW50IHRvIGl0cyBldmVudHVhbCBub2RlIGluIHRoaXMgbXV0YXRpb24gYmF0Y2hcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICAgIGFzRWxlbWVudE9yVGV4dCxcbiAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgICAgICAgICB0b0FkZC5wdXNoKGNoaWxkVmlydHVhbERPTUVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5zZXJ0aW9uSW5kZXgsIDAsIC4uLnRvQWRkKTtcbiAgICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgICBpZiAoIXRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKHRhcmdldE5vZGUsIGF0dHJpYnV0ZU5hbWUpKSB7XG4gICAgICAgICAgY29uc3QgYXR0cmlidXRlVmFsdWUgPSAodGFyZ2V0Tm9kZSBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSk7XG4gICAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICBkZWxldGUgdGFyZ2V0RWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSBhdHRyaWJ1dGVWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGFyYWN0ZXJEYXRhXCIpIHtcbiAgICAgICAgdGFyZ2V0RWxlbWVudC50ZXh0Q29udGVudCA9IHRhcmdldE5vZGUudGV4dENvbnRlbnQgPyB0YXJnZXROb2RlLnRleHRDb250ZW50IDogdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICAvLyBDb252ZXJ0IHRoZSBcInJlYWxcIiBET00gTXV0YXRpb25SZWNvcmQgaW50byBhIFwidmlydHVhbFwiIERPTSBNdXRhdGlvblJlY29yZCB0aGF0IHJlZmVyZW5jZXMgdGhlIFZpcnR1YWxET01FbGVtZW50c1xuICAgICAgLy8gVGhpcyBpcyBkb25lIHNvIHRoYXQgdGhlIHNhbWUgcHJvY2VzcyBmb3IgaGFuZGxpbmcgbXV0YXRpb25zIGNhbiBiZSB1c2VkIGZvciBib3RoIGNoYW5nZXMgdG8gYSBsaXZlIERPTSBhbmQgYWxzb1xuICAgICAgLy8gdG8gZGlmZnMgYmV0d2VlbiBET00gc25hcHNob3RzIHdoZW4gcmVsb2FkaW5nXG5cbiAgICAgIGNvbnN0IGFkZGVkTm9kZXM6IEFycmF5PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50PiA9IHRvQWRkLm1hcCh2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKTtcblxuICAgICAgY29uc3QgbXV0YXRpb25SZWNvcmQ6IFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCA9IHtcbiAgICAgICAgdHlwZTogbXV0YXRpb24udHlwZSxcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICBhZGRlZE5vZGVzLFxuICAgICAgICByZW1vdmVkTm9kZUlkcyxcbiAgICAgICAgcHJldmlvdXNTaWJsaW5nSWQ6IHByZXZpb3VzU2libGluZ0VsZW1lbnQgPyBwcmV2aW91c1NpYmxpbmdFbGVtZW50Lm5vZGVJZCA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlVmlydHVhbERPTUVsZW1lbnQodmlydHVhbERPTUVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IHZvaWQge1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgIHRoaXMubm9kZVRvTm9kZUlkLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50LnJlYWxFbGVtZW50KTtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMpIHtcbiAgICAgIHRoaXMucmVtb3ZlVmlydHVhbERPTUVsZW1lbnQoY2hpbGQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsIHtcbiAgICBjb25zdCBbdmlydHVhbEVsZW1lbnQsIGV4aXN0aW5nXSA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnQobm9kZSwgcGFyZW50KTtcbiAgICBpZiAoIXZpcnR1YWxFbGVtZW50KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXMpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjaGlsZCA9IChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXNbaV07XG4gICAgICAgIGNvbnN0IGNoaWxkVmlydHVhbEVsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgIGNoaWxkIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LFxuICAgICAgICApO1xuICAgICAgICBpZiAoY2hpbGRWaXJ0dWFsRWxlbWVudCkge1xuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LmNoaWxkTm9kZXMucHVzaChjaGlsZFZpcnR1YWxFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnQoXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBbTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCwgYm9vbGVhbl0ge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBbbnVsbCwgZmFsc2VdO1xuICAgIH1cbiAgICBpZiAoIW5vZGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhc3NpZ24gbm9kZSBpZCB0byBudWxsXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmFsdWUgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQobm9kZSk7XG4gICAgaWYgKGV4aXN0aW5nVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLypcbiAgICAgICBUaGlzIGlzIHVuZGVzaXJhYmxlLCBidXQgdGhlIGJhdGNoaW5nIG9mIG11dGF0aW9ucyBmcm9tIE11dGF0aW9uT2JzZXJ2ZXIgbWVhbnMgdGhhdFxuICAgICAgIHRoaXMgbm9kZSBjb3VsZCBiZSBiZWluZyBhZGRlZCBpbiBhIG11dGF0aW9uIGFmdGVyIGEgbXV0YXRpb24gb2YgYSBwYXJlbnQgdGhhdCB3aGVuXG4gICAgICAgaGFuZGxlZCByZXN1bHRpbmcgaW4gYWRkaW5nIHRoaXMgbm9kZSBlYXJseS5cbiAgICAgICovXG4gICAgICByZXR1cm4gW2V4aXN0aW5nVmFsdWUsIHRydWVdO1xuICAgIH1cblxuICAgIGNvbnN0IGF0dHJpYnV0ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBpZiAoKG5vZGUgYXMgYW55KS5hdHRyaWJ1dGVzKSB7XG4gICAgICBjb25zdCBhc0hUTUxFbGVtZW50ID0gbm9kZSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlTmFtZXMoKSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk51bGwgYXR0cmlidXRlIHZhbHVlIGZvciBrZXk6IFwiICsga2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKG5vZGUsIGtleSkpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG5vZGVJZCA9IHRoaXMubmV4dE5vZGVJZCsrO1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSB7XG4gICAgICBub2RlSWQsXG4gICAgICB0YWc6IG5vZGUubm9kZU5hbWUsXG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgY2hpbGROb2RlczogW10sXG4gICAgICByZWFsRWxlbWVudDogbm9kZSxcbiAgICAgIHBhcmVudCxcbiAgICB9O1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCAmJiBub2RlLnRleHRDb250ZW50KSB7XG4gICAgICB2aXJ0dWFsRWxlbWVudC50ZXh0Q29udGVudCA9IG5vZGUudGV4dENvbnRlbnQ7XG4gICAgfVxuICAgIHRoaXMubm9kZVRvTm9kZUlkLnNldCh2aXJ0dWFsRWxlbWVudCwgbm9kZUlkKTtcbiAgICB0aGlzLm5vZGVJZFRvTm9kZS5zZXQobm9kZUlkLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuc2V0KG5vZGUsIHZpcnR1YWxFbGVtZW50KTtcbiAgICByZXR1cm4gW3ZpcnR1YWxFbGVtZW50LCBmYWxzZV07XG4gIH1cblxuICBwcml2YXRlIGdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dCxcbiAgKTogTGl2ZVZpcnR1YWxET01FbGVtZW50IHtcbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChyZWFsRWxlbWVudCk7XG4gICAgaWYgKCF2aXJ0dWFsRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBWaXJ0dWFsIGVsZW1lbnQgbm90IGZvdW5kIGZvciByZWFsIGVsZW1lbnRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0lnbm9yZWRFbGVtZW50KG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuaWdub3JlVGV4dE5vZGVzICYmIG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5IVE1MU2NyaXB0RWxlbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ29tbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkQXR0cmlidXRlKG5vZGU6IEVsZW1lbnQgfCBUZXh0LCBhdHRyaWJ1dGVOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gYXR0cmlidXRlTmFtZS5zdGFydHNXaXRoKFwib25cIik7XG4gIH1cblxuICBwdWJsaWMgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHsgUmVtb3RlRXZlbnQgfSBmcm9tIFwiQG1tbC1pby9uZXR3b3JrZWQtZG9tLXByb3RvY29sXCI7XG5cbmltcG9ydCB7IE9ic2VydmFibGVET01JbnRlcmZhY2UsIE9ic2VydmFibGVET01NZXNzYWdlIH0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgZXZlbnQ6IFJlbW90ZUV2ZW50O1xufTtcblxuZXhwb3J0IHR5cGUgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID1cbiAgfCBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZTtcblxudHlwZSBET01NZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRE9NX01FU1NBR0VfVFlQRTtcbiAgbWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9IERPTU1lc3NhZ2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1lc3NhZ2VUb09ic2VydmFibGVET01JbnN0YW5jZShcbiAgbWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBpbnN0YW5jZTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbikge1xuICBpZiAobWVzc2FnZS50eXBlID09PSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuYWRkQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5yZW1vdmVDb25uZWN0ZWRVc2VySWQobWVzc2FnZS5jb25uZWN0aW9uSWQpO1xuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChtZXNzYWdlLmNvbm5lY3Rpb25JZCwgbWVzc2FnZS5ldmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIG1lc3NhZ2UpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvYnNlcnZhYmxlRE9NSW50ZXJmYWNlVG9NZXNzYWdlU2VuZGVyKFxuICBzZW5kZXI6IChtZXNzYWdlOiBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UpID0+IHZvaWQsXG4gIGRpc3Bvc2U6ICgpID0+IHZvaWQsXG4pIHtcbiAgY29uc3QgcmVtb3RlT2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSA9IHtcbiAgICBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgZXZlbnQ6IHJlbW90ZUV2ZW50LFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgZGlzcG9zZSgpO1xuICAgIH0sXG4gICAgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuICByZXR1cm4gcmVtb3RlT2JzZXJ2YWJsZURPTTtcbn1cbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcbmltcG9ydCB7IERPTVJ1bm5lckZhY3RvcnksIERPTVJ1bm5lckludGVyZmFjZSwgRE9NUnVubmVyTWVzc2FnZSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmxldCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcbmlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKSAtIChkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXIpO1xufVxuXG4vKipcbiAqIFdlYkJyb3dzZXJET01SdW5uZXIgaXMgYSBET01SdW5uZXJJbnRlcmZhY2UgaW1wbGVtZW50YXRpb24gdGhhdCBydW5zIGluIGEgd2ViIGJyb3dzZXIuIEl0IGlzIGludGVuZGVkIHRvIGJlIHJ1biBpblxuICogYW4gaWZyYW1lIGFuZCB0aGUgcGFyZW50IHdpbmRvdyBpcyBleHBlY3RlZCB0byBzZW5kIG1lc3NhZ2VzIHRvIGl0IHRvIGRpc3BhdGNoIGV2ZW50cyBhbmQgdG8gcmVjZWl2ZSBtdXRhdGlvblxuICogbWVzc2FnZXMuXG4gKlxuICogSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgZG9jdW1lbnQgY29udGVudHMgaXMgaW5qZWN0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJCcm93c2VyRE9NUnVubmVyIGltcGxlbWVudHMgRE9NUnVubmVySW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBtdXRhdGlvbk9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IG9iamVjdCwgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkKSB7XG4gICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuXG4gICAgLy8gRm9yd2FyZCBjb25zb2xlIG1lc3NhZ2VzXG4gICAgZm9yIChjb25zdCBsZXZlbCBvZiBbXCJlcnJvclwiLCBcIndhcm5cIiwgXCJpbmZvXCIsIFwibG9nXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBkZWZhdWx0Rm4gPSB3aW5kb3cuY29uc29sZVtsZXZlbF07XG5cbiAgICAgIHdpbmRvdy5jb25zb2xlW2xldmVsXSA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGFyZ3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlZmF1bHRGbiguLi5hcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRm9yd2FyZCB1bmNhdWdodCBlcnJvcnNcbiAgICB3aW5kb3cub25lcnJvciA9IChtZXNzYWdlLCBzb3VyY2UsIGxpbmUsIGNvbHVtbiwgZXJyb3IpID0+IHtcbiAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgIGxldmVsOiBcInN5c3RlbVwiLFxuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgdHlwZTogZXJyb3I/Lm5hbWUsXG4gICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgIGNvbHVtbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBsZXQgZGlkU2VuZExvYWQgPSBmYWxzZTtcblxuICAgIHRoaXMubXV0YXRpb25PYnNlcnZlciA9IG5ldyB3aW5kb3cuTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25MaXN0KSA9PiB7XG4gICAgICBpZiAoIWRvY3VtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXV0YXRpb25PYnNlcnZlciBjYWxsZWQgYmVmb3JlIGxvYWRcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbXV0YXRpb25MaXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAod2luZG93IGFzIGFueSkucGFyYW1zID0gcGFyYW1zO1xuXG4gICAgY29uc3QgZmluaXNoTG9hZCA9ICgpID0+IHtcbiAgICAgIGlmIChkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5pc2hMb2FkIGNhbGxlZCB0d2ljZVwiKTtcbiAgICAgIH1cbiAgICAgIGRpZFNlbmRMb2FkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHRoaXMubXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHdpbmRvdy5kb2N1bWVudCwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICBzZXRUaW1lb3V0KGZpbmlzaExvYWQsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgZmluaXNoTG9hZCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBidWJibGVzID0gcmVtb3RlRXZlbnQuYnViYmxlcyB8fCBmYWxzZTtcbiAgICBjb25zdCByZW1vdGVFdmVudE9iamVjdCA9IG5ldyBDdXN0b21FdmVudChyZW1vdGVFdmVudC5uYW1lLCB7XG4gICAgICBidWJibGVzLFxuICAgICAgZGV0YWlsOiB7IC4uLnJlbW90ZUV2ZW50LnBhcmFtcywgY29ubmVjdGlvbklkIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBldmVudFR5cGVMb3dlckNhc2UgPSByZW1vdGVFdmVudC5uYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBUT0RPIC0gY2hlY2sgaWYgdGhlcmUgYXJlIG90aGVyIGV2ZW50cyB0aGF0IGF1dG9tYXRpY2FsbHkgd2lyZSB1cCBzaW1pbGFybHkgdG8gY2xpY2stPm9uY2xpY2sgYW5kIGF2b2lkIHRob3NlIHRvb1xuICAgIGlmIChldmVudFR5cGVMb3dlckNhc2UgIT09IFwiY2xpY2tcIikge1xuICAgICAgY29uc3QgaGFuZGxlckF0dHJpYnV0ZU5hbWUgPSBcIm9uXCIgKyBldmVudFR5cGVMb3dlckNhc2U7XG4gICAgICBjb25zdCBoYW5kbGVyQXR0cmlidXRlVmFsdWUgPSByZWFsRWxlbWVudC5nZXRBdHRyaWJ1dGUoaGFuZGxlckF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSkge1xuICAgICAgICAvLyBUaGlzIGV2ZW50IGlzIGRlZmluZWQgYXMgYW4gSFRNTCBldmVudCBhdHRyaWJ1dGUuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZm4gPSBGdW5jdGlvbihcImV2ZW50XCIsIGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSk7XG4gICAgICAgICAgZm4uYXBwbHkocmVhbEVsZW1lbnQsIFtyZW1vdGVFdmVudE9iamVjdF0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHJ1bm5pbmcgZXZlbnQgaGFuZGxlcjpcIiwgZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0aGUgZXZlbnQgdmlhIEphdmFTY3JpcHQuXG4gICAgcmVhbEVsZW1lbnQuZGlzcGF0Y2hFdmVudChyZW1vdGVFdmVudE9iamVjdCk7XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIC8vIFRPRE8gLSBoYW5kbGUgZGlzcG9zZVxuICAgIGNvbnNvbGUubG9nKFwiV2ViQnJvd3NlckRPTVJ1bm5lci5kaXNwb3NlXCIpO1xuICB9XG5cbiAgZ2V0RG9jdW1lbnQoKTogRG9jdW1lbnQge1xuICAgIHJldHVybiBkb2N1bWVudDtcbiAgfVxuXG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXIge1xuICAgIGNvbnN0IGRhdGVCYXNlZERvY3VtZW50VGltZSA9IERhdGUubm93KCkgLSBkb2N1bWVudExvYWRUaW1lO1xuICAgIGlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICAgICAgY29uc3QgdGltZSA9IGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lIGFzIG51bWJlcjtcbiAgICAgIGlmIChkYXRlQmFzZWREb2N1bWVudFRpbWUgPiB0aW1lICsgNTAwKSB7XG4gICAgICAgIC8vIFRoZSB0aW1lbGluZSBjYW4gYmUgXCJsZWZ0IGJlaGluZFwiIGlmIHRoZSB0YWIgaXMgYmFja2dyb3VuZGVkIGZvciBhIHdoaWxlLCBzbyB3ZSB1c2UgdGhlIGRhdGUtYmFzZWQgdGltZVxuICAgICAgICAvLyBpbnN0ZWFkLiBJZi93aGVuIHRoZSBkb2N1bWVudCBpcyBicm91Z2h0IGJhY2sgaW50byB0aGUgZm9yZWdyb3VuZCwgdGhlIHRpbWVsaW5lIHdpbGwgY2F0Y2ggdXAuXG4gICAgICAgIHJldHVybiBkYXRlQmFzZWREb2N1bWVudFRpbWU7XG4gICAgICB9XG4gICAgICAvLyBJZGVhbCBjYXNlIC0gdXNlIHRoZSBkb2N1bWVudC50aW1lbGluZSBhcyBpdCdzIHdoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSBkb2N1bWVudCBzY3JpcHRcbiAgICAgIHJldHVybiB0aW1lO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUJhc2VkRG9jdW1lbnRUaW1lO1xuICB9XG5cbiAgLy8gVE9ETyAtIHJlc29sdmUgdHlwZXMgKFdpbmRvdyBuZWVkcyB0byBleHBvc2UgY2xhc3NlcyBzdWNoIGFzIEN1c3RvbUV2ZW50IGFzIHByb3BlcnRpZXMpXG4gIGdldFdpbmRvdygpOiBhbnkge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH1cbn1cbiIsICJpbXBvcnQgeyBPYnNlcnZhYmxlRE9NIH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20vc3JjL09ic2VydmFibGVET01cIjtcbmltcG9ydCB7XG4gIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICBET01fTUVTU0FHRV9UWVBFLFxuICBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG59IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tLWNvbW1vblwiO1xuXG5pbXBvcnQgeyBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSB9IGZyb20gXCIuL1dlYkJyb3dzZXJET01SdW5uZXJcIjtcblxuLyoqXG4gKiBUaGlzIGlzIHJ1biBpbiB0aGUgaWZyYW1lIHRoYXQgd2lsbCBleGVjdXRlIHRoZSBkb2N1bWVudCBzY3JpcHQgdG8gc2V0dXAgdGhlIGxpc3RlbmluZyBmb3IgZXZlbnRzIG1lc3NhZ2VzIGFuZFxuICogb2JzZXJ2aW5nIG9mIERPTSBtdXRhdGlvbiB1c2luZyB0aGUgV2ViQnJvd3NlckRPTVJ1bm5lciBjbGFzcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBzZXR1cElmcmFtZVdlYlJ1bm5lciB9IGZyb20gXCIuL0lmcmFtZVdlYlJ1bm5lclwiO1xuXG5jb25zdCBhcmdzID0gKHdpbmRvdyBhcyBhbnkpLmFyZ3M7XG5zZXR1cElmcmFtZVdlYlJ1bm5lcihhcmdzKTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFJTyxTQUFTLDBCQUEwQixJQUFvRDtBQUM1RixTQUFPO0FBQUEsSUFDTCxRQUFRLEdBQUc7QUFBQSxJQUNYLEtBQUssR0FBRztBQUFBLElBQ1IsWUFBWSxHQUFHO0FBQUEsSUFDZixZQUFZLEdBQUcsV0FBVyxJQUFJLENBQUMsVUFBVSwwQkFBMEIsS0FBSyxDQUFDO0FBQUEsSUFDekUsYUFBYSxHQUFHO0FBQUEsRUFDbEI7QUFDRjs7O0FDd0NPLElBQU0sZ0JBQU4sTUFBc0Q7QUFBQSxFQWMzRCxZQUNFLHlCQUNBLFVBQ0EsZUFDQTtBQWpCRixTQUFRLGVBQWUsb0JBQUksSUFBbUM7QUFDOUQsU0FBUSxlQUFlLG9CQUFJLElBQW1DO0FBQzlELFNBQVEsOEJBQThCLG9CQUFJLElBQTJDO0FBQ3JGLFNBQVEsa0JBQWtCO0FBRTFCLFNBQVEsYUFBYTtBQUdyQixTQUFRLFNBQVM7QUFDakIsU0FBUSxxQkFBd0MsQ0FBQztBQVMvQyxTQUFLLFdBQVcsd0JBQXdCO0FBQ3hDLFNBQUssa0JBQWtCLHdCQUF3QjtBQUMvQyxTQUFLLFdBQVc7QUFF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\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.loaded = false;\n this.preLoadLogMessages = [];\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.loaded = true;\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 for (const logMessage of this.preLoadLogMessages) {\n this.callback(\n {\n logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n this.preLoadLogMessages = [];\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n if (!this.loaded) {\n this.preLoadLogMessages.push(domRunnerMessage.logMessage);\n return;\n }\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 const targetNode = mutation.target;\n const targetElement = this.realElementToVirtualElement.get(targetNode);\n if (!targetElement) {\n throw new Error("Unknown node:" + targetNode + "," + mutation.type);\n }\n let previousSiblingElement = null;\n let insertionIndex = 0;\n const toAdd = [];\n const removedNodeIds = [];\n if (mutation.type === "childList") {\n mutation.removedNodes.forEach((node) => {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n return;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n return;\n } else {\n const index = targetElement.childNodes.indexOf(childDOMElement);\n if (index === -1) {\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n removedNodeIds.push(childDOMElement.nodeId);\n const removal = targetElement.childNodes.splice(index, 1);\n if (removal.length !== 1) {\n throw new Error("Removal length not 1");\n } else {\n if (removal[0].nodeId !== childDOMElement.nodeId) {\n throw new Error("Removal node id mismatch");\n }\n }\n }\n }\n });\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n if (asElementOrText.parentNode !== targetNode) {\n } else {\n if (!previousSiblingElement) {\n let firstNonIgnoredPreviousSibling = asElementOrText.previousSibling;\n let virtualPreviousSibling;\n while (firstNonIgnoredPreviousSibling && !virtualPreviousSibling) {\n virtualPreviousSibling = this.realElementToVirtualElement.get(\n firstNonIgnoredPreviousSibling\n );\n if (virtualPreviousSibling && targetElement.childNodes.indexOf(virtualPreviousSibling) === -1) {\n virtualPreviousSibling = void 0;\n }\n firstNonIgnoredPreviousSibling = firstNonIgnoredPreviousSibling.previousSibling;\n }\n if (virtualPreviousSibling) {\n previousSiblingElement = virtualPreviousSibling;\n insertionIndex = targetElement.childNodes.indexOf(previousSiblingElement);\n if (insertionIndex === -1) {\n throw new Error(\n "Previous sibling is not currently a child of the parent element"\n );\n }\n insertionIndex += 1;\n }\n }\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n targetElement\n );\n if (childVirtualDOMElement) {\n toAdd.push(childVirtualDOMElement);\n }\n }\n });\n targetElement.childNodes.splice(insertionIndex, 0, ...toAdd);\n } else if (mutation.type === "attributes") {\n const attributeName = mutation.attributeName;\n if (!this.isIgnoredAttribute(targetNode, attributeName)) {\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete targetElement.attributes[attributeName];\n } else {\n targetElement.attributes[attributeName] = attributeValue;\n }\n }\n } else if (mutation.type === "characterData") {\n targetElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n const addedNodes = toAdd.map(virtualDOMElementToStatic);\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: previousSiblingElement ? previousSiblingElement.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 }\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, existing] = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (existing) {\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, false];\n }\n if (!node) {\n throw new Error("Cannot assign node id to null");\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n return [existingValue, true];\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, false];\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(params, callback);\n};\nvar documentLoadTime = Date.now();\nif (document.timeline && document.timeline.currentTime) {\n documentLoadTime = Date.now() - document.timeline.currentTime;\n}\nvar WebBrowserDOMRunner = class {\n constructor(params, callback) {\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 const eventTypeLowerCase = remoteEvent.name.toLowerCase();\n if (eventTypeLowerCase !== "click") {\n const handlerAttributeName = "on" + eventTypeLowerCase;\n const handlerAttributeValue = realElement.getAttribute(handlerAttributeName);\n if (handlerAttributeValue) {\n try {\n const fn = Function("event", handlerAttributeValue);\n fn.apply(realElement, [remoteEventObject]);\n } catch (e) {\n console.error("Error running event handler:", e);\n }\n }\n }\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log("WebBrowserDOMRunner.dispose");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n const dateBasedDocumentTime = Date.now() - documentLoadTime;\n if (document.timeline && document.timeline.currentTime) {\n const time = document.timeline.currentTime;\n if (dateBasedDocumentTime > time + 500) {\n return dateBasedDocumentTime;\n }\n return time;\n }\n return dateBasedDocumentTime;\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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuLyoqXG4gKiBUaGUgT2JzZXJ2YWJsZURPTSBjbGFzcyBoYW5kbGVzIHRoZSBydW5uaW5nIG9mIGFuIEhUTUwgZG9jdW1lbnQgdXNpbmcgYSBwcm92aWRlZCBET01SdW5uZXJGYWN0b3J5IGFuZCBjb252ZXJ0aW5nIHRoZVxuICogbXV0YXRpb25zIHRoYXQgYXJlIHN0cnVjdHVyZWQgYXMgcmVmZXJlbmNlcyB0byBsaXZlIERPTSBlbGVtZW50cyBpbnRvIG1lc3NhZ2VzIHRoYXQgcmVmZXIgdG8gZWxlbWVudHMgYnkgbm9kZUlkcy5cbiAqL1xuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuICBwcml2YXRlIGxvYWRlZCA9IGZhbHNlO1xuICBwcml2YXRlIHByZUxvYWRMb2dNZXNzYWdlczogQXJyYXk8TG9nTWVzc2FnZT4gPSBbXTtcblxuICBwcml2YXRlIGRvY3VtZW50VGltZUludGVydmFsVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzOiBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycyxcbiAgICBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkLFxuICAgIHJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnksXG4gICkge1xuICAgIHRoaXMuaHRtbFBhdGggPSBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aDtcbiAgICB0aGlzLmlnbm9yZVRleHROb2RlcyA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmlnbm9yZVRleHROb2RlcztcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICB0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICB7XG4gICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLFxuICAgICAgKTtcbiAgICB9LCBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5waW5nSW50ZXJ2YWxNaWxsaXNlY29uZHMgfHwgNTAwMCk7XG5cbiAgICB0aGlzLmRvbVJ1bm5lciA9IHJ1bm5lckZhY3RvcnkoXG4gICAgICBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aCxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxDb250ZW50cyxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBhcmFtcyxcbiAgICAgIChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChkb21SdW5uZXJNZXNzYWdlLmxvYWRlZCkge1xuICAgICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoXG4gICAgICAgICAgICB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNuYXBzaG90LFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICAgIGZvciAoY29uc3QgbG9nTWVzc2FnZSBvZiB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcykge1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIGlmICghdGhpcy5sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzLnB1c2goZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbG9nTWVzc2FnZTogZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlLFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJkaXNjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChtdXRhdGlvbkxpc3Q6IEFycmF5PE11dGF0aW9uUmVjb3JkPik6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudDtcbiAgICBjb25zdCBkb2N1bWVudFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KGRvY3VtZW50RWwpO1xuICAgIGlmICghZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBkb2N1bWVudCBub3QgY3JlYXRlZCBpbiBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdGApO1xuICAgIH1cblxuICAgIGlmIChtdXRhdGlvbkxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy8gVE9ETyAoaHR0cHM6Ly9naXRodWIuY29tL21tbC1pby9tbWwvaXNzdWVzLzEwMCkgLSB3YWxrIGJhY2sgdGhyb3VnaCB0aGUgcmVjb3JkcyB0byBkZXJpdmUgdGhlIGludGVybWVkaWF0ZVxuICAgICAgLy8gIHN0YXRlcyAoZS5nLiBpZiBhbiBhdHRyaWJ1dGUgaXMgbGF0ZXIgYWRkZWQgdG8gYW4gZWxlbWVudCBjcmVhdGVkIGluIGFuIGVhcmxpZXIgcmVjb3JkIHRoZW4gaXQgc2hvdWxkIG5vdFxuICAgICAgLy8gIGhhdmUgdGhhdCBhdHRyaWJ1dGUgd2hlbiB0aGUgZWxlbWVudCBpcyBhZGRlZC4gVGhpcyBpcyBpbXBvcnRhbnQgYXMgaW5jb3JyZWN0IGF0dHJpYnV0ZSBzZXRzIGNhbiBhZmZlY3RcbiAgICAgIC8vICB2aXNpYmlsaXR5IGFuZCBleHBlY3RlZCBjbGllbnQgcGVyZm9ybWFuY2UuXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIiAmJlxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICB0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQsIG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldCh0YXJnZXROb2RlKTtcbiAgICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIG5vZGU6XCIgKyB0YXJnZXROb2RlICsgXCIsXCIgKyBtdXRhdGlvbi50eXBlKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHByZXZpb3VzU2libGluZ0VsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgICAgbGV0IGluc2VydGlvbkluZGV4ID0gMDtcbiAgICAgIGNvbnN0IHRvQWRkOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+ID0gW107XG4gICAgICBjb25zdCByZW1vdmVkTm9kZUlkczogQXJyYXk8bnVtYmVyPiA9IFtdO1xuXG4gICAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgICBtdXRhdGlvbi5yZW1vdmVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGFzRWxlbWVudE9yVGV4dCA9IG5vZGUgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChhc0VsZW1lbnRPclRleHQpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNoaWxkRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChhc0VsZW1lbnRPclRleHQpO1xuICAgICAgICAgIGlmICghY2hpbGRET01FbGVtZW50KSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZiBlbGVtZW50IHdhcyBhIGNoaWxkIG9mIGEgcGFyZW50IGVsZW1lbnQsIGJ1dCB3YXMgbW92ZWQgdG8gYSBuZXcgcGFyZW50IGluIHRoZSBzYW1lIGJhdGNoIG9mIG11dGF0aW9ucy5cbiAgICAgICAgICAgICBXZSBjYW4gaWdub3JlIHRoaXMgcmVtb3ZhbCBhcyB0aGUgZWxlbWVudCB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IHBsYWNlIGluIHRoZSBoaWVyYXJjaHkgYWxyZWFkeS5cbiAgICAgICAgICAgICovXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YoY2hpbGRET01FbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICBUaGlzIGNhbiBoYXBwZW4gaWYgZWxlbWVudCB3YXMgYSBjaGlsZCBvZiBhIHBhcmVudCBlbGVtZW50LCBidXQgd2FzIG1vdmVkIHRvIGEgbmV3IHBhcmVudCBpbiB0aGUgc2FtZSBiYXRjaCBvZiBtdXRhdGlvbnMuXG4gICAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgICAqL1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKGNoaWxkRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgICAgICAgICAgICBjb25zdCByZW1vdmFsID0gdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgIGlmIChyZW1vdmFsLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbGVuZ3RoIG5vdCAxXCIpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChyZW1vdmFsWzBdLm5vZGVJZCAhPT0gY2hpbGRET01FbGVtZW50Lm5vZGVJZCkge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVtb3ZhbCBub2RlIGlkIG1pc21hdGNoXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgbXV0YXRpb24uYWRkZWROb2Rlcy5mb3JFYWNoKChub2RlOiBOb2RlKSA9PiB7XG4gICAgICAgICAgY29uc3QgYXNFbGVtZW50T3JUZXh0ID0gbm9kZSBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgICAgICBpZiAoYXNFbGVtZW50T3JUZXh0LnBhcmVudE5vZGUgIT09IHRhcmdldE5vZGUpIHtcbiAgICAgICAgICAgIC8vIElnbm9yZSB0aGlzIGFkZGl0aW9uIC0gaXQgaXMgbGlrZWx5IG92ZXJyaWRkZW4gYnkgYW4gZWFybGllciBhZGRpdGlvbiBvZiB0aGlzIGVsZW1lbnQgdG8gaXRzIGV2ZW50dWFsIG5vZGUgaW4gdGhpcyBtdXRhdGlvbiBiYXRjaFxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgIEVpdGhlciB0aGVyZSBpcyBubyBwcmV2aW91cyBlbGVtZW50ICh0aGlzIGlzIHRoZSBmaXJzdCBlbGVtZW50KVxuICAgICAgICAgICAgICAgb3IgdGhlIHByZXZpb3VzIGVsZW1lbnQgaGFzIG5vdCB5ZXQgYmVlbiBkZXRlcm1pbmVkLlxuXG4gICAgICAgICAgICAgICBVc2UgdGhlIGN1cnJlbnQgcHJldmlvdXMgc2libGluZyBvZiB0aGlzIGFkZGVkIG5vZGUgYXMgdGhlIGZpcnN0XG4gICAgICAgICAgICAgICBjaG9pY2UgZm9yIHRoZSBwcmV2aW91cyBzaWJsaW5nLCBidXQgb25seSB1c2UgcHJldmlvdXMgc2libGluZ3NcbiAgICAgICAgICAgICAgIHRoYXQgYXJlIG5vdCBpZ25vcmVkIChhcmUgdHJhY2tlZCBhcyB2aXJ0dWFsIGVsZW1lbnRzKS5cbiAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgbGV0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZzogRWxlbWVudCB8IFRleHQgfCBudWxsID1cbiAgICAgICAgICAgICAgICBhc0VsZW1lbnRPclRleHQucHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICAgICAgICBsZXQgdmlydHVhbFByZXZpb3VzU2libGluZzogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB3aGlsZSAoZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nICYmICF2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgdmlydHVhbFByZXZpb3VzU2libGluZyA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChcbiAgICAgICAgICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIHZpcnR1YWxQcmV2aW91c1NpYmxpbmcgJiZcbiAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKHZpcnR1YWxQcmV2aW91c1NpYmxpbmcpID09PSAtMVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgLy8gVGhpcyBlbGVtZW50IGlzIG5vdCBhIGNoaWxkIG9mIHRoZSBwYXJlbnQgZWxlbWVudCAtIGl0IGlzIG5vdCBhIHZhbGlkIHByZXZpb3VzIHNpYmxpbmdcbiAgICAgICAgICAgICAgICAgIHZpcnR1YWxQcmV2aW91c1NpYmxpbmcgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nID0gZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nLnByZXZpb3VzU2libGluZyBhc1xuICAgICAgICAgICAgICAgICAgfCBFbGVtZW50XG4gICAgICAgICAgICAgICAgICB8IFRleHRcbiAgICAgICAgICAgICAgICAgIHwgbnVsbDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmICh2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgcHJldmlvdXNTaWJsaW5nRWxlbWVudCA9IHZpcnR1YWxQcmV2aW91c1NpYmxpbmc7XG4gICAgICAgICAgICAgICAgaW5zZXJ0aW9uSW5kZXggPSB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihwcmV2aW91c1NpYmxpbmdFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoaW5zZXJ0aW9uSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIFwiUHJldmlvdXMgc2libGluZyBpcyBub3QgY3VycmVudGx5IGEgY2hpbGQgb2YgdGhlIHBhcmVudCBlbGVtZW50XCIsXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpbnNlcnRpb25JbmRleCArPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICAgICAgYXNFbGVtZW50T3JUZXh0LFxuICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgICAgIHRvQWRkLnB1c2goY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLnNwbGljZShpbnNlcnRpb25JbmRleCwgMCwgLi4udG9BZGQpO1xuICAgICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICBjb25zdCBhdHRyaWJ1dGVOYW1lID0gbXV0YXRpb24uYXR0cmlidXRlTmFtZSE7XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUodGFyZ2V0Tm9kZSwgYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVWYWx1ZSA9ICh0YXJnZXROb2RlIGFzIEVsZW1lbnQpLmdldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lKTtcbiAgICAgICAgICBpZiAoYXR0cmlidXRlVmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImNoYXJhY3RlckRhdGFcIikge1xuICAgICAgICB0YXJnZXRFbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcblxuICAgICAgY29uc3QgYWRkZWROb2RlczogQXJyYXk8U3RhdGljVmlydHVhbERPTUVsZW1lbnQ+ID0gdG9BZGQubWFwKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMpO1xuXG4gICAgICBjb25zdCBtdXRhdGlvblJlY29yZDogU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkID0ge1xuICAgICAgICB0eXBlOiBtdXRhdGlvbi50eXBlLFxuICAgICAgICB0YXJnZXRJZDogdGFyZ2V0RWxlbWVudC5ub2RlSWQsXG4gICAgICAgIGFkZGVkTm9kZXMsXG4gICAgICAgIHJlbW92ZWROb2RlSWRzLFxuICAgICAgICBwcmV2aW91c1NpYmxpbmdJZDogcHJldmlvdXNTaWJsaW5nRWxlbWVudFxuICAgICAgICAgID8gKHByZXZpb3VzU2libGluZ0VsZW1lbnQgYXMgTGl2ZVZpcnR1YWxET01FbGVtZW50KS5ub2RlSWRcbiAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlVmlydHVhbERPTUVsZW1lbnQodmlydHVhbERPTUVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IHZvaWQge1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgIHRoaXMubm9kZVRvTm9kZUlkLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50LnJlYWxFbGVtZW50KTtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMpIHtcbiAgICAgIHRoaXMucmVtb3ZlVmlydHVhbERPTUVsZW1lbnQoY2hpbGQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsIHtcbiAgICBjb25zdCBbdmlydHVhbEVsZW1lbnQsIGV4aXN0aW5nXSA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnQobm9kZSwgcGFyZW50KTtcbiAgICBpZiAoIXZpcnR1YWxFbGVtZW50KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXMpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjaGlsZCA9IChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXNbaV07XG4gICAgICAgIGNvbnN0IGNoaWxkVmlydHVhbEVsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgIGNoaWxkIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LFxuICAgICAgICApO1xuICAgICAgICBpZiAoY2hpbGRWaXJ0dWFsRWxlbWVudCkge1xuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LmNoaWxkTm9kZXMucHVzaChjaGlsZFZpcnR1YWxFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnQoXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBbTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCwgYm9vbGVhbl0ge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBbbnVsbCwgZmFsc2VdO1xuICAgIH1cbiAgICBpZiAoIW5vZGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhc3NpZ24gbm9kZSBpZCB0byBudWxsXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmFsdWUgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQobm9kZSk7XG4gICAgaWYgKGV4aXN0aW5nVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLypcbiAgICAgICBUaGlzIGlzIHVuZGVzaXJhYmxlLCBidXQgdGhlIGJhdGNoaW5nIG9mIG11dGF0aW9ucyBmcm9tIE11dGF0aW9uT2JzZXJ2ZXIgbWVhbnMgdGhhdFxuICAgICAgIHRoaXMgbm9kZSBjb3VsZCBiZSBiZWluZyBhZGRlZCBpbiBhIG11dGF0aW9uIGFmdGVyIGEgbXV0YXRpb24gb2YgYSBwYXJlbnQgdGhhdCB3aGVuXG4gICAgICAgaGFuZGxlZCByZXN1bHRpbmcgaW4gYWRkaW5nIHRoaXMgbm9kZSBlYXJseS5cbiAgICAgICovXG4gICAgICByZXR1cm4gW2V4aXN0aW5nVmFsdWUsIHRydWVdO1xuICAgIH1cblxuICAgIGNvbnN0IGF0dHJpYnV0ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBpZiAoKG5vZGUgYXMgYW55KS5hdHRyaWJ1dGVzKSB7XG4gICAgICBjb25zdCBhc0hUTUxFbGVtZW50ID0gbm9kZSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlTmFtZXMoKSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk51bGwgYXR0cmlidXRlIHZhbHVlIGZvciBrZXk6IFwiICsga2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKG5vZGUsIGtleSkpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG5vZGVJZCA9IHRoaXMubmV4dE5vZGVJZCsrO1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSB7XG4gICAgICBub2RlSWQsXG4gICAgICB0YWc6IG5vZGUubm9kZU5hbWUsXG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgY2hpbGROb2RlczogW10sXG4gICAgICByZWFsRWxlbWVudDogbm9kZSxcbiAgICAgIHBhcmVudCxcbiAgICB9O1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCAmJiBub2RlLnRleHRDb250ZW50KSB7XG4gICAgICB2aXJ0dWFsRWxlbWVudC50ZXh0Q29udGVudCA9IG5vZGUudGV4dENvbnRlbnQ7XG4gICAgfVxuICAgIHRoaXMubm9kZVRvTm9kZUlkLnNldCh2aXJ0dWFsRWxlbWVudCwgbm9kZUlkKTtcbiAgICB0aGlzLm5vZGVJZFRvTm9kZS5zZXQobm9kZUlkLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuc2V0KG5vZGUsIHZpcnR1YWxFbGVtZW50KTtcbiAgICByZXR1cm4gW3ZpcnR1YWxFbGVtZW50LCBmYWxzZV07XG4gIH1cblxuICBwcml2YXRlIGdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dCxcbiAgKTogTGl2ZVZpcnR1YWxET01FbGVtZW50IHtcbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChyZWFsRWxlbWVudCk7XG4gICAgaWYgKCF2aXJ0dWFsRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBWaXJ0dWFsIGVsZW1lbnQgbm90IGZvdW5kIGZvciByZWFsIGVsZW1lbnRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0lnbm9yZWRFbGVtZW50KG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuaWdub3JlVGV4dE5vZGVzICYmIG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5IVE1MU2NyaXB0RWxlbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ29tbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkQXR0cmlidXRlKG5vZGU6IEVsZW1lbnQgfCBUZXh0LCBhdHRyaWJ1dGVOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gYXR0cmlidXRlTmFtZS5zdGFydHNXaXRoKFwib25cIik7XG4gIH1cblxuICBwdWJsaWMgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHsgUmVtb3RlRXZlbnQgfSBmcm9tIFwiQG1tbC1pby9uZXR3b3JrZWQtZG9tLXByb3RvY29sXCI7XG5cbmltcG9ydCB7IE9ic2VydmFibGVET01JbnRlcmZhY2UsIE9ic2VydmFibGVET01NZXNzYWdlIH0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgZXZlbnQ6IFJlbW90ZUV2ZW50O1xufTtcblxuZXhwb3J0IHR5cGUgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID1cbiAgfCBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZTtcblxudHlwZSBET01NZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRE9NX01FU1NBR0VfVFlQRTtcbiAgbWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9IERPTU1lc3NhZ2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1lc3NhZ2VUb09ic2VydmFibGVET01JbnN0YW5jZShcbiAgbWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBpbnN0YW5jZTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbikge1xuICBpZiAobWVzc2FnZS50eXBlID09PSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuYWRkQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5yZW1vdmVDb25uZWN0ZWRVc2VySWQobWVzc2FnZS5jb25uZWN0aW9uSWQpO1xuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChtZXNzYWdlLmNvbm5lY3Rpb25JZCwgbWVzc2FnZS5ldmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIG1lc3NhZ2UpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvYnNlcnZhYmxlRE9NSW50ZXJmYWNlVG9NZXNzYWdlU2VuZGVyKFxuICBzZW5kZXI6IChtZXNzYWdlOiBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UpID0+IHZvaWQsXG4gIGRpc3Bvc2U6ICgpID0+IHZvaWQsXG4pIHtcbiAgY29uc3QgcmVtb3RlT2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSA9IHtcbiAgICBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgZXZlbnQ6IHJlbW90ZUV2ZW50LFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgZGlzcG9zZSgpO1xuICAgIH0sXG4gICAgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuICByZXR1cm4gcmVtb3RlT2JzZXJ2YWJsZURPTTtcbn1cbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcbmltcG9ydCB7IERPTVJ1bm5lckZhY3RvcnksIERPTVJ1bm5lckludGVyZmFjZSwgRE9NUnVubmVyTWVzc2FnZSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmxldCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcbmlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKSAtIChkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXIpO1xufVxuXG4vKipcbiAqIFdlYkJyb3dzZXJET01SdW5uZXIgaXMgYSBET01SdW5uZXJJbnRlcmZhY2UgaW1wbGVtZW50YXRpb24gdGhhdCBydW5zIGluIGEgd2ViIGJyb3dzZXIuIEl0IGlzIGludGVuZGVkIHRvIGJlIHJ1biBpblxuICogYW4gaWZyYW1lIGFuZCB0aGUgcGFyZW50IHdpbmRvdyBpcyBleHBlY3RlZCB0byBzZW5kIG1lc3NhZ2VzIHRvIGl0IHRvIGRpc3BhdGNoIGV2ZW50cyBhbmQgdG8gcmVjZWl2ZSBtdXRhdGlvblxuICogbWVzc2FnZXMuXG4gKlxuICogSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgZG9jdW1lbnQgY29udGVudHMgaXMgaW5qZWN0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJCcm93c2VyRE9NUnVubmVyIGltcGxlbWVudHMgRE9NUnVubmVySW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBtdXRhdGlvbk9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IG9iamVjdCwgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkKSB7XG4gICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuXG4gICAgLy8gRm9yd2FyZCBjb25zb2xlIG1lc3NhZ2VzXG4gICAgZm9yIChjb25zdCBsZXZlbCBvZiBbXCJlcnJvclwiLCBcIndhcm5cIiwgXCJpbmZvXCIsIFwibG9nXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBkZWZhdWx0Rm4gPSB3aW5kb3cuY29uc29sZVtsZXZlbF07XG5cbiAgICAgIHdpbmRvdy5jb25zb2xlW2xldmVsXSA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGFyZ3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlZmF1bHRGbiguLi5hcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRm9yd2FyZCB1bmNhdWdodCBlcnJvcnNcbiAgICB3aW5kb3cub25lcnJvciA9IChtZXNzYWdlLCBzb3VyY2UsIGxpbmUsIGNvbHVtbiwgZXJyb3IpID0+IHtcbiAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgIGxldmVsOiBcInN5c3RlbVwiLFxuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgdHlwZTogZXJyb3I/Lm5hbWUsXG4gICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgIGNvbHVtbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBsZXQgZGlkU2VuZExvYWQgPSBmYWxzZTtcblxuICAgIHRoaXMubXV0YXRpb25PYnNlcnZlciA9IG5ldyB3aW5kb3cuTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25MaXN0KSA9PiB7XG4gICAgICBpZiAoIWRvY3VtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXV0YXRpb25PYnNlcnZlciBjYWxsZWQgYmVmb3JlIGxvYWRcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbXV0YXRpb25MaXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAod2luZG93IGFzIGFueSkucGFyYW1zID0gcGFyYW1zO1xuXG4gICAgY29uc3QgZmluaXNoTG9hZCA9ICgpID0+IHtcbiAgICAgIGlmIChkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5pc2hMb2FkIGNhbGxlZCB0d2ljZVwiKTtcbiAgICAgIH1cbiAgICAgIGRpZFNlbmRMb2FkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHRoaXMubXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHdpbmRvdy5kb2N1bWVudCwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICBzZXRUaW1lb3V0KGZpbmlzaExvYWQsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgZmluaXNoTG9hZCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBidWJibGVzID0gcmVtb3RlRXZlbnQuYnViYmxlcyB8fCBmYWxzZTtcbiAgICBjb25zdCByZW1vdGVFdmVudE9iamVjdCA9IG5ldyBDdXN0b21FdmVudChyZW1vdGVFdmVudC5uYW1lLCB7XG4gICAgICBidWJibGVzLFxuICAgICAgZGV0YWlsOiB7IC4uLnJlbW90ZUV2ZW50LnBhcmFtcywgY29ubmVjdGlvbklkIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBldmVudFR5cGVMb3dlckNhc2UgPSByZW1vdGVFdmVudC5uYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBUT0RPIC0gY2hlY2sgaWYgdGhlcmUgYXJlIG90aGVyIGV2ZW50cyB0aGF0IGF1dG9tYXRpY2FsbHkgd2lyZSB1cCBzaW1pbGFybHkgdG8gY2xpY2stPm9uY2xpY2sgYW5kIGF2b2lkIHRob3NlIHRvb1xuICAgIGlmIChldmVudFR5cGVMb3dlckNhc2UgIT09IFwiY2xpY2tcIikge1xuICAgICAgY29uc3QgaGFuZGxlckF0dHJpYnV0ZU5hbWUgPSBcIm9uXCIgKyBldmVudFR5cGVMb3dlckNhc2U7XG4gICAgICBjb25zdCBoYW5kbGVyQXR0cmlidXRlVmFsdWUgPSByZWFsRWxlbWVudC5nZXRBdHRyaWJ1dGUoaGFuZGxlckF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSkge1xuICAgICAgICAvLyBUaGlzIGV2ZW50IGlzIGRlZmluZWQgYXMgYW4gSFRNTCBldmVudCBhdHRyaWJ1dGUuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZm4gPSBGdW5jdGlvbihcImV2ZW50XCIsIGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSk7XG4gICAgICAgICAgZm4uYXBwbHkocmVhbEVsZW1lbnQsIFtyZW1vdGVFdmVudE9iamVjdF0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHJ1bm5pbmcgZXZlbnQgaGFuZGxlcjpcIiwgZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0aGUgZXZlbnQgdmlhIEphdmFTY3JpcHQuXG4gICAgcmVhbEVsZW1lbnQuZGlzcGF0Y2hFdmVudChyZW1vdGVFdmVudE9iamVjdCk7XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIC8vIFRPRE8gLSBoYW5kbGUgZGlzcG9zZVxuICAgIGNvbnNvbGUubG9nKFwiV2ViQnJvd3NlckRPTVJ1bm5lci5kaXNwb3NlXCIpO1xuICB9XG5cbiAgZ2V0RG9jdW1lbnQoKTogRG9jdW1lbnQge1xuICAgIHJldHVybiBkb2N1bWVudDtcbiAgfVxuXG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXIge1xuICAgIGNvbnN0IGRhdGVCYXNlZERvY3VtZW50VGltZSA9IERhdGUubm93KCkgLSBkb2N1bWVudExvYWRUaW1lO1xuICAgIGlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICAgICAgY29uc3QgdGltZSA9IGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lIGFzIG51bWJlcjtcbiAgICAgIGlmIChkYXRlQmFzZWREb2N1bWVudFRpbWUgPiB0aW1lICsgNTAwKSB7XG4gICAgICAgIC8vIFRoZSB0aW1lbGluZSBjYW4gYmUgXCJsZWZ0IGJlaGluZFwiIGlmIHRoZSB0YWIgaXMgYmFja2dyb3VuZGVkIGZvciBhIHdoaWxlLCBzbyB3ZSB1c2UgdGhlIGRhdGUtYmFzZWQgdGltZVxuICAgICAgICAvLyBpbnN0ZWFkLiBJZi93aGVuIHRoZSBkb2N1bWVudCBpcyBicm91Z2h0IGJhY2sgaW50byB0aGUgZm9yZWdyb3VuZCwgdGhlIHRpbWVsaW5lIHdpbGwgY2F0Y2ggdXAuXG4gICAgICAgIHJldHVybiBkYXRlQmFzZWREb2N1bWVudFRpbWU7XG4gICAgICB9XG4gICAgICAvLyBJZGVhbCBjYXNlIC0gdXNlIHRoZSBkb2N1bWVudC50aW1lbGluZSBhcyBpdCdzIHdoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSBkb2N1bWVudCBzY3JpcHRcbiAgICAgIHJldHVybiB0aW1lO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUJhc2VkRG9jdW1lbnRUaW1lO1xuICB9XG5cbiAgLy8gVE9ETyAtIHJlc29sdmUgdHlwZXMgKFdpbmRvdyBuZWVkcyB0byBleHBvc2UgY2xhc3NlcyBzdWNoIGFzIEN1c3RvbUV2ZW50IGFzIHByb3BlcnRpZXMpXG4gIGdldFdpbmRvdygpOiBhbnkge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH1cbn1cbiIsICJpbXBvcnQgeyBPYnNlcnZhYmxlRE9NIH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20vc3JjL09ic2VydmFibGVET01cIjtcbmltcG9ydCB7XG4gIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICBET01fTUVTU0FHRV9UWVBFLFxuICBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG59IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tLWNvbW1vblwiO1xuXG5pbXBvcnQgeyBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSB9IGZyb20gXCIuL1dlYkJyb3dzZXJET01SdW5uZXJcIjtcblxuLyoqXG4gKiBUaGlzIGlzIHJ1biBpbiB0aGUgaWZyYW1lIHRoYXQgd2lsbCBleGVjdXRlIHRoZSBkb2N1bWVudCBzY3JpcHQgdG8gc2V0dXAgdGhlIGxpc3RlbmluZyBmb3IgZXZlbnRzIG1lc3NhZ2VzIGFuZFxuICogb2JzZXJ2aW5nIG9mIERPTSBtdXRhdGlvbiB1c2luZyB0aGUgV2ViQnJvd3NlckRPTVJ1bm5lciBjbGFzcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBzZXR1cElmcmFtZVdlYlJ1bm5lciB9IGZyb20gXCIuL0lmcmFtZVdlYlJ1bm5lclwiO1xuXG5jb25zdCBhcmdzID0gKHdpbmRvdyBhcyBhbnkpLmFyZ3M7XG5zZXR1cElmcmFtZVdlYlJ1bm5lcihhcmdzKTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFJTyxTQUFTLDBCQUEwQixJQUFvRDtBQUM1RixTQUFPO0FBQUEsSUFDTCxRQUFRLEdBQUc7QUFBQSxJQUNYLEtBQUssR0FBRztBQUFBLElBQ1IsWUFBWSxHQUFHO0FBQUEsSUFDZixZQUFZLEdBQUcsV0FBVyxJQUFJLENBQUMsVUFBVSwwQkFBMEIsS0FBSyxDQUFDO0FBQUEsSUFDekUsYUFBYSxHQUFHO0FBQUEsRUFDbEI7QUFDRjs7O0FDd0NPLElBQU0sZ0JBQU4sTUFBc0Q7QUFBQSxFQWMzRCxZQUNFLHlCQUNBLFVBQ0EsZUFDQTtBQWpCRixTQUFRLGVBQWUsb0JBQUksSUFBbUM7QUFDOUQsU0FBUSxlQUFlLG9CQUFJLElBQW1DO0FBQzlELFNBQVEsOEJBQThCLG9CQUFJLElBQTJDO0FBQ3JGLFNBQVEsa0JBQWtCO0FBRTFCLFNBQVEs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Q0Y7QUFBQSxJQUNGO0FBR0EsZ0JBQVksY0FBYyxpQkFBaUI7QUFBQSxFQUM3QztBQUFBLEVBRUEsVUFBZ0I7QUFFZCxZQUFRLElBQUksNkJBQTZCO0FBQUEsRUFDM0M7QUFBQSxFQUVBLGNBQXdCO0FBQ3RCLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFQSxrQkFBMEI7QUFDeEIsVUFBTSx3QkFBd0IsS0FBSyxJQUFJLElBQUk7QUFDM0MsUUFBSSxTQUFTLFlBQVksU0FBUyxTQUFTLGFBQWE7QUFDdEQsWUFBTSxPQUFPLFNBQVMsU0FBUztBQUMvQixVQUFJLHdCQUF3QixPQUFPLEtBQUs7QUFHdEMsZUFBTztBQUFBLE1BQ1Q7QUFFQSxhQUFPO0FBQUEsSUFDVDtBQUNBLFdBQU87QUFBQSxFQUNUO0FBQUE7QUFBQSxFQUdBLFlBQWlCO0FBQ2YsV0FBTztBQUFBLEVBQ1Q7QUFDRjs7O0FDaEpPLFNBQVMscUJBQXFCLFlBQW9CO0FBQ3ZELFFBQU0sc0JBQXNCLEtBQUssTUFBTSxLQUFLLFVBQVUsQ0FBQztBQUV2RCxRQUFNLHVCQUF1QixDQUFDLFlBQThDO0FBQzFFLFdBQU8sT0FBTyxZQUFZLEtBQUssVUFBVSxPQUFPLEdBQUcsR0FBRztBQUFBLEVBQ3hEO0FBRUEsUUFBTSxnQkFBZ0IsSUFBSTtBQUFBLElBQ3hCO0FBQUEsTUFDRSxHQUFHO0FBQUEsTUFDSCxjQUFjO0FBQUE7QUFBQSxJQUNoQjtBQUFBLElBQ0EsQ0FBQyx5QkFBK0M7QUFDOUMsMkJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFFBQ04sU0FBUztBQUFBLE1BQ1gsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBO0FBQUEsRUFDRjtBQUVBLFNBQU8saUJBQWlCLFdBQVcsQ0FBQyxNQUFNO0FBQ3hDLFVBQU0sU0FBUyxLQUFLLE1BQU0sRUFBRSxJQUFJO0FBQ2hDLFlBQVEsT0FBTyxNQUFNO0FBQUEsTUFDbkIsS0FBSztBQUNILHNCQUFjLG9DQUFvQyxPQUFPLGNBQWMsT0FBTyxLQUFLO0FBQ25GO0FBQUEsTUFDRixLQUFLO0FBQ0gsc0JBQWMsbUJBQW1CLE9BQU8sWUFBWTtBQUNwRDtBQUFBLE1BQ0YsS0FBSztBQUNILHNCQUFjLHNCQUFzQixPQUFPLFlBQVk7QUFDdkQ7QUFBQSxNQUNGO0FBQ0UsZ0JBQVEsTUFBTSx3QkFBd0IsTUFBTTtBQUFBLElBQ2hEO0FBQUEsRUFDRixDQUFDO0FBQ0g7OztBQ3JEQSxJQUFNLE9BQVEsT0FBZTtBQUM3QixxQkFBcUIsSUFBSTsiLAogICJuYW1lcyI6IFsiYXJncyJdCn0K\n';
6
6
 
7
7
  // src/RunnerIframe.ts
8
8
  var RunnerIframe = class {
@@ -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", "// ../../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.loaded = false;\n this.preLoadLogMessages = [];\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.loaded = true;\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 for (const logMessage of this.preLoadLogMessages) {\n this.callback(\n {\n logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n this.preLoadLogMessages = [];\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n if (!this.loaded) {\n this.preLoadLogMessages.push(domRunnerMessage.logMessage);\n return;\n }\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 const targetNode = mutation.target;\n const targetElement = this.realElementToVirtualElement.get(targetNode);\n if (!targetElement) {\n throw new Error(\"Unknown node:\" + targetNode + \",\" + mutation.type);\n }\n let firstNonIgnoredPreviousSibling = mutation.previousSibling;\n let insertionIndex = 0;\n while (firstNonIgnoredPreviousSibling && this.isIgnoredElement(firstNonIgnoredPreviousSibling)) {\n firstNonIgnoredPreviousSibling = firstNonIgnoredPreviousSibling.previousSibling;\n }\n let previousSiblingElement = void 0;\n if (firstNonIgnoredPreviousSibling) {\n previousSiblingElement = this.realElementToVirtualElement.get(\n firstNonIgnoredPreviousSibling\n );\n if (!previousSiblingElement) {\n throw new Error(\"Unknown previous sibling\");\n }\n insertionIndex = targetElement.childNodes.indexOf(previousSiblingElement);\n if (insertionIndex === -1) {\n throw new Error(\"Previous sibling is not currently a child of the parent element\");\n }\n insertionIndex += 1;\n }\n const toAdd = [];\n const removedNodeIds = [];\n if (mutation.type === \"childList\") {\n mutation.removedNodes.forEach((node) => {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n return;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n return;\n } else {\n const index = targetElement.childNodes.indexOf(childDOMElement);\n if (index === -1) {\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n removedNodeIds.push(childDOMElement.nodeId);\n const removal = targetElement.childNodes.splice(index, 1);\n if (removal.length !== 1) {\n throw new Error(\"Removal length not 1\");\n } else {\n if (removal[0].nodeId !== childDOMElement.nodeId) {\n throw new Error(\"Removal node id mismatch\");\n }\n }\n }\n }\n });\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n if (asElementOrText.parentNode !== targetNode) {\n } else {\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n targetElement\n );\n if (childVirtualDOMElement) {\n toAdd.push(childVirtualDOMElement);\n }\n }\n });\n targetElement.childNodes.splice(insertionIndex, 0, ...toAdd);\n } else if (mutation.type === \"attributes\") {\n const attributeName = mutation.attributeName;\n if (!this.isIgnoredAttribute(targetNode, attributeName)) {\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete targetElement.attributes[attributeName];\n } else {\n targetElement.attributes[attributeName] = attributeValue;\n }\n }\n } else if (mutation.type === \"characterData\") {\n targetElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n const addedNodes = toAdd.map(virtualDOMElementToStatic);\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: previousSiblingElement ? previousSiblingElement.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 }\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, existing] = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (existing) {\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, false];\n }\n if (!node) {\n throw new Error(\"Cannot assign node id to null\");\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n return [existingValue, true];\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, false];\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(params, callback);\n};\nvar documentLoadTime = Date.now();\nif (document.timeline && document.timeline.currentTime) {\n documentLoadTime = Date.now() - document.timeline.currentTime;\n}\nvar WebBrowserDOMRunner = class {\n constructor(params, callback) {\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 const eventTypeLowerCase = remoteEvent.name.toLowerCase();\n if (eventTypeLowerCase !== \"click\") {\n const handlerAttributeName = \"on\" + eventTypeLowerCase;\n const handlerAttributeValue = realElement.getAttribute(handlerAttributeName);\n if (handlerAttributeValue) {\n try {\n const fn = Function(\"event\", handlerAttributeValue);\n fn.apply(realElement, [remoteEventObject]);\n } catch (e) {\n console.error(\"Error running event handler:\", e);\n }\n }\n }\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log(\"WebBrowserDOMRunner.dispose\");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n const dateBasedDocumentTime = Date.now() - documentLoadTime;\n if (document.timeline && document.timeline.currentTime) {\n const time = document.timeline.currentTime;\n if (dateBasedDocumentTime > time + 500) {\n return dateBasedDocumentTime;\n }\n return time;\n }\n return dateBasedDocumentTime;\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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuLyoqXG4gKiBUaGUgT2JzZXJ2YWJsZURPTSBjbGFzcyBoYW5kbGVzIHRoZSBydW5uaW5nIG9mIGFuIEhUTUwgZG9jdW1lbnQgdXNpbmcgYSBwcm92aWRlZCBET01SdW5uZXJGYWN0b3J5IGFuZCBjb252ZXJ0aW5nIHRoZVxuICogbXV0YXRpb25zIHRoYXQgYXJlIHN0cnVjdHVyZWQgYXMgcmVmZXJlbmNlcyB0byBsaXZlIERPTSBlbGVtZW50cyBpbnRvIG1lc3NhZ2VzIHRoYXQgcmVmZXIgdG8gZWxlbWVudHMgYnkgbm9kZUlkcy5cbiAqL1xuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuICBwcml2YXRlIGxvYWRlZCA9IGZhbHNlO1xuICBwcml2YXRlIHByZUxvYWRMb2dNZXNzYWdlczogQXJyYXk8TG9nTWVzc2FnZT4gPSBbXTtcblxuICBwcml2YXRlIGRvY3VtZW50VGltZUludGVydmFsVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzOiBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycyxcbiAgICBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkLFxuICAgIHJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnksXG4gICkge1xuICAgIHRoaXMuaHRtbFBhdGggPSBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aDtcbiAgICB0aGlzLmlnbm9yZVRleHROb2RlcyA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmlnbm9yZVRleHROb2RlcztcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICB0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICB7XG4gICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLFxuICAgICAgKTtcbiAgICB9LCBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5waW5nSW50ZXJ2YWxNaWxsaXNlY29uZHMgfHwgNTAwMCk7XG5cbiAgICB0aGlzLmRvbVJ1bm5lciA9IHJ1bm5lckZhY3RvcnkoXG4gICAgICBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aCxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxDb250ZW50cyxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBhcmFtcyxcbiAgICAgIChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChkb21SdW5uZXJNZXNzYWdlLmxvYWRlZCkge1xuICAgICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoXG4gICAgICAgICAgICB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNuYXBzaG90LFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICAgIGZvciAoY29uc3QgbG9nTWVzc2FnZSBvZiB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcykge1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIGlmICghdGhpcy5sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzLnB1c2goZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbG9nTWVzc2FnZTogZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlLFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJkaXNjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChtdXRhdGlvbkxpc3Q6IEFycmF5PE11dGF0aW9uUmVjb3JkPik6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudDtcbiAgICBjb25zdCBkb2N1bWVudFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KGRvY3VtZW50RWwpO1xuICAgIGlmICghZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBkb2N1bWVudCBub3QgY3JlYXRlZCBpbiBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdGApO1xuICAgIH1cblxuICAgIGlmIChtdXRhdGlvbkxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy8gVE9ETyAoaHR0cHM6Ly9naXRodWIuY29tL21tbC1pby9tbWwvaXNzdWVzLzEwMCkgLSB3YWxrIGJhY2sgdGhyb3VnaCB0aGUgcmVjb3JkcyB0byBkZXJpdmUgdGhlIGludGVybWVkaWF0ZVxuICAgICAgLy8gIHN0YXRlcyAoZS5nLiBpZiBhbiBhdHRyaWJ1dGUgaXMgbGF0ZXIgYWRkZWQgdG8gYW4gZWxlbWVudCBjcmVhdGVkIGluIGFuIGVhcmxpZXIgcmVjb3JkIHRoZW4gaXQgc2hvdWxkIG5vdFxuICAgICAgLy8gIGhhdmUgdGhhdCBhdHRyaWJ1dGUgd2hlbiB0aGUgZWxlbWVudCBpcyBhZGRlZC4gVGhpcyBpcyBpbXBvcnRhbnQgYXMgaW5jb3JyZWN0IGF0dHJpYnV0ZSBzZXRzIGNhbiBhZmZlY3RcbiAgICAgIC8vICB2aXNpYmlsaXR5IGFuZCBleHBlY3RlZCBjbGllbnQgcGVyZm9ybWFuY2UuXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIiAmJlxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICB0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQsIG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldCh0YXJnZXROb2RlKTtcbiAgICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIG5vZGU6XCIgKyB0YXJnZXROb2RlICsgXCIsXCIgKyBtdXRhdGlvbi50eXBlKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZzogRWxlbWVudCB8IFRleHQgfCBudWxsID0gbXV0YXRpb24ucHJldmlvdXNTaWJsaW5nIGFzXG4gICAgICAgIHwgRWxlbWVudFxuICAgICAgICB8IFRleHQ7XG4gICAgICBsZXQgaW5zZXJ0aW9uSW5kZXggPSAwO1xuICAgICAgd2hpbGUgKFxuICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgJiZcbiAgICAgICAgdGhpcy5pc0lnbm9yZWRFbGVtZW50KGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dClcbiAgICAgICkge1xuICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgPSBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcucHJldmlvdXNTaWJsaW5nIGFzXG4gICAgICAgICAgfCBFbGVtZW50XG4gICAgICAgICAgfCBUZXh0XG4gICAgICAgICAgfCBudWxsO1xuICAgICAgfVxuICAgICAgbGV0IHByZXZpb3VzU2libGluZ0VsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICAgIGlmIChmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcpIHtcbiAgICAgICAgcHJldmlvdXNTaWJsaW5nRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChcbiAgICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICk7XG4gICAgICAgIGlmICghcHJldmlvdXNTaWJsaW5nRWxlbWVudCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gcHJldmlvdXMgc2libGluZ1wiKTtcbiAgICAgICAgfVxuICAgICAgICBpbnNlcnRpb25JbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKHByZXZpb3VzU2libGluZ0VsZW1lbnQpO1xuICAgICAgICBpZiAoaW5zZXJ0aW9uSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUHJldmlvdXMgc2libGluZyBpcyBub3QgY3VycmVudGx5IGEgY2hpbGQgb2YgdGhlIHBhcmVudCBlbGVtZW50XCIpO1xuICAgICAgICB9XG4gICAgICAgIGluc2VydGlvbkluZGV4ICs9IDE7XG4gICAgICB9XG4gICAgICBjb25zdCB0b0FkZDogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PiA9IFtdO1xuICAgICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcblxuICAgICAgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiY2hpbGRMaXN0XCIpIHtcbiAgICAgICAgbXV0YXRpb24ucmVtb3ZlZE5vZGVzLmZvckVhY2goKG5vZGU6IE5vZGUpID0+IHtcbiAgICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQoYXNFbGVtZW50T3JUZXh0KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBjaGlsZERPTUVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQoYXNFbGVtZW50T3JUZXh0KTtcbiAgICAgICAgICBpZiAoIWNoaWxkRE9NRWxlbWVudCkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICBUaGlzIGNhbiBoYXBwZW4gaWYgZWxlbWVudCB3YXMgYSBjaGlsZCBvZiBhIHBhcmVudCBlbGVtZW50LCBidXQgd2FzIG1vdmVkIHRvIGEgbmV3IHBhcmVudCBpbiB0aGUgc2FtZSBiYXRjaCBvZiBtdXRhdGlvbnMuXG4gICAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgVGhpcyBjYW4gaGFwcGVuIGlmIGVsZW1lbnQgd2FzIGEgY2hpbGQgb2YgYSBwYXJlbnQgZWxlbWVudCwgYnV0IHdhcyBtb3ZlZCB0byBhIG5ldyBwYXJlbnQgaW4gdGhlIHNhbWUgYmF0Y2ggb2YgbXV0YXRpb25zLlxuICAgICAgICAgICAgIFdlIGNhbiBpZ25vcmUgdGhpcyByZW1vdmFsIGFzIHRoZSBlbGVtZW50IHdpbGwgYmUgaW4gdGhlIGNvcnJlY3QgcGxhY2UgaW4gdGhlIGhpZXJhcmNoeSBhbHJlYWR5LlxuICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMucmVtb3ZlVmlydHVhbERPTUVsZW1lbnQoY2hpbGRET01FbGVtZW50KTtcbiAgICAgICAgICAgICAgcmVtb3ZlZE5vZGVJZHMucHVzaChjaGlsZERPTUVsZW1lbnQubm9kZUlkKTtcbiAgICAgICAgICAgICAgY29uc3QgcmVtb3ZhbCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICBpZiAocmVtb3ZhbC5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZW1vdmFsIGxlbmd0aCBub3QgMVwiKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAocmVtb3ZhbFswXS5ub2RlSWQgIT09IGNoaWxkRE9NRWxlbWVudC5ub2RlSWQpIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbm9kZSBpZCBtaXNtYXRjaFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGFzRWxlbWVudE9yVGV4dCA9IG5vZGUgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgICAgaWYgKGFzRWxlbWVudE9yVGV4dC5wYXJlbnROb2RlICE9PSB0YXJnZXROb2RlKSB7XG4gICAgICAgICAgICAvLyBJZ25vcmUgdGhpcyBhZGRpdGlvbiAtIGl0IGlzIGxpa2VseSBvdmVycmlkZGVuIGJ5IGFuIGVhcmxpZXIgYWRkaXRpb24gb2YgdGhpcyBlbGVtZW50IHRvIGl0cyBldmVudHVhbCBub2RlIGluIHRoaXMgbXV0YXRpb24gYmF0Y2hcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICAgIGFzRWxlbWVudE9yVGV4dCxcbiAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgICAgICAgICB0b0FkZC5wdXNoKGNoaWxkVmlydHVhbERPTUVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5zZXJ0aW9uSW5kZXgsIDAsIC4uLnRvQWRkKTtcbiAgICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgICBpZiAoIXRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKHRhcmdldE5vZGUsIGF0dHJpYnV0ZU5hbWUpKSB7XG4gICAgICAgICAgY29uc3QgYXR0cmlidXRlVmFsdWUgPSAodGFyZ2V0Tm9kZSBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSk7XG4gICAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICBkZWxldGUgdGFyZ2V0RWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSBhdHRyaWJ1dGVWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGFyYWN0ZXJEYXRhXCIpIHtcbiAgICAgICAgdGFyZ2V0RWxlbWVudC50ZXh0Q29udGVudCA9IHRhcmdldE5vZGUudGV4dENvbnRlbnQgPyB0YXJnZXROb2RlLnRleHRDb250ZW50IDogdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICAvLyBDb252ZXJ0IHRoZSBcInJlYWxcIiBET00gTXV0YXRpb25SZWNvcmQgaW50byBhIFwidmlydHVhbFwiIERPTSBNdXRhdGlvblJlY29yZCB0aGF0IHJlZmVyZW5jZXMgdGhlIFZpcnR1YWxET01FbGVtZW50c1xuICAgICAgLy8gVGhpcyBpcyBkb25lIHNvIHRoYXQgdGhlIHNhbWUgcHJvY2VzcyBmb3IgaGFuZGxpbmcgbXV0YXRpb25zIGNhbiBiZSB1c2VkIGZvciBib3RoIGNoYW5nZXMgdG8gYSBsaXZlIERPTSBhbmQgYWxzb1xuICAgICAgLy8gdG8gZGlmZnMgYmV0d2VlbiBET00gc25hcHNob3RzIHdoZW4gcmVsb2FkaW5nXG5cbiAgICAgIGNvbnN0IGFkZGVkTm9kZXM6IEFycmF5PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50PiA9IHRvQWRkLm1hcCh2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKTtcblxuICAgICAgY29uc3QgbXV0YXRpb25SZWNvcmQ6IFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCA9IHtcbiAgICAgICAgdHlwZTogbXV0YXRpb24udHlwZSxcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICBhZGRlZE5vZGVzLFxuICAgICAgICByZW1vdmVkTm9kZUlkcyxcbiAgICAgICAgcHJldmlvdXNTaWJsaW5nSWQ6IHByZXZpb3VzU2libGluZ0VsZW1lbnQgPyBwcmV2aW91c1NpYmxpbmdFbGVtZW50Lm5vZGVJZCA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlVmlydHVhbERPTUVsZW1lbnQodmlydHVhbERPTUVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IHZvaWQge1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgIHRoaXMubm9kZVRvTm9kZUlkLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50LnJlYWxFbGVtZW50KTtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMpIHtcbiAgICAgIHRoaXMucmVtb3ZlVmlydHVhbERPTUVsZW1lbnQoY2hpbGQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsIHtcbiAgICBjb25zdCBbdmlydHVhbEVsZW1lbnQsIGV4aXN0aW5nXSA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnQobm9kZSwgcGFyZW50KTtcbiAgICBpZiAoIXZpcnR1YWxFbGVtZW50KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXMpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjaGlsZCA9IChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXNbaV07XG4gICAgICAgIGNvbnN0IGNoaWxkVmlydHVhbEVsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgIGNoaWxkIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LFxuICAgICAgICApO1xuICAgICAgICBpZiAoY2hpbGRWaXJ0dWFsRWxlbWVudCkge1xuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LmNoaWxkTm9kZXMucHVzaChjaGlsZFZpcnR1YWxFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnQoXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBbTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCwgYm9vbGVhbl0ge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBbbnVsbCwgZmFsc2VdO1xuICAgIH1cbiAgICBpZiAoIW5vZGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhc3NpZ24gbm9kZSBpZCB0byBudWxsXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmFsdWUgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQobm9kZSk7XG4gICAgaWYgKGV4aXN0aW5nVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLypcbiAgICAgICBUaGlzIGlzIHVuZGVzaXJhYmxlLCBidXQgdGhlIGJhdGNoaW5nIG9mIG11dGF0aW9ucyBmcm9tIE11dGF0aW9uT2JzZXJ2ZXIgbWVhbnMgdGhhdFxuICAgICAgIHRoaXMgbm9kZSBjb3VsZCBiZSBiZWluZyBhZGRlZCBpbiBhIG11dGF0aW9uIGFmdGVyIGEgbXV0YXRpb24gb2YgYSBwYXJlbnQgdGhhdCB3aGVuXG4gICAgICAgaGFuZGxlZCByZXN1bHRpbmcgaW4gYWRkaW5nIHRoaXMgbm9kZSBlYXJseS5cbiAgICAgICovXG4gICAgICByZXR1cm4gW2V4aXN0aW5nVmFsdWUsIHRydWVdO1xuICAgIH1cblxuICAgIGNvbnN0IGF0dHJpYnV0ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBpZiAoKG5vZGUgYXMgYW55KS5hdHRyaWJ1dGVzKSB7XG4gICAgICBjb25zdCBhc0hUTUxFbGVtZW50ID0gbm9kZSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlTmFtZXMoKSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk51bGwgYXR0cmlidXRlIHZhbHVlIGZvciBrZXk6IFwiICsga2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKG5vZGUsIGtleSkpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG5vZGVJZCA9IHRoaXMubmV4dE5vZGVJZCsrO1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSB7XG4gICAgICBub2RlSWQsXG4gICAgICB0YWc6IG5vZGUubm9kZU5hbWUsXG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgY2hpbGROb2RlczogW10sXG4gICAgICByZWFsRWxlbWVudDogbm9kZSxcbiAgICAgIHBhcmVudCxcbiAgICB9O1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCAmJiBub2RlLnRleHRDb250ZW50KSB7XG4gICAgICB2aXJ0dWFsRWxlbWVudC50ZXh0Q29udGVudCA9IG5vZGUudGV4dENvbnRlbnQ7XG4gICAgfVxuICAgIHRoaXMubm9kZVRvTm9kZUlkLnNldCh2aXJ0dWFsRWxlbWVudCwgbm9kZUlkKTtcbiAgICB0aGlzLm5vZGVJZFRvTm9kZS5zZXQobm9kZUlkLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuc2V0KG5vZGUsIHZpcnR1YWxFbGVtZW50KTtcbiAgICByZXR1cm4gW3ZpcnR1YWxFbGVtZW50LCBmYWxzZV07XG4gIH1cblxuICBwcml2YXRlIGdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dCxcbiAgKTogTGl2ZVZpcnR1YWxET01FbGVtZW50IHtcbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChyZWFsRWxlbWVudCk7XG4gICAgaWYgKCF2aXJ0dWFsRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBWaXJ0dWFsIGVsZW1lbnQgbm90IGZvdW5kIGZvciByZWFsIGVsZW1lbnRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0lnbm9yZWRFbGVtZW50KG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuaWdub3JlVGV4dE5vZGVzICYmIG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5IVE1MU2NyaXB0RWxlbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ29tbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkQXR0cmlidXRlKG5vZGU6IEVsZW1lbnQgfCBUZXh0LCBhdHRyaWJ1dGVOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gYXR0cmlidXRlTmFtZS5zdGFydHNXaXRoKFwib25cIik7XG4gIH1cblxuICBwdWJsaWMgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHsgUmVtb3RlRXZlbnQgfSBmcm9tIFwiQG1tbC1pby9uZXR3b3JrZWQtZG9tLXByb3RvY29sXCI7XG5cbmltcG9ydCB7IE9ic2VydmFibGVET01JbnRlcmZhY2UsIE9ic2VydmFibGVET01NZXNzYWdlIH0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgZXZlbnQ6IFJlbW90ZUV2ZW50O1xufTtcblxuZXhwb3J0IHR5cGUgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID1cbiAgfCBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZTtcblxudHlwZSBET01NZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRE9NX01FU1NBR0VfVFlQRTtcbiAgbWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9IERPTU1lc3NhZ2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1lc3NhZ2VUb09ic2VydmFibGVET01JbnN0YW5jZShcbiAgbWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBpbnN0YW5jZTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbikge1xuICBpZiAobWVzc2FnZS50eXBlID09PSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuYWRkQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5yZW1vdmVDb25uZWN0ZWRVc2VySWQobWVzc2FnZS5jb25uZWN0aW9uSWQpO1xuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChtZXNzYWdlLmNvbm5lY3Rpb25JZCwgbWVzc2FnZS5ldmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIG1lc3NhZ2UpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvYnNlcnZhYmxlRE9NSW50ZXJmYWNlVG9NZXNzYWdlU2VuZGVyKFxuICBzZW5kZXI6IChtZXNzYWdlOiBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UpID0+IHZvaWQsXG4gIGRpc3Bvc2U6ICgpID0+IHZvaWQsXG4pIHtcbiAgY29uc3QgcmVtb3RlT2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSA9IHtcbiAgICBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgZXZlbnQ6IHJlbW90ZUV2ZW50LFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgZGlzcG9zZSgpO1xuICAgIH0sXG4gICAgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuICByZXR1cm4gcmVtb3RlT2JzZXJ2YWJsZURPTTtcbn1cbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcbmltcG9ydCB7IERPTVJ1bm5lckZhY3RvcnksIERPTVJ1bm5lckludGVyZmFjZSwgRE9NUnVubmVyTWVzc2FnZSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmxldCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcbmlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKSAtIChkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXIpO1xufVxuXG4vKipcbiAqIFdlYkJyb3dzZXJET01SdW5uZXIgaXMgYSBET01SdW5uZXJJbnRlcmZhY2UgaW1wbGVtZW50YXRpb24gdGhhdCBydW5zIGluIGEgd2ViIGJyb3dzZXIuIEl0IGlzIGludGVuZGVkIHRvIGJlIHJ1biBpblxuICogYW4gaWZyYW1lIGFuZCB0aGUgcGFyZW50IHdpbmRvdyBpcyBleHBlY3RlZCB0byBzZW5kIG1lc3NhZ2VzIHRvIGl0IHRvIGRpc3BhdGNoIGV2ZW50cyBhbmQgdG8gcmVjZWl2ZSBtdXRhdGlvblxuICogbWVzc2FnZXMuXG4gKlxuICogSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgZG9jdW1lbnQgY29udGVudHMgaXMgaW5qZWN0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJCcm93c2VyRE9NUnVubmVyIGltcGxlbWVudHMgRE9NUnVubmVySW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBtdXRhdGlvbk9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IG9iamVjdCwgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkKSB7XG4gICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuXG4gICAgLy8gRm9yd2FyZCBjb25zb2xlIG1lc3NhZ2VzXG4gICAgZm9yIChjb25zdCBsZXZlbCBvZiBbXCJlcnJvclwiLCBcIndhcm5cIiwgXCJpbmZvXCIsIFwibG9nXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBkZWZhdWx0Rm4gPSB3aW5kb3cuY29uc29sZVtsZXZlbF07XG5cbiAgICAgIHdpbmRvdy5jb25zb2xlW2xldmVsXSA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGFyZ3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlZmF1bHRGbiguLi5hcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRm9yd2FyZCB1bmNhdWdodCBlcnJvcnNcbiAgICB3aW5kb3cub25lcnJvciA9IChtZXNzYWdlLCBzb3VyY2UsIGxpbmUsIGNvbHVtbiwgZXJyb3IpID0+IHtcbiAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgIGxldmVsOiBcInN5c3RlbVwiLFxuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgdHlwZTogZXJyb3I/Lm5hbWUsXG4gICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgIGNvbHVtbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBsZXQgZGlkU2VuZExvYWQgPSBmYWxzZTtcblxuICAgIHRoaXMubXV0YXRpb25PYnNlcnZlciA9IG5ldyB3aW5kb3cuTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25MaXN0KSA9PiB7XG4gICAgICBpZiAoIWRvY3VtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXV0YXRpb25PYnNlcnZlciBjYWxsZWQgYmVmb3JlIGxvYWRcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbXV0YXRpb25MaXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAod2luZG93IGFzIGFueSkucGFyYW1zID0gcGFyYW1zO1xuXG4gICAgY29uc3QgZmluaXNoTG9hZCA9ICgpID0+IHtcbiAgICAgIGlmIChkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5pc2hMb2FkIGNhbGxlZCB0d2ljZVwiKTtcbiAgICAgIH1cbiAgICAgIGRpZFNlbmRMb2FkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHRoaXMubXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHdpbmRvdy5kb2N1bWVudCwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICBzZXRUaW1lb3V0KGZpbmlzaExvYWQsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgZmluaXNoTG9hZCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBidWJibGVzID0gcmVtb3RlRXZlbnQuYnViYmxlcyB8fCBmYWxzZTtcbiAgICBjb25zdCByZW1vdGVFdmVudE9iamVjdCA9IG5ldyBDdXN0b21FdmVudChyZW1vdGVFdmVudC5uYW1lLCB7XG4gICAgICBidWJibGVzLFxuICAgICAgZGV0YWlsOiB7IC4uLnJlbW90ZUV2ZW50LnBhcmFtcywgY29ubmVjdGlvbklkIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBldmVudFR5cGVMb3dlckNhc2UgPSByZW1vdGVFdmVudC5uYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBUT0RPIC0gY2hlY2sgaWYgdGhlcmUgYXJlIG90aGVyIGV2ZW50cyB0aGF0IGF1dG9tYXRpY2FsbHkgd2lyZSB1cCBzaW1pbGFybHkgdG8gY2xpY2stPm9uY2xpY2sgYW5kIGF2b2lkIHRob3NlIHRvb1xuICAgIGlmIChldmVudFR5cGVMb3dlckNhc2UgIT09IFwiY2xpY2tcIikge1xuICAgICAgY29uc3QgaGFuZGxlckF0dHJpYnV0ZU5hbWUgPSBcIm9uXCIgKyBldmVudFR5cGVMb3dlckNhc2U7XG4gICAgICBjb25zdCBoYW5kbGVyQXR0cmlidXRlVmFsdWUgPSByZWFsRWxlbWVudC5nZXRBdHRyaWJ1dGUoaGFuZGxlckF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSkge1xuICAgICAgICAvLyBUaGlzIGV2ZW50IGlzIGRlZmluZWQgYXMgYW4gSFRNTCBldmVudCBhdHRyaWJ1dGUuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZm4gPSBGdW5jdGlvbihcImV2ZW50XCIsIGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSk7XG4gICAgICAgICAgZm4uYXBwbHkocmVhbEVsZW1lbnQsIFtyZW1vdGVFdmVudE9iamVjdF0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHJ1bm5pbmcgZXZlbnQgaGFuZGxlcjpcIiwgZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0aGUgZXZlbnQgdmlhIEphdmFTY3JpcHQuXG4gICAgcmVhbEVsZW1lbnQuZGlzcGF0Y2hFdmVudChyZW1vdGVFdmVudE9iamVjdCk7XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIC8vIFRPRE8gLSBoYW5kbGUgZGlzcG9zZVxuICAgIGNvbnNvbGUubG9nKFwiV2ViQnJvd3NlckRPTVJ1bm5lci5kaXNwb3NlXCIpO1xuICB9XG5cbiAgZ2V0RG9jdW1lbnQoKTogRG9jdW1lbnQge1xuICAgIHJldHVybiBkb2N1bWVudDtcbiAgfVxuXG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXIge1xuICAgIGNvbnN0IGRhdGVCYXNlZERvY3VtZW50VGltZSA9IERhdGUubm93KCkgLSBkb2N1bWVudExvYWRUaW1lO1xuICAgIGlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICAgICAgY29uc3QgdGltZSA9IGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lIGFzIG51bWJlcjtcbiAgICAgIGlmIChkYXRlQmFzZWREb2N1bWVudFRpbWUgPiB0aW1lICsgNTAwKSB7XG4gICAgICAgIC8vIFRoZSB0aW1lbGluZSBjYW4gYmUgXCJsZWZ0IGJlaGluZFwiIGlmIHRoZSB0YWIgaXMgYmFja2dyb3VuZGVkIGZvciBhIHdoaWxlLCBzbyB3ZSB1c2UgdGhlIGRhdGUtYmFzZWQgdGltZVxuICAgICAgICAvLyBpbnN0ZWFkLiBJZi93aGVuIHRoZSBkb2N1bWVudCBpcyBicm91Z2h0IGJhY2sgaW50byB0aGUgZm9yZWdyb3VuZCwgdGhlIHRpbWVsaW5lIHdpbGwgY2F0Y2ggdXAuXG4gICAgICAgIHJldHVybiBkYXRlQmFzZWREb2N1bWVudFRpbWU7XG4gICAgICB9XG4gICAgICAvLyBJZGVhbCBjYXNlIC0gdXNlIHRoZSBkb2N1bWVudC50aW1lbGluZSBhcyBpdCdzIHdoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSBkb2N1bWVudCBzY3JpcHRcbiAgICAgIHJldHVybiB0aW1lO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUJhc2VkRG9jdW1lbnRUaW1lO1xuICB9XG5cbiAgLy8gVE9ETyAtIHJlc29sdmUgdHlwZXMgKFdpbmRvdyBuZWVkcyB0byBleHBvc2UgY2xhc3NlcyBzdWNoIGFzIEN1c3RvbUV2ZW50IGFzIHByb3BlcnRpZXMpXG4gIGdldFdpbmRvdygpOiBhbnkge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH1cbn1cbiIsICJpbXBvcnQgeyBPYnNlcnZhYmxlRE9NIH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20vc3JjL09ic2VydmFibGVET01cIjtcbmltcG9ydCB7XG4gIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICBET01fTUVTU0FHRV9UWVBFLFxuICBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG59IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tLWNvbW1vblwiO1xuXG5pbXBvcnQgeyBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSB9IGZyb20gXCIuL1dlYkJyb3dzZXJET01SdW5uZXJcIjtcblxuLyoqXG4gKiBUaGlzIGlzIHJ1biBpbiB0aGUgaWZyYW1lIHRoYXQgd2lsbCBleGVjdXRlIHRoZSBkb2N1bWVudCBzY3JpcHQgdG8gc2V0dXAgdGhlIGxpc3RlbmluZyBmb3IgZXZlbnRzIG1lc3NhZ2VzIGFuZFxuICogb2JzZXJ2aW5nIG9mIERPTSBtdXRhdGlvbiB1c2luZyB0aGUgV2ViQnJvd3NlckRPTVJ1bm5lciBjbGFzcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBzZXR1cElmcmFtZVdlYlJ1bm5lciB9IGZyb20gXCIuL0lmcmFtZVdlYlJ1bm5lclwiO1xuXG5jb25zdCBhcmdzID0gKHdpbmRvdyBhcyBhbnkpLmFyZ3M7XG5zZXR1cElmcmFtZVdlYlJ1bm5lcihhcmdzKTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFJTyxTQUFTLDBCQUEwQixJQUFvRDtBQUM1RixTQUFPO0FBQUEsSUFDTCxRQUFRLEdBQUc7QUFBQSxJQUNYLEtBQUssR0FBRztBQUFBLElBQ1IsWUFBWSxHQUFHO0FBQUEsSUFDZixZQUFZLEdBQUcsV0FBVyxJQUFJLENBQUMsVUFBVSwwQkFBMEIsS0FBSyxDQUFDO0FBQUEsSUFDekUsYUFBYSxHQUFHO0FBQUEsRUFDbEI7QUFDRjs7O0FDd0NPLElBQU0sZ0JBQU4sTUFBc0Q7QUFBQSxFQWMzRCxZQUNFLHlCQUNBLFVBQ0EsZUFDQTtBQWpCRixTQUFRLGVBQWUsb0JBQUksSUFBbUM7QUFDOUQsU0FBUSxlQUFlLG9CQUFJLElBQW1DO0FBQzlELFNBQVEsOEJBQThCLG9CQUFJLElBQTJDO0FBQ3JGLFNBQVEsa0JBQWtCO0FBRTFCLFNBQVEsYUFBYTtBQUdyQixTQUFRLFNBQVM7QUFDakIsU0FBUSxxQkFBd0MsQ0FBQztBQVMvQyxTQUFLLFdBQVcsd0JBQXdCO0FBQ3hDLFNBQUssa0JBQWtCLHdCQUF3QjtBQUMvQyxTQUFLLFdBQVc7QUFF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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\n/**\n * RunnerIframe is a class that creates an iframe that includes the networked-dom-web-runner-iframe package in it and\n * injects the provided HTML into it. This class then communicates with the iframe using postMessage.\n */\nexport class RunnerIframe {\n private iframe: HTMLIFrameElement;\n private postMessageListener: (messageEvent: MessageEvent) => void;\n\n constructor(\n private observableDOMParameters: ObservableDOMParameters,\n private 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 ...this.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.postMessageListener = (e: MessageEvent) => {\n if (e.source === this.iframe.contentWindow || (isJSDOM && e.source === null)) {\n const parsed = JSON.parse(e.data) as FromObservableDOMInstanceMessage;\n this.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\n/**\n * The NetworkedDOMWebRunnerClient class can be used to view and interact with a NetworkedDOM document instance that is\n * available directly in the browser (rather than exposed over the network). This is useful for usage modes where the\n * document does not need to be available to other clients, such as a single-user or an edit/preview mode.\n *\n * The class takes arguments for where the view of the document should be synchronized to in the DOM, and which window\n * instance to use to create any other elements (to allow for using iframes to isolate the document from the rest of\n * the page).\n */\nexport class NetworkedDOMWebRunnerClient {\n public readonly element: HTMLElement;\n\n public connectedState: {\n document: NetworkedDOM | EditableNetworkedDOM;\n domWebsocket: NetworkedDOMWebsocket;\n fakeWebsocket: FakeWebsocket;\n } | null = null;\n private enableEventHandling: boolean;\n\n constructor(enableEventHandling = true, element?: HTMLElement) {\n this.enableEventHandling = enableEventHandling;\n this.element = element || document.createElement(\"div\");\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.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.element.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.element,\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", "/**\n * WebsocketEnd is one end of a FakeWebsocket connection. It is used to simulate a websocket connection for testing or\n * matching the interface of a real websocket connection without doing any actual networking.\n */\nclass 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\n/**\n * FakeWebsocket is a pair of WebsocketEnds that are connected to each other. It is used to simulate a websocket\n * connection for testing or matching the interface of a real websocket connection without doing any actual networking.\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\n/**\n * Creates an ObservableDOMInterface that uses an iframe to run the document.\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"],
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.loaded = false;\n this.preLoadLogMessages = [];\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.loaded = true;\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 for (const logMessage of this.preLoadLogMessages) {\n this.callback(\n {\n logMessage,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n this.preLoadLogMessages = [];\n } else if (domRunnerMessage.mutationList) {\n this.processModificationList(domRunnerMessage.mutationList);\n } else if (domRunnerMessage.logMessage) {\n if (!this.loaded) {\n this.preLoadLogMessages.push(domRunnerMessage.logMessage);\n return;\n }\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 const targetNode = mutation.target;\n const targetElement = this.realElementToVirtualElement.get(targetNode);\n if (!targetElement) {\n throw new Error(\"Unknown node:\" + targetNode + \",\" + mutation.type);\n }\n let previousSiblingElement = null;\n let insertionIndex = 0;\n const toAdd = [];\n const removedNodeIds = [];\n if (mutation.type === \"childList\") {\n mutation.removedNodes.forEach((node) => {\n const asElementOrText = node;\n if (this.isIgnoredElement(asElementOrText)) {\n return;\n }\n const childDOMElement = this.realElementToVirtualElement.get(asElementOrText);\n if (!childDOMElement) {\n return;\n } else {\n const index = targetElement.childNodes.indexOf(childDOMElement);\n if (index === -1) {\n } else {\n this.removeVirtualDOMElement(childDOMElement);\n removedNodeIds.push(childDOMElement.nodeId);\n const removal = targetElement.childNodes.splice(index, 1);\n if (removal.length !== 1) {\n throw new Error(\"Removal length not 1\");\n } else {\n if (removal[0].nodeId !== childDOMElement.nodeId) {\n throw new Error(\"Removal node id mismatch\");\n }\n }\n }\n }\n });\n mutation.addedNodes.forEach((node) => {\n const asElementOrText = node;\n if (asElementOrText.parentNode !== targetNode) {\n } else {\n if (!previousSiblingElement) {\n let firstNonIgnoredPreviousSibling = asElementOrText.previousSibling;\n let virtualPreviousSibling;\n while (firstNonIgnoredPreviousSibling && !virtualPreviousSibling) {\n virtualPreviousSibling = this.realElementToVirtualElement.get(\n firstNonIgnoredPreviousSibling\n );\n if (virtualPreviousSibling && targetElement.childNodes.indexOf(virtualPreviousSibling) === -1) {\n virtualPreviousSibling = void 0;\n }\n firstNonIgnoredPreviousSibling = firstNonIgnoredPreviousSibling.previousSibling;\n }\n if (virtualPreviousSibling) {\n previousSiblingElement = virtualPreviousSibling;\n insertionIndex = targetElement.childNodes.indexOf(previousSiblingElement);\n if (insertionIndex === -1) {\n throw new Error(\n \"Previous sibling is not currently a child of the parent element\"\n );\n }\n insertionIndex += 1;\n }\n }\n const childVirtualDOMElement = this.createVirtualDOMElementWithChildren(\n asElementOrText,\n targetElement\n );\n if (childVirtualDOMElement) {\n toAdd.push(childVirtualDOMElement);\n }\n }\n });\n targetElement.childNodes.splice(insertionIndex, 0, ...toAdd);\n } else if (mutation.type === \"attributes\") {\n const attributeName = mutation.attributeName;\n if (!this.isIgnoredAttribute(targetNode, attributeName)) {\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n delete targetElement.attributes[attributeName];\n } else {\n targetElement.attributes[attributeName] = attributeValue;\n }\n }\n } else if (mutation.type === \"characterData\") {\n targetElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n }\n const addedNodes = toAdd.map(virtualDOMElementToStatic);\n const mutationRecord = {\n type: mutation.type,\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: previousSiblingElement ? previousSiblingElement.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 }\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, existing] = this.createVirtualDOMElement(node, parent);\n if (!virtualElement) {\n return null;\n }\n if (existing) {\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, false];\n }\n if (!node) {\n throw new Error(\"Cannot assign node id to null\");\n }\n const existingValue = this.realElementToVirtualElement.get(node);\n if (existingValue !== void 0) {\n return [existingValue, true];\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, false];\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(params, callback);\n};\nvar documentLoadTime = Date.now();\nif (document.timeline && document.timeline.currentTime) {\n documentLoadTime = Date.now() - document.timeline.currentTime;\n}\nvar WebBrowserDOMRunner = class {\n constructor(params, callback) {\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 const eventTypeLowerCase = remoteEvent.name.toLowerCase();\n if (eventTypeLowerCase !== \"click\") {\n const handlerAttributeName = \"on\" + eventTypeLowerCase;\n const handlerAttributeValue = realElement.getAttribute(handlerAttributeName);\n if (handlerAttributeValue) {\n try {\n const fn = Function(\"event\", handlerAttributeValue);\n fn.apply(realElement, [remoteEventObject]);\n } catch (e) {\n console.error(\"Error running event handler:\", e);\n }\n }\n }\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n console.log(\"WebBrowserDOMRunner.dispose\");\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n const dateBasedDocumentTime = Date.now() - documentLoadTime;\n if (document.timeline && document.timeline.currentTime) {\n const time = document.timeline.currentTime;\n if (dateBasedDocumentTime > time + 500) {\n return dateBasedDocumentTime;\n }\n return time;\n }\n return dateBasedDocumentTime;\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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBlbC5hdHRyaWJ1dGVzLFxuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJlbW90ZUV2ZW50LFxuICBTdGF0aWNWaXJ0dWFsRE9NRWxlbWVudCxcbiAgU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lck1lc3NhZ2UgPSB7XG4gIGxvYWRlZD86IGJvb2xlYW47XG4gIG11dGF0aW9uTGlzdD86IEFycmF5PE11dGF0aW9uUmVjb3JkPjtcbiAgbG9nTWVzc2FnZT86IExvZ01lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJJbnRlcmZhY2UgPSB7XG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50O1xuICBnZXRXaW5kb3coKTogV2luZG93ICYge1xuICAgIEN1c3RvbUV2ZW50OiB0eXBlb2YgQ3VzdG9tRXZlbnQ7XG4gICAgVGV4dDogdHlwZW9mIFRleHQ7XG4gICAgSFRNTFNjcmlwdEVsZW1lbnQ6IHR5cGVvZiBIVE1MU2NyaXB0RWxlbWVudDtcbiAgICBDb21tZW50OiB0eXBlb2YgQ29tbWVudDtcbiAgfTsgLy8gVE9ETyAtIERlZmluZSB0aGlzIHdpdGhvdXQgdXNpbmcgSlNET00gdHlwZXNcbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkO1xuICBkaXNwb3NlKCk6IHZvaWQ7XG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJGYWN0b3J5ID0gKFxuICBodG1sUGF0aDogc3RyaW5nLFxuICBodG1sQ29udGVudHM6IHN0cmluZyxcbiAgcGFyYW1zOiBvYmplY3QsXG4gIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbikgPT4gRE9NUnVubmVySW50ZXJmYWNlO1xuXG5leHBvcnQgdHlwZSBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSBPbWl0PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50LCBcImNoaWxkTm9kZXNcIj4gJiB7XG4gIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dDtcbiAgY2hpbGROb2RlczogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PjtcbiAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsO1xufTtcblxuLyoqXG4gKiBUaGUgT2JzZXJ2YWJsZURPTSBjbGFzcyBoYW5kbGVzIHRoZSBydW5uaW5nIG9mIGFuIEhUTUwgZG9jdW1lbnQgdXNpbmcgYSBwcm92aWRlZCBET01SdW5uZXJGYWN0b3J5IGFuZCBjb252ZXJ0aW5nIHRoZVxuICogbXV0YXRpb25zIHRoYXQgYXJlIHN0cnVjdHVyZWQgYXMgcmVmZXJlbmNlcyB0byBsaXZlIERPTSBlbGVtZW50cyBpbnRvIG1lc3NhZ2VzIHRoYXQgcmVmZXIgdG8gZWxlbWVudHMgYnkgbm9kZUlkcy5cbiAqL1xuZXhwb3J0IGNsYXNzIE9ic2VydmFibGVET00gaW1wbGVtZW50cyBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBub2RlVG9Ob2RlSWQgPSBuZXcgTWFwPExpdmVWaXJ0dWFsRE9NRWxlbWVudCwgbnVtYmVyPigpO1xuICBwcml2YXRlIG5vZGVJZFRvTm9kZSA9IG5ldyBNYXA8bnVtYmVyLCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgcmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50ID0gbmV3IE1hcDxFbGVtZW50IHwgVGV4dCwgTGl2ZVZpcnR1YWxET01FbGVtZW50PigpO1xuICBwcml2YXRlIGlnbm9yZVRleHROb2RlcyA9IHRydWU7XG4gIHByaXZhdGUgY2FsbGJhY2s6IChtZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSwgb2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBuZXh0Tm9kZUlkID0gMTtcbiAgcHJpdmF0ZSBodG1sUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGRvbVJ1bm5lcjogRE9NUnVubmVySW50ZXJmYWNlO1xuICBwcml2YXRlIGxvYWRlZCA9IGZhbHNlO1xuICBwcml2YXRlIHByZUxvYWRMb2dNZXNzYWdlczogQXJyYXk8TG9nTWVzc2FnZT4gPSBbXTtcblxuICBwcml2YXRlIGRvY3VtZW50VGltZUludGVydmFsVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzOiBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycyxcbiAgICBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkLFxuICAgIHJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnksXG4gICkge1xuICAgIHRoaXMuaHRtbFBhdGggPSBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aDtcbiAgICB0aGlzLmlnbm9yZVRleHROb2RlcyA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmlnbm9yZVRleHROb2RlcztcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICB0aGlzLmRvY3VtZW50VGltZUludGVydmFsVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICB7XG4gICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLFxuICAgICAgKTtcbiAgICB9LCBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5waW5nSW50ZXJ2YWxNaWxsaXNlY29uZHMgfHwgNTAwMCk7XG5cbiAgICB0aGlzLmRvbVJ1bm5lciA9IHJ1bm5lckZhY3RvcnkoXG4gICAgICBvYnNlcnZhYmxlRE9NUGFyYW1ldGVycy5odG1sUGF0aCxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxDb250ZW50cyxcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBhcmFtcyxcbiAgICAgIChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChkb21SdW5uZXJNZXNzYWdlLmxvYWRlZCkge1xuICAgICAgICAgIHRoaXMubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgICAgdGhpcy5kb21SdW5uZXIuZ2V0RG9jdW1lbnQoKSBhcyB1bmtub3duIGFzIEVsZW1lbnQsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoXG4gICAgICAgICAgICB0aGlzLmdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNuYXBzaG90LFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICAgIGZvciAoY29uc3QgbG9nTWVzc2FnZSBvZiB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcykge1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIGlmIChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCkge1xuICAgICAgICAgIHRoaXMucHJvY2Vzc01vZGlmaWNhdGlvbkxpc3QoZG9tUnVubmVyTWVzc2FnZS5tdXRhdGlvbkxpc3QpO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9nTWVzc2FnZSkge1xuICAgICAgICAgIGlmICghdGhpcy5sb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzLnB1c2goZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbG9nTWVzc2FnZTogZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlLFxuICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuZGlzcGF0Y2hFdmVudChcbiAgICAgIG5ldyAodGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ3VzdG9tRXZlbnQpKFwiY29ubmVjdGVkXCIsIHtcbiAgICAgICAgZGV0YWlsOiB7IGNvbm5lY3Rpb25JZCB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJkaXNjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChtdXRhdGlvbkxpc3Q6IEFycmF5PE11dGF0aW9uUmVjb3JkPik6IHZvaWQge1xuICAgIGNvbnN0IGRvY3VtZW50RWwgPSB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudDtcbiAgICBjb25zdCBkb2N1bWVudFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KGRvY3VtZW50RWwpO1xuICAgIGlmICghZG9jdW1lbnRWaXJ0dWFsRE9NRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBkb2N1bWVudCBub3QgY3JlYXRlZCBpbiBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdGApO1xuICAgIH1cblxuICAgIGlmIChtdXRhdGlvbkxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy8gVE9ETyAoaHR0cHM6Ly9naXRodWIuY29tL21tbC1pby9tbWwvaXNzdWVzLzEwMCkgLSB3YWxrIGJhY2sgdGhyb3VnaCB0aGUgcmVjb3JkcyB0byBkZXJpdmUgdGhlIGludGVybWVkaWF0ZVxuICAgICAgLy8gIHN0YXRlcyAoZS5nLiBpZiBhbiBhdHRyaWJ1dGUgaXMgbGF0ZXIgYWRkZWQgdG8gYW4gZWxlbWVudCBjcmVhdGVkIGluIGFuIGVhcmxpZXIgcmVjb3JkIHRoZW4gaXQgc2hvdWxkIG5vdFxuICAgICAgLy8gIGhhdmUgdGhhdCBhdHRyaWJ1dGUgd2hlbiB0aGUgZWxlbWVudCBpcyBhZGRlZC4gVGhpcyBpcyBpbXBvcnRhbnQgYXMgaW5jb3JyZWN0IGF0dHJpYnV0ZSBzZXRzIGNhbiBhZmZlY3RcbiAgICAgIC8vICB2aXNpYmlsaXR5IGFuZCBleHBlY3RlZCBjbGllbnQgcGVyZm9ybWFuY2UuXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIiAmJlxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICB0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQsIG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhKVxuICAgICAgKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0YXJnZXROb2RlID0gbXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldCh0YXJnZXROb2RlKTtcbiAgICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIG5vZGU6XCIgKyB0YXJnZXROb2RlICsgXCIsXCIgKyBtdXRhdGlvbi50eXBlKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHByZXZpb3VzU2libGluZ0VsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgICAgbGV0IGluc2VydGlvbkluZGV4ID0gMDtcbiAgICAgIGNvbnN0IHRvQWRkOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+ID0gW107XG4gICAgICBjb25zdCByZW1vdmVkTm9kZUlkczogQXJyYXk8bnVtYmVyPiA9IFtdO1xuXG4gICAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgICBtdXRhdGlvbi5yZW1vdmVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGFzRWxlbWVudE9yVGV4dCA9IG5vZGUgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChhc0VsZW1lbnRPclRleHQpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNoaWxkRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChhc0VsZW1lbnRPclRleHQpO1xuICAgICAgICAgIGlmICghY2hpbGRET01FbGVtZW50KSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZiBlbGVtZW50IHdhcyBhIGNoaWxkIG9mIGEgcGFyZW50IGVsZW1lbnQsIGJ1dCB3YXMgbW92ZWQgdG8gYSBuZXcgcGFyZW50IGluIHRoZSBzYW1lIGJhdGNoIG9mIG11dGF0aW9ucy5cbiAgICAgICAgICAgICBXZSBjYW4gaWdub3JlIHRoaXMgcmVtb3ZhbCBhcyB0aGUgZWxlbWVudCB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IHBsYWNlIGluIHRoZSBoaWVyYXJjaHkgYWxyZWFkeS5cbiAgICAgICAgICAgICovXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YoY2hpbGRET01FbGVtZW50KTtcbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICBUaGlzIGNhbiBoYXBwZW4gaWYgZWxlbWVudCB3YXMgYSBjaGlsZCBvZiBhIHBhcmVudCBlbGVtZW50LCBidXQgd2FzIG1vdmVkIHRvIGEgbmV3IHBhcmVudCBpbiB0aGUgc2FtZSBiYXRjaCBvZiBtdXRhdGlvbnMuXG4gICAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgICAqL1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKGNoaWxkRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgICAgICAgICAgICBjb25zdCByZW1vdmFsID0gdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgIGlmIChyZW1vdmFsLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbGVuZ3RoIG5vdCAxXCIpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChyZW1vdmFsWzBdLm5vZGVJZCAhPT0gY2hpbGRET01FbGVtZW50Lm5vZGVJZCkge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVtb3ZhbCBub2RlIGlkIG1pc21hdGNoXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgbXV0YXRpb24uYWRkZWROb2Rlcy5mb3JFYWNoKChub2RlOiBOb2RlKSA9PiB7XG4gICAgICAgICAgY29uc3QgYXNFbGVtZW50T3JUZXh0ID0gbm9kZSBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgICAgICBpZiAoYXNFbGVtZW50T3JUZXh0LnBhcmVudE5vZGUgIT09IHRhcmdldE5vZGUpIHtcbiAgICAgICAgICAgIC8vIElnbm9yZSB0aGlzIGFkZGl0aW9uIC0gaXQgaXMgbGlrZWx5IG92ZXJyaWRkZW4gYnkgYW4gZWFybGllciBhZGRpdGlvbiBvZiB0aGlzIGVsZW1lbnQgdG8gaXRzIGV2ZW50dWFsIG5vZGUgaW4gdGhpcyBtdXRhdGlvbiBiYXRjaFxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgIEVpdGhlciB0aGVyZSBpcyBubyBwcmV2aW91cyBlbGVtZW50ICh0aGlzIGlzIHRoZSBmaXJzdCBlbGVtZW50KVxuICAgICAgICAgICAgICAgb3IgdGhlIHByZXZpb3VzIGVsZW1lbnQgaGFzIG5vdCB5ZXQgYmVlbiBkZXRlcm1pbmVkLlxuXG4gICAgICAgICAgICAgICBVc2UgdGhlIGN1cnJlbnQgcHJldmlvdXMgc2libGluZyBvZiB0aGlzIGFkZGVkIG5vZGUgYXMgdGhlIGZpcnN0XG4gICAgICAgICAgICAgICBjaG9pY2UgZm9yIHRoZSBwcmV2aW91cyBzaWJsaW5nLCBidXQgb25seSB1c2UgcHJldmlvdXMgc2libGluZ3NcbiAgICAgICAgICAgICAgIHRoYXQgYXJlIG5vdCBpZ25vcmVkIChhcmUgdHJhY2tlZCBhcyB2aXJ0dWFsIGVsZW1lbnRzKS5cbiAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgbGV0IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZzogRWxlbWVudCB8IFRleHQgfCBudWxsID1cbiAgICAgICAgICAgICAgICBhc0VsZW1lbnRPclRleHQucHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICAgICAgICBsZXQgdmlydHVhbFByZXZpb3VzU2libGluZzogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB3aGlsZSAoZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nICYmICF2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgdmlydHVhbFByZXZpb3VzU2libGluZyA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChcbiAgICAgICAgICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgIHZpcnR1YWxQcmV2aW91c1NpYmxpbmcgJiZcbiAgICAgICAgICAgICAgICAgIHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKHZpcnR1YWxQcmV2aW91c1NpYmxpbmcpID09PSAtMVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgLy8gVGhpcyBlbGVtZW50IGlzIG5vdCBhIGNoaWxkIG9mIHRoZSBwYXJlbnQgZWxlbWVudCAtIGl0IGlzIG5vdCBhIHZhbGlkIHByZXZpb3VzIHNpYmxpbmdcbiAgICAgICAgICAgICAgICAgIHZpcnR1YWxQcmV2aW91c1NpYmxpbmcgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nID0gZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nLnByZXZpb3VzU2libGluZyBhc1xuICAgICAgICAgICAgICAgICAgfCBFbGVtZW50XG4gICAgICAgICAgICAgICAgICB8IFRleHRcbiAgICAgICAgICAgICAgICAgIHwgbnVsbDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmICh2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgcHJldmlvdXNTaWJsaW5nRWxlbWVudCA9IHZpcnR1YWxQcmV2aW91c1NpYmxpbmc7XG4gICAgICAgICAgICAgICAgaW5zZXJ0aW9uSW5kZXggPSB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihwcmV2aW91c1NpYmxpbmdFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoaW5zZXJ0aW9uSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIFwiUHJldmlvdXMgc2libGluZyBpcyBub3QgY3VycmVudGx5IGEgY2hpbGQgb2YgdGhlIHBhcmVudCBlbGVtZW50XCIsXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpbnNlcnRpb25JbmRleCArPSAxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxET01FbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICAgICAgYXNFbGVtZW50T3JUZXh0LFxuICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgICAgIHRvQWRkLnB1c2goY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLnNwbGljZShpbnNlcnRpb25JbmRleCwgMCwgLi4udG9BZGQpO1xuICAgICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICBjb25zdCBhdHRyaWJ1dGVOYW1lID0gbXV0YXRpb24uYXR0cmlidXRlTmFtZSE7XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUodGFyZ2V0Tm9kZSwgYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVWYWx1ZSA9ICh0YXJnZXROb2RlIGFzIEVsZW1lbnQpLmdldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lKTtcbiAgICAgICAgICBpZiAoYXR0cmlidXRlVmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImNoYXJhY3RlckRhdGFcIikge1xuICAgICAgICB0YXJnZXRFbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcblxuICAgICAgY29uc3QgYWRkZWROb2RlczogQXJyYXk8U3RhdGljVmlydHVhbERPTUVsZW1lbnQ+ID0gdG9BZGQubWFwKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMpO1xuXG4gICAgICBjb25zdCBtdXRhdGlvblJlY29yZDogU3RhdGljVmlydHVhbERPTU11dGF0aW9uSWRzUmVjb3JkID0ge1xuICAgICAgICB0eXBlOiBtdXRhdGlvbi50eXBlLFxuICAgICAgICB0YXJnZXRJZDogdGFyZ2V0RWxlbWVudC5ub2RlSWQsXG4gICAgICAgIGFkZGVkTm9kZXMsXG4gICAgICAgIHJlbW92ZWROb2RlSWRzLFxuICAgICAgICBwcmV2aW91c1NpYmxpbmdJZDogcHJldmlvdXNTaWJsaW5nRWxlbWVudFxuICAgICAgICAgID8gKHByZXZpb3VzU2libGluZ0VsZW1lbnQgYXMgTGl2ZVZpcnR1YWxET01FbGVtZW50KS5ub2RlSWRcbiAgICAgICAgICA6IG51bGwsXG4gICAgICAgIGF0dHJpYnV0ZTogbXV0YXRpb24uYXR0cmlidXRlTmFtZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICB2YWx1ZTogKG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUobXV0YXRpb24uYXR0cmlidXRlTmFtZSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcblxuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uOiBtdXRhdGlvblJlY29yZCxcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlVmlydHVhbERPTUVsZW1lbnQodmlydHVhbERPTUVsZW1lbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IHZvaWQge1xuICAgIHRoaXMubm9kZUlkVG9Ob2RlLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgIHRoaXMubm9kZVRvTm9kZUlkLmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50LnJlYWxFbGVtZW50KTtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHZpcnR1YWxET01FbGVtZW50LmNoaWxkTm9kZXMpIHtcbiAgICAgIHRoaXMucmVtb3ZlVmlydHVhbERPTUVsZW1lbnQoY2hpbGQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsIHtcbiAgICBjb25zdCBbdmlydHVhbEVsZW1lbnQsIGV4aXN0aW5nXSA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnQobm9kZSwgcGFyZW50KTtcbiAgICBpZiAoIXZpcnR1YWxFbGVtZW50KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXMpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjaGlsZCA9IChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXNbaV07XG4gICAgICAgIGNvbnN0IGNoaWxkVmlydHVhbEVsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgIGNoaWxkIGFzIEVsZW1lbnQgfCBUZXh0LFxuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LFxuICAgICAgICApO1xuICAgICAgICBpZiAoY2hpbGRWaXJ0dWFsRWxlbWVudCkge1xuICAgICAgICAgIHZpcnR1YWxFbGVtZW50LmNoaWxkTm9kZXMucHVzaChjaGlsZFZpcnR1YWxFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmlydHVhbERPTUVsZW1lbnQoXG4gICAgbm9kZTogRWxlbWVudCB8IFRleHQsXG4gICAgcGFyZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLFxuICApOiBbTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCwgYm9vbGVhbl0ge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobm9kZSkpIHtcbiAgICAgIHJldHVybiBbbnVsbCwgZmFsc2VdO1xuICAgIH1cbiAgICBpZiAoIW5vZGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBhc3NpZ24gbm9kZSBpZCB0byBudWxsXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nVmFsdWUgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQobm9kZSk7XG4gICAgaWYgKGV4aXN0aW5nVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLypcbiAgICAgICBUaGlzIGlzIHVuZGVzaXJhYmxlLCBidXQgdGhlIGJhdGNoaW5nIG9mIG11dGF0aW9ucyBmcm9tIE11dGF0aW9uT2JzZXJ2ZXIgbWVhbnMgdGhhdFxuICAgICAgIHRoaXMgbm9kZSBjb3VsZCBiZSBiZWluZyBhZGRlZCBpbiBhIG11dGF0aW9uIGFmdGVyIGEgbXV0YXRpb24gb2YgYSBwYXJlbnQgdGhhdCB3aGVuXG4gICAgICAgaGFuZGxlZCByZXN1bHRpbmcgaW4gYWRkaW5nIHRoaXMgbm9kZSBlYXJseS5cbiAgICAgICovXG4gICAgICByZXR1cm4gW2V4aXN0aW5nVmFsdWUsIHRydWVdO1xuICAgIH1cblxuICAgIGNvbnN0IGF0dHJpYnV0ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBpZiAoKG5vZGUgYXMgYW55KS5hdHRyaWJ1dGVzKSB7XG4gICAgICBjb25zdCBhc0hUTUxFbGVtZW50ID0gbm9kZSBhcyBIVE1MRWxlbWVudDtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlTmFtZXMoKSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGFzSFRNTEVsZW1lbnQuZ2V0QXR0cmlidXRlKGtleSk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk51bGwgYXR0cmlidXRlIHZhbHVlIGZvciBrZXk6IFwiICsga2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuaXNJZ25vcmVkQXR0cmlidXRlKG5vZGUsIGtleSkpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG5vZGVJZCA9IHRoaXMubmV4dE5vZGVJZCsrO1xuICAgIGNvbnN0IHZpcnR1YWxFbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgPSB7XG4gICAgICBub2RlSWQsXG4gICAgICB0YWc6IG5vZGUubm9kZU5hbWUsXG4gICAgICBhdHRyaWJ1dGVzLFxuICAgICAgY2hpbGROb2RlczogW10sXG4gICAgICByZWFsRWxlbWVudDogbm9kZSxcbiAgICAgIHBhcmVudCxcbiAgICB9O1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCAmJiBub2RlLnRleHRDb250ZW50KSB7XG4gICAgICB2aXJ0dWFsRWxlbWVudC50ZXh0Q29udGVudCA9IG5vZGUudGV4dENvbnRlbnQ7XG4gICAgfVxuICAgIHRoaXMubm9kZVRvTm9kZUlkLnNldCh2aXJ0dWFsRWxlbWVudCwgbm9kZUlkKTtcbiAgICB0aGlzLm5vZGVJZFRvTm9kZS5zZXQobm9kZUlkLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuc2V0KG5vZGUsIHZpcnR1YWxFbGVtZW50KTtcbiAgICByZXR1cm4gW3ZpcnR1YWxFbGVtZW50LCBmYWxzZV07XG4gIH1cblxuICBwcml2YXRlIGdldFZpcnR1YWxET01FbGVtZW50Rm9yUmVhbEVsZW1lbnRPclRocm93KFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50IHwgVGV4dCxcbiAgKTogTGl2ZVZpcnR1YWxET01FbGVtZW50IHtcbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChyZWFsRWxlbWVudCk7XG4gICAgaWYgKCF2aXJ0dWFsRWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBWaXJ0dWFsIGVsZW1lbnQgbm90IGZvdW5kIGZvciByZWFsIGVsZW1lbnRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0lnbm9yZWRFbGVtZW50KG5vZGU6IEVsZW1lbnQgfCBUZXh0KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuaWdub3JlVGV4dE5vZGVzICYmIG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5IVE1MU2NyaXB0RWxlbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuQ29tbWVudCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkQXR0cmlidXRlKG5vZGU6IEVsZW1lbnQgfCBUZXh0LCBhdHRyaWJ1dGVOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gYXR0cmlidXRlTmFtZS5zdGFydHNXaXRoKFwib25cIik7XG4gIH1cblxuICBwdWJsaWMgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHsgUmVtb3RlRXZlbnQgfSBmcm9tIFwiQG1tbC1pby9uZXR3b3JrZWQtZG9tLXByb3RvY29sXCI7XG5cbmltcG9ydCB7IE9ic2VydmFibGVET01JbnRlcmZhY2UsIE9ic2VydmFibGVET01NZXNzYWdlIH0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgZXZlbnQ6IFJlbW90ZUV2ZW50O1xufTtcblxuZXhwb3J0IHR5cGUgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID1cbiAgfCBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZTtcblxudHlwZSBET01NZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRE9NX01FU1NBR0VfVFlQRTtcbiAgbWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9IERPTU1lc3NhZ2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1lc3NhZ2VUb09ic2VydmFibGVET01JbnN0YW5jZShcbiAgbWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBpbnN0YW5jZTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbikge1xuICBpZiAobWVzc2FnZS50eXBlID09PSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuYWRkQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5yZW1vdmVDb25uZWN0ZWRVc2VySWQobWVzc2FnZS5jb25uZWN0aW9uSWQpO1xuICB9IGVsc2UgaWYgKG1lc3NhZ2UudHlwZSA9PT0gRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUpIHtcbiAgICBpbnN0YW5jZS5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChtZXNzYWdlLmNvbm5lY3Rpb25JZCwgbWVzc2FnZS5ldmVudCk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIG1lc3NhZ2UpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvYnNlcnZhYmxlRE9NSW50ZXJmYWNlVG9NZXNzYWdlU2VuZGVyKFxuICBzZW5kZXI6IChtZXNzYWdlOiBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UpID0+IHZvaWQsXG4gIGRpc3Bvc2U6ICgpID0+IHZvaWQsXG4pIHtcbiAgY29uc3QgcmVtb3RlT2JzZXJ2YWJsZURPTTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSA9IHtcbiAgICBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBudW1iZXIsIHJlbW90ZUV2ZW50OiBSZW1vdGVFdmVudCk6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgZXZlbnQ6IHJlbW90ZUV2ZW50LFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgZGlzcG9zZSgpO1xuICAgIH0sXG4gICAgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuICByZXR1cm4gcmVtb3RlT2JzZXJ2YWJsZURPTTtcbn1cbiIsICJpbXBvcnQgeyBSZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL25ldHdvcmtlZC1kb20tcHJvdG9jb2xcIjtcbmltcG9ydCB7IERPTVJ1bm5lckZhY3RvcnksIERPTVJ1bm5lckludGVyZmFjZSwgRE9NUnVubmVyTWVzc2FnZSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmxldCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcbmlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKSAtIChkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXIpO1xufVxuXG4vKipcbiAqIFdlYkJyb3dzZXJET01SdW5uZXIgaXMgYSBET01SdW5uZXJJbnRlcmZhY2UgaW1wbGVtZW50YXRpb24gdGhhdCBydW5zIGluIGEgd2ViIGJyb3dzZXIuIEl0IGlzIGludGVuZGVkIHRvIGJlIHJ1biBpblxuICogYW4gaWZyYW1lIGFuZCB0aGUgcGFyZW50IHdpbmRvdyBpcyBleHBlY3RlZCB0byBzZW5kIG1lc3NhZ2VzIHRvIGl0IHRvIGRpc3BhdGNoIGV2ZW50cyBhbmQgdG8gcmVjZWl2ZSBtdXRhdGlvblxuICogbWVzc2FnZXMuXG4gKlxuICogSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgZG9jdW1lbnQgY29udGVudHMgaXMgaW5qZWN0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJCcm93c2VyRE9NUnVubmVyIGltcGxlbWVudHMgRE9NUnVubmVySW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBtdXRhdGlvbk9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IG9iamVjdCwgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkKSB7XG4gICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuXG4gICAgLy8gRm9yd2FyZCBjb25zb2xlIG1lc3NhZ2VzXG4gICAgZm9yIChjb25zdCBsZXZlbCBvZiBbXCJlcnJvclwiLCBcIndhcm5cIiwgXCJpbmZvXCIsIFwibG9nXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBkZWZhdWx0Rm4gPSB3aW5kb3cuY29uc29sZVtsZXZlbF07XG5cbiAgICAgIHdpbmRvdy5jb25zb2xlW2xldmVsXSA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGFyZ3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlZmF1bHRGbiguLi5hcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRm9yd2FyZCB1bmNhdWdodCBlcnJvcnNcbiAgICB3aW5kb3cub25lcnJvciA9IChtZXNzYWdlLCBzb3VyY2UsIGxpbmUsIGNvbHVtbiwgZXJyb3IpID0+IHtcbiAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgIGxldmVsOiBcInN5c3RlbVwiLFxuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgdHlwZTogZXJyb3I/Lm5hbWUsXG4gICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgIGNvbHVtbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBsZXQgZGlkU2VuZExvYWQgPSBmYWxzZTtcblxuICAgIHRoaXMubXV0YXRpb25PYnNlcnZlciA9IG5ldyB3aW5kb3cuTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25MaXN0KSA9PiB7XG4gICAgICBpZiAoIWRvY3VtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXV0YXRpb25PYnNlcnZlciBjYWxsZWQgYmVmb3JlIGxvYWRcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbXV0YXRpb25MaXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAod2luZG93IGFzIGFueSkucGFyYW1zID0gcGFyYW1zO1xuXG4gICAgY29uc3QgZmluaXNoTG9hZCA9ICgpID0+IHtcbiAgICAgIGlmIChkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5pc2hMb2FkIGNhbGxlZCB0d2ljZVwiKTtcbiAgICAgIH1cbiAgICAgIGRpZFNlbmRMb2FkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHRoaXMubXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHdpbmRvdy5kb2N1bWVudCwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICBzZXRUaW1lb3V0KGZpbmlzaExvYWQsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgZmluaXNoTG9hZCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IFJlbW90ZUV2ZW50LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBidWJibGVzID0gcmVtb3RlRXZlbnQuYnViYmxlcyB8fCBmYWxzZTtcbiAgICBjb25zdCByZW1vdGVFdmVudE9iamVjdCA9IG5ldyBDdXN0b21FdmVudChyZW1vdGVFdmVudC5uYW1lLCB7XG4gICAgICBidWJibGVzLFxuICAgICAgZGV0YWlsOiB7IC4uLnJlbW90ZUV2ZW50LnBhcmFtcywgY29ubmVjdGlvbklkIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBldmVudFR5cGVMb3dlckNhc2UgPSByZW1vdGVFdmVudC5uYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBUT0RPIC0gY2hlY2sgaWYgdGhlcmUgYXJlIG90aGVyIGV2ZW50cyB0aGF0IGF1dG9tYXRpY2FsbHkgd2lyZSB1cCBzaW1pbGFybHkgdG8gY2xpY2stPm9uY2xpY2sgYW5kIGF2b2lkIHRob3NlIHRvb1xuICAgIGlmIChldmVudFR5cGVMb3dlckNhc2UgIT09IFwiY2xpY2tcIikge1xuICAgICAgY29uc3QgaGFuZGxlckF0dHJpYnV0ZU5hbWUgPSBcIm9uXCIgKyBldmVudFR5cGVMb3dlckNhc2U7XG4gICAgICBjb25zdCBoYW5kbGVyQXR0cmlidXRlVmFsdWUgPSByZWFsRWxlbWVudC5nZXRBdHRyaWJ1dGUoaGFuZGxlckF0dHJpYnV0ZU5hbWUpO1xuICAgICAgaWYgKGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSkge1xuICAgICAgICAvLyBUaGlzIGV2ZW50IGlzIGRlZmluZWQgYXMgYW4gSFRNTCBldmVudCBhdHRyaWJ1dGUuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZm4gPSBGdW5jdGlvbihcImV2ZW50XCIsIGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSk7XG4gICAgICAgICAgZm4uYXBwbHkocmVhbEVsZW1lbnQsIFtyZW1vdGVFdmVudE9iamVjdF0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHJ1bm5pbmcgZXZlbnQgaGFuZGxlcjpcIiwgZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0aGUgZXZlbnQgdmlhIEphdmFTY3JpcHQuXG4gICAgcmVhbEVsZW1lbnQuZGlzcGF0Y2hFdmVudChyZW1vdGVFdmVudE9iamVjdCk7XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIC8vIFRPRE8gLSBoYW5kbGUgZGlzcG9zZVxuICAgIGNvbnNvbGUubG9nKFwiV2ViQnJvd3NlckRPTVJ1bm5lci5kaXNwb3NlXCIpO1xuICB9XG5cbiAgZ2V0RG9jdW1lbnQoKTogRG9jdW1lbnQge1xuICAgIHJldHVybiBkb2N1bWVudDtcbiAgfVxuXG4gIGdldERvY3VtZW50VGltZSgpOiBudW1iZXIge1xuICAgIGNvbnN0IGRhdGVCYXNlZERvY3VtZW50VGltZSA9IERhdGUubm93KCkgLSBkb2N1bWVudExvYWRUaW1lO1xuICAgIGlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICAgICAgY29uc3QgdGltZSA9IGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lIGFzIG51bWJlcjtcbiAgICAgIGlmIChkYXRlQmFzZWREb2N1bWVudFRpbWUgPiB0aW1lICsgNTAwKSB7XG4gICAgICAgIC8vIFRoZSB0aW1lbGluZSBjYW4gYmUgXCJsZWZ0IGJlaGluZFwiIGlmIHRoZSB0YWIgaXMgYmFja2dyb3VuZGVkIGZvciBhIHdoaWxlLCBzbyB3ZSB1c2UgdGhlIGRhdGUtYmFzZWQgdGltZVxuICAgICAgICAvLyBpbnN0ZWFkLiBJZi93aGVuIHRoZSBkb2N1bWVudCBpcyBicm91Z2h0IGJhY2sgaW50byB0aGUgZm9yZWdyb3VuZCwgdGhlIHRpbWVsaW5lIHdpbGwgY2F0Y2ggdXAuXG4gICAgICAgIHJldHVybiBkYXRlQmFzZWREb2N1bWVudFRpbWU7XG4gICAgICB9XG4gICAgICAvLyBJZGVhbCBjYXNlIC0gdXNlIHRoZSBkb2N1bWVudC50aW1lbGluZSBhcyBpdCdzIHdoYXQgaXMgYXZhaWxhYmxlIHRvIHRoZSBkb2N1bWVudCBzY3JpcHRcbiAgICAgIHJldHVybiB0aW1lO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZUJhc2VkRG9jdW1lbnRUaW1lO1xuICB9XG5cbiAgLy8gVE9ETyAtIHJlc29sdmUgdHlwZXMgKFdpbmRvdyBuZWVkcyB0byBleHBvc2UgY2xhc3NlcyBzdWNoIGFzIEN1c3RvbUV2ZW50IGFzIHByb3BlcnRpZXMpXG4gIGdldFdpbmRvdygpOiBhbnkge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH1cbn1cbiIsICJpbXBvcnQgeyBPYnNlcnZhYmxlRE9NIH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20vc3JjL09ic2VydmFibGVET01cIjtcbmltcG9ydCB7XG4gIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICBET01fTUVTU0FHRV9UWVBFLFxuICBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG59IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tLWNvbW1vblwiO1xuXG5pbXBvcnQgeyBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSB9IGZyb20gXCIuL1dlYkJyb3dzZXJET01SdW5uZXJcIjtcblxuLyoqXG4gKiBUaGlzIGlzIHJ1biBpbiB0aGUgaWZyYW1lIHRoYXQgd2lsbCBleGVjdXRlIHRoZSBkb2N1bWVudCBzY3JpcHQgdG8gc2V0dXAgdGhlIGxpc3RlbmluZyBmb3IgZXZlbnRzIG1lc3NhZ2VzIGFuZFxuICogb2JzZXJ2aW5nIG9mIERPTSBtdXRhdGlvbiB1c2luZyB0aGUgV2ViQnJvd3NlckRPTVJ1bm5lciBjbGFzcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldHVwSWZyYW1lV2ViUnVubmVyKGFyZ3NTdHJpbmc6IHN0cmluZykge1xuICBjb25zdCBvYnNlcnZhYmxlRE9NUGFyYW1zID0gSlNPTi5wYXJzZShhdG9iKGFyZ3NTdHJpbmcpKSBhcyBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycztcblxuICBjb25zdCBzZW5kTWVzc2FnZVRvSGFuZGxlciA9IChtZXNzYWdlOiBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSkgPT4ge1xuICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoSlNPTi5zdHJpbmdpZnkobWVzc2FnZSksIFwiKlwiKTtcbiAgfTtcblxuICBjb25zdCBvYnNlcnZhYmxlRE9NID0gbmV3IE9ic2VydmFibGVET00oXG4gICAge1xuICAgICAgLi4ub2JzZXJ2YWJsZURPTVBhcmFtcyxcbiAgICAgIGh0bWxDb250ZW50czogXCJcIiwgLy8gVGhpcyBtdXN0IGJlIGVtcHR5IGFzIHRoZSBjb250ZW50cyBhcmUgYXNzdW1lZCB0byBiZSBwcm92aWRlZCBieSB0aGUgc3JjZG9jXG4gICAgfSxcbiAgICAob2JzZXJ2YWJsZURPTU1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlKSA9PiB7XG4gICAgICBzZW5kTWVzc2FnZVRvSGFuZGxlcih7XG4gICAgICAgIHR5cGU6IERPTV9NRVNTQUdFX1RZUEUsXG4gICAgICAgIG1lc3NhZ2U6IG9ic2VydmFibGVET01NZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeSxcbiAgKTtcblxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgKGUpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGUuZGF0YSkgYXMgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlO1xuICAgIHN3aXRjaCAocGFyc2VkLnR5cGUpIHtcbiAgICAgIGNhc2UgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmV2ZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00uYWRkQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5yZW1vdmVDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVua25vd24gbWVzc2FnZSB0eXBlXCIsIHBhcnNlZCk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgeyBzZXR1cElmcmFtZVdlYlJ1bm5lciB9IGZyb20gXCIuL0lmcmFtZVdlYlJ1bm5lclwiO1xuXG5jb25zdCBhcmdzID0gKHdpbmRvdyBhcyBhbnkpLmFyZ3M7XG5zZXR1cElmcmFtZVdlYlJ1bm5lcihhcmdzKTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFJTyxTQUFTLDBCQUEwQixJQUFvRDtBQUM1RixTQUFPO0FBQUEsSUFDTCxRQUFRLEdBQUc7QUFBQSxJQUNYLEtBQUssR0FBRztBQUFBLElBQ1IsWUFBWSxHQUFHO0FBQUEsSUFDZixZQUFZLEdBQUcsV0FBVyxJQUFJLENBQUMsVUFBVSwwQkFBMEIsS0FBSyxDQUFDO0FBQUEsSUFDekUsYUFBYSxHQUFHO0FBQUEsRUFDbEI7QUFDRjs7O0FDd0NPLElBQU0sZ0JBQU4sTUFBc0Q7QUFBQSxFQWMzRCxZQUNFLHlCQUNBLFVBQ0EsZUFDQTtBQWpCRixTQUFRLGVBQWUsb0JBQUksSUFBbUM7QUFDOUQsU0FBUSxlQUFlLG9CQUFJLElBQW1DO0FBQzlELFNBQVEsOEJBQThCLG9CQUFJLElBQTJDO0FBQ3JGLFNBQVEsa0JBQWtCO0FBRTFCLFNBQVEs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Q0Y7QUFBQSxJQUNGO0FBR0EsZ0JBQVksY0FBYyxpQkFBaUI7QUFBQSxFQUM3QztBQUFBLEVBRUEsVUFBZ0I7QUFFZCxZQUFRLElBQUksNkJBQTZCO0FBQUEsRUFDM0M7QUFBQSxFQUVBLGNBQXdCO0FBQ3RCLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFQSxrQkFBMEI7QUFDeEIsVUFBTSx3QkFBd0IsS0FBSyxJQUFJLElBQUk7QUFDM0MsUUFBSSxTQUFTLFlBQVksU0FBUyxTQUFTLGFBQWE7QUFDdEQsWUFBTSxPQUFPLFNBQVMsU0FBUztBQUMvQixVQUFJLHdCQUF3QixPQUFPLEtBQUs7QUFHdEMsZUFBTztBQUFBLE1BQ1Q7QUFFQSxhQUFPO0FBQUEsSUFDVDtBQUNBLFdBQU87QUFBQSxFQUNUO0FBQUE7QUFBQSxFQUdBLFlBQWlCO0FBQ2YsV0FBTztBQUFBLEVBQ1Q7QUFDRjs7O0FDaEpPLFNBQVMscUJBQXFCLFlBQW9CO0FBQ3ZELFFBQU0sc0JBQXNCLEtBQUssTUFBTSxLQUFLLFVBQVUsQ0FBQztBQUV2RCxRQUFNLHVCQUF1QixDQUFDLFlBQThDO0FBQzFFLFdBQU8sT0FBTyxZQUFZLEtBQUssVUFBVSxPQUFPLEdBQUcsR0FBRztBQUFBLEVBQ3hEO0FBRUEsUUFBTSxnQkFBZ0IsSUFBSTtBQUFBLElBQ3hCO0FBQUEsTUFDRSxHQUFHO0FBQUEsTUFDSCxjQUFjO0FBQUE7QUFBQSxJQUNoQjtBQUFBLElBQ0EsQ0FBQyx5QkFBK0M7QUFDOUMsMkJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFFBQ04sU0FBUztBQUFBLE1BQ1gsQ0FBQztBQUFBLElBQ0g7QUFBQSxJQUNBO0FBQUEsRUFDRjtBQUVBLFNBQU8saUJBQWlCLFdBQVcsQ0FBQyxNQUFNO0FBQ3hDLFVBQU0sU0FBUyxLQUFLLE1BQU0sRUFBRSxJQUFJO0FBQ2hDLFlBQVEsT0FBTyxNQUFNO0FBQUEsTUFDbkIsS0FBSztBQUNILHNCQUFjLG9DQUFvQyxPQUFPLGNBQWMsT0FBTyxLQUFLO0FBQ25GO0FBQUEsTUFDRixLQUFLO0FBQ0gsc0JBQWMsbUJBQW1CLE9BQU8sWUFBWTtBQUNwRDtBQUFBLE1BQ0YsS0FBSztBQUNILHNCQUFjLHNCQUFzQixPQUFPLFlBQVk7QUFDdkQ7QUFBQSxNQUNGO0FBQ0UsZ0JBQVEsTUFBTSx3QkFBd0IsTUFBTTtBQUFBLElBQ2hEO0FBQUEsRUFDRixDQUFDO0FBQ0g7OztBQ3JEQSxJQUFNLE9BQVEsT0FBZTtBQUM3QixxQkFBcUIsSUFBSTsiLAogICJuYW1lcyI6IFsiYXJncyJdCn0K\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\n/**\n * RunnerIframe is a class that creates an iframe that includes the networked-dom-web-runner-iframe package in it and\n * injects the provided HTML into it. This class then communicates with the iframe using postMessage.\n */\nexport class RunnerIframe {\n private iframe: HTMLIFrameElement;\n private postMessageListener: (messageEvent: MessageEvent) => void;\n\n constructor(\n private observableDOMParameters: ObservableDOMParameters,\n private 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 ...this.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.postMessageListener = (e: MessageEvent) => {\n if (e.source === this.iframe.contentWindow || (isJSDOM && e.source === null)) {\n const parsed = JSON.parse(e.data) as FromObservableDOMInstanceMessage;\n this.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\n/**\n * The NetworkedDOMWebRunnerClient class can be used to view and interact with a NetworkedDOM document instance that is\n * available directly in the browser (rather than exposed over the network). This is useful for usage modes where the\n * document does not need to be available to other clients, such as a single-user or an edit/preview mode.\n *\n * The class takes arguments for where the view of the document should be synchronized to in the DOM, and which window\n * instance to use to create any other elements (to allow for using iframes to isolate the document from the rest of\n * the page).\n */\nexport class NetworkedDOMWebRunnerClient {\n public readonly element: HTMLElement;\n\n public connectedState: {\n document: NetworkedDOM | EditableNetworkedDOM;\n domWebsocket: NetworkedDOMWebsocket;\n fakeWebsocket: FakeWebsocket;\n } | null = null;\n private enableEventHandling: boolean;\n\n constructor(enableEventHandling = true, element?: HTMLElement) {\n this.enableEventHandling = enableEventHandling;\n this.element = element || document.createElement(\"div\");\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.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.element.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.element,\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", "/**\n * WebsocketEnd is one end of a FakeWebsocket connection. It is used to simulate a websocket connection for testing or\n * matching the interface of a real websocket connection without doing any actual networking.\n */\nclass 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\n/**\n * FakeWebsocket is a pair of WebsocketEnds that are connected to each other. It is used to simulate a websocket\n * connection for testing or matching the interface of a real websocket connection without doing any actual networking.\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\n/**\n * Creates an ObservableDOMInterface that uses an iframe to run the document.\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
5
  "mappings": "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",
6
6
  "names": ["document"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mml-io/networked-dom-web-runner",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -20,8 +20,8 @@
20
20
  "test-iterate": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch"
21
21
  },
22
22
  "dependencies": {
23
- "@mml-io/networked-dom-web": "^0.17.1",
24
- "@mml-io/observable-dom-common": "^0.17.1"
23
+ "@mml-io/networked-dom-web": "^0.18.0",
24
+ "@mml-io/observable-dom-common": "^0.18.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@mml-io/networked-dom-web-runner-iframe": "file:../networked-dom-web-runner-iframe",
@@ -29,5 +29,5 @@
29
29
  "jest-environment-jsdom": "29.7.0",
30
30
  "jest-expect-message": "1.1.3"
31
31
  },
32
- "gitHead": "d1069c5541fadd1ae78700dbbd94d55a481d373a"
32
+ "gitHead": "b1a31e364d69287681b0afeecdca2b4bc576e3d3"
33
33
  }