25 lines
107 KiB
JavaScript
25 lines
107 KiB
JavaScript
"use strict";
|
|
/*
|
|
* ATTENTION: An "eval-source-map" devtool has been used.
|
|
* This devtool is neither made for production nor for readable output files.
|
|
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
|
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
* or disable the default devtool with "devtool: false".
|
|
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
*/
|
|
exports.id = "vendor-chunks/@lexical+selection@0.41.0";
|
|
exports.ids = ["vendor-chunks/@lexical+selection@0.41.0"];
|
|
exports.modules = {
|
|
|
|
/***/ "(rsc)/./node_modules/.pnpm/@lexical+selection@0.41.0/node_modules/@lexical/selection/LexicalSelection.dev.mjs":
|
|
/*!***************************************************************************************************************!*\
|
|
!*** ./node_modules/.pnpm/@lexical+selection@0.41.0/node_modules/@lexical/selection/LexicalSelection.dev.mjs ***!
|
|
\***************************************************************************************************************/
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ $addNodeStyle: () => (/* binding */ $addNodeStyle),\n/* harmony export */ $cloneWithProperties: () => (/* reexport safe */ lexical__WEBPACK_IMPORTED_MODULE_0__.$cloneWithProperties),\n/* harmony export */ $copyBlockFormatIndent: () => (/* binding */ $copyBlockFormatIndent),\n/* harmony export */ $ensureForwardRangeSelection: () => (/* binding */ $ensureForwardRangeSelection),\n/* harmony export */ $forEachSelectedTextNode: () => (/* binding */ $forEachSelectedTextNode),\n/* harmony export */ $getComputedStyleForElement: () => (/* binding */ $getComputedStyleForElement),\n/* harmony export */ $getComputedStyleForParent: () => (/* binding */ $getComputedStyleForParent),\n/* harmony export */ $getSelectionStyleValueForProperty: () => (/* binding */ $getSelectionStyleValueForProperty),\n/* harmony export */ $isAtNodeEnd: () => (/* binding */ $isAtNodeEnd),\n/* harmony export */ $isParentElementRTL: () => (/* binding */ $isParentElementRTL),\n/* harmony export */ $isParentRTL: () => (/* binding */ $isParentRTL),\n/* harmony export */ $moveCaretSelection: () => (/* binding */ $moveCaretSelection),\n/* harmony export */ $moveCharacter: () => (/* binding */ $moveCharacter),\n/* harmony export */ $patchStyleText: () => (/* binding */ $patchStyleText),\n/* harmony export */ $selectAll: () => (/* reexport safe */ lexical__WEBPACK_IMPORTED_MODULE_0__.$selectAll),\n/* harmony export */ $setBlocksType: () => (/* binding */ $setBlocksType),\n/* harmony export */ $shouldOverrideDefaultCharacterSelection: () => (/* binding */ $shouldOverrideDefaultCharacterSelection),\n/* harmony export */ $sliceSelectedTextNodeContent: () => (/* binding */ $sliceSelectedTextNodeContent),\n/* harmony export */ $trimTextContentFromAnchor: () => (/* binding */ $trimTextContentFromAnchor),\n/* harmony export */ $wrapNodes: () => (/* binding */ $wrapNodes),\n/* harmony export */ createDOMRange: () => (/* binding */ createDOMRange),\n/* harmony export */ createRectsFromDOMRange: () => (/* binding */ createRectsFromDOMRange),\n/* harmony export */ getCSSFromStyleObject: () => (/* binding */ getCSSFromStyleObject),\n/* harmony export */ getStyleObjectFromCSS: () => (/* binding */ getStyleObjectFromCSS),\n/* harmony export */ trimTextContentFromAnchor: () => (/* binding */ trimTextContentFromAnchor)\n/* harmony export */ });\n/* harmony import */ var lexical__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lexical */ \"(rsc)/./node_modules/.pnpm/lexical@0.41.0/node_modules/lexical/Lexical.dev.mjs\");\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n\n\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n// Do not require this module directly! Use normal `invariant` calls.\n\nfunction formatDevErrorMessage(message) {\n throw new Error(message);\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\nconst CSS_TO_STYLES = new Map();\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nfunction getDOMTextNode(element) {\n let node = element;\n while (node != null) {\n if (node.nodeType === Node.TEXT_NODE) {\n return node;\n }\n node = node.firstChild;\n }\n return null;\n}\nfunction getDOMIndexWithinParent(node) {\n const parent = node.parentNode;\n if (parent == null) {\n throw new Error('Should never happen');\n }\n return [parent, Array.from(parent.childNodes).indexOf(node)];\n}\n\n/**\n * Creates a selection range for the DOM.\n * @param editor - The lexical editor.\n * @param anchorNode - The anchor node of a selection.\n * @param _anchorOffset - The amount of space offset from the anchor to the focus.\n * @param focusNode - The current focus.\n * @param _focusOffset - The amount of space offset from the focus to the anchor.\n * @returns The range of selection for the DOM that was created.\n */\nfunction createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffset) {\n const anchorKey = anchorNode.getKey();\n const focusKey = focusNode.getKey();\n const range = document.createRange();\n let anchorDOM = editor.getElementByKey(anchorKey);\n let focusDOM = editor.getElementByKey(focusKey);\n let anchorOffset = _anchorOffset;\n let focusOffset = _focusOffset;\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(anchorNode)) {\n anchorDOM = getDOMTextNode(anchorDOM);\n }\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(focusNode)) {\n focusDOM = getDOMTextNode(focusDOM);\n }\n if (anchorNode === undefined || focusNode === undefined || anchorDOM === null || focusDOM === null) {\n return null;\n }\n if (anchorDOM.nodeName === 'BR') {\n [anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);\n }\n if (focusDOM.nodeName === 'BR') {\n [focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);\n }\n const firstChild = anchorDOM.firstChild;\n if (anchorDOM === focusDOM && firstChild != null && firstChild.nodeName === 'BR' && anchorOffset === 0 && focusOffset === 0) {\n focusOffset = 1;\n }\n try {\n range.setStart(anchorDOM, anchorOffset);\n range.setEnd(focusDOM, focusOffset);\n } catch (_e) {\n return null;\n }\n if (range.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {\n // Range is backwards, we need to reverse it\n range.setStart(focusDOM, focusOffset);\n range.setEnd(anchorDOM, anchorOffset);\n }\n return range;\n}\n\n/**\n * Creates DOMRects, generally used to help the editor find a specific location on the screen.\n * @param editor - The lexical editor\n * @param range - A fragment of a document that can contain nodes and parts of text nodes.\n * @returns The selectionRects as an array.\n */\nfunction createRectsFromDOMRange(editor, range) {\n const rootElement = editor.getRootElement();\n if (rootElement === null) {\n return [];\n }\n const rootRect = rootElement.getBoundingClientRect();\n const computedStyle = getComputedStyle(rootElement);\n const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);\n const selectionRects = Array.from(range.getClientRects());\n let selectionRectsLength = selectionRects.length;\n //sort rects from top left to bottom right.\n selectionRects.sort((a, b) => {\n const top = a.top - b.top;\n // Some rects match position closely, but not perfectly,\n // so we give a 3px tolerance.\n if (Math.abs(top) <= 3) {\n return a.left - b.left;\n }\n return top;\n });\n let prevRect;\n for (let i = 0; i < selectionRectsLength; i++) {\n const selectionRect = selectionRects[i];\n // Exclude rects that overlap preceding Rects in the sorted list.\n const isOverlappingRect = prevRect && prevRect.top <= selectionRect.top && prevRect.top + prevRect.height > selectionRect.top && prevRect.left + prevRect.width > selectionRect.left;\n // Exclude selections that span the entire element\n const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;\n if (isOverlappingRect || selectionSpansElement) {\n selectionRects.splice(i--, 1);\n selectionRectsLength--;\n continue;\n }\n prevRect = selectionRect;\n }\n return selectionRects;\n}\n\n/**\n * Creates an object containing all the styles and their values provided in the CSS string.\n * @param css - The CSS string of styles and their values.\n * @returns The styleObject containing all the styles and their values.\n */\nfunction getStyleObjectFromRawCSS(css) {\n const styleObject = {};\n if (!css) {\n return styleObject;\n }\n const styles = css.split(';');\n for (const style of styles) {\n if (style !== '') {\n const [key, value] = style.split(/:([^]+)/); // split on first colon\n if (key && value) {\n styleObject[key.trim()] = value.trim();\n }\n }\n }\n return styleObject;\n}\n\n/**\n * Given a CSS string, returns an object from the style cache.\n * @param css - The CSS property as a string.\n * @returns The value of the given CSS property.\n */\nfunction getStyleObjectFromCSS(css) {\n let value = CSS_TO_STYLES.get(css);\n if (value === undefined) {\n value = getStyleObjectFromRawCSS(css);\n CSS_TO_STYLES.set(css, value);\n }\n {\n // Freeze the value in DEV to prevent accidental mutations\n Object.freeze(value);\n }\n return value;\n}\n\n/**\n * Gets the CSS styles from the style object.\n * @param styles - The style object containing the styles to get.\n * @returns A string containing the CSS styles and their values.\n */\nfunction getCSSFromStyleObject(styles) {\n let css = '';\n for (const style in styles) {\n if (style) {\n css += `${style}: ${styles[style]};`;\n }\n }\n return css;\n}\n\n/**\n * Gets the computed DOM styles of the element.\n * @param element - The node to check the styles for.\n * @returns the computed styles of the element or null if there is no DOM element or no default view for the document.\n */\nfunction $getComputedStyleForElement(element) {\n const editor = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getEditor)();\n const domElement = editor.getElementByKey(element.getKey());\n if (domElement === null) {\n return null;\n }\n const view = domElement.ownerDocument.defaultView;\n if (view === null) {\n return null;\n }\n return view.getComputedStyle(domElement);\n}\n\n/**\n * Gets the computed DOM styles of the parent of the node.\n * @param node - The node to check its parent's styles for.\n * @returns the computed styles of the node or null if there is no DOM element or no default view for the document.\n */\nfunction $getComputedStyleForParent(node) {\n const parent = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootNode)(node) ? node : node.getParentOrThrow();\n return $getComputedStyleForElement(parent);\n}\n\n/**\n * Determines whether a node's parent is RTL.\n * @param node - The node to check whether it is RTL.\n * @returns whether the node is RTL.\n */\nfunction $isParentRTL(node) {\n const styles = $getComputedStyleForParent(node);\n return styles !== null && styles.direction === 'rtl';\n}\n\n/**\n * Generally used to append text content to HTML and JSON. Grabs the text content and \"slices\"\n * it to be generated into the new TextNode.\n * @param selection - The selection containing the node whose TextNode is to be edited.\n * @param textNode - The TextNode to be edited.\n * @param mutates - 'clone' to return a clone before mutating, 'self' to update in-place\n * @returns The updated TextNode or clone.\n */\nfunction $sliceSelectedTextNodeContent(selection, textNode, mutates = 'self') {\n const anchorAndFocus = selection.getStartEndPoints();\n if (textNode.isSelected(selection) && !(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTokenOrSegmented)(textNode) && anchorAndFocus !== null) {\n const [anchor, focus] = anchorAndFocus;\n const isBackward = selection.isBackward();\n const anchorNode = anchor.getNode();\n const focusNode = focus.getNode();\n const isAnchor = textNode.is(anchorNode);\n const isFocus = textNode.is(focusNode);\n if (isAnchor || isFocus) {\n const [anchorOffset, focusOffset] = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getCharacterOffsets)(selection);\n const isSame = anchorNode.is(focusNode);\n const isFirst = textNode.is(isBackward ? focusNode : anchorNode);\n const isLast = textNode.is(isBackward ? anchorNode : focusNode);\n let startOffset = 0;\n let endOffset = undefined;\n if (isSame) {\n startOffset = anchorOffset > focusOffset ? focusOffset : anchorOffset;\n endOffset = anchorOffset > focusOffset ? anchorOffset : focusOffset;\n } else if (isFirst) {\n const offset = isBackward ? focusOffset : anchorOffset;\n startOffset = offset;\n endOffset = undefined;\n } else if (isLast) {\n const offset = isBackward ? anchorOffset : focusOffset;\n startOffset = 0;\n endOffset = offset;\n }\n\n // NOTE: This mutates __text directly because the primary use case is to\n // modify a $cloneWithProperties node that should never be added\n // to the EditorState so we must not call getWritable via setTextContent\n const text = textNode.__text.slice(startOffset, endOffset);\n if (text !== textNode.__text) {\n if (mutates === 'clone') {\n textNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$cloneWithPropertiesEphemeral)(textNode);\n }\n textNode.__text = text;\n }\n }\n }\n return textNode;\n}\n\n/**\n * Determines if the current selection is at the end of the node.\n * @param point - The point of the selection to test.\n * @returns true if the provided point offset is in the last possible position, false otherwise.\n */\nfunction $isAtNodeEnd(point) {\n if (point.type === 'text') {\n return point.offset === point.getNode().getTextContentSize();\n }\n const node = point.getNode();\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node)) {\n formatDevErrorMessage(`isAtNodeEnd: node must be a TextNode or ElementNode`);\n }\n return point.offset === node.getChildrenSize();\n}\n\n/**\n * Trims text from a node in order to shorten it, eg. to enforce a text's max length. If it deletes text\n * that is an ancestor of the anchor then it will leave 2 indents, otherwise, if no text content exists, it deletes\n * the TextNode. It will move the focus to either the end of any left over text or beginning of a new TextNode.\n * @param editor - The lexical editor.\n * @param anchor - The anchor of the current selection, where the selection should be pointing.\n * @param delCount - The amount of characters to delete. Useful as a dynamic variable eg. textContentSize - maxLength;\n */\nfunction $trimTextContentFromAnchor(editor, anchor, delCount) {\n // Work from the current selection anchor point\n let currentNode = anchor.getNode();\n let remaining = delCount;\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(currentNode)) {\n const descendantNode = currentNode.getDescendantByIndex(anchor.offset);\n if (descendantNode !== null) {\n currentNode = descendantNode;\n }\n }\n while (remaining > 0 && currentNode !== null) {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(currentNode)) {\n const lastDescendant = currentNode.getLastDescendant();\n if (lastDescendant !== null) {\n currentNode = lastDescendant;\n }\n }\n let nextNode = currentNode.getPreviousSibling();\n let additionalElementWhitespace = 0;\n if (nextNode === null) {\n let parent = currentNode.getParentOrThrow();\n let parentSibling = parent.getPreviousSibling();\n while (parentSibling === null) {\n parent = parent.getParent();\n if (parent === null) {\n nextNode = null;\n break;\n }\n parentSibling = parent.getPreviousSibling();\n }\n if (parent !== null) {\n additionalElementWhitespace = parent.isInline() ? 0 : 2;\n nextNode = parentSibling;\n }\n }\n let text = currentNode.getTextContent();\n // If the text is empty, we need to consider adding in two line breaks to match\n // the content if we were to get it from its parent.\n if (text === '' && (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(currentNode) && !currentNode.isInline()) {\n // TODO: should this be handled in core?\n text = '\\n\\n';\n }\n const currentNodeSize = text.length;\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(currentNode) || remaining >= currentNodeSize) {\n const parent = currentNode.getParent();\n currentNode.remove();\n if (parent != null && parent.getChildrenSize() === 0 && !(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootNode)(parent)) {\n parent.remove();\n }\n remaining -= currentNodeSize + additionalElementWhitespace;\n currentNode = nextNode;\n } else {\n const key = currentNode.getKey();\n // See if we can just revert it to what was in the last editor state\n const prevTextContent = editor.getEditorState().read(() => {\n const prevNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getNodeByKey)(key);\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(prevNode) && prevNode.isSimpleText()) {\n return prevNode.getTextContent();\n }\n return null;\n });\n const offset = currentNodeSize - remaining;\n const slicedText = text.slice(0, offset);\n if (prevTextContent !== null && prevTextContent !== text) {\n const prevSelection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getPreviousSelection)();\n let target = currentNode;\n if (!currentNode.isSimpleText()) {\n const textNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createTextNode)(prevTextContent);\n currentNode.replace(textNode);\n target = textNode;\n } else {\n currentNode.setTextContent(prevTextContent);\n }\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(prevSelection) && prevSelection.isCollapsed()) {\n const prevOffset = prevSelection.anchor.offset;\n target.select(prevOffset, prevOffset);\n }\n } else if (currentNode.isSimpleText()) {\n // Split text\n const isSelected = anchor.key === key;\n let anchorOffset = anchor.offset;\n // Move offset to end if it's less than the remaining number, otherwise\n // we'll have a negative splitStart.\n if (anchorOffset < remaining) {\n anchorOffset = currentNodeSize;\n }\n const splitStart = isSelected ? anchorOffset - remaining : 0;\n const splitEnd = isSelected ? anchorOffset : offset;\n if (isSelected && splitStart === 0) {\n const [excessNode] = currentNode.splitText(splitStart, splitEnd);\n excessNode.remove();\n } else {\n const [, excessNode] = currentNode.splitText(splitStart, splitEnd);\n excessNode.remove();\n }\n } else {\n const textNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createTextNode)(slicedText);\n currentNode.replace(textNode);\n }\n remaining = 0;\n }\n }\n}\n\n/**\n * Gets the TextNode's style object and adds the styles to the CSS.\n * @param node - The TextNode to add styles to.\n */\nfunction $addNodeStyle(node) {\n const CSSText = node.getStyle();\n const styles = getStyleObjectFromRawCSS(CSSText);\n CSS_TO_STYLES.set(CSSText, styles);\n}\n\n/**\n * Applies the provided styles to the given TextNode, ElementNode, or\n * collapsed RangeSelection.\n *\n * @param target - The TextNode, ElementNode, or collapsed RangeSelection to apply the styles to\n * @param patch - The patch to apply, which can include multiple styles. \\\\{CSSProperty: value\\\\} . Can also accept a function that returns the new property value.\n */\nfunction $patchStyle(target, patch) {\n if (!((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(target) ? target.isCollapsed() : (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(target) || (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(target))) {\n formatDevErrorMessage(`$patchStyle must only be called with a TextNode, ElementNode, or collapsed RangeSelection`);\n }\n const prevStyles = getStyleObjectFromCSS((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(target) ? target.style : (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(target) ? target.getStyle() : target.getTextStyle());\n const newStyles = Object.entries(patch).reduce((styles, [key, value]) => {\n if (typeof value === 'function') {\n styles[key] = value(prevStyles[key], target);\n } else if (value === null) {\n delete styles[key];\n } else {\n styles[key] = value;\n }\n return styles;\n }, {\n ...prevStyles\n });\n const newCSSText = getCSSFromStyleObject(newStyles);\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(target) || (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(target)) {\n target.setStyle(newCSSText);\n } else {\n target.setTextStyle(newCSSText);\n }\n CSS_TO_STYLES.set(newCSSText, newStyles);\n}\n\n/**\n * Applies the provided styles to the TextNodes in the provided Selection.\n * Will update partially selected TextNodes by splitting the TextNode and applying\n * the styles to the appropriate one.\n * @param selection - The selected node(s) to update.\n * @param patch - The patch to apply, which can include multiple styles. \\\\{CSSProperty: value\\\\} . Can also accept a function that returns the new property value.\n */\nfunction $patchStyleText(selection, patch) {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection) && selection.isCollapsed()) {\n $patchStyle(selection, patch);\n const emptyNode = selection.anchor.getNode();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(emptyNode) && emptyNode.isEmpty()) {\n $patchStyle(emptyNode, patch);\n }\n }\n $forEachSelectedTextNode(textNode => {\n $patchStyle(textNode, patch);\n });\n const nodes = selection.getNodes();\n if (nodes.length > 0) {\n const patchedElementKeys = new Set();\n for (const node of nodes) {\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) || !node.canBeEmpty() || node.getChildrenSize() !== 0) {\n continue;\n }\n const key = node.getKey();\n if (patchedElementKeys.has(key)) {\n continue;\n }\n patchedElementKeys.add(key);\n $patchStyle(node, patch);\n }\n }\n}\nfunction $forEachSelectedTextNode(fn) {\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if (!selection) {\n return;\n }\n const slicedTextNodes = new Map();\n const getSliceIndices = node => slicedTextNodes.get(node.getKey()) || [0, node.getTextContentSize()];\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection)) {\n for (const slice of (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$caretRangeFromSelection)(selection).getTextSlices()) {\n if (slice) {\n slicedTextNodes.set(slice.caret.origin.getKey(), slice.getSliceIndices());\n }\n }\n }\n const selectedNodes = selection.getNodes();\n for (const selectedNode of selectedNodes) {\n if (!((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(selectedNode) && selectedNode.canHaveFormat())) {\n continue;\n }\n const [startOffset, endOffset] = getSliceIndices(selectedNode);\n // No actual text is selected, so do nothing.\n if (endOffset === startOffset) {\n continue;\n }\n\n // The entire node is selected or a token/segment, so just format it\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTokenOrSegmented)(selectedNode) || startOffset === 0 && endOffset === selectedNode.getTextContentSize()) {\n fn(selectedNode);\n } else {\n // The node is partially selected, so split it into two or three nodes\n // and style the selected one.\n const splitNodes = selectedNode.splitText(startOffset, endOffset);\n const replacement = splitNodes[startOffset === 0 ? 0 : 1];\n fn(replacement);\n }\n }\n // Prior to NodeCaret #7046 this would have been a side-effect\n // so we do this for test compatibility.\n // TODO: we may want to consider simplifying by removing this\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection) && selection.anchor.type === 'text' && selection.focus.type === 'text' && selection.anchor.key === selection.focus.key) {\n $ensureForwardRangeSelection(selection);\n }\n}\n\n/**\n * Ensure that the given RangeSelection is not backwards. If it\n * is backwards, then the anchor and focus points will be swapped\n * in-place. Ensuring that the selection is a writable RangeSelection\n * is the responsibility of the caller (e.g. in a read-only context\n * you will want to clone $getSelection() before using this).\n *\n * @param selection a writable RangeSelection\n */\nfunction $ensureForwardRangeSelection(selection) {\n if (selection.isBackward()) {\n const {\n anchor,\n focus\n } = selection;\n // stash for the in-place swap\n const {\n key,\n offset,\n type\n } = anchor;\n anchor.set(focus.key, focus.offset, focus.type);\n focus.set(key, offset, type);\n }\n}\n\nfunction $copyBlockFormatIndent(srcNode, destNode) {\n const format = srcNode.getFormatType();\n const indent = srcNode.getIndent();\n if (format !== destNode.getFormatType()) {\n destNode.setFormat(format);\n }\n if (indent !== destNode.getIndent()) {\n destNode.setIndent(indent);\n }\n}\n\n/**\n * Converts all nodes in the selection that are of one block type to another.\n * @param selection - The selected blocks to be converted.\n * @param $createElement - The function that creates the node. eg. $createParagraphNode.\n * @param $afterCreateElement - The function that updates the new node based on the previous one ($copyBlockFormatIndent by default)\n */\nfunction $setBlocksType(selection, $createElement, $afterCreateElement = $copyBlockFormatIndent) {\n if (selection === null) {\n return;\n }\n // Selections tend to not include their containing blocks so we effectively\n // expand it here\n const anchorAndFocus = selection.getStartEndPoints();\n const blockMap = new Map();\n let newSelection = null;\n if (anchorAndFocus) {\n const [anchor, focus] = anchorAndFocus;\n newSelection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createRangeSelection)();\n newSelection.anchor.set(anchor.key, anchor.offset, anchor.type);\n newSelection.focus.set(focus.key, focus.offset, focus.type);\n const anchorBlock = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$findMatchingParent)(anchor.getNode(), lexical__WEBPACK_IMPORTED_MODULE_0__.INTERNAL_$isBlock);\n const focusBlock = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$findMatchingParent)(focus.getNode(), lexical__WEBPACK_IMPORTED_MODULE_0__.INTERNAL_$isBlock);\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(anchorBlock)) {\n blockMap.set(anchorBlock.getKey(), anchorBlock);\n }\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(focusBlock)) {\n blockMap.set(focusBlock.getKey(), focusBlock);\n }\n }\n for (const node of selection.getNodes()) {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) && (0,lexical__WEBPACK_IMPORTED_MODULE_0__.INTERNAL_$isBlock)(node)) {\n blockMap.set(node.getKey(), node);\n } else if (anchorAndFocus === null) {\n const ancestorBlock = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$findMatchingParent)(node, lexical__WEBPACK_IMPORTED_MODULE_0__.INTERNAL_$isBlock);\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(ancestorBlock)) {\n blockMap.set(ancestorBlock.getKey(), ancestorBlock);\n }\n }\n }\n for (const [key, prevNode] of blockMap) {\n const element = $createElement();\n $afterCreateElement(prevNode, element);\n prevNode.replace(element, true);\n if (newSelection) {\n if (key === newSelection.anchor.key) {\n newSelection.anchor.set(element.getKey(), newSelection.anchor.offset, newSelection.anchor.type);\n }\n if (key === newSelection.focus.key) {\n newSelection.focus.set(element.getKey(), newSelection.focus.offset, newSelection.focus.type);\n }\n }\n }\n if (newSelection && selection.is((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)())) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$setSelection)(newSelection);\n }\n}\nfunction isPointAttached(point) {\n return point.getNode().isAttached();\n}\nfunction $removeParentEmptyElements(startingNode) {\n let node = startingNode;\n while (node !== null && !(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(node)) {\n const latest = node.getLatest();\n const parentNode = node.getParent();\n if (latest.getChildrenSize() === 0) {\n node.remove(true);\n }\n node = parentNode;\n }\n}\n\n/**\n * @deprecated In favor of $setBlockTypes\n * Wraps all nodes in the selection into another node of the type returned by createElement.\n * @param selection - The selection of nodes to be wrapped.\n * @param createElement - A function that creates the wrapping ElementNode. eg. $createParagraphNode.\n * @param wrappingElement - An element to append the wrapped selection and its children to.\n */\nfunction $wrapNodes(selection, createElement, wrappingElement = null) {\n const anchorAndFocus = selection.getStartEndPoints();\n const anchor = anchorAndFocus ? anchorAndFocus[0] : null;\n const nodes = selection.getNodes();\n const nodesLength = nodes.length;\n if (anchor !== null && (nodesLength === 0 || nodesLength === 1 && anchor.type === 'element' && anchor.getNode().getChildrenSize() === 0)) {\n const target = anchor.type === 'text' ? anchor.getNode().getParentOrThrow() : anchor.getNode();\n const children = target.getChildren();\n let element = createElement();\n element.setFormat(target.getFormatType());\n element.setIndent(target.getIndent());\n children.forEach(child => element.append(child));\n if (wrappingElement) {\n element = wrappingElement.append(element);\n }\n target.replace(element);\n return;\n }\n let topLevelNode = null;\n let descendants = [];\n for (let i = 0; i < nodesLength; i++) {\n const node = nodes[i];\n // Determine whether wrapping has to be broken down into multiple chunks. This can happen if the\n // user selected multiple Root-like nodes that have to be treated separately as if they are\n // their own branch. I.e. you don't want to wrap a whole table, but rather the contents of each\n // of each of the cell nodes.\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(node)) {\n $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);\n descendants = [];\n topLevelNode = node;\n } else if (topLevelNode === null || topLevelNode !== null && (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$hasAncestor)(node, topLevelNode)) {\n descendants.push(node);\n } else {\n $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);\n descendants = [node];\n }\n }\n $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);\n}\n\n/**\n * Wraps each node into a new ElementNode.\n * @param selection - The selection of nodes to wrap.\n * @param nodes - An array of nodes, generally the descendants of the selection.\n * @param nodesLength - The length of nodes.\n * @param createElement - A function that creates the wrapping ElementNode. eg. $createParagraphNode.\n * @param wrappingElement - An element to wrap all the nodes into.\n * @returns\n */\nfunction $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingElement = null) {\n if (nodes.length === 0) {\n return;\n }\n const firstNode = nodes[0];\n const elementMapping = new Map();\n const elements = [];\n // The below logic is to find the right target for us to\n // either insertAfter/insertBefore/append the corresponding\n // elements to. This is made more complicated due to nested\n // structures.\n let target = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(firstNode) ? firstNode : firstNode.getParentOrThrow();\n if (target.isInline()) {\n target = target.getParentOrThrow();\n }\n let targetIsPrevSibling = false;\n while (target !== null) {\n const prevSibling = target.getPreviousSibling();\n if (prevSibling !== null) {\n target = prevSibling;\n targetIsPrevSibling = true;\n break;\n }\n target = target.getParentOrThrow();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(target)) {\n break;\n }\n }\n const emptyElements = new Set();\n\n // Find any top level empty elements\n for (let i = 0; i < nodesLength; i++) {\n const node = nodes[i];\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) && node.getChildrenSize() === 0) {\n emptyElements.add(node.getKey());\n }\n }\n const movedNodes = new Set();\n\n // Move out all leaf nodes into our elements array.\n // If we find a top level empty element, also move make\n // an element for that.\n for (let i = 0; i < nodesLength; i++) {\n const node = nodes[i];\n let parent = node.getParent();\n if (parent !== null && parent.isInline()) {\n parent = parent.getParent();\n }\n if (parent !== null && (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isLeafNode)(node) && !movedNodes.has(node.getKey())) {\n const parentKey = parent.getKey();\n if (elementMapping.get(parentKey) === undefined) {\n const targetElement = createElement();\n targetElement.setFormat(parent.getFormatType());\n targetElement.setIndent(parent.getIndent());\n elements.push(targetElement);\n elementMapping.set(parentKey, targetElement);\n // Move node and its siblings to the new\n // element.\n parent.getChildren().forEach(child => {\n targetElement.append(child);\n movedNodes.add(child.getKey());\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(child)) {\n // Skip nested leaf nodes if the parent has already been moved\n child.getChildrenKeys().forEach(key => movedNodes.add(key));\n }\n });\n $removeParentEmptyElements(parent);\n }\n } else if (emptyElements.has(node.getKey())) {\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node)) {\n formatDevErrorMessage(`Expected node in emptyElements to be an ElementNode`);\n }\n const targetElement = createElement();\n targetElement.setFormat(node.getFormatType());\n targetElement.setIndent(node.getIndent());\n elements.push(targetElement);\n node.remove(true);\n }\n }\n if (wrappingElement !== null) {\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n wrappingElement.append(element);\n }\n }\n let lastElement = null;\n\n // If our target is Root-like, let's see if we can re-adjust\n // so that the target is the first child instead.\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(target)) {\n if (targetIsPrevSibling) {\n if (wrappingElement !== null) {\n target.insertAfter(wrappingElement);\n } else {\n for (let i = elements.length - 1; i >= 0; i--) {\n const element = elements[i];\n target.insertAfter(element);\n }\n }\n } else {\n const firstChild = target.getFirstChild();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(firstChild)) {\n target = firstChild;\n }\n if (firstChild === null) {\n if (wrappingElement) {\n target.append(wrappingElement);\n } else {\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n target.append(element);\n lastElement = element;\n }\n }\n } else {\n if (wrappingElement !== null) {\n firstChild.insertBefore(wrappingElement);\n } else {\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n firstChild.insertBefore(element);\n lastElement = element;\n }\n }\n }\n }\n } else {\n if (wrappingElement) {\n target.insertAfter(wrappingElement);\n } else {\n for (let i = elements.length - 1; i >= 0; i--) {\n const element = elements[i];\n target.insertAfter(element);\n lastElement = element;\n }\n }\n }\n const prevSelection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getPreviousSelection)();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(prevSelection) && isPointAttached(prevSelection.anchor) && isPointAttached(prevSelection.focus)) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$setSelection)(prevSelection.clone());\n } else if (lastElement !== null) {\n lastElement.selectEnd();\n } else {\n selection.dirty = true;\n }\n}\n\n/**\n * Tests if the selection's parent element has vertical writing mode.\n * @param selection - The selection whose parent to test.\n * @returns true if the selection's parent has vertical writing mode (writing-mode: vertical-rl), false otherwise.\n */\nfunction $isEditorVerticalOrientation(selection) {\n const computedStyle = $getComputedStyle(selection);\n return computedStyle !== null && computedStyle.writingMode === 'vertical-rl';\n}\n\n/**\n * Gets the computed DOM styles of the parent of the selection's anchor node.\n * @param selection - The selection to check the styles for.\n * @returns the computed styles of the node or null if there is no DOM element or no default view for the document.\n */\nfunction $getComputedStyle(selection) {\n const anchorNode = selection.anchor.getNode();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(anchorNode)) {\n return $getComputedStyleForElement(anchorNode);\n }\n return $getComputedStyleForParent(anchorNode);\n}\n\n/**\n * Determines if the default character selection should be overridden. Used with DecoratorNodes\n * @param selection - The selection whose default character selection may need to be overridden.\n * @param isBackward - Is the selection backwards (the focus comes before the anchor)?\n * @returns true if it should be overridden, false if not.\n */\nfunction $shouldOverrideDefaultCharacterSelection(selection, isBackward) {\n const isVertical = $isEditorVerticalOrientation(selection);\n\n // In vertical writing mode, we adjust the direction for correct caret movement\n let adjustedIsBackward = isVertical ? !isBackward : isBackward;\n\n // In right-to-left writing mode, we invert the direction for correct caret movement\n if ($isParentElementRTL(selection)) {\n adjustedIsBackward = !adjustedIsBackward;\n }\n const focusCaret = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$caretFromPoint)(selection.focus, adjustedIsBackward ? 'previous' : 'next');\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isExtendableTextPointCaret)(focusCaret)) {\n return false;\n }\n for (const nextCaret of (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$extendCaretToRange)(focusCaret)) {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isChildCaret)(nextCaret)) {\n return !nextCaret.origin.isInline();\n } else if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(nextCaret.origin)) {\n continue;\n } else if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isDecoratorNode)(nextCaret.origin)) {\n return true;\n }\n break;\n }\n return false;\n}\n\n/**\n * Moves the selection according to the arguments.\n * @param selection - The selected text or nodes.\n * @param isHoldingShift - Is the shift key being held down during the operation.\n * @param isBackward - Is the selection selected backwards (the focus comes before the anchor)?\n * @param granularity - The distance to adjust the current selection.\n */\nfunction $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {\n selection.modify(isHoldingShift ? 'extend' : 'move', isBackward, granularity);\n}\n\n/**\n * Tests a parent element for right to left direction.\n * @param selection - The selection whose parent is to be tested.\n * @returns true if the selections' parent element has a direction of 'rtl' (right to left), false otherwise.\n */\nfunction $isParentElementRTL(selection) {\n const computedStyle = $getComputedStyle(selection);\n return computedStyle !== null && computedStyle.direction === 'rtl';\n}\n\n/**\n * Moves selection by character according to arguments.\n * @param selection - The selection of the characters to move.\n * @param isHoldingShift - Is the shift key being held down during the operation.\n * @param isBackward - Is the selection backward (the focus comes before the anchor)?\n */\nfunction $moveCharacter(selection, isHoldingShift, isBackward) {\n const isRTL = $isParentElementRTL(selection);\n const isVertical = $isEditorVerticalOrientation(selection);\n\n // In vertical-rl writing mode, arrow key directions need to be flipped\n // to match the visual flow of text (top to bottom, right to left)\n let adjustedIsBackward;\n if (isVertical) {\n // In vertical-rl mode, we need to completely invert the direction\n // Left arrow (backward) should move down (forward)\n // Right arrow (forward) should move up (backward)\n adjustedIsBackward = !isBackward;\n } else if (isRTL) {\n // In horizontal RTL mode, use the standard RTL behavior\n adjustedIsBackward = !isBackward;\n } else {\n // Standard LTR horizontal text\n adjustedIsBackward = isBackward;\n }\n\n // Apply the direction adjustment to move the caret\n $moveCaretSelection(selection, isHoldingShift, adjustedIsBackward, 'character');\n}\n\n/**\n * Returns the current value of a CSS property for Nodes, if set. If not set, it returns the defaultValue.\n * @param node - The node whose style value to get.\n * @param styleProperty - The CSS style property.\n * @param defaultValue - The default value for the property.\n * @returns The value of the property for node.\n */\nfunction $getNodeStyleValueForProperty(node, styleProperty, defaultValue) {\n const css = node.getStyle();\n const styleObject = getStyleObjectFromCSS(css);\n if (styleObject !== null) {\n return styleObject[styleProperty] || defaultValue;\n }\n return defaultValue;\n}\n\n/**\n * Returns the current value of a CSS property for TextNodes in the Selection, if set. If not set, it returns the defaultValue.\n * If all TextNodes do not have the same value, it returns an empty string.\n * @param selection - The selection of TextNodes whose value to find.\n * @param styleProperty - The CSS style property.\n * @param defaultValue - The default value for the property, defaults to an empty string.\n * @returns The value of the property for the selected TextNodes.\n */\nfunction $getSelectionStyleValueForProperty(selection, styleProperty, defaultValue = '') {\n let styleValue = null;\n const nodes = selection.getNodes();\n const anchor = selection.anchor;\n const focus = selection.focus;\n const isBackward = selection.isBackward();\n const endOffset = isBackward ? focus.offset : anchor.offset;\n const endNode = isBackward ? focus.getNode() : anchor.getNode();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection) && selection.isCollapsed() && selection.style !== '') {\n const css = selection.style;\n const styleObject = getStyleObjectFromCSS(css);\n if (styleObject !== null && styleProperty in styleObject) {\n return styleObject[styleProperty];\n }\n }\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n\n // if no actual characters in the end node are selected, we don't\n // include it in the selection for purposes of determining style\n // value\n if (i !== 0 && endOffset === 0 && node.is(endNode)) {\n continue;\n }\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(node)) {\n const nodeStyleValue = $getNodeStyleValueForProperty(node, styleProperty, defaultValue);\n if (styleValue === null) {\n styleValue = nodeStyleValue;\n } else if (styleValue !== nodeStyleValue) {\n // multiple text nodes are in the selection and they don't all\n // have the same style.\n styleValue = '';\n break;\n }\n }\n }\n return styleValue === null ? defaultValue : styleValue;\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n/** @deprecated renamed to {@link $trimTextContentFromAnchor} by @lexical/eslint-plugin rules-of-lexical */\nconst trimTextContentFromAnchor = $trimTextContentFromAnchor;\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9ub2RlX21vZHVsZXMvLnBucG0vQGxleGljYWwrc2VsZWN0aW9uQDAuNDEuMC9ub2RlX21vZHVsZXMvQGxleGljYWwvc2VsZWN0aW9uL0xleGljYWxTZWxlY3Rpb24uZGV2Lm1qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUU4ZTtBQUNuYjs7QUFFM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTSxvREFBVztBQUNqQjtBQUNBO0FBQ0EsTUFBTSxvREFBVztBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0Esa0JBQWtCLDBCQUEwQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsTUFBTSxJQUFJLGVBQWU7QUFDekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLG1EQUFVO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixvREFBVztBQUM1QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qyw0REFBbUI7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsNkRBQW9CO0FBQzlEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixzRUFBNkI7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLHVEQUFjO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0sdURBQWM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSx1REFBYztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHVEQUFjO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUyxvREFBVztBQUNwQjtBQUNBO0FBQ0EsK0RBQStELG9EQUFXO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QixzREFBYTtBQUN0QyxZQUFZLG9EQUFXO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsOERBQXFCO0FBQ25EO0FBQ0E7QUFDQSwyQkFBMkIsd0RBQWU7QUFDMUM7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0EsWUFBWSwwREFBaUI7QUFDN0I7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUix5QkFBeUIsd0RBQWU7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEVBQTRFLHNCQUFzQjtBQUNsRztBQUNBO0FBQ0EsUUFBUSwwREFBaUIsa0NBQWtDLG9EQUFXLFlBQVksdURBQWM7QUFDaEc7QUFDQTtBQUNBLDJDQUEyQywwREFBaUIsMEJBQTBCLG9EQUFXO0FBQ2pHO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxNQUFNLDBEQUFpQixZQUFZLG9EQUFXO0FBQzlDO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0RUFBNEUsc0JBQXNCO0FBQ2xHO0FBQ0E7QUFDQSxNQUFNLDBEQUFpQjtBQUN2QjtBQUNBO0FBQ0EsUUFBUSx1REFBYztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyx1REFBYztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0Isc0RBQWE7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0sMERBQWlCO0FBQ3ZCLHdCQUF3QixpRUFBd0I7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLG9EQUFXO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSw0REFBbUI7QUFDM0I7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNLDBEQUFpQjtBQUN2QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsOERBQXFCO0FBQ3hDO0FBQ0E7QUFDQSx3QkFBd0IsNERBQW1CLG1CQUFtQixzREFBaUI7QUFDL0UsdUJBQXVCLDREQUFtQixrQkFBa0Isc0RBQWlCO0FBQzdFLFFBQVEsdURBQWM7QUFDdEI7QUFDQTtBQUNBLFFBQVEsdURBQWM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLHVEQUFjLFVBQVUsMERBQWlCO0FBQ2pEO0FBQ0EsTUFBTTtBQUNOLDRCQUE0Qiw0REFBbUIsT0FBTyxzREFBaUI7QUFDdkUsVUFBVSx1REFBYztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLHNEQUFhO0FBQ2hELElBQUksc0RBQWE7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsNERBQW1CO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUSw0REFBbUI7QUFDM0I7QUFDQTtBQUNBO0FBQ0EsTUFBTSwyREFBMkQscURBQVk7QUFDN0U7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHVEQUFjO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsNERBQW1CO0FBQzNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBLFFBQVEsdURBQWM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLG9EQUFXO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsdURBQWM7QUFDNUI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxNQUFNO0FBQ04sV0FBVyx1REFBYztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixxQkFBcUI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTSw0REFBbUI7QUFDekI7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSLDBDQUEwQyxRQUFRO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsVUFBVSx1REFBYztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWLDBCQUEwQixxQkFBcUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0EsVUFBVTtBQUNWLDBCQUEwQixxQkFBcUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLE1BQU07QUFDTix3Q0FBd0MsUUFBUTtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsOERBQXFCO0FBQzdDLE1BQU0sMERBQWlCO0FBQ3ZCLElBQUksc0RBQWE7QUFDakIsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNLHVEQUFjO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQix3REFBZTtBQUNwQyxNQUFNLG9FQUEyQjtBQUNqQztBQUNBO0FBQ0EsMEJBQTBCLDREQUFtQjtBQUM3QyxRQUFRLHNEQUFhO0FBQ3JCO0FBQ0EsTUFBTSxTQUFTLHVEQUFjO0FBQzdCO0FBQ0EsTUFBTSxTQUFTLHlEQUFnQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNLDBEQUFpQjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0Isa0JBQWtCO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsb0RBQVc7QUFDbkI7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEIsa0NBQWtDO0FBQzlEOztBQUVnaUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9tYXJjbWludGVsL1Byb2plY3RzL2UtdGliLmNvbS9ub2RlX21vZHVsZXMvLnBucG0vQGxleGljYWwrc2VsZWN0aW9uQDAuNDEuMC9ub2RlX21vZHVsZXMvQGxleGljYWwvc2VsZWN0aW9uL0xleGljYWxTZWxlY3Rpb24uZGV2Lm1qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgTWV0YSBQbGF0Zm9ybXMsIEluYy4gYW5kIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICovXG5cbmltcG9ydCB7ICRpc1RleHROb2RlLCAkZ2V0RWRpdG9yLCAkaXNSb290Tm9kZSwgJGlzRWxlbWVudE5vZGUsICRnZXROb2RlQnlLZXksICRnZXRQcmV2aW91c1NlbGVjdGlvbiwgJGNyZWF0ZVRleHROb2RlLCAkaXNSYW5nZVNlbGVjdGlvbiwgJGdldFNlbGVjdGlvbiwgJGNhcmV0UmFuZ2VGcm9tU2VsZWN0aW9uLCAkaXNUb2tlbk9yU2VnbWVudGVkLCAkZ2V0Q2hhcmFjdGVyT2Zmc2V0cywgJGNsb25lV2l0aFByb3BlcnRpZXNFcGhlbWVyYWwsICRjcmVhdGVSYW5nZVNlbGVjdGlvbiwgJGZpbmRNYXRjaGluZ1BhcmVudCwgSU5URVJOQUxfJGlzQmxvY2ssICRzZXRTZWxlY3Rpb24sICRjYXJldEZyb21Qb2ludCwgJGlzRXh0ZW5kYWJsZVRleHRQb2ludENhcmV0LCAkZXh0ZW5kQ2FyZXRUb1JhbmdlLCAkaXNDaGlsZENhcmV0LCAkaXNEZWNvcmF0b3JOb2RlLCAkaXNSb290T3JTaGFkb3dSb290LCAkaGFzQW5jZXN0b3IsICRpc0xlYWZOb2RlIH0gZnJvbSAnbGV4aWNhbCc7XG5leHBvcnQgeyAkY2xvbmVXaXRoUHJvcGVydGllcywgJHNlbGVjdEFsbCB9IGZyb20gJ2xleGljYWwnO1xuXG4vKipcbiAqIENvcHlyaWdodCAoYykgTWV0YSBQbGF0Zm9ybXMsIEluYy4gYW5kIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICovXG5cbi8vIERvIG5vdCByZXF1aXJlIHRoaXMgbW9kdWxlIGRpcmVjdGx5ISBVc2Ugbm9ybWFsIGBpbnZhcmlhbnRgIGNhbGxzLlxuXG5mdW5jdGlvbiBmb3JtYXREZXZFcnJvck1lc3NhZ2UobWVzc2FnZSkge1xuICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG59XG5cbi8qKlxuICogQ29weXJpZ2h0IChjKSBNZXRhIFBsYXRmb3JtcywgSW5jLiBhbmQgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKi9cbmNvbnN0IENTU19UT19TVFlMRVMgPSBuZXcgTWFwKCk7XG5cbi8qKlxuICogQ29weXJpZ2h0IChjKSBNZXRhIFBsYXRmb3JtcywgSW5jLiBhbmQgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKi9cblxuZnVuY3Rpb24gZ2V0RE9NVGV4dE5vZGUoZWxlbWVudCkge1xuICBsZXQgbm9kZSA9IGVsZW1lbnQ7XG4gIHdoaWxlIChub2RlICE9IG51bGwpIHtcbiAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgIHJldHVybiBub2RlO1xuICAgIH1cbiAgICBub2RlID0gbm9kZS5maXJzdENoaWxkO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gZ2V0RE9NSW5kZXhXaXRoaW5QYXJlbnQobm9kZSkge1xuICBjb25zdCBwYXJlbnQgPSBub2RlLnBhcmVudE5vZGU7XG4gIGlmIChwYXJlbnQgPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBFcnJvcignU2hvdWxkIG5ldmVyIGhhcHBlbicpO1xuICB9XG4gIHJldHVybiBbcGFyZW50LCBBcnJheS5mcm9tKHBhcmVudC5jaGlsZE5vZGVzKS5pbmRleE9mKG5vZGUpXTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc2VsZWN0aW9uIHJhbmdlIGZvciB0aGUgRE9NLlxuICogQHBhcmFtIGVkaXRvciAtIFRoZSBsZXhpY2FsIGVkaXRvci5cbiAqIEBwYXJhbSBhbmNob3JOb2RlIC0gVGhlIGFuY2hvciBub2RlIG9mIGEgc2VsZWN0aW9uLlxuICogQHBhcmFtIF9hbmNob3JPZmZzZXQgLSBUaGUgYW1vdW50IG9mIHNwYWNlIG9mZnNldCBmcm9tIHRoZSBhbmNob3IgdG8gdGhlIGZvY3VzLlxuICogQHBhcmFtIGZvY3VzTm9kZSAtIFRoZSBjdXJyZW50IGZvY3VzLlxuICogQHBhcmFtIF9mb2N1c09mZnNldCAtIFRoZSBhbW91bnQgb2Ygc3BhY2Ugb2Zmc2V0IGZyb20gdGhlIGZvY3VzIHRvIHRoZSBhbmNob3IuXG4gKiBAcmV0dXJucyBUaGUgcmFuZ2Ugb2Ygc2VsZWN0aW9uIGZvciB0aGUgRE9NIHRoYXQgd2FzIGNyZWF0ZWQuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZURPTVJhbmdlKGVkaXRvciwgYW5jaG9yTm9kZSwgX2FuY2hvck9mZnNldCwgZm9jdXNOb2RlLCBfZm9jdXNPZmZzZXQpIHtcbiAgY29uc3QgYW5jaG9yS2V5ID0gYW5jaG9yTm9kZS5nZXRLZXkoKTtcbiAgY29uc3QgZm9jdXNLZXkgPSBmb2N1c05vZGUuZ2V0S2V5KCk7XG4gIGNvbnN0IHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgbGV0IGFuY2hvckRPTSA9IGVkaXRvci5nZXRFbGVtZW50QnlLZXkoYW5jaG9yS2V5KTtcbiAgbGV0IGZvY3VzRE9NID0gZWRpdG9yLmdldEVsZW1lbnRCeUtleShmb2N1c0tleSk7XG4gIGxldCBhbmNob3JPZmZzZXQgPSBfYW5jaG9yT2Zmc2V0O1xuICBsZXQgZm9jdXNPZmZzZXQgPSBfZm9jdXNPZmZzZXQ7XG4gIGlmICgkaXNUZXh0Tm9kZShhbmNob3JOb2RlKSkge1xuICAgIGFuY2hvckRPTSA9IGdldERPTVRleHROb2RlKGFuY2hvckRPTSk7XG4gIH1cbiAgaWYgKCRpc1RleHROb2RlKGZvY3VzTm9kZSkpIHtcbiAgICBmb2N1c0RPTSA9IGdldERPTVRleHROb2RlKGZvY3VzRE9NKTtcbiAgfVxuICBpZiAoYW5jaG9yTm9kZSA9PT0gdW5kZWZpbmVkIHx8IGZvY3VzTm9kZSA9PT0gdW5kZWZpbmVkIHx8IGFuY2hvckRPTSA9PT0gbnVsbCB8fCBmb2N1c0RPTSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGlmIChhbmNob3JET00ubm9kZU5hbWUgPT09ICdCUicpIHtcbiAgICBbYW5jaG9yRE9NLCBhbmNob3JPZmZzZXRdID0gZ2V0RE9NSW5kZXhXaXRoaW5QYXJlbnQoYW5jaG9yRE9NKTtcbiAgfVxuICBpZiAoZm9jdXNET00ubm9kZU5hbWUgPT09ICdCUicpIHtcbiAgICBbZm9jdXNET00sIGZvY3VzT2Zmc2V0XSA9IGdldERPTUluZGV4V2l0aGluUGFyZW50KGZvY3VzRE9NKTtcbiAgfVxuICBjb25zdCBmaXJzdENoaWxkID0gYW5jaG9yRE9NLmZpcnN0Q2hpbGQ7XG4gIGlmIChhbmNob3JET00gPT09IGZvY3VzRE9NICYmIGZpcnN0Q2hpbGQgIT0gbnVsbCAmJiBmaXJzdENoaWxkLm5vZGVOYW1lID09PSAnQlInICYmIGFuY2hvck9mZnNldCA9PT0gMCAmJiBmb2N1c09mZnNldCA9PT0gMCkge1xuICAgIGZvY3VzT2Zmc2V0ID0gMTtcbiAgfVxuICB0cnkge1xuICAgIHJhbmdlLnNldFN0YXJ0KGFuY2hvckRPTSwgYW5jaG9yT2Zmc2V0KTtcbiAgICByYW5nZS5zZXRFbmQoZm9jdXNET00sIGZvY3VzT2Zmc2V0KTtcbiAgfSBjYXRjaCAoX2UpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBpZiAocmFuZ2UuY29sbGFwc2VkICYmIChhbmNob3JPZmZzZXQgIT09IGZvY3VzT2Zmc2V0IHx8IGFuY2hvcktleSAhPT0gZm9jdXNLZXkpKSB7XG4gICAgLy8gUmFuZ2UgaXMgYmFja3dhcmRzLCB3ZSBuZWVkIHRvIHJldmVyc2UgaXRcbiAgICByYW5nZS5zZXRTdGFydChmb2N1c0RPTSwgZm9jdXNPZmZzZXQpO1xuICAgIHJhbmdlLnNldEVuZChhbmNob3JET00sIGFuY2hvck9mZnNldCk7XG4gIH1cbiAgcmV0dXJuIHJhbmdlO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgRE9NUmVjdHMsIGdlbmVyYWxseSB1c2VkIHRvIGhlbHAgdGhlIGVkaXRvciBmaW5kIGEgc3BlY2lmaWMgbG9jYXRpb24gb24gdGhlIHNjcmVlbi5cbiAqIEBwYXJhbSBlZGl0b3IgLSBUaGUgbGV4aWNhbCBlZGl0b3JcbiAqIEBwYXJhbSByYW5nZSAtIEEgZnJhZ21lbnQgb2YgYSBkb2N1bWVudCB0aGF0IGNhbiBjb250YWluIG5vZGVzIGFuZCBwYXJ0cyBvZiB0ZXh0IG5vZGVzLlxuICogQHJldHVybnMgVGhlIHNlbGVjdGlvblJlY3RzIGFzIGFuIGFycmF5LlxuICovXG5mdW5jdGlvbiBjcmVhdGVSZWN0c0Zyb21ET01SYW5nZShlZGl0b3IsIHJhbmdlKSB7XG4gIGNvbnN0IHJvb3RFbGVtZW50ID0gZWRpdG9yLmdldFJvb3RFbGVtZW50KCk7XG4gIGlmIChyb290RWxlbWVudCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICBjb25zdCByb290UmVjdCA9IHJvb3RFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICBjb25zdCBjb21wdXRlZFN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShyb290RWxlbWVudCk7XG4gIGNvbnN0IHJvb3RQYWRkaW5nID0gcGFyc2VGbG9hdChjb21wdXRlZFN0eWxlLnBhZGRpbmdMZWZ0KSArIHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZS5wYWRkaW5nUmlnaHQpO1xuICBjb25zdCBzZWxlY3Rpb25SZWN0cyA9IEFycmF5LmZyb20ocmFuZ2UuZ2V0Q2xpZW50UmVjdHMoKSk7XG4gIGxldCBzZWxlY3Rpb25SZWN0c0xlbmd0aCA9IHNlbGVjdGlvblJlY3RzLmxlbmd0aDtcbiAgLy9zb3J0IHJlY3RzIGZyb20gdG9wIGxlZnQgdG8gYm90dG9tIHJpZ2h0LlxuICBzZWxlY3Rpb25SZWN0cy5zb3J0KChhLCBiKSA9PiB7XG4gICAgY29uc3QgdG9wID0gYS50b3AgLSBiLnRvcDtcbiAgICAvLyBTb21lIHJlY3RzIG1hdGNoIHBvc2l0aW9uIGNsb3NlbHksIGJ1dCBub3QgcGVyZmVjdGx5LFxuICAgIC8vIHNvIHdlIGdpdmUgYSAzcHggdG9sZXJhbmNlLlxuICAgIGlmIChNYXRoLmFicyh0b3ApIDw9IDMpIHtcbiAgICAgIHJldHVybiBhLmxlZnQgLSBiLmxlZnQ7XG4gICAgfVxuICAgIHJldHVybiB0b3A7XG4gIH0pO1xuICBsZXQgcHJldlJlY3Q7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uUmVjdHNMZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHNlbGVjdGlvblJlY3QgPSBzZWxlY3Rpb25SZWN0c1tpXTtcbiAgICAvLyBFeGNsdWRlIHJlY3RzIHRoYXQgb3ZlcmxhcCBwcmVjZWRpbmcgUmVjdHMgaW4gdGhlIHNvcnRlZCBsaXN0LlxuICAgIGNvbnN0IGlzT3ZlcmxhcHBpbmdSZWN0ID0gcHJldlJlY3QgJiYgcHJldlJlY3QudG9wIDw9IHNlbGVjdGlvblJlY3QudG9wICYmIHByZXZSZWN0LnRvcCArIHByZXZSZWN0LmhlaWdodCA+IHNlbGVjdGlvblJlY3QudG9wICYmIHByZXZSZWN0LmxlZnQgKyBwcmV2UmVjdC53aWR0aCA+IHNlbGVjdGlvblJlY3QubGVmdDtcbiAgICAvLyBFeGNsdWRlIHNlbGVjdGlvbnMgdGhhdCBzcGFuIHRoZSBlbnRpcmUgZWxlbWVudFxuICAgIGNvbnN0IHNlbGVjdGlvblNwYW5zRWxlbWVudCA9IHNlbGVjdGlvblJlY3Qud2lkdGggKyByb290UGFkZGluZyA9PT0gcm9vdFJlY3Qud2lkdGg7XG4gICAgaWYgKGlzT3ZlcmxhcHBpbmdSZWN0IHx8IHNlbGVjdGlvblNwYW5zRWxlbWVudCkge1xuICAgICAgc2VsZWN0aW9uUmVjdHMuc3BsaWNlKGktLSwgMSk7XG4gICAgICBzZWxlY3Rpb25SZWN0c0xlbmd0aC0tO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHByZXZSZWN0ID0gc2VsZWN0aW9uUmVjdDtcbiAgfVxuICByZXR1cm4gc2VsZWN0aW9uUmVjdHM7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBvYmplY3QgY29udGFpbmluZyBhbGwgdGhlIHN0eWxlcyBhbmQgdGhlaXIgdmFsdWVzIHByb3ZpZGVkIGluIHRoZSBDU1Mgc3RyaW5nLlxuICogQHBhcmFtIGNzcyAtIFRoZSBDU1Mgc3RyaW5nIG9mIHN0eWxlcyBhbmQgdGhlaXIgdmFsdWVzLlxuICogQHJldHVybnMgVGhlIHN0eWxlT2JqZWN0IGNvbnRhaW5pbmcgYWxsIHRoZSBzdHlsZXMgYW5kIHRoZWlyIHZhbHVlcy5cbiAqL1xuZnVuY3Rpb24gZ2V0U3R5bGVPYmplY3RGcm9tUmF3Q1NTKGNzcykge1xuICBjb25zdCBzdHlsZU9iamVjdCA9IHt9O1xuICBpZiAoIWNzcykge1xuICAgIHJldHVybiBzdHlsZU9iamVjdDtcbiAgfVxuICBjb25zdCBzdHlsZXMgPSBjc3Muc3BsaXQoJzsnKTtcbiAgZm9yIChjb25zdCBzdHlsZSBvZiBzdHlsZXMpIHtcbiAgICBpZiAoc3R5bGUgIT09ICcnKSB7XG4gICAgICBjb25zdCBba2V5LCB2YWx1ZV0gPSBzdHlsZS5zcGxpdCgvOihbXl0rKS8pOyAvLyBzcGxpdCBvbiBmaXJzdCBjb2xvblxuICAgICAgaWYgKGtleSAmJiB2YWx1ZSkge1xuICAgICAgICBzdHlsZU9iamVjdFtrZXkudHJpbSgpXSA9IHZhbHVlLnRyaW0oKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0eWxlT2JqZWN0O1xufVxuXG4vKipcbiAqIEdpdmVuIGEgQ1NTIHN0cmluZywgcmV0dXJucyBhbiBvYmplY3QgZnJvbSB0aGUgc3R5bGUgY2FjaGUuXG4gKiBAcGFyYW0gY3NzIC0gVGhlIENTUyBwcm9wZXJ0eSBhcyBhIHN0cmluZy5cbiAqIEByZXR1cm5zIFRoZSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gQ1NTIHByb3BlcnR5LlxuICovXG5mdW5jdGlvbiBnZXRTdHlsZU9iamVjdEZyb21DU1MoY3NzKSB7XG4gIGxldCB2YWx1ZSA9IENTU19UT19TVFlMRVMuZ2V0KGNzcyk7XG4gIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdmFsdWUgPSBnZXRTdHlsZU9iamVjdEZyb21SYXdDU1MoY3NzKTtcbiAgICBDU1NfVE9fU1RZTEVTLnNldChjc3MsIHZhbHVlKTtcbiAgfVxuICB7XG4gICAgLy8gRnJlZXplIHRoZSB2YWx1ZSBpbiBERVYgdG8gcHJldmVudCBhY2NpZGVudGFsIG11dGF0aW9uc1xuICAgIE9iamVjdC5mcmVlemUodmFsdWUpO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBDU1Mgc3R5bGVzIGZyb20gdGhlIHN0eWxlIG9iamVjdC5cbiAqIEBwYXJhbSBzdHlsZXMgLSBUaGUgc3R5bGUgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHN0eWxlcyB0byBnZXQuXG4gKiBAcmV0dXJucyBBIHN0cmluZyBjb250YWluaW5nIHRoZSBDU1Mgc3R5bGVzIGFuZCB0aGVpciB2YWx1ZXMuXG4gKi9cbmZ1bmN0aW9uIGdldENTU0Zyb21TdHlsZU9iamVjdChzdHlsZXMpIHtcbiAgbGV0IGNzcyA9ICcnO1xuICBmb3IgKGNvbnN0IHN0eWxlIGluIHN0eWxlcykge1xuICAgIGlmIChzdHlsZSkge1xuICAgICAgY3NzICs9IGAke3N0eWxlfTogJHtzdHlsZXNbc3R5bGVdfTtgO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY3NzO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGNvbXB1dGVkIERPTSBzdHlsZXMgb2YgdGhlIGVsZW1lbnQuXG4gKiBAcGFyYW0gZWxlbWVudCAtIFRoZSBub2RlIHRvIGNoZWNrIHRoZSBzdHlsZXMgZm9yLlxuICogQHJldHVybnMgdGhlIGNvbXB1dGVkIHN0eWxlcyBvZiB0aGUgZWxlbWVudCBvciBudWxsIGlmIHRoZXJlIGlzIG5vIERPTSBlbGVtZW50IG9yIG5vIGRlZmF1bHQgdmlldyBmb3IgdGhlIGRvY3VtZW50LlxuICovXG5mdW5jdGlvbiAkZ2V0Q29tcHV0ZWRTdHlsZUZvckVsZW1lbnQoZWxlbWVudCkge1xuICBjb25zdCBlZGl0b3IgPSAkZ2V0RWRpdG9yKCk7XG4gIGNvbnN0IGRvbUVsZW1lbnQgPSBlZGl0b3IuZ2V0RWxlbWVudEJ5S2V5KGVsZW1lbnQuZ2V0S2V5KCkpO1xuICBpZiAoZG9tRWxlbWVudCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHZpZXcgPSBkb21FbGVtZW50Lm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXc7XG4gIGlmICh2aWV3ID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgcmV0dXJuIHZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShkb21FbGVtZW50KTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBjb21wdXRlZCBET00gc3R5bGVzIG9mIHRoZSBwYXJlbnQgb2YgdGhlIG5vZGUuXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrIGl0cyBwYXJlbnQncyBzdHlsZXMgZm9yLlxuICogQHJldHVybnMgdGhlIGNvbXB1dGVkIHN0eWxlcyBvZiB0aGUgbm9kZSBvciBudWxsIGlmIHRoZXJlIGlzIG5vIERPTSBlbGVtZW50IG9yIG5vIGRlZmF1bHQgdmlldyBmb3IgdGhlIGRvY3VtZW50LlxuICovXG5mdW5jdGlvbiAkZ2V0Q29tcHV0ZWRTdHlsZUZvclBhcmVudChub2RlKSB7XG4gIGNvbnN0IHBhcmVudCA9ICRpc1Jvb3ROb2RlKG5vZGUpID8gbm9kZSA6IG5vZGUuZ2V0UGFyZW50T3JUaHJvdygpO1xuICByZXR1cm4gJGdldENvbXB1dGVkU3R5bGVGb3JFbGVtZW50KHBhcmVudCk7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIGEgbm9kZSdzIHBhcmVudCBpcyBSVEwuXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGNoZWNrIHdoZXRoZXIgaXQgaXMgUlRMLlxuICogQHJldHVybnMgd2hldGhlciB0aGUgbm9kZSBpcyBSVEwuXG4gKi9cbmZ1bmN0aW9uICRpc1BhcmVudFJUTChub2RlKSB7XG4gIGNvbnN0IHN0eWxlcyA9ICRnZXRDb21wdXRlZFN0eWxlRm9yUGFyZW50KG5vZGUpO1xuICByZXR1cm4gc3R5bGVzICE9PSBudWxsICYmIHN0eWxlcy5kaXJlY3Rpb24gPT09ICdydGwnO1xufVxuXG4vKipcbiAqIEdlbmVyYWxseSB1c2VkIHRvIGFwcGVuZCB0ZXh0IGNvbnRlbnQgdG8gSFRNTCBhbmQgSlNPTi4gR3JhYnMgdGhlIHRleHQgY29udGVudCBhbmQgXCJzbGljZXNcIlxuICogaXQgdG8gYmUgZ2VuZXJhdGVkIGludG8gdGhlIG5ldyBUZXh0Tm9kZS5cbiAqIEBwYXJhbSBzZWxlY3Rpb24gLSBUaGUgc2VsZWN0aW9uIGNvbnRhaW5pbmcgdGhlIG5vZGUgd2hvc2UgVGV4dE5vZGUgaXMgdG8gYmUgZWRpdGVkLlxuICogQHBhcmFtIHRleHROb2RlIC0gVGhlIFRleHROb2RlIHRvIGJlIGVkaXRlZC5cbiAqIEBwYXJhbSBtdXRhdGVzIC0gJ2Nsb25lJyB0byByZXR1cm4gYSBjbG9uZSBiZWZvcmUgbXV0YXRpbmcsICdzZWxmJyB0byB1cGRhdGUgaW4tcGxhY2VcbiAqIEByZXR1cm5zIFRoZSB1cGRhdGVkIFRleHROb2RlIG9yIGNsb25lLlxuICovXG5mdW5jdGlvbiAkc2xpY2VTZWxlY3RlZFRleHROb2RlQ29udGVudChzZWxlY3Rpb24sIHRleHROb2RlLCBtdXRhdGVzID0gJ3NlbGYnKSB7XG4gIGNvbnN0IGFuY2hvckFuZEZvY3VzID0gc2VsZWN0aW9uLmdldFN0YXJ0RW5kUG9pbnRzKCk7XG4gIGlmICh0ZXh0Tm9kZS5pc1NlbGVjdGVkKHNlbGVjdGlvbikgJiYgISRpc1Rva2VuT3JTZWdtZW50ZWQodGV4dE5vZGUpICYmIGFuY2hvckFuZEZvY3VzICE9PSBudWxsKSB7XG4gICAgY29uc3QgW2FuY2hvciwgZm9jdXNdID0gYW5jaG9yQW5kRm9jdXM7XG4gICAgY29uc3QgaXNCYWNrd2FyZCA9IHNlbGVjdGlvbi5pc0JhY2t3YXJkKCk7XG4gICAgY29uc3QgYW5jaG9yTm9kZSA9IGFuY2hvci5nZXROb2RlKCk7XG4gICAgY29uc3QgZm9jdXNOb2RlID0gZm9jdXMuZ2V0Tm9kZSgpO1xuICAgIGNvbnN0IGlzQW5jaG9yID0gdGV4dE5vZGUuaXMoYW5jaG9yTm9kZSk7XG4gICAgY29uc3QgaXNGb2N1cyA9IHRleHROb2RlLmlzKGZvY3VzTm9kZSk7XG4gICAgaWYgKGlzQW5jaG9yIHx8IGlzRm9jdXMpIHtcbiAgICAgIGNvbnN0IFthbmNob3JPZmZzZXQsIGZvY3VzT2Zmc2V0XSA9ICRnZXRDaGFyYWN0ZXJPZmZzZXRzKHNlbGVjdGlvbik7XG4gICAgICBjb25zdCBpc1NhbWUgPSBhbmNob3JOb2RlLmlzKGZvY3VzTm9kZSk7XG4gICAgICBjb25zdCBpc0ZpcnN0ID0gdGV4dE5vZGUuaXMoaXNCYWNrd2FyZCA/IGZvY3VzTm9kZSA6IGFuY2hvck5vZGUpO1xuICAgICAgY29uc3QgaXNMYXN0ID0gdGV4dE5vZGUuaXMoaXNCYWNrd2FyZCA/IGFuY2hvck5vZGUgOiBmb2N1c05vZGUpO1xuICAgICAgbGV0IHN0YXJ0T2Zmc2V0ID0gMDtcbiAgICAgIGxldCBlbmRPZmZzZXQgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAoaXNTYW1lKSB7XG4gICAgICAgIHN0YXJ0T2Zmc2V0ID0gYW5jaG9yT2Zmc2V0ID4gZm9jdXNPZmZzZXQgPyBmb2N1c09mZnNldCA6IGFuY2hvck9mZnNldDtcbiAgICAgICAgZW5kT2Zmc2V0ID0gYW5jaG9yT2Zmc2V0ID4gZm9jdXNPZmZzZXQgPyBhbmNob3JPZmZzZXQgOiBmb2N1c09mZnNldDtcbiAgICAgIH0gZWxzZSBpZiAoaXNGaXJzdCkge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBpc0JhY2t3YXJkID8gZm9jdXNPZmZzZXQgOiBhbmNob3JPZmZzZXQ7XG4gICAgICAgIHN0YXJ0T2Zmc2V0ID0gb2Zmc2V0O1xuICAgICAgICBlbmRPZmZzZXQgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2UgaWYgKGlzTGFzdCkge1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBpc0JhY2t3YXJkID8gYW5jaG9yT2Zmc2V0IDogZm9jdXNPZmZzZXQ7XG4gICAgICAgIHN0YXJ0T2Zmc2V0ID0gMDtcbiAgICAgICAgZW5kT2Zmc2V0ID0gb2Zmc2V0O1xuICAgICAgfVxuXG4gICAgICAvLyBOT1RFOiBUaGlzIG11dGF0ZXMgX190ZXh0IGRpcmVjdGx5IGJlY2F1c2UgdGhlIHByaW1hcnkgdXNlIGNhc2UgaXMgdG9cbiAgICAgIC8vIG1vZGlmeSBhICRjbG9uZVdpdGhQcm9wZXJ0aWVzIG5vZGUgdGhhdCBzaG91bGQgbmV2ZXIgYmUgYWRkZWRcbiAgICAgIC8vIHRvIHRoZSBFZGl0b3JTdGF0ZSBzbyB3ZSBtdXN0IG5vdCBjYWxsIGdldFdyaXRhYmxlIHZpYSBzZXRUZXh0Q29udGVudFxuICAgICAgY29uc3QgdGV4dCA9IHRleHROb2RlLl9fdGV4dC5zbGljZShzdGFydE9mZnNldCwgZW5kT2Zmc2V0KTtcbiAgICAgIGlmICh0ZXh0ICE9PSB0ZXh0Tm9kZS5fX3RleHQpIHtcbiAgICAgICAgaWYgKG11dGF0ZXMgPT09ICdjbG9uZScpIHtcbiAgICAgICAgICB0ZXh0Tm9kZSA9ICRjbG9uZVdpdGhQcm9wZXJ0aWVzRXBoZW1lcmFsKHRleHROb2RlKTtcbiAgICAgICAgfVxuICAgICAgICB0ZXh0Tm9kZS5fX3RleHQgPSB0ZXh0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gdGV4dE5vZGU7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lcyBpZiB0aGUgY3VycmVudCBzZWxlY3Rpb24gaXMgYXQgdGhlIGVuZCBvZiB0aGUgbm9kZS5cbiAqIEBwYXJhbSBwb2ludCAtIFRoZSBwb2ludCBvZiB0aGUgc2VsZWN0aW9uIHRvIHRlc3QuXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlZCBwb2ludCBvZmZzZXQgaXMgaW4gdGhlIGxhc3QgcG9zc2libGUgcG9zaXRpb24sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZnVuY3Rpb24gJGlzQXROb2RlRW5kKHBvaW50KSB7XG4gIGlmIChwb2ludC50eXBlID09PSAndGV4dCcpIHtcbiAgICByZXR1cm4gcG9pbnQub2Zmc2V0ID09PSBwb2ludC5nZXROb2RlKCkuZ2V0VGV4dENvbnRlbnRTaXplKCk7XG4gIH1cbiAgY29uc3Qgbm9kZSA9IHBvaW50LmdldE5vZGUoKTtcbiAgaWYgKCEkaXNFbGVtZW50Tm9kZShub2RlKSkge1xuICAgIGZvcm1hdERldkVycm9yTWVzc2FnZShgaXNBdE5vZGVFbmQ6IG5vZGUgbXVzdCBiZSBhIFRleHROb2RlIG9yIEVsZW1lbnROb2RlYCk7XG4gIH1cbiAgcmV0dXJuIHBvaW50Lm9mZnNldCA9PT0gbm9kZS5nZXRDaGlsZHJlblNpemUoKTtcbn1cblxuLyoqXG4gKiBUcmltcyB0ZXh0IGZyb20gYSBub2RlIGluIG9yZGVyIHRvIHNob3J0ZW4gaXQsIGVnLiB0byBlbmZvcmNlIGEgdGV4dCdzIG1heCBsZW5ndGguIElmIGl0IGRlbGV0ZXMgdGV4dFxuICogdGhhdCBpcyBhbiBhbmNlc3RvciBvZiB0aGUgYW5jaG9yIHRoZW4gaXQgd2lsbCBsZWF2ZSAyIGluZGVudHMsIG90aGVyd2lzZSwgaWYgbm8gdGV4dCBjb250ZW50IGV4aXN0cywgaXQgZGVsZXRlc1xuICogdGhlIFRleHROb2RlLiBJdCB3aWxsIG1vdmUgdGhlIGZvY3VzIHRvIGVpdGhlciB0aGUgZW5kIG9mIGFueSBsZWZ0IG92ZXIgdGV4dCBvciBiZWdpbm5pbmcgb2YgYSBuZXcgVGV4dE5vZGUuXG4gKiBAcGFyYW0gZWRpdG9yIC0gVGhlIGxleGljYWwgZWRpdG9yLlxuICogQHBhcmFtIGFuY2hvciAtIFRoZSBhbmNob3Igb2YgdGhlIGN1cnJlbnQgc2VsZWN0aW9uLCB3aGVyZSB0aGUgc2VsZWN0aW9uIHNob3VsZCBiZSBwb2ludGluZy5cbiAqIEBwYXJhbSBkZWxDb3VudCAtIFRoZSBhbW91bnQgb2YgY2hhcmFjdGVycyB0byBkZWxldGUuIFVzZWZ1bCBhcyBhIGR5bmFtaWMgdmFyaWFibGUgZWcuIHRleHRDb250ZW50U2l6ZSAtIG1heExlbmd0aDtcbiAqL1xuZnVuY3Rpb24gJHRyaW1UZXh0Q29udGVudEZyb21BbmNob3IoZWRpdG9yLCBhbmNob3IsIGRlbENvdW50KSB7XG4gIC8vIFdvcmsgZnJvbSB0aGUgY3VycmVudCBzZWxlY3Rpb24gYW5jaG9yIHBvaW50XG4gIGxldCBjdXJyZW50Tm9kZSA9IGFuY2hvci5nZXROb2RlKCk7XG4gIGxldCByZW1haW5pbmcgPSBkZWxDb3VudDtcbiAgaWYgKCRpc0VsZW1lbnROb2RlKGN1cnJlbnROb2RlKSkge1xuICAgIGNvbnN0IGRlc2NlbmRhbnROb2RlID0gY3VycmVudE5vZGUuZ2V0RGVzY2VuZGFudEJ5SW5kZXgoYW5jaG9yLm9mZnNldCk7XG4gICAgaWYgKGRlc2NlbmRhbnROb2RlICE9PSBudWxsKSB7XG4gICAgICBjdXJyZW50Tm9kZSA9IGRlc2NlbmRhbnROb2RlO1xuICAgIH1cbiAgfVxuICB3aGlsZSAocmVtYWluaW5nID4gMCAmJiBjdXJyZW50Tm9kZSAhPT0gbnVsbCkge1xuICAgIGlmICgkaXNFbGVtZW50Tm9kZShjdXJyZW50Tm9kZSkpIHtcbiAgICAgIGNvbnN0IGxhc3REZXNjZW5kYW50ID0gY3VycmVudE5vZGUuZ2V0TGFzdERlc2NlbmRhbnQoKTtcbiAgICAgIGlmIChsYXN0RGVzY2VuZGFudCAhPT0gbnVsbCkge1xuICAgICAgICBjdXJyZW50Tm9kZSA9IGxhc3REZXNjZW5kYW50O1xuICAgICAgfVxuICAgIH1cbiAgICBsZXQgbmV4dE5vZGUgPSBjdXJyZW50Tm9kZS5nZXRQcmV2aW91c1NpYmxpbmcoKTtcbiAgICBsZXQgYWRkaXRpb25hbEVsZW1lbnRXaGl0ZXNwYWNlID0gMDtcbiAgICBpZiAobmV4dE5vZGUgPT09IG51bGwpIHtcbiAgICAgIGxldCBwYXJlbnQgPSBjdXJyZW50Tm9kZS5nZXRQYXJlbnRPclRocm93KCk7XG4gICAgICBsZXQgcGFyZW50U2libGluZyA9IHBhcmVudC5nZXRQcmV2aW91c1NpYmxpbmcoKTtcbiAgICAgIHdoaWxlIChwYXJlbnRTaWJsaW5nID09PSBudWxsKSB7XG4gICAgICAgIHBhcmVudCA9IHBhcmVudC5nZXRQYXJlbnQoKTtcbiAgICAgICAgaWYgKHBhcmVudCA9PT0gbnVsbCkge1xuICAgICAgICAgIG5leHROb2RlID0gbnVsbDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRTaWJsaW5nID0gcGFyZW50LmdldFByZXZpb3VzU2libGluZygpO1xuICAgICAgfVxuICAgICAgaWYgKHBhcmVudCAhPT0gbnVsbCkge1xuICAgICAgICBhZGRpdGlvbmFsRWxlbWVudFdoaXRlc3BhY2UgPSBwYXJlbnQuaXNJbmxpbmUoKSA/IDAgOiAyO1xuICAgICAgICBuZXh0Tm9kZSA9IHBhcmVudFNpYmxpbmc7XG4gICAgICB9XG4gICAgfVxuICAgIGxldCB0ZXh0ID0gY3VycmVudE5vZGUuZ2V0VGV4dENvbnRlbnQoKTtcbiAgICAvLyBJZiB0aGUgdGV4dCBpcyBlbXB0eSwgd2UgbmVlZCB0byBjb25zaWRlciBhZGRpbmcgaW4gdHdvIGxpbmUgYnJlYWtzIHRvIG1hdGNoXG4gICAgLy8gdGhlIGNvbnRlbnQgaWYgd2Ugd2VyZSB0byBnZXQgaXQgZnJvbSBpdHMgcGFyZW50LlxuICAgIGlmICh0ZXh0ID09PSAnJyAmJiAkaXNFbGVtZW50Tm9kZShjdXJyZW50Tm9kZSkgJiYgIWN1cnJlbnROb2RlLmlzSW5saW5lKCkpIHtcbiAgICAgIC8vIFRPRE86IHNob3VsZCB0aGlzIGJlIGhhbmRsZWQgaW4gY29yZT9cbiAgICAgIHRleHQgPSAnXFxuXFxuJztcbiAgICB9XG4gICAgY29uc3QgY3VycmVudE5vZGVTaXplID0gdGV4dC5sZW5ndGg7XG4gICAgaWYgKCEkaXNUZXh0Tm9kZShjdXJyZW50Tm9kZSkgfHwgcmVtYWluaW5nID49IGN1cnJlbnROb2RlU2l6ZSkge1xuICAgICAgY29uc3QgcGFyZW50ID0gY3VycmVudE5vZGUuZ2V0UGFyZW50KCk7XG4gICAgICBjdXJyZW50Tm9kZS5yZW1vdmUoKTtcbiAgICAgIGlmIChwYXJlbnQgIT0gbnVsbCAmJiBwYXJlbnQuZ2V0Q2hpbGRyZW5TaXplKCkgPT09IDAgJiYgISRpc1Jvb3ROb2RlKHBhcmVudCkpIHtcbiAgICAgICAgcGFyZW50LnJlbW92ZSgpO1xuICAgICAgfVxuICAgICAgcmVtYWluaW5nIC09IGN1cnJlbnROb2RlU2l6ZSArIGFkZGl0aW9uYWxFbGVtZW50V2hpdGVzcGFjZTtcbiAgICAgIGN1cnJlbnROb2RlID0gbmV4dE5vZGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGtleSA9IGN1cnJlbnROb2RlLmdldEtleSgpO1xuICAgICAgLy8gU2VlIGlmIHdlIGNhbiBqdXN0IHJldmVydCBpdCB0byB3aGF0IHdhcyBpbiB0aGUgbGFzdCBlZGl0b3Igc3RhdGVcbiAgICAgIGNvbnN0IHByZXZUZXh0Q29udGVudCA9IGVkaXRvci5nZXRFZGl0b3JTdGF0ZSgpLnJlYWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBwcmV2Tm9kZSA9ICRnZXROb2RlQnlLZXkoa2V5KTtcbiAgICAgICAgaWYgKCRpc1RleHROb2RlKHByZXZOb2RlKSAmJiBwcmV2Tm9kZS5pc1NpbXBsZVRleHQoKSkge1xuICAgICAgICAgIHJldHVybiBwcmV2Tm9kZS5nZXRUZXh0Q29udGVudCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSk7XG4gICAgICBjb25zdCBvZmZzZXQgPSBjdXJyZW50Tm9kZVNpemUgLSByZW1haW5pbmc7XG4gICAgICBjb25zdCBzbGljZWRUZXh0ID0gdGV4dC5zbGljZSgwLCBvZmZzZXQpO1xuICAgICAgaWYgKHByZXZUZXh0Q29udGVudCAhPT0gbnVsbCAmJiBwcmV2VGV4dENvbnRlbnQgIT09IHRleHQpIHtcbiAgICAgICAgY29uc3QgcHJldlNlbGVjdGlvbiA9ICRnZXRQcmV2aW91c1NlbGVjdGlvbigpO1xuICAgICAgICBsZXQgdGFyZ2V0ID0gY3VycmVudE5vZGU7XG4gICAgICAgIGlmICghY3VycmVudE5vZGUuaXNTaW1wbGVUZXh0KCkpIHtcbiAgICAgICAgICBjb25zdCB0ZXh0Tm9kZSA9ICRjcmVhdGVUZXh0Tm9kZShwcmV2VGV4dENvbnRlbnQpO1xuICAgICAgICAgIGN1cnJlbnROb2RlLnJlcGxhY2UodGV4dE5vZGUpO1xuICAgICAgICAgIHRhcmdldCA9IHRleHROb2RlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGN1cnJlbnROb2RlLnNldFRleHRDb250ZW50KHByZXZUZXh0Q29udGVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCRpc1JhbmdlU2VsZWN0aW9uKHByZXZTZWxlY3Rpb24pICYmIHByZXZTZWxlY3Rpb24uaXNDb2xsYXBzZWQoKSkge1xuICAgICAgICAgIGNvbnN0IHByZXZPZmZzZXQgPSBwcmV2U2VsZWN0aW9uLmFuY2hvci5vZmZzZXQ7XG4gICAgICAgICAgdGFyZ2V0LnNlbGVjdChwcmV2T2Zmc2V0LCBwcmV2T2Zmc2V0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChjdXJyZW50Tm9kZS5pc1NpbXBsZVRleHQoKSkge1xuICAgICAgICAvLyBTcGxpdCB0ZXh0XG4gICAgICAgIGNvbnN0IGlzU2VsZWN0ZWQgPSBhbmNob3Iua2V5ID09PSBrZXk7XG4gICAgICAgIGxldCBhbmNob3JPZmZzZXQgPSBhbmNob3Iub2Zmc2V0O1xuICAgICAgICAvLyBNb3ZlIG9mZnNldCB0byBlbmQgaWYgaXQncyBsZXNzIHRoYW4gdGhlIHJlbWFpbmluZyBudW1iZXIsIG90aGVyd2lzZVxuICAgICAgICAvLyB3ZSdsbCBoYXZlIGEgbmVnYXRpdmUgc3BsaXRTdGFydC5cbiAgICAgICAgaWYgKGFuY2hvck9mZnNldCA8IHJlbWFpbmluZykge1xuICAgICAgICAgIGFuY2hvck9mZnNldCA9IGN1cnJlbnROb2RlU2l6ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzcGxpdFN0YXJ0ID0gaXNTZWxlY3RlZCA/IGFuY2hvck9mZnNldCAtIHJlbWFpbmluZyA6IDA7XG4gICAgICAgIGNvbnN0IHNwbGl0RW5kID0gaXNTZWxlY3RlZCA/IGFuY2hvck9mZnNldCA6IG9mZnNldDtcbiAgICAgICAgaWYgKGlzU2VsZWN0ZWQgJiYgc3BsaXRTdGFydCA9PT0gMCkge1xuICAgICAgICAgIGNvbnN0IFtleGNlc3NOb2RlXSA9IGN1cnJlbnROb2RlLnNwbGl0VGV4dChzcGxpdFN0YXJ0LCBzcGxpdEVuZCk7XG4gICAgICAgICAgZXhjZXNzTm9kZS5yZW1vdmUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBbLCBleGNlc3NOb2RlXSA9IGN1cnJlbnROb2RlLnNwbGl0VGV4dChzcGxpdFN0YXJ0LCBzcGxpdEVuZCk7XG4gICAgICAgICAgZXhjZXNzTm9kZS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgdGV4dE5vZGUgPSAkY3JlYXRlVGV4dE5vZGUoc2xpY2VkVGV4dCk7XG4gICAgICAgIGN1cnJlbnROb2RlLnJlcGxhY2UodGV4dE5vZGUpO1xuICAgICAgfVxuICAgICAgcmVtYWluaW5nID0gMDtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBUZXh0Tm9kZSdzIHN0eWxlIG9iamVjdCBhbmQgYWRkcyB0aGUgc3R5bGVzIHRvIHRoZSBDU1MuXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBUZXh0Tm9kZSB0byBhZGQgc3R5bGVzIHRvLlxuICovXG5mdW5jdGlvbiAkYWRkTm9kZVN0eWxlKG5vZGUpIHtcbiAgY29uc3QgQ1NTVGV4dCA9IG5vZGUuZ2V0U3R5bGUoKTtcbiAgY29uc3Qgc3R5bGVzID0gZ2V0U3R5bGVPYmplY3RGcm9tUmF3Q1NTKENTU1RleHQpO1xuICBDU1NfVE9fU1RZTEVTLnNldChDU1NUZXh0LCBzdHlsZXMpO1xufVxuXG4vKipcbiAqIEFwcGxpZXMgdGhlIHByb3ZpZGVkIHN0eWxlcyB0byB0aGUgZ2l2ZW4gVGV4dE5vZGUsIEVsZW1lbnROb2RlLCBvclxuICogY29sbGFwc2VkIFJhbmdlU2VsZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB0YXJnZXQgLSBUaGUgVGV4dE5vZGUsIEVsZW1lbnROb2RlLCBvciBjb2xsYXBzZWQgUmFuZ2VTZWxlY3Rpb24gdG8gYXBwbHkgdGhlIHN0eWxlcyB0b1xuICogQHBhcmFtIHBhdGNoIC0gVGhlIHBhdGNoIHRvIGFwcGx5LCB3aGljaCBjYW4gaW5jbHVkZSBtdWx0aXBsZSBzdHlsZXMuIFxcXFx7Q1NTUHJvcGVydHk6IHZhbHVlXFxcXH0gLiBDYW4gYWxzbyBhY2NlcHQgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIG5ldyBwcm9wZXJ0eSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gJHBhdGNoU3R5bGUodGFyZ2V0LCBwYXRjaCkge1xuICBpZiAoISgkaXNSYW5nZVNlbGVjdGlvbih0YXJnZXQpID8gdGFyZ2V0LmlzQ29sbGFwc2VkKCkgOiAkaXNUZXh0Tm9kZSh0YXJnZXQpIHx8ICRpc0VsZW1lbnROb2RlKHRhcmdldCkpKSB7XG4gICAgZm9ybWF0RGV2RXJyb3JNZXNzYWdlKGAkcGF0Y2hTdHlsZSBtdXN0IG9ubHkgYmUgY2FsbGVkIHdpdGggYSBUZXh0Tm9kZSwgRWxlbWVudE5vZGUsIG9yIGNvbGxhcHNlZCBSYW5nZVNlbGVjdGlvbmApO1xuICB9XG4gIGNvbnN0IHByZXZTdHlsZXMgPSBnZXRTdHlsZU9iamVjdEZyb21DU1MoJGlzUmFuZ2VTZWxlY3Rpb24odGFyZ2V0KSA/IHRhcmdldC5zdHlsZSA6ICRpc1RleHROb2RlKHRhcmdldCkgPyB0YXJnZXQuZ2V0U3R5bGUoKSA6IHRhcmdldC5nZXRUZXh0U3R5bGUoKSk7XG4gIGNvbnN0IG5ld1N0eWxlcyA9IE9iamVjdC5lbnRyaWVzKHBhdGNoKS5yZWR1Y2UoKHN0eWxlcywgW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgc3R5bGVzW2tleV0gPSB2YWx1ZShwcmV2U3R5bGVzW2tleV0sIHRhcmdldCk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHN0eWxlc1trZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZXNba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gc3R5bGVzO1xuICB9LCB7XG4gICAgLi4ucHJldlN0eWxlc1xuICB9KTtcbiAgY29uc3QgbmV3Q1NTVGV4dCA9IGdldENTU0Zyb21TdHlsZU9iamVjdChuZXdTdHlsZXMpO1xuICBpZiAoJGlzUmFuZ2VTZWxlY3Rpb24odGFyZ2V0KSB8fCAkaXNUZXh0Tm9kZSh0YXJnZXQpKSB7XG4gICAgdGFyZ2V0LnNldFN0eWxlKG5ld0NTU1RleHQpO1xuICB9IGVsc2Uge1xuICAgIHRhcmdldC5zZXRUZXh0U3R5bGUobmV3Q1NTVGV4dCk7XG4gIH1cbiAgQ1NTX1RPX1NUWUxFUy5zZXQobmV3Q1NTVGV4dCwgbmV3U3R5bGVzKTtcbn1cblxuLyoqXG4gKiBBcHBsaWVzIHRoZSBwcm92aWRlZCBzdHlsZXMgdG8gdGhlIFRleHROb2RlcyBpbiB0aGUgcHJvdmlkZWQgU2VsZWN0aW9uLlxuICogV2lsbCB1cGRhdGUgcGFydGlhbGx5IHNlbGVjdGVkIFRleHROb2RlcyBieSBzcGxpdHRpbmcgdGhlIFRleHROb2RlIGFuZCBhcHBseWluZ1xuICogdGhlIHN0eWxlcyB0byB0aGUgYXBwcm9wcmlhdGUgb25lLlxuICogQHBhcmFtIHNlbGVjdGlvbiAtIFRoZSBzZWxlY3RlZCBub2RlKHMpIHRvIHVwZGF0ZS5cbiAqIEBwYXJhbSBwYXRjaCAtIFRoZSBwYXRjaCB0byBhcHBseSwgd2hpY2ggY2FuIGluY2x1ZGUgbXVsdGlwbGUgc3R5bGVzLiBcXFxce0NTU1Byb3BlcnR5OiB2YWx1ZVxcXFx9IC4gQ2FuIGFsc28gYWNjZXB0IGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBuZXcgcHJvcGVydHkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uICRwYXRjaFN0eWxlVGV4dChzZWxlY3Rpb24sIHBhdGNoKSB7XG4gIGlmICgkaXNSYW5nZVNlbGVjdGlvbihzZWxlY3Rpb24pICYmIHNlbGVjdGlvbi5pc0NvbGxhcHNlZCgpKSB7XG4gICAgJHBhdGNoU3R5bGUoc2VsZWN0aW9uLCBwYXRjaCk7XG4gICAgY29uc3QgZW1wdHlOb2RlID0gc2VsZWN0aW9uLmFuY2hvci5nZXROb2RlKCk7XG4gICAgaWYgKCRpc0VsZW1lbnROb2RlKGVtcHR5Tm9kZSkgJiYgZW1wdHlOb2RlLmlzRW1wdHkoKSkge1xuICAgICAgJHBhdGNoU3R5bGUoZW1wdHlOb2RlLCBwYXRjaCk7XG4gICAgfVxuICB9XG4gICRmb3JFYWNoU2VsZWN0ZWRUZXh0Tm9kZSh0ZXh0Tm9kZSA9PiB7XG4gICAgJHBhdGNoU3R5bGUodGV4dE5vZGUsIHBhdGNoKTtcbiAgfSk7XG4gIGNvbnN0IG5vZGVzID0gc2VsZWN0aW9uLmdldE5vZGVzKCk7XG4gIGlmIChub2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgcGF0Y2hlZEVsZW1lbnRLZXlzID0gbmV3IFNldCgpO1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgaWYgKCEkaXNFbGVtZW50Tm9kZShub2RlKSB8fCAhbm9kZS5jYW5CZUVtcHR5KCkgfHwgbm9kZS5nZXRDaGlsZHJlblNpemUoKSAhPT0gMCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGtleSA9IG5vZGUuZ2V0S2V5KCk7XG4gICAgICBpZiAocGF0Y2hlZEVsZW1lbnRLZXlzLmhhcyhrZXkpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgcGF0Y2hlZEVsZW1lbnRLZXlzLmFkZChrZXkpO1xuICAgICAgJHBhdGNoU3R5bGUobm9kZSwgcGF0Y2gpO1xuICAgIH1cbiAgfVxufVxuZnVuY3Rpb24gJGZvckVhY2hTZWxlY3RlZFRleHROb2RlKGZuKSB7XG4gIGNvbnN0IHNlbGVjdGlvbiA9ICRnZXRTZWxlY3Rpb24oKTtcbiAgaWYgKCFzZWxlY3Rpb24pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgc2xpY2VkVGV4dE5vZGVzID0gbmV3IE1hcCgpO1xuICBjb25zdCBnZXRTbGljZUluZGljZXMgPSBub2RlID0+IHNsaWNlZFRleHROb2Rlcy5nZXQobm9kZS5nZXRLZXkoKSkgfHwgWzAsIG5vZGUuZ2V0VGV4dENvbnRlbnRTaXplKCldO1xuICBpZiAoJGlzUmFuZ2VTZWxlY3Rpb24oc2VsZWN0aW9uKSkge1xuICAgIGZvciAoY29uc3Qgc2xpY2Ugb2YgJGNhcmV0UmFuZ2VGcm9tU2VsZWN0aW9uKHNlbGVjdGlvbikuZ2V0VGV4dFNsaWNlcygpKSB7XG4gICAgICBpZiAoc2xpY2UpIHtcbiAgICAgICAgc2xpY2VkVGV4dE5vZGVzLnNldChzbGljZS5jYXJldC5vcmlnaW4uZ2V0S2V5KCksIHNsaWNlLmdldFNsaWNlSW5kaWNlcygpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgY29uc3Qgc2VsZWN0ZWROb2RlcyA9IHNlbGVjdGlvbi5nZXROb2RlcygpO1xuICBmb3IgKGNvbnN0IHNlbGVjdGVkTm9kZSBvZiBzZWxlY3RlZE5vZGVzKSB7XG4gICAgaWYgKCEoJGlzVGV4dE5vZGUoc2VsZWN0ZWROb2RlKSAmJiBzZWxlY3RlZE5vZGUuY2FuSGF2ZUZvcm1hdCgpKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNvbnN0IFtzdGFydE9mZnNldCwgZW5kT2Zmc2V0XSA9IGdldFNsaWNlSW5kaWNlcyhzZWxlY3RlZE5vZGUpO1xuICAgIC8vIE5vIGFjdHVhbCB0ZXh0IGlzIHNlbGVjdGVkLCBzbyBkbyBub3RoaW5nLlxuICAgIGlmIChlbmRPZmZzZXQgPT09IHN0YXJ0T2Zmc2V0KSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBUaGUgZW50aXJlIG5vZGUgaXMgc2VsZWN0ZWQgb3IgYSB0b2tlbi9zZWdtZW50LCBzbyBqdXN0IGZvcm1hdCBpdFxuICAgIGlmICgkaXNUb2tlbk9yU2VnbWVudGVkKHNlbGVjdGVkTm9kZSkgfHwgc3RhcnRPZmZzZXQgPT09IDAgJiYgZW5kT2Zmc2V0ID09PSBzZWxlY3RlZE5vZGUuZ2V0VGV4dENvbnRlbnRTaXplKCkpIHtcbiAgICAgIGZuKHNlbGVjdGVkTm9kZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFRoZSBub2RlIGlzIHBhcnRpYWxseSBzZWxlY3RlZCwgc28gc3BsaXQgaXQgaW50byB0d28gb3IgdGhyZWUgbm9kZXNcbiAgICAgIC8vIGFuZCBzdHlsZSB0aGUgc2VsZWN0ZWQgb25lLlxuICAgICAgY29uc3Qgc3BsaXROb2RlcyA9IHNlbGVjdGVkTm9kZS5zcGxpdFRleHQoc3RhcnRPZmZzZXQsIGVuZE9mZnNldCk7XG4gICAgICBjb25zdCByZXBsYWNlbWVudCA9IHNwbGl0Tm9kZXNbc3RhcnRPZmZzZXQgPT09IDAgPyAwIDogMV07XG4gICAgICBmbihyZXBsYWNlbWVudCk7XG4gICAgfVxuICB9XG4gIC8vIFByaW9yIHRvIE5vZGVDYXJldCAjNzA0NiB0aGlzIHdvdWxkIGhhdmUgYmVlbiBhIHNpZGUtZWZmZWN0XG4gIC8vIHNvIHdlIGRvIHRoaXMgZm9yIHRlc3QgY29tcGF0aWJpbGl0eS5cbiAgLy8gVE9ETzogd2UgbWF5IHdhbnQgdG8gY29uc2lkZXIgc2ltcGxpZnlpbmcgYnkgcmVtb3ZpbmcgdGhpc1xuICBpZiAoJGlzUmFuZ2VTZWxlY3Rpb24oc2VsZWN0aW9uKSAmJiBzZWxlY3Rpb24uYW5jaG9yLnR5cGUgPT09ICd0ZXh0JyAmJiBzZWxlY3Rpb24uZm9jdXMudHlwZSA9PT0gJ3RleHQnICYmIHNlbGVjdGlvbi5hbmNob3Iua2V5ID09PSBzZWxlY3Rpb24uZm9jdXMua2V5KSB7XG4gICAgJGVuc3VyZUZvcndhcmRSYW5nZVNlbGVjdGlvbihzZWxlY3Rpb24pO1xuICB9XG59XG5cbi8qKlxuICogRW5zdXJlIHRoYXQgdGhlIGdpdmVuIFJhbmdlU2VsZWN0aW9uIGlzIG5vdCBiYWNrd2FyZHMuIElmIGl0XG4gKiBpcyBiYWNrd2FyZHMsIHRoZW4gdGhlIGFuY2hvciBhbmQgZm9jdXMgcG9pbnRzIHdpbGwgYmUgc3dhcHBlZFxuICogaW4tcGxhY2UuIEVuc3VyaW5nIHRoYXQgdGhlIHNlbGVjdGlvbiBpcyBhIHdyaXRhYmxlIFJhbmdlU2VsZWN0aW9uXG4gKiBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgdGhlIGNhbGxlciAoZS5nLiBpbiBhIHJlYWQtb25seSBjb250ZXh0XG4gKiB5b3Ugd2lsbCB3YW50IHRvIGNsb25lICRnZXRTZWxlY3Rpb24oKSBiZWZvcmUgdXNpbmcgdGhpcykuXG4gKlxuICogQHBhcmFtIHNlbGVjdGlvbiBhIHdyaXRhYmxlIFJhbmdlU2VsZWN0aW9uXG4gKi9cbmZ1bmN0aW9uICRlbnN1cmVGb3J3YXJkUmFuZ2VTZWxlY3Rpb24oc2VsZWN0aW9uKSB7XG4gIGlmIChzZWxlY3Rpb24uaXNCYWNrd2FyZCgpKSB7XG4gICAgY29uc3Qge1xuICAgICAgYW5jaG9yLFxuICAgICAgZm9jdXNcbiAgICB9ID0gc2VsZWN0aW9uO1xuICAgIC8vIHN0YXNoIGZvciB0aGUgaW4tcGxhY2Ugc3dhcFxuICAgIGNvbnN0IHtcbiAgICAgIGtleSxcbiAgICAgIG9mZnNldCxcbiAgICAgIHR5cGVcbiAgICB9ID0gYW5jaG9yO1xuICAgIGFuY2hvci5zZXQoZm9jdXMua2V5LCBmb2N1cy5vZmZzZXQsIGZvY3VzLnR5cGUpO1xuICAgIGZvY3VzLnNldChrZXksIG9mZnNldCwgdHlwZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gJGNvcHlCbG9ja0Zvcm1hdEluZGVudChzcmNOb2RlLCBkZXN0Tm9kZSkge1xuICBjb25zdCBmb3JtYXQgPSBzcmNOb2RlLmdldEZvcm1hdFR5cGUoKTtcbiAgY29uc3QgaW5kZW50ID0gc3JjTm9kZS5nZXRJbmRlbnQoKTtcbiAgaWYgKGZvcm1hdCAhPT0gZGVzdE5vZGUuZ2V0Rm9ybWF0VHlwZSgpKSB7XG4gICAgZGVzdE5vZGUuc2V0Rm9ybWF0KGZvcm1hdCk7XG4gIH1cbiAgaWYgKGluZGVudCAhPT0gZGVzdE5vZGUuZ2V0SW5kZW50KCkpIHtcbiAgICBkZXN0Tm9kZS5zZXRJbmRlbnQoaW5kZW50KTtcbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGFsbCBub2RlcyBpbiB0aGUgc2VsZWN0aW9uIHRoYXQgYXJlIG9mIG9uZSBibG9jayB0eXBlIHRvIGFub3RoZXIuXG4gKiBAcGFyYW0gc2VsZWN0aW9uIC0gVGhlIHNlbGVjdGVkIGJsb2NrcyB0byBiZSBjb252ZXJ0ZWQuXG4gKiBAcGFyYW0gJGNyZWF0ZUVsZW1lbnQgLSBUaGUgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIHRoZSBub2RlLiBlZy4gJGNyZWF0ZVBhcmFncmFwaE5vZGUuXG4gKiBAcGFyYW0gJGFmdGVyQ3JlYXRlRWxlbWVudCAtIFRoZSBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgdGhlIG5ldyBub2RlIGJhc2VkIG9uIHRoZSBwcmV2aW91cyBvbmUgKCRjb3B5QmxvY2tGb3JtYXRJbmRlbnQgYnkgZGVmYXVsdClcbiAqL1xuZnVuY3Rpb24gJHNldEJsb2Nrc1R5cGUoc2VsZWN0aW9uLCAkY3JlYXRlRWxlbWVudCwgJGFmdGVyQ3JlYXRlRWxlbWVudCA9ICRjb3B5QmxvY2tGb3JtYXRJbmRlbnQpIHtcbiAgaWYgKHNlbGVjdGlvbiA9PT0gbnVsbCkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBTZWxlY3Rpb25zIHRlbmQgdG8gbm90IGluY2x1ZGUgdGhlaXIgY29udGFpbmluZyBibG9ja3Mgc28gd2UgZWZmZWN0aXZlbHlcbiAgLy8gZXhwYW5kIGl0IGhlcmVcbiAgY29uc3QgYW5jaG9yQW5kRm9jdXMgPSBzZWxlY3Rpb24uZ2V0U3RhcnRFbmRQb2ludHMoKTtcbiAgY29uc3QgYmxvY2tNYXAgPSBuZXcgTWFwKCk7XG4gIGxldCBuZXdTZWxlY3Rpb24gPSBudWxsO1xuICBpZiAoYW5jaG9yQW5kRm9jdXMpIHtcbiAgICBjb25zdCBbYW5jaG9yLCBmb2N1c10gPSBhbmNob3JBbmRGb2N1cztcbiAgICBuZXdTZWxlY3Rpb24gPSAkY3JlYXRlUmFuZ2VTZWxlY3Rpb24oKTtcbiAgICBuZXdTZWxlY3Rpb24uYW5jaG9yLnNldChhbmNob3Iua2V5LCBhbmNob3Iub2Zmc2V0LCBhbmNob3IudHlwZSk7XG4gICAgbmV3U2VsZWN0aW9uLmZvY3VzLnNldChmb2N1cy5rZXksIGZvY3VzLm9mZnNldCwgZm9jdXMudHlwZSk7XG4gICAgY29uc3QgYW5jaG9yQmxvY2sgPSAkZmluZE1hdGNoaW5nUGFyZW50KGFuY2hvci5nZXROb2RlKCksIElOVEVSTkFMXyRpc0Jsb2NrKTtcbiAgICBjb25zdCBmb2N1c0Jsb2NrID0gJGZpbmRNYXRjaGluZ1BhcmVudChmb2N1cy5nZXROb2RlKCksIElOVEVSTkFMXyRpc0Jsb2NrKTtcbiAgICBpZiAoJGlzRWxlbWVudE5vZGUoYW5jaG9yQmxvY2spKSB7XG4gICAgICBibG9ja01hcC5zZXQoYW5jaG9yQmxvY2suZ2V0S2V5KCksIGFuY2hvckJsb2NrKTtcbiAgICB9XG4gICAgaWYgKCRpc0VsZW1lbnROb2RlKGZvY3VzQmxvY2spKSB7XG4gICAgICBibG9ja01hcC5zZXQoZm9jdXNCbG9jay5nZXRLZXkoKSwgZm9jdXNCbG9jayk7XG4gICAgfVxuICB9XG4gIGZvciAoY29uc3Qgbm9kZSBvZiBzZWxlY3Rpb24uZ2V0Tm9kZXMoKSkge1xuICAgIGlmICgkaXNFbGVtZW50Tm9kZShub2RlKSAmJiBJTlRFUk5BTF8kaXNCbG9jayhub2RlKSkge1xuICAgICAgYmxvY2tNYXAuc2V0KG5vZGUuZ2V0S2V5KCksIG5vZGUpO1xuICAgIH0gZWxzZSBpZiAoYW5jaG9yQW5kRm9jdXMgPT09IG51bGwpIHtcbiAgICAgIGNvbnN0IGFuY2VzdG9yQmxvY2sgPSAkZmluZE1hdGNoaW5nUGFyZW50KG5vZGUsIElOVEVSTkFMXyRpc0Jsb2NrKTtcbiAgICAgIGlmICgkaXNFbGVtZW50Tm9kZShhbmNlc3RvckJsb2NrKSkge1xuICAgICAgICBibG9ja01hcC5zZXQoYW5jZXN0b3JCbG9jay5nZXRLZXkoKSwgYW5jZXN0b3JCbG9jayk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZvciAoY29uc3QgW2tleSwgcHJldk5vZGVdIG9mIGJsb2NrTWFwKSB7XG4gICAgY29uc3QgZWxlbWVudCA9ICRjcmVhdGVFbGVtZW50KCk7XG4gICAgJGFmdGVyQ3JlYXRlRWxlbWVudChwcmV2Tm9kZSwgZWxlbWVudCk7XG4gICAgcHJldk5vZGUucmVwbGFjZShlbGVtZW50LCB0cnVlKTtcbiAgICBpZiAobmV3U2VsZWN0aW9uKSB7XG4gICAgICBpZiAoa2V5ID09PSBuZXdTZWxlY3Rpb24uYW5jaG9yLmtleSkge1xuICAgICAgICBuZXdTZWxlY3Rpb24uYW5jaG9yLnNldChlbGVtZW50LmdldEtleSgpLCBuZXdTZWxlY3Rpb24uYW5jaG9yLm9mZnNldCwgbmV3U2VsZWN0aW9uLmFuY2hvci50eXBlKTtcbiAgICAgIH1cbiAgICAgIGlmIChrZXkgPT09IG5ld1NlbGVjdGlvbi5mb2N1cy5rZXkpIHtcbiAgICAgICAgbmV3U2VsZWN0aW9uLmZvY3VzLnNldChlbGVtZW50LmdldEtleSgpLCBuZXdTZWxlY3Rpb24uZm9jdXMub2Zmc2V0LCBuZXdTZWxlY3Rpb24uZm9jdXMudHlwZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGlmIChuZXdTZWxlY3Rpb24gJiYgc2VsZWN0aW9uLmlzKCRnZXRTZWxlY3Rpb24oKSkpIHtcbiAgICAkc2V0U2VsZWN0aW9uKG5ld1NlbGVjdGlvbik7XG4gIH1cbn1cbmZ1bmN0aW9uIGlzUG9pbnRBdHRhY2hlZChwb2ludCkge1xuICByZXR1cm4gcG9pbnQuZ2V0Tm9kZSgpLmlzQXR0YWNoZWQoKTtcbn1cbmZ1bmN0aW9uICRyZW1vdmVQYXJlbnRFbXB0eUVsZW1lbnRzKHN0YXJ0aW5nTm9kZSkge1xuICBsZXQgbm9kZSA9IHN0YXJ0aW5nTm9kZTtcbiAgd2hpbGUgKG5vZGUgIT09IG51bGwgJiYgISRpc1Jvb3RPclNoYWRvd1Jvb3Qobm9kZSkpIHtcbiAgICBjb25zdCBsYXRlc3QgPSBub2RlLmdldExhdGVzdCgpO1xuICAgIGNvbnN0IHBhcmVudE5vZGUgPSBub2RlLmdldFBhcmVudCgpO1xuICAgIGlmIChsYXRlc3QuZ2V0Q2hpbGRyZW5TaXplKCkgPT09IDApIHtcbiAgICAgIG5vZGUucmVtb3ZlKHRydWUpO1xuICAgIH1cbiAgICBub2RlID0gcGFyZW50Tm9kZTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkIEluIGZhdm9yIG9mICRzZXRCbG9ja1R5cGVzXG4gKiBXcmFwcyBhbGwgbm9kZXMgaW4gdGhlIHNlbGVjdGlvbiBpbnRvIGFub3RoZXIgbm9kZSBvZiB0aGUgdHlwZSByZXR1cm5lZCBieSBjcmVhdGVFbGVtZW50LlxuICogQHBhcmFtIHNlbGVjdGlvbiAtIFRoZSBzZWxlY3Rpb24gb2Ygbm9kZXMgdG8gYmUgd3JhcHBlZC5cbiAqIEBwYXJhbSBjcmVhdGVFbGVtZW50IC0gQSBmdW5jdGlvbiB0aGF0IGNyZWF0ZXMgdGhlIHdyYXBwaW5nIEVsZW1lbnROb2RlLiBlZy4gJGNyZWF0ZVBhcmFncmFwaE5vZGUuXG4gKiBAcGFyYW0gd3JhcHBpbmdFbGVtZW50IC0gQW4gZWxlbWVudCB0byBhcHBlbmQgdGhlIHdyYXBwZWQgc2VsZWN0aW9uIGFuZCBpdHMgY2hpbGRyZW4gdG8uXG4gKi9cbmZ1bmN0aW9uICR3cmFwTm9kZXMoc2VsZWN0aW9uLCBjcmVhdGVFbGVtZW50LCB3cmFwcGluZ0VsZW1lbnQgPSBudWxsKSB7XG4gIGNvbnN0IGFuY2hvckFuZEZvY3VzID0gc2VsZWN0aW9uLmdldFN0YXJ0RW5kUG9pbnRzKCk7XG4gIGNvbnN0IGFuY2hvciA9IGFuY2hvckFuZEZvY3VzID8gYW5jaG9yQW5kRm9jdXNbMF0gOiBudWxsO1xuICBjb25zdCBub2RlcyA9IHNlbGVjdGlvbi5nZXROb2RlcygpO1xuICBjb25zdCBub2Rlc0xlbmd0aCA9IG5vZGVzLmxlbmd0aDtcbiAgaWYgKGFuY2hvciAhPT0gbnVsbCAmJiAobm9kZXNMZW5ndGggPT09IDAgfHwgbm9kZXNMZW5ndGggPT09IDEgJiYgYW5jaG9yLnR5cGUgPT09ICdlbGVtZW50JyAmJiBhbmNob3IuZ2V0Tm9kZSgpLmdldENoaWxkcmVuU2l6ZSgpID09PSAwKSkge1xuICAgIGNvbnN0IHRhcmdldCA9IGFuY2hvci50eXBlID09PSAndGV4dCcgPyBhbmNob3IuZ2V0Tm9kZSgpLmdldFBhcmVudE9yVGhyb3coKSA6IGFuY2hvci5nZXROb2RlKCk7XG4gICAgY29uc3QgY2hpbGRyZW4gPSB0YXJnZXQuZ2V0Q2hpbGRyZW4oKTtcbiAgICBsZXQgZWxlbWVudCA9IGNyZWF0ZUVsZW1lbnQoKTtcbiAgICBlbGVtZW50LnNldEZvcm1hdCh0YXJnZXQuZ2V0Rm9ybWF0VHlwZSgpKTtcbiAgICBlbGVtZW50LnNldEluZGVudCh0YXJnZXQuZ2V0SW5kZW50KCkpO1xuICAgIGNoaWxkcmVuLmZvckVhY2goY2hpbGQgPT4gZWxlbWVudC5hcHBlbmQoY2hpbGQpKTtcbiAgICBpZiAod3JhcHBpbmdFbGVtZW50KSB7XG4gICAgICBlbGVtZW50ID0gd3JhcHBpbmdFbGVtZW50LmFwcGVuZChlbGVtZW50KTtcbiAgICB9XG4gICAgdGFyZ2V0LnJlcGxhY2UoZWxlbWVudCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGxldCB0b3BMZXZlbE5vZGUgPSBudWxsO1xuICBsZXQgZGVzY2VuZGFudHMgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlc0xlbmd0aDsgaSsrKSB7XG4gICAgY29uc3Qgbm9kZSA9IG5vZGVzW2ldO1xuICAgIC8vIERldGVybWluZSB3aGV0aGVyIHdyYXBwaW5nIGhhcyB0byBiZSBicm9rZW4gZG93biBpbnRvIG11bHRpcGxlIGNodW5rcy4gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZVxuICAgIC8vIHVzZXIgc2VsZWN0ZWQgbXVsdGlwbGUgUm9vdC1saWtlIG5vZGVzIHRoYXQgaGF2ZSB0byBiZSB0cmVhdGVkIHNlcGFyYXRlbHkgYXMgaWYgdGhleSBhcmVcbiAgICAvLyB0aGVpciBvd24gYnJhbmNoLiBJLmUuIHlvdSBkb24ndCB3YW50IHRvIHdyYXAgYSB3aG9sZSB0YWJsZSwgYnV0IHJhdGhlciB0aGUgY29udGVudHMgb2YgZWFjaFxuICAgIC8vIG9mIGVhY2ggb2YgdGhlIGNlbGwgbm9kZXMuXG4gICAgaWYgKCRpc1Jvb3RPclNoYWRvd1Jvb3Qobm9kZSkpIHtcbiAgICAgICR3cmFwTm9kZXNJbXBsKHNlbGVjdGlvbiwgZGVzY2VuZGFudHMsIGRlc2NlbmRhbnRzLmxlbmd0aCwgY3JlYXRlRWxlbWVudCwgd3JhcHBpbmdFbGVtZW50KTtcbiAgICAgIGRlc2NlbmRhbnRzID0gW107XG4gICAgICB0b3BMZXZlbE5vZGUgPSBub2RlO1xuICAgIH0gZWxzZSBpZiAodG9wTGV2ZWxOb2RlID09PSBudWxsIHx8IHRvcExldmVsTm9kZSAhPT0gbnVsbCAmJiAkaGFzQW5jZXN0b3Iobm9kZSwgdG9wTGV2ZWxOb2RlKSkge1xuICAgICAgZGVzY2VuZGFudHMucHVzaChub2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgJHdyYXBOb2Rlc0ltcGwoc2VsZWN0aW9uLCBkZXNjZW5kYW50cywgZGVzY2VuZGFudHMubGVuZ3RoLCBjcmVhdGVFbGVtZW50LCB3cmFwcGluZ0VsZW1lbnQpO1xuICAgICAgZGVzY2VuZGFudHMgPSBbbm9kZV07XG4gICAgfVxuICB9XG4gICR3cmFwTm9kZXNJbXBsKHNlbGVjdGlvbiwgZGVzY2VuZGFudHMsIGRlc2NlbmRhbnRzLmxlbmd0aCwgY3JlYXRlRWxlbWVudCwgd3JhcHBpbmdFbGVtZW50KTtcbn1cblxuLyoqXG4gKiBXcmFwcyBlYWNoIG5vZGUgaW50byBhIG5ldyBFbGVtZW50Tm9kZS5cbiAqIEBwYXJhbSBzZWxlY3Rpb24gLSBUaGUgc2VsZWN0aW9uIG9mIG5vZGVzIHRvIHdyYXAuXG4gKiBAcGFyYW0gbm9kZXMgLSBBbiBhcnJheSBvZiBub2RlcywgZ2VuZXJhbGx5IHRoZSBkZXNjZW5kYW50cyBvZiB0aGUgc2VsZWN0aW9uLlxuICogQHBhcmFtIG5vZGVzTGVuZ3RoIC0gVGhlIGxlbmd0aCBvZiBub2Rlcy5cbiAqIEBwYXJhbSBjcmVhdGVFbGVtZW50IC0gQSBmdW5jdGlvbiB0aGF0IGNyZWF0ZXMgdGhlIHdyYXBwaW5nIEVsZW1lbnROb2RlLiBlZy4gJGNyZWF0ZVBhcmFncmFwaE5vZGUuXG4gKiBAcGFyYW0gd3JhcHBpbmdFbGVtZW50IC0gQW4gZWxlbWVudCB0byB3cmFwIGFsbCB0aGUgbm9kZXMgaW50by5cbiAqIEByZXR1cm5zXG4gKi9cbmZ1bmN0aW9uICR3cmFwTm9kZXNJbXBsKHNlbGVjdGlvbiwgbm9kZXMsIG5vZGVzTGVuZ3RoLCBjcmVhdGVFbGVtZW50LCB3cmFwcGluZ0VsZW1lbnQgPSBudWxsKSB7XG4gIGlmIChub2Rlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgZmlyc3ROb2RlID0gbm9kZXNbMF07XG4gIGNvbnN0IGVsZW1lbnRNYXBwaW5nID0gbmV3IE1hcCgpO1xuICBjb25zdCBlbGVtZW50cyA9IFtdO1xuICAvLyBUaGUgYmVsb3cgbG9naWMgaXMgdG8gZmluZCB0aGUgcmlnaHQgdGFyZ2V0IGZvciB1cyB0b1xuICAvLyBlaXRoZXIgaW5zZXJ0QWZ0ZXIvaW5zZXJ0QmVmb3JlL2FwcGVuZCB0aGUgY29ycmVzcG9uZGluZ1xuICAvLyBlbGVtZW50cyB0by4gVGhpcyBpcyBtYWRlIG1vcmUgY29tcGxpY2F0ZWQgZHVlIHRvIG5lc3RlZFxuICAvLyBzdHJ1Y3R1cmVzLlxuICBsZXQgdGFyZ2V0ID0gJGlzRWxlbWVudE5vZGUoZmlyc3ROb2RlKSA/IGZpcnN0Tm9kZSA6IGZpcnN0Tm9kZS5nZXRQYXJlbnRPclRocm93KCk7XG4gIGlmICh0YXJnZXQuaXNJbmxpbmUoKSkge1xuICAgIHRhcmdldCA9IHRhcmdldC5nZXRQYXJlbnRPclRocm93KCk7XG4gIH1cbiAgbGV0IHRhcmdldElzUHJldlNpYmxpbmcgPSBmYWxzZTtcbiAgd2hpbGUgKHRhcmdldCAhPT0gbnVsbCkge1xuICAgIGNvbnN0IHByZXZTaWJsaW5nID0gdGFyZ2V0LmdldFByZXZpb3VzU2libGluZygpO1xuICAgIGlmIChwcmV2U2libGluZyAhPT0gbnVsbCkge1xuICAgICAgdGFyZ2V0ID0gcHJldlNpYmxpbmc7XG4gICAgICB0YXJnZXRJc1ByZXZTaWJsaW5nID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICB0YXJnZXQgPSB0YXJnZXQuZ2V0UGFyZW50T3JUaHJvdygpO1xuICAgIGlmICgkaXNSb290T3JTaGFkb3dSb290KHRhcmdldCkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBjb25zdCBlbXB0eUVsZW1lbnRzID0gbmV3IFNldCgpO1xuXG4gIC8vIEZpbmQgYW55IHRvcCBsZXZlbCBlbXB0eSBlbGVtZW50c1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzTGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG4gICAgaWYgKCRpc0VsZW1lbnROb2RlKG5vZGUpICYmIG5vZGUuZ2V0Q2hpbGRyZW5TaXplKCkgPT09IDApIHtcbiAgICAgIGVtcHR5RWxlbWVudHMuYWRkKG5vZGUuZ2V0S2V5KCkpO1xuICAgIH1cbiAgfVxuICBjb25zdCBtb3ZlZE5vZGVzID0gbmV3IFNldCgpO1xuXG4gIC8vIE1vdmUgb3V0IGFsbCBsZWFmIG5vZGVzIGludG8gb3VyIGVsZW1lbnRzIGFycmF5LlxuICAvLyBJZiB3ZSBmaW5kIGEgdG9wIGxldmVsIGVtcHR5IGVsZW1lbnQsIGFsc28gbW92ZSBtYWtlXG4gIC8vIGFuIGVsZW1lbnQgZm9yIHRoYXQuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXNMZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcbiAgICBsZXQgcGFyZW50ID0gbm9kZS5nZXRQYXJlbnQoKTtcbiAgICBpZiAocGFyZW50ICE9PSBudWxsICYmIHBhcmVudC5pc0lubGluZSgpKSB7XG4gICAgICBwYXJlbnQgPSBwYXJlbnQuZ2V0UGFyZW50KCk7XG4gICAgfVxuICAgIGlmIChwYXJlbnQgIT09IG51bGwgJiYgJGlzTGVhZk5vZGUobm9kZSkgJiYgIW1vdmVkTm9kZXMuaGFzKG5vZGUuZ2V0S2V5KCkpKSB7XG4gICAgICBjb25zdCBwYXJlbnRLZXkgPSBwYXJlbnQuZ2V0S2V5KCk7XG4gICAgICBpZiAoZWxlbWVudE1hcHBpbmcuZ2V0KHBhcmVudEtleSkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gY3JlYXRlRWxlbWVudCgpO1xuICAgICAgICB0YXJnZXRFbGVtZW50LnNldEZvcm1hdChwYXJlbnQuZ2V0Rm9ybWF0VHlwZSgpKTtcbiAgICAgICAgdGFyZ2V0RWxlbWVudC5zZXRJbmRlbnQocGFyZW50LmdldEluZGVudCgpKTtcbiAgICAgICAgZWxlbWVudHMucHVzaCh0YXJnZXRFbGVtZW50KTtcbiAgICAgICAgZWxlbWVudE1hcHBpbmcuc2V0KHBhcmVudEtleSwgdGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIC8vIE1vdmUgbm9kZSBhbmQgaXRzIHNpYmxpbmdzIHRvIHRoZSBuZXdcbiAgICAgICAgLy8gZWxlbWVudC5cbiAgICAgICAgcGFyZW50LmdldENoaWxkcmVuKCkuZm9yRWFjaChjaGlsZCA9PiB7XG4gICAgICAgICAgdGFyZ2V0RWxlbWVudC5hcHBlbmQoY2hpbGQpO1xuICAgICAgICAgIG1vdmVkTm9kZXMuYWRkKGNoaWxkLmdldEtleSgpKTtcbiAgICAgICAgICBpZiAoJGlzRWxlbWVudE5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAvLyBTa2lwIG5lc3RlZCBsZWFmIG5vZGVzIGlmIHRoZSBwYXJlbnQgaGFzIGFscmVhZHkgYmVlbiBtb3ZlZFxuICAgICAgICAgICAgY2hpbGQuZ2V0Q2hpbGRyZW5LZXlzKCkuZm9yRWFjaChrZXkgPT4gbW92ZWROb2Rlcy5hZGQoa2V5KSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJHJlbW92ZVBhcmVudEVtcHR5RWxlbWVudHMocGFyZW50KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGVtcHR5RWxlbWVudHMuaGFzKG5vZGUuZ2V0S2V5KCkpKSB7XG4gICAgICBpZiAoISRpc0VsZW1lbnROb2RlKG5vZGUpKSB7XG4gICAgICAgIGZvcm1hdERldkVycm9yTWVzc2FnZShgRXhwZWN0ZWQgbm9kZSBpbiBlbXB0eUVsZW1lbnRzIHRvIGJlIGFuIEVsZW1lbnROb2RlYCk7XG4gICAgICB9XG4gICAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gY3JlYXRlRWxlbWVudCgpO1xuICAgICAgdGFyZ2V0RWxlbWVudC5zZXRGb3JtYXQobm9kZS5nZXRGb3JtYXRUeXBlKCkpO1xuICAgICAgdGFyZ2V0RWxlbWVudC5zZXRJbmRlbnQobm9kZS5nZXRJbmRlbnQoKSk7XG4gICAgICBlbGVtZW50cy5wdXNoKHRhcmdldEVsZW1lbnQpO1xuICAgICAgbm9kZS5yZW1vdmUodHJ1ZSk7XG4gICAgfVxuICB9XG4gIGlmICh3cmFwcGluZ0VsZW1lbnQgIT09IG51bGwpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gZWxlbWVudHNbaV07XG4gICAgICB3cmFwcGluZ0VsZW1lbnQuYXBwZW5kKGVsZW1lbnQpO1xuICAgIH1cbiAgfVxuICBsZXQgbGFzdEVsZW1lbnQgPSBudWxsO1xuXG4gIC8vIElmIG91ciB0YXJnZXQgaXMgUm9vdC1saWtlLCBsZXQncyBzZWUgaWYgd2UgY2FuIHJlLWFkanVzdFxuICAvLyBzbyB0aGF0IHRoZSB0YXJnZXQgaXMgdGhlIGZpcnN0IGNoaWxkIGluc3RlYWQuXG4gIGlmICgkaXNSb290T3JTaGFkb3dSb290KHRhcmdldCkpIHtcbiAgICBpZiAodGFyZ2V0SXNQcmV2U2libGluZykge1xuICAgICAgaWYgKHdyYXBwaW5nRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICB0YXJnZXQuaW5zZXJ0QWZ0ZXIod3JhcHBpbmdFbGVtZW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAobGV0IGkgPSBlbGVtZW50cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgICAgICB0YXJnZXQuaW5zZXJ0QWZ0ZXIoZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZmlyc3RDaGlsZCA9IHRhcmdldC5nZXRGaXJzdENoaWxkKCk7XG4gICAgICBpZiAoJGlzRWxlbWVudE5vZGUoZmlyc3RDaGlsZCkpIHtcbiAgICAgICAgdGFyZ2V0ID0gZmlyc3RDaGlsZDtcbiAgICAgIH1cbiAgICAgIGlmIChmaXJzdENoaWxkID09PSBudWxsKSB7XG4gICAgICAgIGlmICh3cmFwcGluZ0VsZW1lbnQpIHtcbiAgICAgICAgICB0YXJnZXQuYXBwZW5kKHdyYXBwaW5nRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgdGFyZ2V0LmFwcGVuZChlbGVtZW50KTtcbiAgICAgICAgICAgIGxhc3RFbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh3cmFwcGluZ0VsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgICAgICBmaXJzdENoaWxkLmluc2VydEJlZm9yZSh3cmFwcGluZ0VsZW1lbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgICAgICAgIGZpcnN0Q2hpbGQuaW5zZXJ0QmVmb3JlKGVsZW1lbnQpO1xuICAgICAgICAgICAgbGFzdEVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAod3JhcHBpbmdFbGVtZW50KSB7XG4gICAgICB0YXJnZXQuaW5zZXJ0QWZ0ZXIod3JhcHBpbmdFbGVtZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgaSA9IGVsZW1lbnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgICAgdGFyZ2V0Lmluc2VydEFmdGVyKGVsZW1lbnQpO1xuICAgICAgICBsYXN0RWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGNvbnN0IHByZXZTZWxlY3Rpb24gPSAkZ2V0UHJldmlvdXNTZWxlY3Rpb24oKTtcbiAgaWYgKCRpc1JhbmdlU2VsZWN0aW9uKHByZXZTZWxlY3Rpb24pICYmIGlzUG9pbnRBdHRhY2hlZChwcmV2U2VsZWN0aW9uLmFuY2hvcikgJiYgaXNQb2ludEF0dGFjaGVkKHByZXZTZWxlY3Rpb24uZm9jdXMpKSB7XG4gICAgJHNldFNlbGVjdGlvbihwcmV2U2VsZWN0aW9uLmNsb25lKCkpO1xuICB9IGVsc2UgaWYgKGxhc3RFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgbGFzdEVsZW1lbnQuc2VsZWN0RW5kKCk7XG4gIH0gZWxzZSB7XG4gICAgc2VsZWN0aW9uLmRpcnR5ID0gdHJ1ZTtcbiAgfVxufVxuXG4vKipcbiAqIFRlc3RzIGlmIHRoZSBzZWxlY3Rpb24ncyBwYXJlbnQgZWxlbWVudCBoYXMgdmVydGljYWwgd3JpdGluZyBtb2RlLlxuICogQHBhcmFtIHNlbGVjdGlvbiAtIFRoZSBzZWxlY3Rpb24gd2hvc2UgcGFyZW50IHRvIHRlc3QuXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBzZWxlY3Rpb24ncyBwYXJlbnQgaGFzIHZlcnRpY2FsIHdyaXRpbmcgbW9kZSAod3JpdGluZy1tb2RlOiB2ZXJ0aWNhbC1ybCksIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZnVuY3Rpb24gJGlzRWRpdG9yVmVydGljYWxPcmllbnRhdGlvbihzZWxlY3Rpb24pIHtcbiAgY29uc3QgY29tcHV0ZWRTdHlsZSA9ICRnZXRDb21wdXRlZFN0eWxlKHNlbGVjdGlvbik7XG4gIHJldHVybiBjb21wdXRlZFN0eWxlICE9PSBudWxsICYmIGNvbXB1dGVkU3R5bGUud3JpdGluZ01vZGUgPT09ICd2ZXJ0aWNhbC1ybCc7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgY29tcHV0ZWQgRE9NIHN0eWxlcyBvZiB0aGUgcGFyZW50IG9mIHRoZSBzZWxlY3Rpb24ncyBhbmNob3Igbm9kZS5cbiAqIEBwYXJhbSBzZWxlY3Rpb24gLSBUaGUgc2VsZWN0aW9uIHRvIGNoZWNrIHRoZSBzdHlsZXMgZm9yLlxuICogQHJldHVybnMgdGhlIGNvbXB1dGVkIHN0eWxlcyBvZiB0aGUgbm9kZSBvciBudWxsIGlmIHRoZXJlIGlzIG5vIERPTSBlbGVtZW50IG9yIG5vIGRlZmF1bHQgdmlldyBmb3IgdGhlIGRvY3VtZW50LlxuICovXG5mdW5jdGlvbiAkZ2V0Q29tcHV0ZWRTdHlsZShzZWxlY3Rpb24pIHtcbiAgY29uc3QgYW5jaG9yTm9kZSA9IHNlbGVjdGlvbi5hbmNob3IuZ2V0Tm9kZSgpO1xuICBpZiAoJGlzRWxlbWVudE5vZGUoYW5jaG9yTm9kZSkpIHtcbiAgICByZXR1cm4gJGdldENvbXB1dGVkU3R5bGVGb3JFbGVtZW50KGFuY2hvck5vZGUpO1xuICB9XG4gIHJldHVybiAkZ2V0Q29tcHV0ZWRTdHlsZUZvclBhcmVudChhbmNob3JOb2RlKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmVzIGlmIHRoZSBkZWZhdWx0IGNoYXJhY3RlciBzZWxlY3Rpb24gc2hvdWxkIGJlIG92ZXJyaWRkZW4uIFVzZWQgd2l0aCBEZWNvcmF0b3JOb2Rlc1xuICogQHBhcmFtIHNlbGVjdGlvbiAtIFRoZSBzZWxlY3Rpb24gd2hvc2UgZGVmYXVsdCBjaGFyYWN0ZXIgc2VsZWN0aW9uIG1heSBuZWVkIHRvIGJlIG92ZXJyaWRkZW4uXG4gKiBAcGFyYW0gaXNCYWNrd2FyZCAtIElzIHRoZSBzZWxlY3Rpb24gYmFja3dhcmRzICh0aGUgZm9jdXMgY29tZXMgYmVmb3JlIHRoZSBhbmNob3IpP1xuICogQHJldHVybnMgdHJ1ZSBpZiBpdCBzaG91bGQgYmUgb3ZlcnJpZGRlbiwgZmFsc2UgaWYgbm90LlxuICovXG5mdW5jdGlvbiAkc2hvdWxkT3ZlcnJpZGVEZWZhdWx0Q2hhcmFjdGVyU2VsZWN0aW9uKHNlbGVjdGlvbiwgaXNCYWNrd2FyZCkge1xuICBjb25zdCBpc1ZlcnRpY2FsID0gJGlzRWRpdG9yVmVydGljYWxPcmllbnRhdGlvbihzZWxlY3Rpb24pO1xuXG4gIC8vIEluIHZlcnRpY2FsIHdyaXRpbmcgbW9kZSwgd2UgYWRqdXN0IHRoZSBkaXJlY3Rpb24gZm9yIGNvcnJlY3QgY2FyZXQgbW92ZW1lbnRcbiAgbGV0IGFkanVzdGVkSXNCYWNrd2FyZCA9IGlzVmVydGljYWwgPyAhaXNCYWNrd2FyZCA6IGlzQmFja3dhcmQ7XG5cbiAgLy8gSW4gcmlnaHQtdG8tbGVmdCB3cml0aW5nIG1vZGUsIHdlIGludmVydCB0aGUgZGlyZWN0aW9uIGZvciBjb3JyZWN0IGNhcmV0IG1vdmVtZW50XG4gIGlmICgkaXNQYXJlbnRFbGVtZW50UlRMKHNlbGVjdGlvbikpIHtcbiAgICBhZGp1c3RlZElzQmFja3dhcmQgPSAhYWRqdXN0ZWRJc0JhY2t3YXJkO1xuICB9XG4gIGNvbnN0IGZvY3VzQ2FyZXQgPSAkY2FyZXRGcm9tUG9pbnQoc2VsZWN0aW9uLmZvY3VzLCBhZGp1c3RlZElzQmFja3dhcmQgPyAncHJldmlvdXMnIDogJ25leHQnKTtcbiAgaWYgKCRpc0V4dGVuZGFibGVUZXh0UG9pbnRDYXJldChmb2N1c0NhcmV0KSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGNvbnN0IG5leHRDYXJldCBvZiAkZXh0ZW5kQ2FyZXRUb1JhbmdlKGZvY3VzQ2FyZXQpKSB7XG4gICAgaWYgKCRpc0NoaWxkQ2FyZXQobmV4dENhcmV0KSkge1xuICAgICAgcmV0dXJuICFuZXh0Q2FyZXQub3JpZ2luLmlzSW5saW5lKCk7XG4gICAgfSBlbHNlIGlmICgkaXNFbGVtZW50Tm9kZShuZXh0Q2FyZXQub3JpZ2luKSkge1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIGlmICgkaXNEZWNvcmF0b3JOb2RlKG5leHRDYXJldC5vcmlnaW4pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgYnJlYWs7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIE1vdmVzIHRoZSBzZWxlY3Rpb24gYWNjb3JkaW5nIHRvIHRoZSBhcmd1bWVudHMuXG4gKiBAcGFyYW0gc2VsZWN0aW9uIC0gVGhlIHNlbGVjdGVkIHRleHQgb3Igbm9kZXMuXG4gKiBAcGFyYW0gaXNIb2xkaW5nU2hpZnQgLSBJcyB0aGUgc2hpZnQga2V5IGJlaW5nIGhlbGQgZG93biBkdXJpbmcgdGhlIG9wZXJhdGlvbi5cbiAqIEBwYXJhbSBpc0JhY2t3YXJkIC0gSXMgdGhlIHNlbGVjdGlvbiBzZWxlY3RlZCBiYWNrd2FyZHMgKHRoZSBmb2N1cyBjb21lcyBiZWZvcmUgdGhlIGFuY2hvcik/XG4gKiBAcGFyYW0gZ3JhbnVsYXJpdHkgLSBUaGUgZGlzdGFuY2UgdG8gYWRqdXN0IHRoZSBjdXJyZW50IHNlbGVjdGlvbi5cbiAqL1xuZnVuY3Rpb24gJG1vdmVDYXJldFNlbGVjdGlvbihzZWxlY3Rpb24sIGlzSG9sZGluZ1NoaWZ0LCBpc0JhY2t3YXJkLCBncmFudWxhcml0eSkge1xuICBzZWxlY3Rpb24ubW9kaWZ5KGlzSG9sZGluZ1NoaWZ0ID8gJ2V4dGVuZCcgOiAnbW92ZScsIGlzQmFja3dhcmQsIGdyYW51bGFyaXR5KTtcbn1cblxuLyoqXG4gKiBUZXN0cyBhIHBhcmVudCBlbGVtZW50IGZvciByaWdodCB0byBsZWZ0IGRpcmVjdGlvbi5cbiAqIEBwYXJhbSBzZWxlY3Rpb24gLSBUaGUgc2VsZWN0aW9uIHdob3NlIHBhcmVudCBpcyB0byBiZSB0ZXN0ZWQuXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBzZWxlY3Rpb25zJyBwYXJlbnQgZWxlbWVudCBoYXMgYSBkaXJlY3Rpb24gb2YgJ3J0bCcgKHJpZ2h0IHRvIGxlZnQpLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmZ1bmN0aW9uICRpc1BhcmVudEVsZW1lbnRSVEwoc2VsZWN0aW9uKSB7XG4gIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSAkZ2V0Q29tcHV0ZWRTdHlsZShzZWxlY3Rpb24pO1xuICByZXR1cm4gY29tcHV0ZWRTdHlsZSAhPT0gbnVsbCAmJiBjb21wdXRlZFN0eWxlLmRpcmVjdGlvbiA9PT0gJ3J0bCc7XG59XG5cbi8qKlxuICogTW92ZXMgc2VsZWN0aW9uIGJ5IGNoYXJhY3RlciBhY2NvcmRpbmcgdG8gYXJndW1lbnRzLlxuICogQHBhcmFtIHNlbGVjdGlvbiAtIFRoZSBzZWxlY3Rpb24gb2YgdGhlIGNoYXJhY3RlcnMgdG8gbW92ZS5cbiAqIEBwYXJhbSBpc0hvbGRpbmdTaGlmdCAtIElzIHRoZSBzaGlmdCBrZXkgYmVpbmcgaGVsZCBkb3duIGR1cmluZyB0aGUgb3BlcmF0aW9uLlxuICogQHBhcmFtIGlzQmFja3dhcmQgLSBJcyB0aGUgc2VsZWN0aW9uIGJhY2t3YXJkICh0aGUgZm9jdXMgY29tZXMgYmVmb3JlIHRoZSBhbmNob3IpP1xuICovXG5mdW5jdGlvbiAkbW92ZUNoYXJhY3RlcihzZWxlY3Rpb24sIGlzSG9sZGluZ1NoaWZ0LCBpc0JhY2t3YXJkKSB7XG4gIGNvbnN0IGlzUlRMID0gJGlzUGFyZW50RWxlbWVudFJUTChzZWxlY3Rpb24pO1xuICBjb25zdCBpc1ZlcnRpY2FsID0gJGlzRWRpdG9yVmVydGljYWxPcmllbnRhdGlvbihzZWxlY3Rpb24pO1xuXG4gIC8vIEluIHZlcnRpY2FsLXJsIHdyaXRpbmcgbW9kZSwgYXJyb3cga2V5IGRpcmVjdGlvbnMgbmVlZCB0byBiZSBmbGlwcGVkXG4gIC8vIHRvIG1hdGNoIHRoZSB2aXN1YWwgZmxvdyBvZiB0ZXh0ICh0b3AgdG8gYm90dG9tLCByaWdodCB0byBsZWZ0KVxuICBsZXQgYWRqdXN0ZWRJc0JhY2t3YXJkO1xuICBpZiAoaXNWZXJ0aWNhbCkge1xuICAgIC8vIEluIHZlcnRpY2FsLXJsIG1vZGUsIHdlIG5lZWQgdG8gY29tcGxldGVseSBpbnZlcnQgdGhlIGRpcmVjdGlvblxuICAgIC8vIExlZnQgYXJyb3cgKGJhY2t3YXJkKSBzaG91bGQgbW92ZSBkb3duIChmb3J3YXJkKVxuICAgIC8vIFJpZ2h0IGFycm93IChmb3J3YXJkKSBzaG91bGQgbW92ZSB1cCAoYmFja3dhcmQpXG4gICAgYWRqdXN0ZWRJc0JhY2t3YXJkID0gIWlzQmFja3dhcmQ7XG4gIH0gZWxzZSBpZiAoaXNSVEwpIHtcbiAgICAvLyBJbiBob3Jpem9udGFsIFJUTCBtb2RlLCB1c2UgdGhlIHN0YW5kYXJkIFJUTCBiZWhhdmlvclxuICAgIGFkanVzdGVkSXNCYWNrd2FyZCA9ICFpc0JhY2t3YXJkO1xuICB9IGVsc2Uge1xuICAgIC8vIFN0YW5kYXJkIExUUiBob3Jpem9udGFsIHRleHRcbiAgICBhZGp1c3RlZElzQmFja3dhcmQgPSBpc0JhY2t3YXJkO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIGRpcmVjdGlvbiBhZGp1c3RtZW50IHRvIG1vdmUgdGhlIGNhcmV0XG4gICRtb3ZlQ2FyZXRTZWxlY3Rpb24oc2VsZWN0aW9uLCBpc0hvbGRpbmdTaGlmdCwgYWRqdXN0ZWRJc0JhY2t3YXJkLCAnY2hhcmFjdGVyJyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3VycmVudCB2YWx1ZSBvZiBhIENTUyBwcm9wZXJ0eSBmb3IgTm9kZXMsIGlmIHNldC4gSWYgbm90IHNldCwgaXQgcmV0dXJucyB0aGUgZGVmYXVsdFZhbHVlLlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB3aG9zZSBzdHlsZSB2YWx1ZSB0byBnZXQuXG4gKiBAcGFyYW0gc3R5bGVQcm9wZXJ0eSAtIFRoZSBDU1Mgc3R5bGUgcHJvcGVydHkuXG4gKiBAcGFyYW0gZGVmYXVsdFZhbHVlIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBwcm9wZXJ0eS5cbiAqIEByZXR1cm5zIFRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgZm9yIG5vZGUuXG4gKi9cbmZ1bmN0aW9uICRnZXROb2RlU3R5bGVWYWx1ZUZvclByb3BlcnR5KG5vZGUsIHN0eWxlUHJvcGVydHksIGRlZmF1bHRWYWx1ZSkge1xuICBjb25zdCBjc3MgPSBub2RlLmdldFN0eWxlKCk7XG4gIGNvbnN0IHN0eWxlT2JqZWN0ID0gZ2V0U3R5bGVPYmplY3RGcm9tQ1NTKGNzcyk7XG4gIGlmIChzdHlsZU9iamVjdCAhPT0gbnVsbCkge1xuICAgIHJldHVybiBzdHlsZU9iamVjdFtzdHlsZVByb3BlcnR5XSB8fCBkZWZhdWx0VmFsdWU7XG4gIH1cbiAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjdXJyZW50IHZhbHVlIG9mIGEgQ1NTIHByb3BlcnR5IGZvciBUZXh0Tm9kZXMgaW4gdGhlIFNlbGVjdGlvbiwgaWYgc2V0LiBJZiBub3Qgc2V0LCBpdCByZXR1cm5zIHRoZSBkZWZhdWx0VmFsdWUuXG4gKiBJZiBhbGwgVGV4dE5vZGVzIGRvIG5vdCBoYXZlIHRoZSBzYW1lIHZhbHVlLCBpdCByZXR1cm5zIGFuIGVtcHR5IHN0cmluZy5cbiAqIEBwYXJhbSBzZWxlY3Rpb24gLSBUaGUgc2VsZWN0aW9uIG9mIFRleHROb2RlcyB3aG9zZSB2YWx1ZSB0byBmaW5kLlxuICogQHBhcmFtIHN0eWxlUHJvcGVydHkgLSBUaGUgQ1NTIHN0eWxlIHByb3BlcnR5LlxuICogQHBhcmFtIGRlZmF1bHRWYWx1ZSAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgcHJvcGVydHksIGRlZmF1bHRzIHRvIGFuIGVtcHR5IHN0cmluZy5cbiAqIEByZXR1cm5zIFRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgZm9yIHRoZSBzZWxlY3RlZCBUZXh0Tm9kZXMuXG4gKi9cbmZ1bmN0aW9uICRnZXRTZWxlY3Rpb25TdHlsZVZhbHVlRm9yUHJvcGVydHkoc2VsZWN0aW9uLCBzdHlsZVByb3BlcnR5LCBkZWZhdWx0VmFsdWUgPSAnJykge1xuICBsZXQgc3R5bGVWYWx1ZSA9IG51bGw7XG4gIGNvbnN0IG5vZGVzID0gc2VsZWN0aW9uLmdldE5vZGVzKCk7XG4gIGNvbnN0IGFuY2hvciA9IHNlbGVjdGlvbi5hbmNob3I7XG4gIGNvbnN0IGZvY3VzID0gc2VsZWN0aW9uLmZvY3VzO1xuICBjb25zdCBpc0JhY2t3YXJkID0gc2VsZWN0aW9uLmlzQmFja3dhcmQoKTtcbiAgY29uc3QgZW5kT2Zmc2V0ID0gaXNCYWNrd2FyZCA/IGZvY3VzLm9mZnNldCA6IGFuY2hvci5vZmZzZXQ7XG4gIGNvbnN0IGVuZE5vZGUgPSBpc0JhY2t3YXJkID8gZm9jdXMuZ2V0Tm9kZSgpIDogYW5jaG9yLmdldE5vZGUoKTtcbiAgaWYgKCRpc1JhbmdlU2VsZWN0aW9uKHNlbGVjdGlvbikgJiYgc2VsZWN0aW9uLmlzQ29sbGFwc2VkKCkgJiYgc2VsZWN0aW9uLnN0eWxlICE9PSAnJykge1xuICAgIGNvbnN0IGNzcyA9IHNlbGVjdGlvbi5zdHlsZTtcbiAgICBjb25zdCBzdHlsZU9iamVjdCA9IGdldFN0eWxlT2JqZWN0RnJvbUNTUyhjc3MpO1xuICAgIGlmIChzdHlsZU9iamVjdCAhPT0gbnVsbCAmJiBzdHlsZVByb3BlcnR5IGluIHN0eWxlT2JqZWN0KSB7XG4gICAgICByZXR1cm4gc3R5bGVPYmplY3Rbc3R5bGVQcm9wZXJ0eV07XG4gICAgfVxuICB9XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG5cbiAgICAvLyBpZiBubyBhY3R1YWwgY2hhcmFjdGVycyBpbiB0aGUgZW5kIG5vZGUgYXJlIHNlbGVjdGVkLCB3ZSBkb24ndFxuICAgIC8vIGluY2x1ZGUgaXQgaW4gdGhlIHNlbGVjdGlvbiBmb3IgcHVycG9zZXMgb2YgZGV0ZXJtaW5pbmcgc3R5bGVcbiAgICAvLyB2YWx1ZVxuICAgIGlmIChpICE9PSAwICYmIGVuZE9mZnNldCA9PT0gMCAmJiBub2RlLmlzKGVuZE5vZGUpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKCRpc1RleHROb2RlKG5vZGUpKSB7XG4gICAgICBjb25zdCBub2RlU3R5bGVWYWx1ZSA9ICRnZXROb2RlU3R5bGVWYWx1ZUZvclByb3BlcnR5KG5vZGUsIHN0eWxlUHJvcGVydHksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICBpZiAoc3R5bGVWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICBzdHlsZVZhbHVlID0gbm9kZVN0eWxlVmFsdWU7XG4gICAgICB9IGVsc2UgaWYgKHN0eWxlVmFsdWUgIT09IG5vZGVTdHlsZVZhbHVlKSB7XG4gICAgICAgIC8vIG11bHRpcGxlIHRleHQgbm9kZXMgYXJlIGluIHRoZSBzZWxlY3Rpb24gYW5kIHRoZXkgZG9uJ3QgYWxsXG4gICAgICAgIC8vIGhhdmUgdGhlIHNhbWUgc3R5bGUuXG4gICAgICAgIHN0eWxlVmFsdWUgPSAnJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBzdHlsZVZhbHVlID09PSBudWxsID8gZGVmYXVsdFZhbHVlIDogc3R5bGVWYWx1ZTtcbn1cblxuLyoqXG4gKiBDb3B5cmlnaHQgKGMpIE1ldGEgUGxhdGZvcm1zLCBJbmMuIGFuZCBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqL1xuXG4vKiogQGRlcHJlY2F0ZWQgcmVuYW1lZCB0byB7QGxpbmsgJHRyaW1UZXh0Q29udGVudEZyb21BbmNob3J9IGJ5IEBsZXhpY2FsL2VzbGludC1wbHVnaW4gcnVsZXMtb2YtbGV4aWNhbCAqL1xuY29uc3QgdHJpbVRleHRDb250ZW50RnJvbUFuY2hvciA9ICR0cmltVGV4dENvbnRlbnRGcm9tQW5jaG9yO1xuXG5leHBvcnQgeyAkYWRkTm9kZVN0eWxlLCAkY29weUJsb2NrRm9ybWF0SW5kZW50LCAkZW5zdXJlRm9yd2FyZFJhbmdlU2VsZWN0aW9uLCAkZm9yRWFjaFNlbGVjdGVkVGV4dE5vZGUsICRnZXRDb21wdXRlZFN0eWxlRm9yRWxlbWVudCwgJGdldENvbXB1dGVkU3R5bGVGb3JQYXJlbnQsICRnZXRTZWxlY3Rpb25TdHlsZVZhbHVlRm9yUHJvcGVydHksICRpc0F0Tm9kZUVuZCwgJGlzUGFyZW50RWxlbWVudFJUTCwgJGlzUGFyZW50UlRMLCAkbW92ZUNhcmV0U2VsZWN0aW9uLCAkbW92ZUNoYXJhY3RlciwgJHBhdGNoU3R5bGVUZXh0LCAkc2V0QmxvY2tzVHlwZSwgJHNob3VsZE92ZXJyaWRlRGVmYXVsdENoYXJhY3RlclNlbGVjdGlvbiwgJHNsaWNlU2VsZWN0ZWRUZXh0Tm9kZUNvbnRlbnQsICR0cmltVGV4dENvbnRlbnRGcm9tQW5jaG9yLCAkd3JhcE5vZGVzLCBjcmVhdGVET01SYW5nZSwgY3JlYXRlUmVjdHNGcm9tRE9NUmFuZ2UsIGdldENTU0Zyb21TdHlsZU9iamVjdCwgZ2V0U3R5bGVPYmplY3RGcm9tQ1NTLCB0cmltVGV4dENvbnRlbnRGcm9tQW5jaG9yIH07XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(rsc)/./node_modules/.pnpm/@lexical+selection@0.41.0/node_modules/@lexical/selection/LexicalSelection.dev.mjs\n");
|
|
|
|
/***/ })
|
|
|
|
};
|
|
; |