@mml-io/networked-dom-web-runner 0.19.0 → 0.19.2

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.
@@ -5,9 +5,12 @@
5
5
  declare class WebsocketEnd extends EventTarget {
6
6
  private readonly sendCallback;
7
7
  readonly protocol: string;
8
+ private hasMessageListener;
9
+ private bufferedEvents;
8
10
  constructor(protocol: string, sendCallback: (data: string | ArrayBufferLike | Blob | ArrayBufferView) => void);
9
11
  close(): void;
10
12
  addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
13
+ dispatchEvent(event: Event): boolean;
11
14
  send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
12
15
  }
13
16
  /**
package/build/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
  var WebsocketEnd = class extends EventTarget {
3
3
  constructor(protocol, sendCallback) {
4
4
  super();
5
+ this.hasMessageListener = false;
6
+ this.bufferedEvents = [];
5
7
  this.protocol = protocol;
6
8
  this.sendCallback = sendCallback;
7
9
  }
@@ -16,6 +18,23 @@ var WebsocketEnd = class extends EventTarget {
16
18
  return;
17
19
  }
18
20
  super.addEventListener(type, listener, options);
21
+ if (type === "message") {
22
+ this.hasMessageListener = true;
23
+ const bufferedEvents = this.bufferedEvents;
24
+ this.bufferedEvents = [];
25
+ bufferedEvents.forEach((event) => {
26
+ this.dispatchEvent(event);
27
+ });
28
+ }
29
+ }
30
+ dispatchEvent(event) {
31
+ if (event.type === "message") {
32
+ if (!this.hasMessageListener) {
33
+ this.bufferedEvents.push(event);
34
+ return true;
35
+ }
36
+ }
37
+ return super.dispatchEvent(event);
19
38
  }
20
39
  send(data) {
21
40
  this.sendCallback(data);
@@ -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\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 super.addEventListener(type, listener, options);\n }\n\n public send(data: string | ArrayBufferLike | Blob | ArrayBufferView) {\n this.sendCallback(data);\n }\n}\n\n/**\n * FakeWebsocket is a pair of WebsocketEnds that are connected to each other. It is used to simulate a websocket\n * connection for testing or matching the interface of a real websocket connection without doing any actual networking.\n */\nexport class FakeWebsocket {\n public clientSideWebsocket: WebsocketEnd;\n public serverSideWebsocket: WebsocketEnd;\n\n constructor(protocol: string) {\n this.clientSideWebsocket = new WebsocketEnd(protocol, (data) => {\n this.serverSideWebsocket.dispatchEvent(\n new MessageEvent(\"message\", {\n data,\n }),\n );\n });\n\n this.serverSideWebsocket = new WebsocketEnd(protocol, (data) => {\n this.clientSideWebsocket.dispatchEvent(\n new MessageEvent(\"message\", {\n data,\n }),\n );\n });\n }\n}\n", "import { ObservableDOMFactory } from \"@mml-io/networked-dom-document\";\nimport {\n DOM_MESSAGE_TYPE,\n FromObservableDOMInstanceMessage,\n ObservableDOMInterface,\n observableDOMInterfaceToMessageSender,\n ObservableDOMMessage,\n ObservableDOMParameters,\n ToObservableDOMInstanceMessage,\n} from \"@mml-io/observable-dom-common\";\n\nimport { RunnerIframe } from \"./RunnerIframe\";\n\n/**\n * Creates an ObservableDOMInterface that uses an iframe to run the document.\n */\nexport const IframeObservableDOMFactory: ObservableDOMFactory = (\n observableDOMParameters: ObservableDOMParameters,\n callback: (message: ObservableDOMMessage, observableDOM: ObservableDOMInterface) => void,\n) => {\n const runnerIframe = new RunnerIframe(\n observableDOMParameters,\n (message: FromObservableDOMInstanceMessage) => {\n switch (message.type) {\n case DOM_MESSAGE_TYPE:\n callback(message.message, remoteObservableDOM);\n break;\n default:\n console.error(\"Unknown message type\", message.type);\n }\n },\n );\n\n const remoteObservableDOM: ObservableDOMInterface = observableDOMInterfaceToMessageSender(\n (message: ToObservableDOMInstanceMessage) => {\n runnerIframe.sendMessageToRunner(message);\n },\n () => {\n runnerIframe.dispose();\n },\n );\n return remoteObservableDOM;\n};\n", "// ../../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) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"connected\", {\n detail: { connectionId }\n })\n );\n }\n removeConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"disconnected\", {\n detail: { connectionId }\n })\n );\n }\n processModificationList(mutationList) {\n 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 virtualElement = {\n nodeId,\n tag: node.nodeName,\n attributes,\n childNodes: [],\n realElement: node,\n parent\n };\n if (node instanceof this.domRunner.getWindow().Text && node.textContent) {\n virtualElement.textContent = node.textContent;\n }\n this.nodeToNodeId.set(virtualElement, nodeId);\n this.nodeIdToNode.set(nodeId, virtualElement);\n this.realElementToVirtualElement.set(node, virtualElement);\n return [virtualElement, false];\n }\n getVirtualDOMElementForRealElementOrThrow(realElement) {\n const virtualElement = this.realElementToVirtualElement.get(realElement);\n if (!virtualElement) {\n throw new Error(`Virtual element not found for real element`);\n }\n return virtualElement;\n }\n isIgnoredElement(node) {\n if (this.ignoreTextNodes && node instanceof this.domRunner.getWindow().Text) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().HTMLScriptElement) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().Comment) {\n return true;\n }\n return false;\n }\n isIgnoredAttribute(node, attributeName) {\n return attributeName.startsWith(\"on\");\n }\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n const domNode = this.nodeIdToNode.get(remoteEvent.nodeId);\n if (!domNode) {\n console.error(\"Unknown node ID in remote event: \" + remoteEvent.nodeId);\n return;\n }\n if (domNode instanceof this.domRunner.getWindow().Text) {\n console.warn(\"Cannot dispatch remote event to text node\");\n return;\n }\n this.domRunner.dispatchRemoteEventFromConnectionId(\n connectionId,\n domNode.realElement,\n remoteEvent\n );\n }\n dispose() {\n clearInterval(this.documentTimeIntervalTimer);\n this.domRunner.dispose();\n }\n getDocumentTime() {\n return this.domRunner.getDocumentTime();\n }\n};\n\n// ../../observable-dom-common/build/index.js\nvar ADD_CONNECTED_USER_ID_MESSAGE_TYPE = \"addConnectedUserId\";\nvar REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE = \"removeConnectedUserId\";\nvar DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE = \"dispatchRemoteEventFromConnectionId\";\nvar DOM_MESSAGE_TYPE = \"dom\";\n\n// src/WebBrowserDOMRunner.ts\nvar WebBrowserDOMRunnerFactory = (htmlPath, htmlContents, params, callback) => {\n return new WebBrowserDOMRunner(params, callback);\n};\nvar documentLoadTime = Date.now();\nif (document.timeline && document.timeline.currentTime) {\n documentLoadTime = Date.now() - document.timeline.currentTime;\n}\nvar WebBrowserDOMRunner = class {\n constructor(params, callback) {\n this.callback = callback;\n for (const level of [\"error\", \"warn\", \"info\", \"log\"]) {\n const defaultFn = window.console[level];\n window.console[level] = (...args2) => {\n callback({\n logMessage: {\n level,\n content: args2\n }\n });\n defaultFn(...args2);\n };\n }\n window.onerror = (message, source, line, column, error) => {\n callback({\n logMessage: {\n level: \"system\",\n content: [\n {\n message,\n type: error?.name,\n line,\n column\n }\n ]\n }\n });\n return false;\n };\n let didSendLoad = false;\n this.mutationObserver = new window.MutationObserver((mutationList) => {\n if (!document) {\n return;\n }\n if (!didSendLoad) {\n throw new Error(\"MutationObserver called before load\");\n }\n this.callback({\n mutationList\n });\n });\n window.params = params;\n const finishLoad = () => {\n if (didSendLoad) {\n throw new Error(\"finishLoad called twice\");\n }\n didSendLoad = true;\n this.callback({\n loaded: true\n });\n this.mutationObserver.observe(window.document, {\n attributes: true,\n childList: true,\n subtree: true,\n characterData: true\n });\n };\n if (document.body) {\n setTimeout(finishLoad, 0);\n } else {\n window.addEventListener(\"DOMContentLoaded\", finishLoad);\n }\n }\n dispatchRemoteEventFromConnectionId(connectionId, realElement, remoteEvent) {\n const bubbles = remoteEvent.bubbles || false;\n const remoteEventObject = new CustomEvent(remoteEvent.name, {\n bubbles,\n detail: { ...remoteEvent.params, connectionId }\n });\n const eventTypeLowerCase = remoteEvent.name.toLowerCase();\n if (eventTypeLowerCase !== \"click\") {\n const handlerAttributeName = \"on\" + eventTypeLowerCase;\n const handlerAttributeValue = realElement.getAttribute(handlerAttributeName);\n if (handlerAttributeValue) {\n try {\n const fn = Function(\"event\", handlerAttributeValue);\n fn.apply(realElement, [remoteEventObject]);\n } catch (e) {\n console.error(\"Error running event handler:\", e);\n }\n }\n }\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n const dateBasedDocumentTime = Date.now() - documentLoadTime;\n if (document.timeline && document.timeline.currentTime) {\n const time = document.timeline.currentTime;\n if (dateBasedDocumentTime > time + 500) {\n return dateBasedDocumentTime;\n }\n return time;\n }\n return dateBasedDocumentTime;\n }\n // TODO - resolve types (Window needs to expose classes such as CustomEvent as properties)\n getWindow() {\n return window;\n }\n};\n\n// src/IframeWebRunner.ts\nfunction setupIframeWebRunner(argsString) {\n const observableDOMParams = JSON.parse(atob(argsString));\n const sendMessageToHandler = (message) => {\n window.parent.postMessage(JSON.stringify(message), \"*\");\n };\n const observableDOM = new ObservableDOM(\n {\n ...observableDOMParams,\n htmlContents: \"\"\n // This must be empty as the contents are assumed to be provided by the srcdoc\n },\n (observableDOMMessage) => {\n sendMessageToHandler({\n type: DOM_MESSAGE_TYPE,\n message: observableDOMMessage\n });\n },\n WebBrowserDOMRunnerFactory\n );\n window.addEventListener(\"message\", (e) => {\n const parsed = JSON.parse(e.data);\n switch (parsed.type) {\n case DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE:\n observableDOM.dispatchRemoteEventFromConnectionId(parsed.connectionId, parsed.event);\n break;\n case ADD_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.addConnectedUserId(parsed.connectionId);\n break;\n case REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.removeConnectedUserId(parsed.connectionId);\n break;\n default:\n console.error(\"Unknown message type\", parsed);\n }\n });\n}\n\n// src/index.ts\nvar args = window.args;\nsetupIframeWebRunner(args);\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBPYmplY3QuYXNzaWduKHt9LCBlbC5hdHRyaWJ1dGVzKSwgLy8gQ29weSB0aGUgYXR0cmlidXRlcyBvYmplY3QgLSBzaGFsbG93IGNvcHkgaXMgZmluZSBhcyB0aGUgYXR0cmlidXRlcyBhcmUgc3RyaW5nc1xuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgU3RhdGljVmlydHVhbERPTUVsZW1lbnQsXG4gIFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJNZXNzYWdlID0ge1xuICBsb2FkZWQ/OiBib29sZWFuO1xuICBtdXRhdGlvbkxpc3Q/OiBBcnJheTxNdXRhdGlvblJlY29yZD47XG4gIGxvZ01lc3NhZ2U/OiBMb2dNZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRE9NUnVubmVySW50ZXJmYWNlID0ge1xuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudDtcbiAgZ2V0V2luZG93KCk6IFdpbmRvdyAmIHtcbiAgICBDdXN0b21FdmVudDogdHlwZW9mIEN1c3RvbUV2ZW50O1xuICAgIFRleHQ6IHR5cGVvZiBUZXh0O1xuICAgIEhUTUxTY3JpcHRFbGVtZW50OiB0eXBlb2YgSFRNTFNjcmlwdEVsZW1lbnQ7XG4gICAgQ29tbWVudDogdHlwZW9mIENvbW1lbnQ7XG4gIH07IC8vIFRPRE8gLSBEZWZpbmUgdGhpcyB3aXRob3V0IHVzaW5nIEpTRE9NIHR5cGVzXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQ7XG4gIGRpc3Bvc2UoKTogdm9pZDtcbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkLFxuKSA9PiBET01SdW5uZXJJbnRlcmZhY2U7XG5cbmV4cG9ydCB0eXBlIExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IE9taXQ8U3RhdGljVmlydHVhbERPTUVsZW1lbnQsIFwiY2hpbGROb2Rlc1wiPiAmIHtcbiAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQgfCBUZXh0O1xuICBjaGlsZE5vZGVzOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+O1xuICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGw7XG59O1xuXG4vKipcbiAqIFRoZSBPYnNlcnZhYmxlRE9NIGNsYXNzIGhhbmRsZXMgdGhlIHJ1bm5pbmcgb2YgYW4gSFRNTCBkb2N1bWVudCB1c2luZyBhIHByb3ZpZGVkIERPTVJ1bm5lckZhY3RvcnkgYW5kIGNvbnZlcnRpbmcgdGhlXG4gKiBtdXRhdGlvbnMgdGhhdCBhcmUgc3RydWN0dXJlZCBhcyByZWZlcmVuY2VzIHRvIGxpdmUgRE9NIGVsZW1lbnRzIGludG8gbWVzc2FnZXMgdGhhdCByZWZlciB0byBlbGVtZW50cyBieSBub2RlSWRzLlxuICovXG5leHBvcnQgY2xhc3MgT2JzZXJ2YWJsZURPTSBpbXBsZW1lbnRzIE9ic2VydmFibGVET01JbnRlcmZhY2Uge1xuICBwcml2YXRlIG5vZGVUb05vZGVJZCA9IG5ldyBNYXA8TGl2ZVZpcnR1YWxET01FbGVtZW50LCBudW1iZXI+KCk7XG4gIHByaXZhdGUgbm9kZUlkVG9Ob2RlID0gbmV3IE1hcDxudW1iZXIsIExpdmVWaXJ0dWFsRE9NRWxlbWVudD4oKTtcbiAgcHJpdmF0ZSByZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQgPSBuZXcgTWFwPEVsZW1lbnQgfCBUZXh0LCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgaWdub3JlVGV4dE5vZGVzID0gdHJ1ZTtcbiAgcHJpdmF0ZSBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkO1xuICBwcml2YXRlIG5leHROb2RlSWQgPSAxO1xuICBwcml2YXRlIGh0bWxQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgZG9tUnVubmVyOiBET01SdW5uZXJJbnRlcmZhY2U7XG4gIHByaXZhdGUgbG9hZGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcHJlTG9hZExvZ01lc3NhZ2VzOiBBcnJheTxMb2dNZXNzYWdlPiA9IFtdO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhcbiAgICAgICAgICAgIHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc25hcHNob3QsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yIChjb25zdCBsb2dNZXNzYWdlIG9mIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcyA9IFtdO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubXV0YXRpb25MaXN0KSB7XG4gICAgICAgICAgdGhpcy5wcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLmxvYWRlZCkge1xuICAgICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMucHVzaChkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBsb2dNZXNzYWdlOiBkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUNvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImRpc2Nvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQgfSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NNb2RpZmljYXRpb25MaXN0KG11dGF0aW9uTGlzdDogQXJyYXk8TXV0YXRpb25SZWNvcmQ+KTogdm9pZCB7XG4gICAgaWYgKG11dGF0aW9uTGlzdC5sZW5ndGggPiAxKSB7XG4gICAgICAvLyBUT0RPIChodHRwczovL2dpdGh1Yi5jb20vbW1sLWlvL21tbC9pc3N1ZXMvMTAwKSAtIHdhbGsgYmFjayB0aHJvdWdoIHRoZSByZWNvcmRzIHRvIGRlcml2ZSB0aGUgaW50ZXJtZWRpYXRlXG4gICAgICAvLyAgc3RhdGVzIChlLmcuIGlmIGFuIGF0dHJpYnV0ZSBpcyBsYXRlciBhZGRlZCB0byBhbiBlbGVtZW50IGNyZWF0ZWQgaW4gYW4gZWFybGllciByZWNvcmQgdGhlbiBpdCBzaG91bGQgbm90XG4gICAgICAvLyAgaGF2ZSB0aGF0IGF0dHJpYnV0ZSB3aGVuIHRoZSBlbGVtZW50IGlzIGFkZGVkLiBUaGlzIGlzIGltcG9ydGFudCBhcyBpbmNvcnJlY3QgYXR0cmlidXRlIHNldHMgY2FuIGFmZmVjdFxuICAgICAgLy8gIHZpc2liaWxpdHkgYW5kIGV4cGVjdGVkIGNsaWVudCBwZXJmb3JtYW5jZS5cbiAgICB9XG5cbiAgICBjb25zdCBhbGxNdXRhdGlvblJlY29yZHM6IEFycmF5PFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZD4gPSBbXTtcbiAgICBmb3IgKGNvbnN0IG11dGF0aW9uIG9mIG11dGF0aW9uTGlzdCkge1xuICAgICAgY29uc3QgaWRzUmVjb3JkID0gdGhpcy5jcmVhdGVNdXRhdGlvblJlY29yZChtdXRhdGlvbik7XG4gICAgICBpZiAoaWRzUmVjb3JkKSB7XG4gICAgICAgIGFsbE11dGF0aW9uUmVjb3Jkcy5wdXNoKGlkc1JlY29yZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGFsbE11dGF0aW9uUmVjb3Jkcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICB7XG4gICAgICAgICAgbXV0YXRpb25zOiBhbGxNdXRhdGlvblJlY29yZHMsXG4gICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU11dGF0aW9uUmVjb3JkKG11dGF0aW9uOiBNdXRhdGlvblJlY29yZCk6IFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCB8IG51bGwge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgbXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIgJiZcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICB0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQsIG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhKVxuICAgICkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0Tm9kZSA9IG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KHRhcmdldE5vZGUpO1xuICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZSB0YXJnZXQgZWxlbWVudCBmb3IgdGhpcyBtdXRhdGlvbiBoYXMgYmVlbiByZW1vdmVkIGluIGEgcHJldmlvdXMgbXV0YXRpb25cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCBwcmV2aW91c1NpYmxpbmdFbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgICBsZXQgaW5zZXJ0aW9uSW5kZXggPSAwO1xuICAgIGNvbnN0IHRvQWRkOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+ID0gW107XG4gICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcblxuICAgIGlmIChtdXRhdGlvbi50eXBlID09PSBcImNoaWxkTGlzdFwiKSB7XG4gICAgICBtdXRhdGlvbi5yZW1vdmVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KGFzRWxlbWVudE9yVGV4dCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hpbGRET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KGFzRWxlbWVudE9yVGV4dCk7XG4gICAgICAgIGlmICghY2hpbGRET01FbGVtZW50KSB7XG4gICAgICAgICAgLypcbiAgICAgICAgICAgVGhpcyBjYW4gaGFwcGVuIGlmIGVsZW1lbnQgd2FzIGEgY2hpbGQgb2YgYSBwYXJlbnQgZWxlbWVudCwgYnV0IHdhcyBtb3ZlZCB0byBhIG5ldyBwYXJlbnQgaW4gdGhlIHNhbWUgYmF0Y2ggb2YgbXV0YXRpb25zLlxuICAgICAgICAgICBXZSBjYW4gaWdub3JlIHRoaXMgcmVtb3ZhbCBhcyB0aGUgZWxlbWVudCB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IHBsYWNlIGluIHRoZSBoaWVyYXJjaHkgYWxyZWFkeS5cbiAgICAgICAgICAqL1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBpbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgVGhpcyBjYW4gaGFwcGVuIGlmIGVsZW1lbnQgd2FzIGEgY2hpbGQgb2YgYSBwYXJlbnQgZWxlbWVudCwgYnV0IHdhcyBtb3ZlZCB0byBhIG5ldyBwYXJlbnQgaW4gdGhlIHNhbWUgYmF0Y2ggb2YgbXV0YXRpb25zLlxuICAgICAgICAgICBXZSBjYW4gaWdub3JlIHRoaXMgcmVtb3ZhbCBhcyB0aGUgZWxlbWVudCB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IHBsYWNlIGluIHRoZSBoaWVyYXJjaHkgYWxyZWFkeS5cbiAgICAgICAgICAqL1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVZpcnR1YWxET01FbGVtZW50KGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKGNoaWxkRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgICAgICAgICAgY29uc3QgcmVtb3ZhbCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgaWYgKHJlbW92YWwubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbGVuZ3RoIG5vdCAxXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKHJlbW92YWxbMF0ubm9kZUlkICE9PSBjaGlsZERPTUVsZW1lbnQubm9kZUlkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVtb3ZhbCBub2RlIGlkIG1pc21hdGNoXCIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgbXV0YXRpb24uYWRkZWROb2Rlcy5mb3JFYWNoKChub2RlOiBOb2RlKSA9PiB7XG4gICAgICAgIGNvbnN0IGFzRWxlbWVudE9yVGV4dCA9IG5vZGUgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgIGlmIChhc0VsZW1lbnRPclRleHQucGFyZW50Tm9kZSAhPT0gdGFyZ2V0Tm9kZSkge1xuICAgICAgICAgIC8vIElnbm9yZSB0aGlzIGFkZGl0aW9uIC0gaXQgaXMgbGlrZWx5IG92ZXJyaWRkZW4gYnkgYW4gZWFybGllciBhZGRpdGlvbiBvZiB0aGlzIGVsZW1lbnQgdG8gaXRzIGV2ZW50dWFsIG5vZGUgaW4gdGhpcyBtdXRhdGlvbiBiYXRjaFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghcHJldmlvdXNTaWJsaW5nRWxlbWVudCkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICBFaXRoZXIgdGhlcmUgaXMgbm8gcHJldmlvdXMgZWxlbWVudCAodGhpcyBpcyB0aGUgZmlyc3QgZWxlbWVudClcbiAgICAgICAgICAgICBvciB0aGUgcHJldmlvdXMgZWxlbWVudCBoYXMgbm90IHlldCBiZWVuIGRldGVybWluZWQuXG5cbiAgICAgICAgICAgICBVc2UgdGhlIGN1cnJlbnQgcHJldmlvdXMgc2libGluZyBvZiB0aGlzIGFkZGVkIG5vZGUgYXMgdGhlIGZpcnN0XG4gICAgICAgICAgICAgY2hvaWNlIGZvciB0aGUgcHJldmlvdXMgc2libGluZywgYnV0IG9ubHkgdXNlIHByZXZpb3VzIHNpYmxpbmdzXG4gICAgICAgICAgICAgdGhhdCBhcmUgbm90IGlnbm9yZWQgKGFyZSB0cmFja2VkIGFzIHZpcnR1YWwgZWxlbWVudHMpLlxuICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGxldCBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmc6IEVsZW1lbnQgfCBUZXh0IHwgbnVsbCA9XG4gICAgICAgICAgICAgIGFzRWxlbWVudE9yVGV4dC5wcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgICAgICBsZXQgdmlydHVhbFByZXZpb3VzU2libGluZzogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgd2hpbGUgKGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyAmJiAhdmlydHVhbFByZXZpb3VzU2libGluZykge1xuICAgICAgICAgICAgICB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KFxuICAgICAgICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHZpcnR1YWxQcmV2aW91c1NpYmxpbmcgJiZcbiAgICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZih2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSA9PT0gLTFcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBlbGVtZW50IGlzIG5vdCBhIGNoaWxkIG9mIHRoZSBwYXJlbnQgZWxlbWVudCAtIGl0IGlzIG5vdCBhIHZhbGlkIHByZXZpb3VzIHNpYmxpbmdcbiAgICAgICAgICAgICAgICB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nID0gZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nLnByZXZpb3VzU2libGluZyBhc1xuICAgICAgICAgICAgICAgIHwgRWxlbWVudFxuICAgICAgICAgICAgICAgIHwgVGV4dFxuICAgICAgICAgICAgICAgIHwgbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHZpcnR1YWxQcmV2aW91c1NpYmxpbmcpIHtcbiAgICAgICAgICAgICAgcHJldmlvdXNTaWJsaW5nRWxlbWVudCA9IHZpcnR1YWxQcmV2aW91c1NpYmxpbmc7XG4gICAgICAgICAgICAgIGluc2VydGlvbkluZGV4ID0gdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YocHJldmlvdXNTaWJsaW5nRWxlbWVudCk7XG4gICAgICAgICAgICAgIGlmIChpbnNlcnRpb25JbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcmV2aW91cyBzaWJsaW5nIGlzIG5vdCBjdXJyZW50bHkgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnRcIik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaW5zZXJ0aW9uSW5kZXggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICBhc0VsZW1lbnRPclRleHQsXG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50LFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGNoaWxkVmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRvQWRkLnB1c2goY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5zZXJ0aW9uSW5kZXgsIDAsIC4uLnRvQWRkKTtcblxuICAgICAgaWYgKHRvQWRkLmxlbmd0aCA9PT0gMCAmJiByZW1vdmVkTm9kZUlkcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgLy8gVGhpcyBpcyBhIG5vLW9wIG11dGF0aW9uXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgLy8gQ29udmVydCB0aGUgXCJyZWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIGludG8gYSBcInZpcnR1YWxcIiBET00gTXV0YXRpb25SZWNvcmQgdGhhdCByZWZlcmVuY2VzIHRoZSBWaXJ0dWFsRE9NRWxlbWVudHNcbiAgICAgIC8vIFRoaXMgaXMgZG9uZSBzbyB0aGF0IHRoZSBzYW1lIHByb2Nlc3MgZm9yIGhhbmRsaW5nIG11dGF0aW9ucyBjYW4gYmUgdXNlZCBmb3IgYm90aCBjaGFuZ2VzIHRvIGEgbGl2ZSBET00gYW5kIGFsc29cbiAgICAgIC8vIHRvIGRpZmZzIGJldHdlZW4gRE9NIHNuYXBzaG90cyB3aGVuIHJlbG9hZGluZ1xuICAgICAgY29uc3QgYWRkZWROb2RlczogQXJyYXk8U3RhdGljVmlydHVhbERPTUVsZW1lbnQ+ID0gdG9BZGQubWFwKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJjaGlsZExpc3RcIixcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICBhZGRlZE5vZGVzLFxuICAgICAgICByZW1vdmVkTm9kZUlkcyxcbiAgICAgICAgcHJldmlvdXNTaWJsaW5nSWQ6IHByZXZpb3VzU2libGluZ0VsZW1lbnRcbiAgICAgICAgICA/IChwcmV2aW91c1NpYmxpbmdFbGVtZW50IGFzIExpdmVWaXJ0dWFsRE9NRWxlbWVudCkubm9kZUlkXG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgaWYgKCF0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZSh0YXJnZXROb2RlLCBhdHRyaWJ1dGVOYW1lKSkge1xuICAgICAgICBjb25zdCBwcmV2aW91c1ZhbHVlID0gdGFyZ2V0RWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICBjb25zdCBhdHRyaWJ1dGVWYWx1ZSA9ICh0YXJnZXROb2RlIGFzIEVsZW1lbnQpLmdldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lKTtcbiAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBhIG5vLW9wIG11dGF0aW9uXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVsZXRlIHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoYXR0cmlidXRlVmFsdWUgPT09IHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBuby1vcCBtdXRhdGlvblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogXCJhdHRyaWJ1dGVzXCIsXG4gICAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgIFthdHRyaWJ1dGVOYW1lXTogYXR0cmlidXRlVmFsdWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiY2hhcmFjdGVyRGF0YVwiKSB7XG4gICAgICB0YXJnZXRFbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImNoYXJhY3RlckRhdGFcIixcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICB0ZXh0Q29udGVudDogdGFyZ2V0RWxlbWVudC50ZXh0Q29udGVudCA/IHRhcmdldEVsZW1lbnQudGV4dENvbnRlbnQgOiBcIlwiLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIG11dGF0aW9uIHR5cGU6IFwiICsgbXV0YXRpb24udHlwZSk7XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZVZpcnR1YWxET01FbGVtZW50KHZpcnR1YWxET01FbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLm5vZGVJZFRvTm9kZS5kZWxldGUodmlydHVhbERPTUVsZW1lbnQubm9kZUlkKTtcbiAgICB0aGlzLm5vZGVUb05vZGVJZC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQpO1xuICAgIHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudC5yZWFsRWxlbWVudCk7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiB2aXJ0dWFsRE9NRWxlbWVudC5jaGlsZE5vZGVzKSB7XG4gICAgICB0aGlzLnJlbW92ZVZpcnR1YWxET01FbGVtZW50KGNoaWxkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgIG5vZGU6IEVsZW1lbnQgfCBUZXh0LFxuICAgIHBhcmVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCxcbiAgKTogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCB7XG4gICAgY29uc3QgW3ZpcnR1YWxFbGVtZW50LCBleGlzdGluZ10gPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50KG5vZGUsIHBhcmVudCk7XG4gICAgaWYgKCF2aXJ0dWFsRWxlbWVudCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChleGlzdGluZykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICgobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzW2ldO1xuICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxFbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICBjaGlsZCBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgICB2aXJ0dWFsRWxlbWVudCxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNoaWxkVmlydHVhbEVsZW1lbnQpIHtcbiAgICAgICAgICB2aXJ0dWFsRWxlbWVudC5jaGlsZE5vZGVzLnB1c2goY2hpbGRWaXJ0dWFsRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdmlydHVhbEVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVZpcnR1YWxET01FbGVtZW50KFxuICAgIG5vZGU6IEVsZW1lbnQgfCBUZXh0LFxuICAgIHBhcmVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCxcbiAgKTogW0xpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsIGJvb2xlYW5dIHtcbiAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG5vZGUpKSB7XG4gICAgICByZXR1cm4gW251bGwsIGZhbHNlXTtcbiAgICB9XG4gICAgaWYgKCFub2RlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgYXNzaWduIG5vZGUgaWQgdG8gbnVsbFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KG5vZGUpO1xuICAgIGlmIChleGlzdGluZ1ZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8qXG4gICAgICAgVGhpcyBpcyB1bmRlc2lyYWJsZSwgYnV0IHRoZSBiYXRjaGluZyBvZiBtdXRhdGlvbnMgZnJvbSBNdXRhdGlvbk9ic2VydmVyIG1lYW5zIHRoYXRcbiAgICAgICB0aGlzIG5vZGUgY291bGQgYmUgYmVpbmcgYWRkZWQgaW4gYSBtdXRhdGlvbiBhZnRlciBhIG11dGF0aW9uIG9mIGEgcGFyZW50IHRoYXQgd2hlblxuICAgICAgIGhhbmRsZWQgcmVzdWx0aW5nIGluIGFkZGluZyB0aGlzIG5vZGUgZWFybHkuXG4gICAgICAqL1xuICAgICAgcmV0dXJuIFtleGlzdGluZ1ZhbHVlLCB0cnVlXTtcbiAgICB9XG5cbiAgICBjb25zdCBhdHRyaWJ1dGVzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gICAgaWYgKChub2RlIGFzIGFueSkuYXR0cmlidXRlcykge1xuICAgICAgY29uc3QgYXNIVE1MRWxlbWVudCA9IG5vZGUgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBhc0hUTUxFbGVtZW50LmdldEF0dHJpYnV0ZU5hbWVzKCkpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBhc0hUTUxFbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpO1xuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOdWxsIGF0dHJpYnV0ZSB2YWx1ZSBmb3Iga2V5OiBcIiArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShub2RlLCBrZXkpKSB7XG4gICAgICAgICAgYXR0cmlidXRlc1trZXldID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBub2RlSWQgPSB0aGlzLm5leHROb2RlSWQrKztcbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50ID0ge1xuICAgICAgbm9kZUlkLFxuICAgICAgdGFnOiBub2RlLm5vZGVOYW1lLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIGNoaWxkTm9kZXM6IFtdLFxuICAgICAgcmVhbEVsZW1lbnQ6IG5vZGUsXG4gICAgICBwYXJlbnQsXG4gICAgfTtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLlRleHQgJiYgbm9kZS50ZXh0Q29udGVudCkge1xuICAgICAgdmlydHVhbEVsZW1lbnQudGV4dENvbnRlbnQgPSBub2RlLnRleHRDb250ZW50O1xuICAgIH1cbiAgICB0aGlzLm5vZGVUb05vZGVJZC5zZXQodmlydHVhbEVsZW1lbnQsIG5vZGVJZCk7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuc2V0KG5vZGVJZCwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LnNldChub2RlLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgcmV0dXJuIFt2aXJ0dWFsRWxlbWVudCwgZmFsc2VdO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHtcbiAgT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbn0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgZXZlbnQ6IE9ic2VydmFibGVET01SZW1vdGVFdmVudDtcbn07XG5cbmV4cG9ydCB0eXBlIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9XG4gIHwgQWRkQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2VcbiAgfCBEaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZE1lc3NhZ2U7XG5cbnR5cGUgRE9NTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERPTV9NRVNTQUdFX1RZUEU7XG4gIG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UgPSBET01NZXNzYWdlO1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlNZXNzYWdlVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2UoXG4gIG1lc3NhZ2U6IFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgaW5zdGFuY2U6IE9ic2VydmFibGVET01JbnRlcmZhY2UsXG4pIHtcbiAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLmFkZENvbm5lY3RlZFVzZXJJZChtZXNzYWdlLmNvbm5lY3Rpb25JZCk7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UucmVtb3ZlQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQobWVzc2FnZS5jb25uZWN0aW9uSWQsIG1lc3NhZ2UuZXZlbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2YWJsZURPTUludGVyZmFjZVRvTWVzc2FnZVNlbmRlcihcbiAgc2VuZGVyOiAobWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB2b2lkLFxuICBkaXNwb3NlOiAoKSA9PiB2b2lkLFxuKSB7XG4gIGNvbnN0IHJlbW90ZU9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UgPSB7XG4gICAgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgICByZW1vdGVFdmVudDogT2JzZXJ2YWJsZURPTVJlbW90ZUV2ZW50LFxuICAgICk6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgZXZlbnQ6IHJlbW90ZUV2ZW50LFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgZGlzcG9zZSgpO1xuICAgIH0sXG4gICAgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuICByZXR1cm4gcmVtb3RlT2JzZXJ2YWJsZURPTTtcbn1cbiIsICJpbXBvcnQgeyBET01SdW5uZXJGYWN0b3J5LCBET01SdW5uZXJJbnRlcmZhY2UsIERPTVJ1bm5lck1lc3NhZ2UgfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbVwiO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZURPTVJlbW90ZUV2ZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmxldCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcbmlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKSAtIChkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXIpO1xufVxuXG4vKipcbiAqIFdlYkJyb3dzZXJET01SdW5uZXIgaXMgYSBET01SdW5uZXJJbnRlcmZhY2UgaW1wbGVtZW50YXRpb24gdGhhdCBydW5zIGluIGEgd2ViIGJyb3dzZXIuIEl0IGlzIGludGVuZGVkIHRvIGJlIHJ1biBpblxuICogYW4gaWZyYW1lIGFuZCB0aGUgcGFyZW50IHdpbmRvdyBpcyBleHBlY3RlZCB0byBzZW5kIG1lc3NhZ2VzIHRvIGl0IHRvIGRpc3BhdGNoIGV2ZW50cyBhbmQgdG8gcmVjZWl2ZSBtdXRhdGlvblxuICogbWVzc2FnZXMuXG4gKlxuICogSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgZG9jdW1lbnQgY29udGVudHMgaXMgaW5qZWN0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJCcm93c2VyRE9NUnVubmVyIGltcGxlbWVudHMgRE9NUnVubmVySW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBtdXRhdGlvbk9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IG9iamVjdCwgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkKSB7XG4gICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuXG4gICAgLy8gRm9yd2FyZCBjb25zb2xlIG1lc3NhZ2VzXG4gICAgZm9yIChjb25zdCBsZXZlbCBvZiBbXCJlcnJvclwiLCBcIndhcm5cIiwgXCJpbmZvXCIsIFwibG9nXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBkZWZhdWx0Rm4gPSB3aW5kb3cuY29uc29sZVtsZXZlbF07XG5cbiAgICAgIHdpbmRvdy5jb25zb2xlW2xldmVsXSA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGFyZ3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlZmF1bHRGbiguLi5hcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRm9yd2FyZCB1bmNhdWdodCBlcnJvcnNcbiAgICB3aW5kb3cub25lcnJvciA9IChtZXNzYWdlLCBzb3VyY2UsIGxpbmUsIGNvbHVtbiwgZXJyb3IpID0+IHtcbiAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgIGxldmVsOiBcInN5c3RlbVwiLFxuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgdHlwZTogZXJyb3I/Lm5hbWUsXG4gICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgIGNvbHVtbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBsZXQgZGlkU2VuZExvYWQgPSBmYWxzZTtcblxuICAgIHRoaXMubXV0YXRpb25PYnNlcnZlciA9IG5ldyB3aW5kb3cuTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25MaXN0KSA9PiB7XG4gICAgICBpZiAoIWRvY3VtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXV0YXRpb25PYnNlcnZlciBjYWxsZWQgYmVmb3JlIGxvYWRcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbXV0YXRpb25MaXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAod2luZG93IGFzIGFueSkucGFyYW1zID0gcGFyYW1zO1xuXG4gICAgY29uc3QgZmluaXNoTG9hZCA9ICgpID0+IHtcbiAgICAgIGlmIChkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5pc2hMb2FkIGNhbGxlZCB0d2ljZVwiKTtcbiAgICAgIH1cbiAgICAgIGRpZFNlbmRMb2FkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHRoaXMubXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHdpbmRvdy5kb2N1bWVudCwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICBzZXRUaW1lb3V0KGZpbmlzaExvYWQsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgZmluaXNoTG9hZCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgYnViYmxlcyA9IHJlbW90ZUV2ZW50LmJ1YmJsZXMgfHwgZmFsc2U7XG4gICAgY29uc3QgcmVtb3RlRXZlbnRPYmplY3QgPSBuZXcgQ3VzdG9tRXZlbnQocmVtb3RlRXZlbnQubmFtZSwge1xuICAgICAgYnViYmxlcyxcbiAgICAgIGRldGFpbDogeyAuLi5yZW1vdGVFdmVudC5wYXJhbXMsIGNvbm5lY3Rpb25JZCB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgZXZlbnRUeXBlTG93ZXJDYXNlID0gcmVtb3RlRXZlbnQubmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gVE9ETyAtIGNoZWNrIGlmIHRoZXJlIGFyZSBvdGhlciBldmVudHMgdGhhdCBhdXRvbWF0aWNhbGx5IHdpcmUgdXAgc2ltaWxhcmx5IHRvIGNsaWNrLT5vbmNsaWNrIGFuZCBhdm9pZCB0aG9zZSB0b29cbiAgICBpZiAoZXZlbnRUeXBlTG93ZXJDYXNlICE9PSBcImNsaWNrXCIpIHtcbiAgICAgIGNvbnN0IGhhbmRsZXJBdHRyaWJ1dGVOYW1lID0gXCJvblwiICsgZXZlbnRUeXBlTG93ZXJDYXNlO1xuICAgICAgY29uc3QgaGFuZGxlckF0dHJpYnV0ZVZhbHVlID0gcmVhbEVsZW1lbnQuZ2V0QXR0cmlidXRlKGhhbmRsZXJBdHRyaWJ1dGVOYW1lKTtcbiAgICAgIGlmIChoYW5kbGVyQXR0cmlidXRlVmFsdWUpIHtcbiAgICAgICAgLy8gVGhpcyBldmVudCBpcyBkZWZpbmVkIGFzIGFuIEhUTUwgZXZlbnQgYXR0cmlidXRlLlxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZuID0gRnVuY3Rpb24oXCJldmVudFwiLCBoYW5kbGVyQXR0cmlidXRlVmFsdWUpO1xuICAgICAgICAgIGZuLmFwcGx5KHJlYWxFbGVtZW50LCBbcmVtb3RlRXZlbnRPYmplY3RdKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBydW5uaW5nIGV2ZW50IGhhbmRsZXI6XCIsIGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGlzcGF0Y2ggdGhlIGV2ZW50IHZpYSBKYXZhU2NyaXB0LlxuICAgIHJlYWxFbGVtZW50LmRpc3BhdGNoRXZlbnQocmVtb3RlRXZlbnRPYmplY3QpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAvLyBUT0RPIC0gaGFuZGxlIGRpc3Bvc2VcbiAgfVxuXG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50IHtcbiAgICByZXR1cm4gZG9jdW1lbnQ7XG4gIH1cblxuICBnZXREb2N1bWVudFRpbWUoKTogbnVtYmVyIHtcbiAgICBjb25zdCBkYXRlQmFzZWREb2N1bWVudFRpbWUgPSBEYXRlLm5vdygpIC0gZG9jdW1lbnRMb2FkVGltZTtcbiAgICBpZiAoZG9jdW1lbnQudGltZWxpbmUgJiYgZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUpIHtcbiAgICAgIGNvbnN0IHRpbWUgPSBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXI7XG4gICAgICBpZiAoZGF0ZUJhc2VkRG9jdW1lbnRUaW1lID4gdGltZSArIDUwMCkge1xuICAgICAgICAvLyBUaGUgdGltZWxpbmUgY2FuIGJlIFwibGVmdCBiZWhpbmRcIiBpZiB0aGUgdGFiIGlzIGJhY2tncm91bmRlZCBmb3IgYSB3aGlsZSwgc28gd2UgdXNlIHRoZSBkYXRlLWJhc2VkIHRpbWVcbiAgICAgICAgLy8gaW5zdGVhZC4gSWYvd2hlbiB0aGUgZG9jdW1lbnQgaXMgYnJvdWdodCBiYWNrIGludG8gdGhlIGZvcmVncm91bmQsIHRoZSB0aW1lbGluZSB3aWxsIGNhdGNoIHVwLlxuICAgICAgICByZXR1cm4gZGF0ZUJhc2VkRG9jdW1lbnRUaW1lO1xuICAgICAgfVxuICAgICAgLy8gSWRlYWwgY2FzZSAtIHVzZSB0aGUgZG9jdW1lbnQudGltZWxpbmUgYXMgaXQncyB3aGF0IGlzIGF2YWlsYWJsZSB0byB0aGUgZG9jdW1lbnQgc2NyaXB0XG4gICAgICByZXR1cm4gdGltZTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGVCYXNlZERvY3VtZW50VGltZTtcbiAgfVxuXG4gIC8vIFRPRE8gLSByZXNvbHZlIHR5cGVzIChXaW5kb3cgbmVlZHMgdG8gZXhwb3NlIGNsYXNzZXMgc3VjaCBhcyBDdXN0b21FdmVudCBhcyBwcm9wZXJ0aWVzKVxuICBnZXRXaW5kb3coKTogYW55IHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9XG59XG4iLCAiaW1wb3J0IHsgT2JzZXJ2YWJsZURPTSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NXCI7XG5pbXBvcnQge1xuICBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSxcbiAgRE9NX01FU1NBR0VfVFlQRSxcbiAgRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01NZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycyxcbiAgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3RvcnkgfSBmcm9tIFwiLi9XZWJCcm93c2VyRE9NUnVubmVyXCI7XG5cbi8qKlxuICogVGhpcyBpcyBydW4gaW4gdGhlIGlmcmFtZSB0aGF0IHdpbGwgZXhlY3V0ZSB0aGUgZG9jdW1lbnQgc2NyaXB0IHRvIHNldHVwIHRoZSBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBtZXNzYWdlcyBhbmRcbiAqIG9ic2VydmluZyBvZiBET00gbXV0YXRpb24gdXNpbmcgdGhlIFdlYkJyb3dzZXJET01SdW5uZXIgY2xhc3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cElmcmFtZVdlYlJ1bm5lcihhcmdzU3RyaW5nOiBzdHJpbmcpIHtcbiAgY29uc3Qgb2JzZXJ2YWJsZURPTVBhcmFtcyA9IEpTT04ucGFyc2UoYXRvYihhcmdzU3RyaW5nKSkgYXMgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM7XG5cbiAgY29uc3Qgc2VuZE1lc3NhZ2VUb0hhbmRsZXIgPSAobWVzc2FnZTogRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UpID0+IHtcbiAgICB3aW5kb3cucGFyZW50LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpLCBcIipcIik7XG4gIH07XG5cbiAgY29uc3Qgb2JzZXJ2YWJsZURPTSA9IG5ldyBPYnNlcnZhYmxlRE9NKFxuICAgIHtcbiAgICAgIC4uLm9ic2VydmFibGVET01QYXJhbXMsXG4gICAgICBodG1sQ29udGVudHM6IFwiXCIsIC8vIFRoaXMgbXVzdCBiZSBlbXB0eSBhcyB0aGUgY29udGVudHMgYXJlIGFzc3VtZWQgdG8gYmUgcHJvdmlkZWQgYnkgdGhlIHNyY2RvY1xuICAgIH0sXG4gICAgKG9ic2VydmFibGVET01NZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSkgPT4ge1xuICAgICAgc2VuZE1lc3NhZ2VUb0hhbmRsZXIoe1xuICAgICAgICB0eXBlOiBET01fTUVTU0FHRV9UWVBFLFxuICAgICAgICBtZXNzYWdlOiBvYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3RvcnksXG4gICk7XG5cbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChlKSA9PiB7XG4gICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShlLmRhdGEpIGFzIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZTtcbiAgICBzd2l0Y2ggKHBhcnNlZC50eXBlKSB7XG4gICAgICBjYXNlIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFOlxuICAgICAgICBvYnNlcnZhYmxlRE9NLmRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKHBhcnNlZC5jb25uZWN0aW9uSWQsIHBhcnNlZC5ldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFOlxuICAgICAgICBvYnNlcnZhYmxlRE9NLmFkZENvbm5lY3RlZFVzZXJJZChwYXJzZWQuY29ubmVjdGlvbklkKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00ucmVtb3ZlQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBwYXJzZWQpO1xuICAgIH1cbiAgfSk7XG59XG4iLCAiaW1wb3J0IHsgc2V0dXBJZnJhbWVXZWJSdW5uZXIgfSBmcm9tIFwiLi9JZnJhbWVXZWJSdW5uZXJcIjtcblxuY29uc3QgYXJncyA9ICh3aW5kb3cgYXMgYW55KS5hcmdzO1xuc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJncyk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBSU8sU0FBUywwQkFBMEIsSUFBb0Q7QUFDNUYsU0FBTztBQUFBLElBQ0wsUUFBUSxHQUFHO0FBQUEsSUFDWCxLQUFLLEdBQUc7QUFBQSxJQUNSLFlBQVksT0FBTyxPQUFPLENBQUMsR0FBRyxHQUFHLFVBQVU7QUFBQTtBQUFBLElBQzNDLFlBQVksR0FBRyxXQUFXLElBQUksQ0FBQyxVQUFVLDBCQUEwQixLQUFLLENBQUM7QUFBQSxJQUN6RSxhQUFhLEdBQUc7QUFBQSxFQUNsQjtBQUNGOzs7QUN3Q08sSUFBTSxnQkFBTixNQUFzRDtBQUFBLEVBYzNELFlBQ0UseUJBQ0EsVUFDQSxlQUNBO0FBakJGLFNBQVEsZUFBZSxvQkFBSSxJQUFtQztBQUM5RCxTQUFRLGVBQWUsb0JBQUksSUFBbUM7QUFDOUQsU0FBUSw4QkFBOEIsb0JBQUksSUFBMkM7QUFDckYsU0FBUSxrQkFBa0I7QUFFMUIsU0FBUSxhQUFhO0FBR3JCLFNBQVEsU0FBUztBQUNqQixTQUFRLHFCQUF3QyxDQUFDO0FBUy9DLFNBQUssV0FBVyx3QkFBd0I7QUFDeEMsU0FBSyxrQkFBa0Isd0JBQXdCO0FBQy9DLFNBQUssV0FBVztBQUVoQixTQUFLLDRCQUE0QixZQUFZLE1BQU07QUFDakQsV0FBSztBQUFBLFFBQ0g7QUFBQSxVQUNFLGNBQWMsS0FBSyxnQkFBZ0I7QUFBQSxRQUNyQztBQUFBLFFBQ0E7QUFBQSxNQUNGO0FBQUEsSUFDRixHQUFHLHdCQUF3Qiw0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UyxHQUFHO0FBQ1Ysa0JBQVEsTUFBTSxnQ0FBZ0MsQ0FBQztBQUFBLFFBQ2pEO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFHQSxnQkFBWSxjQUFjLGlCQUFpQjtBQUFBLEVBQzdDO0FBQUEsRUFFQSxVQUFnQjtBQUFBLEVBRWhCO0FBQUEsRUFFQSxjQUF3QjtBQUN0QixXQUFPO0FBQUEsRUFDVDtBQUFBLEVBRUEsa0JBQTBCO0FBQ3hCLFVBQU0sd0JBQXdCLEtBQUssSUFBSSxJQUFJO0FBQzNDLFFBQUksU0FBUyxZQUFZLFNBQVMsU0FBUyxhQUFhO0FBQ3RELFlBQU0sT0FBTyxTQUFTLFNBQVM7QUFDL0IsVUFBSSx3QkFBd0IsT0FBTyxLQUFLO0FBR3RDLGVBQU87QUFBQSxNQUNUO0FBRUEsYUFBTztBQUFBLElBQ1Q7QUFDQSxXQUFPO0FBQUEsRUFDVDtBQUFBO0FBQUEsRUFHQSxZQUFpQjtBQUNmLFdBQU87QUFBQSxFQUNUO0FBQ0Y7OztBQy9JTyxTQUFTLHFCQUFxQixZQUFvQjtBQUN2RCxRQUFNLHNCQUFzQixLQUFLLE1BQU0sS0FBSyxVQUFVLENBQUM7QUFFdkQsUUFBTSx1QkFBdUIsQ0FBQyxZQUE4QztBQUMxRSxXQUFPLE9BQU8sWUFBWSxLQUFLLFVBQVUsT0FBTyxHQUFHLEdBQUc7QUFBQSxFQUN4RDtBQUVBLFFBQU0sZ0JBQWdCLElBQUk7QUFBQSxJQUN4QjtBQUFBLE1BQ0UsR0FBRztBQUFBLE1BQ0gsY0FBYztBQUFBO0FBQUEsSUFDaEI7QUFBQSxJQUNBLENBQUMseUJBQStDO0FBQzlDLDJCQUFxQjtBQUFBLFFBQ25CLE1BQU07QUFBQSxRQUNOLFNBQVM7QUFBQSxNQUNYLENBQUM7QUFBQSxJQUNIO0FBQUEsSUFDQTtBQUFBLEVBQ0Y7QUFFQSxTQUFPLGlCQUFpQixXQUFXLENBQUMsTUFBTTtBQUN4QyxVQUFNLFNBQVMsS0FBSyxNQUFNLEVBQUUsSUFBSTtBQUNoQyxZQUFRLE9BQU8sTUFBTTtBQUFBLE1BQ25CLEtBQUs7QUFDSCxzQkFBYyxvQ0FBb0MsT0FBTyxjQUFjLE9BQU8sS0FBSztBQUNuRjtBQUFBLE1BQ0YsS0FBSztBQUNILHNCQUFjLG1CQUFtQixPQUFPLFlBQVk7QUFDcEQ7QUFBQSxNQUNGLEtBQUs7QUFDSCxzQkFBYyxzQkFBc0IsT0FBTyxZQUFZO0FBQ3ZEO0FBQUEsTUFDRjtBQUNFLGdCQUFRLE1BQU0sd0JBQXdCLE1BQU07QUFBQSxJQUNoRDtBQUFBLEVBQ0YsQ0FBQztBQUNIOzs7QUNyREEsSUFBTSxPQUFRLE9BQWU7QUFDN0IscUJBQXFCLElBQUk7IiwKICAibmFtZXMiOiBbImFyZ3MiXQp9Cg==\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.visibility = \"hidden\";\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": ";AAIA,IAAM,eAAN,cAA2B,YAAY;AAAA,EAIrC,YACE,UACA,cACA;AACA,UAAM;AACN,SAAK,WAAW;AAChB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEO,QAAQ;AACb,SAAK,cAAc,IAAI,WAAW,OAAO,CAAC;AAAA,EAC5C;AAAA,EAEO,iBACL,MACA,UACA,SACA;AACA,QAAI,SAAS,QAAQ;AACnB,iBAAW,MAAM;AACf,iBAAS,KAAK,IAAI,EAAE,IAAI,MAAM,MAAM,CAAC;AAAA,MACvC,GAAG,CAAC;AACJ;AAAA,IACF;AACA,UAAM,iBAAiB,MAAM,UAAU,OAAO;AAAA,EAChD;AAAA,EAEO,KAAK,MAAyD;AACnE,SAAK,aAAa,IAAI;AAAA,EACxB;AACF;AAMO,IAAM,gBAAN,MAAoB;AAAA,EAIzB,YAAY,UAAkB;AAC5B,SAAK,sBAAsB,IAAI,aAAa,UAAU,CAAC,SAAS;AAC9D,WAAK,oBAAoB;AAAA,QACvB,IAAI,aAAa,WAAW;AAAA,UAC1B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,SAAK,sBAAsB,IAAI,aAAa,UAAU,CAAC,SAAS;AAC9D,WAAK,oBAAoB;AAAA,QACvB,IAAI,aAAa,WAAW;AAAA,UAC1B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AChEA;AAAA,EACE;AAAA,EAGA;AAAA,OAIK;;;ACTP;;;ACYO,IAAM,eAAN,MAAmB;AAAA,EAIxB,YACU,yBACA,mBACR;AAFQ;AACA;AAER,SAAK,SAAS,SAAS,cAAc,QAAQ;AAC7C,SAAK,OAAO,aAAa,WAAW,eAAe;AACnD,SAAK,OAAO,MAAM,WAAW;AAC7B,SAAK,OAAO,MAAM,MAAM;AACxB,SAAK,OAAO,MAAM,OAAO;AACzB,SAAK,OAAO,MAAM,QAAQ;AAC1B,SAAK,OAAO,MAAM,SAAS;AAC3B,SAAK,OAAO,MAAM,SAAS;AAC3B,SAAK,OAAO,MAAM,aAAa;AAE/B,UAAM,kBAAoD;AAAA,MACxD,GAAG,KAAK;AAAA,IACV;AACA,WAAO,gBAAgB;AAEvB,UAAM,OAAO,KAAK,KAAK,UAAU,eAAe,CAAC;AAEjD,UAAM,UAAU,UAAU,UAAU,SAAS,OAAO;AACpD,QAAI,SAAS;AAEX,eAAS,KAAK,OAAO,KAAK,MAAM;AAEhC,YAAM,aAAa,KAAK,OAAO,cAAe,SAAS;AACvD,YAAM,oBAAoB,SAAS,cAAc,QAAQ;AACzD,wBAAkB,YAAY,gBAAgB,IAAI;AAClD,iBAAW,OAAO,iBAAiB;AACnC,YAAM,sBAAsB,SAAS,cAAc,QAAQ;AAC3D,0BAAoB,YAAY;AAChC,iBAAW,OAAO,mBAAmB;AACrC,YAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,iBAAW,OAAO,aAAa;AAC/B,oBAAc,YAAY,wBAAwB;AAAA,IACpD,OAAO;AACL,WAAK,OAAO;AAAA,QACV;AAAA,QACA;AAAA,6BACqB,IAAI;AAAA,gBACjB,aAAU;AAAA,QAClB,wBAAwB,YAAY;AAAA;AAAA,MAEtC;AACA,eAAS,KAAK,OAAO,KAAK,MAAM;AAAA,IAClC;AAEA,SAAK,sBAAsB,CAAC,MAAoB;AAC9C,UAAI,EAAE,WAAW,KAAK,OAAO,iBAAkB,WAAW,EAAE,WAAW,MAAO;AAC5E,cAAM,SAAS,KAAK,MAAM,EAAE,IAAI;AAChC,aAAK,kBAAkB,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,WAAO,iBAAiB,WAAW,KAAK,mBAAmB;AAAA,EAC7D;AAAA,EAEA,oBAAoB,SAAyC;AAE3D,SAAK,OAAO,cAAe,YAAY,KAAK,UAAU,OAAO,GAAG,GAAG;AAAA,EACrE;AAAA,EAEA,UAAU;AACR,WAAO,oBAAoB,WAAW,KAAK,mBAAmB;AAC9D,SAAK,OAAO,OAAO;AAAA,EACrB;AACF;;;AFlEO,IAAM,6BAAmD,CAC9D,yBACA,aACG;AACH,QAAM,eAAe,IAAI;AAAA,IACvB;AAAA,IACA,CAAC,YAA8C;AAC7C,cAAQ,QAAQ,MAAM;AAAA,QACpB,KAAK;AACH,mBAAS,QAAQ,SAAS,mBAAmB;AAC7C;AAAA,QACF;AACE,kBAAQ,MAAM,wBAAwB,QAAQ,IAAI;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,sBAA8C;AAAA,IAClD,CAAC,YAA4C;AAC3C,mBAAa,oBAAoB,OAAO;AAAA,IAC1C;AAAA,IACA,MAAM;AACJ,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;;;AGzCA,SAAS,4CAA4C;AACrD,SAAS,6BAA6B;AAa/B,IAAM,8BAAN,MAAkC;AAAA,EAUvC,YAAY,sBAAsB,MAAM,SAAuB;AAP/D,SAAO,iBAII;AAIT,SAAK,sBAAsB;AAC3B,SAAK,UAAU,WAAW,SAAS,cAAc,KAAK;AAAA,EACxD;AAAA,EAEO,aAAa;AAClB,QAAI,CAAC,KAAK,gBAAgB;AACxB;AAAA,IACF;AACA,SAAK,eAAe,SAAS;AAAA,MAC3B,KAAK,eAAe,cAAc;AAAA,IACpC;AACA,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEO,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAEO,QACLA,WACA,cACA;AACA,QAAI,KAAK,gBAAgB;AACvB,WAAK,WAAW;AAAA,IAClB;AACA,UAAM,gBAAgB,IAAI,cAAc,oCAAoC;AAC5E,QAAI,oBAAiF;AACrF,UAAM,eAAe,CAAC,SAAsB,UAAuB;AACjE,UAAI,CAAC,mBAAmB;AACtB,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,wBAAkB,SAAS,KAAK;AAAA,IAClC;AAEA,QAAI,KAAK,qBAAqB;AAC5B,WAAK,QAAQ,iBAAiB,SAAS,CAAC,UAAiB;AACvD,qBAAa,MAAM,QAAuB,KAAoB;AAC9D,cAAM,gBAAgB;AACtB,cAAM,eAAe;AACrB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,IAAI;AAAA,MACvB;AAAA,MACA,MAAM,cAAc;AAAA,MACpB,KAAK;AAAA,MACL;AAAA,IACF;AACA,wBAAoB,CAAC,SAAsB,UAAuB;AAChE,mBAAa,YAAY,SAAS,KAAK;AAAA,IACzC;AACA,IAAAA,UAAS,aAAa,cAAc,mBAA2C;AAC/E,SAAK,iBAAiB;AAAA,MACpB,UAAAA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AClFA,cAAc;",
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) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"connected\", {\n detail: { connectionId }\n })\n );\n }\n removeConnectedUserId(connectionId) {\n this.domRunner.getWindow().dispatchEvent(\n new (this.domRunner.getWindow()).CustomEvent(\"disconnected\", {\n detail: { connectionId }\n })\n );\n }\n processModificationList(mutationList) {\n 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 virtualElement = {\n nodeId,\n tag: node.nodeName,\n attributes,\n childNodes: [],\n realElement: node,\n parent\n };\n if (node instanceof this.domRunner.getWindow().Text && node.textContent) {\n virtualElement.textContent = node.textContent;\n }\n this.nodeToNodeId.set(virtualElement, nodeId);\n this.nodeIdToNode.set(nodeId, virtualElement);\n this.realElementToVirtualElement.set(node, virtualElement);\n return [virtualElement, false];\n }\n getVirtualDOMElementForRealElementOrThrow(realElement) {\n const virtualElement = this.realElementToVirtualElement.get(realElement);\n if (!virtualElement) {\n throw new Error(`Virtual element not found for real element`);\n }\n return virtualElement;\n }\n isIgnoredElement(node) {\n if (this.ignoreTextNodes && node instanceof this.domRunner.getWindow().Text) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().HTMLScriptElement) {\n return true;\n } else if (node instanceof this.domRunner.getWindow().Comment) {\n return true;\n }\n return false;\n }\n isIgnoredAttribute(node, attributeName) {\n return attributeName.startsWith(\"on\");\n }\n dispatchRemoteEventFromConnectionId(connectionId, remoteEvent) {\n const domNode = this.nodeIdToNode.get(remoteEvent.nodeId);\n if (!domNode) {\n console.error(\"Unknown node ID in remote event: \" + remoteEvent.nodeId);\n return;\n }\n if (domNode instanceof this.domRunner.getWindow().Text) {\n console.warn(\"Cannot dispatch remote event to text node\");\n return;\n }\n this.domRunner.dispatchRemoteEventFromConnectionId(\n connectionId,\n domNode.realElement,\n remoteEvent\n );\n }\n dispose() {\n clearInterval(this.documentTimeIntervalTimer);\n this.domRunner.dispose();\n }\n getDocumentTime() {\n return this.domRunner.getDocumentTime();\n }\n};\n\n// ../../observable-dom-common/build/index.js\nvar ADD_CONNECTED_USER_ID_MESSAGE_TYPE = \"addConnectedUserId\";\nvar REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE = \"removeConnectedUserId\";\nvar DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE = \"dispatchRemoteEventFromConnectionId\";\nvar DOM_MESSAGE_TYPE = \"dom\";\n\n// src/WebBrowserDOMRunner.ts\nvar WebBrowserDOMRunnerFactory = (htmlPath, htmlContents, params, callback) => {\n return new WebBrowserDOMRunner(params, callback);\n};\nvar documentLoadTime = Date.now();\nif (document.timeline && document.timeline.currentTime) {\n documentLoadTime = Date.now() - document.timeline.currentTime;\n}\nvar WebBrowserDOMRunner = class {\n constructor(params, callback) {\n this.callback = callback;\n for (const level of [\"error\", \"warn\", \"info\", \"log\"]) {\n const defaultFn = window.console[level];\n window.console[level] = (...args2) => {\n callback({\n logMessage: {\n level,\n content: args2\n }\n });\n defaultFn(...args2);\n };\n }\n window.onerror = (message, source, line, column, error) => {\n callback({\n logMessage: {\n level: \"system\",\n content: [\n {\n message,\n type: error?.name,\n line,\n column\n }\n ]\n }\n });\n return false;\n };\n let didSendLoad = false;\n this.mutationObserver = new window.MutationObserver((mutationList) => {\n if (!document) {\n return;\n }\n if (!didSendLoad) {\n throw new Error(\"MutationObserver called before load\");\n }\n this.callback({\n mutationList\n });\n });\n window.params = params;\n const finishLoad = () => {\n if (didSendLoad) {\n throw new Error(\"finishLoad called twice\");\n }\n didSendLoad = true;\n this.callback({\n loaded: true\n });\n this.mutationObserver.observe(window.document, {\n attributes: true,\n childList: true,\n subtree: true,\n characterData: true\n });\n };\n if (document.body) {\n setTimeout(finishLoad, 0);\n } else {\n window.addEventListener(\"DOMContentLoaded\", finishLoad);\n }\n }\n dispatchRemoteEventFromConnectionId(connectionId, realElement, remoteEvent) {\n const bubbles = remoteEvent.bubbles || false;\n const remoteEventObject = new CustomEvent(remoteEvent.name, {\n bubbles,\n detail: { ...remoteEvent.params, connectionId }\n });\n const eventTypeLowerCase = remoteEvent.name.toLowerCase();\n if (eventTypeLowerCase !== \"click\") {\n const handlerAttributeName = \"on\" + eventTypeLowerCase;\n const handlerAttributeValue = realElement.getAttribute(handlerAttributeName);\n if (handlerAttributeValue) {\n try {\n const fn = Function(\"event\", handlerAttributeValue);\n fn.apply(realElement, [remoteEventObject]);\n } catch (e) {\n console.error(\"Error running event handler:\", e);\n }\n }\n }\n realElement.dispatchEvent(remoteEventObject);\n }\n dispose() {\n }\n getDocument() {\n return document;\n }\n getDocumentTime() {\n const dateBasedDocumentTime = Date.now() - documentLoadTime;\n if (document.timeline && document.timeline.currentTime) {\n const time = document.timeline.currentTime;\n if (dateBasedDocumentTime > time + 500) {\n return dateBasedDocumentTime;\n }\n return time;\n }\n return dateBasedDocumentTime;\n }\n // TODO - resolve types (Window needs to expose classes such as CustomEvent as properties)\n getWindow() {\n return window;\n }\n};\n\n// src/IframeWebRunner.ts\nfunction setupIframeWebRunner(argsString) {\n const observableDOMParams = JSON.parse(atob(argsString));\n const sendMessageToHandler = (message) => {\n window.parent.postMessage(JSON.stringify(message), \"*\");\n };\n const observableDOM = new ObservableDOM(\n {\n ...observableDOMParams,\n htmlContents: \"\"\n // This must be empty as the contents are assumed to be provided by the srcdoc\n },\n (observableDOMMessage) => {\n sendMessageToHandler({\n type: DOM_MESSAGE_TYPE,\n message: observableDOMMessage\n });\n },\n WebBrowserDOMRunnerFactory\n );\n window.addEventListener(\"message\", (e) => {\n const parsed = JSON.parse(e.data);\n switch (parsed.type) {\n case DISPATCH_REMOTE_EVENT_FROM_CONNECTION_ID_MESSAGE_TYPE:\n observableDOM.dispatchRemoteEventFromConnectionId(parsed.connectionId, parsed.event);\n break;\n case ADD_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.addConnectedUserId(parsed.connectionId);\n break;\n case REMOVE_CONNECTED_USER_ID_MESSAGE_TYPE:\n observableDOM.removeConnectedUserId(parsed.connectionId);\n break;\n default:\n console.error(\"Unknown message type\", parsed);\n }\n });\n}\n\n// src/index.ts\nvar args = window.args;\nsetupIframeWebRunner(args);\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vb2JzZXJ2YWJsZS1kb20vc3JjL3V0aWxzLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NLnRzIiwgIi4uLy4uLy4uL29ic2VydmFibGUtZG9tLWNvbW1vbi9zcmMvbWVzc2FnZXMudHMiLCAiLi4vc3JjL1dlYkJyb3dzZXJET01SdW5uZXIudHMiLCAiLi4vc3JjL0lmcmFtZVdlYlJ1bm5lci50cyIsICIuLi9zcmMvaW5kZXgudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB9IGZyb20gXCIuL09ic2VydmFibGVET01cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMoZWw6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCk6IFN0YXRpY1ZpcnR1YWxET01FbGVtZW50IHtcbiAgcmV0dXJuIHtcbiAgICBub2RlSWQ6IGVsLm5vZGVJZCxcbiAgICB0YWc6IGVsLnRhZyxcbiAgICBhdHRyaWJ1dGVzOiBPYmplY3QuYXNzaWduKHt9LCBlbC5hdHRyaWJ1dGVzKSwgLy8gQ29weSB0aGUgYXR0cmlidXRlcyBvYmplY3QgLSBzaGFsbG93IGNvcHkgaXMgZmluZSBhcyB0aGUgYXR0cmlidXRlcyBhcmUgc3RyaW5nc1xuICAgIGNoaWxkTm9kZXM6IGVsLmNoaWxkTm9kZXMubWFwKChjaGlsZCkgPT4gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhjaGlsZCkpLFxuICAgIHRleHRDb250ZW50OiBlbC50ZXh0Q29udGVudCxcbiAgfTtcbn1cbiIsICJpbXBvcnQge1xuICBMb2dNZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlLFxuICBPYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgU3RhdGljVmlydHVhbERPTUVsZW1lbnQsXG4gIFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCxcbn0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmltcG9ydCB7IHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgdHlwZSBET01SdW5uZXJNZXNzYWdlID0ge1xuICBsb2FkZWQ/OiBib29sZWFuO1xuICBtdXRhdGlvbkxpc3Q/OiBBcnJheTxNdXRhdGlvblJlY29yZD47XG4gIGxvZ01lc3NhZ2U/OiBMb2dNZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRE9NUnVubmVySW50ZXJmYWNlID0ge1xuICBnZXREb2N1bWVudCgpOiBEb2N1bWVudDtcbiAgZ2V0V2luZG93KCk6IFdpbmRvdyAmIHtcbiAgICBDdXN0b21FdmVudDogdHlwZW9mIEN1c3RvbUV2ZW50O1xuICAgIFRleHQ6IHR5cGVvZiBUZXh0O1xuICAgIEhUTUxTY3JpcHRFbGVtZW50OiB0eXBlb2YgSFRNTFNjcmlwdEVsZW1lbnQ7XG4gICAgQ29tbWVudDogdHlwZW9mIENvbW1lbnQ7XG4gIH07IC8vIFRPRE8gLSBEZWZpbmUgdGhpcyB3aXRob3V0IHVzaW5nIEpTRE9NIHR5cGVzXG4gIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlYWxFbGVtZW50OiBFbGVtZW50LFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQ7XG4gIGRpc3Bvc2UoKTogdm9pZDtcbiAgZ2V0RG9jdW1lbnRUaW1lKCk6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERPTVJ1bm5lckZhY3RvcnkgPSAoXG4gIGh0bWxQYXRoOiBzdHJpbmcsXG4gIGh0bWxDb250ZW50czogc3RyaW5nLFxuICBwYXJhbXM6IG9iamVjdCxcbiAgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkLFxuKSA9PiBET01SdW5uZXJJbnRlcmZhY2U7XG5cbmV4cG9ydCB0eXBlIExpdmVWaXJ0dWFsRE9NRWxlbWVudCA9IE9taXQ8U3RhdGljVmlydHVhbERPTUVsZW1lbnQsIFwiY2hpbGROb2Rlc1wiPiAmIHtcbiAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQgfCBUZXh0O1xuICBjaGlsZE5vZGVzOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+O1xuICBwYXJlbnQ6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGw7XG59O1xuXG4vKipcbiAqIFRoZSBPYnNlcnZhYmxlRE9NIGNsYXNzIGhhbmRsZXMgdGhlIHJ1bm5pbmcgb2YgYW4gSFRNTCBkb2N1bWVudCB1c2luZyBhIHByb3ZpZGVkIERPTVJ1bm5lckZhY3RvcnkgYW5kIGNvbnZlcnRpbmcgdGhlXG4gKiBtdXRhdGlvbnMgdGhhdCBhcmUgc3RydWN0dXJlZCBhcyByZWZlcmVuY2VzIHRvIGxpdmUgRE9NIGVsZW1lbnRzIGludG8gbWVzc2FnZXMgdGhhdCByZWZlciB0byBlbGVtZW50cyBieSBub2RlSWRzLlxuICovXG5leHBvcnQgY2xhc3MgT2JzZXJ2YWJsZURPTSBpbXBsZW1lbnRzIE9ic2VydmFibGVET01JbnRlcmZhY2Uge1xuICBwcml2YXRlIG5vZGVUb05vZGVJZCA9IG5ldyBNYXA8TGl2ZVZpcnR1YWxET01FbGVtZW50LCBudW1iZXI+KCk7XG4gIHByaXZhdGUgbm9kZUlkVG9Ob2RlID0gbmV3IE1hcDxudW1iZXIsIExpdmVWaXJ0dWFsRE9NRWxlbWVudD4oKTtcbiAgcHJpdmF0ZSByZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQgPSBuZXcgTWFwPEVsZW1lbnQgfCBUZXh0LCBMaXZlVmlydHVhbERPTUVsZW1lbnQ+KCk7XG4gIHByaXZhdGUgaWdub3JlVGV4dE5vZGVzID0gdHJ1ZTtcbiAgcHJpdmF0ZSBjYWxsYmFjazogKG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlLCBvYnNlcnZhYmxlRE9NOiBPYnNlcnZhYmxlRE9NSW50ZXJmYWNlKSA9PiB2b2lkO1xuICBwcml2YXRlIG5leHROb2RlSWQgPSAxO1xuICBwcml2YXRlIGh0bWxQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgZG9tUnVubmVyOiBET01SdW5uZXJJbnRlcmZhY2U7XG4gIHByaXZhdGUgbG9hZGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcHJlTG9hZExvZ01lc3NhZ2VzOiBBcnJheTxMb2dNZXNzYWdlPiA9IFtdO1xuXG4gIHByaXZhdGUgZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcjogTm9kZUpTLlRpbWVvdXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM6IE9ic2VydmFibGVET01QYXJhbWV0ZXJzLFxuICAgIGNhbGxiYWNrOiAobWVzc2FnZTogT2JzZXJ2YWJsZURPTU1lc3NhZ2UsIG9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UpID0+IHZvaWQsXG4gICAgcnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSxcbiAgKSB7XG4gICAgdGhpcy5odG1sUGF0aCA9IG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoO1xuICAgIHRoaXMuaWdub3JlVGV4dE5vZGVzID0gb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaWdub3JlVGV4dE5vZGVzO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgIHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHRoaXMuY2FsbGJhY2soXG4gICAgICAgIHtcbiAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH0sIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLnBpbmdJbnRlcnZhbE1pbGxpc2Vjb25kcyB8fCA1MDAwKTtcblxuICAgIHRoaXMuZG9tUnVubmVyID0gcnVubmVyRmFjdG9yeShcbiAgICAgIG9ic2VydmFibGVET01QYXJhbWV0ZXJzLmh0bWxQYXRoLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMuaHRtbENvbnRlbnRzLFxuICAgICAgb2JzZXJ2YWJsZURPTVBhcmFtZXRlcnMucGFyYW1zLFxuICAgICAgKGRvbVJ1bm5lck1lc3NhZ2U6IERPTVJ1bm5lck1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubG9hZGVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICB0aGlzLmRvbVJ1bm5lci5nZXREb2N1bWVudCgpIGFzIHVua25vd24gYXMgRWxlbWVudCxcbiAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gdmlydHVhbERPTUVsZW1lbnRUb1N0YXRpYyhcbiAgICAgICAgICAgIHRoaXMuZ2V0VmlydHVhbERPTUVsZW1lbnRGb3JSZWFsRWxlbWVudE9yVGhyb3coXG4gICAgICAgICAgICAgIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50KCkgYXMgdW5rbm93biBhcyBFbGVtZW50LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdGhpcy5jYWxsYmFjayhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc25hcHNob3QsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yIChjb25zdCBsb2dNZXNzYWdlIG9mIHRoaXMucHJlTG9hZExvZ01lc3NhZ2VzKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbG9nTWVzc2FnZSxcbiAgICAgICAgICAgICAgICBkb2N1bWVudFRpbWU6IHRoaXMuZ2V0RG9jdW1lbnRUaW1lKCksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnByZUxvYWRMb2dNZXNzYWdlcyA9IFtdO1xuICAgICAgICB9IGVsc2UgaWYgKGRvbVJ1bm5lck1lc3NhZ2UubXV0YXRpb25MaXN0KSB7XG4gICAgICAgICAgdGhpcy5wcm9jZXNzTW9kaWZpY2F0aW9uTGlzdChkb21SdW5uZXJNZXNzYWdlLm11dGF0aW9uTGlzdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZG9tUnVubmVyTWVzc2FnZS5sb2dNZXNzYWdlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLmxvYWRlZCkge1xuICAgICAgICAgICAgdGhpcy5wcmVMb2FkTG9nTWVzc2FnZXMucHVzaChkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBsb2dNZXNzYWdlOiBkb21SdW5uZXJNZXNzYWdlLmxvZ01lc3NhZ2UsXG4gICAgICAgICAgICAgIGRvY3VtZW50VGltZTogdGhpcy5nZXREb2N1bWVudFRpbWUoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRDb25uZWN0ZWRVc2VySWQoY29ubmVjdGlvbklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5kaXNwYXRjaEV2ZW50KFxuICAgICAgbmV3ICh0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5DdXN0b21FdmVudCkoXCJjb25uZWN0ZWRcIiwge1xuICAgICAgICBkZXRhaWw6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUNvbm5lY3RlZFVzZXJJZChjb25uZWN0aW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgKHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkN1c3RvbUV2ZW50KShcImRpc2Nvbm5lY3RlZFwiLCB7XG4gICAgICAgIGRldGFpbDogeyBjb25uZWN0aW9uSWQgfSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NNb2RpZmljYXRpb25MaXN0KG11dGF0aW9uTGlzdDogQXJyYXk8TXV0YXRpb25SZWNvcmQ+KTogdm9pZCB7XG4gICAgaWYgKG11dGF0aW9uTGlzdC5sZW5ndGggPiAxKSB7XG4gICAgICAvLyBUT0RPIChodHRwczovL2dpdGh1Yi5jb20vbW1sLWlvL21tbC9pc3N1ZXMvMTAwKSAtIHdhbGsgYmFjayB0aHJvdWdoIHRoZSByZWNvcmRzIHRvIGRlcml2ZSB0aGUgaW50ZXJtZWRpYXRlXG4gICAgICAvLyAgc3RhdGVzIChlLmcuIGlmIGFuIGF0dHJpYnV0ZSBpcyBsYXRlciBhZGRlZCB0byBhbiBlbGVtZW50IGNyZWF0ZWQgaW4gYW4gZWFybGllciByZWNvcmQgdGhlbiBpdCBzaG91bGQgbm90XG4gICAgICAvLyAgaGF2ZSB0aGF0IGF0dHJpYnV0ZSB3aGVuIHRoZSBlbGVtZW50IGlzIGFkZGVkLiBUaGlzIGlzIGltcG9ydGFudCBhcyBpbmNvcnJlY3QgYXR0cmlidXRlIHNldHMgY2FuIGFmZmVjdFxuICAgICAgLy8gIHZpc2liaWxpdHkgYW5kIGV4cGVjdGVkIGNsaWVudCBwZXJmb3JtYW5jZS5cbiAgICB9XG5cbiAgICBjb25zdCBhbGxNdXRhdGlvblJlY29yZHM6IEFycmF5PFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZD4gPSBbXTtcbiAgICBmb3IgKGNvbnN0IG11dGF0aW9uIG9mIG11dGF0aW9uTGlzdCkge1xuICAgICAgY29uc3QgaWRzUmVjb3JkID0gdGhpcy5jcmVhdGVNdXRhdGlvblJlY29yZChtdXRhdGlvbik7XG4gICAgICBpZiAoaWRzUmVjb3JkKSB7XG4gICAgICAgIGFsbE11dGF0aW9uUmVjb3Jkcy5wdXNoKGlkc1JlY29yZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGFsbE11dGF0aW9uUmVjb3Jkcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmNhbGxiYWNrKFxuICAgICAgICB7XG4gICAgICAgICAgbXV0YXRpb25zOiBhbGxNdXRhdGlvblJlY29yZHMsXG4gICAgICAgICAgZG9jdW1lbnRUaW1lOiB0aGlzLmdldERvY3VtZW50VGltZSgpLFxuICAgICAgICB9LFxuICAgICAgICB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU11dGF0aW9uUmVjb3JkKG11dGF0aW9uOiBNdXRhdGlvblJlY29yZCk6IFN0YXRpY1ZpcnR1YWxET01NdXRhdGlvbklkc1JlY29yZCB8IG51bGwge1xuICAgIGlmICh0aGlzLmlzSWdub3JlZEVsZW1lbnQobXV0YXRpb24udGFyZ2V0IGFzIEVsZW1lbnQgfCBUZXh0KSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgbXV0YXRpb24udHlwZSA9PT0gXCJhdHRyaWJ1dGVzXCIgJiZcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICB0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShtdXRhdGlvbi50YXJnZXQgYXMgRWxlbWVudCB8IFRleHQsIG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhKVxuICAgICkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0Tm9kZSA9IG11dGF0aW9uLnRhcmdldCBhcyBFbGVtZW50IHwgVGV4dDtcbiAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KHRhcmdldE5vZGUpO1xuICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZSB0YXJnZXQgZWxlbWVudCBmb3IgdGhpcyBtdXRhdGlvbiBoYXMgYmVlbiByZW1vdmVkIGluIGEgcHJldmlvdXMgbXV0YXRpb25cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCBwcmV2aW91c1NpYmxpbmdFbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgICBsZXQgaW5zZXJ0aW9uSW5kZXggPSAwO1xuICAgIGNvbnN0IHRvQWRkOiBBcnJheTxMaXZlVmlydHVhbERPTUVsZW1lbnQ+ID0gW107XG4gICAgY29uc3QgcmVtb3ZlZE5vZGVJZHM6IEFycmF5PG51bWJlcj4gPSBbXTtcblxuICAgIGlmIChtdXRhdGlvbi50eXBlID09PSBcImNoaWxkTGlzdFwiKSB7XG4gICAgICBtdXRhdGlvbi5yZW1vdmVkTm9kZXMuZm9yRWFjaCgobm9kZTogTm9kZSkgPT4ge1xuICAgICAgICBjb25zdCBhc0VsZW1lbnRPclRleHQgPSBub2RlIGFzIEVsZW1lbnQgfCBUZXh0O1xuICAgICAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KGFzRWxlbWVudE9yVGV4dCkpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2hpbGRET01FbGVtZW50ID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KGFzRWxlbWVudE9yVGV4dCk7XG4gICAgICAgIGlmICghY2hpbGRET01FbGVtZW50KSB7XG4gICAgICAgICAgLypcbiAgICAgICAgICAgVGhpcyBjYW4gaGFwcGVuIGlmIGVsZW1lbnQgd2FzIGEgY2hpbGQgb2YgYSBwYXJlbnQgZWxlbWVudCwgYnV0IHdhcyBtb3ZlZCB0byBhIG5ldyBwYXJlbnQgaW4gdGhlIHNhbWUgYmF0Y2ggb2YgbXV0YXRpb25zLlxuICAgICAgICAgICBXZSBjYW4gaWdub3JlIHRoaXMgcmVtb3ZhbCBhcyB0aGUgZWxlbWVudCB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IHBsYWNlIGluIHRoZSBoaWVyYXJjaHkgYWxyZWFkeS5cbiAgICAgICAgICAqL1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBpbmRleCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5pbmRleE9mKGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgVGhpcyBjYW4gaGFwcGVuIGlmIGVsZW1lbnQgd2FzIGEgY2hpbGQgb2YgYSBwYXJlbnQgZWxlbWVudCwgYnV0IHdhcyBtb3ZlZCB0byBhIG5ldyBwYXJlbnQgaW4gdGhlIHNhbWUgYmF0Y2ggb2YgbXV0YXRpb25zLlxuICAgICAgICAgICBXZSBjYW4gaWdub3JlIHRoaXMgcmVtb3ZhbCBhcyB0aGUgZWxlbWVudCB3aWxsIGJlIGluIHRoZSBjb3JyZWN0IHBsYWNlIGluIHRoZSBoaWVyYXJjaHkgYWxyZWFkeS5cbiAgICAgICAgICAqL1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZVZpcnR1YWxET01FbGVtZW50KGNoaWxkRE9NRWxlbWVudCk7XG4gICAgICAgICAgICByZW1vdmVkTm9kZUlkcy5wdXNoKGNoaWxkRE9NRWxlbWVudC5ub2RlSWQpO1xuICAgICAgICAgICAgY29uc3QgcmVtb3ZhbCA9IHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgaWYgKHJlbW92YWwubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlbW92YWwgbGVuZ3RoIG5vdCAxXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYgKHJlbW92YWxbMF0ubm9kZUlkICE9PSBjaGlsZERPTUVsZW1lbnQubm9kZUlkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVtb3ZhbCBub2RlIGlkIG1pc21hdGNoXCIpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgbXV0YXRpb24uYWRkZWROb2Rlcy5mb3JFYWNoKChub2RlOiBOb2RlKSA9PiB7XG4gICAgICAgIGNvbnN0IGFzRWxlbWVudE9yVGV4dCA9IG5vZGUgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgIGlmIChhc0VsZW1lbnRPclRleHQucGFyZW50Tm9kZSAhPT0gdGFyZ2V0Tm9kZSkge1xuICAgICAgICAgIC8vIElnbm9yZSB0aGlzIGFkZGl0aW9uIC0gaXQgaXMgbGlrZWx5IG92ZXJyaWRkZW4gYnkgYW4gZWFybGllciBhZGRpdGlvbiBvZiB0aGlzIGVsZW1lbnQgdG8gaXRzIGV2ZW50dWFsIG5vZGUgaW4gdGhpcyBtdXRhdGlvbiBiYXRjaFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghcHJldmlvdXNTaWJsaW5nRWxlbWVudCkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICBFaXRoZXIgdGhlcmUgaXMgbm8gcHJldmlvdXMgZWxlbWVudCAodGhpcyBpcyB0aGUgZmlyc3QgZWxlbWVudClcbiAgICAgICAgICAgICBvciB0aGUgcHJldmlvdXMgZWxlbWVudCBoYXMgbm90IHlldCBiZWVuIGRldGVybWluZWQuXG5cbiAgICAgICAgICAgICBVc2UgdGhlIGN1cnJlbnQgcHJldmlvdXMgc2libGluZyBvZiB0aGlzIGFkZGVkIG5vZGUgYXMgdGhlIGZpcnN0XG4gICAgICAgICAgICAgY2hvaWNlIGZvciB0aGUgcHJldmlvdXMgc2libGluZywgYnV0IG9ubHkgdXNlIHByZXZpb3VzIHNpYmxpbmdzXG4gICAgICAgICAgICAgdGhhdCBhcmUgbm90IGlnbm9yZWQgKGFyZSB0cmFja2VkIGFzIHZpcnR1YWwgZWxlbWVudHMpLlxuICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGxldCBmaXJzdE5vbklnbm9yZWRQcmV2aW91c1NpYmxpbmc6IEVsZW1lbnQgfCBUZXh0IHwgbnVsbCA9XG4gICAgICAgICAgICAgIGFzRWxlbWVudE9yVGV4dC5wcmV2aW91c1NpYmxpbmcgYXMgRWxlbWVudCB8IFRleHQ7XG4gICAgICAgICAgICBsZXQgdmlydHVhbFByZXZpb3VzU2libGluZzogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgd2hpbGUgKGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyAmJiAhdmlydHVhbFByZXZpb3VzU2libGluZykge1xuICAgICAgICAgICAgICB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KFxuICAgICAgICAgICAgICAgIGZpcnN0Tm9uSWdub3JlZFByZXZpb3VzU2libGluZyBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHZpcnR1YWxQcmV2aW91c1NpYmxpbmcgJiZcbiAgICAgICAgICAgICAgICB0YXJnZXRFbGVtZW50LmNoaWxkTm9kZXMuaW5kZXhPZih2aXJ0dWFsUHJldmlvdXNTaWJsaW5nKSA9PT0gLTFcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBlbGVtZW50IGlzIG5vdCBhIGNoaWxkIG9mIHRoZSBwYXJlbnQgZWxlbWVudCAtIGl0IGlzIG5vdCBhIHZhbGlkIHByZXZpb3VzIHNpYmxpbmdcbiAgICAgICAgICAgICAgICB2aXJ0dWFsUHJldmlvdXNTaWJsaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nID0gZmlyc3ROb25JZ25vcmVkUHJldmlvdXNTaWJsaW5nLnByZXZpb3VzU2libGluZyBhc1xuICAgICAgICAgICAgICAgIHwgRWxlbWVudFxuICAgICAgICAgICAgICAgIHwgVGV4dFxuICAgICAgICAgICAgICAgIHwgbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHZpcnR1YWxQcmV2aW91c1NpYmxpbmcpIHtcbiAgICAgICAgICAgICAgcHJldmlvdXNTaWJsaW5nRWxlbWVudCA9IHZpcnR1YWxQcmV2aW91c1NpYmxpbmc7XG4gICAgICAgICAgICAgIGluc2VydGlvbkluZGV4ID0gdGFyZ2V0RWxlbWVudC5jaGlsZE5vZGVzLmluZGV4T2YocHJldmlvdXNTaWJsaW5nRWxlbWVudCk7XG4gICAgICAgICAgICAgIGlmIChpbnNlcnRpb25JbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcmV2aW91cyBzaWJsaW5nIGlzIG5vdCBjdXJyZW50bHkgYSBjaGlsZCBvZiB0aGUgcGFyZW50IGVsZW1lbnRcIik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaW5zZXJ0aW9uSW5kZXggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCA9IHRoaXMuY3JlYXRlVmlydHVhbERPTUVsZW1lbnRXaXRoQ2hpbGRyZW4oXG4gICAgICAgICAgICBhc0VsZW1lbnRPclRleHQsXG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50LFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKGNoaWxkVmlydHVhbERPTUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRvQWRkLnB1c2goY2hpbGRWaXJ0dWFsRE9NRWxlbWVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRhcmdldEVsZW1lbnQuY2hpbGROb2Rlcy5zcGxpY2UoaW5zZXJ0aW9uSW5kZXgsIDAsIC4uLnRvQWRkKTtcblxuICAgICAgaWYgKHRvQWRkLmxlbmd0aCA9PT0gMCAmJiByZW1vdmVkTm9kZUlkcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgLy8gVGhpcyBpcyBhIG5vLW9wIG11dGF0aW9uXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgLy8gQ29udmVydCB0aGUgXCJyZWFsXCIgRE9NIE11dGF0aW9uUmVjb3JkIGludG8gYSBcInZpcnR1YWxcIiBET00gTXV0YXRpb25SZWNvcmQgdGhhdCByZWZlcmVuY2VzIHRoZSBWaXJ0dWFsRE9NRWxlbWVudHNcbiAgICAgIC8vIFRoaXMgaXMgZG9uZSBzbyB0aGF0IHRoZSBzYW1lIHByb2Nlc3MgZm9yIGhhbmRsaW5nIG11dGF0aW9ucyBjYW4gYmUgdXNlZCBmb3IgYm90aCBjaGFuZ2VzIHRvIGEgbGl2ZSBET00gYW5kIGFsc29cbiAgICAgIC8vIHRvIGRpZmZzIGJldHdlZW4gRE9NIHNuYXBzaG90cyB3aGVuIHJlbG9hZGluZ1xuICAgICAgY29uc3QgYWRkZWROb2RlczogQXJyYXk8U3RhdGljVmlydHVhbERPTUVsZW1lbnQ+ID0gdG9BZGQubWFwKHZpcnR1YWxET01FbGVtZW50VG9TdGF0aWMpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJjaGlsZExpc3RcIixcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICBhZGRlZE5vZGVzLFxuICAgICAgICByZW1vdmVkTm9kZUlkcyxcbiAgICAgICAgcHJldmlvdXNTaWJsaW5nSWQ6IHByZXZpb3VzU2libGluZ0VsZW1lbnRcbiAgICAgICAgICA/IChwcmV2aW91c1NpYmxpbmdFbGVtZW50IGFzIExpdmVWaXJ0dWFsRE9NRWxlbWVudCkubm9kZUlkXG4gICAgICAgICAgOiBudWxsLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IG11dGF0aW9uLmF0dHJpYnV0ZU5hbWUhO1xuICAgICAgaWYgKCF0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZSh0YXJnZXROb2RlLCBhdHRyaWJ1dGVOYW1lKSkge1xuICAgICAgICBjb25zdCBwcmV2aW91c1ZhbHVlID0gdGFyZ2V0RWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdO1xuICAgICAgICBjb25zdCBhdHRyaWJ1dGVWYWx1ZSA9ICh0YXJnZXROb2RlIGFzIEVsZW1lbnQpLmdldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lKTtcbiAgICAgICAgaWYgKGF0dHJpYnV0ZVZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBhIG5vLW9wIG11dGF0aW9uXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVsZXRlIHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoYXR0cmlidXRlVmFsdWUgPT09IHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYSBuby1vcCBtdXRhdGlvblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRhcmdldEVsZW1lbnQuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXSA9IGF0dHJpYnV0ZVZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogXCJhdHRyaWJ1dGVzXCIsXG4gICAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgIFthdHRyaWJ1dGVOYW1lXTogYXR0cmlidXRlVmFsdWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG11dGF0aW9uLnR5cGUgPT09IFwiY2hhcmFjdGVyRGF0YVwiKSB7XG4gICAgICB0YXJnZXRFbGVtZW50LnRleHRDb250ZW50ID0gdGFyZ2V0Tm9kZS50ZXh0Q29udGVudCA/IHRhcmdldE5vZGUudGV4dENvbnRlbnQgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImNoYXJhY3RlckRhdGFcIixcbiAgICAgICAgdGFyZ2V0SWQ6IHRhcmdldEVsZW1lbnQubm9kZUlkLFxuICAgICAgICB0ZXh0Q29udGVudDogdGFyZ2V0RWxlbWVudC50ZXh0Q29udGVudCA/IHRhcmdldEVsZW1lbnQudGV4dENvbnRlbnQgOiBcIlwiLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIG11dGF0aW9uIHR5cGU6IFwiICsgbXV0YXRpb24udHlwZSk7XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZVZpcnR1YWxET01FbGVtZW50KHZpcnR1YWxET01FbGVtZW50OiBMaXZlVmlydHVhbERPTUVsZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLm5vZGVJZFRvTm9kZS5kZWxldGUodmlydHVhbERPTUVsZW1lbnQubm9kZUlkKTtcbiAgICB0aGlzLm5vZGVUb05vZGVJZC5kZWxldGUodmlydHVhbERPTUVsZW1lbnQpO1xuICAgIHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LmRlbGV0ZSh2aXJ0dWFsRE9NRWxlbWVudC5yZWFsRWxlbWVudCk7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiB2aXJ0dWFsRE9NRWxlbWVudC5jaGlsZE5vZGVzKSB7XG4gICAgICB0aGlzLnJlbW92ZVZpcnR1YWxET01FbGVtZW50KGNoaWxkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVZpcnR1YWxET01FbGVtZW50V2l0aENoaWxkcmVuKFxuICAgIG5vZGU6IEVsZW1lbnQgfCBUZXh0LFxuICAgIHBhcmVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCxcbiAgKTogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCB7XG4gICAgY29uc3QgW3ZpcnR1YWxFbGVtZW50LCBleGlzdGluZ10gPSB0aGlzLmNyZWF0ZVZpcnR1YWxET01FbGVtZW50KG5vZGUsIHBhcmVudCk7XG4gICAgaWYgKCF2aXJ0dWFsRWxlbWVudCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChleGlzdGluZykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICgobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IChub2RlIGFzIEVsZW1lbnQpLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSAobm9kZSBhcyBFbGVtZW50KS5jaGlsZE5vZGVzW2ldO1xuICAgICAgICBjb25zdCBjaGlsZFZpcnR1YWxFbGVtZW50ID0gdGhpcy5jcmVhdGVWaXJ0dWFsRE9NRWxlbWVudFdpdGhDaGlsZHJlbihcbiAgICAgICAgICBjaGlsZCBhcyBFbGVtZW50IHwgVGV4dCxcbiAgICAgICAgICB2aXJ0dWFsRWxlbWVudCxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNoaWxkVmlydHVhbEVsZW1lbnQpIHtcbiAgICAgICAgICB2aXJ0dWFsRWxlbWVudC5jaGlsZE5vZGVzLnB1c2goY2hpbGRWaXJ0dWFsRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdmlydHVhbEVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVZpcnR1YWxET01FbGVtZW50KFxuICAgIG5vZGU6IEVsZW1lbnQgfCBUZXh0LFxuICAgIHBhcmVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50IHwgbnVsbCxcbiAgKTogW0xpdmVWaXJ0dWFsRE9NRWxlbWVudCB8IG51bGwsIGJvb2xlYW5dIHtcbiAgICBpZiAodGhpcy5pc0lnbm9yZWRFbGVtZW50KG5vZGUpKSB7XG4gICAgICByZXR1cm4gW251bGwsIGZhbHNlXTtcbiAgICB9XG4gICAgaWYgKCFub2RlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgYXNzaWduIG5vZGUgaWQgdG8gbnVsbFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5yZWFsRWxlbWVudFRvVmlydHVhbEVsZW1lbnQuZ2V0KG5vZGUpO1xuICAgIGlmIChleGlzdGluZ1ZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8qXG4gICAgICAgVGhpcyBpcyB1bmRlc2lyYWJsZSwgYnV0IHRoZSBiYXRjaGluZyBvZiBtdXRhdGlvbnMgZnJvbSBNdXRhdGlvbk9ic2VydmVyIG1lYW5zIHRoYXRcbiAgICAgICB0aGlzIG5vZGUgY291bGQgYmUgYmVpbmcgYWRkZWQgaW4gYSBtdXRhdGlvbiBhZnRlciBhIG11dGF0aW9uIG9mIGEgcGFyZW50IHRoYXQgd2hlblxuICAgICAgIGhhbmRsZWQgcmVzdWx0aW5nIGluIGFkZGluZyB0aGlzIG5vZGUgZWFybHkuXG4gICAgICAqL1xuICAgICAgcmV0dXJuIFtleGlzdGluZ1ZhbHVlLCB0cnVlXTtcbiAgICB9XG5cbiAgICBjb25zdCBhdHRyaWJ1dGVzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gICAgaWYgKChub2RlIGFzIGFueSkuYXR0cmlidXRlcykge1xuICAgICAgY29uc3QgYXNIVE1MRWxlbWVudCA9IG5vZGUgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBhc0hUTUxFbGVtZW50LmdldEF0dHJpYnV0ZU5hbWVzKCkpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBhc0hUTUxFbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpO1xuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOdWxsIGF0dHJpYnV0ZSB2YWx1ZSBmb3Iga2V5OiBcIiArIGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmlzSWdub3JlZEF0dHJpYnV0ZShub2RlLCBrZXkpKSB7XG4gICAgICAgICAgYXR0cmlidXRlc1trZXldID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBub2RlSWQgPSB0aGlzLm5leHROb2RlSWQrKztcbiAgICBjb25zdCB2aXJ0dWFsRWxlbWVudDogTGl2ZVZpcnR1YWxET01FbGVtZW50ID0ge1xuICAgICAgbm9kZUlkLFxuICAgICAgdGFnOiBub2RlLm5vZGVOYW1lLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIGNoaWxkTm9kZXM6IFtdLFxuICAgICAgcmVhbEVsZW1lbnQ6IG5vZGUsXG4gICAgICBwYXJlbnQsXG4gICAgfTtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLlRleHQgJiYgbm9kZS50ZXh0Q29udGVudCkge1xuICAgICAgdmlydHVhbEVsZW1lbnQudGV4dENvbnRlbnQgPSBub2RlLnRleHRDb250ZW50O1xuICAgIH1cbiAgICB0aGlzLm5vZGVUb05vZGVJZC5zZXQodmlydHVhbEVsZW1lbnQsIG5vZGVJZCk7XG4gICAgdGhpcy5ub2RlSWRUb05vZGUuc2V0KG5vZGVJZCwgdmlydHVhbEVsZW1lbnQpO1xuICAgIHRoaXMucmVhbEVsZW1lbnRUb1ZpcnR1YWxFbGVtZW50LnNldChub2RlLCB2aXJ0dWFsRWxlbWVudCk7XG4gICAgcmV0dXJuIFt2aXJ0dWFsRWxlbWVudCwgZmFsc2VdO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRWaXJ0dWFsRE9NRWxlbWVudEZvclJlYWxFbGVtZW50T3JUaHJvdyhcbiAgICByZWFsRWxlbWVudDogRWxlbWVudCB8IFRleHQsXG4gICk6IExpdmVWaXJ0dWFsRE9NRWxlbWVudCB7XG4gICAgY29uc3QgdmlydHVhbEVsZW1lbnQgPSB0aGlzLnJlYWxFbGVtZW50VG9WaXJ0dWFsRWxlbWVudC5nZXQocmVhbEVsZW1lbnQpO1xuICAgIGlmICghdmlydHVhbEVsZW1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVmlydHVhbCBlbGVtZW50IG5vdCBmb3VuZCBmb3IgcmVhbCBlbGVtZW50YCk7XG4gICAgfVxuICAgIHJldHVybiB2aXJ0dWFsRWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgaXNJZ25vcmVkRWxlbWVudChub2RlOiBFbGVtZW50IHwgVGV4dCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlnbm9yZVRleHROb2RlcyAmJiBub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuVGV4dCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgdGhpcy5kb21SdW5uZXIuZ2V0V2luZG93KCkuSFRNTFNjcmlwdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHRoaXMuZG9tUnVubmVyLmdldFdpbmRvdygpLkNvbW1lbnQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGlzSWdub3JlZEF0dHJpYnV0ZShub2RlOiBFbGVtZW50IHwgVGV4dCwgYXR0cmlidXRlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZU5hbWUuc3RhcnRzV2l0aChcIm9uXCIpO1xuICB9XG5cbiAgcHVibGljIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgIGNvbm5lY3Rpb25JZDogbnVtYmVyLFxuICAgIHJlbW90ZUV2ZW50OiBPYnNlcnZhYmxlRE9NUmVtb3RlRXZlbnQsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGRvbU5vZGUgPSB0aGlzLm5vZGVJZFRvTm9kZS5nZXQocmVtb3RlRXZlbnQubm9kZUlkKTtcbiAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG5vZGUgSUQgaW4gcmVtb3RlIGV2ZW50OiBcIiArIHJlbW90ZUV2ZW50Lm5vZGVJZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGRvbU5vZGUgaW5zdGFuY2VvZiB0aGlzLmRvbVJ1bm5lci5nZXRXaW5kb3coKS5UZXh0KSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJDYW5ub3QgZGlzcGF0Y2ggcmVtb3RlIGV2ZW50IHRvIHRleHQgbm9kZVwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRvbVJ1bm5lci5kaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZChcbiAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgIGRvbU5vZGUucmVhbEVsZW1lbnQgYXMgRWxlbWVudCxcbiAgICAgIHJlbW90ZUV2ZW50LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpIHtcbiAgICBjbGVhckludGVydmFsKHRoaXMuZG9jdW1lbnRUaW1lSW50ZXJ2YWxUaW1lcik7XG4gICAgdGhpcy5kb21SdW5uZXIuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREb2N1bWVudFRpbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZG9tUnVubmVyLmdldERvY3VtZW50VGltZSgpO1xuICB9XG59XG4iLCAiaW1wb3J0IHtcbiAgT2JzZXJ2YWJsZURPTUludGVyZmFjZSxcbiAgT2JzZXJ2YWJsZURPTU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbn0gZnJvbSBcIi4vT2JzZXJ2YWJsZURPTUludGVyZmFjZVwiO1xuXG5leHBvcnQgY29uc3QgQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwiYWRkQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSA9IFwicmVtb3ZlQ29ubmVjdGVkVXNlcklkXCI7XG5leHBvcnQgY29uc3QgRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUgPVxuICBcImRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkXCI7XG5leHBvcnQgY29uc3QgRE9NX01FU1NBR0VfVFlQRSA9IFwiZG9tXCI7XG5cbmV4cG9ydCB0eXBlIEFkZENvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2UgPSB7XG4gIHR5cGU6IHR5cGVvZiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIERpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFO1xuICBjb25uZWN0aW9uSWQ6IG51bWJlcjtcbiAgZXZlbnQ6IE9ic2VydmFibGVET01SZW1vdGVFdmVudDtcbn07XG5cbmV4cG9ydCB0eXBlIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSA9XG4gIHwgQWRkQ29ubmVjdGVkVXNlcklkTWVzc2FnZVxuICB8IFJlbW92ZUNvbm5lY3RlZFVzZXJJZE1lc3NhZ2VcbiAgfCBEaXNwYXRjaFJlbW90ZUV2ZW50RnJvbUNvbm5lY3Rpb25JZE1lc3NhZ2U7XG5cbnR5cGUgRE9NTWVzc2FnZSA9IHtcbiAgdHlwZTogdHlwZW9mIERPTV9NRVNTQUdFX1RZUEU7XG4gIG1lc3NhZ2U6IE9ic2VydmFibGVET01NZXNzYWdlO1xufTtcblxuZXhwb3J0IHR5cGUgRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UgPSBET01NZXNzYWdlO1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlNZXNzYWdlVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2UoXG4gIG1lc3NhZ2U6IFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZSxcbiAgaW5zdGFuY2U6IE9ic2VydmFibGVET01JbnRlcmZhY2UsXG4pIHtcbiAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gQUREX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSkge1xuICAgIGluc3RhbmNlLmFkZENvbm5lY3RlZFVzZXJJZChtZXNzYWdlLmNvbm5lY3Rpb25JZCk7XG4gIH0gZWxzZSBpZiAobWVzc2FnZS50eXBlID09PSBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UucmVtb3ZlQ29ubmVjdGVkVXNlcklkKG1lc3NhZ2UuY29ubmVjdGlvbklkKTtcbiAgfSBlbHNlIGlmIChtZXNzYWdlLnR5cGUgPT09IERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFKSB7XG4gICAgaW5zdGFuY2UuZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQobWVzc2FnZS5jb25uZWN0aW9uSWQsIG1lc3NhZ2UuZXZlbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2YWJsZURPTUludGVyZmFjZVRvTWVzc2FnZVNlbmRlcihcbiAgc2VuZGVyOiAobWVzc2FnZTogVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlKSA9PiB2b2lkLFxuICBkaXNwb3NlOiAoKSA9PiB2b2lkLFxuKSB7XG4gIGNvbnN0IHJlbW90ZU9ic2VydmFibGVET006IE9ic2VydmFibGVET01JbnRlcmZhY2UgPSB7XG4gICAgYWRkQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIGRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKFxuICAgICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgICByZW1vdGVFdmVudDogT2JzZXJ2YWJsZURPTVJlbW90ZUV2ZW50LFxuICAgICk6IHZvaWQge1xuICAgICAgc2VuZGVyKHtcbiAgICAgICAgdHlwZTogRElTUEFUQ0hfUkVNT1RFX0VWRU5UX0ZST01fQ09OTkVDVElPTl9JRF9NRVNTQUdFX1RZUEUsXG4gICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgZXZlbnQ6IHJlbW90ZUV2ZW50LFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkaXNwb3NlKCk6IHZvaWQge1xuICAgICAgZGlzcG9zZSgpO1xuICAgIH0sXG4gICAgcmVtb3ZlQ29ubmVjdGVkVXNlcklkKGNvbm5lY3Rpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICBzZW5kZXIoe1xuICAgICAgICB0eXBlOiBSRU1PVkVfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuICByZXR1cm4gcmVtb3RlT2JzZXJ2YWJsZURPTTtcbn1cbiIsICJpbXBvcnQgeyBET01SdW5uZXJGYWN0b3J5LCBET01SdW5uZXJJbnRlcmZhY2UsIERPTVJ1bm5lck1lc3NhZ2UgfSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbVwiO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZURPTVJlbW90ZUV2ZW50IH0gZnJvbSBcIkBtbWwtaW8vb2JzZXJ2YWJsZS1kb20tY29tbW9uXCI7XG5cbmV4cG9ydCBjb25zdCBXZWJCcm93c2VyRE9NUnVubmVyRmFjdG9yeTogRE9NUnVubmVyRmFjdG9yeSA9IChcbiAgaHRtbFBhdGg6IHN0cmluZyxcbiAgaHRtbENvbnRlbnRzOiBzdHJpbmcsXG4gIHBhcmFtczogb2JqZWN0LFxuICBjYWxsYmFjazogKG11dGF0aW9uTGlzdDogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZCxcbik6IERPTVJ1bm5lckludGVyZmFjZSA9PiB7XG4gIHJldHVybiBuZXcgV2ViQnJvd3NlckRPTVJ1bm5lcihwYXJhbXMsIGNhbGxiYWNrKTtcbn07XG5cbmxldCBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKTtcbmlmIChkb2N1bWVudC50aW1lbGluZSAmJiBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSkge1xuICBkb2N1bWVudExvYWRUaW1lID0gRGF0ZS5ub3coKSAtIChkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXIpO1xufVxuXG4vKipcbiAqIFdlYkJyb3dzZXJET01SdW5uZXIgaXMgYSBET01SdW5uZXJJbnRlcmZhY2UgaW1wbGVtZW50YXRpb24gdGhhdCBydW5zIGluIGEgd2ViIGJyb3dzZXIuIEl0IGlzIGludGVuZGVkIHRvIGJlIHJ1biBpblxuICogYW4gaWZyYW1lIGFuZCB0aGUgcGFyZW50IHdpbmRvdyBpcyBleHBlY3RlZCB0byBzZW5kIG1lc3NhZ2VzIHRvIGl0IHRvIGRpc3BhdGNoIGV2ZW50cyBhbmQgdG8gcmVjZWl2ZSBtdXRhdGlvblxuICogbWVzc2FnZXMuXG4gKlxuICogSXQgaXMgZXhwZWN0ZWQgdGhhdCB0aGUgZG9jdW1lbnQgY29udGVudHMgaXMgaW5qZWN0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhpcyBjbGFzcyBpcyBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJCcm93c2VyRE9NUnVubmVyIGltcGxlbWVudHMgRE9NUnVubmVySW50ZXJmYWNlIHtcbiAgcHJpdmF0ZSBtdXRhdGlvbk9ic2VydmVyOiBNdXRhdGlvbk9ic2VydmVyO1xuICBwcml2YXRlIGNhbGxiYWNrOiAoZG9tUnVubmVyTWVzc2FnZTogRE9NUnVubmVyTWVzc2FnZSkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IG9iamVjdCwgY2FsbGJhY2s6IChkb21SdW5uZXJNZXNzYWdlOiBET01SdW5uZXJNZXNzYWdlKSA9PiB2b2lkKSB7XG4gICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuXG4gICAgLy8gRm9yd2FyZCBjb25zb2xlIG1lc3NhZ2VzXG4gICAgZm9yIChjb25zdCBsZXZlbCBvZiBbXCJlcnJvclwiLCBcIndhcm5cIiwgXCJpbmZvXCIsIFwibG9nXCJdIGFzIGNvbnN0KSB7XG4gICAgICBjb25zdCBkZWZhdWx0Rm4gPSB3aW5kb3cuY29uc29sZVtsZXZlbF07XG5cbiAgICAgIHdpbmRvdy5jb25zb2xlW2xldmVsXSA9ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgICBsb2dNZXNzYWdlOiB7XG4gICAgICAgICAgICBsZXZlbCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGFyZ3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGRlZmF1bHRGbiguLi5hcmdzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRm9yd2FyZCB1bmNhdWdodCBlcnJvcnNcbiAgICB3aW5kb3cub25lcnJvciA9IChtZXNzYWdlLCBzb3VyY2UsIGxpbmUsIGNvbHVtbiwgZXJyb3IpID0+IHtcbiAgICAgIGNhbGxiYWNrKHtcbiAgICAgICAgbG9nTWVzc2FnZToge1xuICAgICAgICAgIGxldmVsOiBcInN5c3RlbVwiLFxuICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgdHlwZTogZXJyb3I/Lm5hbWUsXG4gICAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICAgIGNvbHVtbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBsZXQgZGlkU2VuZExvYWQgPSBmYWxzZTtcblxuICAgIHRoaXMubXV0YXRpb25PYnNlcnZlciA9IG5ldyB3aW5kb3cuTXV0YXRpb25PYnNlcnZlcigobXV0YXRpb25MaXN0KSA9PiB7XG4gICAgICBpZiAoIWRvY3VtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghZGlkU2VuZExvYWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXV0YXRpb25PYnNlcnZlciBjYWxsZWQgYmVmb3JlIGxvYWRcIik7XG4gICAgICB9XG4gICAgICB0aGlzLmNhbGxiYWNrKHtcbiAgICAgICAgbXV0YXRpb25MaXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAod2luZG93IGFzIGFueSkucGFyYW1zID0gcGFyYW1zO1xuXG4gICAgY29uc3QgZmluaXNoTG9hZCA9ICgpID0+IHtcbiAgICAgIGlmIChkaWRTZW5kTG9hZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmaW5pc2hMb2FkIGNhbGxlZCB0d2ljZVwiKTtcbiAgICAgIH1cbiAgICAgIGRpZFNlbmRMb2FkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2FsbGJhY2soe1xuICAgICAgICBsb2FkZWQ6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIHRoaXMubXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHdpbmRvdy5kb2N1bWVudCwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICBzZXRUaW1lb3V0KGZpbmlzaExvYWQsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgZmluaXNoTG9hZCk7XG4gICAgfVxuICB9XG5cbiAgZGlzcGF0Y2hSZW1vdGVFdmVudEZyb21Db25uZWN0aW9uSWQoXG4gICAgY29ubmVjdGlvbklkOiBudW1iZXIsXG4gICAgcmVhbEVsZW1lbnQ6IEVsZW1lbnQsXG4gICAgcmVtb3RlRXZlbnQ6IE9ic2VydmFibGVET01SZW1vdGVFdmVudCxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgYnViYmxlcyA9IHJlbW90ZUV2ZW50LmJ1YmJsZXMgfHwgZmFsc2U7XG4gICAgY29uc3QgcmVtb3RlRXZlbnRPYmplY3QgPSBuZXcgQ3VzdG9tRXZlbnQocmVtb3RlRXZlbnQubmFtZSwge1xuICAgICAgYnViYmxlcyxcbiAgICAgIGRldGFpbDogeyAuLi5yZW1vdGVFdmVudC5wYXJhbXMsIGNvbm5lY3Rpb25JZCB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgZXZlbnRUeXBlTG93ZXJDYXNlID0gcmVtb3RlRXZlbnQubmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gVE9ETyAtIGNoZWNrIGlmIHRoZXJlIGFyZSBvdGhlciBldmVudHMgdGhhdCBhdXRvbWF0aWNhbGx5IHdpcmUgdXAgc2ltaWxhcmx5IHRvIGNsaWNrLT5vbmNsaWNrIGFuZCBhdm9pZCB0aG9zZSB0b29cbiAgICBpZiAoZXZlbnRUeXBlTG93ZXJDYXNlICE9PSBcImNsaWNrXCIpIHtcbiAgICAgIGNvbnN0IGhhbmRsZXJBdHRyaWJ1dGVOYW1lID0gXCJvblwiICsgZXZlbnRUeXBlTG93ZXJDYXNlO1xuICAgICAgY29uc3QgaGFuZGxlckF0dHJpYnV0ZVZhbHVlID0gcmVhbEVsZW1lbnQuZ2V0QXR0cmlidXRlKGhhbmRsZXJBdHRyaWJ1dGVOYW1lKTtcbiAgICAgIGlmIChoYW5kbGVyQXR0cmlidXRlVmFsdWUpIHtcbiAgICAgICAgLy8gVGhpcyBldmVudCBpcyBkZWZpbmVkIGFzIGFuIEhUTUwgZXZlbnQgYXR0cmlidXRlLlxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZuID0gRnVuY3Rpb24oXCJldmVudFwiLCBoYW5kbGVyQXR0cmlidXRlVmFsdWUpO1xuICAgICAgICAgIGZuLmFwcGx5KHJlYWxFbGVtZW50LCBbcmVtb3RlRXZlbnRPYmplY3RdKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBydW5uaW5nIGV2ZW50IGhhbmRsZXI6XCIsIGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGlzcGF0Y2ggdGhlIGV2ZW50IHZpYSBKYXZhU2NyaXB0LlxuICAgIHJlYWxFbGVtZW50LmRpc3BhdGNoRXZlbnQocmVtb3RlRXZlbnRPYmplY3QpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAvLyBUT0RPIC0gaGFuZGxlIGRpc3Bvc2VcbiAgfVxuXG4gIGdldERvY3VtZW50KCk6IERvY3VtZW50IHtcbiAgICByZXR1cm4gZG9jdW1lbnQ7XG4gIH1cblxuICBnZXREb2N1bWVudFRpbWUoKTogbnVtYmVyIHtcbiAgICBjb25zdCBkYXRlQmFzZWREb2N1bWVudFRpbWUgPSBEYXRlLm5vdygpIC0gZG9jdW1lbnRMb2FkVGltZTtcbiAgICBpZiAoZG9jdW1lbnQudGltZWxpbmUgJiYgZG9jdW1lbnQudGltZWxpbmUuY3VycmVudFRpbWUpIHtcbiAgICAgIGNvbnN0IHRpbWUgPSBkb2N1bWVudC50aW1lbGluZS5jdXJyZW50VGltZSBhcyBudW1iZXI7XG4gICAgICBpZiAoZGF0ZUJhc2VkRG9jdW1lbnRUaW1lID4gdGltZSArIDUwMCkge1xuICAgICAgICAvLyBUaGUgdGltZWxpbmUgY2FuIGJlIFwibGVmdCBiZWhpbmRcIiBpZiB0aGUgdGFiIGlzIGJhY2tncm91bmRlZCBmb3IgYSB3aGlsZSwgc28gd2UgdXNlIHRoZSBkYXRlLWJhc2VkIHRpbWVcbiAgICAgICAgLy8gaW5zdGVhZC4gSWYvd2hlbiB0aGUgZG9jdW1lbnQgaXMgYnJvdWdodCBiYWNrIGludG8gdGhlIGZvcmVncm91bmQsIHRoZSB0aW1lbGluZSB3aWxsIGNhdGNoIHVwLlxuICAgICAgICByZXR1cm4gZGF0ZUJhc2VkRG9jdW1lbnRUaW1lO1xuICAgICAgfVxuICAgICAgLy8gSWRlYWwgY2FzZSAtIHVzZSB0aGUgZG9jdW1lbnQudGltZWxpbmUgYXMgaXQncyB3aGF0IGlzIGF2YWlsYWJsZSB0byB0aGUgZG9jdW1lbnQgc2NyaXB0XG4gICAgICByZXR1cm4gdGltZTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGVCYXNlZERvY3VtZW50VGltZTtcbiAgfVxuXG4gIC8vIFRPRE8gLSByZXNvbHZlIHR5cGVzIChXaW5kb3cgbmVlZHMgdG8gZXhwb3NlIGNsYXNzZXMgc3VjaCBhcyBDdXN0b21FdmVudCBhcyBwcm9wZXJ0aWVzKVxuICBnZXRXaW5kb3coKTogYW55IHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9XG59XG4iLCAiaW1wb3J0IHsgT2JzZXJ2YWJsZURPTSB9IGZyb20gXCJAbW1sLWlvL29ic2VydmFibGUtZG9tL3NyYy9PYnNlcnZhYmxlRE9NXCI7XG5pbXBvcnQge1xuICBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFLFxuICBESVNQQVRDSF9SRU1PVEVfRVZFTlRfRlJPTV9DT05ORUNUSU9OX0lEX01FU1NBR0VfVFlQRSxcbiAgRE9NX01FU1NBR0VfVFlQRSxcbiAgRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UsXG4gIE9ic2VydmFibGVET01NZXNzYWdlLFxuICBPYnNlcnZhYmxlRE9NUGFyYW1ldGVycyxcbiAgUkVNT1ZFX0NPTk5FQ1RFRF9VU0VSX0lEX01FU1NBR0VfVFlQRSxcbiAgVG9PYnNlcnZhYmxlRE9NSW5zdGFuY2VNZXNzYWdlLFxufSBmcm9tIFwiQG1tbC1pby9vYnNlcnZhYmxlLWRvbS1jb21tb25cIjtcblxuaW1wb3J0IHsgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3RvcnkgfSBmcm9tIFwiLi9XZWJCcm93c2VyRE9NUnVubmVyXCI7XG5cbi8qKlxuICogVGhpcyBpcyBydW4gaW4gdGhlIGlmcmFtZSB0aGF0IHdpbGwgZXhlY3V0ZSB0aGUgZG9jdW1lbnQgc2NyaXB0IHRvIHNldHVwIHRoZSBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBtZXNzYWdlcyBhbmRcbiAqIG9ic2VydmluZyBvZiBET00gbXV0YXRpb24gdXNpbmcgdGhlIFdlYkJyb3dzZXJET01SdW5uZXIgY2xhc3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cElmcmFtZVdlYlJ1bm5lcihhcmdzU3RyaW5nOiBzdHJpbmcpIHtcbiAgY29uc3Qgb2JzZXJ2YWJsZURPTVBhcmFtcyA9IEpTT04ucGFyc2UoYXRvYihhcmdzU3RyaW5nKSkgYXMgT2JzZXJ2YWJsZURPTVBhcmFtZXRlcnM7XG5cbiAgY29uc3Qgc2VuZE1lc3NhZ2VUb0hhbmRsZXIgPSAobWVzc2FnZTogRnJvbU9ic2VydmFibGVET01JbnN0YW5jZU1lc3NhZ2UpID0+IHtcbiAgICB3aW5kb3cucGFyZW50LnBvc3RNZXNzYWdlKEpTT04uc3RyaW5naWZ5KG1lc3NhZ2UpLCBcIipcIik7XG4gIH07XG5cbiAgY29uc3Qgb2JzZXJ2YWJsZURPTSA9IG5ldyBPYnNlcnZhYmxlRE9NKFxuICAgIHtcbiAgICAgIC4uLm9ic2VydmFibGVET01QYXJhbXMsXG4gICAgICBodG1sQ29udGVudHM6IFwiXCIsIC8vIFRoaXMgbXVzdCBiZSBlbXB0eSBhcyB0aGUgY29udGVudHMgYXJlIGFzc3VtZWQgdG8gYmUgcHJvdmlkZWQgYnkgdGhlIHNyY2RvY1xuICAgIH0sXG4gICAgKG9ic2VydmFibGVET01NZXNzYWdlOiBPYnNlcnZhYmxlRE9NTWVzc2FnZSkgPT4ge1xuICAgICAgc2VuZE1lc3NhZ2VUb0hhbmRsZXIoe1xuICAgICAgICB0eXBlOiBET01fTUVTU0FHRV9UWVBFLFxuICAgICAgICBtZXNzYWdlOiBvYnNlcnZhYmxlRE9NTWVzc2FnZSxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgV2ViQnJvd3NlckRPTVJ1bm5lckZhY3RvcnksXG4gICk7XG5cbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChlKSA9PiB7XG4gICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShlLmRhdGEpIGFzIFRvT2JzZXJ2YWJsZURPTUluc3RhbmNlTWVzc2FnZTtcbiAgICBzd2l0Y2ggKHBhcnNlZC50eXBlKSB7XG4gICAgICBjYXNlIERJU1BBVENIX1JFTU9URV9FVkVOVF9GUk9NX0NPTk5FQ1RJT05fSURfTUVTU0FHRV9UWVBFOlxuICAgICAgICBvYnNlcnZhYmxlRE9NLmRpc3BhdGNoUmVtb3RlRXZlbnRGcm9tQ29ubmVjdGlvbklkKHBhcnNlZC5jb25uZWN0aW9uSWQsIHBhcnNlZC5ldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBBRERfQ09OTkVDVEVEX1VTRVJfSURfTUVTU0FHRV9UWVBFOlxuICAgICAgICBvYnNlcnZhYmxlRE9NLmFkZENvbm5lY3RlZFVzZXJJZChwYXJzZWQuY29ubmVjdGlvbklkKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFJFTU9WRV9DT05ORUNURURfVVNFUl9JRF9NRVNTQUdFX1RZUEU6XG4gICAgICAgIG9ic2VydmFibGVET00ucmVtb3ZlQ29ubmVjdGVkVXNlcklkKHBhcnNlZC5jb25uZWN0aW9uSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmtub3duIG1lc3NhZ2UgdHlwZVwiLCBwYXJzZWQpO1xuICAgIH1cbiAgfSk7XG59XG4iLCAiaW1wb3J0IHsgc2V0dXBJZnJhbWVXZWJSdW5uZXIgfSBmcm9tIFwiLi9JZnJhbWVXZWJSdW5uZXJcIjtcblxuY29uc3QgYXJncyA9ICh3aW5kb3cgYXMgYW55KS5hcmdzO1xuc2V0dXBJZnJhbWVXZWJSdW5uZXIoYXJncyk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBSU8sU0FBUywwQkFBMEIsSUFBb0Q7QUFDNUYsU0FBTztBQUFBLElBQ0wsUUFBUSxHQUFHO0FBQUEsSUFDWCxLQUFLLEdBQUc7QUFBQSxJQUNSLFlBQVksT0FBTyxPQUFPLENBQUMsR0FBRyxHQUFHLFVBQVU7QUFBQTtBQUFBLElBQzNDLFlBQVksR0FBRyxXQUFXLElBQUksQ0FBQyxVQUFVLDBCQUEwQixLQUFLLENBQUM7QUFBQSxJQUN6RSxhQUFhLEdBQUc7QUFBQSxFQUNsQjtBQUNGOzs7QUN3Q08sSUFBTSxnQkFBTixNQUFzRDtBQUFBLEVBYzNELFlBQ0UseUJBQ0EsVUFDQSxlQUNBO0FBakJGLFNBQVEsZUFBZSxvQkFBSSxJQUFtQztBQUM5RCxTQUFRLGVBQWUsb0JBQUksSUFBbUM7QUFDOUQsU0FBUSw4QkFBOEIsb0JBQUksSUFBMkM7QUFDckYsU0FBUSxrQkFBa0I7QUFFMUIsU0FBUSxhQUFhO0FBR3JCLFNBQVEsU0FBUztBQUNqQixTQUFRLHFCQUF3QyxDQUFDO0FBUy9DLFNBQUssV0FBVyx3QkFBd0I7QUFDeEMsU0FBSyxrQkFBa0Isd0JBQXdCO0FBQy9DLFNBQUssV0FBVztBQUVoQixTQUFLLDRCQUE0QixZQUFZLE1BQU07QUFDakQsV0FBSztBQUFBLFFBQ0g7QUFBQSxVQUNFLGNBQWMsS0FBSyxnQkFBZ0I7QUFBQSxRQUNyQztBQUFBLFFBQ0E7QUFBQSxNQUNGO0FBQUEsSUFDRixHQUFHLHdCQUF3Qiw0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UyxHQUFHO0FBQ1Ysa0JBQVEsTUFBTSxnQ0FBZ0MsQ0FBQztBQUFBLFFBQ2pEO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFHQSxnQkFBWSxjQUFjLGlCQUFpQjtBQUFBLEVBQzdDO0FBQUEsRUFFQSxVQUFnQjtBQUFBLEVBRWhCO0FBQUEsRUFFQSxjQUF3QjtBQUN0QixXQUFPO0FBQUEsRUFDVDtBQUFBLEVBRUEsa0JBQTBCO0FBQ3hCLFVBQU0sd0JBQXdCLEtBQUssSUFBSSxJQUFJO0FBQzNDLFFBQUksU0FBUyxZQUFZLFNBQVMsU0FBUyxhQUFhO0FBQ3RELFlBQU0sT0FBTyxTQUFTLFNBQVM7QUFDL0IsVUFBSSx3QkFBd0IsT0FBTyxLQUFLO0FBR3RDLGVBQU87QUFBQSxNQUNUO0FBRUEsYUFBTztBQUFBLElBQ1Q7QUFDQSxXQUFPO0FBQUEsRUFDVDtBQUFBO0FBQUEsRUFHQSxZQUFpQjtBQUNmLFdBQU87QUFBQSxFQUNUO0FBQ0Y7OztBQy9JTyxTQUFTLHFCQUFxQixZQUFvQjtBQUN2RCxRQUFNLHNCQUFzQixLQUFLLE1BQU0sS0FBSyxVQUFVLENBQUM7QUFFdkQsUUFBTSx1QkFBdUIsQ0FBQyxZQUE4QztBQUMxRSxXQUFPLE9BQU8sWUFBWSxLQUFLLFVBQVUsT0FBTyxHQUFHLEdBQUc7QUFBQSxFQUN4RDtBQUVBLFFBQU0sZ0JBQWdCLElBQUk7QUFBQSxJQUN4QjtBQUFBLE1BQ0UsR0FBRztBQUFBLE1BQ0gsY0FBYztBQUFBO0FBQUEsSUFDaEI7QUFBQSxJQUNBLENBQUMseUJBQStDO0FBQzlDLDJCQUFxQjtBQUFBLFFBQ25CLE1BQU07QUFBQSxRQUNOLFNBQVM7QUFBQSxNQUNYLENBQUM7QUFBQSxJQUNIO0FBQUEsSUFDQTtBQUFBLEVBQ0Y7QUFFQSxTQUFPLGlCQUFpQixXQUFXLENBQUMsTUFBTTtBQUN4QyxVQUFNLFNBQVMsS0FBSyxNQUFNLEVBQUUsSUFBSTtBQUNoQyxZQUFRLE9BQU8sTUFBTTtBQUFBLE1BQ25CLEtBQUs7QUFDSCxzQkFBYyxvQ0FBb0MsT0FBTyxjQUFjLE9BQU8sS0FBSztBQUNuRjtBQUFBLE1BQ0YsS0FBSztBQUNILHNCQUFjLG1CQUFtQixPQUFPLFlBQVk7QUFDcEQ7QUFBQSxNQUNGLEtBQUs7QUFDSCxzQkFBYyxzQkFBc0IsT0FBTyxZQUFZO0FBQ3ZEO0FBQUEsTUFDRjtBQUNFLGdCQUFRLE1BQU0sd0JBQXdCLE1BQU07QUFBQSxJQUNoRDtBQUFBLEVBQ0YsQ0FBQztBQUNIOzs7QUNyREEsSUFBTSxPQUFRLE9BQWU7QUFDN0IscUJBQXFCLElBQUk7IiwKICAibmFtZXMiOiBbImFyZ3MiXQp9Cg==\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.visibility = \"hidden\";\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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",
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.19.0",
3
+ "version": "0.19.2",
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.19.0",
24
- "@mml-io/observable-dom-common": "^0.19.0"
23
+ "@mml-io/networked-dom-web": "^0.19.2",
24
+ "@mml-io/observable-dom-common": "^0.19.2"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@mml-io/networked-dom-web-runner-iframe": "file:../networked-dom-web-runner-iframe",
@@ -29,5 +29,5 @@
29
29
  "jest-environment-jsdom": "29.7.0",
30
30
  "jest-expect-message": "1.1.3"
31
31
  },
32
- "gitHead": "edf5cd7afa62c6ad8b8bcaa70dda9ded4a51cc3b"
32
+ "gitHead": "e1926507273fca794f77211d76fbcef178318987"
33
33
  }