@mml-io/networked-dom-web-runner 0.22.0 → 0.23.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/FakeWebsocket.d.ts +1 -0
- package/build/FakeWebsocket.d.ts.map +1 -0
- package/build/IframeObservableDOMFactory.d.ts +1 -0
- package/build/IframeObservableDOMFactory.d.ts.map +1 -0
- package/build/NetworkedDOMWebRunnerClient.d.ts +1 -0
- package/build/NetworkedDOMWebRunnerClient.d.ts.map +1 -0
- package/build/RunnerIframe.d.ts +1 -0
- package/build/RunnerIframe.d.ts.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +6 -2
- package/build/index.js.map +2 -2
- package/package.json +4 -4
package/build/FakeWebsocket.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FakeWebsocket.d.ts","sourceRoot":"","sources":["../src/FakeWebsocket.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAM,YAAa,SAAQ,WAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoE;IACjG,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,cAAc,CAA2B;gBAG/C,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,eAAe,KAAK,IAAI;IAO1E,KAAK;IAIL,gBAAgB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACvD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,GAAG,EAC5D,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB;IAqBtC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAWpC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,eAAe;CAGpE;AAED;;;GAGG;AACH,qBAAa,aAAa;IACjB,mBAAmB,EAAE,YAAY,CAAC;IAClC,mBAAmB,EAAE,YAAY,CAAC;gBAE7B,QAAQ,EAAE,MAAM;CAiB7B"}
|
|
@@ -3,3 +3,4 @@ import { ObservableDOMFactory } from "@mml-io/networked-dom-document";
|
|
|
3
3
|
* Creates an ObservableDOMInterface that uses an iframe to run the document.
|
|
4
4
|
*/
|
|
5
5
|
export declare const IframeObservableDOMFactory: ObservableDOMFactory;
|
|
6
|
+
//# sourceMappingURL=IframeObservableDOMFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IframeObservableDOMFactory.d.ts","sourceRoot":"","sources":["../src/IframeObservableDOMFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAatE;;GAEG;AACH,eAAO,MAAM,0BAA0B,EAAE,oBA0BxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NetworkedDOMWebRunnerClient.d.ts","sourceRoot":"","sources":["../src/NetworkedDOMWebRunnerClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;GAQG;AACH,qBAAa,2BAA2B;IACtC,SAAgB,OAAO,EAAE,WAAW,CAAC;IAE9B,cAAc,EAAE;QACrB,QAAQ,EAAE,YAAY,GAAG,oBAAoB,CAAC;QAC9C,YAAY,EAAE,qBAAqB,CAAC;QACpC,aAAa,EAAE,aAAa,CAAC;KAC9B,GAAG,IAAI,CAAQ;IAChB,OAAO,CAAC,mBAAmB,CAAU;gBAEzB,mBAAmB,UAAO,EAAE,OAAO,CAAC,EAAE,WAAW;IAKtD,UAAU;IAgBV,OAAO;IAKP,OAAO,CACZ,QAAQ,EAAE,YAAY,GAAG,oBAAoB,EAC7C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;CAuCxC"}
|
package/build/RunnerIframe.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunnerIframe.d.ts","sourceRoot":"","sources":["../src/RunnerIframe.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,uBAAuB,EACvB,8BAA8B,EAC/B,MAAM,+BAA+B,CAAC;AAIvC;;;GAGG;AACH,qBAAa,YAAY;IAKrB,OAAO,CAAC,uBAAuB;IAC/B,OAAO,CAAC,iBAAiB;IAL3B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,mBAAmB,CAAuC;gBAGxD,uBAAuB,EAAE,uBAAuB,EAChD,iBAAiB,EAAE,CAAC,OAAO,EAAE,gCAAgC,KAAK,IAAI;IAwDhF,mBAAmB,CAAC,OAAO,EAAE,8BAA8B;IAK3D,OAAO;CAIR"}
|
package/build/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gCAAgC,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -167,9 +167,13 @@ var NetworkedDOMWebRunnerClient = class {
|
|
|
167
167
|
if (!this.connectedState) {
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
|
-
this.connectedState.document.
|
|
170
|
+
if (this.connectedState.document.hasWebSocket(
|
|
171
171
|
this.connectedState.fakeWebsocket.serverSideWebsocket
|
|
172
|
-
)
|
|
172
|
+
)) {
|
|
173
|
+
this.connectedState.document.removeWebSocket(
|
|
174
|
+
this.connectedState.fakeWebsocket.serverSideWebsocket
|
|
175
|
+
);
|
|
176
|
+
}
|
|
173
177
|
this.connectedState = null;
|
|
174
178
|
}
|
|
175
179
|
dispose() {
|
package/build/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/FakeWebsocket.ts", "../src/IframeObservableDOMFactory.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/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\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 private hasMessageListener = false;\n private bufferedEvents: Array<MessageEvent> = [];\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 setTimeout(() => {\n listener.bind(this)(new Event(\"open\"));\n }, 1);\n return;\n }\n\n super.addEventListener(type, listener, options);\n\n if (type === \"message\") {\n this.hasMessageListener = true;\n const bufferedEvents = this.bufferedEvents;\n this.bufferedEvents = [];\n bufferedEvents.forEach((event) => {\n this.dispatchEvent(event);\n });\n }\n }\n\n public dispatchEvent(event: Event): boolean {\n if (event.type === \"message\") {\n if (!this.hasMessageListener) {\n // The message listener is not setup yet - buffer the event\n this.bufferedEvents.push(event as MessageEvent);\n return true;\n }\n }\n return super.dispatchEvent(event);\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", "// ../../observable-dom/src/utils.ts\nfunction virtualDOMElementToStatic(el) {\n return {\n nodeId: el.nodeId,\n tag: el.tag,\n attributes: Object.assign({}, el.attributes),\n // Copy the attributes object - shallow copy is fine as the attributes are strings\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, connectionToken) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"connected\", {\n detail: { connectionId, connectionToken }\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 if (mutationList.length > 1) {\n }\n const allMutationRecords = [];\n for (const mutation of mutationList) {\n const idsRecord = this.createMutationRecord(mutation);\n if (idsRecord) {\n allMutationRecords.push(idsRecord);\n }\n }\n if (allMutationRecords.length > 0) {\n this.callback(\n {\n mutations: allMutationRecords,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n }\n createMutationRecord(mutation) {\n if (this.isIgnoredElement(mutation.target)) {\n return null;\n }\n if (mutation.type === \"attributes\" && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.isIgnoredAttribute(mutation.target, mutation.attributeName)) {\n return null;\n }\n const targetNode = mutation.target;\n const targetElement = this.realElementToVirtualElement.get(targetNode);\n if (!targetElement) {\n return null;\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(\"Previous sibling is not currently a child of the parent element\");\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 if (toAdd.length === 0 && removedNodeIds.length === 0) {\n return null;\n }\n const addedNodes = toAdd.map(virtualDOMElementToStatic);\n return {\n type: \"childList\",\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: previousSiblingElement ? previousSiblingElement.nodeId : null\n };\n } else if (mutation.type === \"attributes\") {\n const attributeName = mutation.attributeName;\n if (!this.isIgnoredAttribute(targetNode, attributeName)) {\n const previousValue = targetElement.attributes[attributeName];\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n if (previousValue === void 0) {\n return null;\n }\n delete targetElement.attributes[attributeName];\n } else {\n if (attributeValue === previousValue) {\n return null;\n }\n targetElement.attributes[attributeName] = attributeValue;\n }\n return {\n type: \"attributes\",\n targetId: targetElement.nodeId,\n attributes: {\n [attributeName]: attributeValue\n }\n };\n }\n } else if (mutation.type === \"characterData\") {\n targetElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n return {\n type: \"characterData\",\n targetId: targetElement.nodeId,\n textContent: targetElement.textContent ? targetElement.textContent : \"\"\n };\n }\n throw new Error(\"Unknown mutation type: \" + mutation.type);\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 localNameValue = node.localName;\n const nodeNameValue = node.nodeName;\n let tag = localNameValue || nodeNameValue;\n if (tag !== \"#text\") {\n tag = tag.toUpperCase();\n }\n const virtualElement = {\n nodeId,\n tag,\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 }\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, parsed.connectionToken ?? null);\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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBPYmplY3QuYXNzaWduKHt9LCBlbC5hdHRyaWJ1dGVzKSwgLy8gQ29weSB0aGUgYXR0cmlidXRlcyBvYmplY3QgLSBzaGFsbG93IGNvcHkgaXMgZmluZSBhcyB0aGUgYXR0cmlidXRlcyBhcmUgc3RyaW5nc1xuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgU3RhdGljVmlydHVhbERPTUVsZW1lbnQsXG4gIFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJNZXNzYWdlID0ge1xuICBsb2FkZWQ/OiBib29sZWFuO1xuICBtdXRhdGlvbkxpc3Q/OiBBcnJheTxNdXRhdGlvblJlY29yZD47XG4gIGxvZ01lc3NhZ2U/OiBMb2dNZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRE9NUnVubmVySW50ZXJmYWNlID0ge1xuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudDtcbiAgZ2V0V2luZG93KCk6IFdpbmRvdyAmIHtcbiAgICBDdXN0b21FdmVudDogdHlwZW9mIEN1c3RvbUV2ZW50O1xuICAgIFRleHQ6IHR5cGVvZiBUZXh0O1xuICAgIEhUTUxTY3JpcHRFbGVtZW50OiB0eXBlb2YgSFRNTFNjcmlwdEVsZW1lbnQ7XG4gICAgQ29tbWVudDogdHlwZW9mIENvbW1lbnQ7XG4gIH07IC8vIFRPRE8gLSBEZWZpbmUgdGhpcyB3aXRob3V0IHVzaW5nIEpTRE9NIHR5cGVzXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQ7XG4gIGRpc3Bvc2UoKTogdm9pZDtcbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkLFxuKSA9PiBET01SdW5uZXJJbnRlcmZhY2U7XG5cbmV4cG9ydCB0eXBlIExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IE9taXQ8U3RhdGljVmlydHVhbERPTUVsZW1lbnQsIFwiY2hpbGROb2Rlc1wiPiAmIHtcbiAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQgfCBUZXh0O1xuICBjaGlsZE5vZGVzOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+O1xuICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGw7XG59O1xuXG4vKipcbiAqIFRoZSBPYnNlcnZhYmxlRE9NIGNsYXNzIGhhbmRsZXMgdGhlIHJ1bm5pbmcgb2YgYW4gSFRNTCBkb2N1bWVudCB1c2luZyBhIHByb3ZpZGVkIERPTVJ1bm5lckZhY3RvcnkgYW5kIGNvbnZlcnRpbmcgdGhlXG4gKiBtdXRhdGlvbnMgdGhhdCBhcmUgc3RydWN0dXJlZCBhcyByZWZlcmVuY2VzIHRvIGxpdmUgRE9NIGVsZW1lbnRzIGludG8gbWVzc2FnZXMgdGhhdCByZWZlciB0byBlbGVtZW50cyBieSBub2RlSWRzLlxuICovXG5leHBvcnQgY2xhc3MgT2JzZXJ2YWJsZURPTSBpbXBsZW1lbnRzIE9ic2VydmFibGVET01JbnRlcmZhY2Uge1xuICBwcml2YXRlIG5vZGVUb05vZGVJZCA9IG5ldyBNYXA8TGl2ZVZpcnR1YWxET01FbGVtZW50LCBudW1iZXI+KCk7XG4gIHByaXZhdGUgbm9kZUlkVG9Ob2RlID0gbmV3IE1hcDxudW1iZXIsIExpdmVWaXJ0dWFsRE9NRWxlbWVudD4oKTtcbiAgcHJpdmF0ZSByZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQgPSBuZXcgTWFwPEVsZW1lbnQgfCBUZXh0LCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgaWdub3JlVGV4dE5vZGVzID0gdHJ1ZTtcbiAgcHJpdmF0ZSBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkO1xuICBwcml2YXRlIG5leHROb2RlSWQgPSAxO1xuICBwcml2YXRlIGh0bWxQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgZG9tUnVubmVyOiBET01SdW5uZXJJbnRlcmZhY2U7XG4gIHByaXZhdGUgbG9hZGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcHJlTG9hZExvZ01lc3NhZ2VzOiBBcnJheTxMb2dNZXNzYWdlPiA9IFtdO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhcbiAgICAgICAgICAgIHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc25hcHNob3QsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yIChjb25zdCBsb2dNZXNzYWdlIG9mIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcyA9IFtdO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubXV0YXRpb25MaXN0KSB7XG4gICAgICAgICAgdGhpcy5wcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLmxvYWRlZCkge1xuICAgICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMucHVzaChkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBsb2dNZXNzYWdlOiBkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIsIGNvbm5lY3Rpb25Ub2tlbjogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImNvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQsIGNvbm5lY3Rpb25Ub2tlbiB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJkaXNjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChtdXRhdGlvbkxpc3Q6IEFycmF5PE11dGF0aW9uUmVjb3JkPik6IHZvaWQge1xuICAgIGlmIChtdXRhdGlvbkxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy8gVE9ETyAoaHR0cHM6Ly9naXRodWIuY29tL21tbC1pby9tbWwvaXNzdWVzLzEwMCkgLSB3YWxrIGJhY2sgdGhyb3VnaCB0aGUgcmVjb3JkcyB0byBkZXJpdmUgdGhlIGludGVybWVkaWF0ZVxuICAgICAgLy8gIHN0YXRlcyAoZS5nLiBpZiBhbiBhdHRyaWJ1dGUgaXMgbGF0ZXIgYWRkZWQgdG8gYW4gZWxlbWVudCBjcmVhdGVkIGluIGFuIGVhcmxpZXIgcmVjb3JkIHRoZW4gaXQgc2hvdWxkIG5vdFxuICAgICAgLy8gIGhhdmUgdGhhdCBhdHRyaWJ1dGUgd2hlbiB0aGUgZWxlbWVudCBpcyBhZGRlZC4gVGhpcyBpcyBpbXBvcnRhbnQgYXMgaW5jb3JyZWN0IGF0dHJpYnV0ZSBzZXRzIGNhbiBhZmZlY3RcbiAgICAgIC8vICB2aXNpYmlsaXR5IGFuZCBleHBlY3RlZCBjbGllbnQgcGVyZm9ybWFuY2UuXG4gICAgfVxuXG4gICAgY29uc3QgYWxsTXV0YXRpb25SZWNvcmRzOiBBcnJheTxTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQ+ID0gW107XG4gICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgIGNvbnN0IGlkc1JlY29yZCA9IHRoaXMuY3JlYXRlTXV0YXRpb25SZWNvcmQobXV0YXRpb24pO1xuICAgICAgaWYgKGlkc1JlY29yZCkge1xuICAgICAgICBhbGxNdXRhdGlvblJlY29yZHMucHVzaChpZHNSZWNvcmQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChhbGxNdXRhdGlvblJlY29yZHMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uczogYWxsTXV0YXRpb25SZWNvcmRzLFxuICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgfSxcbiAgICAgICAgdGhpcyxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVNdXRhdGlvblJlY29yZChtdXRhdGlvbjogTXV0YXRpb25SZWNvcmQpOiBTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQgfCBudWxsIHtcbiAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiICYmXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0LCBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lISlcbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHRhcmdldE5vZGUgPSBtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldCh0YXJnZXROb2RlKTtcbiAgICBpZiAoIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgIC8vIFRoaXMgY2FuIGhhcHBlbiBpZiB0aGUgdGFyZ2V0IGVsZW1lbnQgZm9yIHRoaXMgbXV0YXRpb24gaGFzIGJlZW4gcmVtb3ZlZCBpbiBhIHByZXZpb3VzIG11dGF0aW9uXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBsZXQgcHJldmlvdXNTaWJsaW5nRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGluc2VydGlvbkluZGV4ID0gMDtcbiAgICBjb25zdCB0b0FkZDogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PiA9IFtdO1xuICAgIGNvbnN0IHJlbW92ZWROb2RlSWRzOiBBcnJheTxudW1iZXI+ID0gW107XG5cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgbXV0YXRpb24ucmVtb3ZlZE5vZGVzLmZvckVhY2goKG5vZGU6IE5vZGUpID0+IHtcbiAgICAgICAgY29uc3QgYXNFbGVtZW50T3JUZXh0ID0gbm9kZSBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChhc0VsZW1lbnRPclRleHQpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoaWxkRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChhc0VsZW1lbnRPclRleHQpO1xuICAgICAgICBpZiAoIWNoaWxkRE9NRWxlbWVudCkge1xuICAgICAgICAgIC8qXG4gICAgICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZiBlbGVtZW50IHdhcyBhIGNoaWxkIG9mIGEgcGFyZW50IGVsZW1lbnQsIGJ1dCB3YXMgbW92ZWQgdG8gYSBuZXcgcGFyZW50IGluIHRoZSBzYW1lIGJhdGNoIG9mIG11dGF0aW9ucy5cbiAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgKi9cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgaW5kZXggPSB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZiBlbGVtZW50IHdhcyBhIGNoaWxkIG9mIGEgcGFyZW50IGVsZW1lbnQsIGJ1dCB3YXMgbW92ZWQgdG8gYSBuZXcgcGFyZW50IGluIHRoZSBzYW1lIGJhdGNoIG9mIG11dGF0aW9ucy5cbiAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgKi9cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgICAgcmVtb3ZlZE5vZGVJZHMucHVzaChjaGlsZERPTUVsZW1lbnQubm9kZUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbW92YWwgPSB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIGlmIChyZW1vdmFsLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZW1vdmFsIGxlbmd0aCBub3QgMVwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChyZW1vdmFsWzBdLm5vZGVJZCAhPT0gY2hpbGRET01FbGVtZW50Lm5vZGVJZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbm9kZSBpZCBtaXNtYXRjaFwiKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAoYXNFbGVtZW50T3JUZXh0LnBhcmVudE5vZGUgIT09IHRhcmdldE5vZGUpIHtcbiAgICAgICAgICAvLyBJZ25vcmUgdGhpcyBhZGRpdGlvbiAtIGl0IGlzIGxpa2VseSBvdmVycmlkZGVuIGJ5IGFuIGVhcmxpZXIgYWRkaXRpb24gb2YgdGhpcyBlbGVtZW50IHRvIGl0cyBldmVudHVhbCBub2RlIGluIHRoaXMgbXV0YXRpb24gYmF0Y2hcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgRWl0aGVyIHRoZXJlIGlzIG5vIHByZXZpb3VzIGVsZW1lbnQgKHRoaXMgaXMgdGhlIGZpcnN0IGVsZW1lbnQpXG4gICAgICAgICAgICAgb3IgdGhlIHByZXZpb3VzIGVsZW1lbnQgaGFzIG5vdCB5ZXQgYmVlbiBkZXRlcm1pbmVkLlxuXG4gICAgICAgICAgICAgVXNlIHRoZSBjdXJyZW50IHByZXZpb3VzIHNpYmxpbmcgb2YgdGhpcyBhZGRlZCBub2RlIGFzIHRoZSBmaXJzdFxuICAgICAgICAgICAgIGNob2ljZSBmb3IgdGhlIHByZXZpb3VzIHNpYmxpbmcsIGJ1dCBvbmx5IHVzZSBwcmV2aW91cyBzaWJsaW5nc1xuICAgICAgICAgICAgIHRoYXQgYXJlIG5vdCBpZ25vcmVkIChhcmUgdHJhY2tlZCBhcyB2aXJ0dWFsIGVsZW1lbnRzKS5cbiAgICAgICAgICAgICovXG4gICAgICAgICAgICBsZXQgZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nOiBFbGVtZW50IHwgVGV4dCB8IG51bGwgPVxuICAgICAgICAgICAgICBhc0VsZW1lbnRPclRleHQucHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICAgICAgbGV0IHZpcnR1YWxQcmV2aW91c1NpYmxpbmc6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHdoaWxlIChmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgJiYgIXZpcnR1YWxQcmV2aW91c1NpYmxpbmcpIHtcbiAgICAgICAgICAgICAgdmlydHVhbFByZXZpb3VzU2libGluZyA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChcbiAgICAgICAgICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nICYmXG4gICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YodmlydHVhbFByZXZpb3VzU2libGluZykgPT09IC0xXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgZWxlbWVudCBpcyBub3QgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnQgLSBpdCBpcyBub3QgYSB2YWxpZCBwcmV2aW91cyBzaWJsaW5nXG4gICAgICAgICAgICAgICAgdmlydHVhbFByZXZpb3VzU2libGluZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyA9IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZy5wcmV2aW91c1NpYmxpbmcgYXNcbiAgICAgICAgICAgICAgICB8IEVsZW1lbnRcbiAgICAgICAgICAgICAgICB8IFRleHRcbiAgICAgICAgICAgICAgICB8IG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgICAgICAgIHByZXZpb3VzU2libGluZ0VsZW1lbnQgPSB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nO1xuICAgICAgICAgICAgICBpbnNlcnRpb25JbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKHByZXZpb3VzU2libGluZ0VsZW1lbnQpO1xuICAgICAgICAgICAgICBpZiAoaW5zZXJ0aW9uSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUHJldmlvdXMgc2libGluZyBpcyBub3QgY3VycmVudGx5IGEgY2hpbGQgb2YgdGhlIHBhcmVudCBlbGVtZW50XCIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGluc2VydGlvbkluZGV4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNoaWxkVmlydHVhbERPTUVsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgICAgYXNFbGVtZW50T3JUZXh0LFxuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgICB0b0FkZC5wdXNoKGNoaWxkVmlydHVhbERPTUVsZW1lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluc2VydGlvbkluZGV4LCAwLCAuLi50b0FkZCk7XG5cbiAgICAgIGlmICh0b0FkZC5sZW5ndGggPT09IDAgJiYgcmVtb3ZlZE5vZGVJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIFRoaXMgaXMgYSBuby1vcCBtdXRhdGlvblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcbiAgICAgIGNvbnN0IGFkZGVkTm9kZXM6IEFycmF5PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50PiA9IHRvQWRkLm1hcCh2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiY2hpbGRMaXN0XCIsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgYWRkZWROb2RlcyxcbiAgICAgICAgcmVtb3ZlZE5vZGVJZHMsXG4gICAgICAgIHByZXZpb3VzU2libGluZ0lkOiBwcmV2aW91c1NpYmxpbmdFbGVtZW50XG4gICAgICAgICAgPyAocHJldmlvdXNTaWJsaW5nRWxlbWVudCBhcyBMaXZlVmlydHVhbERPTUVsZW1lbnQpLm5vZGVJZFxuICAgICAgICAgIDogbnVsbCxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZU5hbWUgPSBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lITtcbiAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUodGFyZ2V0Tm9kZSwgYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgICAgY29uc3QgcHJldmlvdXNWYWx1ZSA9IHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXTtcbiAgICAgICAgY29uc3QgYXR0cmlidXRlVmFsdWUgPSAodGFyZ2V0Tm9kZSBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSk7XG4gICAgICAgIGlmIChhdHRyaWJ1dGVWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBuby1vcCBtdXRhdGlvblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGRlbGV0ZSB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIGEgbm8tb3AgbXV0YXRpb25cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSBhdHRyaWJ1dGVWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiYXR0cmlidXRlc1wiLFxuICAgICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICBbYXR0cmlidXRlTmFtZV06IGF0dHJpYnV0ZVZhbHVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImNoYXJhY3RlckRhdGFcIikge1xuICAgICAgdGFyZ2V0RWxlbWVudC50ZXh0Q29udGVudCA9IHRhcmdldE5vZGUudGV4dENvbnRlbnQgPyB0YXJnZXROb2RlLnRleHRDb250ZW50IDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJjaGFyYWN0ZXJEYXRhXCIsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgdGV4dENvbnRlbnQ6IHRhcmdldEVsZW1lbnQudGV4dENvbnRlbnQgPyB0YXJnZXRFbGVtZW50LnRleHRDb250ZW50IDogXCJcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBtdXRhdGlvbiB0eXBlOiBcIiArIG11dGF0aW9uLnR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVWaXJ0dWFsRE9NRWxlbWVudCh2aXJ0dWFsRE9NRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQucmVhbEVsZW1lbnQpO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcykge1xuICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGNvbnN0IFt2aXJ0dWFsRWxlbWVudCwgZXhpc3RpbmddID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChub2RlLCBwYXJlbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgY2hpbGQgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxFbGVtZW50KSB7XG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQuY2hpbGROb2Rlcy5wdXNoKGNoaWxkVmlydHVhbEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IFtMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLCBib29sZWFuXSB7XG4gICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChub2RlKSkge1xuICAgICAgcmV0dXJuIFtudWxsLCBmYWxzZV07XG4gICAgfVxuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFzc2lnbiBub2RlIGlkIHRvIG51bGxcIik7XG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmdWYWx1ZSA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChub2RlKTtcbiAgICBpZiAoZXhpc3RpbmdWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvKlxuICAgICAgIFRoaXMgaXMgdW5kZXNpcmFibGUsIGJ1dCB0aGUgYmF0Y2hpbmcgb2YgbXV0YXRpb25zIGZyb20gTXV0YXRpb25PYnNlcnZlciBtZWFucyB0aGF0XG4gICAgICAgdGhpcyBub2RlIGNvdWxkIGJlIGJlaW5nIGFkZGVkIGluIGEgbXV0YXRpb24gYWZ0ZXIgYSBtdXRhdGlvbiBvZiBhIHBhcmVudCB0aGF0IHdoZW5cbiAgICAgICBoYW5kbGVkIHJlc3VsdGluZyBpbiBhZGRpbmcgdGhpcyBub2RlIGVhcmx5LlxuICAgICAgKi9cbiAgICAgIHJldHVybiBbZXhpc3RpbmdWYWx1ZSwgdHJ1ZV07XG4gICAgfVxuXG4gICAgY29uc3QgYXR0cmlidXRlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGlmICgobm9kZSBhcyBhbnkpLmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IGFzSFRNTEVsZW1lbnQgPSBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGVOYW1lcygpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVsbCBhdHRyaWJ1dGUgdmFsdWUgZm9yIGtleTogXCIgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobm9kZSwga2V5KSkge1xuICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUlkID0gdGhpcy5uZXh0Tm9kZUlkKys7XG4gICAgY29uc3QgbG9jYWxOYW1lVmFsdWUgPSAobm9kZSBhcyBFbGVtZW50KS5sb2NhbE5hbWU7XG4gICAgY29uc3Qgbm9kZU5hbWVWYWx1ZSA9IG5vZGUubm9kZU5hbWU7XG4gICAgbGV0IHRhZyA9IGxvY2FsTmFtZVZhbHVlIHx8IG5vZGVOYW1lVmFsdWU7XG4gICAgaWYgKHRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICB0YWcgPSB0YWcudG9VcHBlckNhc2UoKTtcbiAgICB9XG5cbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50ID0ge1xuICAgICAgbm9kZUlkLFxuICAgICAgdGFnLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIGNoaWxkTm9kZXM6IFtdLFxuICAgICAgcmVhbEVsZW1lbnQ6IG5vZGUsXG4gICAgICBwYXJlbnQsXG4gICAgfTtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLlRleHQgJiYgbm9kZS50ZXh0Q29udGVudCkge1xuICAgICAgdmlydHVhbEVsZW1lbnQudGV4dENvbnRlbnQgPSBub2RlLnRleHRDb250ZW50O1xuICAgIH1cbiAgICB0aGlzLm5vZGVUb05vZGVJZC5zZXQodmlydHVhbEVsZW1lbnQsIG5vZGVJZCk7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuc2V0KG5vZGVJZCwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LnNldChub2RlLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgcmV0dXJuIFt2aXJ0dWFsRWxlbWVudCwgZmFsc2VdO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHtcbiAgT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbn0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgY29ubmVjdGlvblRva2VuOiBzdHJpbmcgfCBudWxsO1xufTtcblxuZXhwb3J0IHR5cGUgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgRGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xuICBldmVudDogT2JzZXJ2YWJsZURPTVJlbW90ZUV2ZW50O1xufTtcblxuZXhwb3J0IHR5cGUgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID1cbiAgfCBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZTtcblxudHlwZSBET01NZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRE9NX01FU1NBR0VfVFlQRTtcbiAgbWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9IERPTU1lc3NhZ2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1lc3NhZ2VUb09ic2VydmFibGVET01JbnN0YW5jZShcbiAgbWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBpbnN0YW5jZTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbikge1xuICBpZiAobWVzc2FnZS50eXBlID09PSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuYWRkQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkLCBtZXNzYWdlLmNvbm5lY3Rpb25Ub2tlbik7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UucmVtb3ZlQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQobWVzc2FnZS5jb25uZWN0aW9uSWQsIG1lc3NhZ2UuZXZlbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2YWJsZURPTUludGVyZmFjZVRvTWVzc2FnZVNlbmRlcihcbiAgc2VuZGVyOiAobWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB2b2lkLFxuICBkaXNwb3NlOiAoKSA9PiB2b2lkLFxuKSB7XG4gIGNvbnN0IHJlbW90ZU9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UgPSB7XG4gICAgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCBjb25uZWN0aW9uVG9rZW46IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgY29ubmVjdGlvblRva2VuLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgICAgcmVtb3RlRXZlbnQ6IE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgICApOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICAgIGV2ZW50OiByZW1vdGVFdmVudCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgIGRpc3Bvc2UoKTtcbiAgICB9LFxuICAgIHJlbW92ZUNvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbiAgcmV0dXJuIHJlbW90ZU9ic2VydmFibGVET007XG59XG4iLCAiaW1wb3J0IHsgRE9NUnVubmVyRmFjdG9yeSwgRE9NUnVubmVySW50ZXJmYWNlLCBET01SdW5uZXJNZXNzYWdlIH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb21cIjtcbmltcG9ydCB7IE9ic2VydmFibGVET01SZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tLWNvbW1vblwiO1xuXG5leHBvcnQgY29uc3QgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChtdXRhdGlvbkxpc3Q6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQsXG4pOiBET01SdW5uZXJJbnRlcmZhY2UgPT4ge1xuICByZXR1cm4gbmV3IFdlYkJyb3dzZXJET01SdW5uZXIocGFyYW1zLCBjYWxsYmFjayk7XG59O1xuXG5sZXQgZG9jdW1lbnRMb2FkVGltZSA9IERhdGUubm93KCk7XG5pZiAoZG9jdW1lbnQudGltZWxpbmUgJiYgZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUpIHtcbiAgZG9jdW1lbnRMb2FkVGltZSA9IERhdGUubm93KCkgLSAoZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUgYXMgbnVtYmVyKTtcbn1cblxuLyoqXG4gKiBXZWJCcm93c2VyRE9NUnVubmVyIGlzIGEgRE9NUnVubmVySW50ZXJmYWNlIGltcGxlbWVudGF0aW9uIHRoYXQgcnVucyBpbiBhIHdlYiBicm93c2VyLiBJdCBpcyBpbnRlbmRlZCB0byBiZSBydW4gaW5cbiAqIGFuIGlmcmFtZSBhbmQgdGhlIHBhcmVudCB3aW5kb3cgaXMgZXhwZWN0ZWQgdG8gc2VuZCBtZXNzYWdlcyB0byBpdCB0byBkaXNwYXRjaCBldmVudHMgYW5kIHRvIHJlY2VpdmUgbXV0YXRpb25cbiAqIG1lc3NhZ2VzLlxuICpcbiAqIEl0IGlzIGV4cGVjdGVkIHRoYXQgdGhlIGRvY3VtZW50IGNvbnRlbnRzIGlzIGluamVjdGVkIGltbWVkaWF0ZWx5IGFmdGVyIHRoaXMgY2xhc3MgaXMgaW5zdGFudGlhdGVkLlxuICovXG5leHBvcnQgY2xhc3MgV2ViQnJvd3NlckRPTVJ1bm5lciBpbXBsZW1lbnRzIERPTVJ1bm5lckludGVyZmFjZSB7XG4gIHByaXZhdGUgbXV0YXRpb25PYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlcjtcbiAgcHJpdmF0ZSBjYWxsYmFjazogKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IocGFyYW1zOiBvYmplY3QsIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCkge1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIC8vIEZvcndhcmQgY29uc29sZSBtZXNzYWdlc1xuICAgIGZvciAoY29uc3QgbGV2ZWwgb2YgW1wiZXJyb3JcIiwgXCJ3YXJuXCIsIFwiaW5mb1wiLCBcImxvZ1wiXSBhcyBjb25zdCkge1xuICAgICAgY29uc3QgZGVmYXVsdEZuID0gd2luZG93LmNvbnNvbGVbbGV2ZWxdO1xuXG4gICAgICB3aW5kb3cuY29uc29sZVtsZXZlbF0gPSAoLi4uYXJncykgPT4ge1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgICAgbGV2ZWwsXG4gICAgICAgICAgICBjb250ZW50OiBhcmdzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBkZWZhdWx0Rm4oLi4uYXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZvcndhcmQgdW5jYXVnaHQgZXJyb3JzXG4gICAgd2luZG93Lm9uZXJyb3IgPSAobWVzc2FnZSwgc291cmNlLCBsaW5lLCBjb2x1bW4sIGVycm9yKSA9PiB7XG4gICAgICBjYWxsYmFjayh7XG4gICAgICAgIGxvZ01lc3NhZ2U6IHtcbiAgICAgICAgICBsZXZlbDogXCJzeXN0ZW1cIixcbiAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgIHR5cGU6IGVycm9yPy5uYW1lLFxuICAgICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgICBjb2x1bW4sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgbGV0IGRpZFNlbmRMb2FkID0gZmFsc2U7XG5cbiAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIgPSBuZXcgd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9uTGlzdCkgPT4ge1xuICAgICAgaWYgKCFkb2N1bWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWRpZFNlbmRMb2FkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk11dGF0aW9uT2JzZXJ2ZXIgY2FsbGVkIGJlZm9yZSBsb2FkXCIpO1xuICAgICAgfVxuICAgICAgdGhpcy5jYWxsYmFjayh7XG4gICAgICAgIG11dGF0aW9uTGlzdCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgKHdpbmRvdyBhcyBhbnkpLnBhcmFtcyA9IHBhcmFtcztcblxuICAgIGNvbnN0IGZpbmlzaExvYWQgPSAoKSA9PiB7XG4gICAgICBpZiAoZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmluaXNoTG9hZCBjYWxsZWQgdHdpY2VcIik7XG4gICAgICB9XG4gICAgICBkaWRTZW5kTG9hZCA9IHRydWU7XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbG9hZGVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIub2JzZXJ2ZSh3aW5kb3cuZG9jdW1lbnQsIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfTtcbiAgICBpZiAoZG9jdW1lbnQuYm9keSkge1xuICAgICAgc2V0VGltZW91dChmaW5pc2hMb2FkLCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGZpbmlzaExvYWQpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGJ1YmJsZXMgPSByZW1vdGVFdmVudC5idWJibGVzIHx8IGZhbHNlO1xuICAgIGNvbnN0IHJlbW90ZUV2ZW50T2JqZWN0ID0gbmV3IEN1c3RvbUV2ZW50KHJlbW90ZUV2ZW50Lm5hbWUsIHtcbiAgICAgIGJ1YmJsZXMsXG4gICAgICBkZXRhaWw6IHsgLi4ucmVtb3RlRXZlbnQucGFyYW1zLCBjb25uZWN0aW9uSWQgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGV2ZW50VHlwZUxvd2VyQ2FzZSA9IHJlbW90ZUV2ZW50Lm5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIFRPRE8gLSBjaGVjayBpZiB0aGVyZSBhcmUgb3RoZXIgZXZlbnRzIHRoYXQgYXV0b21hdGljYWxseSB3aXJlIHVwIHNpbWlsYXJseSB0byBjbGljay0+b25jbGljayBhbmQgYXZvaWQgdGhvc2UgdG9vXG4gICAgaWYgKGV2ZW50VHlwZUxvd2VyQ2FzZSAhPT0gXCJjbGlja1wiKSB7XG4gICAgICBjb25zdCBoYW5kbGVyQXR0cmlidXRlTmFtZSA9IFwib25cIiArIGV2ZW50VHlwZUxvd2VyQ2FzZTtcbiAgICAgIGNvbnN0IGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSA9IHJlYWxFbGVtZW50LmdldEF0dHJpYnV0ZShoYW5kbGVyQXR0cmlidXRlTmFtZSk7XG4gICAgICBpZiAoaGFuZGxlckF0dHJpYnV0ZVZhbHVlKSB7XG4gICAgICAgIC8vIFRoaXMgZXZlbnQgaXMgZGVmaW5lZCBhcyBhbiBIVE1MIGV2ZW50IGF0dHJpYnV0ZS5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBmbiA9IEZ1bmN0aW9uKFwiZXZlbnRcIiwgaGFuZGxlckF0dHJpYnV0ZVZhbHVlKTtcbiAgICAgICAgICBmbi5hcHBseShyZWFsRWxlbWVudCwgW3JlbW90ZUV2ZW50T2JqZWN0XSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgcnVubmluZyBldmVudCBoYW5kbGVyOlwiLCBlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIERpc3BhdGNoIHRoZSBldmVudCB2aWEgSmF2YVNjcmlwdC5cbiAgICByZWFsRWxlbWVudC5kaXNwYXRjaEV2ZW50KHJlbW90ZUV2ZW50T2JqZWN0KTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgLy8gVE9ETyAtIGhhbmRsZSBkaXNwb3NlXG4gIH1cblxuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudCB7XG4gICAgcmV0dXJuIGRvY3VtZW50O1xuICB9XG5cbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlciB7XG4gICAgY29uc3QgZGF0ZUJhc2VkRG9jdW1lbnRUaW1lID0gRGF0ZS5ub3coKSAtIGRvY3VtZW50TG9hZFRpbWU7XG4gICAgaWYgKGRvY3VtZW50LnRpbWVsaW5lICYmIGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lKSB7XG4gICAgICBjb25zdCB0aW1lID0gZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUgYXMgbnVtYmVyO1xuICAgICAgaWYgKGRhdGVCYXNlZERvY3VtZW50VGltZSA+IHRpbWUgKyA1MDApIHtcbiAgICAgICAgLy8gVGhlIHRpbWVsaW5lIGNhbiBiZSBcImxlZnQgYmVoaW5kXCIgaWYgdGhlIHRhYiBpcyBiYWNrZ3JvdW5kZWQgZm9yIGEgd2hpbGUsIHNvIHdlIHVzZSB0aGUgZGF0ZS1iYXNlZCB0aW1lXG4gICAgICAgIC8vIGluc3RlYWQuIElmL3doZW4gdGhlIGRvY3VtZW50IGlzIGJyb3VnaHQgYmFjayBpbnRvIHRoZSBmb3JlZ3JvdW5kLCB0aGUgdGltZWxpbmUgd2lsbCBjYXRjaCB1cC5cbiAgICAgICAgcmV0dXJuIGRhdGVCYXNlZERvY3VtZW50VGltZTtcbiAgICAgIH1cbiAgICAgIC8vIElkZWFsIGNhc2UgLSB1c2UgdGhlIGRvY3VtZW50LnRpbWVsaW5lIGFzIGl0J3Mgd2hhdCBpcyBhdmFpbGFibGUgdG8gdGhlIGRvY3VtZW50IHNjcmlwdFxuICAgICAgcmV0dXJuIHRpbWU7XG4gICAgfVxuICAgIHJldHVybiBkYXRlQmFzZWREb2N1bWVudFRpbWU7XG4gIH1cblxuICAvLyBUT0RPIC0gcmVzb2x2ZSB0eXBlcyAoV2luZG93IG5lZWRzIHRvIGV4cG9zZSBjbGFzc2VzIHN1Y2ggYXMgQ3VzdG9tRXZlbnQgYXMgcHJvcGVydGllcylcbiAgZ2V0V2luZG93KCk6IGFueSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfVxufVxuIiwgImltcG9ydCB7IE9ic2VydmFibGVET00gfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTVwiO1xuaW1wb3J0IHtcbiAgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gIERPTV9NRVNTQUdFX1RZUEUsXG4gIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5IH0gZnJvbSBcIi4vV2ViQnJvd3NlckRPTVJ1bm5lclwiO1xuXG4vKipcbiAqIFRoaXMgaXMgcnVuIGluIHRoZSBpZnJhbWUgdGhhdCB3aWxsIGV4ZWN1dGUgdGhlIGRvY3VtZW50IHNjcmlwdCB0byBzZXR1cCB0aGUgbGlzdGVuaW5nIGZvciBldmVudHMgbWVzc2FnZXMgYW5kXG4gKiBvYnNlcnZpbmcgb2YgRE9NIG11dGF0aW9uIHVzaW5nIHRoZSBXZWJCcm93c2VyRE9NUnVubmVyIGNsYXNzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJnc1N0cmluZzogc3RyaW5nKSB7XG4gIGNvbnN0IG9ic2VydmFibGVET01QYXJhbXMgPSBKU09OLnBhcnNlKGF0b2IoYXJnc1N0cmluZykpIGFzIE9ic2VydmFibGVET01QYXJhbWV0ZXJzO1xuXG4gIGNvbnN0IHNlbmRNZXNzYWdlVG9IYW5kbGVyID0gKG1lc3NhZ2U6IEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB7XG4gICAgd2luZG93LnBhcmVudC5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeShtZXNzYWdlKSwgXCIqXCIpO1xuICB9O1xuXG4gIGNvbnN0IG9ic2VydmFibGVET00gPSBuZXcgT2JzZXJ2YWJsZURPTShcbiAgICB7XG4gICAgICAuLi5vYnNlcnZhYmxlRE9NUGFyYW1zLFxuICAgICAgaHRtbENvbnRlbnRzOiBcIlwiLCAvLyBUaGlzIG11c3QgYmUgZW1wdHkgYXMgdGhlIGNvbnRlbnRzIGFyZSBhc3N1bWVkIHRvIGJlIHByb3ZpZGVkIGJ5IHRoZSBzcmNkb2NcbiAgICB9LFxuICAgIChvYnNlcnZhYmxlRE9NTWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UpID0+IHtcbiAgICAgIHNlbmRNZXNzYWdlVG9IYW5kbGVyKHtcbiAgICAgICAgdHlwZTogRE9NX01FU1NBR0VfVFlQRSxcbiAgICAgICAgbWVzc2FnZTogb2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5LFxuICApO1xuXG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCAoZSkgPT4ge1xuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoZS5kYXRhKSBhcyBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2U7XG4gICAgc3dpdGNoIChwYXJzZWQudHlwZSkge1xuICAgICAgY2FzZSBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChwYXJzZWQuY29ubmVjdGlvbklkLCBwYXJzZWQuZXZlbnQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5hZGRDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmNvbm5lY3Rpb25Ub2tlbiA/PyBudWxsKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00ucmVtb3ZlQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBwYXJzZWQpO1xuICAgIH1cbiAgfSk7XG59XG4iLCAiaW1wb3J0IHsgc2V0dXBJZnJhbWVXZWJSdW5uZXIgfSBmcm9tIFwiLi9JZnJhbWVXZWJSdW5uZXJcIjtcblxuY29uc3QgYXJncyA9ICh3aW5kb3cgYXMgYW55KS5hcmdzO1xuc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJncyk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBSU8sU0FBUywwQkFBMEIsSUFBb0Q7QUFDNUYsU0FBTztBQUFBLElBQ0wsUUFBUSxHQUFHO0FBQUEsSUFDWCxLQUFLLEdBQUc7QUFBQSxJQUNSLFlBQVksT0FBTyxPQUFPLENBQUMsR0FBRyxHQUFHLFVBQVU7QUFBQTtBQUFBLElBQzNDLFlBQVksR0FBRyxXQUFXLElBQUksQ0FBQyxVQUFVLDBCQUEwQixLQUFLLENBQUM7QUFBQSxJQUN6RSxhQUFhLEdBQUc7QUFBQSxFQUNsQjtBQUNGOzs7QUN3Q08s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\n", "import {\n FromObservableDOMInstanceMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n// @ts-expect-error - import is defined in esbuild plugin\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 this.iframe.style.opacity = \"0\";\n this.iframe.style.pointerEvents = \"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 { networkedDOMProtocolSubProtocol_v0_1 } from \"@mml-io/networked-dom-protocol\";\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(networkedDOMProtocolSubProtocol_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", "export * from \"./FakeWebsocket\";\nexport * from \"./IframeObservableDOMFactory\";\nexport * from \"./NetworkedDOMWebRunnerClient\";\nexport * from \"./RunnerIframe\";\nexport * from \"@mml-io/networked-dom-document\";\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\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 private hasMessageListener = false;\n private bufferedEvents: Array<MessageEvent> = [];\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 setTimeout(() => {\n listener.bind(this)(new Event(\"open\"));\n }, 1);\n return;\n }\n\n super.addEventListener(type, listener, options);\n\n if (type === \"message\") {\n this.hasMessageListener = true;\n const bufferedEvents = this.bufferedEvents;\n this.bufferedEvents = [];\n bufferedEvents.forEach((event) => {\n this.dispatchEvent(event);\n });\n }\n }\n\n public dispatchEvent(event: Event): boolean {\n if (event.type === \"message\") {\n if (!this.hasMessageListener) {\n // The message listener is not setup yet - buffer the event\n this.bufferedEvents.push(event as MessageEvent);\n return true;\n }\n }\n return super.dispatchEvent(event);\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", "// ../../observable-dom/src/utils.ts\nfunction virtualDOMElementToStatic(el) {\n return {\n nodeId: el.nodeId,\n tag: el.tag,\n attributes: Object.assign({}, el.attributes),\n // Copy the attributes object - shallow copy is fine as the attributes are strings\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, connectionToken) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"connected\", {\n detail: { connectionId, connectionToken }\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 if (mutationList.length > 1) {\n }\n const allMutationRecords = [];\n for (const mutation of mutationList) {\n const idsRecord = this.createMutationRecord(mutation);\n if (idsRecord) {\n allMutationRecords.push(idsRecord);\n }\n }\n if (allMutationRecords.length > 0) {\n this.callback(\n {\n mutations: allMutationRecords,\n documentTime: this.getDocumentTime()\n },\n this\n );\n }\n }\n createMutationRecord(mutation) {\n if (this.isIgnoredElement(mutation.target)) {\n return null;\n }\n if (mutation.type === \"attributes\" && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.isIgnoredAttribute(mutation.target, mutation.attributeName)) {\n return null;\n }\n const targetNode = mutation.target;\n const targetElement = this.realElementToVirtualElement.get(targetNode);\n if (!targetElement) {\n return null;\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(\"Previous sibling is not currently a child of the parent element\");\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 if (toAdd.length === 0 && removedNodeIds.length === 0) {\n return null;\n }\n const addedNodes = toAdd.map(virtualDOMElementToStatic);\n return {\n type: \"childList\",\n targetId: targetElement.nodeId,\n addedNodes,\n removedNodeIds,\n previousSiblingId: previousSiblingElement ? previousSiblingElement.nodeId : null\n };\n } else if (mutation.type === \"attributes\") {\n const attributeName = mutation.attributeName;\n if (!this.isIgnoredAttribute(targetNode, attributeName)) {\n const previousValue = targetElement.attributes[attributeName];\n const attributeValue = targetNode.getAttribute(attributeName);\n if (attributeValue === null) {\n if (previousValue === void 0) {\n return null;\n }\n delete targetElement.attributes[attributeName];\n } else {\n if (attributeValue === previousValue) {\n return null;\n }\n targetElement.attributes[attributeName] = attributeValue;\n }\n return {\n type: \"attributes\",\n targetId: targetElement.nodeId,\n attributes: {\n [attributeName]: attributeValue\n }\n };\n }\n } else if (mutation.type === \"characterData\") {\n targetElement.textContent = targetNode.textContent ? targetNode.textContent : void 0;\n return {\n type: \"characterData\",\n targetId: targetElement.nodeId,\n textContent: targetElement.textContent ? targetElement.textContent : \"\"\n };\n }\n throw new Error(\"Unknown mutation type: \" + mutation.type);\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 localNameValue = node.localName;\n const nodeNameValue = node.nodeName;\n let tag = localNameValue || nodeNameValue;\n if (tag !== \"#text\") {\n tag = tag.toUpperCase();\n }\n const virtualElement = {\n nodeId,\n tag,\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 }\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, parsed.connectionToken ?? null);\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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBPYmplY3QuYXNzaWduKHt9LCBlbC5hdHRyaWJ1dGVzKSwgLy8gQ29weSB0aGUgYXR0cmlidXRlcyBvYmplY3QgLSBzaGFsbG93IGNvcHkgaXMgZmluZSBhcyB0aGUgYXR0cmlidXRlcyBhcmUgc3RyaW5nc1xuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgU3RhdGljVmlydHVhbERPTUVsZW1lbnQsXG4gIFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJNZXNzYWdlID0ge1xuICBsb2FkZWQ/OiBib29sZWFuO1xuICBtdXRhdGlvbkxpc3Q/OiBBcnJheTxNdXRhdGlvblJlY29yZD47XG4gIGxvZ01lc3NhZ2U/OiBMb2dNZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRE9NUnVubmVySW50ZXJmYWNlID0ge1xuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudDtcbiAgZ2V0V2luZG93KCk6IFdpbmRvdyAmIHtcbiAgICBDdXN0b21FdmVudDogdHlwZW9mIEN1c3RvbUV2ZW50O1xuICAgIFRleHQ6IHR5cGVvZiBUZXh0O1xuICAgIEhUTUxTY3JpcHRFbGVtZW50OiB0eXBlb2YgSFRNTFNjcmlwdEVsZW1lbnQ7XG4gICAgQ29tbWVudDogdHlwZW9mIENvbW1lbnQ7XG4gIH07IC8vIFRPRE8gLSBEZWZpbmUgdGhpcyB3aXRob3V0IHVzaW5nIEpTRE9NIHR5cGVzXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQ7XG4gIGRpc3Bvc2UoKTogdm9pZDtcbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkLFxuKSA9PiBET01SdW5uZXJJbnRlcmZhY2U7XG5cbmV4cG9ydCB0eXBlIExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IE9taXQ8U3RhdGljVmlydHVhbERPTUVsZW1lbnQsIFwiY2hpbGROb2Rlc1wiPiAmIHtcbiAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQgfCBUZXh0O1xuICBjaGlsZE5vZGVzOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+O1xuICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGw7XG59O1xuXG4vKipcbiAqIFRoZSBPYnNlcnZhYmxlRE9NIGNsYXNzIGhhbmRsZXMgdGhlIHJ1bm5pbmcgb2YgYW4gSFRNTCBkb2N1bWVudCB1c2luZyBhIHByb3ZpZGVkIERPTVJ1bm5lckZhY3RvcnkgYW5kIGNvbnZlcnRpbmcgdGhlXG4gKiBtdXRhdGlvbnMgdGhhdCBhcmUgc3RydWN0dXJlZCBhcyByZWZlcmVuY2VzIHRvIGxpdmUgRE9NIGVsZW1lbnRzIGludG8gbWVzc2FnZXMgdGhhdCByZWZlciB0byBlbGVtZW50cyBieSBub2RlSWRzLlxuICovXG5leHBvcnQgY2xhc3MgT2JzZXJ2YWJsZURPTSBpbXBsZW1lbnRzIE9ic2VydmFibGVET01JbnRlcmZhY2Uge1xuICBwcml2YXRlIG5vZGVUb05vZGVJZCA9IG5ldyBNYXA8TGl2ZVZpcnR1YWxET01FbGVtZW50LCBudW1iZXI+KCk7XG4gIHByaXZhdGUgbm9kZUlkVG9Ob2RlID0gbmV3IE1hcDxudW1iZXIsIExpdmVWaXJ0dWFsRE9NRWxlbWVudD4oKTtcbiAgcHJpdmF0ZSByZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQgPSBuZXcgTWFwPEVsZW1lbnQgfCBUZXh0LCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgaWdub3JlVGV4dE5vZGVzID0gdHJ1ZTtcbiAgcHJpdmF0ZSBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkO1xuICBwcml2YXRlIG5leHROb2RlSWQgPSAxO1xuICBwcml2YXRlIGh0bWxQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgZG9tUnVubmVyOiBET01SdW5uZXJJbnRlcmZhY2U7XG4gIHByaXZhdGUgbG9hZGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcHJlTG9hZExvZ01lc3NhZ2VzOiBBcnJheTxMb2dNZXNzYWdlPiA9IFtdO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhcbiAgICAgICAgICAgIHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc25hcHNob3QsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yIChjb25zdCBsb2dNZXNzYWdlIG9mIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcyA9IFtdO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubXV0YXRpb25MaXN0KSB7XG4gICAgICAgICAgdGhpcy5wcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLmxvYWRlZCkge1xuICAgICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMucHVzaChkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBsb2dNZXNzYWdlOiBkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIsIGNvbm5lY3Rpb25Ub2tlbjogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImNvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQsIGNvbm5lY3Rpb25Ub2tlbiB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJkaXNjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChtdXRhdGlvbkxpc3Q6IEFycmF5PE11dGF0aW9uUmVjb3JkPik6IHZvaWQge1xuICAgIGlmIChtdXRhdGlvbkxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgLy8gVE9ETyAoaHR0cHM6Ly9naXRodWIuY29tL21tbC1pby9tbWwvaXNzdWVzLzEwMCkgLSB3YWxrIGJhY2sgdGhyb3VnaCB0aGUgcmVjb3JkcyB0byBkZXJpdmUgdGhlIGludGVybWVkaWF0ZVxuICAgICAgLy8gIHN0YXRlcyAoZS5nLiBpZiBhbiBhdHRyaWJ1dGUgaXMgbGF0ZXIgYWRkZWQgdG8gYW4gZWxlbWVudCBjcmVhdGVkIGluIGFuIGVhcmxpZXIgcmVjb3JkIHRoZW4gaXQgc2hvdWxkIG5vdFxuICAgICAgLy8gIGhhdmUgdGhhdCBhdHRyaWJ1dGUgd2hlbiB0aGUgZWxlbWVudCBpcyBhZGRlZC4gVGhpcyBpcyBpbXBvcnRhbnQgYXMgaW5jb3JyZWN0IGF0dHJpYnV0ZSBzZXRzIGNhbiBhZmZlY3RcbiAgICAgIC8vICB2aXNpYmlsaXR5IGFuZCBleHBlY3RlZCBjbGllbnQgcGVyZm9ybWFuY2UuXG4gICAgfVxuXG4gICAgY29uc3QgYWxsTXV0YXRpb25SZWNvcmRzOiBBcnJheTxTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQ+ID0gW107XG4gICAgZm9yIChjb25zdCBtdXRhdGlvbiBvZiBtdXRhdGlvbkxpc3QpIHtcbiAgICAgIGNvbnN0IGlkc1JlY29yZCA9IHRoaXMuY3JlYXRlTXV0YXRpb25SZWNvcmQobXV0YXRpb24pO1xuICAgICAgaWYgKGlkc1JlY29yZCkge1xuICAgICAgICBhbGxNdXRhdGlvblJlY29yZHMucHVzaChpZHNSZWNvcmQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChhbGxNdXRhdGlvblJlY29yZHMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAge1xuICAgICAgICAgIG11dGF0aW9uczogYWxsTXV0YXRpb25SZWNvcmRzLFxuICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgfSxcbiAgICAgICAgdGhpcyxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVNdXRhdGlvblJlY29yZChtdXRhdGlvbjogTXV0YXRpb25SZWNvcmQpOiBTdGF0aWNWaXJ0dWFsRE9NTXV0YXRpb25JZHNSZWNvcmQgfCBudWxsIHtcbiAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dCkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiICYmXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0LCBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lISlcbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHRhcmdldE5vZGUgPSBtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgY29uc3QgdGFyZ2V0RWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldCh0YXJnZXROb2RlKTtcbiAgICBpZiAoIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgIC8vIFRoaXMgY2FuIGhhcHBlbiBpZiB0aGUgdGFyZ2V0IGVsZW1lbnQgZm9yIHRoaXMgbXV0YXRpb24gaGFzIGJlZW4gcmVtb3ZlZCBpbiBhIHByZXZpb3VzIG11dGF0aW9uXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBsZXQgcHJldmlvdXNTaWJsaW5nRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGluc2VydGlvbkluZGV4ID0gMDtcbiAgICBjb25zdCB0b0FkZDogQXJyYXk8TGl2ZVZpcnR1YWxET01FbGVtZW50PiA9IFtdO1xuICAgIGNvbnN0IHJlbW92ZWROb2RlSWRzOiBBcnJheTxudW1iZXI+ID0gW107XG5cbiAgICBpZiAobXV0YXRpb24udHlwZSA9PT0gXCJjaGlsZExpc3RcIikge1xuICAgICAgbXV0YXRpb24ucmVtb3ZlZE5vZGVzLmZvckVhY2goKG5vZGU6IE5vZGUpID0+IHtcbiAgICAgICAgY29uc3QgYXNFbGVtZW50T3JUZXh0ID0gbm9kZSBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICAgICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChhc0VsZW1lbnRPclRleHQpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoaWxkRE9NRWxlbWVudCA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChhc0VsZW1lbnRPclRleHQpO1xuICAgICAgICBpZiAoIWNoaWxkRE9NRWxlbWVudCkge1xuICAgICAgICAgIC8qXG4gICAgICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZiBlbGVtZW50IHdhcyBhIGNoaWxkIG9mIGEgcGFyZW50IGVsZW1lbnQsIGJ1dCB3YXMgbW92ZWQgdG8gYSBuZXcgcGFyZW50IGluIHRoZSBzYW1lIGJhdGNoIG9mIG11dGF0aW9ucy5cbiAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgKi9cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgaW5kZXggPSB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZihjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgIFRoaXMgY2FuIGhhcHBlbiBpZiBlbGVtZW50IHdhcyBhIGNoaWxkIG9mIGEgcGFyZW50IGVsZW1lbnQsIGJ1dCB3YXMgbW92ZWQgdG8gYSBuZXcgcGFyZW50IGluIHRoZSBzYW1lIGJhdGNoIG9mIG11dGF0aW9ucy5cbiAgICAgICAgICAgV2UgY2FuIGlnbm9yZSB0aGlzIHJlbW92YWwgYXMgdGhlIGVsZW1lbnQgd2lsbCBiZSBpbiB0aGUgY29ycmVjdCBwbGFjZSBpbiB0aGUgaGllcmFyY2h5IGFscmVhZHkuXG4gICAgICAgICAgKi9cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZERPTUVsZW1lbnQpO1xuICAgICAgICAgICAgcmVtb3ZlZE5vZGVJZHMucHVzaChjaGlsZERPTUVsZW1lbnQubm9kZUlkKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbW92YWwgPSB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIGlmIChyZW1vdmFsLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZW1vdmFsIGxlbmd0aCBub3QgMVwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChyZW1vdmFsWzBdLm5vZGVJZCAhPT0gY2hpbGRET01FbGVtZW50Lm5vZGVJZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbm9kZSBpZCBtaXNtYXRjaFwiKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIG11dGF0aW9uLmFkZGVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAoYXNFbGVtZW50T3JUZXh0LnBhcmVudE5vZGUgIT09IHRhcmdldE5vZGUpIHtcbiAgICAgICAgICAvLyBJZ25vcmUgdGhpcyBhZGRpdGlvbiAtIGl0IGlzIGxpa2VseSBvdmVycmlkZGVuIGJ5IGFuIGVhcmxpZXIgYWRkaXRpb24gb2YgdGhpcyBlbGVtZW50IHRvIGl0cyBldmVudHVhbCBub2RlIGluIHRoaXMgbXV0YXRpb24gYmF0Y2hcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIXByZXZpb3VzU2libGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgRWl0aGVyIHRoZXJlIGlzIG5vIHByZXZpb3VzIGVsZW1lbnQgKHRoaXMgaXMgdGhlIGZpcnN0IGVsZW1lbnQpXG4gICAgICAgICAgICAgb3IgdGhlIHByZXZpb3VzIGVsZW1lbnQgaGFzIG5vdCB5ZXQgYmVlbiBkZXRlcm1pbmVkLlxuXG4gICAgICAgICAgICAgVXNlIHRoZSBjdXJyZW50IHByZXZpb3VzIHNpYmxpbmcgb2YgdGhpcyBhZGRlZCBub2RlIGFzIHRoZSBmaXJzdFxuICAgICAgICAgICAgIGNob2ljZSBmb3IgdGhlIHByZXZpb3VzIHNpYmxpbmcsIGJ1dCBvbmx5IHVzZSBwcmV2aW91cyBzaWJsaW5nc1xuICAgICAgICAgICAgIHRoYXQgYXJlIG5vdCBpZ25vcmVkIChhcmUgdHJhY2tlZCBhcyB2aXJ0dWFsIGVsZW1lbnRzKS5cbiAgICAgICAgICAgICovXG4gICAgICAgICAgICBsZXQgZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nOiBFbGVtZW50IHwgVGV4dCB8IG51bGwgPVxuICAgICAgICAgICAgICBhc0VsZW1lbnRPclRleHQucHJldmlvdXNTaWJsaW5nIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICAgICAgbGV0IHZpcnR1YWxQcmV2aW91c1NpYmxpbmc6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHdoaWxlIChmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgJiYgIXZpcnR1YWxQcmV2aW91c1NpYmxpbmcpIHtcbiAgICAgICAgICAgICAgdmlydHVhbFByZXZpb3VzU2libGluZyA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChcbiAgICAgICAgICAgICAgICBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nICYmXG4gICAgICAgICAgICAgICAgdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YodmlydHVhbFByZXZpb3VzU2libGluZykgPT09IC0xXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgZWxlbWVudCBpcyBub3QgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnQgLSBpdCBpcyBub3QgYSB2YWxpZCBwcmV2aW91cyBzaWJsaW5nXG4gICAgICAgICAgICAgICAgdmlydHVhbFByZXZpb3VzU2libGluZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyA9IGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZy5wcmV2aW91c1NpYmxpbmcgYXNcbiAgICAgICAgICAgICAgICB8IEVsZW1lbnRcbiAgICAgICAgICAgICAgICB8IFRleHRcbiAgICAgICAgICAgICAgICB8IG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgICAgICAgIHByZXZpb3VzU2libGluZ0VsZW1lbnQgPSB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nO1xuICAgICAgICAgICAgICBpbnNlcnRpb25JbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKHByZXZpb3VzU2libGluZ0VsZW1lbnQpO1xuICAgICAgICAgICAgICBpZiAoaW5zZXJ0aW9uSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUHJldmlvdXMgc2libGluZyBpcyBub3QgY3VycmVudGx5IGEgY2hpbGQgb2YgdGhlIHBhcmVudCBlbGVtZW50XCIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGluc2VydGlvbkluZGV4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGNoaWxkVmlydHVhbERPTUVsZW1lbnQgPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgICAgICAgICAgYXNFbGVtZW50T3JUZXh0LFxuICAgICAgICAgICAgdGFyZ2V0RWxlbWVudCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChjaGlsZFZpcnR1YWxET01FbGVtZW50KSB7XG4gICAgICAgICAgICB0b0FkZC5wdXNoKGNoaWxkVmlydHVhbERPTUVsZW1lbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuc3BsaWNlKGluc2VydGlvbkluZGV4LCAwLCAuLi50b0FkZCk7XG5cbiAgICAgIGlmICh0b0FkZC5sZW5ndGggPT09IDAgJiYgcmVtb3ZlZE5vZGVJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIFRoaXMgaXMgYSBuby1vcCBtdXRhdGlvblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIENvbnZlcnQgdGhlIFwicmVhbFwiIERPTSBNdXRhdGlvblJlY29yZCBpbnRvIGEgXCJ2aXJ0dWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIHRoYXQgcmVmZXJlbmNlcyB0aGUgVmlydHVhbERPTUVsZW1lbnRzXG4gICAgICAvLyBUaGlzIGlzIGRvbmUgc28gdGhhdCB0aGUgc2FtZSBwcm9jZXNzIGZvciBoYW5kbGluZyBtdXRhdGlvbnMgY2FuIGJlIHVzZWQgZm9yIGJvdGggY2hhbmdlcyB0byBhIGxpdmUgRE9NIGFuZCBhbHNvXG4gICAgICAvLyB0byBkaWZmcyBiZXR3ZWVuIERPTSBzbmFwc2hvdHMgd2hlbiByZWxvYWRpbmdcbiAgICAgIGNvbnN0IGFkZGVkTm9kZXM6IEFycmF5PFN0YXRpY1ZpcnR1YWxET01FbGVtZW50PiA9IHRvQWRkLm1hcCh2aXJ0dWFsRE9NRWxlbWVudFRvU3RhdGljKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiY2hpbGRMaXN0XCIsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgYWRkZWROb2RlcyxcbiAgICAgICAgcmVtb3ZlZE5vZGVJZHMsXG4gICAgICAgIHByZXZpb3VzU2libGluZ0lkOiBwcmV2aW91c1NpYmxpbmdFbGVtZW50XG4gICAgICAgICAgPyAocHJldmlvdXNTaWJsaW5nRWxlbWVudCBhcyBMaXZlVmlydHVhbERPTUVsZW1lbnQpLm5vZGVJZFxuICAgICAgICAgIDogbnVsbCxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZU5hbWUgPSBtdXRhdGlvbi5hdHRyaWJ1dGVOYW1lITtcbiAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUodGFyZ2V0Tm9kZSwgYXR0cmlidXRlTmFtZSkpIHtcbiAgICAgICAgY29uc3QgcHJldmlvdXNWYWx1ZSA9IHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXTtcbiAgICAgICAgY29uc3QgYXR0cmlidXRlVmFsdWUgPSAodGFyZ2V0Tm9kZSBhcyBFbGVtZW50KS5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSk7XG4gICAgICAgIGlmIChhdHRyaWJ1dGVWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBuby1vcCBtdXRhdGlvblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGRlbGV0ZSB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIGEgbm8tb3AgbXV0YXRpb25cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0YXJnZXRFbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0gPSBhdHRyaWJ1dGVWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IFwiYXR0cmlidXRlc1wiLFxuICAgICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICBbYXR0cmlidXRlTmFtZV06IGF0dHJpYnV0ZVZhbHVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChtdXRhdGlvbi50eXBlID09PSBcImNoYXJhY3RlckRhdGFcIikge1xuICAgICAgdGFyZ2V0RWxlbWVudC50ZXh0Q29udGVudCA9IHRhcmdldE5vZGUudGV4dENvbnRlbnQgPyB0YXJnZXROb2RlLnRleHRDb250ZW50IDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJjaGFyYWN0ZXJEYXRhXCIsXG4gICAgICAgIHRhcmdldElkOiB0YXJnZXRFbGVtZW50Lm5vZGVJZCxcbiAgICAgICAgdGV4dENvbnRlbnQ6IHRhcmdldEVsZW1lbnQudGV4dENvbnRlbnQgPyB0YXJnZXRFbGVtZW50LnRleHRDb250ZW50IDogXCJcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBtdXRhdGlvbiB0eXBlOiBcIiArIG11dGF0aW9uLnR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW1vdmVWaXJ0dWFsRE9NRWxlbWVudCh2aXJ0dWFsRE9NRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50Lm5vZGVJZCk7XG4gICAgdGhpcy5ub2RlVG9Ob2RlSWQuZGVsZXRlKHZpcnR1YWxET01FbGVtZW50KTtcbiAgICB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQucmVhbEVsZW1lbnQpO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdmlydHVhbERPTUVsZW1lbnQuY2hpbGROb2Rlcykge1xuICAgICAgdGhpcy5yZW1vdmVWaXJ0dWFsRE9NRWxlbWVudChjaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwge1xuICAgIGNvbnN0IFt2aXJ0dWFsRWxlbWVudCwgZXhpc3RpbmddID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChub2RlLCBwYXJlbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkID0gKG5vZGUgYXMgRWxlbWVudCkuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgY2hpbGQgYXMgRWxlbWVudCB8IFRleHQsXG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjaGlsZFZpcnR1YWxFbGVtZW50KSB7XG4gICAgICAgICAgdmlydHVhbEVsZW1lbnQuY2hpbGROb2Rlcy5wdXNoKGNoaWxkVmlydHVhbEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpcnR1YWxFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWaXJ0dWFsRE9NRWxlbWVudChcbiAgICBub2RlOiBFbGVtZW50IHwgVGV4dCxcbiAgICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsXG4gICk6IFtMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsLCBib29sZWFuXSB7XG4gICAgaWYgKHRoaXMuaXNJZ25vcmVkRWxlbWVudChub2RlKSkge1xuICAgICAgcmV0dXJuIFtudWxsLCBmYWxzZV07XG4gICAgfVxuICAgIGlmICghbm9kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGFzc2lnbiBub2RlIGlkIHRvIG51bGxcIik7XG4gICAgfVxuXG4gICAgY29uc3QgZXhpc3RpbmdWYWx1ZSA9IHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmdldChub2RlKTtcbiAgICBpZiAoZXhpc3RpbmdWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvKlxuICAgICAgIFRoaXMgaXMgdW5kZXNpcmFibGUsIGJ1dCB0aGUgYmF0Y2hpbmcgb2YgbXV0YXRpb25zIGZyb20gTXV0YXRpb25PYnNlcnZlciBtZWFucyB0aGF0XG4gICAgICAgdGhpcyBub2RlIGNvdWxkIGJlIGJlaW5nIGFkZGVkIGluIGEgbXV0YXRpb24gYWZ0ZXIgYSBtdXRhdGlvbiBvZiBhIHBhcmVudCB0aGF0IHdoZW5cbiAgICAgICBoYW5kbGVkIHJlc3VsdGluZyBpbiBhZGRpbmcgdGhpcyBub2RlIGVhcmx5LlxuICAgICAgKi9cbiAgICAgIHJldHVybiBbZXhpc3RpbmdWYWx1ZSwgdHJ1ZV07XG4gICAgfVxuXG4gICAgY29uc3QgYXR0cmlidXRlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGlmICgobm9kZSBhcyBhbnkpLmF0dHJpYnV0ZXMpIHtcbiAgICAgIGNvbnN0IGFzSFRNTEVsZW1lbnQgPSBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGVOYW1lcygpKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXNIVE1MRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTnVsbCBhdHRyaWJ1dGUgdmFsdWUgZm9yIGtleTogXCIgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc0lnbm9yZWRBdHRyaWJ1dGUobm9kZSwga2V5KSkge1xuICAgICAgICAgIGF0dHJpYnV0ZXNba2V5XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZUlkID0gdGhpcy5uZXh0Tm9kZUlkKys7XG4gICAgY29uc3QgbG9jYWxOYW1lVmFsdWUgPSAobm9kZSBhcyBFbGVtZW50KS5sb2NhbE5hbWU7XG4gICAgY29uc3Qgbm9kZU5hbWVWYWx1ZSA9IG5vZGUubm9kZU5hbWU7XG4gICAgbGV0IHRhZyA9IGxvY2FsTmFtZVZhbHVlIHx8IG5vZGVOYW1lVmFsdWU7XG4gICAgaWYgKHRhZyAhPT0gXCIjdGV4dFwiKSB7XG4gICAgICB0YWcgPSB0YWcudG9VcHBlckNhc2UoKTtcbiAgICB9XG5cbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50ID0ge1xuICAgICAgbm9kZUlkLFxuICAgICAgdGFnLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIGNoaWxkTm9kZXM6IFtdLFxuICAgICAgcmVhbEVsZW1lbnQ6IG5vZGUsXG4gICAgICBwYXJlbnQsXG4gICAgfTtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLlRleHQgJiYgbm9kZS50ZXh0Q29udGVudCkge1xuICAgICAgdmlydHVhbEVsZW1lbnQudGV4dENvbnRlbnQgPSBub2RlLnRleHRDb250ZW50O1xuICAgIH1cbiAgICB0aGlzLm5vZGVUb05vZGVJZC5zZXQodmlydHVhbEVsZW1lbnQsIG5vZGVJZCk7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuc2V0KG5vZGVJZCwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LnNldChub2RlLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgcmV0dXJuIFt2aXJ0dWFsRWxlbWVudCwgZmFsc2VdO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHtcbiAgT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbn0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgY29ubmVjdGlvblRva2VuOiBzdHJpbmcgfCBudWxsO1xufTtcblxuZXhwb3J0IHR5cGUgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgRGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWRNZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEU7XG4gIGNvbm5lY3Rpb25JZDogbnVtYmVyO1xuICBldmVudDogT2JzZXJ2YWJsZURPTVJlbW90ZUV2ZW50O1xufTtcblxuZXhwb3J0IHR5cGUgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlID1cbiAgfCBBZGRDb25uZWN0ZWRVc2VySWRNZXNzYWdlXG4gIHwgUmVtb3ZlQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZTtcblxudHlwZSBET01NZXNzYWdlID0ge1xuICB0eXBlOiB0eXBlb2YgRE9NX01FU1NBR0VfVFlQRTtcbiAgbWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2U7XG59O1xuXG5leHBvcnQgdHlwZSBGcm9tT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9IERPTU1lc3NhZ2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseU1lc3NhZ2VUb09ic2VydmFibGVET01JbnN0YW5jZShcbiAgbWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBpbnN0YW5jZTogT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbikge1xuICBpZiAobWVzc2FnZS50eXBlID09PSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuYWRkQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkLCBtZXNzYWdlLmNvbm5lY3Rpb25Ub2tlbik7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UucmVtb3ZlQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQobWVzc2FnZS5jb25uZWN0aW9uSWQsIG1lc3NhZ2UuZXZlbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2YWJsZURPTUludGVyZmFjZVRvTWVzc2FnZVNlbmRlcihcbiAgc2VuZGVyOiAobWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB2b2lkLFxuICBkaXNwb3NlOiAoKSA9PiB2b2lkLFxuKSB7XG4gIGNvbnN0IHJlbW90ZU9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UgPSB7XG4gICAgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyLCBjb25uZWN0aW9uVG9rZW46IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IEFERF9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgY29ubmVjdGlvblRva2VuLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgICAgcmVtb3RlRXZlbnQ6IE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgICApOiB2b2lkIHtcbiAgICAgIHNlbmRlcih7XG4gICAgICAgIHR5cGU6IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICAgIGV2ZW50OiByZW1vdGVFdmVudCxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAgIGRpc3Bvc2UoKTtcbiAgICB9LFxuICAgIHJlbW92ZUNvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgICAgICAgY29ubmVjdGlvbklkLFxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbiAgcmV0dXJuIHJlbW90ZU9ic2VydmFibGVET007XG59XG4iLCAiaW1wb3J0IHsgRE9NUnVubmVyRmFjdG9yeSwgRE9NUnVubmVySW50ZXJmYWNlLCBET01SdW5uZXJNZXNzYWdlIH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb21cIjtcbmltcG9ydCB7IE9ic2VydmFibGVET01SZW1vdGVFdmVudCB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tLWNvbW1vblwiO1xuXG5leHBvcnQgY29uc3QgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3Rvcnk6IERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChtdXRhdGlvbkxpc3Q6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQsXG4pOiBET01SdW5uZXJJbnRlcmZhY2UgPT4ge1xuICByZXR1cm4gbmV3IFdlYkJyb3dzZXJET01SdW5uZXIocGFyYW1zLCBjYWxsYmFjayk7XG59O1xuXG5sZXQgZG9jdW1lbnRMb2FkVGltZSA9IERhdGUubm93KCk7XG5pZiAoZG9jdW1lbnQudGltZWxpbmUgJiYgZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUpIHtcbiAgZG9jdW1lbnRMb2FkVGltZSA9IERhdGUubm93KCkgLSAoZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUgYXMgbnVtYmVyKTtcbn1cblxuLyoqXG4gKiBXZWJCcm93c2VyRE9NUnVubmVyIGlzIGEgRE9NUnVubmVySW50ZXJmYWNlIGltcGxlbWVudGF0aW9uIHRoYXQgcnVucyBpbiBhIHdlYiBicm93c2VyLiBJdCBpcyBpbnRlbmRlZCB0byBiZSBydW4gaW5cbiAqIGFuIGlmcmFtZSBhbmQgdGhlIHBhcmVudCB3aW5kb3cgaXMgZXhwZWN0ZWQgdG8gc2VuZCBtZXNzYWdlcyB0byBpdCB0byBkaXNwYXRjaCBldmVudHMgYW5kIHRvIHJlY2VpdmUgbXV0YXRpb25cbiAqIG1lc3NhZ2VzLlxuICpcbiAqIEl0IGlzIGV4cGVjdGVkIHRoYXQgdGhlIGRvY3VtZW50IGNvbnRlbnRzIGlzIGluamVjdGVkIGltbWVkaWF0ZWx5IGFmdGVyIHRoaXMgY2xhc3MgaXMgaW5zdGFudGlhdGVkLlxuICovXG5leHBvcnQgY2xhc3MgV2ViQnJvd3NlckRPTVJ1bm5lciBpbXBsZW1lbnRzIERPTVJ1bm5lckludGVyZmFjZSB7XG4gIHByaXZhdGUgbXV0YXRpb25PYnNlcnZlcjogTXV0YXRpb25PYnNlcnZlcjtcbiAgcHJpdmF0ZSBjYWxsYmFjazogKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IocGFyYW1zOiBvYmplY3QsIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCkge1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIC8vIEZvcndhcmQgY29uc29sZSBtZXNzYWdlc1xuICAgIGZvciAoY29uc3QgbGV2ZWwgb2YgW1wiZXJyb3JcIiwgXCJ3YXJuXCIsIFwiaW5mb1wiLCBcImxvZ1wiXSBhcyBjb25zdCkge1xuICAgICAgY29uc3QgZGVmYXVsdEZuID0gd2luZG93LmNvbnNvbGVbbGV2ZWxdO1xuXG4gICAgICB3aW5kb3cuY29uc29sZVtsZXZlbF0gPSAoLi4uYXJncykgPT4ge1xuICAgICAgICBjYWxsYmFjayh7XG4gICAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgICAgbGV2ZWwsXG4gICAgICAgICAgICBjb250ZW50OiBhcmdzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBkZWZhdWx0Rm4oLi4uYXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZvcndhcmQgdW5jYXVnaHQgZXJyb3JzXG4gICAgd2luZG93Lm9uZXJyb3IgPSAobWVzc2FnZSwgc291cmNlLCBsaW5lLCBjb2x1bW4sIGVycm9yKSA9PiB7XG4gICAgICBjYWxsYmFjayh7XG4gICAgICAgIGxvZ01lc3NhZ2U6IHtcbiAgICAgICAgICBsZXZlbDogXCJzeXN0ZW1cIixcbiAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgIHR5cGU6IGVycm9yPy5uYW1lLFxuICAgICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgICBjb2x1bW4sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuXG4gICAgbGV0IGRpZFNlbmRMb2FkID0gZmFsc2U7XG5cbiAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIgPSBuZXcgd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9uTGlzdCkgPT4ge1xuICAgICAgaWYgKCFkb2N1bWVudCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWRpZFNlbmRMb2FkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk11dGF0aW9uT2JzZXJ2ZXIgY2FsbGVkIGJlZm9yZSBsb2FkXCIpO1xuICAgICAgfVxuICAgICAgdGhpcy5jYWxsYmFjayh7XG4gICAgICAgIG11dGF0aW9uTGlzdCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgKHdpbmRvdyBhcyBhbnkpLnBhcmFtcyA9IHBhcmFtcztcblxuICAgIGNvbnN0IGZpbmlzaExvYWQgPSAoKSA9PiB7XG4gICAgICBpZiAoZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmluaXNoTG9hZCBjYWxsZWQgdHdpY2VcIik7XG4gICAgICB9XG4gICAgICBkaWRTZW5kTG9hZCA9IHRydWU7XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbG9hZGVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLm11dGF0aW9uT2JzZXJ2ZXIub2JzZXJ2ZSh3aW5kb3cuZG9jdW1lbnQsIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfTtcbiAgICBpZiAoZG9jdW1lbnQuYm9keSkge1xuICAgICAgc2V0VGltZW91dChmaW5pc2hMb2FkLCAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGZpbmlzaExvYWQpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGJ1YmJsZXMgPSByZW1vdGVFdmVudC5idWJibGVzIHx8IGZhbHNlO1xuICAgIGNvbnN0IHJlbW90ZUV2ZW50T2JqZWN0ID0gbmV3IEN1c3RvbUV2ZW50KHJlbW90ZUV2ZW50Lm5hbWUsIHtcbiAgICAgIGJ1YmJsZXMsXG4gICAgICBkZXRhaWw6IHsgLi4ucmVtb3RlRXZlbnQucGFyYW1zLCBjb25uZWN0aW9uSWQgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGV2ZW50VHlwZUxvd2VyQ2FzZSA9IHJlbW90ZUV2ZW50Lm5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIFRPRE8gLSBjaGVjayBpZiB0aGVyZSBhcmUgb3RoZXIgZXZlbnRzIHRoYXQgYXV0b21hdGljYWxseSB3aXJlIHVwIHNpbWlsYXJseSB0byBjbGljay0+b25jbGljayBhbmQgYXZvaWQgdGhvc2UgdG9vXG4gICAgaWYgKGV2ZW50VHlwZUxvd2VyQ2FzZSAhPT0gXCJjbGlja1wiKSB7XG4gICAgICBjb25zdCBoYW5kbGVyQXR0cmlidXRlTmFtZSA9IFwib25cIiArIGV2ZW50VHlwZUxvd2VyQ2FzZTtcbiAgICAgIGNvbnN0IGhhbmRsZXJBdHRyaWJ1dGVWYWx1ZSA9IHJlYWxFbGVtZW50LmdldEF0dHJpYnV0ZShoYW5kbGVyQXR0cmlidXRlTmFtZSk7XG4gICAgICBpZiAoaGFuZGxlckF0dHJpYnV0ZVZhbHVlKSB7XG4gICAgICAgIC8vIFRoaXMgZXZlbnQgaXMgZGVmaW5lZCBhcyBhbiBIVE1MIGV2ZW50IGF0dHJpYnV0ZS5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBmbiA9IEZ1bmN0aW9uKFwiZXZlbnRcIiwgaGFuZGxlckF0dHJpYnV0ZVZhbHVlKTtcbiAgICAgICAgICBmbi5hcHBseShyZWFsRWxlbWVudCwgW3JlbW90ZUV2ZW50T2JqZWN0XSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgcnVubmluZyBldmVudCBoYW5kbGVyOlwiLCBlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIERpc3BhdGNoIHRoZSBldmVudCB2aWEgSmF2YVNjcmlwdC5cbiAgICByZWFsRWxlbWVudC5kaXNwYXRjaEV2ZW50KHJlbW90ZUV2ZW50T2JqZWN0KTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgLy8gVE9ETyAtIGhhbmRsZSBkaXNwb3NlXG4gIH1cblxuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudCB7XG4gICAgcmV0dXJuIGRvY3VtZW50O1xuICB9XG5cbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlciB7XG4gICAgY29uc3QgZGF0ZUJhc2VkRG9jdW1lbnRUaW1lID0gRGF0ZS5ub3coKSAtIGRvY3VtZW50TG9hZFRpbWU7XG4gICAgaWYgKGRvY3VtZW50LnRpbWVsaW5lICYmIGRvY3VtZW50LnRpbWVsaW5lLmN1cnJlbnRUaW1lKSB7XG4gICAgICBjb25zdCB0aW1lID0gZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUgYXMgbnVtYmVyO1xuICAgICAgaWYgKGRhdGVCYXNlZERvY3VtZW50VGltZSA+IHRpbWUgKyA1MDApIHtcbiAgICAgICAgLy8gVGhlIHRpbWVsaW5lIGNhbiBiZSBcImxlZnQgYmVoaW5kXCIgaWYgdGhlIHRhYiBpcyBiYWNrZ3JvdW5kZWQgZm9yIGEgd2hpbGUsIHNvIHdlIHVzZSB0aGUgZGF0ZS1iYXNlZCB0aW1lXG4gICAgICAgIC8vIGluc3RlYWQuIElmL3doZW4gdGhlIGRvY3VtZW50IGlzIGJyb3VnaHQgYmFjayBpbnRvIHRoZSBmb3JlZ3JvdW5kLCB0aGUgdGltZWxpbmUgd2lsbCBjYXRjaCB1cC5cbiAgICAgICAgcmV0dXJuIGRhdGVCYXNlZERvY3VtZW50VGltZTtcbiAgICAgIH1cbiAgICAgIC8vIElkZWFsIGNhc2UgLSB1c2UgdGhlIGRvY3VtZW50LnRpbWVsaW5lIGFzIGl0J3Mgd2hhdCBpcyBhdmFpbGFibGUgdG8gdGhlIGRvY3VtZW50IHNjcmlwdFxuICAgICAgcmV0dXJuIHRpbWU7XG4gICAgfVxuICAgIHJldHVybiBkYXRlQmFzZWREb2N1bWVudFRpbWU7XG4gIH1cblxuICAvLyBUT0RPIC0gcmVzb2x2ZSB0eXBlcyAoV2luZG93IG5lZWRzIHRvIGV4cG9zZSBjbGFzc2VzIHN1Y2ggYXMgQ3VzdG9tRXZlbnQgYXMgcHJvcGVydGllcylcbiAgZ2V0V2luZG93KCk6IGFueSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfVxufVxuIiwgImltcG9ydCB7IE9ic2VydmFibGVET00gfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS9zcmMvT2JzZXJ2YWJsZURPTVwiO1xuaW1wb3J0IHtcbiAgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gIERPTV9NRVNTQUdFX1RZUEUsXG4gIEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEUsXG4gIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5IH0gZnJvbSBcIi4vV2ViQnJvd3NlckRPTVJ1bm5lclwiO1xuXG4vKipcbiAqIFRoaXMgaXMgcnVuIGluIHRoZSBpZnJhbWUgdGhhdCB3aWxsIGV4ZWN1dGUgdGhlIGRvY3VtZW50IHNjcmlwdCB0byBzZXR1cCB0aGUgbGlzdGVuaW5nIGZvciBldmVudHMgbWVzc2FnZXMgYW5kXG4gKiBvYnNlcnZpbmcgb2YgRE9NIG11dGF0aW9uIHVzaW5nIHRoZSBXZWJCcm93c2VyRE9NUnVubmVyIGNsYXNzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJnc1N0cmluZzogc3RyaW5nKSB7XG4gIGNvbnN0IG9ic2VydmFibGVET01QYXJhbXMgPSBKU09OLnBhcnNlKGF0b2IoYXJnc1N0cmluZykpIGFzIE9ic2VydmFibGVET01QYXJhbWV0ZXJzO1xuXG4gIGNvbnN0IHNlbmRNZXNzYWdlVG9IYW5kbGVyID0gKG1lc3NhZ2U6IEZyb21PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB7XG4gICAgd2luZG93LnBhcmVudC5wb3N0TWVzc2FnZShKU09OLnN0cmluZ2lmeShtZXNzYWdlKSwgXCIqXCIpO1xuICB9O1xuXG4gIGNvbnN0IG9ic2VydmFibGVET00gPSBuZXcgT2JzZXJ2YWJsZURPTShcbiAgICB7XG4gICAgICAuLi5vYnNlcnZhYmxlRE9NUGFyYW1zLFxuICAgICAgaHRtbENvbnRlbnRzOiBcIlwiLCAvLyBUaGlzIG11c3QgYmUgZW1wdHkgYXMgdGhlIGNvbnRlbnRzIGFyZSBhc3N1bWVkIHRvIGJlIHByb3ZpZGVkIGJ5IHRoZSBzcmNkb2NcbiAgICB9LFxuICAgIChvYnNlcnZhYmxlRE9NTWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UpID0+IHtcbiAgICAgIHNlbmRNZXNzYWdlVG9IYW5kbGVyKHtcbiAgICAgICAgdHlwZTogRE9NX01FU1NBR0VfVFlQRSxcbiAgICAgICAgbWVzc2FnZTogb2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIFdlYkJyb3dzZXJET01SdW5uZXJGYWN0b3J5LFxuICApO1xuXG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCAoZSkgPT4ge1xuICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UoZS5kYXRhKSBhcyBUb09ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2U7XG4gICAgc3dpdGNoIChwYXJzZWQudHlwZSkge1xuICAgICAgY2FzZSBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChwYXJzZWQuY29ubmVjdGlvbklkLCBwYXJzZWQuZXZlbnQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRTpcbiAgICAgICAgb2JzZXJ2YWJsZURPTS5hZGRDb25uZWN0ZWRVc2VySWQocGFyc2VkLmNvbm5lY3Rpb25JZCwgcGFyc2VkLmNvbm5lY3Rpb25Ub2tlbiA/PyBudWxsKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00ucmVtb3ZlQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBwYXJzZWQpO1xuICAgIH1cbiAgfSk7XG59XG4iLCAiaW1wb3J0IHsgc2V0dXBJZnJhbWVXZWJSdW5uZXIgfSBmcm9tIFwiLi9JZnJhbWVXZWJSdW5uZXJcIjtcblxuY29uc3QgYXJncyA9ICh3aW5kb3cgYXMgYW55KS5hcmdzO1xuc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJncyk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBSU8sU0FBUywwQkFBMEIsSUFBb0Q7QUFDNUYsU0FBTztBQUFBLElBQ0wsUUFBUSxHQUFHO0FBQUEsSUFDWCxLQUFLLEdBQUc7QUFBQSxJQUNSLFlBQVksT0FBTyxPQUFPLENBQUMsR0FBRyxHQUFHLFVBQVU7QUFBQTtBQUFBLElBQzNDLFlBQVksR0FBRyxXQUFXLElBQUksQ0FBQyxVQUFVLDBCQUEwQixLQUFLLENBQUM7QUFBQSxJQUN6RSxhQUFhLEdBQUc7QUFBQSxFQUNsQjtBQUNGOzs7QUN3Q08s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\n", "import {\n FromObservableDOMInstanceMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n// @ts-expect-error - import is defined in esbuild plugin\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 this.iframe.style.opacity = \"0\";\n this.iframe.style.pointerEvents = \"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 { networkedDOMProtocolSubProtocol_v0_1 } from \"@mml-io/networked-dom-protocol\";\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 if (\n this.connectedState.document.hasWebSocket(\n this.connectedState.fakeWebsocket.serverSideWebsocket as unknown as WebSocket,\n )\n ) {\n this.connectedState.document.removeWebSocket(\n this.connectedState.fakeWebsocket.serverSideWebsocket as unknown as WebSocket,\n );\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(networkedDOMProtocolSubProtocol_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", "export * from \"./FakeWebsocket\";\nexport * from \"./IframeObservableDOMFactory\";\nexport * from \"./NetworkedDOMWebRunnerClient\";\nexport * from \"./RunnerIframe\";\nexport * from \"@mml-io/networked-dom-document\";\n"],
|
|
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.
|
|
3
|
+
"version": "0.23.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.
|
|
24
|
-
"@mml-io/observable-dom-common": "^0.
|
|
23
|
+
"@mml-io/networked-dom-web": "^0.23.0",
|
|
24
|
+
"@mml-io/observable-dom-common": "^0.23.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": "30.0.4",
|
|
30
30
|
"jest-expect-message": "1.1.3"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "92699e8e944cc238ae856a10173095ad4bf42fad"
|
|
33
33
|
}
|