You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
679 lines
100 KiB
679 lines
100 KiB
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
import { Directionality } from '@angular/cdk/bidi';
|
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
import { DOWN_ARROW, ENTER, ESCAPE, TAB, UP_ARROW, hasModifierKey } from '@angular/cdk/keycodes';
|
|
import { Overlay, OverlayConfig, } from '@angular/cdk/overlay';
|
|
import { _getEventTarget } from '@angular/cdk/platform';
|
|
import { TemplatePortal } from '@angular/cdk/portal';
|
|
import { ViewportRuler } from '@angular/cdk/scrolling';
|
|
import { DOCUMENT } from '@angular/common';
|
|
import { ChangeDetectorRef, Directive, ElementRef, forwardRef, Host, Inject, InjectionToken, Input, NgZone, Optional, ViewContainerRef, } from '@angular/core';
|
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
import { _countGroupLabelsBeforeOption, _getOptionScrollPosition, MatOptionSelectionChange, } from '@angular/material/core';
|
|
import { MAT_FORM_FIELD, MatFormField } from '@angular/material/form-field';
|
|
import { defer, fromEvent, merge, of as observableOf, Subject, Subscription } from 'rxjs';
|
|
import { delay, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
|
import { _MatAutocompleteBase, MAT_AUTOCOMPLETE_DEFAULT_OPTIONS } from './autocomplete';
|
|
import { _MatAutocompleteOriginBase } from './autocomplete-origin';
|
|
/** Injection token that determines the scroll handling while the autocomplete panel is open. */
|
|
import * as ɵngcc0 from '@angular/core';
|
|
import * as ɵngcc1 from '@angular/cdk/overlay';
|
|
import * as ɵngcc2 from '@angular/cdk/bidi';
|
|
import * as ɵngcc3 from '@angular/cdk/scrolling';
|
|
import * as ɵngcc4 from '@angular/material/form-field';
|
|
export const MAT_AUTOCOMPLETE_SCROLL_STRATEGY = new InjectionToken('mat-autocomplete-scroll-strategy');
|
|
/** @docs-private */
|
|
export function MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY(overlay) {
|
|
return () => overlay.scrollStrategies.reposition();
|
|
}
|
|
/** @docs-private */
|
|
export const MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER = {
|
|
provide: MAT_AUTOCOMPLETE_SCROLL_STRATEGY,
|
|
deps: [Overlay],
|
|
useFactory: MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY,
|
|
};
|
|
/**
|
|
* Provider that allows the autocomplete to register as a ControlValueAccessor.
|
|
* @docs-private
|
|
*/
|
|
export const MAT_AUTOCOMPLETE_VALUE_ACCESSOR = {
|
|
provide: NG_VALUE_ACCESSOR,
|
|
useExisting: forwardRef(() => MatAutocompleteTrigger),
|
|
multi: true
|
|
};
|
|
/**
|
|
* Creates an error to be thrown when attempting to use an autocomplete trigger without a panel.
|
|
* @docs-private
|
|
*/
|
|
export function getMatAutocompleteMissingPanelError() {
|
|
return Error('Attempting to open an undefined instance of `mat-autocomplete`. ' +
|
|
'Make sure that the id passed to the `matAutocomplete` is correct and that ' +
|
|
'you\'re attempting to open it after the ngAfterContentInit hook.');
|
|
}
|
|
/** Base class with all of the `MatAutocompleteTrigger` functionality. */
|
|
export class _MatAutocompleteTriggerBase {
|
|
constructor(_element, _overlay, _viewContainerRef, _zone, _changeDetectorRef, scrollStrategy, _dir, _formField, _document, _viewportRuler, _defaults) {
|
|
this._element = _element;
|
|
this._overlay = _overlay;
|
|
this._viewContainerRef = _viewContainerRef;
|
|
this._zone = _zone;
|
|
this._changeDetectorRef = _changeDetectorRef;
|
|
this._dir = _dir;
|
|
this._formField = _formField;
|
|
this._document = _document;
|
|
this._viewportRuler = _viewportRuler;
|
|
this._defaults = _defaults;
|
|
this._componentDestroyed = false;
|
|
this._autocompleteDisabled = false;
|
|
/** Whether or not the label state is being overridden. */
|
|
this._manuallyFloatingLabel = false;
|
|
/** Subscription to viewport size changes. */
|
|
this._viewportSubscription = Subscription.EMPTY;
|
|
/**
|
|
* Whether the autocomplete can open the next time it is focused. Used to prevent a focused,
|
|
* closed autocomplete from being reopened if the user switches to another browser tab and then
|
|
* comes back.
|
|
*/
|
|
this._canOpenOnNextFocus = true;
|
|
/** Stream of keyboard events that can close the panel. */
|
|
this._closeKeyEventStream = new Subject();
|
|
/**
|
|
* Event handler for when the window is blurred. Needs to be an
|
|
* arrow function in order to preserve the context.
|
|
*/
|
|
this._windowBlurHandler = () => {
|
|
// If the user blurred the window while the autocomplete is focused, it means that it'll be
|
|
// refocused when they come back. In this case we want to skip the first focus event, if the
|
|
// pane was closed, in order to avoid reopening it unintentionally.
|
|
this._canOpenOnNextFocus =
|
|
this._document.activeElement !== this._element.nativeElement || this.panelOpen;
|
|
};
|
|
/** `View -> model callback called when value changes` */
|
|
this._onChange = () => { };
|
|
/** `View -> model callback called when autocomplete has been touched` */
|
|
this._onTouched = () => { };
|
|
/**
|
|
* Position of the autocomplete panel relative to the trigger element. A position of `auto`
|
|
* will render the panel underneath the trigger if there is enough space for it to fit in
|
|
* the viewport, otherwise the panel will be shown above it. If the position is set to
|
|
* `above` or `below`, the panel will always be shown above or below the trigger. no matter
|
|
* whether it fits completely in the viewport.
|
|
*/
|
|
this.position = 'auto';
|
|
/**
|
|
* `autocomplete` attribute to be set on the input element.
|
|
* @docs-private
|
|
*/
|
|
this.autocompleteAttribute = 'off';
|
|
this._overlayAttached = false;
|
|
/** Stream of autocomplete option selections. */
|
|
this.optionSelections = defer(() => {
|
|
if (this.autocomplete && this.autocomplete.options) {
|
|
return merge(...this.autocomplete.options.map(option => option.onSelectionChange));
|
|
}
|
|
// If there are any subscribers before `ngAfterViewInit`, the `autocomplete` will be undefined.
|
|
// Return a stream that we'll replace with the real one once everything is in place.
|
|
return this._zone.onStable
|
|
.pipe(take(1), switchMap(() => this.optionSelections));
|
|
});
|
|
this._scrollStrategy = scrollStrategy;
|
|
}
|
|
/**
|
|
* Whether the autocomplete is disabled. When disabled, the element will
|
|
* act as a regular input and the user won't be able to open the panel.
|
|
*/
|
|
get autocompleteDisabled() { return this._autocompleteDisabled; }
|
|
set autocompleteDisabled(value) {
|
|
this._autocompleteDisabled = coerceBooleanProperty(value);
|
|
}
|
|
ngAfterViewInit() {
|
|
const window = this._getWindow();
|
|
if (typeof window !== 'undefined') {
|
|
this._zone.runOutsideAngular(() => window.addEventListener('blur', this._windowBlurHandler));
|
|
}
|
|
}
|
|
ngOnChanges(changes) {
|
|
if (changes['position'] && this._positionStrategy) {
|
|
this._setStrategyPositions(this._positionStrategy);
|
|
if (this.panelOpen) {
|
|
this._overlayRef.updatePosition();
|
|
}
|
|
}
|
|
}
|
|
ngOnDestroy() {
|
|
const window = this._getWindow();
|
|
if (typeof window !== 'undefined') {
|
|
window.removeEventListener('blur', this._windowBlurHandler);
|
|
}
|
|
this._viewportSubscription.unsubscribe();
|
|
this._componentDestroyed = true;
|
|
this._destroyPanel();
|
|
this._closeKeyEventStream.complete();
|
|
}
|
|
/** Whether or not the autocomplete panel is open. */
|
|
get panelOpen() {
|
|
return this._overlayAttached && this.autocomplete.showPanel;
|
|
}
|
|
/** Opens the autocomplete suggestion panel. */
|
|
openPanel() {
|
|
this._attachOverlay();
|
|
this._floatLabel();
|
|
}
|
|
/** Closes the autocomplete suggestion panel. */
|
|
closePanel() {
|
|
this._resetLabel();
|
|
if (!this._overlayAttached) {
|
|
return;
|
|
}
|
|
if (this.panelOpen) {
|
|
// Only emit if the panel was visible.
|
|
this.autocomplete.closed.emit();
|
|
}
|
|
this.autocomplete._isOpen = this._overlayAttached = false;
|
|
if (this._overlayRef && this._overlayRef.hasAttached()) {
|
|
this._overlayRef.detach();
|
|
this._closingActionsSubscription.unsubscribe();
|
|
}
|
|
// Note that in some cases this can end up being called after the component is destroyed.
|
|
// Add a check to ensure that we don't try to run change detection on a destroyed view.
|
|
if (!this._componentDestroyed) {
|
|
// We need to trigger change detection manually, because
|
|
// `fromEvent` doesn't seem to do it at the proper time.
|
|
// This ensures that the label is reset when the
|
|
// user clicks outside.
|
|
this._changeDetectorRef.detectChanges();
|
|
}
|
|
}
|
|
/**
|
|
* Updates the position of the autocomplete suggestion panel to ensure that it fits all options
|
|
* within the viewport.
|
|
*/
|
|
updatePosition() {
|
|
if (this._overlayAttached) {
|
|
this._overlayRef.updatePosition();
|
|
}
|
|
}
|
|
/**
|
|
* A stream of actions that should close the autocomplete panel, including
|
|
* when an option is selected, on blur, and when TAB is pressed.
|
|
*/
|
|
get panelClosingActions() {
|
|
return merge(this.optionSelections, this.autocomplete._keyManager.tabOut.pipe(filter(() => this._overlayAttached)), this._closeKeyEventStream, this._getOutsideClickStream(), this._overlayRef ?
|
|
this._overlayRef.detachments().pipe(filter(() => this._overlayAttached)) :
|
|
observableOf()).pipe(
|
|
// Normalize the output so we return a consistent type.
|
|
map(event => event instanceof MatOptionSelectionChange ? event : null));
|
|
}
|
|
/** The currently active option, coerced to MatOption type. */
|
|
get activeOption() {
|
|
if (this.autocomplete && this.autocomplete._keyManager) {
|
|
return this.autocomplete._keyManager.activeItem;
|
|
}
|
|
return null;
|
|
}
|
|
/** Stream of clicks outside of the autocomplete panel. */
|
|
_getOutsideClickStream() {
|
|
return merge(fromEvent(this._document, 'click'), fromEvent(this._document, 'auxclick'), fromEvent(this._document, 'touchend'))
|
|
.pipe(filter(event => {
|
|
// If we're in the Shadow DOM, the event target will be the shadow root, so we have to
|
|
// fall back to check the first element in the path of the click event.
|
|
const clickTarget = _getEventTarget(event);
|
|
const formField = this._formField ? this._formField._elementRef.nativeElement : null;
|
|
const customOrigin = this.connectedTo ? this.connectedTo.elementRef.nativeElement : null;
|
|
return this._overlayAttached && clickTarget !== this._element.nativeElement &&
|
|
(!formField || !formField.contains(clickTarget)) &&
|
|
(!customOrigin || !customOrigin.contains(clickTarget)) &&
|
|
(!!this._overlayRef && !this._overlayRef.overlayElement.contains(clickTarget));
|
|
}));
|
|
}
|
|
// Implemented as part of ControlValueAccessor.
|
|
writeValue(value) {
|
|
Promise.resolve(null).then(() => this._setTriggerValue(value));
|
|
}
|
|
// Implemented as part of ControlValueAccessor.
|
|
registerOnChange(fn) {
|
|
this._onChange = fn;
|
|
}
|
|
// Implemented as part of ControlValueAccessor.
|
|
registerOnTouched(fn) {
|
|
this._onTouched = fn;
|
|
}
|
|
// Implemented as part of ControlValueAccessor.
|
|
setDisabledState(isDisabled) {
|
|
this._element.nativeElement.disabled = isDisabled;
|
|
}
|
|
_handleKeydown(event) {
|
|
const keyCode = event.keyCode;
|
|
// Prevent the default action on all escape key presses. This is here primarily to bring IE
|
|
// in line with other browsers. By default, pressing escape on IE will cause it to revert
|
|
// the input value to the one that it had on focus, however it won't dispatch any events
|
|
// which means that the model value will be out of sync with the view.
|
|
if (keyCode === ESCAPE && !hasModifierKey(event)) {
|
|
event.preventDefault();
|
|
}
|
|
if (this.activeOption && keyCode === ENTER && this.panelOpen) {
|
|
this.activeOption._selectViaInteraction();
|
|
this._resetActiveItem();
|
|
event.preventDefault();
|
|
}
|
|
else if (this.autocomplete) {
|
|
const prevActiveItem = this.autocomplete._keyManager.activeItem;
|
|
const isArrowKey = keyCode === UP_ARROW || keyCode === DOWN_ARROW;
|
|
if (this.panelOpen || keyCode === TAB) {
|
|
this.autocomplete._keyManager.onKeydown(event);
|
|
}
|
|
else if (isArrowKey && this._canOpen()) {
|
|
this.openPanel();
|
|
}
|
|
if (isArrowKey || this.autocomplete._keyManager.activeItem !== prevActiveItem) {
|
|
this._scrollToOption(this.autocomplete._keyManager.activeItemIndex || 0);
|
|
}
|
|
}
|
|
}
|
|
_handleInput(event) {
|
|
let target = event.target;
|
|
let value = target.value;
|
|
// Based on `NumberValueAccessor` from forms.
|
|
if (target.type === 'number') {
|
|
value = value == '' ? null : parseFloat(value);
|
|
}
|
|
// If the input has a placeholder, IE will fire the `input` event on page load,
|
|
// focus and blur, in addition to when the user actually changed the value. To
|
|
// filter out all of the extra events, we save the value on focus and between
|
|
// `input` events, and we check whether it changed.
|
|
// See: https://connect.microsoft.com/IE/feedback/details/885747/
|
|
if (this._previousValue !== value) {
|
|
this._previousValue = value;
|
|
this._onChange(value);
|
|
if (this._canOpen() && this._document.activeElement === event.target) {
|
|
this.openPanel();
|
|
}
|
|
}
|
|
}
|
|
_handleFocus() {
|
|
if (!this._canOpenOnNextFocus) {
|
|
this._canOpenOnNextFocus = true;
|
|
}
|
|
else if (this._canOpen()) {
|
|
this._previousValue = this._element.nativeElement.value;
|
|
this._attachOverlay();
|
|
this._floatLabel(true);
|
|
}
|
|
}
|
|
/**
|
|
* In "auto" mode, the label will animate down as soon as focus is lost.
|
|
* This causes the value to jump when selecting an option with the mouse.
|
|
* This method manually floats the label until the panel can be closed.
|
|
* @param shouldAnimate Whether the label should be animated when it is floated.
|
|
*/
|
|
_floatLabel(shouldAnimate = false) {
|
|
if (this._formField && this._formField.floatLabel === 'auto') {
|
|
if (shouldAnimate) {
|
|
this._formField._animateAndLockLabel();
|
|
}
|
|
else {
|
|
this._formField.floatLabel = 'always';
|
|
}
|
|
this._manuallyFloatingLabel = true;
|
|
}
|
|
}
|
|
/** If the label has been manually elevated, return it to its normal state. */
|
|
_resetLabel() {
|
|
if (this._manuallyFloatingLabel) {
|
|
this._formField.floatLabel = 'auto';
|
|
this._manuallyFloatingLabel = false;
|
|
}
|
|
}
|
|
/**
|
|
* This method listens to a stream of panel closing actions and resets the
|
|
* stream every time the option list changes.
|
|
*/
|
|
_subscribeToClosingActions() {
|
|
const firstStable = this._zone.onStable.pipe(take(1));
|
|
const optionChanges = this.autocomplete.options.changes.pipe(tap(() => this._positionStrategy.reapplyLastPosition()),
|
|
// Defer emitting to the stream until the next tick, because changing
|
|
// bindings in here will cause "changed after checked" errors.
|
|
delay(0));
|
|
// When the zone is stable initially, and when the option list changes...
|
|
return merge(firstStable, optionChanges)
|
|
.pipe(
|
|
// create a new stream of panelClosingActions, replacing any previous streams
|
|
// that were created, and flatten it so our stream only emits closing events...
|
|
switchMap(() => {
|
|
const wasOpen = this.panelOpen;
|
|
this._resetActiveItem();
|
|
this.autocomplete._setVisibility();
|
|
if (this.panelOpen) {
|
|
this._overlayRef.updatePosition();
|
|
// If the `panelOpen` state changed, we need to make sure to emit the `opened`
|
|
// event, because we may not have emitted it when the panel was attached. This
|
|
// can happen if the users opens the panel and there are no options, but the
|
|
// options come in slightly later or as a result of the value changing.
|
|
if (wasOpen !== this.panelOpen) {
|
|
this.autocomplete.opened.emit();
|
|
}
|
|
}
|
|
return this.panelClosingActions;
|
|
}),
|
|
// when the first closing event occurs...
|
|
take(1))
|
|
// set the value, close the panel, and complete.
|
|
.subscribe(event => this._setValueAndClose(event));
|
|
}
|
|
/** Destroys the autocomplete suggestion panel. */
|
|
_destroyPanel() {
|
|
if (this._overlayRef) {
|
|
this.closePanel();
|
|
this._overlayRef.dispose();
|
|
this._overlayRef = null;
|
|
}
|
|
}
|
|
_setTriggerValue(value) {
|
|
const toDisplay = this.autocomplete && this.autocomplete.displayWith ?
|
|
this.autocomplete.displayWith(value) :
|
|
value;
|
|
// Simply falling back to an empty string if the display value is falsy does not work properly.
|
|
// The display value can also be the number zero and shouldn't fall back to an empty string.
|
|
const inputValue = toDisplay != null ? toDisplay : '';
|
|
// If it's used within a `MatFormField`, we should set it through the property so it can go
|
|
// through change detection.
|
|
if (this._formField) {
|
|
this._formField._control.value = inputValue;
|
|
}
|
|
else {
|
|
this._element.nativeElement.value = inputValue;
|
|
}
|
|
this._previousValue = inputValue;
|
|
}
|
|
/**
|
|
* This method closes the panel, and if a value is specified, also sets the associated
|
|
* control to that value. It will also mark the control as dirty if this interaction
|
|
* stemmed from the user.
|
|
*/
|
|
_setValueAndClose(event) {
|
|
if (event && event.source) {
|
|
this._clearPreviousSelectedOption(event.source);
|
|
this._setTriggerValue(event.source.value);
|
|
this._onChange(event.source.value);
|
|
this._element.nativeElement.focus();
|
|
this.autocomplete._emitSelectEvent(event.source);
|
|
}
|
|
this.closePanel();
|
|
}
|
|
/**
|
|
* Clear any previous selected option and emit a selection change event for this option
|
|
*/
|
|
_clearPreviousSelectedOption(skip) {
|
|
this.autocomplete.options.forEach(option => {
|
|
if (option !== skip && option.selected) {
|
|
option.deselect();
|
|
}
|
|
});
|
|
}
|
|
_attachOverlay() {
|
|
var _a;
|
|
if (!this.autocomplete && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
throw getMatAutocompleteMissingPanelError();
|
|
}
|
|
let overlayRef = this._overlayRef;
|
|
if (!overlayRef) {
|
|
this._portal = new TemplatePortal(this.autocomplete.template, this._viewContainerRef, { id: (_a = this._formField) === null || _a === void 0 ? void 0 : _a.getLabelId() });
|
|
overlayRef = this._overlay.create(this._getOverlayConfig());
|
|
this._overlayRef = overlayRef;
|
|
// Use the `keydownEvents` in order to take advantage of
|
|
// the overlay event targeting provided by the CDK overlay.
|
|
overlayRef.keydownEvents().subscribe(event => {
|
|
// Close when pressing ESCAPE or ALT + UP_ARROW, based on the a11y guidelines.
|
|
// See: https://www.w3.org/TR/wai-aria-practices-1.1/#textbox-keyboard-interaction
|
|
if ((event.keyCode === ESCAPE && !hasModifierKey(event)) ||
|
|
(event.keyCode === UP_ARROW && hasModifierKey(event, 'altKey'))) {
|
|
this._closeKeyEventStream.next();
|
|
this._resetActiveItem();
|
|
// We need to stop propagation, otherwise the event will eventually
|
|
// reach the input itself and cause the overlay to be reopened.
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
this._viewportSubscription = this._viewportRuler.change().subscribe(() => {
|
|
if (this.panelOpen && overlayRef) {
|
|
overlayRef.updateSize({ width: this._getPanelWidth() });
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
// Update the trigger, panel width and direction, in case anything has changed.
|
|
this._positionStrategy.setOrigin(this._getConnectedElement());
|
|
overlayRef.updateSize({ width: this._getPanelWidth() });
|
|
}
|
|
if (overlayRef && !overlayRef.hasAttached()) {
|
|
overlayRef.attach(this._portal);
|
|
this._closingActionsSubscription = this._subscribeToClosingActions();
|
|
}
|
|
const wasOpen = this.panelOpen;
|
|
this.autocomplete._setVisibility();
|
|
this.autocomplete._isOpen = this._overlayAttached = true;
|
|
// We need to do an extra `panelOpen` check in here, because the
|
|
// autocomplete won't be shown if there are no options.
|
|
if (this.panelOpen && wasOpen !== this.panelOpen) {
|
|
this.autocomplete.opened.emit();
|
|
}
|
|
}
|
|
_getOverlayConfig() {
|
|
var _a;
|
|
return new OverlayConfig({
|
|
positionStrategy: this._getOverlayPosition(),
|
|
scrollStrategy: this._scrollStrategy(),
|
|
width: this._getPanelWidth(),
|
|
direction: this._dir,
|
|
panelClass: (_a = this._defaults) === null || _a === void 0 ? void 0 : _a.overlayPanelClass,
|
|
});
|
|
}
|
|
_getOverlayPosition() {
|
|
const strategy = this._overlay.position()
|
|
.flexibleConnectedTo(this._getConnectedElement())
|
|
.withFlexibleDimensions(false)
|
|
.withPush(false);
|
|
this._setStrategyPositions(strategy);
|
|
this._positionStrategy = strategy;
|
|
return strategy;
|
|
}
|
|
/** Sets the positions on a position strategy based on the directive's input state. */
|
|
_setStrategyPositions(positionStrategy) {
|
|
// Note that we provide horizontal fallback positions, even though by default the dropdown
|
|
// width matches the input, because consumers can override the width. See #18854.
|
|
const belowPositions = [
|
|
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },
|
|
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top' }
|
|
];
|
|
// The overlay edge connected to the trigger should have squared corners, while
|
|
// the opposite end has rounded corners. We apply a CSS class to swap the
|
|
// border-radius based on the overlay position.
|
|
const panelClass = this._aboveClass;
|
|
const abovePositions = [
|
|
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', panelClass },
|
|
{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', panelClass }
|
|
];
|
|
let positions;
|
|
if (this.position === 'above') {
|
|
positions = abovePositions;
|
|
}
|
|
else if (this.position === 'below') {
|
|
positions = belowPositions;
|
|
}
|
|
else {
|
|
positions = [...belowPositions, ...abovePositions];
|
|
}
|
|
positionStrategy.withPositions(positions);
|
|
}
|
|
_getConnectedElement() {
|
|
if (this.connectedTo) {
|
|
return this.connectedTo.elementRef;
|
|
}
|
|
return this._formField ? this._formField.getConnectedOverlayOrigin() : this._element;
|
|
}
|
|
_getPanelWidth() {
|
|
return this.autocomplete.panelWidth || this._getHostWidth();
|
|
}
|
|
/** Returns the width of the input element, so the panel width can match it. */
|
|
_getHostWidth() {
|
|
return this._getConnectedElement().nativeElement.getBoundingClientRect().width;
|
|
}
|
|
/**
|
|
* Resets the active item to -1 so arrow events will activate the
|
|
* correct options, or to 0 if the consumer opted into it.
|
|
*/
|
|
_resetActiveItem() {
|
|
const autocomplete = this.autocomplete;
|
|
if (autocomplete.autoActiveFirstOption) {
|
|
// Note that we go through `setFirstItemActive`, rather than `setActiveItem(0)`, because
|
|
// the former will find the next enabled option, if the first one is disabled.
|
|
autocomplete._keyManager.setFirstItemActive();
|
|
}
|
|
else {
|
|
autocomplete._keyManager.setActiveItem(-1);
|
|
}
|
|
}
|
|
/** Determines whether the panel can be opened. */
|
|
_canOpen() {
|
|
const element = this._element.nativeElement;
|
|
return !element.readOnly && !element.disabled && !this._autocompleteDisabled;
|
|
}
|
|
/** Use defaultView of injected document if available or fallback to global window reference */
|
|
_getWindow() {
|
|
var _a;
|
|
return ((_a = this._document) === null || _a === void 0 ? void 0 : _a.defaultView) || window;
|
|
}
|
|
/** Scrolls to a particular option in the list. */
|
|
_scrollToOption(index) {
|
|
// Given that we are not actually focusing active options, we must manually adjust scroll
|
|
// to reveal options below the fold. First, we find the offset of the option from the top
|
|
// of the panel. If that offset is below the fold, the new scrollTop will be the offset -
|
|
// the panel height + the option height, so the active option will be just visible at the
|
|
// bottom of the panel. If that offset is above the top of the visible panel, the new scrollTop
|
|
// will become the offset. If that offset is visible within the panel already, the scrollTop is
|
|
// not adjusted.
|
|
const autocomplete = this.autocomplete;
|
|
const labelCount = _countGroupLabelsBeforeOption(index, autocomplete.options, autocomplete.optionGroups);
|
|
if (index === 0 && labelCount === 1) {
|
|
// If we've got one group label before the option and we're at the top option,
|
|
// scroll the list to the top. This is better UX than scrolling the list to the
|
|
// top of the option, because it allows the user to read the top group's label.
|
|
autocomplete._setScrollTop(0);
|
|
}
|
|
else if (autocomplete.panel) {
|
|
const option = autocomplete.options.toArray()[index];
|
|
if (option) {
|
|
const element = option._getHostElement();
|
|
const newScrollPosition = _getOptionScrollPosition(element.offsetTop, element.offsetHeight, autocomplete._getScrollTop(), autocomplete.panel.nativeElement.offsetHeight);
|
|
autocomplete._setScrollTop(newScrollPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_MatAutocompleteTriggerBase.ɵfac = function _MatAutocompleteTriggerBase_Factory(t) { return new (t || _MatAutocompleteTriggerBase)(ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ElementRef), ɵngcc0.ɵɵdirectiveInject(ɵngcc1.Overlay), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ViewContainerRef), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.NgZone), ɵngcc0.ɵɵdirectiveInject(ɵngcc0.ChangeDetectorRef), ɵngcc0.ɵɵdirectiveInject(MAT_AUTOCOMPLETE_SCROLL_STRATEGY), ɵngcc0.ɵɵdirectiveInject(ɵngcc2.Directionality, 8), ɵngcc0.ɵɵdirectiveInject(MAT_FORM_FIELD, 9), ɵngcc0.ɵɵdirectiveInject(DOCUMENT, 8), ɵngcc0.ɵɵdirectiveInject(ɵngcc3.ViewportRuler), ɵngcc0.ɵɵdirectiveInject(MAT_AUTOCOMPLETE_DEFAULT_OPTIONS, 8)); };
|
|
_MatAutocompleteTriggerBase.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: _MatAutocompleteTriggerBase, inputs: { position: ["matAutocompletePosition", "position"], autocompleteAttribute: ["autocomplete", "autocompleteAttribute"], autocompleteDisabled: ["matAutocompleteDisabled", "autocompleteDisabled"], autocomplete: ["matAutocomplete", "autocomplete"], connectedTo: ["matAutocompleteConnectedTo", "connectedTo"] }, features: [ɵngcc0.ɵɵNgOnChangesFeature] });
|
|
_MatAutocompleteTriggerBase.ctorParameters = () => [
|
|
{ type: ElementRef },
|
|
{ type: Overlay },
|
|
{ type: ViewContainerRef },
|
|
{ type: NgZone },
|
|
{ type: ChangeDetectorRef },
|
|
{ type: undefined, decorators: [{ type: Inject, args: [MAT_AUTOCOMPLETE_SCROLL_STRATEGY,] }] },
|
|
{ type: Directionality, decorators: [{ type: Optional }] },
|
|
{ type: MatFormField, decorators: [{ type: Optional }, { type: Inject, args: [MAT_FORM_FIELD,] }, { type: Host }] },
|
|
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] },
|
|
{ type: ViewportRuler },
|
|
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAT_AUTOCOMPLETE_DEFAULT_OPTIONS,] }] }
|
|
];
|
|
_MatAutocompleteTriggerBase.propDecorators = {
|
|
autocomplete: [{ type: Input, args: ['matAutocomplete',] }],
|
|
position: [{ type: Input, args: ['matAutocompletePosition',] }],
|
|
connectedTo: [{ type: Input, args: ['matAutocompleteConnectedTo',] }],
|
|
autocompleteAttribute: [{ type: Input, args: ['autocomplete',] }],
|
|
autocompleteDisabled: [{ type: Input, args: ['matAutocompleteDisabled',] }]
|
|
};
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(_MatAutocompleteTriggerBase, [{
|
|
type: Directive
|
|
}], function () { return [{ type: ɵngcc0.ElementRef }, { type: ɵngcc1.Overlay }, { type: ɵngcc0.ViewContainerRef }, { type: ɵngcc0.NgZone }, { type: ɵngcc0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
type: Inject,
|
|
args: [MAT_AUTOCOMPLETE_SCROLL_STRATEGY]
|
|
}] }, { type: ɵngcc2.Directionality, decorators: [{
|
|
type: Optional
|
|
}] }, { type: ɵngcc4.MatFormField, decorators: [{
|
|
type: Optional
|
|
}, {
|
|
type: Inject,
|
|
args: [MAT_FORM_FIELD]
|
|
}, {
|
|
type: Host
|
|
}] }, { type: undefined, decorators: [{
|
|
type: Optional
|
|
}, {
|
|
type: Inject,
|
|
args: [DOCUMENT]
|
|
}] }, { type: ɵngcc3.ViewportRuler }, { type: undefined, decorators: [{
|
|
type: Optional
|
|
}, {
|
|
type: Inject,
|
|
args: [MAT_AUTOCOMPLETE_DEFAULT_OPTIONS]
|
|
}] }]; }, { position: [{
|
|
type: Input,
|
|
args: ['matAutocompletePosition']
|
|
}], autocompleteAttribute: [{
|
|
type: Input,
|
|
args: ['autocomplete']
|
|
}], autocompleteDisabled: [{
|
|
type: Input,
|
|
args: ['matAutocompleteDisabled']
|
|
}], autocomplete: [{
|
|
type: Input,
|
|
args: ['matAutocomplete']
|
|
}], connectedTo: [{
|
|
type: Input,
|
|
args: ['matAutocompleteConnectedTo']
|
|
}] }); })();
|
|
export class MatAutocompleteTrigger extends _MatAutocompleteTriggerBase {
|
|
constructor() {
|
|
super(...arguments);
|
|
this._aboveClass = 'mat-autocomplete-panel-above';
|
|
}
|
|
}
|
|
MatAutocompleteTrigger.ɵfac = /*@__PURE__*/ function () { let ɵMatAutocompleteTrigger_BaseFactory; return function MatAutocompleteTrigger_Factory(t) { return (ɵMatAutocompleteTrigger_BaseFactory || (ɵMatAutocompleteTrigger_BaseFactory = ɵngcc0.ɵɵgetInheritedFactory(MatAutocompleteTrigger)))(t || MatAutocompleteTrigger); }; }();
|
|
MatAutocompleteTrigger.ɵdir = /*@__PURE__*/ ɵngcc0.ɵɵdefineDirective({ type: MatAutocompleteTrigger, selectors: [["input", "matAutocomplete", ""], ["textarea", "matAutocomplete", ""]], hostAttrs: [1, "mat-autocomplete-trigger"], hostVars: 7, hostBindings: function MatAutocompleteTrigger_HostBindings(rf, ctx) { if (rf & 1) {
|
|
ɵngcc0.ɵɵlistener("focusin", function MatAutocompleteTrigger_focusin_HostBindingHandler() { return ctx._handleFocus(); })("blur", function MatAutocompleteTrigger_blur_HostBindingHandler() { return ctx._onTouched(); })("input", function MatAutocompleteTrigger_input_HostBindingHandler($event) { return ctx._handleInput($event); })("keydown", function MatAutocompleteTrigger_keydown_HostBindingHandler($event) { return ctx._handleKeydown($event); });
|
|
} if (rf & 2) {
|
|
ɵngcc0.ɵɵattribute("autocomplete", ctx.autocompleteAttribute)("role", ctx.autocompleteDisabled ? null : "combobox")("aria-autocomplete", ctx.autocompleteDisabled ? null : "list")("aria-activedescendant", ctx.panelOpen && ctx.activeOption ? ctx.activeOption.id : null)("aria-expanded", ctx.autocompleteDisabled ? null : ctx.panelOpen.toString())("aria-owns", ctx.autocompleteDisabled || !ctx.panelOpen ? null : ctx.autocomplete == null ? null : ctx.autocomplete.id)("aria-haspopup", !ctx.autocompleteDisabled);
|
|
} }, exportAs: ["matAutocompleteTrigger"], features: [ɵngcc0.ɵɵProvidersFeature([MAT_AUTOCOMPLETE_VALUE_ACCESSOR]), ɵngcc0.ɵɵInheritDefinitionFeature] });
|
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵngcc0.ɵsetClassMetadata(MatAutocompleteTrigger, [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: `input[matAutocomplete], textarea[matAutocomplete]`,
|
|
host: {
|
|
'class': 'mat-autocomplete-trigger',
|
|
'[attr.autocomplete]': 'autocompleteAttribute',
|
|
'[attr.role]': 'autocompleteDisabled ? null : "combobox"',
|
|
'[attr.aria-autocomplete]': 'autocompleteDisabled ? null : "list"',
|
|
'[attr.aria-activedescendant]': '(panelOpen && activeOption) ? activeOption.id : null',
|
|
'[attr.aria-expanded]': 'autocompleteDisabled ? null : panelOpen.toString()',
|
|
'[attr.aria-owns]': '(autocompleteDisabled || !panelOpen) ? null : autocomplete?.id',
|
|
'[attr.aria-haspopup]': '!autocompleteDisabled',
|
|
// Note: we use `focusin`, as opposed to `focus`, in order to open the panel
|
|
// a little earlier. This avoids issues where IE delays the focusing of the input.
|
|
'(focusin)': '_handleFocus()',
|
|
'(blur)': '_onTouched()',
|
|
'(input)': '_handleInput($event)',
|
|
'(keydown)': '_handleKeydown($event)'
|
|
},
|
|
exportAs: 'matAutocompleteTrigger',
|
|
providers: [MAT_AUTOCOMPLETE_VALUE_ACCESSOR]
|
|
}]
|
|
}], null, null); })();
|
|
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b2NvbXBsZXRlLXRyaWdnZXIuanMiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tYXRlcmlhbC9hdXRvY29tcGxldGUvYXV0b2NvbXBsZXRlLXRyaWdnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEVBQWUscUJBQXFCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRSxPQUFPLEVBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUMvRixPQUFPLEVBRUwsT0FBTyxFQUNQLGFBQWEsR0FLZCxNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUN0RCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDbkQsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsVUFBVSxFQUNWLElBQUksRUFDSixNQUFNLEVBQ04sY0FBYyxFQUNkLEtBQUssRUFDTCxNQUFNLEVBRU4sUUFBUSxFQUNSLGdCQUFnQixHQUdqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXVCLGlCQUFpQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkUsT0FBTyxFQUNMLDZCQUE2QixFQUM3Qix3QkFBd0IsRUFFeEIsd0JBQXdCLEdBQ3pCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFDLGNBQWMsRUFBRSxZQUFZLEVBQUMsTUFB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U0FBQyx5QkFBeUI7QUFDOUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7b0JBQUU7QUFnbEJOLE1BQU0sT0FBTyxzQkFBdUIsU0FBUSwyQkFBMkI7QUFDdkUsSUF0QkE7QUFDRztBQUE2QixRQXFCcEIsZ0JBQVcsR0FBRyw4QkFBOEIsQ0FBQztBQUN6RCxJQUFBLENBQUM7QUFDRDtrREF4QkMsU0FBUyxTQUFDLGtCQUNULFFBQVEsRUFBRSxtREFBbUQsa0JBQzdELElBQUksRUFBRSxzQkFDSixPQUFPLEVBQUUsMEJBQTBCLHNCQUNuQyxxQkFBcUIsRUFBRSx1QkFBdUIsc0JBQzlDO0NBQWEsRUFBRSwwQ0FBMEMsc0JBQ3pELDBCQUEwQixFQUFFLHNDQUFzQyxzQkFDbEUsOEJBQThCLEVBQUUsc0RBQXNELHNCQUN0RixzQkFBc0IsRUFBRTthQUFvRCxzQkFDNUUsa0JBQWtCLEVBQUUsZ0VBQWdFLHNCQUNwRixzQkFBc0IsRUFBRSx1QkFBdUIsc0JBQy9DLDRFQUE0RSxxQkFDNUUsa0ZBQWtGLHFCQUNsRixXQUFXLEVBQUUsZ0JBQWdCO0lBQzdCLFFBQVEsRUFBRTtRQUFjLHNCQUN4QixTQUFTLEVBQUUsc0JBQXNCLHNCQUNqQyxXQUFXLEVBQUUsd0JBQXdCLG1CQUN0QyxrQkFDRCxRQUFRLEVBQUUsd0JBQXdCLGtCQUNsQyxTQUFTLEVBQUUsQ0FBQywrQkFBK0IsQ0FBQyxjQUM3Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzswQkFDSTtBQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5pbXBvcnQge0RpcmVjdGlvbmFsaXR5fSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQge0Jvb2xlYW5JbnB1dCwgY29lcmNlQm9vbGVhblByb3BlcnR5fSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHtET1dOX0FSUk9XLCBFTlRFUiwgRVNDQVBFLCBUQUIsIFVQX0FSUk9XLCBoYXNNb2RpZmllcktleX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcbmltcG9ydCB7XG4gIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneSxcbiAgT3ZlcmxheSxcbiAgT3ZlcmxheUNvbmZpZyxcbiAgT3ZlcmxheVJlZixcbiAgUG9zaXRpb25TdHJhdGVneSxcbiAgU2Nyb2xsU3RyYXRlZ3ksXG4gIENvbm5lY3RlZFBvc2l0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XG5pbXBvcnQge19nZXRFdmVudFRhcmdldH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BsYXRmb3JtJztcbmltcG9ydCB7VGVtcGxhdGVQb3J0YWx9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wb3J0YWwnO1xuaW1wb3J0IHtWaWV3cG9ydFJ1bGVyfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7RE9DVU1FTlR9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBmb3J3YXJkUmVmLFxuICBIb3N0LFxuICBJbmplY3QsXG4gIEluamVjdGlvblRva2VuLFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIE9wdGlvbmFsLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1J9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7XG4gIF9jb3VudEdyb3VwTGFiZWxzQmVmb3JlT3B0aW9uLFxuICBfZ2V0T3B0aW9uU2Nyb2xsUG9zaXRpb24sXG4gIE1hdE9wdGlvbixcbiAgTWF0T3B0aW9uU2VsZWN0aW9uQ2hhbmdlLFxufSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jb3JlJztcbmltcG9ydCB7TUFUX0ZPUk1fRklFTEQsIE1hdEZvcm1GaWVsZH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQge2RlZmVyLCBmcm9tRXZlbnQsIG1lcmdlLCBPYnNlcnZhYmxlLCBvZiBhcyBvYnNlcnZhYmxlT2YsIFN1YmplY3QsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2RlbGF5LCBmaWx0ZXIsIG1hcCwgc3dpdGNoTWFwLCB0YWtlLCB0YXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHtcbiAgX01hdEF1dG9jb21wbGV0ZUJhc2UsXG4gIE1BVF9BVVRPQ09NUExFVEVfREVGQVVMVF9PUFRJT05TLFxuICBNYXRBdXRvY29tcGxldGVEZWZhdWx0T3B0aW9uc1xufSBmcm9tICcuL2F1dG9jb21wbGV0ZSc7XG5pbXBvcnQge19NYXRBdXRvY29tcGxldGVPcmlnaW5CYXNlfSBmcm9tICcuL2F1dG9jb21wbGV0ZS1vcmlnaW4nO1xuXG5cbi8qKiBJbmplY3Rpb24gdG9rZW4gdGhhdCBkZXRlcm1pbmVzIHRoZSBzY3JvbGwgaGFuZGxpbmcgd2hpbGUgdGhlIGF1dG9jb21wbGV0ZSBwYW5lbCBpcyBvcGVuLiAqL1xuZXhwb3J0IGNvbnN0IE1BVF9BVVRPQ09NUExFVEVfU0NST0xMX1NUUkFURUdZID1cbiAgICBuZXcgSW5qZWN0aW9uVG9rZW48KCkgPT4gU2Nyb2xsU3RyYXRlZ3k+KCdtYXQtYXV0b2NvbXBsZXRlLXNjcm9sbC1zdHJhdGVneScpO1xuXG4vKiogQGRvY3MtcHJpdmF0ZSAqL1xuZXhwb3J0IGZ1bmN0aW9uIE1BVF9BVVRPQ09NUExFVEVfU0NST0xMX1NUUkFURUdZX0ZBQ1RPUlkob3ZlcmxheTogT3ZlcmxheSk6ICgpID0+IFNjcm9sbFN0cmF0ZWd5IHtcbiAgcmV0dXJuICgpID0+IG92ZXJsYXkuc2Nyb2xsU3RyYXRlZ2llcy5yZXBvc2l0aW9uKCk7XG59XG5cbi8qKiBAZG9jcy1wcml2YXRlICovXG5leHBvcnQgY29uc3QgTUFUX0FVVE9DT01QTEVURV9TQ1JPTExfU1RSQVRFR1lfRkFDVE9SWV9QUk9WSURFUiA9IHtcbiAgcHJvdmlkZTogTUFUX0FVVE9DT01QTEVURV9TQ1JPTExfU1RSQVRFR1ksXG4gIGRlcHM6IFtPdmVybGF5XSxcbiAgdXNlRmFjdG9yeTogTUFUX0FVVE9DT01QTEVURV9TQ1JPTExfU1RSQVRFR1lfRkFDVE9SWSxcbn07XG5cbi8qKlxuICogUHJvdmlkZXIgdGhhdCBhbGxvd3MgdGhlIGF1dG9jb21wbGV0ZSB0byByZWdpc3RlciBhcyBhIENvbnRyb2xWYWx1ZUFjY2Vzc29yLlxuICogQGRvY3MtcHJpdmF0ZVxuICovXG5leHBvcnQgY29uc3QgTUFUX0FVVE9DT01QTEVURV9WQUxVRV9BQ0NFU1NPUjogYW55ID0ge1xuICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gTWF0QXV0b2NvbXBsZXRlVHJpZ2dlciksXG4gIG11bHRpOiB0cnVlXG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gZXJyb3IgdG8gYmUgdGhyb3duIHdoZW4gYXR0ZW1wdGluZyB0byB1c2UgYW4gYXV0b2NvbXBsZXRlIHRyaWdnZXIgd2l0aG91dCBhIHBhbmVsLlxuICogQGRvY3MtcHJpdmF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWF0QXV0b2NvbXBsZXRlTWlzc2luZ1BhbmVsRXJyb3IoKTogRXJyb3Ige1xuICByZXR1cm4gRXJyb3IoJ0F0dGVtcHRpbmcgdG8gb3BlbiBhbiB1bmRlZmluZWQgaW5zdGFuY2Ugb2YgYG1hdC1hdXRvY29tcGxldGVgLiAnICtcbiAgICAgICAgICAgICAgICdNYWtlIHN1cmUgdGhhdCB0aGUgaWQgcGFzc2VkIHRvIHRoZSBgbWF0QXV0b2NvbXBsZXRlYCBpcyBjb3JyZWN0IGFuZCB0aGF0ICcgK1xuICAgICAgICAgICAgICAgJ3lvdVxcJ3JlIGF0dGVtcHRpbmcgdG8gb3BlbiBpdCBhZnRlciB0aGUgbmdBZnRlckNvbnRlbnRJbml0IGhvb2suJyk7XG59XG5cbi8qKiBCYXNlIGNsYXNzIHdpdGggYWxsIG9mIHRoZSBgTWF0QXV0b2NvbXBsZXRlVHJpZ2dlcmAgZnVuY3Rpb25hbGl0eS4gKi9cbkBEaXJlY3RpdmUoKVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIF9NYXRBdXRvY29tcGxldGVUcmlnZ2VyQmFzZSBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBBZnRlclZpZXdJbml0LFxuICBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG5cbiAgcHJpdmF0ZSBfb3ZlcmxheVJlZjogT3ZlcmxheVJlZiB8IG51bGw7XG4gIHByaXZhdGUgX3BvcnRhbDogVGVtcGxhdGVQb3J0YWw7XG4gIHByaXZhdGUgX2NvbXBvbmVudERlc3Ryb3llZCA9IGZhbHNlO1xuICBwcml2YXRlIF9hdXRvY29tcGxldGVEaXNhYmxlZCA9IGZhbHNlO1xuICBwcml2YXRlIF9zY3JvbGxTdHJhdGVneTogKCkgPT4gU2Nyb2xsU3RyYXRlZ3k7XG5cbiAgLyoqIE9sZCB2YWx1ZSBvZiB0aGUgbmF0aXZlIGlucHV0LiBVc2VkIHRvIHdvcmsgYXJvdW5kIGlzc3VlcyB3aXRoIHRoZSBgaW5wdXRgIGV2ZW50IG9uIElFLiAqL1xuICBwcml2YXRlIF9wcmV2aW91c1ZhbHVlOiBzdHJpbmcgfCBudW1iZXIgfCBudWxsO1xuXG4gIC8qKiBTdHJhdGVneSB0aGF0IGlzIHVzZWQgdG8gcG9zaXRpb24gdGhlIHBhbmVsLiAqL1xuICBwcml2YXRlIF9wb3NpdGlvblN0cmF0ZWd5OiBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3k7XG5cbiAgLyoqIFdoZXRoZXIgb3Igbm90IHRoZSBsYWJlbCBzdGF0ZSBpcyBiZWluZyBvdmVycmlkZGVuLiAqL1xuICBwcml2YXRlIF9tYW51YWxseUZsb2F0aW5nTGFiZWwgPSBmYWxzZTtcblxuICAvKiogVGhlIHN1YnNjcmlwdGlvbiBmb3IgY2xvc2luZyBhY3Rpb25zIChzb21lIGFyZSBib3VuZCB0byBkb2N1bWVudCkuICovXG4gIHByaXZhdGUgX2Nsb3NpbmdBY3Rpb25zU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgLyoqIFN1YnNjcmlwdGlvbiB0byB2aWV3cG9ydCBzaXplIGNoYW5nZXMuICovXG4gIHByaXZhdGUgX3ZpZXdwb3J0U3Vic2NyaXB0aW9uID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBhdXRvY29tcGxldGUgY2FuIG9wZW4gdGhlIG5leHQgdGltZSBpdCBpcyBmb2N1c2VkLiBVc2VkIHRvIHByZXZlbnQgYSBmb2N1c2VkLFxuICAgKiBjbG9zZWQgYXV0b2NvbXBsZXRlIGZyb20gYmVpbmcgcmVvcGVuZWQgaWYgdGhlIHVzZXIgc3dpdGNoZXMgdG8gYW5vdGhlciBicm93c2VyIHRhYiBhbmQgdGhlblxuICAgKiBjb21lcyBiYWNrLlxuICAgKi9cbiAgcHJpdmF0ZSBfY2FuT3Blbk9uTmV4dEZvY3VzID0gdHJ1ZTtcblxuICAvKiogU3RyZWFtIG9mIGtleWJvYXJkIGV2ZW50cyB0aGF0IGNhbiBjbG9zZSB0aGUgcGFuZWwuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2Nsb3NlS2V5RXZlbnRTdHJlYW0gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIC8qKlxuICAgKiBFdmVudCBoYW5kbGVyIGZvciB3aGVuIHRoZSB3aW5kb3cgaXMgYmx1cnJlZC4gTmVlZHMgdG8gYmUgYW5cbiAgICogYXJyb3cgZnVuY3Rpb24gaW4gb3JkZXIgdG8gcHJlc2VydmUgdGhlIGNvbnRleHQuXG4gICAqL1xuICBwcml2YXRlIF93aW5kb3dCbHVySGFuZGxlciA9ICgpID0+IHtcbiAgICAvLyBJZiB0aGUgdXNlciBibHVycmVkIHRoZSB3aW5kb3cgd2hpbGUgdGhlIGF1dG9jb21wbGV0ZSBpcyBmb2N1c2VkLCBpdCBtZWFucyB0aGF0IGl0J2xsIGJlXG4gICAgLy8gcmVmb2N1c2VkIHdoZW4gdGhleSBjb21lIGJhY2suIEluIHRoaXMgY2FzZSB3ZSB3YW50IHRvIHNraXAgdGhlIGZpcnN0IGZvY3VzIGV2ZW50LCBpZiB0aGVcbiAgICAvLyBwYW5lIHdhcyBjbG9zZWQsIGluIG9yZGVyIHRvIGF2b2lkIHJlb3BlbmluZyBpdCB1bmludGVudGlvbmFsbHkuXG4gICAgdGhpcy5fY2FuT3Blbk9uTmV4dEZvY3VzID1cbiAgICAgICAgdGhpcy5fZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAhPT0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50IHx8IHRoaXMucGFuZWxPcGVuO1xuICB9XG5cbiAgLyoqIGBWaWV3IC0+IG1vZGVsIGNhbGxiYWNrIGNhbGxlZCB3aGVuIHZhbHVlIGNoYW5nZXNgICovXG4gIF9vbkNoYW5nZTogKHZhbHVlOiBhbnkpID0+IHZvaWQgPSAoKSA9PiB7fTtcblxuICAvKiogYFZpZXcgLT4gbW9kZWwgY2FsbGJhY2sgY2FsbGVkIHdoZW4gYXV0b2NvbXBsZXRlIGhhcyBiZWVuIHRvdWNoZWRgICovXG4gIF9vblRvdWNoZWQgPSAoKSA9PiB7fTtcblxuICAvKiogVGhlIGF1dG9jb21wbGV0ZSBwYW5lbCB0byBiZSBhdHRhY2hlZCB0byB0aGlzIHRyaWdnZXIuICovXG4gIEBJbnB1dCgnbWF0QXV0b2NvbXBsZXRlJykgYXV0b2NvbXBsZXRlOiBfTWF0QXV0b2NvbXBsZXRlQmFzZTtcblxuICAvKipcbiAgICogUG9zaXRpb24gb2YgdGhlIGF1dG9jb21wbGV0ZSBwYW5lbCByZWxhdGl2ZSB0byB0aGUgdHJpZ2dlciBlbGVtZW50LiBBIHBvc2l0aW9uIG9mIGBhdXRvYFxuICAgKiB3aWxsIHJlbmRlciB0aGUgcGFuZWwgdW5kZXJuZWF0aCB0aGUgdHJpZ2dlciBpZiB0aGVyZSBpcyBlbm91Z2ggc3BhY2UgZm9yIGl0IHRvIGZpdCBpblxuICAgKiB0aGUgdmlld3BvcnQsIG90aGVyd2lzZSB0aGUgcGFuZWwgd2lsbCBiZSBzaG93biBhYm92ZSBpdC4gSWYgdGhlIHBvc2l0aW9uIGlzIHNldCB0b1xuICAgKiBgYWJvdmVgIG9yIGBiZWxvd2AsIHRoZSBwYW5lbCB3aWxsIGFsd2F5cyBiZSBzaG93biBhYm92ZSBvciBiZWxvdyB0aGUgdHJpZ2dlci4gbm8gbWF0dGVyXG4gICAqIHdoZXRoZXIgaXQgZml0cyBjb21wbGV0ZWx5IGluIHRoZSB2aWV3cG9ydC5cbiAgICovXG4gIEBJbnB1dCgnbWF0QXV0b2NvbXBsZXRlUG9zaXRpb24nKSBwb3NpdGlvbjogJ2F1dG8nIHwgJ2Fib3ZlJyB8ICdiZWxvdycgPSAnYXV0byc7XG5cbiAgLyoqXG4gICAqIFJlZmVyZW5jZSByZWxhdGl2ZSB0byB3aGljaCB0byBwb3NpdGlvbiB0aGUgYXV0b2NvbXBsZXRlIHBhbmVsLlxuICAgKiBEZWZhdWx0cyB0byB0aGUgYXV0b2NvbXBsZXRlIHRyaWdnZXIgZWxlbWVudC5cbiAgICovXG4gIEBJbnB1dCgnbWF0QXV0b2NvbXBsZXRlQ29ubmVjdGVkVG8nKSBjb25uZWN0ZWRUbzogX01hdEF1dG9jb21wbGV0ZU9yaWdpbkJhc2U7XG5cbiAgLyoqXG4gICAqIGBhdXRvY29tcGxldGVgIGF0dHJpYnV0ZSB0byBiZSBzZXQgb24gdGhlIGlucHV0IGVsZW1lbnQuXG4gICAqIEBkb2NzLXByaXZhdGVcbiAgICovXG4gIEBJbnB1dCgnYXV0b2NvbXBsZXRlJykgYXV0b2NvbXBsZXRlQXR0cmlidXRlOiBzdHJpbmcgPSAnb2ZmJztcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgYXV0b2NvbXBsZXRlIGlzIGRpc2FibGVkLiBXaGVuIGRpc2FibGVkLCB0aGUgZWxlbWVudCB3aWxsXG4gICAqIGFjdCBhcyBhIHJlZ3VsYXIgaW5wdXQgYW5kIHRoZSB1c2VyIHdvbid0IGJlIGFibGUgdG8gb3BlbiB0aGUgcGFuZWwuXG4gICAqL1xuICBASW5wdXQoJ21hdEF1dG9jb21wbGV0ZURpc2FibGVkJylcbiAgZ2V0IGF1dG9jb21wbGV0ZURpc2FibGVkKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5fYXV0b2NvbXBsZXRlRGlzYWJsZWQ7IH1cbiAgc2V0IGF1dG9jb21wbGV0ZURpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fYXV0b2NvbXBsZXRlRGlzYWJsZWQgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfZWxlbWVudDogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PiwgcHJpdmF0ZSBfb3ZlcmxheTogT3ZlcmxheSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfem9uZTogTmdab25lLFxuICAgICAgICAgICAgICBwcml2YXRlIF9jaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgICAgICAgIEBJbmplY3QoTUFUX0FVVE9DT01QTEVURV9TQ1JPTExfU1RSQVRFR1kpIHNjcm9sbFN0cmF0ZWd5OiBhbnksXG4gICAgICAgICAgICAgIEBPcHRpb25hbCgpIHByaXZhdGUgX2RpcjogRGlyZWN0aW9uYWxpdHksXG4gICAgICAgICAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoTUFUX0ZPUk1fRklFTEQpIEBIb3N0KCkgcHJpdmF0ZSBfZm9ybUZpZWxkOiBNYXRGb3JtRmllbGQsXG4gICAgICAgICAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgX2RvY3VtZW50OiBhbnksXG4gICAgICAgICAgICAgIHByaXZhdGUgX3ZpZXdwb3J0UnVsZXI6IFZpZXdwb3J0UnVsZXIsXG4gICAgICAgICAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoTUFUX0FVVE9DT01QTEVURV9ERUZBVUxUX09QVElPTlMpXG4gICAgICAgICAgICAgIHByaXZhdGUgX2RlZmF1bHRzPzogTWF0QXV0b2NvbXBsZXRlRGVmYXVsdE9wdGlvbnMpIHtcbiAgICB0aGlzLl9zY3JvbGxTdHJhdGVneSA9IHNjcm9sbFN0cmF0ZWd5O1xuICB9XG5cbiAgLyoqIENsYXNzIHRvIGFwcGx5IHRvIHRoZSBwYW5lbCB3aGVuIGl0J3MgYWJvdmUgdGhlIGlucHV0LiAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgX2Fib3ZlQ2xhc3M6IHN0cmluZztcblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgY29uc3Qgd2luZG93ID0gdGhpcy5fZ2V0V2luZG93KCk7XG5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMuX3pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4gd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLl93aW5kb3dCbHVySGFuZGxlcikpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlc1sncG9zaXRpb24nXSAmJiB0aGlzLl9wb3NpdGlvblN0cmF0ZWd5KSB7XG4gICAgICB0aGlzLl9zZXRTdHJhdGVneVBvc2l0aW9ucyh0aGlzLl9wb3NpdGlvblN0cmF0ZWd5KTtcblxuICAgICAgaWYgKHRoaXMucGFuZWxPcGVuKSB7XG4gICAgICAgIHRoaXMuX292ZXJsYXlSZWYhLnVwZGF0ZVBvc2l0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgY29uc3Qgd2luZG93ID0gdGhpcy5fZ2V0V2luZG93KCk7XG5cbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fd2luZG93Qmx1ckhhbmRsZXIpO1xuICAgIH1cblxuICAgIHRoaXMuX3ZpZXdwb3J0U3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fY29tcG9uZW50RGVzdHJveWVkID0gdHJ1ZTtcbiAgICB0aGlzLl9kZXN0cm95UGFuZWwoKTtcbiAgICB0aGlzLl9jbG9zZUtleUV2ZW50U3RyZWFtLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKiogV2hldGhlciBvciBub3QgdGhlIGF1dG9jb21wbGV0ZSBwYW5lbCBpcyBvcGVuLiAqL1xuICBnZXQgcGFuZWxPcGVuKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9vdmVybGF5QXR0YWNoZWQgJiYgdGhpcy5hdXRvY29tcGxldGUuc2hvd1BhbmVsO1xuICB9XG4gIHByaXZhdGUgX292ZXJsYXlBdHRhY2hlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBPcGVucyB0aGUgYXV0b2NvbXBsZXRlIHN1Z2dlc3Rpb24gcGFuZWwuICovXG4gIG9wZW5QYW5lbCgpOiB2b2lkIHtcbiAgICB0aGlzLl9hdHRhY2hPdmVybGF5KCk7XG4gICAgdGhpcy5fZmxvYXRMYWJlbCgpO1xuICB9XG5cbiAgLyoqIENsb3NlcyB0aGUgYXV0b2NvbXBsZXRlIHN1Z2dlc3Rpb24gcGFuZWwuICovXG4gIGNsb3NlUGFuZWwoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVzZXRMYWJlbCgpO1xuXG4gICAgaWYgKCF0aGlzLl9vdmVybGF5QXR0YWNoZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYW5lbE9wZW4pIHtcbiAgICAgIC8vIE9ubHkgZW1pdCBpZiB0aGUgcGFuZWwgd2FzIHZpc2libGUuXG4gICAgICB0aGlzLmF1dG9jb21wbGV0ZS5jbG9zZWQuZW1pdCgpO1xuICAgIH1cblxuICAgIHRoaXMuYXV0b2NvbXBsZXRlLl9pc09wZW4gPSB0aGlzLl9vdmVybGF5QXR0YWNoZWQgPSBmYWxzZTtcblxuICAgIGlmICh0aGlzLl9vdmVybGF5UmVmICYmIHRoaXMuX292ZXJsYXlSZWYuaGFzQXR0YWNoZWQoKSkge1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZi5kZXRhY2goKTtcbiAgICAgIHRoaXMuX2Nsb3NpbmdBY3Rpb25zU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgLy8gTm90ZSB0aGF0IGluIHNvbWUgY2FzZXMgdGhpcyBjYW4gZW5kIHVwIGJlaW5nIGNhbGxlZCBhZnRlciB0aGUgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICAvLyBBZGQgYSBjaGVjayB0byBlbnN1cmUgdGhhdCB3ZSBkb24ndCB0cnkgdG8gcnVuIGNoYW5nZSBkZXRlY3Rpb24gb24gYSBkZXN0cm95ZWQgdmlldy5cbiAgICBpZiAoIXRoaXMuX2NvbXBvbmVudERlc3Ryb3llZCkge1xuICAgICAgLy8gV2UgbmVlZCB0byB0cmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb24gbWFudWFsbHksIGJlY2F1c2VcbiAgICAgIC8vIGBmcm9tRXZlbnRgIGRvZXNuJ3Qgc2VlbSB0byBkbyBpdCBhdCB0aGUgcHJvcGVyIHRpbWUuXG4gICAgICAvLyBUaGlzIGVuc3VyZXMgdGhhdCB0aGUgbGFiZWwgaXMgcmVzZXQgd2hlbiB0aGVcbiAgICAgIC8vIHVzZXIgY2xpY2tzIG91dHNpZGUuXG4gICAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHBvc2l0aW9uIG9mIHRoZSBhdXRvY29tcGxldGUgc3VnZ2VzdGlvbiBwYW5lbCB0byBlbnN1cmUgdGhhdCBpdCBmaXRzIGFsbCBvcHRpb25zXG4gICAqIHdpdGhpbiB0aGUgdmlld3BvcnQuXG4gICAqL1xuICB1cGRhdGVQb3NpdGlvbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheUF0dGFjaGVkKSB7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmIS51cGRhdGVQb3NpdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBIHN0cmVhbSBvZiBhY3Rpb25zIHRoYXQgc2hvdWxkIGNsb3NlIHRoZSBhdXRvY29tcGxldGUgcGFuZWwsIGluY2x1ZGluZ1xuICAgKiB3aGVuIGFuIG9wdGlvbiBpcyBzZWxlY3RlZCwgb24gYmx1ciwgYW5kIHdoZW4gVEFCIGlzIHByZXNzZWQuXG4gICAqL1xuICBnZXQgcGFuZWxDbG9zaW5nQWN0aW9ucygpOiBPYnNlcnZhYmxlPE1hdE9wdGlvblNlbGVjdGlvbkNoYW5nZXxudWxsPiB7XG4gICAgcmV0dXJuIG1lcmdlKFxuICAgICAgdGhpcy5vcHRpb25TZWxlY3Rpb25zLFxuICAgICAgdGhpcy5hdXRvY29tcGxldGUuX2tleU1hbmFnZXIudGFiT3V0LnBpcGUoZmlsdGVyKCgpID0+IHRoaXMuX292ZXJsYXlBdHRhY2hlZCkpLFxuICAgICAgdGhpcy5fY2xvc2VLZXlFdmVudFN0cmVhbSxcbiAgICAgIHRoaXMuX2dldE91dHNpZGVDbGlja1N0cmVhbSgpLFxuICAgICAgdGhpcy5fb3ZlcmxheVJlZiA/XG4gICAgICAgICAgdGhpcy5fb3ZlcmxheVJlZi5kZXRhY2htZW50cygpLnBpcGUoZmlsdGVyKCgpID0+IHRoaXMuX292ZXJsYXlBdHRhY2hlZCkpIDpcbiAgICAgICAgICBvYnNlcnZhYmxlT2YoKVxuICAgICkucGlwZShcbiAgICAgIC8vIE5vcm1hbGl6ZSB0aGUgb3V0cHV0IHNvIHdlIHJldHVybiBhIGNvbnNpc3RlbnQgdHlwZS5cbiAgICAgIG1hcChldmVudCA9PiBldmVudCBpbnN0YW5jZW9mIE1hdE9wdGlvblNlbGVjdGlvbkNoYW5nZSA/IGV2ZW50IDogbnVsbClcbiAgICApO1xuICB9XG5cbiAgLyoqIFN0cmVhbSBvZiBhdXRvY29tcGxldGUgb3B0aW9uIHNlbGVjdGlvbnMuICovXG4gIHJlYWRvbmx5IG9wdGlvblNlbGVjdGlvbnM6IE9ic2VydmFibGU8TWF0T3B0aW9uU2VsZWN0aW9uQ2hhbmdlPiA9IGRlZmVyKCgpID0+IHtcbiAgICBpZiAodGhpcy5hdXRvY29tcGxldGUgJiYgdGhpcy5hdXRvY29tcGxldGUub3B0aW9ucykge1xuICAgICAgcmV0dXJuIG1lcmdlKC4uLnRoaXMuYXV0b2NvbXBsZXRlLm9wdGlvbnMubWFwKG9wdGlvbiA9PiBvcHRpb24ub25TZWxlY3Rpb25DaGFuZ2UpKTtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGVyZSBhcmUgYW55IHN1YnNjcmliZXJzIGJlZm9yZSBgbmdBZnRlclZpZXdJbml0YCwgdGhlIGBhdXRvY29tcGxldGVgIHdpbGwgYmUgdW5kZWZpbmVkLlxuICAgIC8vIFJldHVybiBhIHN0cmVhbSB0aGF0IHdlJ2xsIHJlcGxhY2Ugd2l0aCB0aGUgcmVhbCBvbmUgb25jZSBldmVyeXRoaW5nIGlzIGluIHBsYWNlLlxuICAgIHJldHVybiB0aGlzLl96b25lLm9uU3RhYmxlXG4gICAgICAgIC5waXBlKHRha2UoMSksIHN3aXRjaE1hcCgoKSA9PiB0aGlzLm9wdGlvblNlbGVjdGlvbnMpKTtcbiAgfSkgYXMgT2JzZXJ2YWJsZTxNYXRPcHRpb25TZWxlY3Rpb25DaGFuZ2U+O1xuXG4gIC8qKiBUaGUgY3VycmVudGx5IGFjdGl2ZSBvcHRpb24sIGNvZXJjZWQgdG8gTWF0T3B0aW9uIHR5cGUuICovXG4gIGdldCBhY3RpdmVPcHRpb24oKTogTWF0T3B0aW9uIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuYXV0b2NvbXBsZXRlICYmIHRoaXMuYXV0b2NvbXBsZXRlLl9rZXlNYW5hZ2VyKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdXRvY29tcGxldGUuX2tleU1hbmFnZXIuYWN0aXZlSXRlbTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKiBTdHJlYW0gb2YgY2xpY2tzIG91dHNpZGUgb2YgdGhlIGF1dG9jb21wbGV0ZSBwYW5lbC4gKi9cbiAgcHJpdmF0ZSBfZ2V0T3V0c2lkZUNsaWNrU3RyZWFtKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgcmV0dXJuIG1lcmdlKFxuICAgICAgICAgICAgZnJvbUV2ZW50KHRoaXMuX2RvY3VtZW50LCAnY2xpY2snKSBhcyBPYnNlcnZhYmxlPE1vdXNlRXZlbnQ+LFxuICAgICAgICAgICAgZnJvbUV2ZW50KHRoaXMuX2RvY3VtZW50LCAnYXV4Y2xpY2snKSBhcyBPYnNlcnZhYmxlPE1vdXNlRXZlbnQ+LFxuICAgICAgICAgICAgZnJvbUV2ZW50KHRoaXMuX2RvY3VtZW50LCAndG91Y2hlbmQnKSBhcyBPYnNlcnZhYmxlPFRvdWNoRXZlbnQ+KVxuICAgICAgICAucGlwZShmaWx0ZXIoZXZlbnQgPT4ge1xuICAgICAgICAgIC8vIElmIHdlJ3JlIGluIHRoZSBTaGFkb3cgRE9NLCB0aGUgZXZlbnQgdGFyZ2V0IHdpbGwgYmUgdGhlIHNoYWRvdyByb290LCBzbyB3ZSBoYXZlIHRvXG4gICAgICAgICAgLy8gZmFsbCBiYWNrIHRvIGNoZWNrIHRoZSBmaXJzdCBlbGVtZW50IGluIHRoZSBwYXRoIG9mIHRoZSBjbGljayBldmVudC5cbiAgICAgICAgICBjb25zdCBjbGlja1RhcmdldCA9IF9nZXRFdmVudFRhcmdldDxIVE1MRWxlbWVudD4oZXZlbnQpITtcbiAgICAgICAgICBjb25zdCBmb3JtRmllbGQgPSB0aGlzLl9mb3JtRmllbGQgPyB0aGlzLl9mb3JtRmllbGQuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCA6IG51bGw7XG4gICAgICAgICAgY29uc3QgY3VzdG9tT3JpZ2luID0gdGhpcy5jb25uZWN0ZWRUbyA/IHRoaXMuY29ubmVjdGVkVG8uZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IDogbnVsbDtcblxuICAgICAgICAgIHJldHVybiB0aGlzLl9vdmVybGF5QXR0YWNoZWQgJiYgY2xpY2tUYXJnZXQgIT09IHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCAmJlxuICAgICAgICAgICAgICAoIWZvcm1GaWVsZCB8fCAhZm9ybUZpZWxkLmNvbnRhaW5zKGNsaWNrVGFyZ2V0KSkgJiZcbiAgICAgICAgICAgICAgKCFjdXN0b21PcmlnaW4gfHwgIWN1c3RvbU9yaWdpbi5jb250YWlucyhjbGlja1RhcmdldCkpICYmXG4gICAgICAgICAgICAgICghIXRoaXMuX292ZXJsYXlSZWYgJiYgIXRoaXMuX292ZXJsYXlSZWYub3ZlcmxheUVsZW1lbnQuY29udGFpbnMoY2xpY2tUYXJnZXQpKTtcbiAgICAgICAgfSkpO1xuICB9XG5cbiAgLy8gSW1wbGVtZW50ZWQgYXMgcGFydCBvZiBDb250cm9sVmFsdWVBY2Nlc3Nvci5cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgUHJvbWlzZS5yZXNvbHZlKG51bGwpLnRoZW4oKCkgPT4gdGhpcy5fc2V0VHJpZ2dlclZhbHVlKHZhbHVlKSk7XG4gIH1cblxuICAvLyBJbXBsZW1lbnRlZCBhcyBwYXJ0IG9mIENvbnRyb2xWYWx1ZUFjY2Vzc29yLlxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAodmFsdWU6IGFueSkgPT4ge30pOiB2b2lkIHtcbiAgICB0aGlzLl9vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgLy8gSW1wbGVtZW50ZWQgYXMgcGFydCBvZiBDb250cm9sVmFsdWVBY2Nlc3Nvci5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHt9KSB7XG4gICAgdGhpcy5fb25Ub3VjaGVkID0gZm47XG4gIH1cblxuICAvLyBJbXBsZW1lbnRlZCBhcyBwYXJ0IG9mIENvbnRyb2xWYWx1ZUFjY2Vzc29yLlxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICB9XG5cbiAgX2hhbmRsZUtleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBrZXlDb2RlID0gZXZlbnQua2V5Q29kZTtcblxuICAgIC8vIFByZXZlbnQgdGhlIGRlZmF1bHQgYWN0aW9uIG9uIGFsbCBlc2NhcGUga2V5IHByZXNzZXMuIFRoaXMgaXMgaGVyZSBwcmltYXJpbHkgdG8gYnJpbmcgSUVcbiAgICAvLyBpbiBsaW5lIHdpdGggb3RoZXIgYnJvd3NlcnMuIEJ5IGRlZmF1bHQsIHByZXNzaW5nIGVzY2FwZSBvbiBJRSB3aWxsIGNhdXNlIGl0IHRvIHJldmVydFxuICAgIC8vIHRoZSBpbnB1dCB2YWx1ZSB0byB0aGUgb25lIHRoYXQgaXQgaGFkIG9uIGZvY3VzLCBob3dldmVyIGl0IHdvbid0IGRpc3BhdGNoIGFueSBldmVudHNcbiAgICAvLyB3aGljaCBtZWFucyB0aGF0IHRoZSBtb2RlbCB2YWx1ZSB3aWxsIGJlIG91dCBvZiBzeW5jIHdpdGggdGhlIHZpZXcuXG4gICAgaWYgKGtleUNvZGUgPT09IEVTQ0FQRSAmJiAhaGFzTW9kaWZpZXJLZXkoZXZlbnQpKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmFjdGl2ZU9wdGlvbiAmJiBrZXlDb2RlID09PSBFTlRFUiAmJiB0aGlzLnBhbmVsT3Blbikge1xuICAgICAgdGhpcy5hY3RpdmVPcHRpb24uX3NlbGVjdFZpYUludGVyYWN0aW9uKCk7XG4gICAgICB0aGlzLl9yZXNldEFjdGl2ZUl0ZW0oKTtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmF1dG9jb21wbGV0ZSkge1xuICAgICAgY29uc3QgcHJldkFjdGl2ZUl0ZW0gPSB0aGlzLmF1dG9jb21wbGV0ZS5fa2V5TWFuYWdlci5hY3RpdmVJdGVtO1xuICAgICAgY29uc3QgaXNBcnJvd0tleSA9IGtleUNvZGUgPT09IFVQX0FSUk9XIHx8IGtleUNvZGUgPT09IERPV05fQVJST1c7XG5cbiAgICAgIGlmICh0aGlzLnBhbmVsT3BlbiB8fCBrZXlDb2RlID09PSBUQUIpIHtcbiAgICAgICAgdGhpcy5hdXRvY29tcGxldGUuX2tleU1hbmFnZXIub25LZXlkb3duKGV2ZW50KTtcbiAgICAgIH0gZWxzZSBpZiAoaXNBcnJvd0tleSAmJiB0aGlzLl9jYW5PcGVuKCkpIHtcbiAgICAgICAgdGhpcy5vcGVuUGFuZWwoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzQXJyb3dLZXkgfHwgdGhpcy5hdXRvY29tcGxldGUuX2tleU1hbmFnZXIuYWN0aXZlSXRlbSAhPT0gcHJldkFjdGl2ZUl0ZW0pIHtcbiAgICAgICAgdGhpcy5fc2Nyb2xsVG9PcHRpb24odGhpcy5hdXRvY29tcGxldGUuX2tleU1hbmFnZXIuYWN0aXZlSXRlbUluZGV4IHx8IDApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9oYW5kbGVJbnB1dChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGxldCB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBsZXQgdmFsdWU6IG51bWJlciB8IHN0cmluZyB8IG51bGwgPSB0YXJnZXQudmFsdWU7XG5cbiAgICAvLyBCYXNlZCBvbiBgTnVtYmVyVmFsdWVBY2Nlc3NvcmAgZnJvbSBmb3Jtcy5cbiAgICBpZiAodGFyZ2V0LnR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICB2YWx1ZSA9IHZhbHVlID09ICcnID8gbnVsbCA6IHBhcnNlRmxvYXQodmFsdWUpO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBpbnB1dCBoYXMgYSBwbGFjZWhvbGRlciwgSUUgd2lsbCBmaXJlIHRoZSBgaW5wdXRgIGV2ZW50IG9uIHBhZ2UgbG9hZCxcbiAgICAvLyBmb2N1cyBhbmQgYmx1ciwgaW4gYWRkaXRpb24gdG8gd2hlbiB0aGUgdXNlciBhY3R1YWxseSBjaGFuZ2VkIHRoZSB2YWx1ZS4gVG9cbiAgICAvLyBmaWx0ZXIgb3V0IGFsbCBvZiB0aGUgZXh0cmEgZXZlbnRzLCB3ZSBzYXZlIHRoZSB2YWx1ZSBvbiBmb2N1cyBhbmQgYmV0d2VlblxuICAgIC8vIGBpbnB1dGAgZXZlbnRzLCBhbmQgd2UgY2hlY2sgd2hldGhlciBpdCBjaGFuZ2VkLlxuICAgIC8vIFNlZTogaHR0cHM6Ly9jb25uZWN0Lm1pY3Jvc29mdC5jb20vSUUvZmVlZGJhY2svZGV0YWlscy84ODU3NDcvXG4gICAgaWYgKHRoaXMuX3ByZXZpb3VzVmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICB0aGlzLl9wcmV2aW91c1ZhbHVlID0gdmFsdWU7XG4gICAgICB0aGlzLl9vbkNoYW5nZSh2YWx1ZSk7XG5cbiAgICAgIGlmICh0aGlzLl9jYW5PcGVuKCkgJiYgdGhpcy5fZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZXZlbnQudGFyZ2V0KSB7XG4gICAgICAgIHRoaXMub3BlblBhbmVsKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgX2hhbmRsZUZvY3VzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5fY2FuT3Blbk9uTmV4dEZvY3VzKSB7XG4gICAgICB0aGlzLl9jYW5PcGVuT25OZXh0Rm9jdXMgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fY2FuT3BlbigpKSB7XG4gICAgICB0aGlzLl9wcmV2aW91c1ZhbHVlID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnZhbHVlO1xuICAgICAgdGhpcy5fYXR0YWNoT3ZlcmxheSgpO1xuICAgICAgdGhpcy5fZmxvYXRMYWJlbCh0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW4gXCJhdXRvXCIgbW9kZSwgdGhlIGxhYmVsIHdpbGwgYW5pbWF0ZSBkb3duIGFzIHNvb24gYXMgZm9jdXMgaXMgbG9zdC5cbiAgICogVGhpcyBjYXVzZXMgdGhlIHZhbHVlIHRvIGp1bXAgd2hlbiBzZWxlY3RpbmcgYW4gb3B0aW9uIHdpdGggdGhlIG1vdXNlLlxuICAgKiBUaGlzIG1ldGhvZCBtYW51YWxseSBmbG9hdHMgdGhlIGxhYmVsIHVudGlsIHRoZSBwYW5lbCBjYW4gYmUgY2xvc2VkLlxuICAgKiBAcGFyYW0gc2hvdWxkQW5pbWF0ZSBXaGV0aGVyIHRoZSBsYWJlbCBzaG91bGQgYmUgYW5pbWF0ZWQgd2hlbiBpdCBpcyBmbG9hdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBfZmxvYXRMYWJlbChzaG91bGRBbmltYXRlID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZm9ybUZpZWxkICYmIHRoaXMuX2Zvcm1GaWVsZC5mbG9hdExhYmVsID09PSAnYXV0bycpIHtcbiAgICAgIGlmIChzaG91bGRBbmltYXRlKSB7XG4gICAgICAgIHRoaXMuX2Zvcm1GaWVsZC5fYW5pbWF0ZUFuZExvY2tMYWJlbCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fZm9ybUZpZWxkLmZsb2F0TGFiZWwgPSAnYWx3YXlzJztcbiAgICAgIH1cblxuICAgICAgdGhpcy5fbWFudWFsbHlGbG9hdGluZ0xhYmVsID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICAvKiogSWYgdGhlIGxhYmVsIGhhcyBiZWVuIG1hbnVhbGx5IGVsZXZhdGVkLCByZXR1cm4gaXQgdG8gaXRzIG5vcm1hbCBzdGF0ZS4gKi9cbiAgcHJpdmF0ZSBfcmVzZXRMYWJlbCgpOiB2b2lkICB7XG4gICAgaWYgKHRoaXMuX21hbnVhbGx5RmxvYXRpbmdMYWJlbCkge1xuICAgICAgdGhpcy5fZm9ybUZpZWxkLmZsb2F0TGFiZWwgPSAnYXV0byc7XG4gICAgICB0aGlzLl9tYW51YWxseUZsb2F0aW5nTGFiZWwgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgbGlzdGVucyB0byBhIHN0cmVhbSBvZiBwYW5lbCBjbG9zaW5nIGFjdGlvbnMgYW5kIHJlc2V0cyB0aGVcbiAgICogc3RyZWFtIGV2ZXJ5IHRpbWUgdGhlIG9wdGlvbiBsaXN0IGNoYW5nZXMuXG4gICAqL1xuICBwcml2YXRlIF9zdWJzY3JpYmVUb0Nsb3NpbmdBY3Rpb25zKCk6IFN1YnNjcmlwdGlvbiB7XG4gICAgY29uc3QgZmlyc3RTdGFibGUgPSB0aGlzLl96b25lLm9uU3RhYmxlLnBpcGUodGFrZSgxKSk7XG4gICAgY29uc3Qgb3B0aW9uQ2hhbmdlcyA9IHRoaXMuYXV0b2NvbXBsZXRlLm9wdGlvbnMuY2hhbmdlcy5waXBlKFxuICAgICAgdGFwKCgpID0+IHRoaXMuX3Bvc2l0aW9uU3RyYXRlZ3kucmVhcHBseUxhc3RQb3NpdGlvbigpKSxcbiAgICAgIC8vIERlZmVyIGVtaXR0aW5nIHRvIHRoZSBzdHJlYW0gdW50aWwgdGhlIG5leHQgdGljaywgYmVjYXVzZSBjaGFuZ2luZ1xuICAgICAgLy8gYmluZGluZ3MgaW4gaGVyZSB3aWxsIGNhdXNlIFwiY2hhbmdlZCBhZnRlciBjaGVja2VkXCIgZXJyb3JzLlxuICAgICAgZGVsYXkoMClcbiAgICApO1xuXG4gICAgLy8gV2hlbiB0aGUgem9uZSBpcyBzdGFibGUgaW5pdGlhbGx5LCBhbmQgd2hlbiB0aGUgb3B0aW9uIGxpc3QgY2hhbmdlcy4uLlxuICAgIHJldHVybiBtZXJnZShmaXJzdFN0YWJsZSwgb3B0aW9uQ2hhbmdlcylcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAvLyBjcmVhdGUgYSBuZXcgc3RyZWFtIG9mIHBhbmVsQ2xvc2luZ0FjdGlvbnMsIHJlcGxhY2luZyBhbnkgcHJldmlvdXMgc3RyZWFtc1xuICAgICAgICAgICAgLy8gdGhhdCB3ZXJlIGNyZWF0ZWQsIGFuZCBmbGF0dGVuIGl0IHNvIG91ciBzdHJlYW0gb25seSBlbWl0cyBjbG9zaW5nIGV2ZW50cy4uLlxuICAgICAgICAgICAgc3dpdGNoTWFwKCgpID0+IHtcbiAgICAgICAgICAgICAgY29uc3Qgd2FzT3BlbiA9IHRoaXMucGFuZWxPcGVuO1xuICAgICAgICAgICAgICB0aGlzLl9yZXNldEFjdGl2ZUl0ZW0oKTtcbiAgICAgICAgICAgICAgdGhpcy5hdXRvY29tcGxldGUuX3NldFZpc2liaWxpdHkoKTtcblxuICAgICAgICAgICAgICBpZiAodGhpcy5wYW5lbE9wZW4pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9vdmVybGF5UmVmIS51cGRhdGVQb3NpdGlvbigpO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGBwYW5lbE9wZW5gIHN0YXRlIGNoYW5nZWQsIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHRvIGVtaXQgdGhlIGBvcGVuZWRgXG4gICAgICAgICAgICAgICAgLy8gZXZlbnQsIGJlY2F1c2Ugd2UgbWF5IG5vdCBoYXZlIGVtaXR0ZWQgaXQgd2hlbiB0aGUgcGFuZWwgd2FzIGF0dGFjaGVkLiBUaGlzXG4gICAgICAgICAgICAgICAgLy8gY2FuIGhhcHBlbiBpZiB0aGUgdXNlcnMgb3BlbnMgdGhlIHBhbmVsIGFuZCB0aGVyZSBhcmUgbm8gb3B0aW9ucywgYnV0IHRoZVxuICAgICAgICAgICAgICAgIC8vIG9wdGlvbnMgY29tZSBpbiBzbGlnaHRseSBsYXRlciBvciBhcyBhIHJlc3VsdCBvZiB0aGUgdmFsdWUgY2hhbmdpbmcuXG4gICAgICAgICAgICAgICAgaWYgKHdhc09wZW4gIT09IHRoaXMucGFuZWxPcGVuKSB7XG4gICAgICAgICAgICAgICAgICB0aGlzLmF1dG9jb21wbGV0ZS5vcGVuZWQuZW1pdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhbmVsQ2xvc2luZ0FjdGlvbnM7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIC8vIHdoZW4gdGhlIGZpcnN0IGNsb3NpbmcgZXZlbnQgb2NjdXJzLi4uXG4gICAgICAgICAgICB0YWtlKDEpKVxuICAgICAgICAvLyBzZXQgdGhlIHZhbHVlLCBjbG9zZSB0aGUgcGFuZWwsIGFuZCBjb21wbGV0ZS5cbiAgICAgICAgLnN1YnNjcmliZShldmVudCA9PiB0aGlzLl9zZXRWYWx1ZUFuZENsb3NlKGV2ZW50KSk7XG4gIH1cblxuICAvKiogRGVzdHJveXMgdGhlIGF1dG9jb21wbGV0ZSBzdWdnZXN0aW9uIHBhbmVsLiAqL1xuICBwcml2YXRlIF9kZXN0cm95UGFuZWwoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX292ZXJsYXlSZWYpIHtcbiAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZi5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9zZXRUcmlnZ2VyVmFsdWUodmFsdWU6IGFueSk6IHZvaWQge1xuICAgIGNvbnN0IHRvRGlzcGxheSA9IHRoaXMuYXV0b2NvbXBsZXRlICYmIHRoaXMuYXV0b2NvbXBsZXRlLmRpc3BsYXlXaXRoID9cbiAgICAgIHRoaXMuYXV0b2NvbXBsZXRlLmRpc3BsYXlXaXRoKHZhbHVlKSA6XG4gICAgICB2YWx1ZTtcblxuICAgIC8vIFNpbXBseSBmYWxsaW5nIGJhY2sgdG8gYW4gZW1wdHkgc3RyaW5nIGlmIHRoZSBkaXNwbGF5IHZhbHVlIGlzIGZhbHN5IGRvZXMgbm90IHdvcmsgcHJvcGVybHkuXG4gICAgLy8gVGhlIGRpc3BsYXkgdmFsdWUgY2FuIGFsc28gYmUgdGhlIG51bWJlciB6ZXJvIGFuZCBzaG91bGRuJ3QgZmFsbCBiYWNrIHRvIGFuIGVtcHR5IHN0cmluZy5cbiAgICBjb25zdCBpbnB1dFZhbHVlID0gdG9EaXNwbGF5ICE9IG51bGwgPyB0b0Rpc3BsYXkgOiAnJztcblxuICAgIC8vIElmIGl0J3MgdXNlZCB3aXRoaW4gYSBgTWF0Rm9ybUZpZWxkYCwgd2Ugc2hvdWxkIHNldCBpdCB0aHJvdWdoIHRoZSBwcm9wZXJ0eSBzbyBpdCBjYW4gZ29cbiAgICAvLyB0aHJvdWdoIGNoYW5nZSBkZXRlY3Rpb24uXG4gICAgaWYgKHRoaXMuX2Zvcm1GaWVsZCkge1xuICAgICAgdGhpcy5fZm9ybUZpZWxkLl9jb250cm9sLnZhbHVlID0gaW5wdXRWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnZhbHVlID0gaW5wdXRWYWx1ZTtcbiAgICB9XG5cbiAgICB0aGlzLl9wcmV2aW91c1ZhbHVlID0gaW5wdXRWYWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBjbG9zZXMgdGhlIHBhbmVsLCBhbmQgaWYgYSB2YWx1ZSBpcyBzcGVjaWZpZWQsIGFsc28gc2V0cyB0aGUgYXNzb2NpYXRlZFxuICAgKiBjb250cm9sIHRvIHRoYXQgdmFsdWUuIEl0IHdpbGwgYWxzbyBtYXJrIHRoZSBjb250cm9sIGFzIGRpcnR5IGlmIHRoaXMgaW50ZXJhY3Rpb25cbiAgICogc3RlbW1lZCBmcm9tIHRoZSB1c2VyLlxuICAgKi9cbiAgcHJpdmF0ZSBfc2V0VmFsdWVBbmRDbG9zZShldmVudDogTWF0T3B0aW9uU2VsZWN0aW9uQ2hhbmdlIHwgbnVsbCk6IHZvaWQge1xuICAgIGlmIChldmVudCAmJiBldmVudC5zb3VyY2UpIHtcbiAgICAgIHRoaXMuX2NsZWFyUHJldmlvdXNTZWxlY3RlZE9wdGlvbihldmVudC5zb3VyY2UpO1xuICAgICAgdGhpcy5fc2V0VHJpZ2dlclZhbHVlKGV2ZW50LnNvdXJjZS52YWx1ZSk7XG4gICAgICB0aGlzLl9vbkNoYW5nZShldmVudC5zb3VyY2UudmFsdWUpO1xuICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgICB0aGlzLmF1dG9jb21wbGV0ZS5fZW1pdFNlbGVjdEV2ZW50KGV2ZW50LnNvdXJjZSk7XG4gICAgfVxuXG4gICAgdGhpcy5jbG9zZVBhbmVsKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgYW55IHByZXZpb3VzIHNlbGVjdGVkIG9wdGlvbiBhbmQgZW1pdCBhIHNlbGVjdGlvbiBjaGFuZ2UgZXZlbnQgZm9yIHRoaXMgb3B0aW9uXG4gICAqL1xuICBwcml2YXRlIF9jbGVhclByZXZpb3VzU2VsZWN0ZWRPcHRpb24oc2tpcDogTWF0T3B0aW9uKSB7XG4gICAgdGhpcy5hdXRvY29tcGxldGUub3B0aW9ucy5mb3JFYWNoKG9wdGlvbiA9PiB7XG4gICAgICBpZiAob3B0aW9uICE9PSBza2lwICYmIG9wdGlvbi5zZWxlY3RlZCkge1xuICAgICAgICBvcHRpb24uZGVzZWxlY3QoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2F0dGFjaE92ZXJsYXkoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmF1dG9jb21wbGV0ZSAmJiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSkge1xuICAgICAgdGhyb3cgZ2V0TWF0QXV0b2NvbXBsZXRlTWlzc2luZ1BhbmVsRXJyb3IoKTtcbiAgICB9XG5cbiAgICBsZXQgb3ZlcmxheVJlZiA9IHRoaXMuX292ZXJsYXlSZWY7XG5cbiAgICBpZiAoIW92ZXJsYXlSZWYpIHtcbiAgICAgIHRoaXMuX3BvcnRhbCA9IG5ldyBUZW1wbGF0ZVBvcnRhbCh0aGlzLmF1dG9jb21wbGV0ZS50ZW1wbGF0ZSxcbiAgICAgICAgdGhpcy5fdmlld0NvbnRhaW5lclJlZixcbiAgICAgICAge2lkOiB0aGlzLl9mb3JtRmllbGQ/LmdldExhYmVsSWQoKX0pO1xuICAgICAgb3ZlcmxheVJlZiA9IHRoaXMuX292ZXJsYXkuY3JlYXRlKHRoaXMuX2dldE92ZXJsYXlDb25maWcoKSk7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gb3ZlcmxheVJlZjtcblxuICAgICAgLy8gVXNlIHRoZSBga2V5ZG93bkV2ZW50c2AgaW4gb3JkZXIgdG8gdGFrZSBhZHZhbnRhZ2Ugb2ZcbiAgICAgIC8vIHRoZSBvdmVybGF5IGV2ZW50IHRhcmdldGluZyBwcm92aWRlZCBieSB0aGUgQ0RLIG92ZXJsYXkuXG4gICAgICBvdmVybGF5UmVmLmtleWRvd25FdmVudHMoKS5zdWJzY3JpYmUoZXZlbnQgPT4ge1xuICAgICAgICAvLyBDbG9zZSB3aGVuIHByZXNzaW5nIEVTQ0FQRSBvciBBTFQgKyBVUF9BUlJPVywgYmFzZWQgb24gdGhlIGExMXkgZ3VpZGVsaW5lcy5cbiAgICAgICAgLy8gU2VlOiBodHRwczovL3d3dy53My5vcmcvVFIvd2FpLWFyaWEtcHJhY3RpY2VzLTEuMS8jdGV4dGJveC1rZXlib2FyZC1pbnRlcmFjdGlvblxuICAgICAgICBpZiAoKGV2ZW50LmtleUNvZGUgPT09IEVTQ0FQRSAmJiAhaGFzTW9kaWZpZXJLZXkoZXZlbnQpKSB8fFxuICAgICAgICAgICAgKGV2ZW50LmtleUNvZGUgPT09IFVQX0FSUk9XICYmIGhhc01vZGlmaWVyS2V5KGV2ZW50LCAnYWx0S2V5JykpKSB7XG4gICAgICAgICAgdGhpcy5fY2xvc2VLZXlFdmVudFN0cmVhbS5uZXh0KCk7XG4gICAgICAgICAgdGhpcy5fcmVzZXRBY3RpdmVJdGVtKCk7XG5cbiAgICAgICAgICAvLyBXZSBuZWVkIHRvIHN0b3AgcHJvcGFnYXRpb24sIG90aGVyd2lzZSB0aGUgZXZlbnQgd2lsbCBldmVudHVhbGx5XG4gICAgICAgICAgLy8gcmVhY2ggdGhlIGlucHV0IGl0c2VsZiBhbmQgY2F1c2UgdGhlIG92ZXJsYXkgdG8gYmUgcmVvcGVuZWQuXG4gICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuX3ZpZXdwb3J0U3Vic2NyaXB0aW9uID0gdGhpcy5fdmlld3BvcnRSdWxlci5jaGFuZ2UoKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5wYW5lbE9wZW4gJiYgb3ZlcmxheVJlZikge1xuICAgICAgICAgIG92ZXJsYXlSZWYudXBkYXRlU2l6ZSh7d2lkdGg6IHRoaXMuX2dldFBhbmVsV2lkdGgoKX0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVXBkYXRlIHRoZSB0cmlnZ2VyLCBwYW5lbCB3aWR0aCBhbmQgZGlyZWN0aW9uLCBpbiBjYXNlIGFueXRoaW5nIGhhcyBjaGFuZ2VkLlxuICAgICAgdGhpcy5fcG9zaXRpb25TdHJhdGVneS5zZXRPcmlnaW4odGhpcy5fZ2V0Q29ubmVjdGVkRWxlbWVudCgpKTtcbiAgICAgIG92ZXJsYXlSZWYudXBkYXRlU2l6ZSh7d2lkdGg6IHRoaXMuX2dldFBhbmVsV2lkdGgoKX0pO1xuICAgIH1cblxuICAgIGlmIChvdmVybGF5UmVmICYmICFvdmVybGF5UmVmLmhhc0F0dGFjaGVkKCkpIHtcbiAgICAgIG92ZXJsYXlSZWYuYXR0YWNoKHRoaXMuX3BvcnRhbCk7XG4gICAgICB0aGlzLl9jbG9zaW5nQWN0aW9uc1N1YnNjcmlwdGlvbiA9IHRoaXMuX3N1YnNjcmliZVRvQ2xvc2luZ0FjdGlvbnMoKTtcbiAgICB9XG5cbiAgICBjb25zdCB3YXNPcGVuID0gdGhpcy5wYW5lbE9wZW47XG5cbiAgICB0aGlzLmF1dG9jb21wbGV0ZS5fc2V0VmlzaWJpbGl0eSgpO1xuICAgIHRoaXMuYXV0b2NvbXBsZXRlLl9pc09wZW4gPSB0aGlzLl9vdmVybGF5QXR0YWNoZWQgPSB0cnVlO1xuXG4gICAgLy8gV2UgbmVlZCB0byBkbyBhbiBleHRyYSBgcGFuZWxPcGVuYCBjaGVjayBpbiBoZXJlLCBiZWNhdXNlIHRoZVxuICAgIC8vIGF1dG9jb21wbGV0ZSB3b24ndCBiZSBzaG93biBpZiB0aGVyZSBhcmUgbm8gb3B0aW9ucy5cbiAgICBpZiAodGhpcy5wYW5lbE9wZW4gJiYgd2FzT3BlbiAhPT0gdGhpcy5wYW5lbE9wZW4pIHtcbiAgICAgIHRoaXMuYXV0b2NvbXBsZXRlLm9wZW5lZC5lbWl0KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0T3ZlcmxheUNvbmZpZygpOiBPdmVybGF5Q29uZmlnIHtcbiAgICByZXR1cm4gbmV3IE92ZXJsYXlDb25maWcoe1xuICAgICAgcG9zaXRpb25TdHJhdGVneTogdGhpcy5fZ2V0T3ZlcmxheVBvc2l0aW9uKCksXG4gICAgICBzY3JvbGxTdHJhdGVneTogdGhpcy5fc2Nyb2xsU3RyYXRlZ3koKSxcbiAgICAgIHdpZHRoOiB0aGlzLl9nZXRQYW5lbFdpZHRoKCksXG4gICAgICBkaXJlY3Rpb246IHRoaXMuX2RpcixcbiAgICAgIHBhbmVsQ2xhc3M6IHRoaXMuX2RlZmF1bHRzPy5vdmVybGF5UGFuZWxDbGFzcyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2dldE92ZXJsYXlQb3NpdGlvbigpOiBQb3NpdGlvblN0cmF0ZWd5IHtcbiAgICBjb25zdCBzdHJhdGVneSA9IHRoaXMuX292ZXJsYXkucG9zaXRpb24oKVxuICAgICAgLmZsZXhpYmxlQ29ubmVjdGVkVG8odGhpcy5fZ2V0Q29ubmVjdGVkRWxlbWVudCgpKVxuICAgICAgLndpdGhGbGV4aWJsZURpbWVuc2lvbnMoZmFsc2UpXG4gICAgICAud2l0aFB1c2goZmFsc2UpO1xuXG4gICAgdGhpcy5fc2V0U3RyYXRlZ3lQb3NpdGlvbnMoc3RyYXRlZ3kpO1xuICAgIHRoaXMuX3Bvc2l0aW9uU3RyYXRlZ3kgPSBzdHJhdGVneTtcbiAgICByZXR1cm4gc3RyYXRlZ3k7XG4gIH1cblxuICAvKiogU2V0cyB0aGUgcG9zaXRpb25zIG9uIGEgcG9zaXRpb24gc3RyYXRlZ3kgYmFzZWQgb24gdGhlIGRpcmVjdGl2ZSdzIGlucHV0IHN0YXRlLiAqL1xuICBwcml2YXRlIF9zZXRTdHJhdGVneVBvc2l0aW9ucyhwb3NpdGlvblN0cmF0ZWd5OiBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kpIHtcbiAgICAvLyBOb3RlIHRoYXQgd2UgcHJvdmlkZSBob3Jpem9udGFsIGZhbGxiYWNrIHBvc2l0aW9ucywgZXZlbiB0aG91Z2ggYnkgZGVmYXVsdCB0aGUgZHJvcGRvd25cbiAgICAvLyB3aWR0aCBtYXRjaGVzIHRoZSBpbnB1dCwgYmVjYXVzZSBjb25zdW1lcnMgY2FuIG92ZXJyaWRlIHRoZSB3aWR0aC4gU2VlICMxODg1NC5cbiAgICBjb25zdCBiZWxvd1Bvc2l0aW9uczogQ29ubmVjdGVkUG9zaXRpb25bXSA9IFtcbiAgICAgIHtvcmlnaW5YOiAnc3RhcnQnLCBvcmlnaW5ZOiAnYm90dG9tJywgb3ZlcmxheVg6ICdzdGFydCcsIG92ZXJsYXlZOiAndG9wJ30sXG4gICAgICB7b3JpZ2luWDogJ2VuZCcsIG9yaWdpblk6ICdib3R0b20nLCBvdmVybGF5WDogJ2VuZCcsIG92ZXJsYXlZOiAndG9wJ31cbiAgICBdO1xuXG4gICAgLy8gVGhlIG92ZXJsYXkgZWRnZSBjb25uZWN0ZWQgdG8gdGhlIHRyaWdnZXIgc2hvdWxkIGhhdmUgc3F1YXJlZCBjb3JuZXJzLCB3aGlsZVxuICAgIC8vIHRoZSBvcHBvc2l0ZSBlbmQgaGFzIHJvdW5kZWQgY29ybmVycy4gV2UgYXBwbHkgYSBDU1MgY2xhc3MgdG8gc3dhcCB0aGVcbiAgICAvLyBib3JkZXItcmFkaXVzIGJhc2VkIG9uIHRoZSBvdmVybGF5IHBvc2l0aW9uLlxuICAgIGNvbnN0IHBhbmVsQ2xhc3MgPSB0aGlzLl9hYm92ZUNsYXNzO1xuICAgIGNvbnN0IGFib3ZlUG9zaXRpb25zOiBDb25uZWN0ZWRQb3NpdGlvbltdID0gW1xuICAgICAge29yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICd0b3AnLCBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICdib3R0b20nLCBwYW5lbENsYXNzfSxcbiAgICAgIHtvcmlnaW5YOiAnZW5kJywgb3JpZ2luWTogJ3RvcCcsIG92ZXJsYXlYOiAnZW5kJywgb3ZlcmxheVk6ICdib3R0b20nLCBwYW5lbENsYXNzfVxuICAgIF07XG5cbiAgICBsZXQgcG9zaXRpb25zOiBDb25uZWN0ZWRQb3NpdGlvbltdO1xuXG4gICAgaWYgKHRoaXMucG9zaXRpb24gPT09ICdhYm92ZScpIHtcbiAgICAgIHBvc2l0aW9ucyA9IGFib3ZlUG9zaXRpb25zO1xuICAgIH0gZWxzZSBpZiAodGhpcy5wb3NpdGlvbiA9PT0gJ2JlbG93Jykge1xuICAgICAgcG9zaXRpb25zID0gYmVsb3dQb3NpdGlvbnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBvc2l0aW9ucyA9IFsuLi5iZWxvd1Bvc2l0aW9ucywgLi4uYWJvdmVQb3NpdGlvbnNdO1xuICAgIH1cblxuICAgIHBvc2l0aW9uU3RyYXRlZ3kud2l0aFBvc2l0aW9ucyhwb3NpdGlvbnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0Q29ubmVjdGVkRWxlbWVudCgpOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiB7XG4gICAgaWYgKHRoaXMuY29ubmVjdGVkVG8pIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbm5lY3RlZFRvLmVsZW1lbnRSZWY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2Zvcm1GaWVsZCA/IHRoaXMuX2Zvcm1GaWVsZC5nZXRDb25uZWN0ZWRPdmVybGF5T3JpZ2luKCkgOiB0aGlzLl9lbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0UGFuZWxXaWR0aCgpOiBudW1iZXIgfCBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmF1dG9jb21wbGV0ZS5wYW5lbFdpZHRoIHx8IHRoaXMuX2dldEhvc3RXaWR0aCgpO1xuICB9XG5cbiAgLyoqIFJldHVybnMgdGhlIHdpZHRoIG9mIHRoZSBpbnB1dCBlbGVtZW50LCBzbyB0aGUgcGFuZWwgd2lkdGggY2FuIG1hdGNoIGl0LiAqL1xuICBwcml2YXRlIF9nZXRIb3N0V2lkdGgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0Q29ubmVjdGVkRWxlbWVudCgpLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBhY3RpdmUgaXRlbSB0byAtMSBzbyBhcnJvdyBldmVudHMgd2lsbCBhY3RpdmF0ZSB0aGVcbiAgICogY29ycmVjdCBvcHRpb25zLCBvciB0byAwIGlmIHRoZSBjb25zdW1lciBvcHRlZCBpbnRvIGl0LlxuICAgKi9cbiAgcHJpdmF0ZSBfcmVzZXRBY3RpdmVJdGVtKCk6IHZvaWQge1xuICAgIGNvbnN0IGF1dG9jb21wbGV0ZSA9IHRoaXMuYXV0b2NvbXBsZXRlO1xuXG4gICAgaWYgKGF1dG9jb21wbGV0ZS5hdXRvQWN0aXZlRmlyc3RPcHRpb24pIHtcbiAgICAgIC8vIE5vdGUgdGhhdCB3ZSBnbyB0aHJvdWdoIGBzZXRGaXJzdEl0ZW1BY3RpdmVgLCByYXRoZXIgdGhhbiBgc2V0QWN0aXZlSXRlbSgwKWAsIGJlY2F1c2VcbiAgICAgIC8vIHRoZSBmb3JtZXIgd2lsbCBmaW5kIHRoZSBuZXh0IGVuYWJsZWQgb3B0aW9uLCBpZiB0aGUgZmlyc3Qgb25lIGlzIGRpc2FibGVkLlxuICAgICAgYXV0b2NvbXBsZXRlLl9rZXlNYW5hZ2VyLnNldEZpcnN0SXRlbUFjdGl2ZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhdXRvY29tcGxldGUuX2tleU1hbmFnZXIuc2V0QWN0aXZlSXRlbSgtMSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIERldGVybWluZXMgd2hldGhlciB0aGUgcGFuZWwgY2FuIGJlIG9wZW5lZC4gKi9cbiAgcHJpdmF0ZSBfY2FuT3BlbigpOiBib29sZWFuIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgIHJldHVybiAhZWxlbWVudC5yZWFkT25seSAmJiAhZWxlbWVudC5kaXNhYmxlZCAmJiAhdGhpcy5fYXV0b2NvbXBsZXRlRGlzYWJsZWQ7XG4gIH1cblxuICAvKiogVXNlIGRlZmF1bHRWaWV3IG9mIGluamVjdGVkIGRvY3VtZW50IGlmIGF2YWlsYWJsZSBvciBmYWxsYmFjayB0byBnbG9iYWwgd2luZG93IHJlZmVyZW5jZSAqL1xuICBwcml2YXRlIF9nZXRXaW5kb3coKTogV2luZG93IHtcbiAgICByZXR1cm4gdGhpcy5fZG9jdW1lbnQ/LmRlZmF1bHRWaWV3IHx8IHdpbmRvdztcbiAgfVxuXG4gIC8qKiBTY3JvbGxzIHRvIGEgcGFydGljdWxhciBvcHRpb24gaW4gdGhlIGxpc3QuICovXG4gIHByaXZhdGUgX3Njcm9sbFRvT3B0aW9uKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBHaXZlbiB0aGF0IHdlIGFyZSBub3QgYWN0dWFsbHkgZm9jdXNpbmcgYWN0aXZlIG9wdGlvbnMsIHdlIG11c3QgbWFudWFsbHkgYWRqdXN0IHNjcm9sbFxuICAgIC8vIHRvIHJldmVhbCBvcHRpb25zIGJlbG93IHRoZSBmb2xkLiBGaXJzdCwgd2UgZmluZCB0aGUgb2Zmc2V0IG9mIHRoZSBvcHRpb24gZnJvbSB0aGUgdG9wXG4gICAgLy8gb2YgdGhlIHBhbmVsLiBJZiB0aGF0IG9mZnNldCBpcyBiZWxvdyB0aGUgZm9sZCwgdGhlIG5ldyBzY3JvbGxUb3Agd2lsbCBiZSB0aGUgb2Zmc2V0IC1cbiAgICAvLyB0aGUgcGFuZWwgaGVpZ2h0ICsgdGhlIG9wdGlvbiBoZWlnaHQsIHNvIHRoZSBhY3RpdmUgb3B0aW9uIHdpbGwgYmUganVzdCB2aXNpYmxlIGF0IHRoZVxuICAgIC8vIGJvdHRvbSBvZiB0aGUgcGFuZWwuIElmIHRoYXQgb2Zmc2V0IGlzIGFib3ZlIHRoZSB0b3Agb2YgdGhlIHZpc2libGUgcGFuZWwsIHRoZSBuZXcgc2Nyb2xsVG9wXG4gICAgLy8gd2lsbCBiZWNvbWUgdGhlIG9mZnNldC4gSWYgdGhhdCBvZmZzZXQgaXMgdmlzaWJsZSB3aXRoaW4gdGhlIHBhbmVsIGFscmVhZHksIHRoZSBzY3JvbGxUb3AgaXNcbiAgICAvLyBub3QgYWRqdXN0ZWQuXG4gICAgY29uc3QgYXV0b2NvbXBsZXRlID0gdGhpcy5hdXRvY29tcGxldGU7XG4gICAgY29uc3QgbGFiZWxDb3VudCA9IF9jb3VudEdyb3VwTGFiZWxzQmVmb3JlT3B0aW9uKGluZGV4LFxuICAgICAgYXV0b2NvbXBsZXRlLm9wdGlvbnMsIGF1dG9jb21wbGV0ZS5vcHRpb25Hcm91cHMpO1xuXG4gICAgaWYgKGluZGV4ID09PSAwICYmIGxhYmVsQ291bnQgPT09IDEpIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGdvdCBvbmUgZ3JvdXAgbGFiZWwgYmVmb3JlIHRoZSBvcHRpb24gYW5kIHdlJ3JlIGF0IHRoZSB0b3Agb3B0aW9uLFxuICAgICAgLy8gc2Nyb2xsIHRoZSBsaXN0IHRvIHRoZSB0b3AuIFRoaXMgaXMgYmV0dGVyIFVYIHRoYW4gc2Nyb2xsaW5nIHRoZSBsaXN0IHRvIHRoZVxuICAgICAgLy8gdG9wIG9mIHRoZSBvcHRpb24sIGJlY2F1c2UgaXQgYWxsb3dzIHRoZSB1c2VyIHRvIHJlYWQgdGhlIHRvcCBncm91cCdzIGxhYmVsLlxuICAgICAgYXV0b2NvbXBsZXRlLl9zZXRTY3JvbGxUb3AoMCk7XG4gICAgfSBlbHNlIGlmIChhdXRvY29tcGxldGUucGFuZWwpIHtcbiAgICAgIGNvbnN0IG9wdGlvbiA9IGF1dG9jb21wbGV0ZS5vcHRpb25zLnRvQXJyYXkoKVtpbmRleF07XG5cbiAgICAgIGlmIChvcHRpb24pIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IG9wdGlvbi5fZ2V0SG9zdEVsZW1lbnQoKTtcbiAgICAgICAgY29uc3QgbmV3U2Nyb2xsUG9zaXRpb24gPSBfZ2V0T3B0aW9uU2Nyb2xsUG9zaXRpb24oXG4gICAgICAgICAgZWxlbWVudC5vZmZzZXRUb3AsXG4gICAgICAgICAgZWxlbWVudC5vZmZzZXRIZWlnaHQsXG4gICAgICAgICAgYXV0b2NvbXBsZXRlLl9nZXRTY3JvbGxUb3AoKSxcbiAgICAgICAgICBhdXRvY29tcGxldGUucGFuZWwubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHRcbiAgICAgICAgKTtcblxuICAgICAgICBhdXRvY29tcGxldGUuX3NldFNjcm9sbFRvcChuZXdTY3JvbGxQb3NpdGlvbik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX2F1dG9jb21wbGV0ZURpc2FibGVkOiBCb29sZWFuSW5wdXQ7XG59XG5cblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiBgaW5wdXRbbWF0QXV0b2NvbXBsZXRlXSwgdGV4dGFyZWFbbWF0QXV0b2NvbXBsZXRlXWAsXG4gIGhvc3Q6IHtcbiAgICAnY2xhc3MnOiAnbWF0LWF1dG9jb21wbGV0ZS10cmlnZ2VyJyxcbiAgICAnW2F0dHIuYXV0b2NvbXBsZXRlXSc6ICdhdXRvY29tcGxldGVBdHRyaWJ1dGUnLFxuICAgICdbYXR0ci5yb2xlXSc6ICdhdXRvY29tcGxldGVEaXNhYmxlZCA/IG51bGwgOiBcImNvbWJvYm94XCInLFxuICAgICdbYXR0ci5hcmlhLWF1dG9jb21wbGV0ZV0nOiAnYXV0b2NvbXBsZXRlRGlzYWJsZWQgPyBudWxsIDogXCJsaXN0XCInLFxuICAgICdbYXR0ci5hcmlhLWFjdGl2ZWRlc2NlbmRhbnRdJzogJyhwYW5lbE9wZW4gJiYgYWN0aXZlT3B0aW9uKSA/IGFjdGl2ZU9wdGlvbi5pZCA6IG51bGwnLFxuICAgICdbYXR0ci5hcmlhLWV4cGFuZGVkXSc6ICdhdXRvY29tcGxldGVEaXNhYmxlZCA/IG51bGwgOiBwYW5lbE9wZW4udG9TdHJpbmcoKScsXG4gICAgJ1thdHRyLmFyaWEtb3duc10nOiAnKGF1dG9jb21wbGV0ZURpc2FibGVkIHx8ICFwYW5lbE9wZW4pID8gbnVsbCA6IGF1dG9jb21wbGV0ZT8uaWQnLFxuICAgICdbYXR0ci5hcmlhLWhhc3BvcHVwXSc6ICchYXV0b2NvbXBsZXRlRGlzYWJsZWQnLFxuICAgIC8vIE5vdGU6IHdlIHVzZSBgZm9jdXNpbmAsIGFzIG9wcG9zZWQgdG8gYGZvY3VzYCwgaW4gb3JkZXIgdG8gb3BlbiB0aGUgcGFuZWxcbiAgICAvLyBhIGxpdHRsZSBlYXJsaWVyLiBUaGlzIGF2b2lkcyBpc3N1ZXMgd2hlcmUgSUUgZGVsYXlzIHRoZSBmb2N1c2luZyBvZiB0aGUgaW5wdXQuXG4gICAgJyhmb2N1c2luKSc6ICdfaGFuZGxlRm9jdXMoKScsXG4gICAgJyhibHVyKSc6ICdfb25Ub3VjaGVkKCknLFxuICAgICcoaW5wdXQpJzogJ19oYW5kbGVJbnB1dCgkZXZlbnQpJyxcbiAgICAnKGtleWRvd24pJzogJ19oYW5kbGVLZXlkb3duKCRldmVudCknLFxuICB9LFxuICBleHBvcnRBczogJ21hdEF1dG9jb21wbGV0ZVRyaWdnZXInLFxuICBwcm92aWRlcnM6IFtNQVRfQVVUT0NPTVBMRVRFX1ZBTFVFX0FDQ0VTU09SXVxufSlcbmV4cG9ydCBjbGFzcyBNYXRBdXRvY29tcGxldGVUcmlnZ2VyIGV4dGVuZHMgX01hdEF1dG9jb21wbGV0ZVRyaWdnZXJCYXNlIHtcbiAgcHJvdGVjdGVkIF9hYm92ZUNsYXNzID0gJ21hdC1hdXRvY29tcGxldGUtcGFuZWwtYWJvdmUnO1xufVxuIl19
|