jiskattema/spot

View on GitHub
dist/js/npm.dialog-polyfill.chunk.9c69110c8617b21fae07.js

Summary

Maintainability
A
0 mins
Test Coverage

TODO found
Open

(window.webpackJsonp=window.webpackJsonp||[]).push([["npm.dialog-polyfill"],{"5c00":function(module,exports,__webpack_require__){eval("var __WEBPACK_AMD_DEFINE_RESULT__;(function() {\n\n  // nb. This is for IE10 and lower _only_.\n  var supportCustomEvent = window.CustomEvent;\n  if (!supportCustomEvent || typeof supportCustomEvent === 'object') {\n    supportCustomEvent = function CustomEvent(event, x) {\n      x = x || {};\n      var ev = document.createEvent('CustomEvent');\n      ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null);\n      return ev;\n    };\n    supportCustomEvent.prototype = window.Event.prototype;\n  }\n\n  /**\n   * @param {Element} el to check for stacking context\n   * @return {boolean} whether this el or its parents creates a stacking context\n   */\n  function createsStackingContext(el) {\n    while (el && el !== document.body) {\n      var s = window.getComputedStyle(el);\n      var invalid = function(k, ok) {\n        return !(s[k] === undefined || s[k] === ok);\n      }\n      if (s.opacity < 1 ||\n          invalid('zIndex', 'auto') ||\n          invalid('transform', 'none') ||\n          invalid('mixBlendMode', 'normal') ||\n          invalid('filter', 'none') ||\n          invalid('perspective', 'none') ||\n          s['isolation'] === 'isolate' ||\n          s.position === 'fixed' ||\n          s.webkitOverflowScrolling === 'touch') {\n        return true;\n      }\n      el = el.parentElement;\n    }\n    return false;\n  }\n\n  /**\n   * Finds the nearest <dialog> from the passed element.\n   *\n   * @param {Element} el to search from\n   * @return {HTMLDialogElement} dialog found\n   */\n  function findNearestDialog(el) {\n    while (el) {\n      if (el.localName === 'dialog') {\n        return /** @type {HTMLDialogElement} */ (el);\n      }\n      el = el.parentElement;\n    }\n    return null;\n  }\n\n  /**\n   * Blur the specified element, as long as it's not the HTML body element.\n   * This works around an IE9/10 bug - blurring the body causes Windows to\n   * blur the whole application.\n   *\n   * @param {Element} el to blur\n   */\n  function safeBlur(el) {\n    if (el && el.blur && el !== document.body) {\n      el.blur();\n    }\n  }\n\n  /**\n   * @param {!NodeList} nodeList to search\n   * @param {Node} node to find\n   * @return {boolean} whether node is inside nodeList\n   */\n  function inNodeList(nodeList, node) {\n    for (var i = 0; i < nodeList.length; ++i) {\n      if (nodeList[i] === node) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * @param {HTMLFormElement} el to check\n   * @return {boolean} whether this form has method=\"dialog\"\n   */\n  function isFormMethodDialog(el) {\n    if (!el || !el.hasAttribute('method')) {\n      return false;\n    }\n    return el.getAttribute('method').toLowerCase() === 'dialog';\n  }\n\n  /**\n   * @param {!HTMLDialogElement} dialog to upgrade\n   * @constructor\n   */\n  function dialogPolyfillInfo(dialog) {\n    this.dialog_ = dialog;\n    this.replacedStyleTop_ = false;\n    this.openAsModal_ = false;\n\n    // Set a11y role. Browsers that support dialog implicitly know this already.\n    if (!dialog.hasAttribute('role')) {\n      dialog.setAttribute('role', 'dialog');\n    }\n\n    dialog.show = this.show.bind(this);\n    dialog.showModal = this.showModal.bind(this);\n    dialog.close = this.close.bind(this);\n\n    if (!('returnValue' in dialog)) {\n      dialog.returnValue = '';\n    }\n\n    if ('MutationObserver' in window) {\n      var mo = new MutationObserver(this.maybeHideModal.bind(this));\n      mo.observe(dialog, {attributes: true, attributeFilter: ['open']});\n    } else {\n      // IE10 and below support. Note that DOMNodeRemoved etc fire _before_ removal. They also\n      // seem to fire even if the element was removed as part of a parent removal. Use the removed\n      // events to force downgrade (useful if removed/immediately added).\n      var removed = false;\n      var cb = function() {\n        removed ? this.downgradeModal() : this.maybeHideModal();\n        removed = false;\n      }.bind(this);\n      var timeout;\n      var delayModel = function(ev) {\n        if (ev.target !== dialog) { return; }  // not for a child element\n        var cand = 'DOMNodeRemoved';\n        removed |= (ev.type.substr(0, cand.length) === cand);\n        window.clearTimeout(timeout);\n        timeout = window.setTimeout(cb, 0);\n      };\n      ['DOMAttrModified', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument'].forEach(function(name) {\n        dialog.addEventListener(name, delayModel);\n      });\n    }\n    // Note that the DOM is observed inside DialogManager while any dialog\n    // is being displayed as a modal, to catch modal removal from the DOM.\n\n    Object.defineProperty(dialog, 'open', {\n      set: this.setOpen.bind(this),\n      get: dialog.hasAttribute.bind(dialog, 'open')\n    });\n\n    this.backdrop_ = document.createElement('div');\n    this.backdrop_.className = 'backdrop';\n    this.backdrop_.addEventListener('click', this.backdropClick_.bind(this));\n  }\n\n  dialogPolyfillInfo.prototype = {\n\n    get dialog() {\n      return this.dialog_;\n    },\n\n    /**\n     * Maybe remove this dialog from the modal top layer. This is called when\n     * a modal dialog may no longer be tenable, e.g., when the dialog is no\n     * longer open or is no longer part of the DOM.\n     */\n    maybeHideModal: function() {\n      if (this.dialog_.hasAttribute('open') && document.body.contains(this.dialog_)) { return; }\n      this.downgradeModal();\n    },\n\n    /**\n     * Remove this dialog from the modal top layer, leaving it as a non-modal.\n     */\n    downgradeModal: function() {\n      if (!this.openAsModal_) { return; }\n      this.openAsModal_ = false;\n      this.dialog_.style.zIndex = '';\n\n      // This won't match the native <dialog> exactly because if the user set top on a centered\n      // polyfill dialog, that top gets thrown away when the dialog is closed. Not sure it's\n      // possible to polyfill this perfectly.\n      if (this.replacedStyleTop_) {\n        this.dialog_.style.top = '';\n        this.replacedStyleTop_ = false;\n      }\n\n      // Clear the backdrop and remove from the manager.\n      this.backdrop_.parentNode && this.backdrop_.parentNode.removeChild(this.backdrop_);\n      dialogPolyfill.dm.removeDialog(this);\n    },\n\n    /**\n     * @param {boolean} value whether to open or close this dialog\n     */\n    setOpen: function(value) {\n      if (value) {\n        this.dialog_.hasAttribute('open') || this.dialog_.setAttribute('open', '');\n      } else {\n        this.dialog_.removeAttribute('open');\n        this.maybeHideModal();  // nb. redundant with MutationObserver\n      }\n    },\n\n    /**\n     * Handles clicks on the fake .backdrop element, redirecting them as if\n     * they were on the dialog itself.\n     *\n     * @param {!Event} e to redirect\n     */\n    backdropClick_: function(e) {\n      if (!this.dialog_.hasAttribute('tabindex')) {\n        // Clicking on the backdrop should move the implicit cursor, even if dialog cannot be\n        // focused. Create a fake thing to focus on. If the backdrop was _before_ the dialog, this\n        // would not be needed - clicks would move the implicit cursor there.\n        var fake = document.createElement('div');\n        this.dialog_.insertBefore(fake, this.dialog_.firstChild);\n        fake.tabIndex = -1;\n        fake.focus();\n        this.dialog_.removeChild(fake);\n      } else {\n        this.dialog_.focus();\n      }\n\n      var redirectedEvent = document.createEvent('MouseEvents');\n      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,\n          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,\n          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);\n      this.dialog_.dispatchEvent(redirectedEvent);\n      e.stopPropagation();\n    },\n\n    /**\n     * Focuses on the first focusable element within the dialog. This will always blur the current\n     * focus, even if nothing within the dialog is found.\n     */\n    focus_: function() {\n      // Find element with `autofocus` attribute, or fall back to the first form/tabindex control.\n      var target = this.dialog_.querySelector('[autofocus]:not([disabled])');\n      if (!target && this.dialog_.tabIndex >= 0) {\n        target = this.dialog_;\n      }\n      if (!target) {\n        // Note that this is 'any focusable area'. This list is probably not exhaustive, but the\n        // alternative involves stepping through and trying to focus everything.\n        var opts = ['button', 'input', 'keygen', 'select', 'textarea'];\n        var query = opts.map(function(el) {\n          return el + ':not([disabled])';\n        });\n        // TODO(samthor): tabindex values that are not numeric are not focusable.\n        query.push('[tabindex]:not([disabled]):not([tabindex=\"\"])');  // tabindex != \"\", not disabled\n        target = this.dialog_.querySelector(query.join(', '));\n      }\n      safeBlur(document.activeElement);\n      target && target.focus();\n    },\n\n    /**\n     * Sets the zIndex for the backdrop and dialog.\n     *\n     * @param {number} dialogZ\n     * @param {number} backdropZ\n     */\n    updateZIndex: function(dialogZ, backdropZ) {\n      if (dialogZ < backdropZ) {\n        throw new Error('dialogZ should never be < backdropZ');\n      }\n      this.dialog_.style.zIndex = dialogZ;\n      this.backdrop_.style.zIndex = backdropZ;\n    },\n\n    /**\n     * Shows the dialog. If the dialog is already open, this does nothing.\n     */\n    show: function() {\n      if (!this.dialog_.open) {\n        this.setOpen(true);\n        this.focus_();\n      }\n    },\n\n    /**\n     * Show this dialog modally.\n     */\n    showModal: function() {\n      if (this.dialog_.hasAttribute('open')) {\n        throw new Error('Failed to execute \\'showModal\\' on dialog: The element is already open, and therefore cannot be opened modally.');\n      }\n      if (!document.body.contains(this.dialog_)) {\n        throw new Error('Failed to execute \\'showModal\\' on dialog: The element is not in a Document.');\n      }\n      if (!dialogPolyfill.dm.pushDialog(this)) {\n        throw new Error('Failed to execute \\'showModal\\' on dialog: There are too many open modal dialogs.');\n      }\n\n      if (createsStackingContext(this.dialog_.parentElement)) {\n        console.warn('A dialog is being shown inside a stacking context. ' +\n            'This may cause it to be unusable. For more information, see this link: ' +\n            'https://github.com/GoogleChrome/dialog-polyfill/#stacking-context');\n      }\n\n      this.setOpen(true);\n      this.openAsModal_ = true;\n\n      // Optionally center vertically, relative to the current viewport.\n      if (dialogPolyfill.needsCentering(this.dialog_)) {\n        dialogPolyfill.reposition(this.dialog_);\n        this.replacedStyleTop_ = true;\n      } else {\n        this.replacedStyleTop_ = false;\n      }\n\n      // Insert backdrop.\n      this.dialog_.parentNode.insertBefore(this.backdrop_, this.dialog_.nextSibling);\n\n      // Focus on whatever inside the dialog.\n      this.focus_();\n    },\n\n    /**\n     * Closes this HTMLDialogElement. This is optional vs clearing the open\n     * attribute, however this fires a 'close' event.\n     *\n     * @param {string=} opt_returnValue to use as the returnValue\n     */\n    close: function(opt_returnValue) {\n      if (!this.dialog_.hasAttribute('open')) {\n        throw new Error('Failed to execute \\'close\\' on dialog: The element does not have an \\'open\\' attribute, and therefore cannot be closed.');\n      }\n      this.setOpen(false);\n\n      // Leave returnValue untouched in case it was set directly on the element\n      if (opt_returnValue !== undefined) {\n        this.dialog_.returnValue = opt_returnValue;\n      }\n\n      // Triggering \"close\" event for any attached listeners on the <dialog>.\n      var closeEvent = new supportCustomEvent('close', {\n        bubbles: false,\n        cancelable: false\n      });\n      this.dialog_.dispatchEvent(closeEvent);\n    }\n\n  };\n\n  var dialogPolyfill = {};\n\n  dialogPolyfill.reposition = function(element) {\n    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;\n    element.style.top = Math.max(scrollTop, topValue) + 'px';\n  };\n\n  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {\n    for (var i = 0; i < document.styleSheets.length; ++i) {\n      var styleSheet = document.styleSheets[i];\n      var cssRules = null;\n      // Some browsers throw on cssRules.\n      try {\n        cssRules = styleSheet.cssRules;\n      } catch (e) {}\n      if (!cssRules) { continue; }\n      for (var j = 0; j < cssRules.length; ++j) {\n        var rule = cssRules[j];\n        var selectedNodes = null;\n        // Ignore errors on invalid selector texts.\n        try {\n          selectedNodes = document.querySelectorAll(rule.selectorText);\n        } catch(e) {}\n        if (!selectedNodes || !inNodeList(selectedNodes, element)) {\n          continue;\n        }\n        var cssTop = rule.style.getPropertyValue('top');\n        var cssBottom = rule.style.getPropertyValue('bottom');\n        if ((cssTop && cssTop !== 'auto') || (cssBottom && cssBottom !== 'auto')) {\n          return true;\n        }\n      }\n    }\n    return false;\n  };\n\n  dialogPolyfill.needsCentering = function(dialog) {\n    var computedStyle = window.getComputedStyle(dialog);\n    if (computedStyle.position !== 'absolute') {\n      return false;\n    }\n\n    // We must determine whether the top/bottom specified value is non-auto.  In\n    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but\n    // Firefox returns the used value. So we do this crazy thing instead: check\n    // the inline style and then go through CSS rules.\n    if ((dialog.style.top !== 'auto' && dialog.style.top !== '') ||\n        (dialog.style.bottom !== 'auto' && dialog.style.bottom !== '')) {\n      return false;\n    }\n    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);\n  };\n\n  /**\n   * @param {!Element} element to force upgrade\n   */\n  dialogPolyfill.forceRegisterDialog = function(element) {\n    if (window.HTMLDialogElement || element.showModal) {\n      console.warn('This browser already supports <dialog>, the polyfill ' +\n          'may not work correctly', element);\n    }\n    if (element.localName !== 'dialog') {\n      throw new Error('Failed to register dialog: The element is not a dialog.');\n    }\n    new dialogPolyfillInfo(/** @type {!HTMLDialogElement} */ (element));\n  };\n\n  /**\n   * @param {!Element} element to upgrade, if necessary\n   */\n  dialogPolyfill.registerDialog = function(element) {\n    if (!element.showModal) {\n      dialogPolyfill.forceRegisterDialog(element);\n    }\n  };\n\n  /**\n   * @constructor\n   */\n  dialogPolyfill.DialogManager = function() {\n    /** @type {!Array<!dialogPolyfillInfo>} */\n    this.pendingDialogStack = [];\n\n    var checkDOM = this.checkDOM_.bind(this);\n\n    // The overlay is used to simulate how a modal dialog blocks the document.\n    // The blocking dialog is positioned on top of the overlay, and the rest of\n    // the dialogs on the pending dialog stack are positioned below it. In the\n    // actual implementation, the modal dialog stacking is controlled by the\n    // top layer, where z-index has no effect.\n    this.overlay = document.createElement('div');\n    this.overlay.className = '_dialog_overlay';\n    this.overlay.addEventListener('click', function(e) {\n      this.forwardTab_ = undefined;\n      e.stopPropagation();\n      checkDOM([]);  // sanity-check DOM\n    }.bind(this));\n\n    this.handleKey_ = this.handleKey_.bind(this);\n    this.handleFocus_ = this.handleFocus_.bind(this);\n\n    this.zIndexLow_ = 100000;\n    this.zIndexHigh_ = 100000 + 150;\n\n    this.forwardTab_ = undefined;\n\n    if ('MutationObserver' in window) {\n      this.mo_ = new MutationObserver(function(records) {\n        var removed = [];\n        records.forEach(function(rec) {\n          for (var i = 0, c; c = rec.removedNodes[i]; ++i) {\n            if (!(c instanceof Element)) {\n              continue;\n            } else if (c.localName === 'dialog') {\n              removed.push(c);\n            }\n            removed = removed.concat(c.querySelectorAll('dialog'));\n          }\n        });\n        removed.length && checkDOM(removed);\n      });\n    }\n  };\n\n  /**\n   * Called on the first modal dialog being shown. Adds the overlay and related\n   * handlers.\n   */\n  dialogPolyfill.DialogManager.prototype.blockDocument = function() {\n    document.documentElement.addEventListener('focus', this.handleFocus_, true);\n    document.addEventListener('keydown', this.handleKey_);\n    this.mo_ && this.mo_.observe(document, {childList: true, subtree: true});\n  };\n\n  /**\n   * Called on the first modal dialog being removed, i.e., when no more modal\n   * dialogs are visible.\n   */\n  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {\n    document.documentElement.removeEventListener('focus', this.handleFocus_, true);\n    document.removeEventListener('keydown', this.handleKey_);\n    this.mo_ && this.mo_.disconnect();\n  };\n\n  /**\n   * Updates the stacking of all known dialogs.\n   */\n  dialogPolyfill.DialogManager.prototype.updateStacking = function() {\n    var zIndex = this.zIndexHigh_;\n\n    for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {\n      dpi.updateZIndex(--zIndex, --zIndex);\n      if (i === 0) {\n        this.overlay.style.zIndex = --zIndex;\n      }\n    }\n\n    // Make the overlay a sibling of the dialog itself.\n    var last = this.pendingDialogStack[0];\n    if (last) {\n      var p = last.dialog.parentNode || document.body;\n      p.appendChild(this.overlay);\n    } else if (this.overlay.parentNode) {\n      this.overlay.parentNode.removeChild(this.overlay);\n    }\n  };\n\n  /**\n   * @param {Element} candidate to check if contained or is the top-most modal dialog\n   * @return {boolean} whether candidate is contained in top dialog\n   */\n  dialogPolyfill.DialogManager.prototype.containedByTopDialog_ = function(candidate) {\n    while (candidate = findNearestDialog(candidate)) {\n      for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {\n        if (dpi.dialog === candidate) {\n          return i === 0;  // only valid if top-most\n        }\n      }\n      candidate = candidate.parentElement;\n    }\n    return false;\n  };\n\n  dialogPolyfill.DialogManager.prototype.handleFocus_ = function(event) {\n    if (this.containedByTopDialog_(event.target)) { return; }\n\n    event.preventDefault();\n    event.stopPropagation();\n    safeBlur(/** @type {Element} */ (event.target));\n\n    if (this.forwardTab_ === undefined) { return; }  // move focus only from a tab key\n\n    var dpi = this.pendingDialogStack[0];\n    var dialog = dpi.dialog;\n    var position = dialog.compareDocumentPosition(event.target);\n    if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n      if (this.forwardTab_) {  // forward\n        dpi.focus_();\n      } else {  // backwards\n        document.documentElement.focus();\n      }\n    } else {\n      // TODO: Focus after the dialog, is ignored.\n    }\n\n    return false;\n  };\n\n  dialogPolyfill.DialogManager.prototype.handleKey_ = function(event) {\n    this.forwardTab_ = undefined;\n    if (event.keyCode === 27) {\n      event.preventDefault();\n      event.stopPropagation();\n      var cancelEvent = new supportCustomEvent('cancel', {\n        bubbles: false,\n        cancelable: true\n      });\n      var dpi = this.pendingDialogStack[0];\n      if (dpi && dpi.dialog.dispatchEvent(cancelEvent)) {\n        dpi.dialog.close();\n      }\n    } else if (event.keyCode === 9) {\n      this.forwardTab_ = !event.shiftKey;\n    }\n  };\n\n  /**\n   * Finds and downgrades any known modal dialogs that are no longer displayed. Dialogs that are\n   * removed and immediately readded don't stay modal, they become normal.\n   *\n   * @param {!Array<!HTMLDialogElement>} removed that have definitely been removed\n   */\n  dialogPolyfill.DialogManager.prototype.checkDOM_ = function(removed) {\n    // This operates on a clone because it may cause it to change. Each change also calls\n    // updateStacking, which only actually needs to happen once. But who removes many modal dialogs\n    // at a time?!\n    var clone = this.pendingDialogStack.slice();\n    clone.forEach(function(dpi) {\n      if (removed.indexOf(dpi.dialog) !== -1) {\n        dpi.downgradeModal();\n      } else {\n        dpi.maybeHideModal();\n      }\n    });\n  };\n\n  /**\n   * @param {!dialogPolyfillInfo} dpi\n   * @return {boolean} whether the dialog was allowed\n   */\n  dialogPolyfill.DialogManager.prototype.pushDialog = function(dpi) {\n    var allowed = (this.zIndexHigh_ - this.zIndexLow_) / 2 - 1;\n    if (this.pendingDialogStack.length >= allowed) {\n      return false;\n    }\n    if (this.pendingDialogStack.unshift(dpi) === 1) {\n      this.blockDocument();\n    }\n    this.updateStacking();\n    return true;\n  };\n\n  /**\n   * @param {!dialogPolyfillInfo} dpi\n   */\n  dialogPolyfill.DialogManager.prototype.removeDialog = function(dpi) {\n    var index = this.pendingDialogStack.indexOf(dpi);\n    if (index === -1) { return; }\n\n    this.pendingDialogStack.splice(index, 1);\n    if (this.pendingDialogStack.length === 0) {\n      this.unblockDocument();\n    }\n    this.updateStacking();\n  };\n\n  dialogPolyfill.dm = new dialogPolyfill.DialogManager();\n  dialogPolyfill.formSubmitter = null;\n  dialogPolyfill.useValue = null;\n\n  /**\n   * Installs global handlers, such as click listers and native method overrides. These are needed\n   * even if a no dialog is registered, as they deal with <form method=\"dialog\">.\n   */\n  if (window.HTMLDialogElement === undefined) {\n\n    /**\n     * If HTMLFormElement translates method=\"DIALOG\" into 'get', then replace the descriptor with\n     * one that returns the correct value.\n     */\n    var testForm = document.createElement('form');\n    testForm.setAttribute('method', 'dialog');\n    if (testForm.method !== 'dialog') {\n      var methodDescriptor = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'method');\n      if (methodDescriptor) {\n        // nb. Some older iOS and older PhantomJS fail to return the descriptor. Don't do anything\n        // and don't bother to update the element.\n        var realGet = methodDescriptor.get;\n        methodDescriptor.get = function() {\n          if (isFormMethodDialog(this)) {\n            return 'dialog';\n          }\n          return realGet.call(this);\n        };\n        var realSet = methodDescriptor.set;\n        methodDescriptor.set = function(v) {\n          if (typeof v === 'string' && v.toLowerCase() === 'dialog') {\n            return this.setAttribute('method', v);\n          }\n          return realSet.call(this, v);\n        };\n        Object.defineProperty(HTMLFormElement.prototype, 'method', methodDescriptor);\n      }\n    }\n\n    /**\n     * Global 'click' handler, to capture the <input type=\"submit\"> or <button> element which has\n     * submitted a <form method=\"dialog\">. Needed as Safari and others don't report this inside\n     * document.activeElement.\n     */\n    document.addEventListener('click', function(ev) {\n      dialogPolyfill.formSubmitter = null;\n      dialogPolyfill.useValue = null;\n      if (ev.defaultPrevented) { return; }  // e.g. a submit which prevents default submission\n\n      var target = /** @type {Element} */ (ev.target);\n      if (!target || !isFormMethodDialog(target.form)) { return; }\n\n      var valid = (target.type === 'submit' && ['button', 'input'].indexOf(target.localName) > -1);\n      if (!valid) {\n        if (!(target.localName === 'input' && target.type === 'image')) { return; }\n        // this is a <input type=\"image\">, which can submit forms\n        dialogPolyfill.useValue = ev.offsetX + ',' + ev.offsetY;\n      }\n\n      var dialog = findNearestDialog(target);\n      if (!dialog) { return; }\n\n      dialogPolyfill.formSubmitter = target;\n    }, false);\n\n    /**\n     * Replace the native HTMLFormElement.submit() method, as it won't fire the\n     * submit event and give us a chance to respond.\n     */\n    var nativeFormSubmit = HTMLFormElement.prototype.submit;\n    var replacementFormSubmit = function () {\n      if (!isFormMethodDialog(this)) {\n        return nativeFormSubmit.call(this);\n      }\n      var dialog = findNearestDialog(this);\n      dialog && dialog.close();\n    };\n    HTMLFormElement.prototype.submit = replacementFormSubmit;\n\n    /**\n     * Global form 'dialog' method handler. Closes a dialog correctly on submit\n     * and possibly sets its return value.\n     */\n    document.addEventListener('submit', function(ev) {\n      var form = /** @type {HTMLFormElement} */ (ev.target);\n      if (!isFormMethodDialog(form)) { return; }\n      ev.preventDefault();\n\n      var dialog = findNearestDialog(form);\n      if (!dialog) { return; }\n\n      // Forms can only be submitted via .submit() or a click (?), but anyway: sanity-check that\n      // the submitter is correct before using its value as .returnValue.\n      var s = dialogPolyfill.formSubmitter;\n      if (s && s.form === form) {\n        dialog.close(dialogPolyfill.useValue || s.value);\n      } else {\n        dialog.close();\n      }\n      dialogPolyfill.formSubmitter = null;\n    }, true);\n  }\n\n  dialogPolyfill['forceRegisterDialog'] = dialogPolyfill.forceRegisterDialog;\n  dialogPolyfill['registerDialog'] = dialogPolyfill.registerDialog;\n\n  if ( true && 'amd' in __webpack_require__(/*! !webpack amd define */ \"30d1\")) {\n    // AMD support\n    !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { return dialogPolyfill; }).call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n  } else if ( true && typeof module['exports'] === 'object') {\n    // CommonJS support\n    module['exports'] = dialogPolyfill;\n  } else {\n    // all others\n    window['dialogPolyfill'] = dialogPolyfill;\n  }\n})();\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNWMwMC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9kaWFsb2ctcG9seWZpbGwvZGlhbG9nLXBvbHlmaWxsLmpzP2M5NzAiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCkge1xuXG4gIC8vIG5iLiBUaGlzIGlzIGZvciBJRTEwIGFuZCBsb3dlciBfb25seV8uXG4gIHZhciBzdXBwb3J0Q3VzdG9tRXZlbnQgPSB3aW5kb3cuQ3VzdG9tRXZlbnQ7XG4gIGlmICghc3VwcG9ydEN1c3RvbUV2ZW50IHx8IHR5cGVvZiBzdXBwb3J0Q3VzdG9tRXZlbnQgPT09ICdvYmplY3QnKSB7XG4gICAgc3VwcG9ydEN1c3RvbUV2ZW50ID0gZnVuY3Rpb24gQ3VzdG9tRXZlbnQoZXZlbnQsIHgpIHtcbiAgICAgIHggPSB4IHx8IHt9O1xuICAgICAgdmFyIGV2ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0N1c3RvbUV2ZW50Jyk7XG4gICAgICBldi5pbml0Q3VzdG9tRXZlbnQoZXZlbnQsICEheC5idWJibGVzLCAhIXguY2FuY2VsYWJsZSwgeC5kZXRhaWwgfHwgbnVsbCk7XG4gICAgICByZXR1cm4gZXY7XG4gICAgfTtcbiAgICBzdXBwb3J0Q3VzdG9tRXZlbnQucHJvdG90eXBlID0gd2luZG93LkV2ZW50LnByb3RvdHlwZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsIHRvIGNoZWNrIGZvciBzdGFja2luZyBjb250ZXh0XG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IHdoZXRoZXIgdGhpcyBlbCBvciBpdHMgcGFyZW50cyBjcmVhdGVzIGEgc3RhY2tpbmcgY29udGV4dFxuICAgKi9cbiAgZnVuY3Rpb24gY3JlYXRlc1N0YWNraW5nQ29udGV4dChlbCkge1xuICAgIHdoaWxlIChlbCAmJiBlbCAhPT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgdmFyIHMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICB2YXIgaW52YWxpZCA9IGZ1bmN0aW9uKGssIG9rKSB7XG4gICAgICAgIHJldHVybiAhKHNba10gPT09IHVuZGVmaW5lZCB8fCBzW2tdID09PSBvayk7XG4gICAgICB9XG4gICAgICBpZiAocy5vcGFjaXR5IDwgMSB8fFxuICAgICAgICAgIGludmFsaWQoJ3pJbmRleCcsICdhdXRvJykgfHxcbiAgICAgICAgICBpbnZhbGlkKCd0cmFuc2Zvcm0nLCAnbm9uZScpIHx8XG4gICAgICAgICAgaW52YWxpZCgnbWl4QmxlbmRNb2RlJywgJ25vcm1hbCcpIHx8XG4gICAgICAgICAgaW52YWxpZCgnZmlsdGVyJywgJ25vbmUnKSB8fFxuICAgICAgICAgIGludmFsaWQoJ3BlcnNwZWN0aXZlJywgJ25vbmUnKSB8fFxuICAgICAgICAgIHNbJ2lzb2xhdGlvbiddID09PSAnaXNvbGF0ZScgfHxcbiAgICAgICAgICBzLnBvc2l0aW9uID09PSAnZml4ZWQnIHx8XG4gICAgICAgICAgcy53ZWJraXRPdmVyZmxvd1Njcm9sbGluZyA9PT0gJ3RvdWNoJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGVsID0gZWwucGFyZW50RWxlbWVudDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBuZWFyZXN0IDxkaWFsb2c+IGZyb20gdGhlIHBhc3NlZCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsIHRvIHNlYXJjaCBmcm9tXG4gICAqIEByZXR1cm4ge0hUTUxEaWFsb2dFbGVtZW50fSBkaWFsb2cgZm91bmRcbiAgICovXG4gIGZ1bmN0aW9uIGZpbmROZWFyZXN0RGlhbG9nKGVsKSB7XG4gICAgd2hpbGUgKGVsKSB7XG4gICAgICBpZiAoZWwubG9jYWxOYW1lID09PSAnZGlhbG9nJykge1xuICAgICAgICByZXR1cm4gLyoqIEB0eXBlIHtIVE1MRGlhbG9nRWxlbWVudH0gKi8gKGVsKTtcbiAgICAgIH1cbiAgICAgIGVsID0gZWwucGFyZW50RWxlbWVudDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQmx1ciB0aGUgc3BlY2lmaWVkIGVsZW1lbnQsIGFzIGxvbmcgYXMgaXQncyBub3QgdGhlIEhUTUwgYm9keSBlbGVtZW50LlxuICAgKiBUaGlzIHdvcmtzIGFyb3VuZCBhbiBJRTkvMTAgYnVnIC0gYmx1cnJpbmcgdGhlIGJvZHkgY2F1c2VzIFdpbmRvd3MgdG9cbiAgICogYmx1ciB0aGUgd2hvbGUgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWwgdG8gYmx1clxuICAgKi9cbiAgZnVuY3Rpb24gc2FmZUJsdXIoZWwpIHtcbiAgICBpZiAoZWwgJiYgZWwuYmx1ciAmJiBlbCAhPT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgZWwuYmx1cigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFOb2RlTGlzdH0gbm9kZUxpc3QgdG8gc2VhcmNoXG4gICAqIEBwYXJhbSB7Tm9kZX0gbm9kZSB0byBmaW5kXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IHdoZXRoZXIgbm9kZSBpcyBpbnNpZGUgbm9kZUxpc3RcbiAgICovXG4gIGZ1bmN0aW9uIGluTm9kZUxpc3Qobm9kZUxpc3QsIG5vZGUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVMaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAobm9kZUxpc3RbaV0gPT09IG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudH0gZWwgdG8gY2hlY2tcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciB0aGlzIGZvcm0gaGFzIG1ldGhvZD1cImRpYWxvZ1wiXG4gICAqL1xuICBmdW5jdGlvbiBpc0Zvcm1NZXRob2REaWFsb2coZWwpIHtcbiAgICBpZiAoIWVsIHx8ICFlbC5oYXNBdHRyaWJ1dGUoJ21ldGhvZCcpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlbC5nZXRBdHRyaWJ1dGUoJ21ldGhvZCcpLnRvTG93ZXJDYXNlKCkgPT09ICdkaWFsb2cnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUhUTUxEaWFsb2dFbGVtZW50fSBkaWFsb2cgdG8gdXBncmFkZVxuICAgKiBAY29uc3RydWN0b3JcbiAgICovXG4gIGZ1bmN0aW9uIGRpYWxvZ1BvbHlmaWxsSW5mbyhkaWFsb2cpIHtcbiAgICB0aGlzLmRpYWxvZ18gPSBkaWFsb2c7XG4gICAgdGhpcy5yZXBsYWNlZFN0eWxlVG9wXyA9IGZhbHNlO1xuICAgIHRoaXMub3BlbkFzTW9kYWxfID0gZmFsc2U7XG5cbiAgICAvLyBTZXQgYTExeSByb2xlLiBCcm93c2VycyB0aGF0IHN1cHBvcnQgZGlhbG9nIGltcGxpY2l0bHkga25vdyB0aGlzIGFscmVhZHkuXG4gICAgaWYgKCFkaWFsb2cuaGFzQXR0cmlidXRlKCdyb2xlJykpIHtcbiAgICAgIGRpYWxvZy5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnZGlhbG9nJyk7XG4gICAgfVxuXG4gICAgZGlhbG9nLnNob3cgPSB0aGlzLnNob3cuYmluZCh0aGlzKTtcbiAgICBkaWFsb2cuc2hvd01vZGFsID0gdGhpcy5zaG93TW9kYWwuYmluZCh0aGlzKTtcbiAgICBkaWFsb2cuY2xvc2UgPSB0aGlzLmNsb3NlLmJpbmQodGhpcyk7XG5cbiAgICBpZiAoISgncmV0dXJuVmFsdWUnIGluIGRpYWxvZykpIHtcbiAgICAgIGRpYWxvZy5yZXR1cm5WYWx1ZSA9ICcnO1xuICAgIH1cblxuICAgIGlmICgnTXV0YXRpb25PYnNlcnZlcicgaW4gd2luZG93KSB7XG4gICAgICB2YXIgbW8gPSBuZXcgTXV0YXRpb25PYnNlcnZlcih0aGlzLm1heWJlSGlkZU1vZGFsLmJpbmQodGhpcykpO1xuICAgICAgbW8ub2JzZXJ2ZShkaWFsb2csIHthdHRyaWJ1dGVzOiB0cnVlLCBhdHRyaWJ1dGVGaWx0ZXI6IFsnb3BlbiddfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElFMTAgYW5kIGJlbG93IHN1cHBvcnQuIE5vdGUgdGhhdCBET01Ob2RlUmVtb3ZlZCBldGMgZmlyZSBfYmVmb3JlXyByZW1vdmFsLiBUaGV5IGFsc29cbiAgICAgIC8vIHNlZW0gdG8gZmlyZSBldmVuIGlmIHRoZSBlbGVtZW50IHdhcyByZW1vdmVkIGFzIHBhcnQgb2YgYSBwYXJlbnQgcmVtb3ZhbC4gVXNlIHRoZSByZW1vdmVkXG4gICAgICAvLyBldmVudHMgdG8gZm9yY2UgZG93bmdyYWRlICh1c2VmdWwgaWYgcmVtb3ZlZC9pbW1lZGlhdGVseSBhZGRlZCkuXG4gICAgICB2YXIgcmVtb3ZlZCA9IGZhbHNlO1xuICAgICAgdmFyIGNiID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlbW92ZWQgPyB0aGlzLmRvd25ncmFkZU1vZGFsKCkgOiB0aGlzLm1heWJlSGlkZU1vZGFsKCk7XG4gICAgICAgIHJlbW92ZWQgPSBmYWxzZTtcbiAgICAgIH0uYmluZCh0aGlzKTtcbiAgICAgIHZhciB0aW1lb3V0O1xuICAgICAgdmFyIGRlbGF5TW9kZWwgPSBmdW5jdGlvbihldikge1xuICAgICAgICBpZiAoZXYudGFyZ2V0ICE9PSBkaWFsb2cpIHsgcmV0dXJuOyB9ICAvLyBub3QgZm9yIGEgY2hpbGQgZWxlbWVudFxuICAgICAgICB2YXIgY2FuZCA9ICdET01Ob2RlUmVtb3ZlZCc7XG4gICAgICAgIHJlbW92ZWQgfD0gKGV2LnR5cGUuc3Vic3RyKDAsIGNhbmQubGVuZ3RoKSA9PT0gY2FuZCk7XG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIHRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dChjYiwgMCk7XG4gICAgICB9O1xuICAgICAgWydET01BdHRyTW9kaWZpZWQnLCAnRE9NTm9kZVJlbW92ZWQnLCAnRE9NTm9kZVJlbW92ZWRGcm9tRG9jdW1lbnQnXS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgZGlhbG9nLmFkZEV2ZW50TGlzdGVuZXIobmFtZSwgZGVsYXlNb2RlbCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gTm90ZSB0aGF0IHRoZSBET00gaXMgb2JzZXJ2ZWQgaW5zaWRlIERpYWxvZ01hbmFnZXIgd2hpbGUgYW55IGRpYWxvZ1xuICAgIC8vIGlzIGJlaW5nIGRpc3BsYXllZCBhcyBhIG1vZGFsLCB0byBjYXRjaCBtb2RhbCByZW1vdmFsIGZyb20gdGhlIERPTS5cblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkaWFsb2csICdvcGVuJywge1xuICAgICAgc2V0OiB0aGlzLnNldE9wZW4uYmluZCh0aGlzKSxcbiAgICAgIGdldDogZGlhbG9nLmhhc0F0dHJpYnV0ZS5iaW5kKGRpYWxvZywgJ29wZW4nKVxuICAgIH0pO1xuXG4gICAgdGhpcy5iYWNrZHJvcF8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB0aGlzLmJhY2tkcm9wXy5jbGFzc05hbWUgPSAnYmFja2Ryb3AnO1xuICAgIHRoaXMuYmFja2Ryb3BfLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5iYWNrZHJvcENsaWNrXy5iaW5kKHRoaXMpKTtcbiAgfVxuXG4gIGRpYWxvZ1BvbHlmaWxsSW5mby5wcm90b3R5cGUgPSB7XG5cbiAgICBnZXQgZGlhbG9nKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGlhbG9nXztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTWF5YmUgcmVtb3ZlIHRoaXMgZGlhbG9nIGZyb20gdGhlIG1vZGFsIHRvcCBsYXllci4gVGhpcyBpcyBjYWxsZWQgd2hlblxuICAgICAqIGEgbW9kYWwgZGlhbG9nIG1heSBubyBsb25nZXIgYmUgdGVuYWJsZSwgZS5nLiwgd2hlbiB0aGUgZGlhbG9nIGlzIG5vXG4gICAgICogbG9uZ2VyIG9wZW4gb3IgaXMgbm8gbG9uZ2VyIHBhcnQgb2YgdGhlIERPTS5cbiAgICAgKi9cbiAgICBtYXliZUhpZGVNb2RhbDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5kaWFsb2dfLmhhc0F0dHJpYnV0ZSgnb3BlbicpICYmIGRvY3VtZW50LmJvZHkuY29udGFpbnModGhpcy5kaWFsb2dfKSkgeyByZXR1cm47IH1cbiAgICAgIHRoaXMuZG93bmdyYWRlTW9kYWwoKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoaXMgZGlhbG9nIGZyb20gdGhlIG1vZGFsIHRvcCBsYXllciwgbGVhdmluZyBpdCBhcyBhIG5vbi1tb2RhbC5cbiAgICAgKi9cbiAgICBkb3duZ3JhZGVNb2RhbDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoIXRoaXMub3BlbkFzTW9kYWxfKSB7IHJldHVybjsgfVxuICAgICAgdGhpcy5vcGVuQXNNb2RhbF8gPSBmYWxzZTtcbiAgICAgIHRoaXMuZGlhbG9nXy5zdHlsZS56SW5kZXggPSAnJztcblxuICAgICAgLy8gVGhpcyB3b24ndCBtYXRjaCB0aGUgbmF0aXZlIDxkaWFsb2c+IGV4YWN0bHkgYmVjYXVzZSBpZiB0aGUgdXNlciBzZXQgdG9wIG9uIGEgY2VudGVyZWRcbiAgICAgIC8vIHBvbHlmaWxsIGRpYWxvZywgdGhhdCB0b3AgZ2V0cyB0aHJvd24gYXdheSB3aGVuIHRoZSBkaWFsb2cgaXMgY2xvc2VkLiBOb3Qgc3VyZSBpdCdzXG4gICAgICAvLyBwb3NzaWJsZSB0byBwb2x5ZmlsbCB0aGlzIHBlcmZlY3RseS5cbiAgICAgIGlmICh0aGlzLnJlcGxhY2VkU3R5bGVUb3BfKSB7XG4gICAgICAgIHRoaXMuZGlhbG9nXy5zdHlsZS50b3AgPSAnJztcbiAgICAgICAgdGhpcy5yZXBsYWNlZFN0eWxlVG9wXyA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBDbGVhciB0aGUgYmFja2Ryb3AgYW5kIHJlbW92ZSBmcm9tIHRoZSBtYW5hZ2VyLlxuICAgICAgdGhpcy5iYWNrZHJvcF8ucGFyZW50Tm9kZSAmJiB0aGlzLmJhY2tkcm9wXy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuYmFja2Ryb3BfKTtcbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmRtLnJlbW92ZURpYWxvZyh0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtib29sZWFufSB2YWx1ZSB3aGV0aGVyIHRvIG9wZW4gb3IgY2xvc2UgdGhpcyBkaWFsb2dcbiAgICAgKi9cbiAgICBzZXRPcGVuOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuZGlhbG9nXy5oYXNBdHRyaWJ1dGUoJ29wZW4nKSB8fCB0aGlzLmRpYWxvZ18uc2V0QXR0cmlidXRlKCdvcGVuJywgJycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kaWFsb2dfLnJlbW92ZUF0dHJpYnV0ZSgnb3BlbicpO1xuICAgICAgICB0aGlzLm1heWJlSGlkZU1vZGFsKCk7ICAvLyBuYi4gcmVkdW5kYW50IHdpdGggTXV0YXRpb25PYnNlcnZlclxuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGNsaWNrcyBvbiB0aGUgZmFrZSAuYmFja2Ryb3AgZWxlbWVudCwgcmVkaXJlY3RpbmcgdGhlbSBhcyBpZlxuICAgICAqIHRoZXkgd2VyZSBvbiB0aGUgZGlhbG9nIGl0c2VsZi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7IUV2ZW50fSBlIHRvIHJlZGlyZWN0XG4gICAgICovXG4gICAgYmFja2Ryb3BDbGlja186IGZ1bmN0aW9uKGUpIHtcbiAgICAgIGlmICghdGhpcy5kaWFsb2dfLmhhc0F0dHJpYnV0ZSgndGFiaW5kZXgnKSkge1xuICAgICAgICAvLyBDbGlja2luZyBvbiB0aGUgYmFja2Ryb3Agc2hvdWxkIG1vdmUgdGhlIGltcGxpY2l0IGN1cnNvciwgZXZlbiBpZiBkaWFsb2cgY2Fubm90IGJlXG4gICAgICAgIC8vIGZvY3VzZWQuIENyZWF0ZSBhIGZha2UgdGhpbmcgdG8gZm9jdXMgb24uIElmIHRoZSBiYWNrZHJvcCB3YXMgX2JlZm9yZV8gdGhlIGRpYWxvZywgdGhpc1xuICAgICAgICAvLyB3b3VsZCBub3QgYmUgbmVlZGVkIC0gY2xpY2tzIHdvdWxkIG1vdmUgdGhlIGltcGxpY2l0IGN1cnNvciB0aGVyZS5cbiAgICAgICAgdmFyIGZha2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5kaWFsb2dfLmluc2VydEJlZm9yZShmYWtlLCB0aGlzLmRpYWxvZ18uZmlyc3RDaGlsZCk7XG4gICAgICAgIGZha2UudGFiSW5kZXggPSAtMTtcbiAgICAgICAgZmFrZS5mb2N1cygpO1xuICAgICAgICB0aGlzLmRpYWxvZ18ucmVtb3ZlQ2hpbGQoZmFrZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmRpYWxvZ18uZm9jdXMoKTtcbiAgICAgIH1cblxuICAgICAgdmFyIHJlZGlyZWN0ZWRFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuICAgICAgcmVkaXJlY3RlZEV2ZW50LmluaXRNb3VzZUV2ZW50KGUudHlwZSwgZS5idWJibGVzLCBlLmNhbmNlbGFibGUsIHdpbmRvdyxcbiAgICAgICAgICBlLmRldGFpbCwgZS5zY3JlZW5YLCBlLnNjcmVlblksIGUuY2xpZW50WCwgZS5jbGllbnRZLCBlLmN0cmxLZXksXG4gICAgICAgICAgZS5hbHRLZXksIGUuc2hpZnRLZXksIGUubWV0YUtleSwgZS5idXR0b24sIGUucmVsYXRlZFRhcmdldCk7XG4gICAgICB0aGlzLmRpYWxvZ18uZGlzcGF0Y2hFdmVudChyZWRpcmVjdGVkRXZlbnQpO1xuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRm9jdXNlcyBvbiB0aGUgZmlyc3QgZm9jdXNhYmxlIGVsZW1lbnQgd2l0aGluIHRoZSBkaWFsb2cuIFRoaXMgd2lsbCBhbHdheXMgYmx1ciB0aGUgY3VycmVudFxuICAgICAqIGZvY3VzLCBldmVuIGlmIG5vdGhpbmcgd2l0aGluIHRoZSBkaWFsb2cgaXMgZm91bmQuXG4gICAgICovXG4gICAgZm9jdXNfOiBmdW5jdGlvbigpIHtcbiAgICAgIC8vIEZpbmQgZWxlbWVudCB3aXRoIGBhdXRvZm9jdXNgIGF0dHJpYnV0ZSwgb3IgZmFsbCBiYWNrIHRvIHRoZSBmaXJzdCBmb3JtL3RhYmluZGV4IGNvbnRyb2wuXG4gICAgICB2YXIgdGFyZ2V0ID0gdGhpcy5kaWFsb2dfLnF1ZXJ5U2VsZWN0b3IoJ1thdXRvZm9jdXNdOm5vdChbZGlzYWJsZWRdKScpO1xuICAgICAgaWYgKCF0YXJnZXQgJiYgdGhpcy5kaWFsb2dfLnRhYkluZGV4ID49IDApIHtcbiAgICAgICAgdGFyZ2V0ID0gdGhpcy5kaWFsb2dfO1xuICAgICAgfVxuICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgLy8gTm90ZSB0aGF0IHRoaXMgaXMgJ2FueSBmb2N1c2FibGUgYXJlYScuIFRoaXMgbGlzdCBpcyBwcm9iYWJseSBub3QgZXhoYXVzdGl2ZSwgYnV0IHRoZVxuICAgICAgICAvLyBhbHRlcm5hdGl2ZSBpbnZvbHZlcyBzdGVwcGluZyB0aHJvdWdoIGFuZCB0cnlpbmcgdG8gZm9jdXMgZXZlcnl0aGluZy5cbiAgICAgICAgdmFyIG9wdHMgPSBbJ2J1dHRvbicsICdpbnB1dCcsICdrZXlnZW4nLCAnc2VsZWN0JywgJ3RleHRhcmVhJ107XG4gICAgICAgIHZhciBxdWVyeSA9IG9wdHMubWFwKGZ1bmN0aW9uKGVsKSB7XG4gICAgICAgICAgcmV0dXJuIGVsICsgJzpub3QoW2Rpc2FibGVkXSknO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gVE9ETyhzYW10aG9yKTogdGFiaW5kZXggdmFsdWVzIHRoYXQgYXJlIG5vdCBudW1lcmljIGFyZSBub3QgZm9jdXNhYmxlLlxuICAgICAgICBxdWVyeS5wdXNoKCdbdGFiaW5kZXhdOm5vdChbZGlzYWJsZWRdKTpub3QoW3RhYmluZGV4PVwiXCJdKScpOyAgLy8gdGFiaW5kZXggIT0gXCJcIiwgbm90IGRpc2FibGVkXG4gICAgICAgIHRhcmdldCA9IHRoaXMuZGlhbG9nXy5xdWVyeVNlbGVjdG9yKHF1ZXJ5LmpvaW4oJywgJykpO1xuICAgICAgfVxuICAgICAgc2FmZUJsdXIoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCk7XG4gICAgICB0YXJnZXQgJiYgdGFyZ2V0LmZvY3VzKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHpJbmRleCBmb3IgdGhlIGJhY2tkcm9wIGFuZCBkaWFsb2cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGlhbG9nWlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiYWNrZHJvcFpcbiAgICAgKi9cbiAgICB1cGRhdGVaSW5kZXg6IGZ1bmN0aW9uKGRpYWxvZ1osIGJhY2tkcm9wWikge1xuICAgICAgaWYgKGRpYWxvZ1ogPCBiYWNrZHJvcFopIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWFsb2daIHNob3VsZCBuZXZlciBiZSA8IGJhY2tkcm9wWicpO1xuICAgICAgfVxuICAgICAgdGhpcy5kaWFsb2dfLnN0eWxlLnpJbmRleCA9IGRpYWxvZ1o7XG4gICAgICB0aGlzLmJhY2tkcm9wXy5zdHlsZS56SW5kZXggPSBiYWNrZHJvcFo7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSBkaWFsb2cuIElmIHRoZSBkaWFsb2cgaXMgYWxyZWFkeSBvcGVuLCB0aGlzIGRvZXMgbm90aGluZy5cbiAgICAgKi9cbiAgICBzaG93OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghdGhpcy5kaWFsb2dfLm9wZW4pIHtcbiAgICAgICAgdGhpcy5zZXRPcGVuKHRydWUpO1xuICAgICAgICB0aGlzLmZvY3VzXygpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTaG93IHRoaXMgZGlhbG9nIG1vZGFsbHkuXG4gICAgICovXG4gICAgc2hvd01vZGFsOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLmRpYWxvZ18uaGFzQXR0cmlidXRlKCdvcGVuJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZXhlY3V0ZSBcXCdzaG93TW9kYWxcXCcgb24gZGlhbG9nOiBUaGUgZWxlbWVudCBpcyBhbHJlYWR5IG9wZW4sIGFuZCB0aGVyZWZvcmUgY2Fubm90IGJlIG9wZW5lZCBtb2RhbGx5LicpO1xuICAgICAgfVxuICAgICAgaWYgKCFkb2N1bWVudC5ib2R5LmNvbnRhaW5zKHRoaXMuZGlhbG9nXykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZXhlY3V0ZSBcXCdzaG93TW9kYWxcXCcgb24gZGlhbG9nOiBUaGUgZWxlbWVudCBpcyBub3QgaW4gYSBEb2N1bWVudC4nKTtcbiAgICAgIH1cbiAgICAgIGlmICghZGlhbG9nUG9seWZpbGwuZG0ucHVzaERpYWxvZyh0aGlzKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBleGVjdXRlIFxcJ3Nob3dNb2RhbFxcJyBvbiBkaWFsb2c6IFRoZXJlIGFyZSB0b28gbWFueSBvcGVuIG1vZGFsIGRpYWxvZ3MuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjcmVhdGVzU3RhY2tpbmdDb250ZXh0KHRoaXMuZGlhbG9nXy5wYXJlbnRFbGVtZW50KSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0EgZGlhbG9nIGlzIGJlaW5nIHNob3duIGluc2lkZSBhIHN0YWNraW5nIGNvbnRleHQuICcgK1xuICAgICAgICAgICAgJ1RoaXMgbWF5IGNhdXNlIGl0IHRvIGJlIHVudXNhYmxlLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIHRoaXMgbGluazogJyArXG4gICAgICAgICAgICAnaHR0cHM6Ly9naXRodWIuY29tL0dvb2dsZUNocm9tZS9kaWFsb2ctcG9seWZpbGwvI3N0YWNraW5nLWNvbnRleHQnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRPcGVuKHRydWUpO1xuICAgICAgdGhpcy5vcGVuQXNNb2RhbF8gPSB0cnVlO1xuXG4gICAgICAvLyBPcHRpb25hbGx5IGNlbnRlciB2ZXJ0aWNhbGx5LCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCB2aWV3cG9ydC5cbiAgICAgIGlmIChkaWFsb2dQb2x5ZmlsbC5uZWVkc0NlbnRlcmluZyh0aGlzLmRpYWxvZ18pKSB7XG4gICAgICAgIGRpYWxvZ1BvbHlmaWxsLnJlcG9zaXRpb24odGhpcy5kaWFsb2dfKTtcbiAgICAgICAgdGhpcy5yZXBsYWNlZFN0eWxlVG9wXyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlcGxhY2VkU3R5bGVUb3BfID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIC8vIEluc2VydCBiYWNrZHJvcC5cbiAgICAgIHRoaXMuZGlhbG9nXy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tkcm9wXywgdGhpcy5kaWFsb2dfLm5leHRTaWJsaW5nKTtcblxuICAgICAgLy8gRm9jdXMgb24gd2hhdGV2ZXIgaW5zaWRlIHRoZSBkaWFsb2cuXG4gICAgICB0aGlzLmZvY3VzXygpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgdGhpcyBIVE1MRGlhbG9nRWxlbWVudC4gVGhpcyBpcyBvcHRpb25hbCB2cyBjbGVhcmluZyB0aGUgb3BlblxuICAgICAqIGF0dHJpYnV0ZSwgaG93ZXZlciB0aGlzIGZpcmVzIGEgJ2Nsb3NlJyBldmVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X3JldHVyblZhbHVlIHRvIHVzZSBhcyB0aGUgcmV0dXJuVmFsdWVcbiAgICAgKi9cbiAgICBjbG9zZTogZnVuY3Rpb24ob3B0X3JldHVyblZhbHVlKSB7XG4gICAgICBpZiAoIXRoaXMuZGlhbG9nXy5oYXNBdHRyaWJ1dGUoJ29wZW4nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBleGVjdXRlIFxcJ2Nsb3NlXFwnIG9uIGRpYWxvZzogVGhlIGVsZW1lbnQgZG9lcyBub3QgaGF2ZSBhbiBcXCdvcGVuXFwnIGF0dHJpYnV0ZSwgYW5kIHRoZXJlZm9yZSBjYW5ub3QgYmUgY2xvc2VkLicpO1xuICAgICAgfVxuICAgICAgdGhpcy5zZXRPcGVuKGZhbHNlKTtcblxuICAgICAgLy8gTGVhdmUgcmV0dXJuVmFsdWUgdW50b3VjaGVkIGluIGNhc2UgaXQgd2FzIHNldCBkaXJlY3RseSBvbiB0aGUgZWxlbWVudFxuICAgICAgaWYgKG9wdF9yZXR1cm5WYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuZGlhbG9nXy5yZXR1cm5WYWx1ZSA9IG9wdF9yZXR1cm5WYWx1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gVHJpZ2dlcmluZyBcImNsb3NlXCIgZXZlbnQgZm9yIGFueSBhdHRhY2hlZCBsaXN0ZW5lcnMgb24gdGhlIDxkaWFsb2c+LlxuICAgICAgdmFyIGNsb3NlRXZlbnQgPSBuZXcgc3VwcG9ydEN1c3RvbUV2ZW50KCdjbG9zZScsIHtcbiAgICAgICAgYnViYmxlczogZmFsc2UsXG4gICAgICAgIGNhbmNlbGFibGU6IGZhbHNlXG4gICAgICB9KTtcbiAgICAgIHRoaXMuZGlhbG9nXy5kaXNwYXRjaEV2ZW50KGNsb3NlRXZlbnQpO1xuICAgIH1cblxuICB9O1xuXG4gIHZhciBkaWFsb2dQb2x5ZmlsbCA9IHt9O1xuXG4gIGRpYWxvZ1BvbHlmaWxsLnJlcG9zaXRpb24gPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgdmFyIHNjcm9sbFRvcCA9IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3A7XG4gICAgdmFyIHRvcFZhbHVlID0gc2Nyb2xsVG9wICsgKHdpbmRvdy5pbm5lckhlaWdodCAtIGVsZW1lbnQub2Zmc2V0SGVpZ2h0KSAvIDI7XG4gICAgZWxlbWVudC5zdHlsZS50b3AgPSBNYXRoLm1heChzY3JvbGxUb3AsIHRvcFZhbHVlKSArICdweCc7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwuaXNJbmxpbmVQb3NpdGlvblNldEJ5U3R5bGVzaGVldCA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRvY3VtZW50LnN0eWxlU2hlZXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgc3R5bGVTaGVldCA9IGRvY3VtZW50LnN0eWxlU2hlZXRzW2ldO1xuICAgICAgdmFyIGNzc1J1bGVzID0gbnVsbDtcbiAgICAgIC8vIFNvbWUgYnJvd3NlcnMgdGhyb3cgb24gY3NzUnVsZXMuXG4gICAgICB0cnkge1xuICAgICAgICBjc3NSdWxlcyA9IHN0eWxlU2hlZXQuY3NzUnVsZXM7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgaWYgKCFjc3NSdWxlcykgeyBjb250aW51ZTsgfVxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjc3NSdWxlcy5sZW5ndGg7ICsraikge1xuICAgICAgICB2YXIgcnVsZSA9IGNzc1J1bGVzW2pdO1xuICAgICAgICB2YXIgc2VsZWN0ZWROb2RlcyA9IG51bGw7XG4gICAgICAgIC8vIElnbm9yZSBlcnJvcnMgb24gaW52YWxpZCBzZWxlY3RvciB0ZXh0cy5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzZWxlY3RlZE5vZGVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChydWxlLnNlbGVjdG9yVGV4dCk7XG4gICAgICAgIH0gY2F0Y2goZSkge31cbiAgICAgICAgaWYgKCFzZWxlY3RlZE5vZGVzIHx8ICFpbk5vZGVMaXN0KHNlbGVjdGVkTm9kZXMsIGVsZW1lbnQpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNzc1RvcCA9IHJ1bGUuc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgndG9wJyk7XG4gICAgICAgIHZhciBjc3NCb3R0b20gPSBydWxlLnN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2JvdHRvbScpO1xuICAgICAgICBpZiAoKGNzc1RvcCAmJiBjc3NUb3AgIT09ICdhdXRvJykgfHwgKGNzc0JvdHRvbSAmJiBjc3NCb3R0b20gIT09ICdhdXRvJykpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwubmVlZHNDZW50ZXJpbmcgPSBmdW5jdGlvbihkaWFsb2cpIHtcbiAgICB2YXIgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRpYWxvZyk7XG4gICAgaWYgKGNvbXB1dGVkU3R5bGUucG9zaXRpb24gIT09ICdhYnNvbHV0ZScpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBXZSBtdXN0IGRldGVybWluZSB3aGV0aGVyIHRoZSB0b3AvYm90dG9tIHNwZWNpZmllZCB2YWx1ZSBpcyBub24tYXV0by4gIEluXG4gICAgLy8gV2ViS2l0L0JsaW5rLCBjaGVja2luZyBjb21wdXRlZFN0eWxlLnRvcCA9PSAnYXV0bycgaXMgc3VmZmljaWVudCwgYnV0XG4gICAgLy8gRmlyZWZveCByZXR1cm5zIHRoZSB1c2VkIHZhbHVlLiBTbyB3ZSBkbyB0aGlzIGNyYXp5IHRoaW5nIGluc3RlYWQ6IGNoZWNrXG4gICAgLy8gdGhlIGlubGluZSBzdHlsZSBhbmQgdGhlbiBnbyB0aHJvdWdoIENTUyBydWxlcy5cbiAgICBpZiAoKGRpYWxvZy5zdHlsZS50b3AgIT09ICdhdXRvJyAmJiBkaWFsb2cuc3R5bGUudG9wICE9PSAnJykgfHxcbiAgICAgICAgKGRpYWxvZy5zdHlsZS5ib3R0b20gIT09ICdhdXRvJyAmJiBkaWFsb2cuc3R5bGUuYm90dG9tICE9PSAnJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuICFkaWFsb2dQb2x5ZmlsbC5pc0lubGluZVBvc2l0aW9uU2V0QnlTdHlsZXNoZWV0KGRpYWxvZyk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgdG8gZm9yY2UgdXBncmFkZVxuICAgKi9cbiAgZGlhbG9nUG9seWZpbGwuZm9yY2VSZWdpc3RlckRpYWxvZyA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAod2luZG93LkhUTUxEaWFsb2dFbGVtZW50IHx8IGVsZW1lbnQuc2hvd01vZGFsKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1RoaXMgYnJvd3NlciBhbHJlYWR5IHN1cHBvcnRzIDxkaWFsb2c+LCB0aGUgcG9seWZpbGwgJyArXG4gICAgICAgICAgJ21heSBub3Qgd29yayBjb3JyZWN0bHknLCBlbGVtZW50KTtcbiAgICB9XG4gICAgaWYgKGVsZW1lbnQubG9jYWxOYW1lICE9PSAnZGlhbG9nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcmVnaXN0ZXIgZGlhbG9nOiBUaGUgZWxlbWVudCBpcyBub3QgYSBkaWFsb2cuJyk7XG4gICAgfVxuICAgIG5ldyBkaWFsb2dQb2x5ZmlsbEluZm8oLyoqIEB0eXBlIHshSFRNTERpYWxvZ0VsZW1lbnR9ICovIChlbGVtZW50KSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgdG8gdXBncmFkZSwgaWYgbmVjZXNzYXJ5XG4gICAqL1xuICBkaWFsb2dQb2x5ZmlsbC5yZWdpc3RlckRpYWxvZyA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoIWVsZW1lbnQuc2hvd01vZGFsKSB7XG4gICAgICBkaWFsb2dQb2x5ZmlsbC5mb3JjZVJlZ2lzdGVyRGlhbG9nKGVsZW1lbnQpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqL1xuICBkaWFsb2dQb2x5ZmlsbC5EaWFsb2dNYW5hZ2VyID0gZnVuY3Rpb24oKSB7XG4gICAgLyoqIEB0eXBlIHshQXJyYXk8IWRpYWxvZ1BvbHlmaWxsSW5mbz59ICovXG4gICAgdGhpcy5wZW5kaW5nRGlhbG9nU3RhY2sgPSBbXTtcblxuICAgIHZhciBjaGVja0RPTSA9IHRoaXMuY2hlY2tET01fLmJpbmQodGhpcyk7XG5cbiAgICAvLyBUaGUgb3ZlcmxheSBpcyB1c2VkIHRvIHNpbXVsYXRlIGhvdyBhIG1vZGFsIGRpYWxvZyBibG9ja3MgdGhlIGRvY3VtZW50LlxuICAgIC8vIFRoZSBibG9ja2luZyBkaWFsb2cgaXMgcG9zaXRpb25lZCBvbiB0b3Agb2YgdGhlIG92ZXJsYXksIGFuZCB0aGUgcmVzdCBvZlxuICAgIC8vIHRoZSBkaWFsb2dzIG9uIHRoZSBwZW5kaW5nIGRpYWxvZyBzdGFjayBhcmUgcG9zaXRpb25lZCBiZWxvdyBpdC4gSW4gdGhlXG4gICAgLy8gYWN0dWFsIGltcGxlbWVudGF0aW9uLCB0aGUgbW9kYWwgZGlhbG9nIHN0YWNraW5nIGlzIGNvbnRyb2xsZWQgYnkgdGhlXG4gICAgLy8gdG9wIGxheWVyLCB3aGVyZSB6LWluZGV4IGhhcyBubyBlZmZlY3QuXG4gICAgdGhpcy5vdmVybGF5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgdGhpcy5vdmVybGF5LmNsYXNzTmFtZSA9ICdfZGlhbG9nX292ZXJsYXknO1xuICAgIHRoaXMub3ZlcmxheS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHRoaXMuZm9yd2FyZFRhYl8gPSB1bmRlZmluZWQ7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgY2hlY2tET00oW10pOyAgLy8gc2FuaXR5LWNoZWNrIERPTVxuICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICB0aGlzLmhhbmRsZUtleV8gPSB0aGlzLmhhbmRsZUtleV8uYmluZCh0aGlzKTtcbiAgICB0aGlzLmhhbmRsZUZvY3VzXyA9IHRoaXMuaGFuZGxlRm9jdXNfLmJpbmQodGhpcyk7XG5cbiAgICB0aGlzLnpJbmRleExvd18gPSAxMDAwMDA7XG4gICAgdGhpcy56SW5kZXhIaWdoXyA9IDEwMDAwMCArIDE1MDtcblxuICAgIHRoaXMuZm9yd2FyZFRhYl8gPSB1bmRlZmluZWQ7XG5cbiAgICBpZiAoJ011dGF0aW9uT2JzZXJ2ZXInIGluIHdpbmRvdykge1xuICAgICAgdGhpcy5tb18gPSBuZXcgTXV0YXRpb25PYnNlcnZlcihmdW5jdGlvbihyZWNvcmRzKSB7XG4gICAgICAgIHZhciByZW1vdmVkID0gW107XG4gICAgICAgIHJlY29yZHMuZm9yRWFjaChmdW5jdGlvbihyZWMpIHtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgYzsgYyA9IHJlYy5yZW1vdmVkTm9kZXNbaV07ICsraSkge1xuICAgICAgICAgICAgaWYgKCEoYyBpbnN0YW5jZW9mIEVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjLmxvY2FsTmFtZSA9PT0gJ2RpYWxvZycpIHtcbiAgICAgICAgICAgICAgcmVtb3ZlZC5wdXNoKGMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtb3ZlZCA9IHJlbW92ZWQuY29uY2F0KGMucXVlcnlTZWxlY3RvckFsbCgnZGlhbG9nJykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlbW92ZWQubGVuZ3RoICYmIGNoZWNrRE9NKHJlbW92ZWQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxsZWQgb24gdGhlIGZpcnN0IG1vZGFsIGRpYWxvZyBiZWluZyBzaG93bi4gQWRkcyB0aGUgb3ZlcmxheSBhbmQgcmVsYXRlZFxuICAgKiBoYW5kbGVycy5cbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLmJsb2NrRG9jdW1lbnQgPSBmdW5jdGlvbigpIHtcbiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmhhbmRsZUZvY3VzXywgdHJ1ZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlS2V5Xyk7XG4gICAgdGhpcy5tb18gJiYgdGhpcy5tb18ub2JzZXJ2ZShkb2N1bWVudCwge2NoaWxkTGlzdDogdHJ1ZSwgc3VidHJlZTogdHJ1ZX0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxsZWQgb24gdGhlIGZpcnN0IG1vZGFsIGRpYWxvZyBiZWluZyByZW1vdmVkLCBpLmUuLCB3aGVuIG5vIG1vcmUgbW9kYWxcbiAgICogZGlhbG9ncyBhcmUgdmlzaWJsZS5cbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLnVuYmxvY2tEb2N1bWVudCA9IGZ1bmN0aW9uKCkge1xuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuaGFuZGxlRm9jdXNfLCB0cnVlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVLZXlfKTtcbiAgICB0aGlzLm1vXyAmJiB0aGlzLm1vXy5kaXNjb25uZWN0KCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHN0YWNraW5nIG9mIGFsbCBrbm93biBkaWFsb2dzLlxuICAgKi9cbiAgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlci5wcm90b3R5cGUudXBkYXRlU3RhY2tpbmcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgekluZGV4ID0gdGhpcy56SW5kZXhIaWdoXztcblxuICAgIGZvciAodmFyIGkgPSAwLCBkcGk7IGRwaSA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrW2ldOyArK2kpIHtcbiAgICAgIGRwaS51cGRhdGVaSW5kZXgoLS16SW5kZXgsIC0tekluZGV4KTtcbiAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgIHRoaXMub3ZlcmxheS5zdHlsZS56SW5kZXggPSAtLXpJbmRleDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBNYWtlIHRoZSBvdmVybGF5IGEgc2libGluZyBvZiB0aGUgZGlhbG9nIGl0c2VsZi5cbiAgICB2YXIgbGFzdCA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrWzBdO1xuICAgIGlmIChsYXN0KSB7XG4gICAgICB2YXIgcCA9IGxhc3QuZGlhbG9nLnBhcmVudE5vZGUgfHwgZG9jdW1lbnQuYm9keTtcbiAgICAgIHAuYXBwZW5kQ2hpbGQodGhpcy5vdmVybGF5KTtcbiAgICB9IGVsc2UgaWYgKHRoaXMub3ZlcmxheS5wYXJlbnROb2RlKSB7XG4gICAgICB0aGlzLm92ZXJsYXkucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLm92ZXJsYXkpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBjYW5kaWRhdGUgdG8gY2hlY2sgaWYgY29udGFpbmVkIG9yIGlzIHRoZSB0b3AtbW9zdCBtb2RhbCBkaWFsb2dcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciBjYW5kaWRhdGUgaXMgY29udGFpbmVkIGluIHRvcCBkaWFsb2dcbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLmNvbnRhaW5lZEJ5VG9wRGlhbG9nXyA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHdoaWxlIChjYW5kaWRhdGUgPSBmaW5kTmVhcmVzdERpYWxvZyhjYW5kaWRhdGUpKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgZHBpOyBkcGkgPSB0aGlzLnBlbmRpbmdEaWFsb2dTdGFja1tpXTsgKytpKSB7XG4gICAgICAgIGlmIChkcGkuZGlhbG9nID09PSBjYW5kaWRhdGUpIHtcbiAgICAgICAgICByZXR1cm4gaSA9PT0gMDsgIC8vIG9ubHkgdmFsaWQgaWYgdG9wLW1vc3RcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2FuZGlkYXRlID0gY2FuZGlkYXRlLnBhcmVudEVsZW1lbnQ7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICBkaWFsb2dQb2x5ZmlsbC5EaWFsb2dNYW5hZ2VyLnByb3RvdHlwZS5oYW5kbGVGb2N1c18gPSBmdW5jdGlvbihldmVudCkge1xuICAgIGlmICh0aGlzLmNvbnRhaW5lZEJ5VG9wRGlhbG9nXyhldmVudC50YXJnZXQpKSB7IHJldHVybjsgfVxuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBzYWZlQmx1cigvKiogQHR5cGUge0VsZW1lbnR9ICovIChldmVudC50YXJnZXQpKTtcblxuICAgIGlmICh0aGlzLmZvcndhcmRUYWJfID09PSB1bmRlZmluZWQpIHsgcmV0dXJuOyB9ICAvLyBtb3ZlIGZvY3VzIG9ubHkgZnJvbSBhIHRhYiBrZXlcblxuICAgIHZhciBkcGkgPSB0aGlzLnBlbmRpbmdEaWFsb2dTdGFja1swXTtcbiAgICB2YXIgZGlhbG9nID0gZHBpLmRpYWxvZztcbiAgICB2YXIgcG9zaXRpb24gPSBkaWFsb2cuY29tcGFyZURvY3VtZW50UG9zaXRpb24oZXZlbnQudGFyZ2V0KTtcbiAgICBpZiAocG9zaXRpb24gJiBOb2RlLkRPQ1VNRU5UX1BPU0lUSU9OX1BSRUNFRElORykge1xuICAgICAgaWYgKHRoaXMuZm9yd2FyZFRhYl8pIHsgIC8vIGZvcndhcmRcbiAgICAgICAgZHBpLmZvY3VzXygpO1xuICAgICAgfSBlbHNlIHsgIC8vIGJhY2t3YXJkc1xuICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVE9ETzogRm9jdXMgYWZ0ZXIgdGhlIGRpYWxvZywgaXMgaWdub3JlZC5cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlci5wcm90b3R5cGUuaGFuZGxlS2V5XyA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgdGhpcy5mb3J3YXJkVGFiXyA9IHVuZGVmaW5lZDtcbiAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMjcpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIHZhciBjYW5jZWxFdmVudCA9IG5ldyBzdXBwb3J0Q3VzdG9tRXZlbnQoJ2NhbmNlbCcsIHtcbiAgICAgICAgYnViYmxlczogZmFsc2UsXG4gICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgdmFyIGRwaSA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrWzBdO1xuICAgICAgaWYgKGRwaSAmJiBkcGkuZGlhbG9nLmRpc3BhdGNoRXZlbnQoY2FuY2VsRXZlbnQpKSB7XG4gICAgICAgIGRwaS5kaWFsb2cuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV2ZW50LmtleUNvZGUgPT09IDkpIHtcbiAgICAgIHRoaXMuZm9yd2FyZFRhYl8gPSAhZXZlbnQuc2hpZnRLZXk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBGaW5kcyBhbmQgZG93bmdyYWRlcyBhbnkga25vd24gbW9kYWwgZGlhbG9ncyB0aGF0IGFyZSBubyBsb25nZXIgZGlzcGxheWVkLiBEaWFsb2dzIHRoYXQgYXJlXG4gICAqIHJlbW92ZWQgYW5kIGltbWVkaWF0ZWx5IHJlYWRkZWQgZG9uJ3Qgc3RheSBtb2RhbCwgdGhleSBiZWNvbWUgbm9ybWFsLlxuICAgKlxuICAgKiBAcGFyYW0geyFBcnJheTwhSFRNTERpYWxvZ0VsZW1lbnQ+fSByZW1vdmVkIHRoYXQgaGF2ZSBkZWZpbml0ZWx5IGJlZW4gcmVtb3ZlZFxuICAgKi9cbiAgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlci5wcm90b3R5cGUuY2hlY2tET01fID0gZnVuY3Rpb24ocmVtb3ZlZCkge1xuICAgIC8vIFRoaXMgb3BlcmF0ZXMgb24gYSBjbG9uZSBiZWNhdXNlIGl0IG1heSBjYXVzZSBpdCB0byBjaGFuZ2UuIEVhY2ggY2hhbmdlIGFsc28gY2FsbHNcbiAgICAvLyB1cGRhdGVTdGFja2luZywgd2hpY2ggb25seSBhY3R1YWxseSBuZWVkcyB0byBoYXBwZW4gb25jZS4gQnV0IHdobyByZW1vdmVzIG1hbnkgbW9kYWwgZGlhbG9nc1xuICAgIC8vIGF0IGEgdGltZT8hXG4gICAgdmFyIGNsb25lID0gdGhpcy5wZW5kaW5nRGlhbG9nU3RhY2suc2xpY2UoKTtcbiAgICBjbG9uZS5mb3JFYWNoKGZ1bmN0aW9uKGRwaSkge1xuICAgICAgaWYgKHJlbW92ZWQuaW5kZXhPZihkcGkuZGlhbG9nKSAhPT0gLTEpIHtcbiAgICAgICAgZHBpLmRvd25ncmFkZU1vZGFsKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkcGkubWF5YmVIaWRlTW9kYWwoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHshZGlhbG9nUG9seWZpbGxJbmZvfSBkcGlcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciB0aGUgZGlhbG9nIHdhcyBhbGxvd2VkXG4gICAqL1xuICBkaWFsb2dQb2x5ZmlsbC5EaWFsb2dNYW5hZ2VyLnByb3RvdHlwZS5wdXNoRGlhbG9nID0gZnVuY3Rpb24oZHBpKSB7XG4gICAgdmFyIGFsbG93ZWQgPSAodGhpcy56SW5kZXhIaWdoXyAtIHRoaXMuekluZGV4TG93XykgLyAyIC0gMTtcbiAgICBpZiAodGhpcy5wZW5kaW5nRGlhbG9nU3RhY2subGVuZ3RoID49IGFsbG93ZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrLnVuc2hpZnQoZHBpKSA9PT0gMSkge1xuICAgICAgdGhpcy5ibG9ja0RvY3VtZW50KCk7XG4gICAgfVxuICAgIHRoaXMudXBkYXRlU3RhY2tpbmcoKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHshZGlhbG9nUG9seWZpbGxJbmZvfSBkcGlcbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLnJlbW92ZURpYWxvZyA9IGZ1bmN0aW9uKGRwaSkge1xuICAgIHZhciBpbmRleCA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrLmluZGV4T2YoZHBpKTtcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7IHJldHVybjsgfVxuXG4gICAgdGhpcy5wZW5kaW5nRGlhbG9nU3RhY2suc3BsaWNlKGluZGV4LCAxKTtcbiAgICBpZiAodGhpcy5wZW5kaW5nRGlhbG9nU3RhY2subGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnVuYmxvY2tEb2N1bWVudCgpO1xuICAgIH1cbiAgICB0aGlzLnVwZGF0ZVN0YWNraW5nKCk7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwuZG0gPSBuZXcgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlcigpO1xuICBkaWFsb2dQb2x5ZmlsbC5mb3JtU3VibWl0dGVyID0gbnVsbDtcbiAgZGlhbG9nUG9seWZpbGwudXNlVmFsdWUgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBJbnN0YWxscyBnbG9iYWwgaGFuZGxlcnMsIHN1Y2ggYXMgY2xpY2sgbGlzdGVycyBhbmQgbmF0aXZlIG1ldGhvZCBvdmVycmlkZXMuIFRoZXNlIGFyZSBuZWVkZWRcbiAgICogZXZlbiBpZiBhIG5vIGRpYWxvZyBpcyByZWdpc3RlcmVkLCBhcyB0aGV5IGRlYWwgd2l0aCA8Zm9ybSBtZXRob2Q9XCJkaWFsb2dcIj4uXG4gICAqL1xuICBpZiAod2luZG93LkhUTUxEaWFsb2dFbGVtZW50ID09PSB1bmRlZmluZWQpIHtcblxuICAgIC8qKlxuICAgICAqIElmIEhUTUxGb3JtRWxlbWVudCB0cmFuc2xhdGVzIG1ldGhvZD1cIkRJQUxPR1wiIGludG8gJ2dldCcsIHRoZW4gcmVwbGFjZSB0aGUgZGVzY3JpcHRvciB3aXRoXG4gICAgICogb25lIHRoYXQgcmV0dXJucyB0aGUgY29ycmVjdCB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgdGVzdEZvcm0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdmb3JtJyk7XG4gICAgdGVzdEZvcm0uc2V0QXR0cmlidXRlKCdtZXRob2QnLCAnZGlhbG9nJyk7XG4gICAgaWYgKHRlc3RGb3JtLm1ldGhvZCAhPT0gJ2RpYWxvZycpIHtcbiAgICAgIHZhciBtZXRob2REZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihIVE1MRm9ybUVsZW1lbnQucHJvdG90eXBlLCAnbWV0aG9kJyk7XG4gICAgICBpZiAobWV0aG9kRGVzY3JpcHRvcikge1xuICAgICAgICAvLyBuYi4gU29tZSBvbGRlciBpT1MgYW5kIG9sZGVyIFBoYW50b21KUyBmYWlsIHRvIHJldHVybiB0aGUgZGVzY3JpcHRvci4gRG9uJ3QgZG8gYW55dGhpbmdcbiAgICAgICAgLy8gYW5kIGRvbid0IGJvdGhlciB0byB1cGRhdGUgdGhlIGVsZW1lbnQuXG4gICAgICAgIHZhciByZWFsR2V0ID0gbWV0aG9kRGVzY3JpcHRvci5nZXQ7XG4gICAgICAgIG1ldGhvZERlc2NyaXB0b3IuZ2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgaWYgKGlzRm9ybU1ldGhvZERpYWxvZyh0aGlzKSkge1xuICAgICAgICAgICAgcmV0dXJuICdkaWFsb2cnO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVhbEdldC5jYWxsKHRoaXMpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgcmVhbFNldCA9IG1ldGhvZERlc2NyaXB0b3Iuc2V0O1xuICAgICAgICBtZXRob2REZXNjcmlwdG9yLnNldCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYudG9Mb3dlckNhc2UoKSA9PT0gJ2RpYWxvZycpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNldEF0dHJpYnV0ZSgnbWV0aG9kJywgdik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByZWFsU2V0LmNhbGwodGhpcywgdik7XG4gICAgICAgIH07XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShIVE1MRm9ybUVsZW1lbnQucHJvdG90eXBlLCAnbWV0aG9kJywgbWV0aG9kRGVzY3JpcHRvcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2xvYmFsICdjbGljaycgaGFuZGxlciwgdG8gY2FwdHVyZSB0aGUgPGlucHV0IHR5cGU9XCJzdWJtaXRcIj4gb3IgPGJ1dHRvbj4gZWxlbWVudCB3aGljaCBoYXNcbiAgICAgKiBzdWJtaXR0ZWQgYSA8Zm9ybSBtZXRob2Q9XCJkaWFsb2dcIj4uIE5lZWRlZCBhcyBTYWZhcmkgYW5kIG90aGVycyBkb24ndCByZXBvcnQgdGhpcyBpbnNpZGVcbiAgICAgKiBkb2N1bWVudC5hY3RpdmVFbGVtZW50LlxuICAgICAqL1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oZXYpIHtcbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmZvcm1TdWJtaXR0ZXIgPSBudWxsO1xuICAgICAgZGlhbG9nUG9seWZpbGwudXNlVmFsdWUgPSBudWxsO1xuICAgICAgaWYgKGV2LmRlZmF1bHRQcmV2ZW50ZWQpIHsgcmV0dXJuOyB9ICAvLyBlLmcuIGEgc3VibWl0IHdoaWNoIHByZXZlbnRzIGRlZmF1bHQgc3VibWlzc2lvblxuXG4gICAgICB2YXIgdGFyZ2V0ID0gLyoqIEB0eXBlIHtFbGVtZW50fSAqLyAoZXYudGFyZ2V0KTtcbiAgICAgIGlmICghdGFyZ2V0IHx8ICFpc0Zvcm1NZXRob2REaWFsb2codGFyZ2V0LmZvcm0pKSB7IHJldHVybjsgfVxuXG4gICAgICB2YXIgdmFsaWQgPSAodGFyZ2V0LnR5cGUgPT09ICdzdWJtaXQnICYmIFsnYnV0dG9uJywgJ2lucHV0J10uaW5kZXhPZih0YXJnZXQubG9jYWxOYW1lKSA+IC0xKTtcbiAgICAgIGlmICghdmFsaWQpIHtcbiAgICAgICAgaWYgKCEodGFyZ2V0LmxvY2FsTmFtZSA9PT0gJ2lucHV0JyAmJiB0YXJnZXQudHlwZSA9PT0gJ2ltYWdlJykpIHsgcmV0dXJuOyB9XG4gICAgICAgIC8vIHRoaXMgaXMgYSA8aW5wdXQgdHlwZT1cImltYWdlXCI+LCB3aGljaCBjYW4gc3VibWl0IGZvcm1zXG4gICAgICAgIGRpYWxvZ1BvbHlmaWxsLnVzZVZhbHVlID0gZXYub2Zmc2V0WCArICcsJyArIGV2Lm9mZnNldFk7XG4gICAgICB9XG5cbiAgICAgIHZhciBkaWFsb2cgPSBmaW5kTmVhcmVzdERpYWxvZyh0YXJnZXQpO1xuICAgICAgaWYgKCFkaWFsb2cpIHsgcmV0dXJuOyB9XG5cbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmZvcm1TdWJtaXR0ZXIgPSB0YXJnZXQ7XG4gICAgfSwgZmFsc2UpO1xuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZSB0aGUgbmF0aXZlIEhUTUxGb3JtRWxlbWVudC5zdWJtaXQoKSBtZXRob2QsIGFzIGl0IHdvbid0IGZpcmUgdGhlXG4gICAgICogc3VibWl0IGV2ZW50IGFuZCBnaXZlIHVzIGEgY2hhbmNlIHRvIHJlc3BvbmQuXG4gICAgICovXG4gICAgdmFyIG5hdGl2ZUZvcm1TdWJtaXQgPSBIVE1MRm9ybUVsZW1lbnQucHJvdG90eXBlLnN1Ym1pdDtcbiAgICB2YXIgcmVwbGFjZW1lbnRGb3JtU3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCFpc0Zvcm1NZXRob2REaWFsb2codGhpcykpIHtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZUZvcm1TdWJtaXQuY2FsbCh0aGlzKTtcbiAgICAgIH1cbiAgICAgIHZhciBkaWFsb2cgPSBmaW5kTmVhcmVzdERpYWxvZyh0aGlzKTtcbiAgICAgIGRpYWxvZyAmJiBkaWFsb2cuY2xvc2UoKTtcbiAgICB9O1xuICAgIEhUTUxGb3JtRWxlbWVudC5wcm90b3R5cGUuc3VibWl0ID0gcmVwbGFjZW1lbnRGb3JtU3VibWl0O1xuXG4gICAgLyoqXG4gICAgICogR2xvYmFsIGZvcm0gJ2RpYWxvZycgbWV0aG9kIGhhbmRsZXIuIENsb3NlcyBhIGRpYWxvZyBjb3JyZWN0bHkgb24gc3VibWl0XG4gICAgICogYW5kIHBvc3NpYmx5IHNldHMgaXRzIHJldHVybiB2YWx1ZS5cbiAgICAgKi9cbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdzdWJtaXQnLCBmdW5jdGlvbihldikge1xuICAgICAgdmFyIGZvcm0gPSAvKiogQHR5cGUge0hUTUxGb3JtRWxlbWVudH0gKi8gKGV2LnRhcmdldCk7XG4gICAgICBpZiAoIWlzRm9ybU1ldGhvZERpYWxvZyhmb3JtKSkgeyByZXR1cm47IH1cbiAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBkaWFsb2cgPSBmaW5kTmVhcmVzdERpYWxvZyhmb3JtKTtcbiAgICAgIGlmICghZGlhbG9nKSB7IHJldHVybjsgfVxuXG4gICAgICAvLyBGb3JtcyBjYW4gb25seSBiZSBzdWJtaXR0ZWQgdmlhIC5zdWJtaXQoKSBvciBhIGNsaWNrICg/KSwgYnV0IGFueXdheTogc2FuaXR5LWNoZWNrIHRoYXRcbiAgICAgIC8vIHRoZSBzdWJtaXR0ZXIgaXMgY29ycmVjdCBiZWZvcmUgdXNpbmcgaXRzIHZhbHVlIGFzIC5yZXR1cm5WYWx1ZS5cbiAgICAgIHZhciBzID0gZGlhbG9nUG9seWZpbGwuZm9ybVN1Ym1pdHRlcjtcbiAgICAgIGlmIChzICYmIHMuZm9ybSA9PT0gZm9ybSkge1xuICAgICAgICBkaWFsb2cuY2xvc2UoZGlhbG9nUG9seWZpbGwudXNlVmFsdWUgfHwgcy52YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgIH1cbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmZvcm1TdWJtaXR0ZXIgPSBudWxsO1xuICAgIH0sIHRydWUpO1xuICB9XG5cbiAgZGlhbG9nUG9seWZpbGxbJ2ZvcmNlUmVnaXN0ZXJEaWFsb2cnXSA9IGRpYWxvZ1BvbHlmaWxsLmZvcmNlUmVnaXN0ZXJEaWFsb2c7XG4gIGRpYWxvZ1BvbHlmaWxsWydyZWdpc3RlckRpYWxvZyddID0gZGlhbG9nUG9seWZpbGwucmVnaXN0ZXJEaWFsb2c7XG5cbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgJ2FtZCcgaW4gZGVmaW5lKSB7XG4gICAgLy8gQU1EIHN1cHBvcnRcbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7IHJldHVybiBkaWFsb2dQb2x5ZmlsbDsgfSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZVsnZXhwb3J0cyddID09PSAnb2JqZWN0Jykge1xuICAgIC8vIENvbW1vbkpTIHN1cHBvcnRcbiAgICBtb2R1bGVbJ2V4cG9ydHMnXSA9IGRpYWxvZ1BvbHlmaWxsO1xuICB9IGVsc2Uge1xuICAgIC8vIGFsbCBvdGhlcnNcbiAgICB3aW5kb3dbJ2RpYWxvZ1BvbHlmaWxsJ10gPSBkaWFsb2dQb2x5ZmlsbDtcbiAgfVxufSkoKTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///5c00\n")}}]);

