14 lines
80 KiB
JavaScript
14 lines
80 KiB
JavaScript
(window["__googlesitekit_webpackJsonp"] = window["__googlesitekit_webpackJsonp"] || []).push([[10],{
|
|
|
|
/***/ "../node_modules/intersection-observer/intersection-observer.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ../node_modules/intersection-observer/intersection-observer.js ***!
|
|
\**********************************************************************/
|
|
/*! no static exports found */
|
|
/***/ (function(module, exports) {
|
|
|
|
eval("/**\n * Copyright 2016 Google Inc. All Rights Reserved.\n *\n * Licensed under the W3C SOFTWARE AND DOCUMENT NOTICE AND LICENSE.\n *\n * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document\n *\n */\n(function() {\n'use strict';\n\n// Exit early if we're not running in a browser.\nif (typeof window !== 'object') {\n return;\n}\n\n// Exit early if all IntersectionObserver and IntersectionObserverEntry\n// features are natively supported.\nif ('IntersectionObserver' in window &&\n 'IntersectionObserverEntry' in window &&\n 'intersectionRatio' in window.IntersectionObserverEntry.prototype) {\n\n // Minimal polyfill for Edge 15's lack of `isIntersecting`\n // See: https://github.com/w3c/IntersectionObserver/issues/211\n if (!('isIntersecting' in window.IntersectionObserverEntry.prototype)) {\n Object.defineProperty(window.IntersectionObserverEntry.prototype,\n 'isIntersecting', {\n get: function () {\n return this.intersectionRatio > 0;\n }\n });\n }\n return;\n}\n\n/**\n * Returns the embedding frame element, if any.\n * @param {!Document} doc\n * @return {!Element}\n */\nfunction getFrameElement(doc) {\n try {\n return doc.defaultView && doc.defaultView.frameElement || null;\n } catch (e) {\n // Ignore the error.\n return null;\n }\n}\n\n/**\n * A local reference to the root document.\n */\nvar document = (function(startDoc) {\n var doc = startDoc;\n var frame = getFrameElement(doc);\n while (frame) {\n doc = frame.ownerDocument;\n frame = getFrameElement(doc);\n }\n return doc;\n})(window.document);\n\n/**\n * An IntersectionObserver registry. This registry exists to hold a strong\n * reference to IntersectionObserver instances currently observing a target\n * element. Without this registry, instances without another reference may be\n * garbage collected.\n */\nvar registry = [];\n\n/**\n * The signal updater for cross-origin intersection. When not null, it means\n * that the polyfill is configured to work in a cross-origin mode.\n * @type {function(DOMRect|ClientRect, DOMRect|ClientRect)}\n */\nvar crossOriginUpdater = null;\n\n/**\n * The current cross-origin intersection. Only used in the cross-origin mode.\n * @type {DOMRect|ClientRect}\n */\nvar crossOriginRect = null;\n\n\n/**\n * Creates the global IntersectionObserverEntry constructor.\n * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry\n * @param {Object} entry A dictionary of instance properties.\n * @constructor\n */\nfunction IntersectionObserverEntry(entry) {\n this.time = entry.time;\n this.target = entry.target;\n this.rootBounds = ensureDOMRect(entry.rootBounds);\n this.boundingClientRect = ensureDOMRect(entry.boundingClientRect);\n this.intersectionRect = ensureDOMRect(entry.intersectionRect || getEmptyRect());\n this.isIntersecting = !!entry.intersectionRect;\n\n // Calculates the intersection ratio.\n var targetRect = this.boundingClientRect;\n var targetArea = targetRect.width * targetRect.height;\n var intersectionRect = this.intersectionRect;\n var intersectionArea = intersectionRect.width * intersectionRect.height;\n\n // Sets intersection ratio.\n if (targetArea) {\n // Round the intersection ratio to avoid floating point math issues:\n // https://github.com/w3c/IntersectionObserver/issues/324\n this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4));\n } else {\n // If area is zero and is intersecting, sets to 1, otherwise to 0\n this.intersectionRatio = this.isIntersecting ? 1 : 0;\n }\n}\n\n\n/**\n * Creates the global IntersectionObserver constructor.\n * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface\n * @param {Function} callback The function to be invoked after intersection\n * changes have queued. The function is not invoked if the queue has\n * been emptied by calling the `takeRecords` method.\n * @param {Object=} opt_options Optional configuration options.\n * @constructor\n */\nfunction IntersectionObserver(callback, opt_options) {\n\n var options = opt_options || {};\n\n if (typeof callback != 'function') {\n throw new Error('callback must be a function');\n }\n\n if (\n options.root &&\n options.root.nodeType != 1 &&\n options.root.nodeType != 9\n ) {\n throw new Error('root must be a Document or Element');\n }\n\n // Binds and throttles `this._checkForIntersections`.\n this._checkForIntersections = throttle(\n this._checkForIntersections.bind(this), this.THROTTLE_TIMEOUT);\n\n // Private properties.\n this._callback = callback;\n this._observationTargets = [];\n this._queuedEntries = [];\n this._rootMarginValues = this._parseRootMargin(options.rootMargin);\n\n // Public properties.\n this.thresholds = this._initThresholds(options.threshold);\n this.root = options.root || null;\n this.rootMargin = this._rootMarginValues.map(function(margin) {\n return margin.value + margin.unit;\n }).join(' ');\n\n /** @private @const {!Array<!Document>} */\n this._monitoringDocuments = [];\n /** @private @const {!Array<function()>} */\n this._monitoringUnsubscribes = [];\n}\n\n\n/**\n * The minimum interval within which the document will be checked for\n * intersection changes.\n */\nIntersectionObserver.prototype.THROTTLE_TIMEOUT = 100;\n\n\n/**\n * The frequency in which the polyfill polls for intersection changes.\n * this can be updated on a per instance basis and must be set prior to\n * calling `observe` on the first target.\n */\nIntersectionObserver.prototype.POLL_INTERVAL = null;\n\n/**\n * Use a mutation observer on the root element\n * to detect intersection changes.\n */\nIntersectionObserver.prototype.USE_MUTATION_OBSERVER = true;\n\n\n/**\n * Sets up the polyfill in the cross-origin mode. The result is the\n * updater function that accepts two arguments: `boundingClientRect` and\n * `intersectionRect` - just as these fields would be available to the\n * parent via `IntersectionObserverEntry`. This function should be called\n * each time the iframe receives intersection information from the parent\n * window, e.g. via messaging.\n * @return {function(DOMRect|ClientRect, DOMRect|ClientRect)}\n */\nIntersectionObserver._setupCrossOriginUpdater = function() {\n if (!crossOriginUpdater) {\n /**\n * @param {DOMRect|ClientRect} boundingClientRect\n * @param {DOMRect|ClientRect} intersectionRect\n */\n crossOriginUpdater = function(boundingClientRect, intersectionRect) {\n if (!boundingClientRect || !intersectionRect) {\n crossOriginRect = getEmptyRect();\n } else {\n crossOriginRect = convertFromParentRect(boundingClientRect, intersectionRect);\n }\n registry.forEach(function(observer) {\n observer._checkForIntersections();\n });\n };\n }\n return crossOriginUpdater;\n};\n\n\n/**\n * Resets the cross-origin mode.\n */\nIntersectionObserver._resetCrossOriginUpdater = function() {\n crossOriginUpdater = null;\n crossOriginRect = null;\n};\n\n\n/**\n * Starts observing a target element for intersection changes based on\n * the thresholds values.\n * @param {Element} target The DOM element to observe.\n */\nIntersectionObserver.prototype.observe = function(target) {\n var isTargetAlreadyObserved = this._observationTargets.some(function(item) {\n return item.element == target;\n });\n\n if (isTargetAlreadyObserved) {\n return;\n }\n\n if (!(target && target.nodeType == 1)) {\n throw new Error('target must be an Element');\n }\n\n this._registerInstance();\n this._observationTargets.push({element: target, entry: null});\n this._monitorIntersections(target.ownerDocument);\n this._checkForIntersections();\n};\n\n\n/**\n * Stops observing a target element for intersection changes.\n * @param {Element} target The DOM element to observe.\n */\nIntersectionObserver.prototype.unobserve = function(target) {\n this._observationTargets =\n this._observationTargets.filter(function(item) {\n return item.element != target;\n });\n this._unmonitorIntersections(target.ownerDocument);\n if (this._observationTargets.length == 0) {\n this._unregisterInstance();\n }\n};\n\n\n/**\n * Stops observing all target elements for intersection changes.\n */\nIntersectionObserver.prototype.disconnect = function() {\n this._observationTargets = [];\n this._unmonitorAllIntersections();\n this._unregisterInstance();\n};\n\n\n/**\n * Returns any queue entries that have not yet been reported to the\n * callback and clears the queue. This can be used in conjunction with the\n * callback to obtain the absolute most up-to-date intersection information.\n * @return {Array} The currently queued entries.\n */\nIntersectionObserver.prototype.takeRecords = function() {\n var records = this._queuedEntries.slice();\n this._queuedEntries = [];\n return records;\n};\n\n\n/**\n * Accepts the threshold value from the user configuration object and\n * returns a sorted array of unique threshold values. If a value is not\n * between 0 and 1 and error is thrown.\n * @private\n * @param {Array|number=} opt_threshold An optional threshold value or\n * a list of threshold values, defaulting to [0].\n * @return {Array} A sorted list of unique and valid threshold values.\n */\nIntersectionObserver.prototype._initThresholds = function(opt_threshold) {\n var threshold = opt_threshold || [0];\n if (!Array.isArray(threshold)) threshold = [threshold];\n\n return threshold.sort().filter(function(t, i, a) {\n if (typeof t != 'number' || isNaN(t) || t < 0 || t > 1) {\n throw new Error('threshold must be a number between 0 and 1 inclusively');\n }\n return t !== a[i - 1];\n });\n};\n\n\n/**\n * Accepts the rootMargin value from the user configuration object\n * and returns an array of the four margin values as an object containing\n * the value and unit properties. If any of the values are not properly\n * formatted or use a unit other than px or %, and error is thrown.\n * @private\n * @param {string=} opt_rootMargin An optional rootMargin value,\n * defaulting to '0px'.\n * @return {Array<Object>} An array of margin objects with the keys\n * value and unit.\n */\nIntersectionObserver.prototype._parseRootMargin = function(opt_rootMargin) {\n var marginString = opt_rootMargin || '0px';\n var margins = marginString.split(/\\s+/).map(function(margin) {\n var parts = /^(-?\\d*\\.?\\d+)(px|%)$/.exec(margin);\n if (!parts) {\n throw new Error('rootMargin must be specified in pixels or percent');\n }\n return {value: parseFloat(parts[1]), unit: parts[2]};\n });\n\n // Handles shorthand.\n margins[1] = margins[1] || margins[0];\n margins[2] = margins[2] || margins[0];\n margins[3] = margins[3] || margins[1];\n\n return margins;\n};\n\n\n/**\n * Starts polling for intersection changes if the polling is not already\n * happening, and if the page's visibility state is visible.\n * @param {!Document} doc\n * @private\n */\nIntersectionObserver.prototype._monitorIntersections = function(doc) {\n var win = doc.defaultView;\n if (!win) {\n // Already destroyed.\n return;\n }\n if (this._monitoringDocuments.indexOf(doc) != -1) {\n // Already monitoring.\n return;\n }\n\n // Private state for monitoring.\n var callback = this._checkForIntersections;\n var monitoringInterval = null;\n var domObserver = null;\n\n // If a poll interval is set, use polling instead of listening to\n // resize and scroll events or DOM mutations.\n if (this.POLL_INTERVAL) {\n monitoringInterval = win.setInterval(callback, this.POLL_INTERVAL);\n } else {\n addEvent(win, 'resize', callback, true);\n addEvent(doc, 'scroll', callback, true);\n if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in win) {\n domObserver = new win.MutationObserver(callback);\n domObserver.observe(doc, {\n attributes: true,\n childList: true,\n characterData: true,\n subtree: true\n });\n }\n }\n\n this._monitoringDocuments.push(doc);\n this._monitoringUnsubscribes.push(function() {\n // Get the window object again. When a friendly iframe is destroyed, it\n // will be null.\n var win = doc.defaultView;\n\n if (win) {\n if (monitoringInterval) {\n win.clearInterval(monitoringInterval);\n }\n removeEvent(win, 'resize', callback, true);\n }\n\n removeEvent(doc, 'scroll', callback, true);\n if (domObserver) {\n domObserver.disconnect();\n }\n });\n\n // Also monitor the parent.\n var rootDoc =\n (this.root && (this.root.ownerDocument || this.root)) || document;\n if (doc != rootDoc) {\n var frame = getFrameElement(doc);\n if (frame) {\n this._monitorIntersections(frame.ownerDocument);\n }\n }\n};\n\n\n/**\n * Stops polling for intersection changes.\n * @param {!Document} doc\n * @private\n */\nIntersectionObserver.prototype._unmonitorIntersections = function(doc) {\n var index = this._monitoringDocuments.indexOf(doc);\n if (index == -1) {\n return;\n }\n\n var rootDoc =\n (this.root && (this.root.ownerDocument || this.root)) || document;\n\n // Check if any dependent targets are still remaining.\n var hasDependentTargets =\n this._observationTargets.some(function(item) {\n var itemDoc = item.element.ownerDocument;\n // Target is in this context.\n if (itemDoc == doc) {\n return true;\n }\n // Target is nested in this context.\n while (itemDoc && itemDoc != rootDoc) {\n var frame = getFrameElement(itemDoc);\n itemDoc = frame && frame.ownerDocument;\n if (itemDoc == doc) {\n return true;\n }\n }\n return false;\n });\n if (hasDependentTargets) {\n return;\n }\n\n // Unsubscribe.\n var unsubscribe = this._monitoringUnsubscribes[index];\n this._monitoringDocuments.splice(index, 1);\n this._monitoringUnsubscribes.splice(index, 1);\n unsubscribe();\n\n // Also unmonitor the parent.\n if (doc != rootDoc) {\n var frame = getFrameElement(doc);\n if (frame) {\n this._unmonitorIntersections(frame.ownerDocument);\n }\n }\n};\n\n\n/**\n * Stops polling for intersection changes.\n * @param {!Document} doc\n * @private\n */\nIntersectionObserver.prototype._unmonitorAllIntersections = function() {\n var unsubscribes = this._monitoringUnsubscribes.slice(0);\n this._monitoringDocuments.length = 0;\n this._monitoringUnsubscribes.length = 0;\n for (var i = 0; i < unsubscribes.length; i++) {\n unsubscribes[i]();\n }\n};\n\n\n/**\n * Scans each observation target for intersection changes and adds them\n * to the internal entries queue. If new entries are found, it\n * schedules the callback to be invoked.\n * @private\n */\nIntersectionObserver.prototype._checkForIntersections = function() {\n if (!this.root && crossOriginUpdater && !crossOriginRect) {\n // Cross origin monitoring, but no initial data available yet.\n return;\n }\n\n var rootIsInDom = this._rootIsInDom();\n var rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect();\n\n this._observationTargets.forEach(function(item) {\n var target = item.element;\n var targetRect = getBoundingClientRect(target);\n var rootContainsTarget = this._rootContainsTarget(target);\n var oldEntry = item.entry;\n var intersectionRect = rootIsInDom && rootContainsTarget &&\n this._computeTargetAndRootIntersection(target, targetRect, rootRect);\n\n var rootBounds = null;\n if (!this._rootContainsTarget(target)) {\n rootBounds = getEmptyRect();\n } else if (!crossOriginUpdater || this.root) {\n rootBounds = rootRect;\n }\n\n var newEntry = item.entry = new IntersectionObserverEntry({\n time: now(),\n target: target,\n boundingClientRect: targetRect,\n rootBounds: rootBounds,\n intersectionRect: intersectionRect\n });\n\n if (!oldEntry) {\n this._queuedEntries.push(newEntry);\n } else if (rootIsInDom && rootContainsTarget) {\n // If the new entry intersection ratio has crossed any of the\n // thresholds, add a new entry.\n if (this._hasCrossedThreshold(oldEntry, newEntry)) {\n this._queuedEntries.push(newEntry);\n }\n } else {\n // If the root is not in the DOM or target is not contained within\n // root but the previous entry for this target had an intersection,\n // add a new record indicating removal.\n if (oldEntry && oldEntry.isIntersecting) {\n this._queuedEntries.push(newEntry);\n }\n }\n }, this);\n\n if (this._queuedEntries.length) {\n this._callback(this.takeRecords(), this);\n }\n};\n\n\n/**\n * Accepts a target and root rect computes the intersection between then\n * following the algorithm in the spec.\n * TODO(philipwalton): at this time clip-path is not considered.\n * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo\n * @param {Element} target The target DOM element\n * @param {Object} targetRect The bounding rect of the target.\n * @param {Object} rootRect The bounding rect of the root after being\n * expanded by the rootMargin value.\n * @return {?Object} The final intersection rect object or undefined if no\n * intersection is found.\n * @private\n */\nIntersectionObserver.prototype._computeTargetAndRootIntersection =\n function(target, targetRect, rootRect) {\n // If the element isn't displayed, an intersection can't happen.\n if (window.getComputedStyle(target).display == 'none') return;\n\n var intersectionRect = targetRect;\n var parent = getParentNode(target);\n var atRoot = false;\n\n while (!atRoot && parent) {\n var parentRect = null;\n var parentComputedStyle = parent.nodeType == 1 ?\n window.getComputedStyle(parent) : {};\n\n // If the parent isn't displayed, an intersection can't happen.\n if (parentComputedStyle.display == 'none') return null;\n\n if (parent == this.root || parent.nodeType == /* DOCUMENT */ 9) {\n atRoot = true;\n if (parent == this.root || parent == document) {\n if (crossOriginUpdater && !this.root) {\n if (!crossOriginRect ||\n crossOriginRect.width == 0 && crossOriginRect.height == 0) {\n // A 0-size cross-origin intersection means no-intersection.\n parent = null;\n parentRect = null;\n intersectionRect = null;\n } else {\n parentRect = crossOriginRect;\n }\n } else {\n parentRect = rootRect;\n }\n } else {\n // Check if there's a frame that can be navigated to.\n var frame = getParentNode(parent);\n var frameRect = frame && getBoundingClientRect(frame);\n var frameIntersect =\n frame &&\n this._computeTargetAndRootIntersection(frame, frameRect, rootRect);\n if (frameRect && frameIntersect) {\n parent = frame;\n parentRect = convertFromParentRect(frameRect, frameIntersect);\n } else {\n parent = null;\n intersectionRect = null;\n }\n }\n } else {\n // If the element has a non-visible overflow, and it's not the <body>\n // or <html> element, update the intersection rect.\n // Note: <body> and <html> cannot be clipped to a rect that's not also\n // the document rect, so no need to compute a new intersection.\n var doc = parent.ownerDocument;\n if (parent != doc.body &&\n parent != doc.documentElement &&\n parentComputedStyle.overflow != 'visible') {\n parentRect = getBoundingClientRect(parent);\n }\n }\n\n // If either of the above conditionals set a new parentRect,\n // calculate new intersection data.\n if (parentRect) {\n intersectionRect = computeRectIntersection(parentRect, intersectionRect);\n }\n if (!intersectionRect) break;\n parent = parent && getParentNode(parent);\n }\n return intersectionRect;\n};\n\n\n/**\n * Returns the root rect after being expanded by the rootMargin value.\n * @return {ClientRect} The expanded root rect.\n * @private\n */\nIntersectionObserver.prototype._getRootRect = function() {\n var rootRect;\n if (this.root && !isDoc(this.root)) {\n rootRect = getBoundingClientRect(this.root);\n } else {\n // Use <html>/<body> instead of window since scroll bars affect size.\n var doc = isDoc(this.root) ? this.root : document;\n var html = doc.documentElement;\n var body = doc.body;\n rootRect = {\n top: 0,\n left: 0,\n right: html.clientWidth || body.clientWidth,\n width: html.clientWidth || body.clientWidth,\n bottom: html.clientHeight || body.clientHeight,\n height: html.clientHeight || body.clientHeight\n };\n }\n return this._expandRectByRootMargin(rootRect);\n};\n\n\n/**\n * Accepts a rect and expands it by the rootMargin value.\n * @param {DOMRect|ClientRect} rect The rect object to expand.\n * @return {ClientRect} The expanded rect.\n * @private\n */\nIntersectionObserver.prototype._expandRectByRootMargin = function(rect) {\n var margins = this._rootMarginValues.map(function(margin, i) {\n return margin.unit == 'px' ? margin.value :\n margin.value * (i % 2 ? rect.width : rect.height) / 100;\n });\n var newRect = {\n top: rect.top - margins[0],\n right: rect.right + margins[1],\n bottom: rect.bottom + margins[2],\n left: rect.left - margins[3]\n };\n newRect.width = newRect.right - newRect.left;\n newRect.height = newRect.bottom - newRect.top;\n\n return newRect;\n};\n\n\n/**\n * Accepts an old and new entry and returns true if at least one of the\n * threshold values has been crossed.\n * @param {?IntersectionObserverEntry} oldEntry The previous entry for a\n * particular target element or null if no previous entry exists.\n * @param {IntersectionObserverEntry} newEntry The current entry for a\n * particular target element.\n * @return {boolean} Returns true if a any threshold has been crossed.\n * @private\n */\nIntersectionObserver.prototype._hasCrossedThreshold =\n function(oldEntry, newEntry) {\n\n // To make comparing easier, an entry that has a ratio of 0\n // but does not actually intersect is given a value of -1\n var oldRatio = oldEntry && oldEntry.isIntersecting ?\n oldEntry.intersectionRatio || 0 : -1;\n var newRatio = newEntry.isIntersecting ?\n newEntry.intersectionRatio || 0 : -1;\n\n // Ignore unchanged ratios\n if (oldRatio === newRatio) return;\n\n for (var i = 0; i < this.thresholds.length; i++) {\n var threshold = this.thresholds[i];\n\n // Return true if an entry matches a threshold or if the new ratio\n // and the old ratio are on the opposite sides of a threshold.\n if (threshold == oldRatio || threshold == newRatio ||\n threshold < oldRatio !== threshold < newRatio) {\n return true;\n }\n }\n};\n\n\n/**\n * Returns whether or not the root element is an element and is in the DOM.\n * @return {boolean} True if the root element is an element and is in the DOM.\n * @private\n */\nIntersectionObserver.prototype._rootIsInDom = function() {\n return !this.root || containsDeep(document, this.root);\n};\n\n\n/**\n * Returns whether or not the target element is a child of root.\n * @param {Element} target The target element to check.\n * @return {boolean} True if the target element is a child of root.\n * @private\n */\nIntersectionObserver.prototype._rootContainsTarget = function(target) {\n var rootDoc =\n (this.root && (this.root.ownerDocument || this.root)) || document;\n return (\n containsDeep(rootDoc, target) &&\n (!this.root || rootDoc == target.ownerDocument)\n );\n};\n\n\n/**\n * Adds the instance to the global IntersectionObserver registry if it isn't\n * already present.\n * @private\n */\nIntersectionObserver.prototype._registerInstance = function() {\n if (registry.indexOf(this) < 0) {\n registry.push(this);\n }\n};\n\n\n/**\n * Removes the instance from the global IntersectionObserver registry.\n * @private\n */\nIntersectionObserver.prototype._unregisterInstance = function() {\n var index = registry.indexOf(this);\n if (index != -1) registry.splice(index, 1);\n};\n\n\n/**\n * Returns the result of the performance.now() method or null in browsers\n * that don't support the API.\n * @return {number} The elapsed time since the page was requested.\n */\nfunction now() {\n return window.performance && performance.now && performance.now();\n}\n\n\n/**\n * Throttles a function and delays its execution, so it's only called at most\n * once within a given time period.\n * @param {Function} fn The function to throttle.\n * @param {number} timeout The amount of time that must pass before the\n * function can be called again.\n * @return {Function} The throttled function.\n */\nfunction throttle(fn, timeout) {\n var timer = null;\n return function () {\n if (!timer) {\n timer = setTimeout(function() {\n fn();\n timer = null;\n }, timeout);\n }\n };\n}\n\n\n/**\n * Adds an event handler to a DOM node ensuring cross-browser compatibility.\n * @param {Node} node The DOM node to add the event handler to.\n * @param {string} event The event name.\n * @param {Function} fn The event handler to add.\n * @param {boolean} opt_useCapture Optionally adds the even to the capture\n * phase. Note: this only works in modern browsers.\n */\nfunction addEvent(node, event, fn, opt_useCapture) {\n if (typeof node.addEventListener == 'function') {\n node.addEventListener(event, fn, opt_useCapture || false);\n }\n else if (typeof node.attachEvent == 'function') {\n node.attachEvent('on' + event, fn);\n }\n}\n\n\n/**\n * Removes a previously added event handler from a DOM node.\n * @param {Node} node The DOM node to remove the event handler from.\n * @param {string} event The event name.\n * @param {Function} fn The event handler to remove.\n * @param {boolean} opt_useCapture If the event handler was added with this\n * flag set to true, it should be set to true here in order to remove it.\n */\nfunction removeEvent(node, event, fn, opt_useCapture) {\n if (typeof node.removeEventListener == 'function') {\n node.removeEventListener(event, fn, opt_useCapture || false);\n }\n else if (typeof node.detatchEvent == 'function') {\n node.detatchEvent('on' + event, fn);\n }\n}\n\n\n/**\n * Returns the intersection between two rect objects.\n * @param {Object} rect1 The first rect.\n * @param {Object} rect2 The second rect.\n * @return {?Object|?ClientRect} The intersection rect or undefined if no\n * intersection is found.\n */\nfunction computeRectIntersection(rect1, rect2) {\n var top = Math.max(rect1.top, rect2.top);\n var bottom = Math.min(rect1.bottom, rect2.bottom);\n var left = Math.max(rect1.left, rect2.left);\n var right = Math.min(rect1.right, rect2.right);\n var width = right - left;\n var height = bottom - top;\n\n return (width >= 0 && height >= 0) && {\n top: top,\n bottom: bottom,\n left: left,\n right: right,\n width: width,\n height: height\n } || null;\n}\n\n\n/**\n * Shims the native getBoundingClientRect for compatibility with older IE.\n * @param {Element} el The element whose bounding rect to get.\n * @return {DOMRect|ClientRect} The (possibly shimmed) rect of the element.\n */\nfunction getBoundingClientRect(el) {\n var rect;\n\n try {\n rect = el.getBoundingClientRect();\n } catch (err) {\n // Ignore Windows 7 IE11 \"Unspecified error\"\n // https://github.com/w3c/IntersectionObserver/pull/205\n }\n\n if (!rect) return getEmptyRect();\n\n // Older IE\n if (!(rect.width && rect.height)) {\n rect = {\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n width: rect.right - rect.left,\n height: rect.bottom - rect.top\n };\n }\n return rect;\n}\n\n\n/**\n * Returns an empty rect object. An empty rect is returned when an element\n * is not in the DOM.\n * @return {ClientRect} The empty rect.\n */\nfunction getEmptyRect() {\n return {\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n width: 0,\n height: 0\n };\n}\n\n\n/**\n * Ensure that the result has all of the necessary fields of the DOMRect.\n * Specifically this ensures that `x` and `y` fields are set.\n *\n * @param {?DOMRect|?ClientRect} rect\n * @return {?DOMRect}\n */\nfunction ensureDOMRect(rect) {\n // A `DOMRect` object has `x` and `y` fields.\n if (!rect || 'x' in rect) {\n return rect;\n }\n // A IE's `ClientRect` type does not have `x` and `y`. The same is the case\n // for internally calculated Rect objects. For the purposes of\n // `IntersectionObserver`, it's sufficient to simply mirror `left` and `top`\n // for these fields.\n return {\n top: rect.top,\n y: rect.top,\n bottom: rect.bottom,\n left: rect.left,\n x: rect.left,\n right: rect.right,\n width: rect.width,\n height: rect.height\n };\n}\n\n\n/**\n * Inverts the intersection and bounding rect from the parent (frame) BCR to\n * the local BCR space.\n * @param {DOMRect|ClientRect} parentBoundingRect The parent's bound client rect.\n * @param {DOMRect|ClientRect} parentIntersectionRect The parent's own intersection rect.\n * @return {ClientRect} The local root bounding rect for the parent's children.\n */\nfunction convertFromParentRect(parentBoundingRect, parentIntersectionRect) {\n var top = parentIntersectionRect.top - parentBoundingRect.top;\n var left = parentIntersectionRect.left - parentBoundingRect.left;\n return {\n top: top,\n left: left,\n height: parentIntersectionRect.height,\n width: parentIntersectionRect.width,\n bottom: top + parentIntersectionRect.height,\n right: left + parentIntersectionRect.width\n };\n}\n\n\n/**\n * Checks to see if a parent element contains a child element (including inside\n * shadow DOM).\n * @param {Node} parent The parent element.\n * @param {Node} child The child element.\n * @return {boolean} True if the parent node contains the child node.\n */\nfunction containsDeep(parent, child) {\n var node = child;\n while (node) {\n if (node == parent) return true;\n\n node = getParentNode(node);\n }\n return false;\n}\n\n\n/**\n * Gets the parent node of an element or its host element if the parent node\n * is a shadow root.\n * @param {Node} node The node whose parent to get.\n * @return {Node|null} The parent node or null if no parent exists.\n */\nfunction getParentNode(node) {\n var parent = node.parentNode;\n\n if (node.nodeType == /* DOCUMENT */ 9 && node != document) {\n // If this node is a document node, look for the embedding frame.\n return getFrameElement(node);\n }\n\n // If the parent has element that is assigned through shadow root slot\n if (parent && parent.assignedSlot) {\n parent = parent.assignedSlot.parentNode\n }\n\n if (parent && parent.nodeType == 11 && parent.host) {\n // If the parent is a shadow root, return the host element.\n return parent.host;\n }\n\n return parent;\n}\n\n/**\n * Returns true if `node` is a Document.\n * @param {!Node} node\n * @returns {boolean}\n */\nfunction isDoc(node) {\n return node && node.nodeType === 9;\n}\n\n\n// Exposes the constructors globally.\nwindow.IntersectionObserver = IntersectionObserver;\nwindow.IntersectionObserverEntry = IntersectionObserverEntry;\n\n}());\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi4vbm9kZV9tb2R1bGVzL2ludGVyc2VjdGlvbi1vYnNlcnZlci9pbnRlcnNlY3Rpb24tb2JzZXJ2ZXIuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi4vbm9kZV9tb2R1bGVzL2ludGVyc2VjdGlvbi1vYnNlcnZlci9pbnRlcnNlY3Rpb24tb2JzZXJ2ZXIuanM/ZWI2OCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAyMDE2IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIFczQyBTT0ZUV0FSRSBBTkQgRE9DVU1FTlQgTk9USUNFIEFORCBMSUNFTlNFLlxuICpcbiAqICBodHRwczovL3d3dy53My5vcmcvQ29uc29ydGl1bS9MZWdhbC8yMDE1L2NvcHlyaWdodC1zb2Z0d2FyZS1hbmQtZG9jdW1lbnRcbiAqXG4gKi9cbihmdW5jdGlvbigpIHtcbid1c2Ugc3RyaWN0JztcblxuLy8gRXhpdCBlYXJseSBpZiB3ZSdyZSBub3QgcnVubmluZyBpbiBhIGJyb3dzZXIuXG5pZiAodHlwZW9mIHdpbmRvdyAhPT0gJ29iamVjdCcpIHtcbiAgcmV0dXJuO1xufVxuXG4vLyBFeGl0IGVhcmx5IGlmIGFsbCBJbnRlcnNlY3Rpb25PYnNlcnZlciBhbmQgSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeVxuLy8gZmVhdHVyZXMgYXJlIG5hdGl2ZWx5IHN1cHBvcnRlZC5cbmlmICgnSW50ZXJzZWN0aW9uT2JzZXJ2ZXInIGluIHdpbmRvdyAmJlxuICAgICdJbnRlcnNlY3Rpb25PYnNlcnZlckVudHJ5JyBpbiB3aW5kb3cgJiZcbiAgICAnaW50ZXJzZWN0aW9uUmF0aW8nIGluIHdpbmRvdy5JbnRlcnNlY3Rpb25PYnNlcnZlckVudHJ5LnByb3RvdHlwZSkge1xuXG4gIC8vIE1pbmltYWwgcG9seWZpbGwgZm9yIEVkZ2UgMTUncyBsYWNrIG9mIGBpc0ludGVyc2VjdGluZ2BcbiAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vdzNjL0ludGVyc2VjdGlvbk9ic2VydmVyL2lzc3Vlcy8yMTFcbiAgaWYgKCEoJ2lzSW50ZXJzZWN0aW5nJyBpbiB3aW5kb3cuSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeS5wcm90b3R5cGUpKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdy5JbnRlcnNlY3Rpb25PYnNlcnZlckVudHJ5LnByb3RvdHlwZSxcbiAgICAgICdpc0ludGVyc2VjdGluZycsIHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pbnRlcnNlY3Rpb25SYXRpbyA+IDA7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGVtYmVkZGluZyBmcmFtZSBlbGVtZW50LCBpZiBhbnkuXG4gKiBAcGFyYW0geyFEb2N1bWVudH0gZG9jXG4gKiBAcmV0dXJuIHshRWxlbWVudH1cbiAqL1xuZnVuY3Rpb24gZ2V0RnJhbWVFbGVtZW50KGRvYykge1xuICB0cnkge1xuICAgIHJldHVybiBkb2MuZGVmYXVsdFZpZXcgJiYgZG9jLmRlZmF1bHRWaWV3LmZyYW1lRWxlbWVudCB8fCBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gSWdub3JlIHRoZSBlcnJvci5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vKipcbiAqIEEgbG9jYWwgcmVmZXJlbmNlIHRvIHRoZSByb290IGRvY3VtZW50LlxuICovXG52YXIgZG9jdW1lbnQgPSAoZnVuY3Rpb24oc3RhcnREb2MpIHtcbiAgdmFyIGRvYyA9IHN0YXJ0RG9jO1xuICB2YXIgZnJhbWUgPSBnZXRGcmFtZUVsZW1lbnQoZG9jKTtcbiAgd2hpbGUgKGZyYW1lKSB7XG4gICAgZG9jID0gZnJhbWUub3duZXJEb2N1bWVudDtcbiAgICBmcmFtZSA9IGdldEZyYW1lRWxlbWVudChkb2MpO1xuICB9XG4gIHJldHVybiBkb2M7XG59KSh3aW5kb3cuZG9jdW1lbnQpO1xuXG4vKipcbiAqIEFuIEludGVyc2VjdGlvbk9ic2VydmVyIHJlZ2lzdHJ5LiBUaGlzIHJlZ2lzdHJ5IGV4aXN0cyB0byBob2xkIGEgc3Ryb25nXG4gKiByZWZlcmVuY2UgdG8gSW50ZXJzZWN0aW9uT2JzZXJ2ZXIgaW5zdGFuY2VzIGN1cnJlbnRseSBvYnNlcnZpbmcgYSB0YXJnZXRcbiAqIGVsZW1lbnQuIFdpdGhvdXQgdGhpcyByZWdpc3RyeSwgaW5zdGFuY2VzIHdpdGhvdXQgYW5vdGhlciByZWZlcmVuY2UgbWF5IGJlXG4gKiBnYXJiYWdlIGNvbGxlY3RlZC5cbiAqL1xudmFyIHJlZ2lzdHJ5ID0gW107XG5cbi8qKlxuICogVGhlIHNpZ25hbCB1cGRhdGVyIGZvciBjcm9zcy1vcmlnaW4gaW50ZXJzZWN0aW9uLiBXaGVuIG5vdCBudWxsLCBpdCBtZWFuc1xuICogdGhhdCB0aGUgcG9seWZpbGwgaXMgY29uZmlndXJlZCB0byB3b3JrIGluIGEgY3Jvc3Mtb3JpZ2luIG1vZGUuXG4gKiBAdHlwZSB7ZnVuY3Rpb24oRE9NUmVjdHxDbGllbnRSZWN0LCBET01SZWN0fENsaWVudFJlY3QpfVxuICovXG52YXIgY3Jvc3NPcmlnaW5VcGRhdGVyID0gbnVsbDtcblxuLyoqXG4gKiBUaGUgY3VycmVudCBjcm9zcy1vcmlnaW4gaW50ZXJzZWN0aW9uLiBPbmx5IHVzZWQgaW4gdGhlIGNyb3NzLW9yaWdpbiBtb2RlLlxuICogQHR5cGUge0RPTVJlY3R8Q2xpZW50UmVjdH1cbiAqL1xudmFyIGNyb3NzT3JpZ2luUmVjdCA9IG51bGw7XG5cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBnbG9iYWwgSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeSBjb25zdHJ1Y3Rvci5cbiAqIGh0dHBzOi8vdzNjLmdpdGh1Yi5pby9JbnRlcnNlY3Rpb25PYnNlcnZlci8jaW50ZXJzZWN0aW9uLW9ic2VydmVyLWVudHJ5XG4gKiBAcGFyYW0ge09iamVjdH0gZW50cnkgQSBkaWN0aW9uYXJ5IG9mIGluc3RhbmNlIHByb3BlcnRpZXMuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeShlbnRyeSkge1xuICB0aGlzLnRpbWUgPSBlbnRyeS50aW1lO1xuICB0aGlzLnRhcmdldCA9IGVudHJ5LnRhcmdldDtcbiAgdGhpcy5yb290Qm91bmRzID0gZW5zdXJlRE9NUmVjdChlbnRyeS5yb290Qm91bmRzKTtcbiAgdGhpcy5ib3VuZGluZ0NsaWVudFJlY3QgPSBlbnN1cmVET01SZWN0KGVudHJ5LmJvdW5kaW5nQ2xpZW50UmVjdCk7XG4gIHRoaXMuaW50ZXJzZWN0aW9uUmVjdCA9IGVuc3VyZURPTVJlY3QoZW50cnkuaW50ZXJzZWN0aW9uUmVjdCB8fCBnZXRFbXB0eVJlY3QoKSk7XG4gIHRoaXMuaXNJbnRlcnNlY3RpbmcgPSAhIWVudHJ5LmludGVyc2VjdGlvblJlY3Q7XG5cbiAgLy8gQ2FsY3VsYXRlcyB0aGUgaW50ZXJzZWN0aW9uIHJhdGlvLlxuICB2YXIgdGFyZ2V0UmVjdCA9IHRoaXMuYm91bmRpbmdDbGllbnRSZWN0O1xuICB2YXIgdGFyZ2V0QXJlYSA9IHRhcmdldFJlY3Qud2lkdGggKiB0YXJnZXRSZWN0LmhlaWdodDtcbiAgdmFyIGludGVyc2VjdGlvblJlY3QgPSB0aGlzLmludGVyc2VjdGlvblJlY3Q7XG4gIHZhciBpbnRlcnNlY3Rpb25BcmVhID0gaW50ZXJzZWN0aW9uUmVjdC53aWR0aCAqIGludGVyc2VjdGlvblJlY3QuaGVpZ2h0O1xuXG4gIC8vIFNldHMgaW50ZXJzZWN0aW9uIHJhdGlvLlxuICBpZiAodGFyZ2V0QXJlYSkge1xuICAgIC8vIFJvdW5kIHRoZSBpbnRlcnNlY3Rpb24gcmF0aW8gdG8gYXZvaWQgZmxvYXRpbmcgcG9pbnQgbWF0aCBpc3N1ZXM6XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3czYy9JbnRlcnNlY3Rpb25PYnNlcnZlci9pc3N1ZXMvMzI0XG4gICAgdGhpcy5pbnRlcnNlY3Rpb25SYXRpbyA9IE51bWJlcigoaW50ZXJzZWN0aW9uQXJlYSAvIHRhcmdldEFyZWEpLnRvRml4ZWQoNCkpO1xuICB9IGVsc2Uge1xuICAgIC8vIElmIGFyZWEgaXMgemVybyBhbmQgaXMgaW50ZXJzZWN0aW5nLCBzZXRzIHRvIDEsIG90aGVyd2lzZSB0byAwXG4gICAgdGhpcy5pbnRlcnNlY3Rpb25SYXRpbyA9IHRoaXMuaXNJbnRlcnNlY3RpbmcgPyAxIDogMDtcbiAgfVxufVxuXG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgZ2xvYmFsIEludGVyc2VjdGlvbk9ic2VydmVyIGNvbnN0cnVjdG9yLlxuICogaHR0cHM6Ly93M2MuZ2l0aHViLmlvL0ludGVyc2VjdGlvbk9ic2VydmVyLyNpbnRlcnNlY3Rpb24tb2JzZXJ2ZXItaW50ZXJmYWNlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gYmUgaW52b2tlZCBhZnRlciBpbnRlcnNlY3Rpb25cbiAqICAgICBjaGFuZ2VzIGhhdmUgcXVldWVkLiBUaGUgZnVuY3Rpb24gaXMgbm90IGludm9rZWQgaWYgdGhlIHF1ZXVlIGhhc1xuICogICAgIGJlZW4gZW1wdGllZCBieSBjYWxsaW5nIHRoZSBgdGFrZVJlY29yZHNgIG1ldGhvZC5cbiAqIEBwYXJhbSB7T2JqZWN0PX0gb3B0X29wdGlvbnMgT3B0aW9uYWwgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmZ1bmN0aW9uIEludGVyc2VjdGlvbk9ic2VydmVyKGNhbGxiYWNrLCBvcHRfb3B0aW9ucykge1xuXG4gIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgfHwge307XG5cbiAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgfVxuXG4gIGlmIChcbiAgICBvcHRpb25zLnJvb3QgJiZcbiAgICBvcHRpb25zLnJvb3Qubm9kZVR5cGUgIT0gMSAmJlxuICAgIG9wdGlvbnMucm9vdC5ub2RlVHlwZSAhPSA5XG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcigncm9vdCBtdXN0IGJlIGEgRG9jdW1lbnQgb3IgRWxlbWVudCcpO1xuICB9XG5cbiAgLy8gQmluZHMgYW5kIHRocm90dGxlcyBgdGhpcy5fY2hlY2tGb3JJbnRlcnNlY3Rpb25zYC5cbiAgdGhpcy5fY2hlY2tGb3JJbnRlcnNlY3Rpb25zID0gdGhyb3R0bGUoXG4gICAgICB0aGlzLl9jaGVja0ZvckludGVyc2VjdGlvbnMuYmluZCh0aGlzKSwgdGhpcy5USFJPVFRMRV9USU1FT1VUKTtcblxuICAvLyBQcml2YXRlIHByb3BlcnRpZXMuXG4gIHRoaXMuX2NhbGxiYWNrID0gY2FsbGJhY2s7XG4gIHRoaXMuX29ic2VydmF0aW9uVGFyZ2V0cyA9IFtdO1xuICB0aGlzLl9xdWV1ZWRFbnRyaWVzID0gW107XG4gIHRoaXMuX3Jvb3RNYXJnaW5WYWx1ZXMgPSB0aGlzLl9wYXJzZVJvb3RNYXJnaW4ob3B0aW9ucy5yb290TWFyZ2luKTtcblxuICAvLyBQdWJsaWMgcHJvcGVydGllcy5cbiAgdGhpcy50aHJlc2hvbGRzID0gdGhpcy5faW5pdFRocmVzaG9sZHMob3B0aW9ucy50aHJlc2hvbGQpO1xuICB0aGlzLnJvb3QgPSBvcHRpb25zLnJvb3QgfHwgbnVsbDtcbiAgdGhpcy5yb290TWFyZ2luID0gdGhpcy5fcm9vdE1hcmdpblZhbHVlcy5tYXAoZnVuY3Rpb24obWFyZ2luKSB7XG4gICAgcmV0dXJuIG1hcmdpbi52YWx1ZSArIG1hcmdpbi51bml0O1xuICB9KS5qb2luKCcgJyk7XG5cbiAgLyoqIEBwcml2YXRlIEBjb25zdCB7IUFycmF5PCFEb2N1bWVudD59ICovXG4gIHRoaXMuX21vbml0b3JpbmdEb2N1bWVudHMgPSBbXTtcbiAgLyoqIEBwcml2YXRlIEBjb25zdCB7IUFycmF5PGZ1bmN0aW9uKCk+fSAqL1xuICB0aGlzLl9tb25pdG9yaW5nVW5zdWJzY3JpYmVzID0gW107XG59XG5cblxuLyoqXG4gKiBUaGUgbWluaW11bSBpbnRlcnZhbCB3aXRoaW4gd2hpY2ggdGhlIGRvY3VtZW50IHdpbGwgYmUgY2hlY2tlZCBmb3JcbiAqIGludGVyc2VjdGlvbiBjaGFuZ2VzLlxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuVEhST1RUTEVfVElNRU9VVCA9IDEwMDtcblxuXG4vKipcbiAqIFRoZSBmcmVxdWVuY3kgaW4gd2hpY2ggdGhlIHBvbHlmaWxsIHBvbGxzIGZvciBpbnRlcnNlY3Rpb24gY2hhbmdlcy5cbiAqIHRoaXMgY2FuIGJlIHVwZGF0ZWQgb24gYSBwZXIgaW5zdGFuY2UgYmFzaXMgYW5kIG11c3QgYmUgc2V0IHByaW9yIHRvXG4gKiBjYWxsaW5nIGBvYnNlcnZlYCBvbiB0aGUgZmlyc3QgdGFyZ2V0LlxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuUE9MTF9JTlRFUlZBTCA9IG51bGw7XG5cbi8qKlxuICogVXNlIGEgbXV0YXRpb24gb2JzZXJ2ZXIgb24gdGhlIHJvb3QgZWxlbWVudFxuICogdG8gZGV0ZWN0IGludGVyc2VjdGlvbiBjaGFuZ2VzLlxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuVVNFX01VVEFUSU9OX09CU0VSVkVSID0gdHJ1ZTtcblxuXG4vKipcbiAqIFNldHMgdXAgdGhlIHBvbHlmaWxsIGluIHRoZSBjcm9zcy1vcmlnaW4gbW9kZS4gVGhlIHJlc3VsdCBpcyB0aGVcbiAqIHVwZGF0ZXIgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHR3byBhcmd1bWVudHM6IGBib3VuZGluZ0NsaWVudFJlY3RgIGFuZFxuICogYGludGVyc2VjdGlvblJlY3RgIC0ganVzdCBhcyB0aGVzZSBmaWVsZHMgd291bGQgYmUgYXZhaWxhYmxlIHRvIHRoZVxuICogcGFyZW50IHZpYSBgSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeWAuIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGNhbGxlZFxuICogZWFjaCB0aW1lIHRoZSBpZnJhbWUgcmVjZWl2ZXMgaW50ZXJzZWN0aW9uIGluZm9ybWF0aW9uIGZyb20gdGhlIHBhcmVudFxuICogd2luZG93LCBlLmcuIHZpYSBtZXNzYWdpbmcuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbihET01SZWN0fENsaWVudFJlY3QsIERPTVJlY3R8Q2xpZW50UmVjdCl9XG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLl9zZXR1cENyb3NzT3JpZ2luVXBkYXRlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIWNyb3NzT3JpZ2luVXBkYXRlcikge1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7RE9NUmVjdHxDbGllbnRSZWN0fSBib3VuZGluZ0NsaWVudFJlY3RcbiAgICAgKiBAcGFyYW0ge0RPTVJlY3R8Q2xpZW50UmVjdH0gaW50ZXJzZWN0aW9uUmVjdFxuICAgICAqL1xuICAgIGNyb3NzT3JpZ2luVXBkYXRlciA9IGZ1bmN0aW9uKGJvdW5kaW5nQ2xpZW50UmVjdCwgaW50ZXJzZWN0aW9uUmVjdCkge1xuICAgICAgaWYgKCFib3VuZGluZ0NsaWVudFJlY3QgfHwgIWludGVyc2VjdGlvblJlY3QpIHtcbiAgICAgICAgY3Jvc3NPcmlnaW5SZWN0ID0gZ2V0RW1wdHlSZWN0KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcm9zc09yaWdpblJlY3QgPSBjb252ZXJ0RnJvbVBhcmVudFJlY3QoYm91bmRpbmdDbGllbnRSZWN0LCBpbnRlcnNlY3Rpb25SZWN0KTtcbiAgICAgIH1cbiAgICAgIHJlZ2lzdHJ5LmZvckVhY2goZnVuY3Rpb24ob2JzZXJ2ZXIpIHtcbiAgICAgICAgb2JzZXJ2ZXIuX2NoZWNrRm9ySW50ZXJzZWN0aW9ucygpO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuICByZXR1cm4gY3Jvc3NPcmlnaW5VcGRhdGVyO1xufTtcblxuXG4vKipcbiAqIFJlc2V0cyB0aGUgY3Jvc3Mtb3JpZ2luIG1vZGUuXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLl9yZXNldENyb3NzT3JpZ2luVXBkYXRlciA9IGZ1bmN0aW9uKCkge1xuICBjcm9zc09yaWdpblVwZGF0ZXIgPSBudWxsO1xuICBjcm9zc09yaWdpblJlY3QgPSBudWxsO1xufTtcblxuXG4vKipcbiAqIFN0YXJ0cyBvYnNlcnZpbmcgYSB0YXJnZXQgZWxlbWVudCBmb3IgaW50ZXJzZWN0aW9uIGNoYW5nZXMgYmFzZWQgb25cbiAqIHRoZSB0aHJlc2hvbGRzIHZhbHVlcy5cbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0IFRoZSBET00gZWxlbWVudCB0byBvYnNlcnZlLlxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uKHRhcmdldCkge1xuICB2YXIgaXNUYXJnZXRBbHJlYWR5T2JzZXJ2ZWQgPSB0aGlzLl9vYnNlcnZhdGlvblRhcmdldHMuc29tZShmdW5jdGlvbihpdGVtKSB7XG4gICAgcmV0dXJuIGl0ZW0uZWxlbWVudCA9PSB0YXJnZXQ7XG4gIH0pO1xuXG4gIGlmIChpc1RhcmdldEFscmVhZHlPYnNlcnZlZCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghKHRhcmdldCAmJiB0YXJnZXQubm9kZVR5cGUgPT0gMSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldCBtdXN0IGJlIGFuIEVsZW1lbnQnKTtcbiAgfVxuXG4gIHRoaXMuX3JlZ2lzdGVySW5zdGFuY2UoKTtcbiAgdGhpcy5fb2JzZXJ2YXRpb25UYXJnZXRzLnB1c2goe2VsZW1lbnQ6IHRhcmdldCwgZW50cnk6IG51bGx9KTtcbiAgdGhpcy5fbW9uaXRvckludGVyc2VjdGlvbnModGFyZ2V0Lm93bmVyRG9jdW1lbnQpO1xuICB0aGlzLl9jaGVja0ZvckludGVyc2VjdGlvbnMoKTtcbn07XG5cblxuLyoqXG4gKiBTdG9wcyBvYnNlcnZpbmcgYSB0YXJnZXQgZWxlbWVudCBmb3IgaW50ZXJzZWN0aW9uIGNoYW5nZXMuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldCBUaGUgRE9NIGVsZW1lbnQgdG8gb2JzZXJ2ZS5cbiAqL1xuSW50ZXJzZWN0aW9uT2JzZXJ2ZXIucHJvdG90eXBlLnVub2JzZXJ2ZSA9IGZ1bmN0aW9uKHRhcmdldCkge1xuICB0aGlzLl9vYnNlcnZhdGlvblRhcmdldHMgPVxuICAgICAgdGhpcy5fb2JzZXJ2YXRpb25UYXJnZXRzLmZpbHRlcihmdW5jdGlvbihpdGVtKSB7XG4gICAgICAgIHJldHVybiBpdGVtLmVsZW1lbnQgIT0gdGFyZ2V0O1xuICAgICAgfSk7XG4gIHRoaXMuX3VubW9uaXRvckludGVyc2VjdGlvbnModGFyZ2V0Lm93bmVyRG9jdW1lbnQpO1xuICBpZiAodGhpcy5fb2JzZXJ2YXRpb25UYXJnZXRzLmxlbmd0aCA9PSAwKSB7XG4gICAgdGhpcy5fdW5yZWdpc3Rlckluc3RhbmNlKCk7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBTdG9wcyBvYnNlcnZpbmcgYWxsIHRhcmdldCBlbGVtZW50cyBmb3IgaW50ZXJzZWN0aW9uIGNoYW5nZXMuXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLnByb3RvdHlwZS5kaXNjb25uZWN0ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuX29ic2VydmF0aW9uVGFyZ2V0cyA9IFtdO1xuICB0aGlzLl91bm1vbml0b3JBbGxJbnRlcnNlY3Rpb25zKCk7XG4gIHRoaXMuX3VucmVnaXN0ZXJJbnN0YW5jZSgpO1xufTtcblxuXG4vKipcbiAqIFJldHVybnMgYW55IHF1ZXVlIGVudHJpZXMgdGhhdCBoYXZlIG5vdCB5ZXQgYmVlbiByZXBvcnRlZCB0byB0aGVcbiAqIGNhbGxiYWNrIGFuZCBjbGVhcnMgdGhlIHF1ZXVlLiBUaGlzIGNhbiBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlXG4gKiBjYWxsYmFjayB0byBvYnRhaW4gdGhlIGFic29sdXRlIG1vc3QgdXAtdG8tZGF0ZSBpbnRlcnNlY3Rpb24gaW5mb3JtYXRpb24uXG4gKiBAcmV0dXJuIHtBcnJheX0gVGhlIGN1cnJlbnRseSBxdWV1ZWQgZW50cmllcy5cbiAqL1xuSW50ZXJzZWN0aW9uT2JzZXJ2ZXIucHJvdG90eXBlLnRha2VSZWNvcmRzID0gZnVuY3Rpb24oKSB7XG4gIHZhciByZWNvcmRzID0gdGhpcy5fcXVldWVkRW50cmllcy5zbGljZSgpO1xuICB0aGlzLl9xdWV1ZWRFbnRyaWVzID0gW107XG4gIHJldHVybiByZWNvcmRzO1xufTtcblxuXG4vKipcbiAqIEFjY2VwdHMgdGhlIHRocmVzaG9sZCB2YWx1ZSBmcm9tIHRoZSB1c2VyIGNvbmZpZ3VyYXRpb24gb2JqZWN0IGFuZFxuICogcmV0dXJucyBhIHNvcnRlZCBhcnJheSBvZiB1bmlxdWUgdGhyZXNob2xkIHZhbHVlcy4gSWYgYSB2YWx1ZSBpcyBub3RcbiAqIGJldHdlZW4gMCBhbmQgMSBhbmQgZXJyb3IgaXMgdGhyb3duLlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl8bnVtYmVyPX0gb3B0X3RocmVzaG9sZCBBbiBvcHRpb25hbCB0aHJlc2hvbGQgdmFsdWUgb3JcbiAqICAgICBhIGxpc3Qgb2YgdGhyZXNob2xkIHZhbHVlcywgZGVmYXVsdGluZyB0byBbMF0uXG4gKiBAcmV0dXJuIHtBcnJheX0gQSBzb3J0ZWQgbGlzdCBvZiB1bmlxdWUgYW5kIHZhbGlkIHRocmVzaG9sZCB2YWx1ZXMuXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLnByb3RvdHlwZS5faW5pdFRocmVzaG9sZHMgPSBmdW5jdGlvbihvcHRfdGhyZXNob2xkKSB7XG4gIHZhciB0aHJlc2hvbGQgPSBvcHRfdGhyZXNob2xkIHx8IFswXTtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHRocmVzaG9sZCkpIHRocmVzaG9sZCA9IFt0aHJlc2hvbGRdO1xuXG4gIHJldHVybiB0aHJlc2hvbGQuc29ydCgpLmZpbHRlcihmdW5jdGlvbih0LCBpLCBhKSB7XG4gICAgaWYgKHR5cGVvZiB0ICE9ICdudW1iZXInIHx8IGlzTmFOKHQpIHx8IHQgPCAwIHx8IHQgPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RocmVzaG9sZCBtdXN0IGJlIGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgMSBpbmNsdXNpdmVseScpO1xuICAgIH1cbiAgICByZXR1cm4gdCAhPT0gYVtpIC0gMV07XG4gIH0pO1xufTtcblxuXG4vKipcbiAqIEFjY2VwdHMgdGhlIHJvb3RNYXJnaW4gdmFsdWUgZnJvbSB0aGUgdXNlciBjb25maWd1cmF0aW9uIG9iamVjdFxuICogYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgdGhlIGZvdXIgbWFyZ2luIHZhbHVlcyBhcyBhbiBvYmplY3QgY29udGFpbmluZ1xuICogdGhlIHZhbHVlIGFuZCB1bml0IHByb3BlcnRpZXMuIElmIGFueSBvZiB0aGUgdmFsdWVzIGFyZSBub3QgcHJvcGVybHlcbiAqIGZvcm1hdHRlZCBvciB1c2UgYSB1bml0IG90aGVyIHRoYW4gcHggb3IgJSwgYW5kIGVycm9yIGlzIHRocm93bi5cbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9yb290TWFyZ2luIEFuIG9wdGlvbmFsIHJvb3RNYXJnaW4gdmFsdWUsXG4gKiAgICAgZGVmYXVsdGluZyB0byAnMHB4Jy5cbiAqIEByZXR1cm4ge0FycmF5PE9iamVjdD59IEFuIGFycmF5IG9mIG1hcmdpbiBvYmplY3RzIHdpdGggdGhlIGtleXNcbiAqICAgICB2YWx1ZSBhbmQgdW5pdC5cbiAqL1xuSW50ZXJzZWN0aW9uT2JzZXJ2ZXIucHJvdG90eXBlLl9wYXJzZVJvb3RNYXJnaW4gPSBmdW5jdGlvbihvcHRfcm9vdE1hcmdpbikge1xuICB2YXIgbWFyZ2luU3RyaW5nID0gb3B0X3Jvb3RNYXJnaW4gfHwgJzBweCc7XG4gIHZhciBtYXJnaW5zID0gbWFyZ2luU3RyaW5nLnNwbGl0KC9cXHMrLykubWFwKGZ1bmN0aW9uKG1hcmdpbikge1xuICAgIHZhciBwYXJ0cyA9IC9eKC0/XFxkKlxcLj9cXGQrKShweHwlKSQvLmV4ZWMobWFyZ2luKTtcbiAgICBpZiAoIXBhcnRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Jvb3RNYXJnaW4gbXVzdCBiZSBzcGVjaWZpZWQgaW4gcGl4ZWxzIG9yIHBlcmNlbnQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHt2YWx1ZTogcGFyc2VGbG9hdChwYXJ0c1sxXSksIHVuaXQ6IHBhcnRzWzJdfTtcbiAgfSk7XG5cbiAgLy8gSGFuZGxlcyBzaG9ydGhhbmQuXG4gIG1hcmdpbnNbMV0gPSBtYXJnaW5zWzFdIHx8IG1hcmdpbnNbMF07XG4gIG1hcmdpbnNbMl0gPSBtYXJnaW5zWzJdIHx8IG1hcmdpbnNbMF07XG4gIG1hcmdpbnNbM10gPSBtYXJnaW5zWzNdIHx8IG1hcmdpbnNbMV07XG5cbiAgcmV0dXJuIG1hcmdpbnM7XG59O1xuXG5cbi8qKlxuICogU3RhcnRzIHBvbGxpbmcgZm9yIGludGVyc2VjdGlvbiBjaGFuZ2VzIGlmIHRoZSBwb2xsaW5nIGlzIG5vdCBhbHJlYWR5XG4gKiBoYXBwZW5pbmcsIGFuZCBpZiB0aGUgcGFnZSdzIHZpc2liaWxpdHkgc3RhdGUgaXMgdmlzaWJsZS5cbiAqIEBwYXJhbSB7IURvY3VtZW50fSBkb2NcbiAqIEBwcml2YXRlXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLnByb3RvdHlwZS5fbW9uaXRvckludGVyc2VjdGlvbnMgPSBmdW5jdGlvbihkb2MpIHtcbiAgdmFyIHdpbiA9IGRvYy5kZWZhdWx0VmlldztcbiAgaWYgKCF3aW4pIHtcbiAgICAvLyBBbHJlYWR5IGRlc3Ryb3llZC5cbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHRoaXMuX21vbml0b3JpbmdEb2N1bWVudHMuaW5kZXhPZihkb2MpICE9IC0xKSB7XG4gICAgLy8gQWxyZWFkeSBtb25pdG9yaW5nLlxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIFByaXZhdGUgc3RhdGUgZm9yIG1vbml0b3JpbmcuXG4gIHZhciBjYWxsYmFjayA9IHRoaXMuX2NoZWNrRm9ySW50ZXJzZWN0aW9ucztcbiAgdmFyIG1vbml0b3JpbmdJbnRlcnZhbCA9IG51bGw7XG4gIHZhciBkb21PYnNlcnZlciA9IG51bGw7XG5cbiAgLy8gSWYgYSBwb2xsIGludGVydmFsIGlzIHNldCwgdXNlIHBvbGxpbmcgaW5zdGVhZCBvZiBsaXN0ZW5pbmcgdG9cbiAgLy8gcmVzaXplIGFuZCBzY3JvbGwgZXZlbnRzIG9yIERPTSBtdXRhdGlvbnMuXG4gIGlmICh0aGlzLlBPTExfSU5URVJWQUwpIHtcbiAgICBtb25pdG9yaW5nSW50ZXJ2YWwgPSB3aW4uc2V0SW50ZXJ2YWwoY2FsbGJhY2ssIHRoaXMuUE9MTF9JTlRFUlZBTCk7XG4gIH0gZWxzZSB7XG4gICAgYWRkRXZlbnQod2luLCAncmVzaXplJywgY2FsbGJhY2ssIHRydWUpO1xuICAgIGFkZEV2ZW50KGRvYywgJ3Njcm9sbCcsIGNhbGxiYWNrLCB0cnVlKTtcbiAgICBpZiAodGhpcy5VU0VfTVVUQVRJT05fT0JTRVJWRVIgJiYgJ011dGF0aW9uT2JzZXJ2ZXInIGluIHdpbikge1xuICAgICAgZG9tT2JzZXJ2ZXIgPSBuZXcgd2luLk11dGF0aW9uT2JzZXJ2ZXIoY2FsbGJhY2spO1xuICAgICAgZG9tT2JzZXJ2ZXIub2JzZXJ2ZShkb2MsIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiB0cnVlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICB0aGlzLl9tb25pdG9yaW5nRG9jdW1lbnRzLnB1c2goZG9jKTtcbiAgdGhpcy5fbW9uaXRvcmluZ1Vuc3Vic2NyaWJlcy5wdXNoKGZ1bmN0aW9uKCkge1xuICAgIC8vIEdldCB0aGUgd2luZG93IG9iamVjdCBhZ2Fpbi4gV2hlbiBhIGZyaWVuZGx5IGlmcmFtZSBpcyBkZXN0cm95ZWQsIGl0XG4gICAgLy8gd2lsbCBiZSBudWxsLlxuICAgIHZhciB3aW4gPSBkb2MuZGVmYXVsdFZpZXc7XG5cbiAgICBpZiAod2luKSB7XG4gICAgICBpZiAobW9uaXRvcmluZ0ludGVydmFsKSB7XG4gICAgICAgIHdpbi5jbGVhckludGVydmFsKG1vbml0b3JpbmdJbnRlcnZhbCk7XG4gICAgICB9XG4gICAgICByZW1vdmVFdmVudCh3aW4sICdyZXNpemUnLCBjYWxsYmFjaywgdHJ1ZSk7XG4gICAgfVxuXG4gICAgcmVtb3ZlRXZlbnQoZG9jLCAnc2Nyb2xsJywgY2FsbGJhY2ssIHRydWUpO1xuICAgIGlmIChkb21PYnNlcnZlcikge1xuICAgICAgZG9tT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gQWxzbyBtb25pdG9yIHRoZSBwYXJlbnQuXG4gIHZhciByb290RG9jID1cbiAgICAodGhpcy5yb290ICYmICh0aGlzLnJvb3Qub3duZXJEb2N1bWVudCB8fCB0aGlzLnJvb3QpKSB8fCBkb2N1bWVudDtcbiAgaWYgKGRvYyAhPSByb290RG9jKSB7XG4gICAgdmFyIGZyYW1lID0gZ2V0RnJhbWVFbGVtZW50KGRvYyk7XG4gICAgaWYgKGZyYW1lKSB7XG4gICAgICB0aGlzLl9tb25pdG9ySW50ZXJzZWN0aW9ucyhmcmFtZS5vd25lckRvY3VtZW50KTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyoqXG4gKiBTdG9wcyBwb2xsaW5nIGZvciBpbnRlcnNlY3Rpb24gY2hhbmdlcy5cbiAqIEBwYXJhbSB7IURvY3VtZW50fSBkb2NcbiAqIEBwcml2YXRlXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLnByb3RvdHlwZS5fdW5tb25pdG9ySW50ZXJzZWN0aW9ucyA9IGZ1bmN0aW9uKGRvYykge1xuICB2YXIgaW5kZXggPSB0aGlzLl9tb25pdG9yaW5nRG9jdW1lbnRzLmluZGV4T2YoZG9jKTtcbiAgaWYgKGluZGV4ID09IC0xKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHJvb3REb2MgPVxuICAgICh0aGlzLnJvb3QgJiYgKHRoaXMucm9vdC5vd25lckRvY3VtZW50IHx8IHRoaXMucm9vdCkpIHx8IGRvY3VtZW50O1xuXG4gIC8vIENoZWNrIGlmIGFueSBkZXBlbmRlbnQgdGFyZ2V0cyBhcmUgc3RpbGwgcmVtYWluaW5nLlxuICB2YXIgaGFzRGVwZW5kZW50VGFyZ2V0cyA9XG4gICAgICB0aGlzLl9vYnNlcnZhdGlvblRhcmdldHMuc29tZShmdW5jdGlvbihpdGVtKSB7XG4gICAgICAgIHZhciBpdGVtRG9jID0gaXRlbS5lbGVtZW50Lm93bmVyRG9jdW1lbnQ7XG4gICAgICAgIC8vIFRhcmdldCBpcyBpbiB0aGlzIGNvbnRleHQuXG4gICAgICAgIGlmIChpdGVtRG9jID09IGRvYykge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRhcmdldCBpcyBuZXN0ZWQgaW4gdGhpcyBjb250ZXh0LlxuICAgICAgICB3aGlsZSAoaXRlbURvYyAmJiBpdGVtRG9jICE9IHJvb3REb2MpIHtcbiAgICAgICAgICB2YXIgZnJhbWUgPSBnZXRGcmFtZUVsZW1lbnQoaXRlbURvYyk7XG4gICAgICAgICAgaXRlbURvYyA9IGZyYW1lICYmIGZyYW1lLm93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgaWYgKGl0ZW1Eb2MgPT0gZG9jKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG4gIGlmIChoYXNEZXBlbmRlbnRUYXJnZXRzKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gVW5zdWJzY3JpYmUuXG4gIHZhciB1bnN1YnNjcmliZSA9IHRoaXMuX21vbml0b3JpbmdVbnN1YnNjcmliZXNbaW5kZXhdO1xuICB0aGlzLl9tb25pdG9yaW5nRG9jdW1lbnRzLnNwbGljZShpbmRleCwgMSk7XG4gIHRoaXMuX21vbml0b3JpbmdVbnN1YnNjcmliZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgdW5zdWJzY3JpYmUoKTtcblxuICAvLyBBbHNvIHVubW9uaXRvciB0aGUgcGFyZW50LlxuICBpZiAoZG9jICE9IHJvb3REb2MpIHtcbiAgICB2YXIgZnJhbWUgPSBnZXRGcmFtZUVsZW1lbnQoZG9jKTtcbiAgICBpZiAoZnJhbWUpIHtcbiAgICAgIHRoaXMuX3VubW9uaXRvckludGVyc2VjdGlvbnMoZnJhbWUub3duZXJEb2N1bWVudCk7XG4gICAgfVxuICB9XG59O1xuXG5cbi8qKlxuICogU3RvcHMgcG9sbGluZyBmb3IgaW50ZXJzZWN0aW9uIGNoYW5nZXMuXG4gKiBAcGFyYW0geyFEb2N1bWVudH0gZG9jXG4gKiBAcHJpdmF0ZVxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuX3VubW9uaXRvckFsbEludGVyc2VjdGlvbnMgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHVuc3Vic2NyaWJlcyA9IHRoaXMuX21vbml0b3JpbmdVbnN1YnNjcmliZXMuc2xpY2UoMCk7XG4gIHRoaXMuX21vbml0b3JpbmdEb2N1bWVudHMubGVuZ3RoID0gMDtcbiAgdGhpcy5fbW9uaXRvcmluZ1Vuc3Vic2NyaWJlcy5sZW5ndGggPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHVuc3Vic2NyaWJlcy5sZW5ndGg7IGkrKykge1xuICAgIHVuc3Vic2NyaWJlc1tpXSgpO1xuICB9XG59O1xuXG5cbi8qKlxuICogU2NhbnMgZWFjaCBvYnNlcnZhdGlvbiB0YXJnZXQgZm9yIGludGVyc2VjdGlvbiBjaGFuZ2VzIGFuZCBhZGRzIHRoZW1cbiAqIHRvIHRoZSBpbnRlcm5hbCBlbnRyaWVzIHF1ZXVlLiBJZiBuZXcgZW50cmllcyBhcmUgZm91bmQsIGl0XG4gKiBzY2hlZHVsZXMgdGhlIGNhbGxiYWNrIHRvIGJlIGludm9rZWQuXG4gKiBAcHJpdmF0ZVxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuX2NoZWNrRm9ySW50ZXJzZWN0aW9ucyA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIXRoaXMucm9vdCAmJiBjcm9zc09yaWdpblVwZGF0ZXIgJiYgIWNyb3NzT3JpZ2luUmVjdCkge1xuICAgIC8vIENyb3NzIG9yaWdpbiBtb25pdG9yaW5nLCBidXQgbm8gaW5pdGlhbCBkYXRhIGF2YWlsYWJsZSB5ZXQuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHJvb3RJc0luRG9tID0gdGhpcy5fcm9vdElzSW5Eb20oKTtcbiAgdmFyIHJvb3RSZWN0ID0gcm9vdElzSW5Eb20gPyB0aGlzLl9nZXRSb290UmVjdCgpIDogZ2V0RW1wdHlSZWN0KCk7XG5cbiAgdGhpcy5fb2JzZXJ2YXRpb25UYXJnZXRzLmZvckVhY2goZnVuY3Rpb24oaXRlbSkge1xuICAgIHZhciB0YXJnZXQgPSBpdGVtLmVsZW1lbnQ7XG4gICAgdmFyIHRhcmdldFJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QodGFyZ2V0KTtcbiAgICB2YXIgcm9vdENvbnRhaW5zVGFyZ2V0ID0gdGhpcy5fcm9vdENvbnRhaW5zVGFyZ2V0KHRhcmdldCk7XG4gICAgdmFyIG9sZEVudHJ5ID0gaXRlbS5lbnRyeTtcbiAgICB2YXIgaW50ZXJzZWN0aW9uUmVjdCA9IHJvb3RJc0luRG9tICYmIHJvb3RDb250YWluc1RhcmdldCAmJlxuICAgICAgICB0aGlzLl9jb21wdXRlVGFyZ2V0QW5kUm9vdEludGVyc2VjdGlvbih0YXJnZXQsIHRhcmdldFJlY3QsIHJvb3RSZWN0KTtcblxuICAgIHZhciByb290Qm91bmRzID0gbnVsbDtcbiAgICBpZiAoIXRoaXMuX3Jvb3RDb250YWluc1RhcmdldCh0YXJnZXQpKSB7XG4gICAgICByb290Qm91bmRzID0gZ2V0RW1wdHlSZWN0KCk7XG4gICAgfSBlbHNlIGlmICghY3Jvc3NPcmlnaW5VcGRhdGVyIHx8IHRoaXMucm9vdCkge1xuICAgICAgcm9vdEJvdW5kcyA9IHJvb3RSZWN0O1xuICAgIH1cblxuICAgIHZhciBuZXdFbnRyeSA9IGl0ZW0uZW50cnkgPSBuZXcgSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeSh7XG4gICAgICB0aW1lOiBub3coKSxcbiAgICAgIHRhcmdldDogdGFyZ2V0LFxuICAgICAgYm91bmRpbmdDbGllbnRSZWN0OiB0YXJnZXRSZWN0LFxuICAgICAgcm9vdEJvdW5kczogcm9vdEJvdW5kcyxcbiAgICAgIGludGVyc2VjdGlvblJlY3Q6IGludGVyc2VjdGlvblJlY3RcbiAgICB9KTtcblxuICAgIGlmICghb2xkRW50cnkpIHtcbiAgICAgIHRoaXMuX3F1ZXVlZEVudHJpZXMucHVzaChuZXdFbnRyeSk7XG4gICAgfSBlbHNlIGlmIChyb290SXNJbkRvbSAmJiByb290Q29udGFpbnNUYXJnZXQpIHtcbiAgICAgIC8vIElmIHRoZSBuZXcgZW50cnkgaW50ZXJzZWN0aW9uIHJhdGlvIGhhcyBjcm9zc2VkIGFueSBvZiB0aGVcbiAgICAgIC8vIHRocmVzaG9sZHMsIGFkZCBhIG5ldyBlbnRyeS5cbiAgICAgIGlmICh0aGlzLl9oYXNDcm9zc2VkVGhyZXNob2xkKG9sZEVudHJ5LCBuZXdFbnRyeSkpIHtcbiAgICAgICAgdGhpcy5fcXVldWVkRW50cmllcy5wdXNoKG5ld0VudHJ5KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgdGhlIHJvb3QgaXMgbm90IGluIHRoZSBET00gb3IgdGFyZ2V0IGlzIG5vdCBjb250YWluZWQgd2l0aGluXG4gICAgICAvLyByb290IGJ1dCB0aGUgcHJldmlvdXMgZW50cnkgZm9yIHRoaXMgdGFyZ2V0IGhhZCBhbiBpbnRlcnNlY3Rpb24sXG4gICAgICAvLyBhZGQgYSBuZXcgcmVjb3JkIGluZGljYXRpbmcgcmVtb3ZhbC5cbiAgICAgIGlmIChvbGRFbnRyeSAmJiBvbGRFbnRyeS5pc0ludGVyc2VjdGluZykge1xuICAgICAgICB0aGlzLl9xdWV1ZWRFbnRyaWVzLnB1c2gobmV3RW50cnkpO1xuICAgICAgfVxuICAgIH1cbiAgfSwgdGhpcyk7XG5cbiAgaWYgKHRoaXMuX3F1ZXVlZEVudHJpZXMubGVuZ3RoKSB7XG4gICAgdGhpcy5fY2FsbGJhY2sodGhpcy50YWtlUmVjb3JkcygpLCB0aGlzKTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEFjY2VwdHMgYSB0YXJnZXQgYW5kIHJvb3QgcmVjdCBjb21wdXRlcyB0aGUgaW50ZXJzZWN0aW9uIGJldHdlZW4gdGhlblxuICogZm9sbG93aW5nIHRoZSBhbGdvcml0aG0gaW4gdGhlIHNwZWMuXG4gKiBUT0RPKHBoaWxpcHdhbHRvbik6IGF0IHRoaXMgdGltZSBjbGlwLXBhdGggaXMgbm90IGNvbnNpZGVyZWQuXG4gKiBodHRwczovL3czYy5naXRodWIuaW8vSW50ZXJzZWN0aW9uT2JzZXJ2ZXIvI2NhbGN1bGF0ZS1pbnRlcnNlY3Rpb24tcmVjdC1hbGdvXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldCBUaGUgdGFyZ2V0IERPTSBlbGVtZW50XG4gKiBAcGFyYW0ge09iamVjdH0gdGFyZ2V0UmVjdCBUaGUgYm91bmRpbmcgcmVjdCBvZiB0aGUgdGFyZ2V0LlxuICogQHBhcmFtIHtPYmplY3R9IHJvb3RSZWN0IFRoZSBib3VuZGluZyByZWN0IG9mIHRoZSByb290IGFmdGVyIGJlaW5nXG4gKiAgICAgZXhwYW5kZWQgYnkgdGhlIHJvb3RNYXJnaW4gdmFsdWUuXG4gKiBAcmV0dXJuIHs/T2JqZWN0fSBUaGUgZmluYWwgaW50ZXJzZWN0aW9uIHJlY3Qgb2JqZWN0IG9yIHVuZGVmaW5lZCBpZiBub1xuICogICAgIGludGVyc2VjdGlvbiBpcyBmb3VuZC5cbiAqIEBwcml2YXRlXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLnByb3RvdHlwZS5fY29tcHV0ZVRhcmdldEFuZFJvb3RJbnRlcnNlY3Rpb24gPVxuICAgIGZ1bmN0aW9uKHRhcmdldCwgdGFyZ2V0UmVjdCwgcm9vdFJlY3QpIHtcbiAgLy8gSWYgdGhlIGVsZW1lbnQgaXNuJ3QgZGlzcGxheWVkLCBhbiBpbnRlcnNlY3Rpb24gY2FuJ3QgaGFwcGVuLlxuICBpZiAod2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KS5kaXNwbGF5ID09ICdub25lJykgcmV0dXJuO1xuXG4gIHZhciBpbnRlcnNlY3Rpb25SZWN0ID0gdGFyZ2V0UmVjdDtcbiAgdmFyIHBhcmVudCA9IGdldFBhcmVudE5vZGUodGFyZ2V0KTtcbiAgdmFyIGF0Um9vdCA9IGZhbHNlO1xuXG4gIHdoaWxlICghYXRSb290ICYmIHBhcmVudCkge1xuICAgIHZhciBwYXJlbnRSZWN0ID0gbnVsbDtcbiAgICB2YXIgcGFyZW50Q29tcHV0ZWRTdHlsZSA9IHBhcmVudC5ub2RlVHlwZSA9PSAxID9cbiAgICAgICAgd2luZG93LmdldENvbXB1dGVkU3R5bGUocGFyZW50KSA6IHt9O1xuXG4gICAgLy8gSWYgdGhlIHBhcmVudCBpc24ndCBkaXNwbGF5ZWQsIGFuIGludGVyc2VjdGlvbiBjYW4ndCBoYXBwZW4uXG4gICAgaWYgKHBhcmVudENvbXB1dGVkU3R5bGUuZGlzcGxheSA9PSAnbm9uZScpIHJldHVybiBudWxsO1xuXG4gICAgaWYgKHBhcmVudCA9PSB0aGlzLnJvb3QgfHwgcGFyZW50Lm5vZGVUeXBlID09IC8qIERPQ1VNRU5UICovIDkpIHtcbiAgICAgIGF0Um9vdCA9IHRydWU7XG4gICAgICBpZiAocGFyZW50ID09IHRoaXMucm9vdCB8fCBwYXJlbnQgPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgaWYgKGNyb3NzT3JpZ2luVXBkYXRlciAmJiAhdGhpcy5yb290KSB7XG4gICAgICAgICAgaWYgKCFjcm9zc09yaWdpblJlY3QgfHxcbiAgICAgICAgICAgICAgY3Jvc3NPcmlnaW5SZWN0LndpZHRoID09IDAgJiYgY3Jvc3NPcmlnaW5SZWN0LmhlaWdodCA9PSAwKSB7XG4gICAgICAgICAgICAvLyBBIDAtc2l6ZSBjcm9zcy1vcmlnaW4gaW50ZXJzZWN0aW9uIG1lYW5zIG5vLWludGVyc2VjdGlvbi5cbiAgICAgICAgICAgIHBhcmVudCA9IG51bGw7XG4gICAgICAgICAgICBwYXJlbnRSZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIGludGVyc2VjdGlvblJlY3QgPSBudWxsO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXJlbnRSZWN0ID0gY3Jvc3NPcmlnaW5SZWN0O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXJlbnRSZWN0ID0gcm9vdFJlY3Q7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoZXJlJ3MgYSBmcmFtZSB0aGF0IGNhbiBiZSBuYXZpZ2F0ZWQgdG8uXG4gICAgICAgIHZhciBmcmFtZSA9IGdldFBhcmVudE5vZGUocGFyZW50KTtcbiAgICAgICAgdmFyIGZyYW1lUmVjdCA9IGZyYW1lICYmIGdldEJvdW5kaW5nQ2xpZW50UmVjdChmcmFtZSk7XG4gICAgICAgIHZhciBmcmFtZUludGVyc2VjdCA9XG4gICAgICAgICAgICBmcmFtZSAmJlxuICAgICAgICAgICAgdGhpcy5fY29tcHV0ZVRhcmdldEFuZFJvb3RJbnRlcnNlY3Rpb24oZnJhbWUsIGZyYW1lUmVjdCwgcm9vdFJlY3QpO1xuICAgICAgICBpZiAoZnJhbWVSZWN0ICYmIGZyYW1lSW50ZXJzZWN0KSB7XG4gICAgICAgICAgcGFyZW50ID0gZnJhbWU7XG4gICAgICAgICAgcGFyZW50UmVjdCA9IGNvbnZlcnRGcm9tUGFyZW50UmVjdChmcmFtZVJlY3QsIGZyYW1lSW50ZXJzZWN0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXJlbnQgPSBudWxsO1xuICAgICAgICAgIGludGVyc2VjdGlvblJlY3QgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHRoZSBlbGVtZW50IGhhcyBhIG5vbi12aXNpYmxlIG92ZXJmbG93LCBhbmQgaXQncyBub3QgdGhlIDxib2R5PlxuICAgICAgLy8gb3IgPGh0bWw+IGVsZW1lbnQsIHVwZGF0ZSB0aGUgaW50ZXJzZWN0aW9uIHJlY3QuXG4gICAgICAvLyBOb3RlOiA8Ym9keT4gYW5kIDxodG1sPiBjYW5ub3QgYmUgY2xpcHBlZCB0byBhIHJlY3QgdGhhdCdzIG5vdCBhbHNvXG4gICAgICAvLyB0aGUgZG9jdW1lbnQgcmVjdCwgc28gbm8gbmVlZCB0byBjb21wdXRlIGEgbmV3IGludGVyc2VjdGlvbi5cbiAgICAgIHZhciBkb2MgPSBwYXJlbnQub3duZXJEb2N1bWVudDtcbiAgICAgIGlmIChwYXJlbnQgIT0gZG9jLmJvZHkgJiZcbiAgICAgICAgICBwYXJlbnQgIT0gZG9jLmRvY3VtZW50RWxlbWVudCAmJlxuICAgICAgICAgIHBhcmVudENvbXB1dGVkU3R5bGUub3ZlcmZsb3cgIT0gJ3Zpc2libGUnKSB7XG4gICAgICAgIHBhcmVudFJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QocGFyZW50KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiBlaXRoZXIgb2YgdGhlIGFib3ZlIGNvbmRpdGlvbmFscyBzZXQgYSBuZXcgcGFyZW50UmVjdCxcbiAgICAvLyBjYWxjdWxhdGUgbmV3IGludGVyc2VjdGlvbiBkYXRhLlxuICAgIGlmIChwYXJlbnRSZWN0KSB7XG4gICAgICBpbnRlcnNlY3Rpb25SZWN0ID0gY29tcHV0ZVJlY3RJbnRlcnNlY3Rpb24ocGFyZW50UmVjdCwgaW50ZXJzZWN0aW9uUmVjdCk7XG4gICAgfVxuICAgIGlmICghaW50ZXJzZWN0aW9uUmVjdCkgYnJlYWs7XG4gICAgcGFyZW50ID0gcGFyZW50ICYmIGdldFBhcmVudE5vZGUocGFyZW50KTtcbiAgfVxuICByZXR1cm4gaW50ZXJzZWN0aW9uUmVjdDtcbn07XG5cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSByb290IHJlY3QgYWZ0ZXIgYmVpbmcgZXhwYW5kZWQgYnkgdGhlIHJvb3RNYXJnaW4gdmFsdWUuXG4gKiBAcmV0dXJuIHtDbGllbnRSZWN0fSBUaGUgZXhwYW5kZWQgcm9vdCByZWN0LlxuICogQHByaXZhdGVcbiAqL1xuSW50ZXJzZWN0aW9uT2JzZXJ2ZXIucHJvdG90eXBlLl9nZXRSb290UmVjdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgcm9vdFJlY3Q7XG4gIGlmICh0aGlzLnJvb3QgJiYgIWlzRG9jKHRoaXMucm9vdCkpIHtcbiAgICByb290UmVjdCA9IGdldEJvdW5kaW5nQ2xpZW50UmVjdCh0aGlzLnJvb3QpO1xuICB9IGVsc2Uge1xuICAgIC8vIFVzZSA8aHRtbD4vPGJvZHk+IGluc3RlYWQgb2Ygd2luZG93IHNpbmNlIHNjcm9sbCBiYXJzIGFmZmVjdCBzaXplLlxuICAgIHZhciBkb2MgPSBpc0RvYyh0aGlzLnJvb3QpID8gdGhpcy5yb290IDogZG9jdW1lbnQ7XG4gICAgdmFyIGh0bWwgPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuICAgIHZhciBib2R5ID0gZG9jLmJvZHk7XG4gICAgcm9vdFJlY3QgPSB7XG4gICAgICB0b3A6IDAsXG4gICAgICBsZWZ0OiAwLFxuICAgICAgcmlnaHQ6IGh0bWwuY2xpZW50V2lkdGggfHwgYm9keS5jbGllbnRXaWR0aCxcbiAgICAgIHdpZHRoOiBodG1sLmNsaWVudFdpZHRoIHx8IGJvZHkuY2xpZW50V2lkdGgsXG4gICAgICBib3R0b206IGh0bWwuY2xpZW50SGVpZ2h0IHx8IGJvZHkuY2xpZW50SGVpZ2h0LFxuICAgICAgaGVpZ2h0OiBodG1sLmNsaWVudEhlaWdodCB8fCBib2R5LmNsaWVudEhlaWdodFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHRoaXMuX2V4cGFuZFJlY3RCeVJvb3RNYXJnaW4ocm9vdFJlY3QpO1xufTtcblxuXG4vKipcbiAqIEFjY2VwdHMgYSByZWN0IGFuZCBleHBhbmRzIGl0IGJ5IHRoZSByb290TWFyZ2luIHZhbHVlLlxuICogQHBhcmFtIHtET01SZWN0fENsaWVudFJlY3R9IHJlY3QgVGhlIHJlY3Qgb2JqZWN0IHRvIGV4cGFuZC5cbiAqIEByZXR1cm4ge0NsaWVudFJlY3R9IFRoZSBleHBhbmRlZCByZWN0LlxuICogQHByaXZhdGVcbiAqL1xuSW50ZXJzZWN0aW9uT2JzZXJ2ZXIucHJvdG90eXBlLl9leHBhbmRSZWN0QnlSb290TWFyZ2luID0gZnVuY3Rpb24ocmVjdCkge1xuICB2YXIgbWFyZ2lucyA9IHRoaXMuX3Jvb3RNYXJnaW5WYWx1ZXMubWFwKGZ1bmN0aW9uKG1hcmdpbiwgaSkge1xuICAgIHJldHVybiBtYXJnaW4udW5pdCA9PSAncHgnID8gbWFyZ2luLnZhbHVlIDpcbiAgICAgICAgbWFyZ2luLnZhbHVlICogKGkgJSAyID8gcmVjdC53aWR0aCA6IHJlY3QuaGVpZ2h0KSAvIDEwMDtcbiAgfSk7XG4gIHZhciBuZXdSZWN0ID0ge1xuICAgIHRvcDogcmVjdC50b3AgLSBtYXJnaW5zWzBdLFxuICAgIHJpZ2h0OiByZWN0LnJpZ2h0ICsgbWFyZ2luc1sxXSxcbiAgICBib3R0b206IHJlY3QuYm90dG9tICsgbWFyZ2luc1syXSxcbiAgICBsZWZ0OiByZWN0LmxlZnQgLSBtYXJnaW5zWzNdXG4gIH07XG4gIG5ld1JlY3Qud2lkdGggPSBuZXdSZWN0LnJpZ2h0IC0gbmV3UmVjdC5sZWZ0O1xuICBuZXdSZWN0LmhlaWdodCA9IG5ld1JlY3QuYm90dG9tIC0gbmV3UmVjdC50b3A7XG5cbiAgcmV0dXJuIG5ld1JlY3Q7XG59O1xuXG5cbi8qKlxuICogQWNjZXB0cyBhbiBvbGQgYW5kIG5ldyBlbnRyeSBhbmQgcmV0dXJucyB0cnVlIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGVcbiAqIHRocmVzaG9sZCB2YWx1ZXMgaGFzIGJlZW4gY3Jvc3NlZC5cbiAqIEBwYXJhbSB7P0ludGVyc2VjdGlvbk9ic2VydmVyRW50cnl9IG9sZEVudHJ5IFRoZSBwcmV2aW91cyBlbnRyeSBmb3IgYVxuICogICAgcGFydGljdWxhciB0YXJnZXQgZWxlbWVudCBvciBudWxsIGlmIG5vIHByZXZpb3VzIGVudHJ5IGV4aXN0cy5cbiAqIEBwYXJhbSB7SW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeX0gbmV3RW50cnkgVGhlIGN1cnJlbnQgZW50cnkgZm9yIGFcbiAqICAgIHBhcnRpY3VsYXIgdGFyZ2V0IGVsZW1lbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgYSBhbnkgdGhyZXNob2xkIGhhcyBiZWVuIGNyb3NzZWQuXG4gKiBAcHJpdmF0ZVxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuX2hhc0Nyb3NzZWRUaHJlc2hvbGQgPVxuICAgIGZ1bmN0aW9uKG9sZEVudHJ5LCBuZXdFbnRyeSkge1xuXG4gIC8vIFRvIG1ha2UgY29tcGFyaW5nIGVhc2llciwgYW4gZW50cnkgdGhhdCBoYXMgYSByYXRpbyBvZiAwXG4gIC8vIGJ1dCBkb2VzIG5vdCBhY3R1YWxseSBpbnRlcnNlY3QgaXMgZ2l2ZW4gYSB2YWx1ZSBvZiAtMVxuICB2YXIgb2xkUmF0aW8gPSBvbGRFbnRyeSAmJiBvbGRFbnRyeS5pc0ludGVyc2VjdGluZyA/XG4gICAgICBvbGRFbnRyeS5pbnRlcnNlY3Rpb25SYXRpbyB8fCAwIDogLTE7XG4gIHZhciBuZXdSYXRpbyA9IG5ld0VudHJ5LmlzSW50ZXJzZWN0aW5nID9cbiAgICAgIG5ld0VudHJ5LmludGVyc2VjdGlvblJhdGlvIHx8IDAgOiAtMTtcblxuICAvLyBJZ25vcmUgdW5jaGFuZ2VkIHJhdGlvc1xuICBpZiAob2xkUmF0aW8gPT09IG5ld1JhdGlvKSByZXR1cm47XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRocmVzaG9sZHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgdGhyZXNob2xkID0gdGhpcy50aHJlc2hvbGRzW2ldO1xuXG4gICAgLy8gUmV0dXJuIHRydWUgaWYgYW4gZW50cnkgbWF0Y2hlcyBhIHRocmVzaG9sZCBvciBpZiB0aGUgbmV3IHJhdGlvXG4gICAgLy8gYW5kIHRoZSBvbGQgcmF0aW8gYXJlIG9uIHRoZSBvcHBvc2l0ZSBzaWRlcyBvZiBhIHRocmVzaG9sZC5cbiAgICBpZiAodGhyZXNob2xkID09IG9sZFJhdGlvIHx8IHRocmVzaG9sZCA9PSBuZXdSYXRpbyB8fFxuICAgICAgICB0aHJlc2hvbGQgPCBvbGRSYXRpbyAhPT0gdGhyZXNob2xkIDwgbmV3UmF0aW8pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxufTtcblxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHJvb3QgZWxlbWVudCBpcyBhbiBlbGVtZW50IGFuZCBpcyBpbiB0aGUgRE9NLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgcm9vdCBlbGVtZW50IGlzIGFuIGVsZW1lbnQgYW5kIGlzIGluIHRoZSBET00uXG4gKiBAcHJpdmF0ZVxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuX3Jvb3RJc0luRG9tID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAhdGhpcy5yb290IHx8IGNvbnRhaW5zRGVlcChkb2N1bWVudCwgdGhpcy5yb290KTtcbn07XG5cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSB0YXJnZXQgZWxlbWVudCBpcyBhIGNoaWxkIG9mIHJvb3QuXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldCBUaGUgdGFyZ2V0IGVsZW1lbnQgdG8gY2hlY2suXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSB0YXJnZXQgZWxlbWVudCBpcyBhIGNoaWxkIG9mIHJvb3QuXG4gKiBAcHJpdmF0ZVxuICovXG5JbnRlcnNlY3Rpb25PYnNlcnZlci5wcm90b3R5cGUuX3Jvb3RDb250YWluc1RhcmdldCA9IGZ1bmN0aW9uKHRhcmdldCkge1xuICB2YXIgcm9vdERvYyA9XG4gICAgKHRoaXMucm9vdCAmJiAodGhpcy5yb290Lm93bmVyRG9jdW1lbnQgfHwgdGhpcy5yb290KSkgfHwgZG9jdW1lbnQ7XG4gIHJldHVybiAoXG4gICAgY29udGFpbnNEZWVwKHJvb3REb2MsIHRhcmdldCkgJiZcbiAgICAoIXRoaXMucm9vdCB8fCByb290RG9jID09IHRhcmdldC5vd25lckRvY3VtZW50KVxuICApO1xufTtcblxuXG4vKipcbiAqIEFkZHMgdGhlIGluc3RhbmNlIHRvIHRoZSBnbG9iYWwgSW50ZXJzZWN0aW9uT2JzZXJ2ZXIgcmVnaXN0cnkgaWYgaXQgaXNuJ3RcbiAqIGFscmVhZHkgcHJlc2VudC5cbiAqIEBwcml2YXRlXG4gKi9cbkludGVyc2VjdGlvbk9ic2VydmVyLnByb3RvdHlwZS5fcmVnaXN0ZXJJbnN0YW5jZSA9IGZ1bmN0aW9uKCkge1xuICBpZiAocmVnaXN0cnkuaW5kZXhPZih0aGlzKSA8IDApIHtcbiAgICByZWdpc3RyeS5wdXNoKHRoaXMpO1xuICB9XG59O1xuXG5cbi8qKlxuICogUmVtb3ZlcyB0aGUgaW5zdGFuY2UgZnJvbSB0aGUgZ2xvYmFsIEludGVyc2VjdGlvbk9ic2VydmVyIHJlZ2lzdHJ5LlxuICogQHByaXZhdGVcbiAqL1xuSW50ZXJzZWN0aW9uT2JzZXJ2ZXIucHJvdG90eXBlLl91bnJlZ2lzdGVySW5zdGFuY2UgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGluZGV4ID0gcmVnaXN0cnkuaW5kZXhPZih0aGlzKTtcbiAgaWYgKGluZGV4ICE9IC0xKSByZWdpc3RyeS5zcGxpY2UoaW5kZXgsIDEpO1xufTtcblxuXG4vKipcbiAqIFJldHVybnMgdGhlIHJlc3VsdCBvZiB0aGUgcGVyZm9ybWFuY2Uubm93KCkgbWV0aG9kIG9yIG51bGwgaW4gYnJvd3NlcnNcbiAqIHRoYXQgZG9uJ3Qgc3VwcG9ydCB0aGUgQVBJLlxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgZWxhcHNlZCB0aW1lIHNpbmNlIHRoZSBwYWdlIHdhcyByZXF1ZXN0ZWQuXG4gKi9cbmZ1bmN0aW9uIG5vdygpIHtcbiAgcmV0dXJuIHdpbmRvdy5wZXJmb3JtYW5jZSAmJiBwZXJmb3JtYW5jZS5ub3cgJiYgcGVyZm9ybWFuY2Uubm93KCk7XG59XG5cblxuLyoqXG4gKiBUaHJvdHRsZXMgYSBmdW5jdGlvbiBhbmQgZGVsYXlzIGl0cyBleGVjdXRpb24sIHNvIGl0J3Mgb25seSBjYWxsZWQgYXQgbW9zdFxuICogb25jZSB3aXRoaW4gYSBnaXZlbiB0aW1lIHBlcmlvZC5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0IFRoZSBhbW91bnQgb2YgdGltZSB0aGF0IG11c3QgcGFzcyBiZWZvcmUgdGhlXG4gKiAgICAgZnVuY3Rpb24gY2FuIGJlIGNhbGxlZCBhZ2Fpbi5cbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgdGhyb3R0bGVkIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiB0aHJvdHRsZShmbiwgdGltZW91dCkge1xuICB2YXIgdGltZXIgPSBudWxsO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGltZXIpIHtcbiAgICAgIHRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgZm4oKTtcbiAgICAgICAgdGltZXIgPSBudWxsO1xuICAgICAgfSwgdGltZW91dCk7XG4gICAgfVxuICB9O1xufVxuXG5cbi8qKlxuICogQWRkcyBhbiBldmVudCBoYW5kbGVyIHRvIGEgRE9NIG5vZGUgZW5zdXJpbmcgY3Jvc3MtYnJvd3NlciBjb21wYXRpYmlsaXR5LlxuICogQHBhcmFtIHtOb2RlfSBub2RlIFRoZSBET00gbm9kZSB0byBhZGQgdGhlIGV2ZW50IGhhbmRsZXIgdG8uXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnQgVGhlIGV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZXZlbnQgaGFuZGxlciB0byBhZGQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9wdF91c2VDYXB0dXJlIE9wdGlvbmFsbHkgYWRkcyB0aGUgZXZlbiB0byB0aGUgY2FwdHVyZVxuICogICAgIHBoYXNlLiBOb3RlOiB0aGlzIG9ubHkgd29ya3MgaW4gbW9kZXJuIGJyb3dzZXJzLlxuICovXG5mdW5jdGlvbiBhZGRFdmVudChub2RlLCBldmVudCwgZm4sIG9wdF91c2VDYXB0dXJlKSB7XG4gIGlmICh0eXBlb2Ygbm9kZS5hZGRFdmVudExpc3RlbmVyID09ICdmdW5jdGlvbicpIHtcbiAgICBub2RlLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGZuLCBvcHRfdXNlQ2FwdHVyZSB8fCBmYWxzZSk7XG4gIH1cbiAgZWxzZSBpZiAodHlwZW9mIG5vZGUuYXR0YWNoRXZlbnQgPT0gJ2Z1bmN0aW9uJykge1xuICAgIG5vZGUuYXR0YWNoRXZlbnQoJ29uJyArIGV2ZW50LCBmbik7XG4gIH1cbn1cblxuXG4vKipcbiAqIFJlbW92ZXMgYSBwcmV2aW91c2x5IGFkZGVkIGV2ZW50IGhhbmRsZXIgZnJvbSBhIERPTSBub2RlLlxuICogQHBhcmFtIHtOb2RlfSBub2RlIFRoZSBET00gbm9kZSB0byByZW1vdmUgdGhlIGV2ZW50IGhhbmRsZXIgZnJvbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBUaGUgZXZlbnQgbmFtZS5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBldmVudCBoYW5kbGVyIHRvIHJlbW92ZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0X3VzZUNhcHR1cmUgSWYgdGhlIGV2ZW50IGhhbmRsZXIgd2FzIGFkZGVkIHdpdGggdGhpc1xuICogICAgIGZsYWcgc2V0IHRvIHRydWUsIGl0IHNob3VsZCBiZSBzZXQgdG8gdHJ1ZSBoZXJlIGluIG9yZGVyIHRvIHJlbW92ZSBpdC5cbiAqL1xuZnVuY3Rpb24gcmVtb3ZlRXZlbnQobm9kZSwgZXZlbnQsIGZuLCBvcHRfdXNlQ2FwdHVyZSkge1xuICBpZiAodHlwZW9mIG5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lciA9PSAnZnVuY3Rpb24nKSB7XG4gICAgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBmbiwgb3B0X3VzZUNhcHR1cmUgfHwgZmFsc2UpO1xuICB9XG4gIGVsc2UgaWYgKHR5cGVvZiBub2RlLmRldGF0Y2hFdmVudCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgbm9kZS5kZXRhdGNoRXZlbnQoJ29uJyArIGV2ZW50LCBmbik7XG4gIH1cbn1cblxuXG4vKipcbiAqIFJldHVybnMgdGhlIGludGVyc2VjdGlvbiBiZXR3ZWVuIHR3byByZWN0IG9iamVjdHMuXG4gKiBAcGFyYW0ge09iamVjdH0gcmVjdDEgVGhlIGZpcnN0IHJlY3QuXG4gKiBAcGFyYW0ge09iamVjdH0gcmVjdDIgVGhlIHNlY29uZCByZWN0LlxuICogQHJldHVybiB7P09iamVjdHw/Q2xpZW50UmVjdH0gVGhlIGludGVyc2VjdGlvbiByZWN0IG9yIHVuZGVmaW5lZCBpZiBub1xuICogICAgIGludGVyc2VjdGlvbiBpcyBmb3VuZC5cbiAqL1xuZnVuY3Rpb24gY29tcHV0ZVJlY3RJbnRlcnNlY3Rpb24ocmVjdDEsIHJlY3QyKSB7XG4gIHZhciB0b3AgPSBNYXRoLm1heChyZWN0MS50b3AsIHJlY3QyLnRvcCk7XG4gIHZhciBib3R0b20gPSBNYXRoLm1pbihyZWN0MS5ib3R0b20sIHJlY3QyLmJvdHRvbSk7XG4gIHZhciBsZWZ0ID0gTWF0aC5tYXgocmVjdDEubGVmdCwgcmVjdDIubGVmdCk7XG4gIHZhciByaWdodCA9IE1hdGgubWluKHJlY3QxLnJpZ2h0LCByZWN0Mi5yaWdodCk7XG4gIHZhciB3aWR0aCA9IHJpZ2h0IC0gbGVmdDtcbiAgdmFyIGhlaWdodCA9IGJvdHRvbSAtIHRvcDtcblxuICByZXR1cm4gKHdpZHRoID49IDAgJiYgaGVpZ2h0ID49IDApICYmIHtcbiAgICB0b3A6IHRvcCxcbiAgICBib3R0b206IGJvdHRvbSxcbiAgICBsZWZ0OiBsZWZ0LFxuICAgIHJpZ2h0OiByaWdodCxcbiAgICB3aWR0aDogd2lkdGgsXG4gICAgaGVpZ2h0OiBoZWlnaHRcbiAgfSB8fCBudWxsO1xufVxuXG5cbi8qKlxuICogU2hpbXMgdGhlIG5hdGl2ZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBJRS5cbiAqIEBwYXJhbSB7RWxlbWVudH0gZWwgVGhlIGVsZW1lbnQgd2hvc2UgYm91bmRpbmcgcmVjdCB0byBnZXQuXG4gKiBAcmV0dXJuIHtET01SZWN0fENsaWVudFJlY3R9IFRoZSAocG9zc2libHkgc2hpbW1lZCkgcmVjdCBvZiB0aGUgZWxlbWVudC5cbiAqL1xuZnVuY3Rpb24gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KGVsKSB7XG4gIHZhciByZWN0O1xuXG4gIHRyeSB7XG4gICAgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICAvLyBJZ25vcmUgV2luZG93cyA3IElFMTEgXCJVbnNwZWNpZmllZCBlcnJvclwiXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3czYy9JbnRlcnNlY3Rpb25PYnNlcnZlci9wdWxsLzIwNVxuICB9XG5cbiAgaWYgKCFyZWN0KSByZXR1cm4gZ2V0RW1wdHlSZWN0KCk7XG5cbiAgLy8gT2xkZXIgSUVcbiAgaWYgKCEocmVjdC53aWR0aCAmJiByZWN0LmhlaWdodCkpIHtcbiAgICByZWN0ID0ge1xuICAgICAgdG9wOiByZWN0LnRvcCxcbiAgICAgIHJpZ2h0OiByZWN0LnJpZ2h0LFxuICAgICAgYm90dG9tOiByZWN0LmJvdHRvbSxcbiAgICAgIGxlZnQ6IHJlY3QubGVmdCxcbiAgICAgIHdpZHRoOiByZWN0LnJpZ2h0IC0gcmVjdC5sZWZ0LFxuICAgICAgaGVpZ2h0OiByZWN0LmJvdHRvbSAtIHJlY3QudG9wXG4gICAgfTtcbiAgfVxuICByZXR1cm4gcmVjdDtcbn1cblxuXG4vKipcbiAqIFJldHVybnMgYW4gZW1wdHkgcmVjdCBvYmplY3QuIEFuIGVtcHR5IHJlY3QgaXMgcmV0dXJuZWQgd2hlbiBhbiBlbGVtZW50XG4gKiBpcyBub3QgaW4gdGhlIERPTS5cbiAqIEByZXR1cm4ge0NsaWVudFJlY3R9IFRoZSBlbXB0eSByZWN0LlxuICovXG5mdW5jdGlvbiBnZXRFbXB0eVJlY3QoKSB7XG4gIHJldHVybiB7XG4gICAgdG9wOiAwLFxuICAgIGJvdHRvbTogMCxcbiAgICBsZWZ0OiAwLFxuICAgIHJpZ2h0OiAwLFxuICAgIHdpZHRoOiAwLFxuICAgIGhlaWdodDogMFxuICB9O1xufVxuXG5cbi8qKlxuICogRW5zdXJlIHRoYXQgdGhlIHJlc3VsdCBoYXMgYWxsIG9mIHRoZSBuZWNlc3NhcnkgZmllbGRzIG9mIHRoZSBET01SZWN0LlxuICogU3BlY2lmaWNhbGx5IHRoaXMgZW5zdXJlcyB0aGF0IGB4YCBhbmQgYHlgIGZpZWxkcyBhcmUgc2V0LlxuICpcbiAqIEBwYXJhbSB7P0RPTVJlY3R8P0NsaWVudFJlY3R9IHJlY3RcbiAqIEByZXR1cm4gez9ET01SZWN0fVxuICovXG5mdW5jdGlvbiBlbnN1cmVET01SZWN0KHJlY3QpIHtcbiAgLy8gQSBgRE9NUmVjdGAgb2JqZWN0IGhhcyBgeGAgYW5kIGB5YCBmaWVsZHMuXG4gIGlmICghcmVjdCB8fCAneCcgaW4gcmVjdCkge1xuICAgIHJldHVybiByZWN0O1xuICB9XG4gIC8vIEEgSUUncyBgQ2xpZW50UmVjdGAgdHlwZSBkb2VzIG5vdCBoYXZlIGB4YCBhbmQgYHlgLiBUaGUgc2FtZSBpcyB0aGUgY2FzZVxuICAvLyBmb3IgaW50ZXJuYWxseSBjYWxjdWxhdGVkIFJlY3Qgb2JqZWN0cy4gRm9yIHRoZSBwdXJwb3NlcyBvZlxuICAvLyBgSW50ZXJzZWN0aW9uT2JzZXJ2ZXJgLCBpdCdzIHN1ZmZpY2llbnQgdG8gc2ltcGx5IG1pcnJvciBgbGVmdGAgYW5kIGB0b3BgXG4gIC8vIGZvciB0aGVzZSBmaWVsZHMuXG4gIHJldHVybiB7XG4gICAgdG9wOiByZWN0LnRvcCxcbiAgICB5OiByZWN0LnRvcCxcbiAgICBib3R0b206IHJlY3QuYm90dG9tLFxuICAgIGxlZnQ6IHJlY3QubGVmdCxcbiAgICB4OiByZWN0LmxlZnQsXG4gICAgcmlnaHQ6IHJlY3QucmlnaHQsXG4gICAgd2lkdGg6IHJlY3Qud2lkdGgsXG4gICAgaGVpZ2h0OiByZWN0LmhlaWdodFxuICB9O1xufVxuXG5cbi8qKlxuICogSW52ZXJ0cyB0aGUgaW50ZXJzZWN0aW9uIGFuZCBib3VuZGluZyByZWN0IGZyb20gdGhlIHBhcmVudCAoZnJhbWUpIEJDUiB0b1xuICogdGhlIGxvY2FsIEJDUiBzcGFjZS5cbiAqIEBwYXJhbSB7RE9NUmVjdHxDbGllbnRSZWN0fSBwYXJlbnRCb3VuZGluZ1JlY3QgVGhlIHBhcmVudCdzIGJvdW5kIGNsaWVudCByZWN0LlxuICogQHBhcmFtIHtET01SZWN0fENsaWVudFJlY3R9IHBhcmVudEludGVyc2VjdGlvblJlY3QgVGhlIHBhcmVudCdzIG93biBpbnRlcnNlY3Rpb24gcmVjdC5cbiAqIEByZXR1cm4ge0NsaWVudFJlY3R9IFRoZSBsb2NhbCByb290IGJvdW5kaW5nIHJlY3QgZm9yIHRoZSBwYXJlbnQncyBjaGlsZHJlbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEZyb21QYXJlbnRSZWN0KHBhcmVudEJvdW5kaW5nUmVjdCwgcGFyZW50SW50ZXJzZWN0aW9uUmVjdCkge1xuICB2YXIgdG9wID0gcGFyZW50SW50ZXJzZWN0aW9uUmVjdC50b3AgLSBwYXJlbnRCb3VuZGluZ1JlY3QudG9wO1xuICB2YXIgbGVmdCA9IHBhcmVudEludGVyc2VjdGlvblJlY3QubGVmdCAtIHBhcmVudEJvdW5kaW5nUmVjdC5sZWZ0O1xuICByZXR1cm4ge1xuICAgIHRvcDogdG9wLFxuICAgIGxlZnQ6IGxlZnQsXG4gICAgaGVpZ2h0OiBwYXJlbnRJbnRlcnNlY3Rpb25SZWN0LmhlaWdodCxcbiAgICB3aWR0aDogcGFyZW50SW50ZXJzZWN0aW9uUmVjdC53aWR0aCxcbiAgICBib3R0b206IHRvcCArIHBhcmVudEludGVyc2VjdGlvblJlY3QuaGVpZ2h0LFxuICAgIHJpZ2h0OiBsZWZ0ICsgcGFyZW50SW50ZXJzZWN0aW9uUmVjdC53aWR0aFxuICB9O1xufVxuXG5cbi8qKlxuICogQ2hlY2tzIHRvIHNlZSBpZiBhIHBhcmVudCBlbGVtZW50IGNvbnRhaW5zIGEgY2hpbGQgZWxlbWVudCAoaW5jbHVkaW5nIGluc2lkZVxuICogc2hhZG93IERPTSkuXG4gKiBAcGFyYW0ge05vZGV9IHBhcmVudCBUaGUgcGFyZW50IGVsZW1lbnQuXG4gKiBAcGFyYW0ge05vZGV9IGNoaWxkIFRoZSBjaGlsZCBlbGVtZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgcGFyZW50IG5vZGUgY29udGFpbnMgdGhlIGNoaWxkIG5vZGUuXG4gKi9cbmZ1bmN0aW9uIGNvbnRhaW5zRGVlcChwYXJlbnQsIGNoaWxkKSB7XG4gIHZhciBub2RlID0gY2hpbGQ7XG4gIHdoaWxlIChub2RlKSB7XG4gICAgaWYgKG5vZGUgPT0gcGFyZW50KSByZXR1cm4gdHJ1ZTtcblxuICAgIG5vZGUgPSBnZXRQYXJlbnROb2RlKG5vZGUpO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuXG4vKipcbiAqIEdldHMgdGhlIHBhcmVudCBub2RlIG9mIGFuIGVsZW1lbnQgb3IgaXRzIGhvc3QgZWxlbWVudCBpZiB0aGUgcGFyZW50IG5vZGVcbiAqIGlzIGEgc2hhZG93IHJvb3QuXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgVGhlIG5vZGUgd2hvc2UgcGFyZW50IHRvIGdldC5cbiAqIEByZXR1cm4ge05vZGV8bnVsbH0gVGhlIHBhcmVudCBub2RlIG9yIG51bGwgaWYgbm8gcGFyZW50IGV4aXN0cy5cbiAqL1xuZnVuY3Rpb24gZ2V0UGFyZW50Tm9kZShub2RlKSB7XG4gIHZhciBwYXJlbnQgPSBub2RlLnBhcmVudE5vZGU7XG5cbiAgaWYgKG5vZGUubm9kZVR5cGUgPT0gLyogRE9DVU1FTlQgKi8gOSAmJiBub2RlICE9IGRvY3VtZW50KSB7XG4gICAgLy8gSWYgdGhpcyBub2RlIGlzIGEgZG9jdW1lbnQgbm9kZSwgbG9vayBmb3IgdGhlIGVtYmVkZGluZyBmcmFtZS5cbiAgICByZXR1cm4gZ2V0RnJhbWVFbGVtZW50KG5vZGUpO1xuICB9XG5cbiAgLy8gSWYgdGhlIHBhcmVudCBoYXMgZWxlbWVudCB0aGF0IGlzIGFzc2lnbmVkIHRocm91Z2ggc2hhZG93IHJvb3Qgc2xvdFxuICBpZiAocGFyZW50ICYmIHBhcmVudC5hc3NpZ25lZFNsb3QpIHtcbiAgICBwYXJlbnQgPSBwYXJlbnQuYXNzaWduZWRTbG90LnBhcmVudE5vZGVcbiAgfVxuXG4gIGlmIChwYXJlbnQgJiYgcGFyZW50Lm5vZGVUeXBlID09IDExICYmIHBhcmVudC5ob3N0KSB7XG4gICAgLy8gSWYgdGhlIHBhcmVudCBpcyBhIHNoYWRvdyByb290LCByZXR1cm4gdGhlIGhvc3QgZWxlbWVudC5cbiAgICByZXR1cm4gcGFyZW50Lmhvc3Q7XG4gIH1cblxuICByZXR1cm4gcGFyZW50O1xufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiBgbm9kZWAgaXMgYSBEb2N1bWVudC5cbiAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc0RvYyhub2RlKSB7XG4gIHJldHVybiBub2RlICYmIG5vZGUubm9kZVR5cGUgPT09IDk7XG59XG5cblxuLy8gRXhwb3NlcyB0aGUgY29uc3RydWN0b3JzIGdsb2JhbGx5Llxud2luZG93LkludGVyc2VjdGlvbk9ic2VydmVyID0gSW50ZXJzZWN0aW9uT2JzZXJ2ZXI7XG53aW5kb3cuSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeSA9IEludGVyc2VjdGlvbk9ic2VydmVyRW50cnk7XG5cbn0oKSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///../node_modules/intersection-observer/intersection-observer.js\n");
|
|
|
|
/***/ })
|
|
|
|
}]); |