TODO found
Open

(window.webpackJsonp=window.webpackJsonp||[]).push([["npm.dialog-polyfill"],{"5c00":function(module,exports,__webpack_require__){eval("var __WEBPACK_AMD_DEFINE_RESULT__;(function() {\n\n  // nb. This is for IE10 and lower _only_.\n  var supportCustomEvent = window.CustomEvent;\n  if (!supportCustomEvent || typeof supportCustomEvent === 'object') {\n    supportCustomEvent = function CustomEvent(event, x) {\n      x = x || {};\n      var ev = document.createEvent('CustomEvent');\n      ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null);\n      return ev;\n    };\n    supportCustomEvent.prototype = window.Event.prototype;\n  }\n\n  /**\n   * @param {Element} el to check for stacking context\n   * @return {boolean} whether this el or its parents creates a stacking context\n   */\n  function createsStackingContext(el) {\n    while (el && el !== document.body) {\n      var s = window.getComputedStyle(el);\n      var invalid = function(k, ok) {\n        return !(s[k] === undefined || s[k] === ok);\n      }\n      if (s.opacity < 1 ||\n          invalid('zIndex', 'auto') ||\n          invalid('transform', 'none') ||\n          invalid('mixBlendMode', 'normal') ||\n          invalid('filter', 'none') ||\n          invalid('perspective', 'none') ||\n          s['isolation'] === 'isolate' ||\n          s.position === 'fixed' ||\n          s.webkitOverflowScrolling === 'touch') {\n        return true;\n      }\n      el = el.parentElement;\n    }\n    return false;\n  }\n\n  /**\n   * Finds the nearest <dialog> from the passed element.\n   *\n   * @param {Element} el to search from\n   * @return {HTMLDialogElement} dialog found\n   */\n  function findNearestDialog(el) {\n    while (el) {\n      if (el.localName === 'dialog') {\n        return /** @type {HTMLDialogElement} */ (el);\n      }\n      el = el.parentElement;\n    }\n    return null;\n  }\n\n  /**\n   * Blur the specified element, as long as it's not the HTML body element.\n   * This works around an IE9/10 bug - blurring the body causes Windows to\n   * blur the whole application.\n   *\n   * @param {Element} el to blur\n   */\n  function safeBlur(el) {\n    if (el && el.blur && el !== document.body) {\n      el.blur();\n    }\n  }\n\n  /**\n   * @param {!NodeList} nodeList to search\n   * @param {Node} node to find\n   * @return {boolean} whether node is inside nodeList\n   */\n  function inNodeList(nodeList, node) {\n    for (var i = 0; i < nodeList.length; ++i) {\n      if (nodeList[i] === node) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * @param {HTMLFormElement} el to check\n   * @return {boolean} whether this form has method=\"dialog\"\n   */\n  function isFormMethodDialog(el) {\n    if (!el || !el.hasAttribute('method')) {\n      return false;\n    }\n    return el.getAttribute('method').toLowerCase() === 'dialog';\n  }\n\n  /**\n   * @param {!HTMLDialogElement} dialog to upgrade\n   * @constructor\n   */\n  function dialogPolyfillInfo(dialog) {\n    this.dialog_ = dialog;\n    this.replacedStyleTop_ = false;\n    this.openAsModal_ = false;\n\n    // Set a11y role. Browsers that support dialog implicitly know this already.\n    if (!dialog.hasAttribute('role')) {\n      dialog.setAttribute('role', 'dialog');\n    }\n\n    dialog.show = this.show.bind(this);\n    dialog.showModal = this.showModal.bind(this);\n    dialog.close = this.close.bind(this);\n\n    if (!('returnValue' in dialog)) {\n      dialog.returnValue = '';\n    }\n\n    if ('MutationObserver' in window) {\n      var mo = new MutationObserver(this.maybeHideModal.bind(this));\n      mo.observe(dialog, {attributes: true, attributeFilter: ['open']});\n    } else {\n      // IE10 and below support. Note that DOMNodeRemoved etc fire _before_ removal. They also\n      // seem to fire even if the element was removed as part of a parent removal. Use the removed\n      // events to force downgrade (useful if removed/immediately added).\n      var removed = false;\n      var cb = function() {\n        removed ? this.downgradeModal() : this.maybeHideModal();\n        removed = false;\n      }.bind(this);\n      var timeout;\n      var delayModel = function(ev) {\n        if (ev.target !== dialog) { return; }  // not for a child element\n        var cand = 'DOMNodeRemoved';\n        removed |= (ev.type.substr(0, cand.length) === cand);\n        window.clearTimeout(timeout);\n        timeout = window.setTimeout(cb, 0);\n      };\n      ['DOMAttrModified', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument'].forEach(function(name) {\n        dialog.addEventListener(name, delayModel);\n      });\n    }\n    // Note that the DOM is observed inside DialogManager while any dialog\n    // is being displayed as a modal, to catch modal removal from the DOM.\n\n    Object.defineProperty(dialog, 'open', {\n      set: this.setOpen.bind(this),\n      get: dialog.hasAttribute.bind(dialog, 'open')\n    });\n\n    this.backdrop_ = document.createElement('div');\n    this.backdrop_.className = 'backdrop';\n    this.backdrop_.addEventListener('click', this.backdropClick_.bind(this));\n  }\n\n  dialogPolyfillInfo.prototype = {\n\n    get dialog() {\n      return this.dialog_;\n    },\n\n    /**\n     * Maybe remove this dialog from the modal top layer. This is called when\n     * a modal dialog may no longer be tenable, e.g., when the dialog is no\n     * longer open or is no longer part of the DOM.\n     */\n    maybeHideModal: function() {\n      if (this.dialog_.hasAttribute('open') && document.body.contains(this.dialog_)) { return; }\n      this.downgradeModal();\n    },\n\n    /**\n     * Remove this dialog from the modal top layer, leaving it as a non-modal.\n     */\n    downgradeModal: function() {\n      if (!this.openAsModal_) { return; }\n      this.openAsModal_ = false;\n      this.dialog_.style.zIndex = '';\n\n      // This won't match the native <dialog> exactly because if the user set top on a centered\n      // polyfill dialog, that top gets thrown away when the dialog is closed. Not sure it's\n      // possible to polyfill this perfectly.\n      if (this.replacedStyleTop_) {\n        this.dialog_.style.top = '';\n        this.replacedStyleTop_ = false;\n      }\n\n      // Clear the backdrop and remove from the manager.\n      this.backdrop_.parentNode && this.backdrop_.parentNode.removeChild(this.backdrop_);\n      dialogPolyfill.dm.removeDialog(this);\n    },\n\n    /**\n     * @param {boolean} value whether to open or close this dialog\n     */\n    setOpen: function(value) {\n      if (value) {\n        this.dialog_.hasAttribute('open') || this.dialog_.setAttribute('open', '');\n      } else {\n        this.dialog_.removeAttribute('open');\n        this.maybeHideModal();  // nb. redundant with MutationObserver\n      }\n    },\n\n    /**\n     * Handles clicks on the fake .backdrop element, redirecting them as if\n     * they were on the dialog itself.\n     *\n     * @param {!Event} e to redirect\n     */\n    backdropClick_: function(e) {\n      if (!this.dialog_.hasAttribute('tabindex')) {\n        // Clicking on the backdrop should move the implicit cursor, even if dialog cannot be\n        // focused. Create a fake thing to focus on. If the backdrop was _before_ the dialog, this\n        // would not be needed - clicks would move the implicit cursor there.\n        var fake = document.createElement('div');\n        this.dialog_.insertBefore(fake, this.dialog_.firstChild);\n        fake.tabIndex = -1;\n        fake.focus();\n        this.dialog_.removeChild(fake);\n      } else {\n        this.dialog_.focus();\n      }\n\n      var redirectedEvent = document.createEvent('MouseEvents');\n      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,\n          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,\n          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);\n      this.dialog_.dispatchEvent(redirectedEvent);\n      e.stopPropagation();\n    },\n\n    /**\n     * Focuses on the first focusable element within the dialog. This will always blur the current\n     * focus, even if nothing within the dialog is found.\n     */\n    focus_: function() {\n      // Find element with `autofocus` attribute, or fall back to the first form/tabindex control.\n      var target = this.dialog_.querySelector('[autofocus]:not([disabled])');\n      if (!target && this.dialog_.tabIndex >= 0) {\n        target = this.dialog_;\n      }\n      if (!target) {\n        // Note that this is 'any focusable area'. This list is probably not exhaustive, but the\n        // alternative involves stepping through and trying to focus everything.\n        var opts = ['button', 'input', 'keygen', 'select', 'textarea'];\n        var query = opts.map(function(el) {\n          return el + ':not([disabled])';\n        });\n        // TODO(samthor): tabindex values that are not numeric are not focusable.\n        query.push('[tabindex]:not([disabled]):not([tabindex=\"\"])');  // tabindex != \"\", not disabled\n        target = this.dialog_.querySelector(query.join(', '));\n      }\n      safeBlur(document.activeElement);\n      target && target.focus();\n    },\n\n    /**\n     * Sets the zIndex for the backdrop and dialog.\n     *\n     * @param {number} dialogZ\n     * @param {number} backdropZ\n     */\n    updateZIndex: function(dialogZ, backdropZ) {\n      if (dialogZ < backdropZ) {\n        throw new Error('dialogZ should never be < backdropZ');\n      }\n      this.dialog_.style.zIndex = dialogZ;\n      this.backdrop_.style.zIndex = backdropZ;\n    },\n\n    /**\n     * Shows the dialog. If the dialog is already open, this does nothing.\n     */\n    show: function() {\n      if (!this.dialog_.open) {\n        this.setOpen(true);\n        this.focus_();\n      }\n    },\n\n    /**\n     * Show this dialog modally.\n     */\n    showModal: function() {\n      if (this.dialog_.hasAttribute('open')) {\n        throw new Error('Failed to execute \\'showModal\\' on dialog: The element is already open, and therefore cannot be opened modally.');\n      }\n      if (!document.body.contains(this.dialog_)) {\n        throw new Error('Failed to execute \\'showModal\\' on dialog: The element is not in a Document.');\n      }\n      if (!dialogPolyfill.dm.pushDialog(this)) {\n        throw new Error('Failed to execute \\'showModal\\' on dialog: There are too many open modal dialogs.');\n      }\n\n      if (createsStackingContext(this.dialog_.parentElement)) {\n        console.warn('A dialog is being shown inside a stacking context. ' +\n            'This may cause it to be unusable. For more information, see this link: ' +\n            'https://github.com/GoogleChrome/dialog-polyfill/#stacking-context');\n      }\n\n      this.setOpen(true);\n      this.openAsModal_ = true;\n\n      // Optionally center vertically, relative to the current viewport.\n      if (dialogPolyfill.needsCentering(this.dialog_)) {\n        dialogPolyfill.reposition(this.dialog_);\n        this.replacedStyleTop_ = true;\n      } else {\n        this.replacedStyleTop_ = false;\n      }\n\n      // Insert backdrop.\n      this.dialog_.parentNode.insertBefore(this.backdrop_, this.dialog_.nextSibling);\n\n      // Focus on whatever inside the dialog.\n      this.focus_();\n    },\n\n    /**\n     * Closes this HTMLDialogElement. This is optional vs clearing the open\n     * attribute, however this fires a 'close' event.\n     *\n     * @param {string=} opt_returnValue to use as the returnValue\n     */\n    close: function(opt_returnValue) {\n      if (!this.dialog_.hasAttribute('open')) {\n        throw new Error('Failed to execute \\'close\\' on dialog: The element does not have an \\'open\\' attribute, and therefore cannot be closed.');\n      }\n      this.setOpen(false);\n\n      // Leave returnValue untouched in case it was set directly on the element\n      if (opt_returnValue !== undefined) {\n        this.dialog_.returnValue = opt_returnValue;\n      }\n\n      // Triggering \"close\" event for any attached listeners on the <dialog>.\n      var closeEvent = new supportCustomEvent('close', {\n        bubbles: false,\n        cancelable: false\n      });\n      this.dialog_.dispatchEvent(closeEvent);\n    }\n\n  };\n\n  var dialogPolyfill = {};\n\n  dialogPolyfill.reposition = function(element) {\n    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;\n    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;\n    element.style.top = Math.max(scrollTop, topValue) + 'px';\n  };\n\n  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {\n    for (var i = 0; i < document.styleSheets.length; ++i) {\n      var styleSheet = document.styleSheets[i];\n      var cssRules = null;\n      // Some browsers throw on cssRules.\n      try {\n        cssRules = styleSheet.cssRules;\n      } catch (e) {}\n      if (!cssRules) { continue; }\n      for (var j = 0; j < cssRules.length; ++j) {\n        var rule = cssRules[j];\n        var selectedNodes = null;\n        // Ignore errors on invalid selector texts.\n        try {\n          selectedNodes = document.querySelectorAll(rule.selectorText);\n        } catch(e) {}\n        if (!selectedNodes || !inNodeList(selectedNodes, element)) {\n          continue;\n        }\n        var cssTop = rule.style.getPropertyValue('top');\n        var cssBottom = rule.style.getPropertyValue('bottom');\n        if ((cssTop && cssTop !== 'auto') || (cssBottom && cssBottom !== 'auto')) {\n          return true;\n        }\n      }\n    }\n    return false;\n  };\n\n  dialogPolyfill.needsCentering = function(dialog) {\n    var computedStyle = window.getComputedStyle(dialog);\n    if (computedStyle.position !== 'absolute') {\n      return false;\n    }\n\n    // We must determine whether the top/bottom specified value is non-auto.  In\n    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but\n    // Firefox returns the used value. So we do this crazy thing instead: check\n    // the inline style and then go through CSS rules.\n    if ((dialog.style.top !== 'auto' && dialog.style.top !== '') ||\n        (dialog.style.bottom !== 'auto' && dialog.style.bottom !== '')) {\n      return false;\n    }\n    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);\n  };\n\n  /**\n   * @param {!Element} element to force upgrade\n   */\n  dialogPolyfill.forceRegisterDialog = function(element) {\n    if (window.HTMLDialogElement || element.showModal) {\n      console.warn('This browser already supports <dialog>, the polyfill ' +\n          'may not work correctly', element);\n    }\n    if (element.localName !== 'dialog') {\n      throw new Error('Failed to register dialog: The element is not a dialog.');\n    }\n    new dialogPolyfillInfo(/** @type {!HTMLDialogElement} */ (element));\n  };\n\n  /**\n   * @param {!Element} element to upgrade, if necessary\n   */\n  dialogPolyfill.registerDialog = function(element) {\n    if (!element.showModal) {\n      dialogPolyfill.forceRegisterDialog(element);\n    }\n  };\n\n  /**\n   * @constructor\n   */\n  dialogPolyfill.DialogManager = function() {\n    /** @type {!Array<!dialogPolyfillInfo>} */\n    this.pendingDialogStack = [];\n\n    var checkDOM = this.checkDOM_.bind(this);\n\n    // The overlay is used to simulate how a modal dialog blocks the document.\n    // The blocking dialog is positioned on top of the overlay, and the rest of\n    // the dialogs on the pending dialog stack are positioned below it. In the\n    // actual implementation, the modal dialog stacking is controlled by the\n    // top layer, where z-index has no effect.\n    this.overlay = document.createElement('div');\n    this.overlay.className = '_dialog_overlay';\n    this.overlay.addEventListener('click', function(e) {\n      this.forwardTab_ = undefined;\n      e.stopPropagation();\n      checkDOM([]);  // sanity-check DOM\n    }.bind(this));\n\n    this.handleKey_ = this.handleKey_.bind(this);\n    this.handleFocus_ = this.handleFocus_.bind(this);\n\n    this.zIndexLow_ = 100000;\n    this.zIndexHigh_ = 100000 + 150;\n\n    this.forwardTab_ = undefined;\n\n    if ('MutationObserver' in window) {\n      this.mo_ = new MutationObserver(function(records) {\n        var removed = [];\n        records.forEach(function(rec) {\n          for (var i = 0, c; c = rec.removedNodes[i]; ++i) {\n            if (!(c instanceof Element)) {\n              continue;\n            } else if (c.localName === 'dialog') {\n              removed.push(c);\n            }\n            removed = removed.concat(c.querySelectorAll('dialog'));\n          }\n        });\n        removed.length && checkDOM(removed);\n      });\n    }\n  };\n\n  /**\n   * Called on the first modal dialog being shown. Adds the overlay and related\n   * handlers.\n   */\n  dialogPolyfill.DialogManager.prototype.blockDocument = function() {\n    document.documentElement.addEventListener('focus', this.handleFocus_, true);\n    document.addEventListener('keydown', this.handleKey_);\n    this.mo_ && this.mo_.observe(document, {childList: true, subtree: true});\n  };\n\n  /**\n   * Called on the first modal dialog being removed, i.e., when no more modal\n   * dialogs are visible.\n   */\n  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {\n    document.documentElement.removeEventListener('focus', this.handleFocus_, true);\n    document.removeEventListener('keydown', this.handleKey_);\n    this.mo_ && this.mo_.disconnect();\n  };\n\n  /**\n   * Updates the stacking of all known dialogs.\n   */\n  dialogPolyfill.DialogManager.prototype.updateStacking = function() {\n    var zIndex = this.zIndexHigh_;\n\n    for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {\n      dpi.updateZIndex(--zIndex, --zIndex);\n      if (i === 0) {\n        this.overlay.style.zIndex = --zIndex;\n      }\n    }\n\n    // Make the overlay a sibling of the dialog itself.\n    var last = this.pendingDialogStack[0];\n    if (last) {\n      var p = last.dialog.parentNode || document.body;\n      p.appendChild(this.overlay);\n    } else if (this.overlay.parentNode) {\n      this.overlay.parentNode.removeChild(this.overlay);\n    }\n  };\n\n  /**\n   * @param {Element} candidate to check if contained or is the top-most modal dialog\n   * @return {boolean} whether candidate is contained in top dialog\n   */\n  dialogPolyfill.DialogManager.prototype.containedByTopDialog_ = function(candidate) {\n    while (candidate = findNearestDialog(candidate)) {\n      for (var i = 0, dpi; dpi = this.pendingDialogStack[i]; ++i) {\n        if (dpi.dialog === candidate) {\n          return i === 0;  // only valid if top-most\n        }\n      }\n      candidate = candidate.parentElement;\n    }\n    return false;\n  };\n\n  dialogPolyfill.DialogManager.prototype.handleFocus_ = function(event) {\n    if (this.containedByTopDialog_(event.target)) { return; }\n\n    event.preventDefault();\n    event.stopPropagation();\n    safeBlur(/** @type {Element} */ (event.target));\n\n    if (this.forwardTab_ === undefined) { return; }  // move focus only from a tab key\n\n    var dpi = this.pendingDialogStack[0];\n    var dialog = dpi.dialog;\n    var position = dialog.compareDocumentPosition(event.target);\n    if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n      if (this.forwardTab_) {  // forward\n        dpi.focus_();\n      } else {  // backwards\n        document.documentElement.focus();\n      }\n    } else {\n      // TODO: Focus after the dialog, is ignored.\n    }\n\n    return false;\n  };\n\n  dialogPolyfill.DialogManager.prototype.handleKey_ = function(event) {\n    this.forwardTab_ = undefined;\n    if (event.keyCode === 27) {\n      event.preventDefault();\n      event.stopPropagation();\n      var cancelEvent = new supportCustomEvent('cancel', {\n        bubbles: false,\n        cancelable: true\n      });\n      var dpi = this.pendingDialogStack[0];\n      if (dpi && dpi.dialog.dispatchEvent(cancelEvent)) {\n        dpi.dialog.close();\n      }\n    } else if (event.keyCode === 9) {\n      this.forwardTab_ = !event.shiftKey;\n    }\n  };\n\n  /**\n   * Finds and downgrades any known modal dialogs that are no longer displayed. Dialogs that are\n   * removed and immediately readded don't stay modal, they become normal.\n   *\n   * @param {!Array<!HTMLDialogElement>} removed that have definitely been removed\n   */\n  dialogPolyfill.DialogManager.prototype.checkDOM_ = function(removed) {\n    // This operates on a clone because it may cause it to change. Each change also calls\n    // updateStacking, which only actually needs to happen once. But who removes many modal dialogs\n    // at a time?!\n    var clone = this.pendingDialogStack.slice();\n    clone.forEach(function(dpi) {\n      if (removed.indexOf(dpi.dialog) !== -1) {\n        dpi.downgradeModal();\n      } else {\n        dpi.maybeHideModal();\n      }\n    });\n  };\n\n  /**\n   * @param {!dialogPolyfillInfo} dpi\n   * @return {boolean} whether the dialog was allowed\n   */\n  dialogPolyfill.DialogManager.prototype.pushDialog = function(dpi) {\n    var allowed = (this.zIndexHigh_ - this.zIndexLow_) / 2 - 1;\n    if (this.pendingDialogStack.length >= allowed) {\n      return false;\n    }\n    if (this.pendingDialogStack.unshift(dpi) === 1) {\n      this.blockDocument();\n    }\n    this.updateStacking();\n    return true;\n  };\n\n  /**\n   * @param {!dialogPolyfillInfo} dpi\n   */\n  dialogPolyfill.DialogManager.prototype.removeDialog = function(dpi) {\n    var index = this.pendingDialogStack.indexOf(dpi);\n    if (index === -1) { return; }\n\n    this.pendingDialogStack.splice(index, 1);\n    if (this.pendingDialogStack.length === 0) {\n      this.unblockDocument();\n    }\n    this.updateStacking();\n  };\n\n  dialogPolyfill.dm = new dialogPolyfill.DialogManager();\n  dialogPolyfill.formSubmitter = null;\n  dialogPolyfill.useValue = null;\n\n  /**\n   * Installs global handlers, such as click listers and native method overrides. These are needed\n   * even if a no dialog is registered, as they deal with <form method=\"dialog\">.\n   */\n  if (window.HTMLDialogElement === undefined) {\n\n    /**\n     * If HTMLFormElement translates method=\"DIALOG\" into 'get', then replace the descriptor with\n     * one that returns the correct value.\n     */\n    var testForm = document.createElement('form');\n    testForm.setAttribute('method', 'dialog');\n    if (testForm.method !== 'dialog') {\n      var methodDescriptor = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'method');\n      if (methodDescriptor) {\n        // nb. Some older iOS and older PhantomJS fail to return the descriptor. Don't do anything\n        // and don't bother to update the element.\n        var realGet = methodDescriptor.get;\n        methodDescriptor.get = function() {\n          if (isFormMethodDialog(this)) {\n            return 'dialog';\n          }\n          return realGet.call(this);\n        };\n        var realSet = methodDescriptor.set;\n        methodDescriptor.set = function(v) {\n          if (typeof v === 'string' && v.toLowerCase() === 'dialog') {\n            return this.setAttribute('method', v);\n          }\n          return realSet.call(this, v);\n        };\n        Object.defineProperty(HTMLFormElement.prototype, 'method', methodDescriptor);\n      }\n    }\n\n    /**\n     * Global 'click' handler, to capture the <input type=\"submit\"> or <button> element which has\n     * submitted a <form method=\"dialog\">. Needed as Safari and others don't report this inside\n     * document.activeElement.\n     */\n    document.addEventListener('click', function(ev) {\n      dialogPolyfill.formSubmitter = null;\n      dialogPolyfill.useValue = null;\n      if (ev.defaultPrevented) { return; }  // e.g. a submit which prevents default submission\n\n      var target = /** @type {Element} */ (ev.target);\n      if (!target || !isFormMethodDialog(target.form)) { return; }\n\n      var valid = (target.type === 'submit' && ['button', 'input'].indexOf(target.localName) > -1);\n      if (!valid) {\n        if (!(target.localName === 'input' && target.type === 'image')) { return; }\n        // this is a <input type=\"image\">, which can submit forms\n        dialogPolyfill.useValue = ev.offsetX + ',' + ev.offsetY;\n      }\n\n      var dialog = findNearestDialog(target);\n      if (!dialog) { return; }\n\n      dialogPolyfill.formSubmitter = target;\n    }, false);\n\n    /**\n     * Replace the native HTMLFormElement.submit() method, as it won't fire the\n     * submit event and give us a chance to respond.\n     */\n    var nativeFormSubmit = HTMLFormElement.prototype.submit;\n    var replacementFormSubmit = function () {\n      if (!isFormMethodDialog(this)) {\n        return nativeFormSubmit.call(this);\n      }\n      var dialog = findNearestDialog(this);\n      dialog && dialog.close();\n    };\n    HTMLFormElement.prototype.submit = replacementFormSubmit;\n\n    /**\n     * Global form 'dialog' method handler. Closes a dialog correctly on submit\n     * and possibly sets its return value.\n     */\n    document.addEventListener('submit', function(ev) {\n      var form = /** @type {HTMLFormElement} */ (ev.target);\n      if (!isFormMethodDialog(form)) { return; }\n      ev.preventDefault();\n\n      var dialog = findNearestDialog(form);\n      if (!dialog) { return; }\n\n      // Forms can only be submitted via .submit() or a click (?), but anyway: sanity-check that\n      // the submitter is correct before using its value as .returnValue.\n      var s = dialogPolyfill.formSubmitter;\n      if (s && s.form === form) {\n        dialog.close(dialogPolyfill.useValue || s.value);\n      } else {\n        dialog.close();\n      }\n      dialogPolyfill.formSubmitter = null;\n    }, true);\n  }\n\n  dialogPolyfill['forceRegisterDialog'] = dialogPolyfill.forceRegisterDialog;\n  dialogPolyfill['registerDialog'] = dialogPolyfill.registerDialog;\n\n  if ( true && 'amd' in __webpack_require__(/*! !webpack amd define */ \"30d1\")) {\n    // AMD support\n    !(__WEBPACK_AMD_DEFINE_RESULT__ = (function() { return dialogPolyfill; }).call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n  } else if ( true && typeof module['exports'] === 'object') {\n    // CommonJS support\n    module['exports'] = dialogPolyfill;\n  } else {\n    // all others\n    window['dialogPolyfill'] = dialogPolyfill;\n  }\n})();\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNWMwMC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9kaWFsb2ctcG9seWZpbGwvZGlhbG9nLXBvbHlmaWxsLmpzP2M5NzAiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCkge1xuXG4gIC8vIG5iLiBUaGlzIGlzIGZvciBJRTEwIGFuZCBsb3dlciBfb25seV8uXG4gIHZhciBzdXBwb3J0Q3VzdG9tRXZlbnQgPSB3aW5kb3cuQ3VzdG9tRXZlbnQ7XG4gIGlmICghc3VwcG9ydEN1c3RvbUV2ZW50IHx8IHR5cGVvZiBzdXBwb3J0Q3VzdG9tRXZlbnQgPT09ICdvYmplY3QnKSB7XG4gICAgc3VwcG9ydEN1c3RvbUV2ZW50ID0gZnVuY3Rpb24gQ3VzdG9tRXZlbnQoZXZlbnQsIHgpIHtcbiAgICAgIHggPSB4IHx8IHt9O1xuICAgICAgdmFyIGV2ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0N1c3RvbUV2ZW50Jyk7XG4gICAgICBldi5pbml0Q3VzdG9tRXZlbnQoZXZlbnQsICEheC5idWJibGVzLCAhIXguY2FuY2VsYWJsZSwgeC5kZXRhaWwgfHwgbnVsbCk7XG4gICAgICByZXR1cm4gZXY7XG4gICAgfTtcbiAgICBzdXBwb3J0Q3VzdG9tRXZlbnQucHJvdG90eXBlID0gd2luZG93LkV2ZW50LnByb3RvdHlwZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsIHRvIGNoZWNrIGZvciBzdGFja2luZyBjb250ZXh0XG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IHdoZXRoZXIgdGhpcyBlbCBvciBpdHMgcGFyZW50cyBjcmVhdGVzIGEgc3RhY2tpbmcgY29udGV4dFxuICAgKi9cbiAgZnVuY3Rpb24gY3JlYXRlc1N0YWNraW5nQ29udGV4dChlbCkge1xuICAgIHdoaWxlIChlbCAmJiBlbCAhPT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgdmFyIHMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICB2YXIgaW52YWxpZCA9IGZ1bmN0aW9uKGssIG9rKSB7XG4gICAgICAgIHJldHVybiAhKHNba10gPT09IHVuZGVmaW5lZCB8fCBzW2tdID09PSBvayk7XG4gICAgICB9XG4gICAgICBpZiAocy5vcGFjaXR5IDwgMSB8fFxuICAgICAgICAgIGludmFsaWQoJ3pJbmRleCcsICdhdXRvJykgfHxcbiAgICAgICAgICBpbnZhbGlkKCd0cmFuc2Zvcm0nLCAnbm9uZScpIHx8XG4gICAgICAgICAgaW52YWxpZCgnbWl4QmxlbmRNb2RlJywgJ25vcm1hbCcpIHx8XG4gICAgICAgICAgaW52YWxpZCgnZmlsdGVyJywgJ25vbmUnKSB8fFxuICAgICAgICAgIGludmFsaWQoJ3BlcnNwZWN0aXZlJywgJ25vbmUnKSB8fFxuICAgICAgICAgIHNbJ2lzb2xhdGlvbiddID09PSAnaXNvbGF0ZScgfHxcbiAgICAgICAgICBzLnBvc2l0aW9uID09PSAnZml4ZWQnIHx8XG4gICAgICAgICAgcy53ZWJraXRPdmVyZmxvd1Njcm9sbGluZyA9PT0gJ3RvdWNoJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGVsID0gZWwucGFyZW50RWxlbWVudDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIHRoZSBuZWFyZXN0IDxkaWFsb2c+IGZyb20gdGhlIHBhc3NlZCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsIHRvIHNlYXJjaCBmcm9tXG4gICAqIEByZXR1cm4ge0hUTUxEaWFsb2dFbGVtZW50fSBkaWFsb2cgZm91bmRcbiAgICovXG4gIGZ1bmN0aW9uIGZpbmROZWFyZXN0RGlhbG9nKGVsKSB7XG4gICAgd2hpbGUgKGVsKSB7XG4gICAgICBpZiAoZWwubG9jYWxOYW1lID09PSAnZGlhbG9nJykge1xuICAgICAgICByZXR1cm4gLyoqIEB0eXBlIHtIVE1MRGlhbG9nRWxlbWVudH0gKi8gKGVsKTtcbiAgICAgIH1cbiAgICAgIGVsID0gZWwucGFyZW50RWxlbWVudDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQmx1ciB0aGUgc3BlY2lmaWVkIGVsZW1lbnQsIGFzIGxvbmcgYXMgaXQncyBub3QgdGhlIEhUTUwgYm9keSBlbGVtZW50LlxuICAgKiBUaGlzIHdvcmtzIGFyb3VuZCBhbiBJRTkvMTAgYnVnIC0gYmx1cnJpbmcgdGhlIGJvZHkgY2F1c2VzIFdpbmRvd3MgdG9cbiAgICogYmx1ciB0aGUgd2hvbGUgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gZWwgdG8gYmx1clxuICAgKi9cbiAgZnVuY3Rpb24gc2FmZUJsdXIoZWwpIHtcbiAgICBpZiAoZWwgJiYgZWwuYmx1ciAmJiBlbCAhPT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgZWwuYmx1cigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFOb2RlTGlzdH0gbm9kZUxpc3QgdG8gc2VhcmNoXG4gICAqIEBwYXJhbSB7Tm9kZX0gbm9kZSB0byBmaW5kXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IHdoZXRoZXIgbm9kZSBpcyBpbnNpZGUgbm9kZUxpc3RcbiAgICovXG4gIGZ1bmN0aW9uIGluTm9kZUxpc3Qobm9kZUxpc3QsIG5vZGUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5vZGVMaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAobm9kZUxpc3RbaV0gPT09IG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudH0gZWwgdG8gY2hlY2tcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciB0aGlzIGZvcm0gaGFzIG1ldGhvZD1cImRpYWxvZ1wiXG4gICAqL1xuICBmdW5jdGlvbiBpc0Zvcm1NZXRob2REaWFsb2coZWwpIHtcbiAgICBpZiAoIWVsIHx8ICFlbC5oYXNBdHRyaWJ1dGUoJ21ldGhvZCcpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlbC5nZXRBdHRyaWJ1dGUoJ21ldGhvZCcpLnRvTG93ZXJDYXNlKCkgPT09ICdkaWFsb2cnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUhUTUxEaWFsb2dFbGVtZW50fSBkaWFsb2cgdG8gdXBncmFkZVxuICAgKiBAY29uc3RydWN0b3JcbiAgICovXG4gIGZ1bmN0aW9uIGRpYWxvZ1BvbHlmaWxsSW5mbyhkaWFsb2cpIHtcbiAgICB0aGlzLmRpYWxvZ18gPSBkaWFsb2c7XG4gICAgdGhpcy5yZXBsYWNlZFN0eWxlVG9wXyA9IGZhbHNlO1xuICAgIHRoaXMub3BlbkFzTW9kYWxfID0gZmFsc2U7XG5cbiAgICAvLyBTZXQgYTExeSByb2xlLiBCcm93c2VycyB0aGF0IHN1cHBvcnQgZGlhbG9nIGltcGxpY2l0bHkga25vdyB0aGlzIGFscmVhZHkuXG4gICAgaWYgKCFkaWFsb2cuaGFzQXR0cmlidXRlKCdyb2xlJykpIHtcbiAgICAgIGRpYWxvZy5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnZGlhbG9nJyk7XG4gICAgfVxuXG4gICAgZGlhbG9nLnNob3cgPSB0aGlzLnNob3cuYmluZCh0aGlzKTtcbiAgICBkaWFsb2cuc2hvd01vZGFsID0gdGhpcy5zaG93TW9kYWwuYmluZCh0aGlzKTtcbiAgICBkaWFsb2cuY2xvc2UgPSB0aGlzLmNsb3NlLmJpbmQodGhpcyk7XG5cbiAgICBpZiAoISgncmV0dXJuVmFsdWUnIGluIGRpYWxvZykpIHtcbiAgICAgIGRpYWxvZy5yZXR1cm5WYWx1ZSA9ICcnO1xuICAgIH1cblxuICAgIGlmICgnTXV0YXRpb25PYnNlcnZlcicgaW4gd2luZG93KSB7XG4gICAgICB2YXIgbW8gPSBuZXcgTXV0YXRpb25PYnNlcnZlcih0aGlzLm1heWJlSGlkZU1vZGFsLmJpbmQodGhpcykpO1xuICAgICAgbW8ub2JzZXJ2ZShkaWFsb2csIHthdHRyaWJ1dGVzOiB0cnVlLCBhdHRyaWJ1dGVGaWx0ZXI6IFsnb3BlbiddfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElFMTAgYW5kIGJlbG93IHN1cHBvcnQuIE5vdGUgdGhhdCBET01Ob2RlUmVtb3ZlZCBldGMgZmlyZSBfYmVmb3JlXyByZW1vdmFsLiBUaGV5IGFsc29cbiAgICAgIC8vIHNlZW0gdG8gZmlyZSBldmVuIGlmIHRoZSBlbGVtZW50IHdhcyByZW1vdmVkIGFzIHBhcnQgb2YgYSBwYXJlbnQgcmVtb3ZhbC4gVXNlIHRoZSByZW1vdmVkXG4gICAgICAvLyBldmVudHMgdG8gZm9yY2UgZG93bmdyYWRlICh1c2VmdWwgaWYgcmVtb3ZlZC9pbW1lZGlhdGVseSBhZGRlZCkuXG4gICAgICB2YXIgcmVtb3ZlZCA9IGZhbHNlO1xuICAgICAgdmFyIGNiID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlbW92ZWQgPyB0aGlzLmRvd25ncmFkZU1vZGFsKCkgOiB0aGlzLm1heWJlSGlkZU1vZGFsKCk7XG4gICAgICAgIHJlbW92ZWQgPSBmYWxzZTtcbiAgICAgIH0uYmluZCh0aGlzKTtcbiAgICAgIHZhciB0aW1lb3V0O1xuICAgICAgdmFyIGRlbGF5TW9kZWwgPSBmdW5jdGlvbihldikge1xuICAgICAgICBpZiAoZXYudGFyZ2V0ICE9PSBkaWFsb2cpIHsgcmV0dXJuOyB9ICAvLyBub3QgZm9yIGEgY2hpbGQgZWxlbWVudFxuICAgICAgICB2YXIgY2FuZCA9ICdET01Ob2RlUmVtb3ZlZCc7XG4gICAgICAgIHJlbW92ZWQgfD0gKGV2LnR5cGUuc3Vic3RyKDAsIGNhbmQubGVuZ3RoKSA9PT0gY2FuZCk7XG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIHRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dChjYiwgMCk7XG4gICAgICB9O1xuICAgICAgWydET01BdHRyTW9kaWZpZWQnLCAnRE9NTm9kZVJlbW92ZWQnLCAnRE9NTm9kZVJlbW92ZWRGcm9tRG9jdW1lbnQnXS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgZGlhbG9nLmFkZEV2ZW50TGlzdGVuZXIobmFtZSwgZGVsYXlNb2RlbCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gTm90ZSB0aGF0IHRoZSBET00gaXMgb2JzZXJ2ZWQgaW5zaWRlIERpYWxvZ01hbmFnZXIgd2hpbGUgYW55IGRpYWxvZ1xuICAgIC8vIGlzIGJlaW5nIGRpc3BsYXllZCBhcyBhIG1vZGFsLCB0byBjYXRjaCBtb2RhbCByZW1vdmFsIGZyb20gdGhlIERPTS5cblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkaWFsb2csICdvcGVuJywge1xuICAgICAgc2V0OiB0aGlzLnNldE9wZW4uYmluZCh0aGlzKSxcbiAgICAgIGdldDogZGlhbG9nLmhhc0F0dHJpYnV0ZS5iaW5kKGRpYWxvZywgJ29wZW4nKVxuICAgIH0pO1xuXG4gICAgdGhpcy5iYWNrZHJvcF8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB0aGlzLmJhY2tkcm9wXy5jbGFzc05hbWUgPSAnYmFja2Ryb3AnO1xuICAgIHRoaXMuYmFja2Ryb3BfLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5iYWNrZHJvcENsaWNrXy5iaW5kKHRoaXMpKTtcbiAgfVxuXG4gIGRpYWxvZ1BvbHlmaWxsSW5mby5wcm90b3R5cGUgPSB7XG5cbiAgICBnZXQgZGlhbG9nKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZGlhbG9nXztcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogTWF5YmUgcmVtb3ZlIHRoaXMgZGlhbG9nIGZyb20gdGhlIG1vZGFsIHRvcCBsYXllci4gVGhpcyBpcyBjYWxsZWQgd2hlblxuICAgICAqIGEgbW9kYWwgZGlhbG9nIG1heSBubyBsb25nZXIgYmUgdGVuYWJsZSwgZS5nLiwgd2hlbiB0aGUgZGlhbG9nIGlzIG5vXG4gICAgICogbG9uZ2VyIG9wZW4gb3IgaXMgbm8gbG9uZ2VyIHBhcnQgb2YgdGhlIERPTS5cbiAgICAgKi9cbiAgICBtYXliZUhpZGVNb2RhbDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5kaWFsb2dfLmhhc0F0dHJpYnV0ZSgnb3BlbicpICYmIGRvY3VtZW50LmJvZHkuY29udGFpbnModGhpcy5kaWFsb2dfKSkgeyByZXR1cm47IH1cbiAgICAgIHRoaXMuZG93bmdyYWRlTW9kYWwoKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoaXMgZGlhbG9nIGZyb20gdGhlIG1vZGFsIHRvcCBsYXllciwgbGVhdmluZyBpdCBhcyBhIG5vbi1tb2RhbC5cbiAgICAgKi9cbiAgICBkb3duZ3JhZGVNb2RhbDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoIXRoaXMub3BlbkFzTW9kYWxfKSB7IHJldHVybjsgfVxuICAgICAgdGhpcy5vcGVuQXNNb2RhbF8gPSBmYWxzZTtcbiAgICAgIHRoaXMuZGlhbG9nXy5zdHlsZS56SW5kZXggPSAnJztcblxuICAgICAgLy8gVGhpcyB3b24ndCBtYXRjaCB0aGUgbmF0aXZlIDxkaWFsb2c+IGV4YWN0bHkgYmVjYXVzZSBpZiB0aGUgdXNlciBzZXQgdG9wIG9uIGEgY2VudGVyZWRcbiAgICAgIC8vIHBvbHlmaWxsIGRpYWxvZywgdGhhdCB0b3AgZ2V0cyB0aHJvd24gYXdheSB3aGVuIHRoZSBkaWFsb2cgaXMgY2xvc2VkLiBOb3Qgc3VyZSBpdCdzXG4gICAgICAvLyBwb3NzaWJsZSB0byBwb2x5ZmlsbCB0aGlzIHBlcmZlY3RseS5cbiAgICAgIGlmICh0aGlzLnJlcGxhY2VkU3R5bGVUb3BfKSB7XG4gICAgICAgIHRoaXMuZGlhbG9nXy5zdHlsZS50b3AgPSAnJztcbiAgICAgICAgdGhpcy5yZXBsYWNlZFN0eWxlVG9wXyA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBDbGVhciB0aGUgYmFja2Ryb3AgYW5kIHJlbW92ZSBmcm9tIHRoZSBtYW5hZ2VyLlxuICAgICAgdGhpcy5iYWNrZHJvcF8ucGFyZW50Tm9kZSAmJiB0aGlzLmJhY2tkcm9wXy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuYmFja2Ryb3BfKTtcbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmRtLnJlbW92ZURpYWxvZyh0aGlzKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtib29sZWFufSB2YWx1ZSB3aGV0aGVyIHRvIG9wZW4gb3IgY2xvc2UgdGhpcyBkaWFsb2dcbiAgICAgKi9cbiAgICBzZXRPcGVuOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuZGlhbG9nXy5oYXNBdHRyaWJ1dGUoJ29wZW4nKSB8fCB0aGlzLmRpYWxvZ18uc2V0QXR0cmlidXRlKCdvcGVuJywgJycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kaWFsb2dfLnJlbW92ZUF0dHJpYnV0ZSgnb3BlbicpO1xuICAgICAgICB0aGlzLm1heWJlSGlkZU1vZGFsKCk7ICAvLyBuYi4gcmVkdW5kYW50IHdpdGggTXV0YXRpb25PYnNlcnZlclxuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGNsaWNrcyBvbiB0aGUgZmFrZSAuYmFja2Ryb3AgZWxlbWVudCwgcmVkaXJlY3RpbmcgdGhlbSBhcyBpZlxuICAgICAqIHRoZXkgd2VyZSBvbiB0aGUgZGlhbG9nIGl0c2VsZi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7IUV2ZW50fSBlIHRvIHJlZGlyZWN0XG4gICAgICovXG4gICAgYmFja2Ryb3BDbGlja186IGZ1bmN0aW9uKGUpIHtcbiAgICAgIGlmICghdGhpcy5kaWFsb2dfLmhhc0F0dHJpYnV0ZSgndGFiaW5kZXgnKSkge1xuICAgICAgICAvLyBDbGlja2luZyBvbiB0aGUgYmFja2Ryb3Agc2hvdWxkIG1vdmUgdGhlIGltcGxpY2l0IGN1cnNvciwgZXZlbiBpZiBkaWFsb2cgY2Fubm90IGJlXG4gICAgICAgIC8vIGZvY3VzZWQuIENyZWF0ZSBhIGZha2UgdGhpbmcgdG8gZm9jdXMgb24uIElmIHRoZSBiYWNrZHJvcCB3YXMgX2JlZm9yZV8gdGhlIGRpYWxvZywgdGhpc1xuICAgICAgICAvLyB3b3VsZCBub3QgYmUgbmVlZGVkIC0gY2xpY2tzIHdvdWxkIG1vdmUgdGhlIGltcGxpY2l0IGN1cnNvciB0aGVyZS5cbiAgICAgICAgdmFyIGZha2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5kaWFsb2dfLmluc2VydEJlZm9yZShmYWtlLCB0aGlzLmRpYWxvZ18uZmlyc3RDaGlsZCk7XG4gICAgICAgIGZha2UudGFiSW5kZXggPSAtMTtcbiAgICAgICAgZmFrZS5mb2N1cygpO1xuICAgICAgICB0aGlzLmRpYWxvZ18ucmVtb3ZlQ2hpbGQoZmFrZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmRpYWxvZ18uZm9jdXMoKTtcbiAgICAgIH1cblxuICAgICAgdmFyIHJlZGlyZWN0ZWRFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuICAgICAgcmVkaXJlY3RlZEV2ZW50LmluaXRNb3VzZUV2ZW50KGUudHlwZSwgZS5idWJibGVzLCBlLmNhbmNlbGFibGUsIHdpbmRvdyxcbiAgICAgICAgICBlLmRldGFpbCwgZS5zY3JlZW5YLCBlLnNjcmVlblksIGUuY2xpZW50WCwgZS5jbGllbnRZLCBlLmN0cmxLZXksXG4gICAgICAgICAgZS5hbHRLZXksIGUuc2hpZnRLZXksIGUubWV0YUtleSwgZS5idXR0b24sIGUucmVsYXRlZFRhcmdldCk7XG4gICAgICB0aGlzLmRpYWxvZ18uZGlzcGF0Y2hFdmVudChyZWRpcmVjdGVkRXZlbnQpO1xuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogRm9jdXNlcyBvbiB0aGUgZmlyc3QgZm9jdXNhYmxlIGVsZW1lbnQgd2l0aGluIHRoZSBkaWFsb2cuIFRoaXMgd2lsbCBhbHdheXMgYmx1ciB0aGUgY3VycmVudFxuICAgICAqIGZvY3VzLCBldmVuIGlmIG5vdGhpbmcgd2l0aGluIHRoZSBkaWFsb2cgaXMgZm91bmQuXG4gICAgICovXG4gICAgZm9jdXNfOiBmdW5jdGlvbigpIHtcbiAgICAgIC8vIEZpbmQgZWxlbWVudCB3aXRoIGBhdXRvZm9jdXNgIGF0dHJpYnV0ZSwgb3IgZmFsbCBiYWNrIHRvIHRoZSBmaXJzdCBmb3JtL3RhYmluZGV4IGNvbnRyb2wuXG4gICAgICB2YXIgdGFyZ2V0ID0gdGhpcy5kaWFsb2dfLnF1ZXJ5U2VsZWN0b3IoJ1thdXRvZm9jdXNdOm5vdChbZGlzYWJsZWRdKScpO1xuICAgICAgaWYgKCF0YXJnZXQgJiYgdGhpcy5kaWFsb2dfLnRhYkluZGV4ID49IDApIHtcbiAgICAgICAgdGFyZ2V0ID0gdGhpcy5kaWFsb2dfO1xuICAgICAgfVxuICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgLy8gTm90ZSB0aGF0IHRoaXMgaXMgJ2FueSBmb2N1c2FibGUgYXJlYScuIFRoaXMgbGlzdCBpcyBwcm9iYWJseSBub3QgZXhoYXVzdGl2ZSwgYnV0IHRoZVxuICAgICAgICAvLyBhbHRlcm5hdGl2ZSBpbnZvbHZlcyBzdGVwcGluZyB0aHJvdWdoIGFuZCB0cnlpbmcgdG8gZm9jdXMgZXZlcnl0aGluZy5cbiAgICAgICAgdmFyIG9wdHMgPSBbJ2J1dHRvbicsICdpbnB1dCcsICdrZXlnZW4nLCAnc2VsZWN0JywgJ3RleHRhcmVhJ107XG4gICAgICAgIHZhciBxdWVyeSA9IG9wdHMubWFwKGZ1bmN0aW9uKGVsKSB7XG4gICAgICAgICAgcmV0dXJuIGVsICsgJzpub3QoW2Rpc2FibGVkXSknO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gVE9ETyhzYW10aG9yKTogdGFiaW5kZXggdmFsdWVzIHRoYXQgYXJlIG5vdCBudW1lcmljIGFyZSBub3QgZm9jdXNhYmxlLlxuICAgICAgICBxdWVyeS5wdXNoKCdbdGFiaW5kZXhdOm5vdChbZGlzYWJsZWRdKTpub3QoW3RhYmluZGV4PVwiXCJdKScpOyAgLy8gdGFiaW5kZXggIT0gXCJcIiwgbm90IGRpc2FibGVkXG4gICAgICAgIHRhcmdldCA9IHRoaXMuZGlhbG9nXy5xdWVyeVNlbGVjdG9yKHF1ZXJ5LmpvaW4oJywgJykpO1xuICAgICAgfVxuICAgICAgc2FmZUJsdXIoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCk7XG4gICAgICB0YXJnZXQgJiYgdGFyZ2V0LmZvY3VzKCk7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHpJbmRleCBmb3IgdGhlIGJhY2tkcm9wIGFuZCBkaWFsb2cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGlhbG9nWlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiYWNrZHJvcFpcbiAgICAgKi9cbiAgICB1cGRhdGVaSW5kZXg6IGZ1bmN0aW9uKGRpYWxvZ1osIGJhY2tkcm9wWikge1xuICAgICAgaWYgKGRpYWxvZ1ogPCBiYWNrZHJvcFopIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWFsb2daIHNob3VsZCBuZXZlciBiZSA8IGJhY2tkcm9wWicpO1xuICAgICAgfVxuICAgICAgdGhpcy5kaWFsb2dfLnN0eWxlLnpJbmRleCA9IGRpYWxvZ1o7XG4gICAgICB0aGlzLmJhY2tkcm9wXy5zdHlsZS56SW5kZXggPSBiYWNrZHJvcFo7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSBkaWFsb2cuIElmIHRoZSBkaWFsb2cgaXMgYWxyZWFkeSBvcGVuLCB0aGlzIGRvZXMgbm90aGluZy5cbiAgICAgKi9cbiAgICBzaG93OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghdGhpcy5kaWFsb2dfLm9wZW4pIHtcbiAgICAgICAgdGhpcy5zZXRPcGVuKHRydWUpO1xuICAgICAgICB0aGlzLmZvY3VzXygpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBTaG93IHRoaXMgZGlhbG9nIG1vZGFsbHkuXG4gICAgICovXG4gICAgc2hvd01vZGFsOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLmRpYWxvZ18uaGFzQXR0cmlidXRlKCdvcGVuJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZXhlY3V0ZSBcXCdzaG93TW9kYWxcXCcgb24gZGlhbG9nOiBUaGUgZWxlbWVudCBpcyBhbHJlYWR5IG9wZW4sIGFuZCB0aGVyZWZvcmUgY2Fubm90IGJlIG9wZW5lZCBtb2RhbGx5LicpO1xuICAgICAgfVxuICAgICAgaWYgKCFkb2N1bWVudC5ib2R5LmNvbnRhaW5zKHRoaXMuZGlhbG9nXykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZXhlY3V0ZSBcXCdzaG93TW9kYWxcXCcgb24gZGlhbG9nOiBUaGUgZWxlbWVudCBpcyBub3QgaW4gYSBEb2N1bWVudC4nKTtcbiAgICAgIH1cbiAgICAgIGlmICghZGlhbG9nUG9seWZpbGwuZG0ucHVzaERpYWxvZyh0aGlzKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBleGVjdXRlIFxcJ3Nob3dNb2RhbFxcJyBvbiBkaWFsb2c6IFRoZXJlIGFyZSB0b28gbWFueSBvcGVuIG1vZGFsIGRpYWxvZ3MuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjcmVhdGVzU3RhY2tpbmdDb250ZXh0KHRoaXMuZGlhbG9nXy5wYXJlbnRFbGVtZW50KSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0EgZGlhbG9nIGlzIGJlaW5nIHNob3duIGluc2lkZSBhIHN0YWNraW5nIGNvbnRleHQuICcgK1xuICAgICAgICAgICAgJ1RoaXMgbWF5IGNhdXNlIGl0IHRvIGJlIHVudXNhYmxlLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIHRoaXMgbGluazogJyArXG4gICAgICAgICAgICAnaHR0cHM6Ly9naXRodWIuY29tL0dvb2dsZUNocm9tZS9kaWFsb2ctcG9seWZpbGwvI3N0YWNraW5nLWNvbnRleHQnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRPcGVuKHRydWUpO1xuICAgICAgdGhpcy5vcGVuQXNNb2RhbF8gPSB0cnVlO1xuXG4gICAgICAvLyBPcHRpb25hbGx5IGNlbnRlciB2ZXJ0aWNhbGx5LCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCB2aWV3cG9ydC5cbiAgICAgIGlmIChkaWFsb2dQb2x5ZmlsbC5uZWVkc0NlbnRlcmluZyh0aGlzLmRpYWxvZ18pKSB7XG4gICAgICAgIGRpYWxvZ1BvbHlmaWxsLnJlcG9zaXRpb24odGhpcy5kaWFsb2dfKTtcbiAgICAgICAgdGhpcy5yZXBsYWNlZFN0eWxlVG9wXyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlcGxhY2VkU3R5bGVUb3BfID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIC8vIEluc2VydCBiYWNrZHJvcC5cbiAgICAgIHRoaXMuZGlhbG9nXy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tkcm9wXywgdGhpcy5kaWFsb2dfLm5leHRTaWJsaW5nKTtcblxuICAgICAgLy8gRm9jdXMgb24gd2hhdGV2ZXIgaW5zaWRlIHRoZSBkaWFsb2cuXG4gICAgICB0aGlzLmZvY3VzXygpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgdGhpcyBIVE1MRGlhbG9nRWxlbWVudC4gVGhpcyBpcyBvcHRpb25hbCB2cyBjbGVhcmluZyB0aGUgb3BlblxuICAgICAqIGF0dHJpYnV0ZSwgaG93ZXZlciB0aGlzIGZpcmVzIGEgJ2Nsb3NlJyBldmVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X3JldHVyblZhbHVlIHRvIHVzZSBhcyB0aGUgcmV0dXJuVmFsdWVcbiAgICAgKi9cbiAgICBjbG9zZTogZnVuY3Rpb24ob3B0X3JldHVyblZhbHVlKSB7XG4gICAgICBpZiAoIXRoaXMuZGlhbG9nXy5oYXNBdHRyaWJ1dGUoJ29wZW4nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBleGVjdXRlIFxcJ2Nsb3NlXFwnIG9uIGRpYWxvZzogVGhlIGVsZW1lbnQgZG9lcyBub3QgaGF2ZSBhbiBcXCdvcGVuXFwnIGF0dHJpYnV0ZSwgYW5kIHRoZXJlZm9yZSBjYW5ub3QgYmUgY2xvc2VkLicpO1xuICAgICAgfVxuICAgICAgdGhpcy5zZXRPcGVuKGZhbHNlKTtcblxuICAgICAgLy8gTGVhdmUgcmV0dXJuVmFsdWUgdW50b3VjaGVkIGluIGNhc2UgaXQgd2FzIHNldCBkaXJlY3RseSBvbiB0aGUgZWxlbWVudFxuICAgICAgaWYgKG9wdF9yZXR1cm5WYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuZGlhbG9nXy5yZXR1cm5WYWx1ZSA9IG9wdF9yZXR1cm5WYWx1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gVHJpZ2dlcmluZyBcImNsb3NlXCIgZXZlbnQgZm9yIGFueSBhdHRhY2hlZCBsaXN0ZW5lcnMgb24gdGhlIDxkaWFsb2c+LlxuICAgICAgdmFyIGNsb3NlRXZlbnQgPSBuZXcgc3VwcG9ydEN1c3RvbUV2ZW50KCdjbG9zZScsIHtcbiAgICAgICAgYnViYmxlczogZmFsc2UsXG4gICAgICAgIGNhbmNlbGFibGU6IGZhbHNlXG4gICAgICB9KTtcbiAgICAgIHRoaXMuZGlhbG9nXy5kaXNwYXRjaEV2ZW50KGNsb3NlRXZlbnQpO1xuICAgIH1cblxuICB9O1xuXG4gIHZhciBkaWFsb2dQb2x5ZmlsbCA9IHt9O1xuXG4gIGRpYWxvZ1BvbHlmaWxsLnJlcG9zaXRpb24gPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgdmFyIHNjcm9sbFRvcCA9IGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3A7XG4gICAgdmFyIHRvcFZhbHVlID0gc2Nyb2xsVG9wICsgKHdpbmRvdy5pbm5lckhlaWdodCAtIGVsZW1lbnQub2Zmc2V0SGVpZ2h0KSAvIDI7XG4gICAgZWxlbWVudC5zdHlsZS50b3AgPSBNYXRoLm1heChzY3JvbGxUb3AsIHRvcFZhbHVlKSArICdweCc7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwuaXNJbmxpbmVQb3NpdGlvblNldEJ5U3R5bGVzaGVldCA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRvY3VtZW50LnN0eWxlU2hlZXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgc3R5bGVTaGVldCA9IGRvY3VtZW50LnN0eWxlU2hlZXRzW2ldO1xuICAgICAgdmFyIGNzc1J1bGVzID0gbnVsbDtcbiAgICAgIC8vIFNvbWUgYnJvd3NlcnMgdGhyb3cgb24gY3NzUnVsZXMuXG4gICAgICB0cnkge1xuICAgICAgICBjc3NSdWxlcyA9IHN0eWxlU2hlZXQuY3NzUnVsZXM7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgaWYgKCFjc3NSdWxlcykgeyBjb250aW51ZTsgfVxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBjc3NSdWxlcy5sZW5ndGg7ICsraikge1xuICAgICAgICB2YXIgcnVsZSA9IGNzc1J1bGVzW2pdO1xuICAgICAgICB2YXIgc2VsZWN0ZWROb2RlcyA9IG51bGw7XG4gICAgICAgIC8vIElnbm9yZSBlcnJvcnMgb24gaW52YWxpZCBzZWxlY3RvciB0ZXh0cy5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzZWxlY3RlZE5vZGVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChydWxlLnNlbGVjdG9yVGV4dCk7XG4gICAgICAgIH0gY2F0Y2goZSkge31cbiAgICAgICAgaWYgKCFzZWxlY3RlZE5vZGVzIHx8ICFpbk5vZGVMaXN0KHNlbGVjdGVkTm9kZXMsIGVsZW1lbnQpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNzc1RvcCA9IHJ1bGUuc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgndG9wJyk7XG4gICAgICAgIHZhciBjc3NCb3R0b20gPSBydWxlLnN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2JvdHRvbScpO1xuICAgICAgICBpZiAoKGNzc1RvcCAmJiBjc3NUb3AgIT09ICdhdXRvJykgfHwgKGNzc0JvdHRvbSAmJiBjc3NCb3R0b20gIT09ICdhdXRvJykpIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwubmVlZHNDZW50ZXJpbmcgPSBmdW5jdGlvbihkaWFsb2cpIHtcbiAgICB2YXIgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRpYWxvZyk7XG4gICAgaWYgKGNvbXB1dGVkU3R5bGUucG9zaXRpb24gIT09ICdhYnNvbHV0ZScpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBXZSBtdXN0IGRldGVybWluZSB3aGV0aGVyIHRoZSB0b3AvYm90dG9tIHNwZWNpZmllZCB2YWx1ZSBpcyBub24tYXV0by4gIEluXG4gICAgLy8gV2ViS2l0L0JsaW5rLCBjaGVja2luZyBjb21wdXRlZFN0eWxlLnRvcCA9PSAnYXV0bycgaXMgc3VmZmljaWVudCwgYnV0XG4gICAgLy8gRmlyZWZveCByZXR1cm5zIHRoZSB1c2VkIHZhbHVlLiBTbyB3ZSBkbyB0aGlzIGNyYXp5IHRoaW5nIGluc3RlYWQ6IGNoZWNrXG4gICAgLy8gdGhlIGlubGluZSBzdHlsZSBhbmQgdGhlbiBnbyB0aHJvdWdoIENTUyBydWxlcy5cbiAgICBpZiAoKGRpYWxvZy5zdHlsZS50b3AgIT09ICdhdXRvJyAmJiBkaWFsb2cuc3R5bGUudG9wICE9PSAnJykgfHxcbiAgICAgICAgKGRpYWxvZy5zdHlsZS5ib3R0b20gIT09ICdhdXRvJyAmJiBkaWFsb2cuc3R5bGUuYm90dG9tICE9PSAnJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuICFkaWFsb2dQb2x5ZmlsbC5pc0lubGluZVBvc2l0aW9uU2V0QnlTdHlsZXNoZWV0KGRpYWxvZyk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgdG8gZm9yY2UgdXBncmFkZVxuICAgKi9cbiAgZGlhbG9nUG9seWZpbGwuZm9yY2VSZWdpc3RlckRpYWxvZyA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAod2luZG93LkhUTUxEaWFsb2dFbGVtZW50IHx8IGVsZW1lbnQuc2hvd01vZGFsKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1RoaXMgYnJvd3NlciBhbHJlYWR5IHN1cHBvcnRzIDxkaWFsb2c+LCB0aGUgcG9seWZpbGwgJyArXG4gICAgICAgICAgJ21heSBub3Qgd29yayBjb3JyZWN0bHknLCBlbGVtZW50KTtcbiAgICB9XG4gICAgaWYgKGVsZW1lbnQubG9jYWxOYW1lICE9PSAnZGlhbG9nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcmVnaXN0ZXIgZGlhbG9nOiBUaGUgZWxlbWVudCBpcyBub3QgYSBkaWFsb2cuJyk7XG4gICAgfVxuICAgIG5ldyBkaWFsb2dQb2x5ZmlsbEluZm8oLyoqIEB0eXBlIHshSFRNTERpYWxvZ0VsZW1lbnR9ICovIChlbGVtZW50KSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnQgdG8gdXBncmFkZSwgaWYgbmVjZXNzYXJ5XG4gICAqL1xuICBkaWFsb2dQb2x5ZmlsbC5yZWdpc3RlckRpYWxvZyA9IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoIWVsZW1lbnQuc2hvd01vZGFsKSB7XG4gICAgICBkaWFsb2dQb2x5ZmlsbC5mb3JjZVJlZ2lzdGVyRGlhbG9nKGVsZW1lbnQpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQGNvbnN0cnVjdG9yXG4gICAqL1xuICBkaWFsb2dQb2x5ZmlsbC5EaWFsb2dNYW5hZ2VyID0gZnVuY3Rpb24oKSB7XG4gICAgLyoqIEB0eXBlIHshQXJyYXk8IWRpYWxvZ1BvbHlmaWxsSW5mbz59ICovXG4gICAgdGhpcy5wZW5kaW5nRGlhbG9nU3RhY2sgPSBbXTtcblxuICAgIHZhciBjaGVja0RPTSA9IHRoaXMuY2hlY2tET01fLmJpbmQodGhpcyk7XG5cbiAgICAvLyBUaGUgb3ZlcmxheSBpcyB1c2VkIHRvIHNpbXVsYXRlIGhvdyBhIG1vZGFsIGRpYWxvZyBibG9ja3MgdGhlIGRvY3VtZW50LlxuICAgIC8vIFRoZSBibG9ja2luZyBkaWFsb2cgaXMgcG9zaXRpb25lZCBvbiB0b3Agb2YgdGhlIG92ZXJsYXksIGFuZCB0aGUgcmVzdCBvZlxuICAgIC8vIHRoZSBkaWFsb2dzIG9uIHRoZSBwZW5kaW5nIGRpYWxvZyBzdGFjayBhcmUgcG9zaXRpb25lZCBiZWxvdyBpdC4gSW4gdGhlXG4gICAgLy8gYWN0dWFsIGltcGxlbWVudGF0aW9uLCB0aGUgbW9kYWwgZGlhbG9nIHN0YWNraW5nIGlzIGNvbnRyb2xsZWQgYnkgdGhlXG4gICAgLy8gdG9wIGxheWVyLCB3aGVyZSB6LWluZGV4IGhhcyBubyBlZmZlY3QuXG4gICAgdGhpcy5vdmVybGF5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgdGhpcy5vdmVybGF5LmNsYXNzTmFtZSA9ICdfZGlhbG9nX292ZXJsYXknO1xuICAgIHRoaXMub3ZlcmxheS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHRoaXMuZm9yd2FyZFRhYl8gPSB1bmRlZmluZWQ7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgY2hlY2tET00oW10pOyAgLy8gc2FuaXR5LWNoZWNrIERPTVxuICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICB0aGlzLmhhbmRsZUtleV8gPSB0aGlzLmhhbmRsZUtleV8uYmluZCh0aGlzKTtcbiAgICB0aGlzLmhhbmRsZUZvY3VzXyA9IHRoaXMuaGFuZGxlRm9jdXNfLmJpbmQodGhpcyk7XG5cbiAgICB0aGlzLnpJbmRleExvd18gPSAxMDAwMDA7XG4gICAgdGhpcy56SW5kZXhIaWdoXyA9IDEwMDAwMCArIDE1MDtcblxuICAgIHRoaXMuZm9yd2FyZFRhYl8gPSB1bmRlZmluZWQ7XG5cbiAgICBpZiAoJ011dGF0aW9uT2JzZXJ2ZXInIGluIHdpbmRvdykge1xuICAgICAgdGhpcy5tb18gPSBuZXcgTXV0YXRpb25PYnNlcnZlcihmdW5jdGlvbihyZWNvcmRzKSB7XG4gICAgICAgIHZhciByZW1vdmVkID0gW107XG4gICAgICAgIHJlY29yZHMuZm9yRWFjaChmdW5jdGlvbihyZWMpIHtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgYzsgYyA9IHJlYy5yZW1vdmVkTm9kZXNbaV07ICsraSkge1xuICAgICAgICAgICAgaWYgKCEoYyBpbnN0YW5jZW9mIEVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjLmxvY2FsTmFtZSA9PT0gJ2RpYWxvZycpIHtcbiAgICAgICAgICAgICAgcmVtb3ZlZC5wdXNoKGMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtb3ZlZCA9IHJlbW92ZWQuY29uY2F0KGMucXVlcnlTZWxlY3RvckFsbCgnZGlhbG9nJykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlbW92ZWQubGVuZ3RoICYmIGNoZWNrRE9NKHJlbW92ZWQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxsZWQgb24gdGhlIGZpcnN0IG1vZGFsIGRpYWxvZyBiZWluZyBzaG93bi4gQWRkcyB0aGUgb3ZlcmxheSBhbmQgcmVsYXRlZFxuICAgKiBoYW5kbGVycy5cbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLmJsb2NrRG9jdW1lbnQgPSBmdW5jdGlvbigpIHtcbiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmhhbmRsZUZvY3VzXywgdHJ1ZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuaGFuZGxlS2V5Xyk7XG4gICAgdGhpcy5tb18gJiYgdGhpcy5tb18ub2JzZXJ2ZShkb2N1bWVudCwge2NoaWxkTGlzdDogdHJ1ZSwgc3VidHJlZTogdHJ1ZX0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxsZWQgb24gdGhlIGZpcnN0IG1vZGFsIGRpYWxvZyBiZWluZyByZW1vdmVkLCBpLmUuLCB3aGVuIG5vIG1vcmUgbW9kYWxcbiAgICogZGlhbG9ncyBhcmUgdmlzaWJsZS5cbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLnVuYmxvY2tEb2N1bWVudCA9IGZ1bmN0aW9uKCkge1xuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuaGFuZGxlRm9jdXNfLCB0cnVlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVLZXlfKTtcbiAgICB0aGlzLm1vXyAmJiB0aGlzLm1vXy5kaXNjb25uZWN0KCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHN0YWNraW5nIG9mIGFsbCBrbm93biBkaWFsb2dzLlxuICAgKi9cbiAgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlci5wcm90b3R5cGUudXBkYXRlU3RhY2tpbmcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgekluZGV4ID0gdGhpcy56SW5kZXhIaWdoXztcblxuICAgIGZvciAodmFyIGkgPSAwLCBkcGk7IGRwaSA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrW2ldOyArK2kpIHtcbiAgICAgIGRwaS51cGRhdGVaSW5kZXgoLS16SW5kZXgsIC0tekluZGV4KTtcbiAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgIHRoaXMub3ZlcmxheS5zdHlsZS56SW5kZXggPSAtLXpJbmRleDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBNYWtlIHRoZSBvdmVybGF5IGEgc2libGluZyBvZiB0aGUgZGlhbG9nIGl0c2VsZi5cbiAgICB2YXIgbGFzdCA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrWzBdO1xuICAgIGlmIChsYXN0KSB7XG4gICAgICB2YXIgcCA9IGxhc3QuZGlhbG9nLnBhcmVudE5vZGUgfHwgZG9jdW1lbnQuYm9keTtcbiAgICAgIHAuYXBwZW5kQ2hpbGQodGhpcy5vdmVybGF5KTtcbiAgICB9IGVsc2UgaWYgKHRoaXMub3ZlcmxheS5wYXJlbnROb2RlKSB7XG4gICAgICB0aGlzLm92ZXJsYXkucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLm92ZXJsYXkpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBjYW5kaWRhdGUgdG8gY2hlY2sgaWYgY29udGFpbmVkIG9yIGlzIHRoZSB0b3AtbW9zdCBtb2RhbCBkaWFsb2dcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciBjYW5kaWRhdGUgaXMgY29udGFpbmVkIGluIHRvcCBkaWFsb2dcbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLmNvbnRhaW5lZEJ5VG9wRGlhbG9nXyA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuICAgIHdoaWxlIChjYW5kaWRhdGUgPSBmaW5kTmVhcmVzdERpYWxvZyhjYW5kaWRhdGUpKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgZHBpOyBkcGkgPSB0aGlzLnBlbmRpbmdEaWFsb2dTdGFja1tpXTsgKytpKSB7XG4gICAgICAgIGlmIChkcGkuZGlhbG9nID09PSBjYW5kaWRhdGUpIHtcbiAgICAgICAgICByZXR1cm4gaSA9PT0gMDsgIC8vIG9ubHkgdmFsaWQgaWYgdG9wLW1vc3RcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2FuZGlkYXRlID0gY2FuZGlkYXRlLnBhcmVudEVsZW1lbnQ7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICBkaWFsb2dQb2x5ZmlsbC5EaWFsb2dNYW5hZ2VyLnByb3RvdHlwZS5oYW5kbGVGb2N1c18gPSBmdW5jdGlvbihldmVudCkge1xuICAgIGlmICh0aGlzLmNvbnRhaW5lZEJ5VG9wRGlhbG9nXyhldmVudC50YXJnZXQpKSB7IHJldHVybjsgfVxuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBzYWZlQmx1cigvKiogQHR5cGUge0VsZW1lbnR9ICovIChldmVudC50YXJnZXQpKTtcblxuICAgIGlmICh0aGlzLmZvcndhcmRUYWJfID09PSB1bmRlZmluZWQpIHsgcmV0dXJuOyB9ICAvLyBtb3ZlIGZvY3VzIG9ubHkgZnJvbSBhIHRhYiBrZXlcblxuICAgIHZhciBkcGkgPSB0aGlzLnBlbmRpbmdEaWFsb2dTdGFja1swXTtcbiAgICB2YXIgZGlhbG9nID0gZHBpLmRpYWxvZztcbiAgICB2YXIgcG9zaXRpb24gPSBkaWFsb2cuY29tcGFyZURvY3VtZW50UG9zaXRpb24oZXZlbnQudGFyZ2V0KTtcbiAgICBpZiAocG9zaXRpb24gJiBOb2RlLkRPQ1VNRU5UX1BPU0lUSU9OX1BSRUNFRElORykge1xuICAgICAgaWYgKHRoaXMuZm9yd2FyZFRhYl8pIHsgIC8vIGZvcndhcmRcbiAgICAgICAgZHBpLmZvY3VzXygpO1xuICAgICAgfSBlbHNlIHsgIC8vIGJhY2t3YXJkc1xuICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVE9ETzogRm9jdXMgYWZ0ZXIgdGhlIGRpYWxvZywgaXMgaWdub3JlZC5cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlci5wcm90b3R5cGUuaGFuZGxlS2V5XyA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgdGhpcy5mb3J3YXJkVGFiXyA9IHVuZGVmaW5lZDtcbiAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMjcpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIHZhciBjYW5jZWxFdmVudCA9IG5ldyBzdXBwb3J0Q3VzdG9tRXZlbnQoJ2NhbmNlbCcsIHtcbiAgICAgICAgYnViYmxlczogZmFsc2UsXG4gICAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgdmFyIGRwaSA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrWzBdO1xuICAgICAgaWYgKGRwaSAmJiBkcGkuZGlhbG9nLmRpc3BhdGNoRXZlbnQoY2FuY2VsRXZlbnQpKSB7XG4gICAgICAgIGRwaS5kaWFsb2cuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV2ZW50LmtleUNvZGUgPT09IDkpIHtcbiAgICAgIHRoaXMuZm9yd2FyZFRhYl8gPSAhZXZlbnQuc2hpZnRLZXk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBGaW5kcyBhbmQgZG93bmdyYWRlcyBhbnkga25vd24gbW9kYWwgZGlhbG9ncyB0aGF0IGFyZSBubyBsb25nZXIgZGlzcGxheWVkLiBEaWFsb2dzIHRoYXQgYXJlXG4gICAqIHJlbW92ZWQgYW5kIGltbWVkaWF0ZWx5IHJlYWRkZWQgZG9uJ3Qgc3RheSBtb2RhbCwgdGhleSBiZWNvbWUgbm9ybWFsLlxuICAgKlxuICAgKiBAcGFyYW0geyFBcnJheTwhSFRNTERpYWxvZ0VsZW1lbnQ+fSByZW1vdmVkIHRoYXQgaGF2ZSBkZWZpbml0ZWx5IGJlZW4gcmVtb3ZlZFxuICAgKi9cbiAgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlci5wcm90b3R5cGUuY2hlY2tET01fID0gZnVuY3Rpb24ocmVtb3ZlZCkge1xuICAgIC8vIFRoaXMgb3BlcmF0ZXMgb24gYSBjbG9uZSBiZWNhdXNlIGl0IG1heSBjYXVzZSBpdCB0byBjaGFuZ2UuIEVhY2ggY2hhbmdlIGFsc28gY2FsbHNcbiAgICAvLyB1cGRhdGVTdGFja2luZywgd2hpY2ggb25seSBhY3R1YWxseSBuZWVkcyB0byBoYXBwZW4gb25jZS4gQnV0IHdobyByZW1vdmVzIG1hbnkgbW9kYWwgZGlhbG9nc1xuICAgIC8vIGF0IGEgdGltZT8hXG4gICAgdmFyIGNsb25lID0gdGhpcy5wZW5kaW5nRGlhbG9nU3RhY2suc2xpY2UoKTtcbiAgICBjbG9uZS5mb3JFYWNoKGZ1bmN0aW9uKGRwaSkge1xuICAgICAgaWYgKHJlbW92ZWQuaW5kZXhPZihkcGkuZGlhbG9nKSAhPT0gLTEpIHtcbiAgICAgICAgZHBpLmRvd25ncmFkZU1vZGFsKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkcGkubWF5YmVIaWRlTW9kYWwoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHshZGlhbG9nUG9seWZpbGxJbmZvfSBkcGlcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gd2hldGhlciB0aGUgZGlhbG9nIHdhcyBhbGxvd2VkXG4gICAqL1xuICBkaWFsb2dQb2x5ZmlsbC5EaWFsb2dNYW5hZ2VyLnByb3RvdHlwZS5wdXNoRGlhbG9nID0gZnVuY3Rpb24oZHBpKSB7XG4gICAgdmFyIGFsbG93ZWQgPSAodGhpcy56SW5kZXhIaWdoXyAtIHRoaXMuekluZGV4TG93XykgLyAyIC0gMTtcbiAgICBpZiAodGhpcy5wZW5kaW5nRGlhbG9nU3RhY2subGVuZ3RoID49IGFsbG93ZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrLnVuc2hpZnQoZHBpKSA9PT0gMSkge1xuICAgICAgdGhpcy5ibG9ja0RvY3VtZW50KCk7XG4gICAgfVxuICAgIHRoaXMudXBkYXRlU3RhY2tpbmcoKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHshZGlhbG9nUG9seWZpbGxJbmZvfSBkcGlcbiAgICovXG4gIGRpYWxvZ1BvbHlmaWxsLkRpYWxvZ01hbmFnZXIucHJvdG90eXBlLnJlbW92ZURpYWxvZyA9IGZ1bmN0aW9uKGRwaSkge1xuICAgIHZhciBpbmRleCA9IHRoaXMucGVuZGluZ0RpYWxvZ1N0YWNrLmluZGV4T2YoZHBpKTtcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7IHJldHVybjsgfVxuXG4gICAgdGhpcy5wZW5kaW5nRGlhbG9nU3RhY2suc3BsaWNlKGluZGV4LCAxKTtcbiAgICBpZiAodGhpcy5wZW5kaW5nRGlhbG9nU3RhY2subGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnVuYmxvY2tEb2N1bWVudCgpO1xuICAgIH1cbiAgICB0aGlzLnVwZGF0ZVN0YWNraW5nKCk7XG4gIH07XG5cbiAgZGlhbG9nUG9seWZpbGwuZG0gPSBuZXcgZGlhbG9nUG9seWZpbGwuRGlhbG9nTWFuYWdlcigpO1xuICBkaWFsb2dQb2x5ZmlsbC5mb3JtU3VibWl0dGVyID0gbnVsbDtcbiAgZGlhbG9nUG9seWZpbGwudXNlVmFsdWUgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBJbnN0YWxscyBnbG9iYWwgaGFuZGxlcnMsIHN1Y2ggYXMgY2xpY2sgbGlzdGVycyBhbmQgbmF0aXZlIG1ldGhvZCBvdmVycmlkZXMuIFRoZXNlIGFyZSBuZWVkZWRcbiAgICogZXZlbiBpZiBhIG5vIGRpYWxvZyBpcyByZWdpc3RlcmVkLCBhcyB0aGV5IGRlYWwgd2l0aCA8Zm9ybSBtZXRob2Q9XCJkaWFsb2dcIj4uXG4gICAqL1xuICBpZiAod2luZG93LkhUTUxEaWFsb2dFbGVtZW50ID09PSB1bmRlZmluZWQpIHtcblxuICAgIC8qKlxuICAgICAqIElmIEhUTUxGb3JtRWxlbWVudCB0cmFuc2xhdGVzIG1ldGhvZD1cIkRJQUxPR1wiIGludG8gJ2dldCcsIHRoZW4gcmVwbGFjZSB0aGUgZGVzY3JpcHRvciB3aXRoXG4gICAgICogb25lIHRoYXQgcmV0dXJucyB0aGUgY29ycmVjdCB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgdGVzdEZvcm0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdmb3JtJyk7XG4gICAgdGVzdEZvcm0uc2V0QXR0cmlidXRlKCdtZXRob2QnLCAnZGlhbG9nJyk7XG4gICAgaWYgKHRlc3RGb3JtLm1ldGhvZCAhPT0gJ2RpYWxvZycpIHtcbiAgICAgIHZhciBtZXRob2REZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihIVE1MRm9ybUVsZW1lbnQucHJvdG90eXBlLCAnbWV0aG9kJyk7XG4gICAgICBpZiAobWV0aG9kRGVzY3JpcHRvcikge1xuICAgICAgICAvLyBuYi4gU29tZSBvbGRlciBpT1MgYW5kIG9sZGVyIFBoYW50b21KUyBmYWlsIHRvIHJldHVybiB0aGUgZGVzY3JpcHRvci4gRG9uJ3QgZG8gYW55dGhpbmdcbiAgICAgICAgLy8gYW5kIGRvbid0IGJvdGhlciB0byB1cGRhdGUgdGhlIGVsZW1lbnQuXG4gICAgICAgIHZhciByZWFsR2V0ID0gbWV0aG9kRGVzY3JpcHRvci5nZXQ7XG4gICAgICAgIG1ldGhvZERlc2NyaXB0b3IuZ2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgaWYgKGlzRm9ybU1ldGhvZERpYWxvZyh0aGlzKSkge1xuICAgICAgICAgICAgcmV0dXJuICdkaWFsb2cnO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVhbEdldC5jYWxsKHRoaXMpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgcmVhbFNldCA9IG1ldGhvZERlc2NyaXB0b3Iuc2V0O1xuICAgICAgICBtZXRob2REZXNjcmlwdG9yLnNldCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYudG9Mb3dlckNhc2UoKSA9PT0gJ2RpYWxvZycpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNldEF0dHJpYnV0ZSgnbWV0aG9kJywgdik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiByZWFsU2V0LmNhbGwodGhpcywgdik7XG4gICAgICAgIH07XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShIVE1MRm9ybUVsZW1lbnQucHJvdG90eXBlLCAnbWV0aG9kJywgbWV0aG9kRGVzY3JpcHRvcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2xvYmFsICdjbGljaycgaGFuZGxlciwgdG8gY2FwdHVyZSB0aGUgPGlucHV0IHR5cGU9XCJzdWJtaXRcIj4gb3IgPGJ1dHRvbj4gZWxlbWVudCB3aGljaCBoYXNcbiAgICAgKiBzdWJtaXR0ZWQgYSA8Zm9ybSBtZXRob2Q9XCJkaWFsb2dcIj4uIE5lZWRlZCBhcyBTYWZhcmkgYW5kIG90aGVycyBkb24ndCByZXBvcnQgdGhpcyBpbnNpZGVcbiAgICAgKiBkb2N1bWVudC5hY3RpdmVFbGVtZW50LlxuICAgICAqL1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oZXYpIHtcbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmZvcm1TdWJtaXR0ZXIgPSBudWxsO1xuICAgICAgZGlhbG9nUG9seWZpbGwudXNlVmFsdWUgPSBudWxsO1xuICAgICAgaWYgKGV2LmRlZmF1bHRQcmV2ZW50ZWQpIHsgcmV0dXJuOyB9ICAvLyBlLmcuIGEgc3VibWl0IHdoaWNoIHByZXZlbnRzIGRlZmF1bHQgc3VibWlzc2lvblxuXG4gICAgICB2YXIgdGFyZ2V0ID0gLyoqIEB0eXBlIHtFbGVtZW50fSAqLyAoZXYudGFyZ2V0KTtcbiAgICAgIGlmICghdGFyZ2V0IHx8ICFpc0Zvcm1NZXRob2REaWFsb2codGFyZ2V0LmZvcm0pKSB7IHJldHVybjsgfVxuXG4gICAgICB2YXIgdmFsaWQgPSAodGFyZ2V0LnR5cGUgPT09ICdzdWJtaXQnICYmIFsnYnV0dG9uJywgJ2lucHV0J10uaW5kZXhPZih0YXJnZXQubG9jYWxOYW1lKSA+IC0xKTtcbiAgICAgIGlmICghdmFsaWQpIHtcbiAgICAgICAgaWYgKCEodGFyZ2V0LmxvY2FsTmFtZSA9PT0gJ2lucHV0JyAmJiB0YXJnZXQudHlwZSA9PT0gJ2ltYWdlJykpIHsgcmV0dXJuOyB9XG4gICAgICAgIC8vIHRoaXMgaXMgYSA8aW5wdXQgdHlwZT1cImltYWdlXCI+LCB3aGljaCBjYW4gc3VibWl0IGZvcm1zXG4gICAgICAgIGRpYWxvZ1BvbHlmaWxsLnVzZVZhbHVlID0gZXYub2Zmc2V0WCArICcsJyArIGV2Lm9mZnNldFk7XG4gICAgICB9XG5cbiAgICAgIHZhciBkaWFsb2cgPSBmaW5kTmVhcmVzdERpYWxvZyh0YXJnZXQpO1xuICAgICAgaWYgKCFkaWFsb2cpIHsgcmV0dXJuOyB9XG5cbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmZvcm1TdWJtaXR0ZXIgPSB0YXJnZXQ7XG4gICAgfSwgZmFsc2UpO1xuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZSB0aGUgbmF0aXZlIEhUTUxGb3JtRWxlbWVudC5zdWJtaXQoKSBtZXRob2QsIGFzIGl0IHdvbid0IGZpcmUgdGhlXG4gICAgICogc3VibWl0IGV2ZW50IGFuZCBnaXZlIHVzIGEgY2hhbmNlIHRvIHJlc3BvbmQuXG4gICAgICovXG4gICAgdmFyIG5hdGl2ZUZvcm1TdWJtaXQgPSBIVE1MRm9ybUVsZW1lbnQucHJvdG90eXBlLnN1Ym1pdDtcbiAgICB2YXIgcmVwbGFjZW1lbnRGb3JtU3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCFpc0Zvcm1NZXRob2REaWFsb2codGhpcykpIHtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZUZvcm1TdWJtaXQuY2FsbCh0aGlzKTtcbiAgICAgIH1cbiAgICAgIHZhciBkaWFsb2cgPSBmaW5kTmVhcmVzdERpYWxvZyh0aGlzKTtcbiAgICAgIGRpYWxvZyAmJiBkaWFsb2cuY2xvc2UoKTtcbiAgICB9O1xuICAgIEhUTUxGb3JtRWxlbWVudC5wcm90b3R5cGUuc3VibWl0ID0gcmVwbGFjZW1lbnRGb3JtU3VibWl0O1xuXG4gICAgLyoqXG4gICAgICogR2xvYmFsIGZvcm0gJ2RpYWxvZycgbWV0aG9kIGhhbmRsZXIuIENsb3NlcyBhIGRpYWxvZyBjb3JyZWN0bHkgb24gc3VibWl0XG4gICAgICogYW5kIHBvc3NpYmx5IHNldHMgaXRzIHJldHVybiB2YWx1ZS5cbiAgICAgKi9cbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdzdWJtaXQnLCBmdW5jdGlvbihldikge1xuICAgICAgdmFyIGZvcm0gPSAvKiogQHR5cGUge0hUTUxGb3JtRWxlbWVudH0gKi8gKGV2LnRhcmdldCk7XG4gICAgICBpZiAoIWlzRm9ybU1ldGhvZERpYWxvZyhmb3JtKSkgeyByZXR1cm47IH1cbiAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHZhciBkaWFsb2cgPSBmaW5kTmVhcmVzdERpYWxvZyhmb3JtKTtcbiAgICAgIGlmICghZGlhbG9nKSB7IHJldHVybjsgfVxuXG4gICAgICAvLyBGb3JtcyBjYW4gb25seSBiZSBzdWJtaXR0ZWQgdmlhIC5zdWJtaXQoKSBvciBhIGNsaWNrICg/KSwgYnV0IGFueXdheTogc2FuaXR5LWNoZWNrIHRoYXRcbiAgICAgIC8vIHRoZSBzdWJtaXR0ZXIgaXMgY29ycmVjdCBiZWZvcmUgdXNpbmcgaXRzIHZhbHVlIGFzIC5yZXR1cm5WYWx1ZS5cbiAgICAgIHZhciBzID0gZGlhbG9nUG9seWZpbGwuZm9ybVN1Ym1pdHRlcjtcbiAgICAgIGlmIChzICYmIHMuZm9ybSA9PT0gZm9ybSkge1xuICAgICAgICBkaWFsb2cuY2xvc2UoZGlhbG9nUG9seWZpbGwudXNlVmFsdWUgfHwgcy52YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgIH1cbiAgICAgIGRpYWxvZ1BvbHlmaWxsLmZvcm1TdWJtaXR0ZXIgPSBudWxsO1xuICAgIH0sIHRydWUpO1xuICB9XG5cbiAgZGlhbG9nUG9seWZpbGxbJ2ZvcmNlUmVnaXN0ZXJEaWFsb2cnXSA9IGRpYWxvZ1BvbHlmaWxsLmZvcmNlUmVnaXN0ZXJEaWFsb2c7XG4gIGRpYWxvZ1BvbHlmaWxsWydyZWdpc3RlckRpYWxvZyddID0gZGlhbG9nUG9seWZpbGwucmVnaXN0ZXJEaWFsb2c7XG5cbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgJ2FtZCcgaW4gZGVmaW5lKSB7XG4gICAgLy8gQU1EIHN1cHBvcnRcbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7IHJldHVybiBkaWFsb2dQb2x5ZmlsbDsgfSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZVsnZXhwb3J0cyddID09PSAnb2JqZWN0Jykge1xuICAgIC8vIENvbW1vbkpTIHN1cHBvcnRcbiAgICBtb2R1bGVbJ2V4cG9ydHMnXSA9IGRpYWxvZ1BvbHlmaWxsO1xuICB9IGVsc2Uge1xuICAgIC8vIGFsbCBvdGhlcnNcbiAgICB3aW5kb3dbJ2RpYWxvZ1BvbHlmaWxsJ10gPSBkaWFsb2dQb2x5ZmlsbDtcbiAgfVxufSkoKTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///5c00\n")}}]);

There are no issues that match your filters.

Category
Status