/**
* @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 { FocusKeyManager } from '@angular/cdk/a11y';
import { Directionality } from '@angular/cdk/bidi';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, ElementRef, Input, Optional, QueryList, ViewEncapsulation, } from '@angular/core';
import { mixinTabIndex } from '@angular/material/core';
import { merge, Subject } from 'rxjs';
import { startWith, switchMap, takeUntil } from 'rxjs/operators';
import { MatChip } from './chip';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/bidi";
/**
* Boilerplate for applying mixins to MatChipSet.
* @docs-private
*/
class MatChipSetBase {
constructor(_elementRef) { }
}
const _MatChipSetMixinBase = mixinTabIndex(MatChipSetBase);
/**
* Basic container component for the MatChip component.
*
* Extended by MatChipListbox and MatChipGrid for different interaction patterns.
*/
export class MatChipSet extends _MatChipSetMixinBase {
/** Combined stream of all of the child chips' focus events. */
get chipFocusChanges() {
return this._getChipStream(chip => chip._onFocus);
}
/** Combined stream of all of the child chips' remove events. */
get chipDestroyedChanges() {
return this._getChipStream(chip => chip.destroyed);
}
/** Whether the chip set is disabled. */
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = coerceBooleanProperty(value);
this._syncChipsState();
}
/** Whether the chip list contains chips or not. */
get empty() {
return !this._chips || this._chips.length === 0;
}
/** The ARIA role applied to the chip set. */
get role() {
if (this._explicitRole) {
return this._explicitRole;
}
return this.empty ? null : this._defaultRole;
}
set role(value) {
this._explicitRole = value;
}
/** Whether any of the chips inside of this chip-set has focus. */
get focused() {
return this._hasFocusedChip();
}
constructor(_elementRef, _changeDetectorRef, _dir) {
super(_elementRef);
this._elementRef = _elementRef;
this._changeDetectorRef = _changeDetectorRef;
this._dir = _dir;
/** Index of the last destroyed chip that had focus. */
this._lastDestroyedFocusedChipIndex = null;
/** Subject that emits when the component has been destroyed. */
this._destroyed = new Subject();
/** Role to use if it hasn't been overwritten by the user. */
this._defaultRole = 'presentation';
this._disabled = false;
this._explicitRole = null;
/** Flat list of all the actions contained within the chips. */
this._chipActions = new QueryList();
}
ngAfterViewInit() {
this._setUpFocusManagement();
this._trackChipSetChanges();
this._trackDestroyedFocusedChip();
}
ngOnDestroy() {
this._keyManager?.destroy();
this._chipActions.destroy();
this._destroyed.next();
this._destroyed.complete();
}
/** Checks whether any of the chips is focused. */
_hasFocusedChip() {
return this._chips && this._chips.some(chip => chip._hasFocus());
}
/** Syncs the chip-set's state with the individual chips. */
_syncChipsState() {
if (this._chips) {
this._chips.forEach(chip => {
chip.disabled = this._disabled;
chip._changeDetectorRef.markForCheck();
});
}
}
/** Dummy method for subclasses to override. Base chip set cannot be focused. */
focus() { }
/** Handles keyboard events on the chip set. */
_handleKeydown(event) {
if (this._originatesFromChip(event)) {
this._keyManager.onKeydown(event);
}
}
/**
* Utility to ensure all indexes are valid.
*
* @param index The index to be checked.
* @returns True if the index is valid for our list of chips.
*/
_isValidIndex(index) {
return index >= 0 && index < this._chips.length;
}
/**
* Removes the `tabindex` from the chip set and resets it back afterwards, allowing the
* user to tab out of it. This prevents the set from capturing focus and redirecting
* it back to the first chip, creating a focus trap, if it user tries to tab away.
*/
_allowFocusEscape() {
if (this.tabIndex !== -1) {
const previousTabIndex = this.tabIndex;
this.tabIndex = -1;
// Note that this needs to be a `setTimeout`, because a `Promise.resolve`
// doesn't allow enough time for the focus to escape.
setTimeout(() => (this.tabIndex = previousTabIndex));
}
}
/**
* Gets a stream of events from all the chips within the set.
* The stream will automatically incorporate any newly-added chips.
*/
_getChipStream(mappingFunction) {
return this._chips.changes.pipe(startWith(null), switchMap(() => merge(...this._chips.map(mappingFunction))));
}
/** Checks whether an event comes from inside a chip element. */
_originatesFromChip(event) {
let currentElement = event.target;
while (currentElement && currentElement !== this._elementRef.nativeElement) {
if (currentElement.classList.contains('mat-mdc-chip')) {
return true;
}
currentElement = currentElement.parentElement;
}
return false;
}
/** Sets up the chip set's focus management logic. */
_setUpFocusManagement() {
// Create a flat `QueryList` containing the actions of all of the chips.
// This allows us to navigate both within the chip and move to the next/previous
// one using the existing `ListKeyManager`.
this._chips.changes.pipe(startWith(this._chips)).subscribe((chips) => {
const actions = [];
chips.forEach(chip => chip._getActions().forEach(action => actions.push(action)));
this._chipActions.reset(actions);
this._chipActions.notifyOnChanges();
});
this._keyManager = new FocusKeyManager(this._chipActions)
.withVerticalOrientation()
.withHorizontalOrientation(this._dir ? this._dir.value : 'ltr')
.withHomeAndEnd()
.skipPredicate(action => this._skipPredicate(action));
// Keep the manager active index in sync so that navigation picks
// up from the current chip if the user clicks into the list directly.
this.chipFocusChanges.pipe(takeUntil(this._destroyed)).subscribe(({ chip }) => {
const action = chip._getSourceAction(document.activeElement);
if (action) {
this._keyManager.updateActiveItem(action);
}
});
this._dir?.change
.pipe(takeUntil(this._destroyed))
.subscribe(direction => this._keyManager.withHorizontalOrientation(direction));
}
/**
* Determines if key manager should avoid putting a given chip action in the tab index. Skip
* non-interactive and disabled actions since the user can't do anything with them.
*/
_skipPredicate(action) {
// Skip chips that the user cannot interact with. `mat-chip-set` does not permit focusing disabled
// chips.
return !action.isInteractive || action.disabled;
}
/** Listens to changes in the chip set and syncs up the state of the individual chips. */
_trackChipSetChanges() {
this._chips.changes.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
if (this.disabled) {
// Since this happens after the content has been
// checked, we need to defer it to the next tick.
Promise.resolve().then(() => this._syncChipsState());
}
this._redirectDestroyedChipFocus();
});
}
/** Starts tracking the destroyed chips in order to capture the focused one. */
_trackDestroyedFocusedChip() {
this.chipDestroyedChanges.pipe(takeUntil(this._destroyed)).subscribe((event) => {
const chipArray = this._chips.toArray();
const chipIndex = chipArray.indexOf(event.chip);
// If the focused chip is destroyed, save its index so that we can move focus to the next
// chip. We only save the index here, rather than move the focus immediately, because we want
// to wait until the chip is removed from the chip list before focusing the next one. This
// allows us to keep focus on the same index if the chip gets swapped out.
if (this._isValidIndex(chipIndex) && event.chip._hasFocus()) {
this._lastDestroyedFocusedChipIndex = chipIndex;
}
});
}
/**
* Finds the next appropriate chip to move focus to,
* if the currently-focused chip is destroyed.
*/
_redirectDestroyedChipFocus() {
if (this._lastDestroyedFocusedChipIndex == null) {
return;
}
if (this._chips.length) {
const newIndex = Math.min(this._lastDestroyedFocusedChipIndex, this._chips.length - 1);
const chipToFocus = this._chips.toArray()[newIndex];
if (chipToFocus.disabled) {
// If we're down to one disabled chip, move focus back to the set.
if (this._chips.length === 1) {
this.focus();
}
else {
this._keyManager.setPreviousItemActive();
}
}
else {
chipToFocus.focus();
}
}
else {
this.focus();
}
this._lastDestroyedFocusedChipIndex = null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: MatChipSet, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.1", type: MatChipSet, selector: "mat-chip-set", inputs: { disabled: "disabled", role: "role" }, host: { listeners: { "keydown": "_handleKeydown($event)" }, properties: { "attr.role": "role" }, classAttribute: "mat-mdc-chip-set mdc-evolution-chip-set" }, queries: [{ propertyName: "_chips", predicate: MatChip, descendants: true }], usesInheritance: true, ngImport: i0, template: `
`, isInline: true, styles: [".mdc-evolution-chip-set{display:flex}.mdc-evolution-chip-set:focus{outline:none}.mdc-evolution-chip-set__chips{display:flex;flex-flow:wrap;min-width:0}.mdc-evolution-chip-set--overflow .mdc-evolution-chip-set__chips{flex-flow:nowrap}.mdc-evolution-chip-set .mdc-evolution-chip-set__chips{margin-left:-8px;margin-right:0}[dir=rtl] .mdc-evolution-chip-set .mdc-evolution-chip-set__chips,.mdc-evolution-chip-set .mdc-evolution-chip-set__chips[dir=rtl]{margin-left:0;margin-right:-8px}.mdc-evolution-chip-set .mdc-evolution-chip{margin-left:8px;margin-right:0}[dir=rtl] .mdc-evolution-chip-set .mdc-evolution-chip,.mdc-evolution-chip-set .mdc-evolution-chip[dir=rtl]{margin-left:0;margin-right:8px}.mdc-evolution-chip-set .mdc-evolution-chip{margin-top:4px;margin-bottom:4px}.mat-mdc-chip-set .mdc-evolution-chip-set__chips{min-width:100%}.mat-mdc-chip-set-stacked{flex-direction:column;align-items:flex-start}.mat-mdc-chip-set-stacked .mat-mdc-chip{width:100%}.mat-mdc-chip-set-stacked .mdc-evolution-chip__graphic{flex-grow:0}.mat-mdc-chip-set-stacked .mdc-evolution-chip__action--primary{flex-basis:100%;justify-content:start}input.mat-mdc-chip-input{flex:1 0 150px;margin-left:8px}[dir=rtl] input.mat-mdc-chip-input{margin-left:0;margin-right:8px}"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.1", ngImport: i0, type: MatChipSet, decorators: [{
type: Component,
args: [{ selector: 'mat-chip-set', template: `
`, host: {
'class': 'mat-mdc-chip-set mdc-evolution-chip-set',
'(keydown)': '_handleKeydown($event)',
'[attr.role]': 'role',
}, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".mdc-evolution-chip-set{display:flex}.mdc-evolution-chip-set:focus{outline:none}.mdc-evolution-chip-set__chips{display:flex;flex-flow:wrap;min-width:0}.mdc-evolution-chip-set--overflow .mdc-evolution-chip-set__chips{flex-flow:nowrap}.mdc-evolution-chip-set .mdc-evolution-chip-set__chips{margin-left:-8px;margin-right:0}[dir=rtl] .mdc-evolution-chip-set .mdc-evolution-chip-set__chips,.mdc-evolution-chip-set .mdc-evolution-chip-set__chips[dir=rtl]{margin-left:0;margin-right:-8px}.mdc-evolution-chip-set .mdc-evolution-chip{margin-left:8px;margin-right:0}[dir=rtl] .mdc-evolution-chip-set .mdc-evolution-chip,.mdc-evolution-chip-set .mdc-evolution-chip[dir=rtl]{margin-left:0;margin-right:8px}.mdc-evolution-chip-set .mdc-evolution-chip{margin-top:4px;margin-bottom:4px}.mat-mdc-chip-set .mdc-evolution-chip-set__chips{min-width:100%}.mat-mdc-chip-set-stacked{flex-direction:column;align-items:flex-start}.mat-mdc-chip-set-stacked .mat-mdc-chip{width:100%}.mat-mdc-chip-set-stacked .mdc-evolution-chip__graphic{flex-grow:0}.mat-mdc-chip-set-stacked .mdc-evolution-chip__action--primary{flex-basis:100%;justify-content:start}input.mat-mdc-chip-input{flex:1 0 150px;margin-left:8px}[dir=rtl] input.mat-mdc-chip-input{margin-left:0;margin-right:8px}"] }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1.Directionality, decorators: [{
type: Optional
}] }]; }, propDecorators: { disabled: [{
type: Input
}], role: [{
type: Input
}], _chips: [{
type: ContentChildren,
args: [MatChip, {
// We need to use `descendants: true`, because Ivy will no longer match
// indirect descendants if it's left as false.
descendants: true,
}]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hpcC1zZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbWF0ZXJpYWwvY2hpcHMvY2hpcC1zZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ2xELE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEVBQWUscUJBQXFCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRSxPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsZUFBZSxFQUNmLFVBQVUsRUFDVixLQUFLLEVBRUwsUUFBUSxFQUNSLFNBQVMsRUFDVCxpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFjLGFBQWEsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xFLE9BQU8sRUFBQyxLQUFLLEVBQWMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQy9ELE9BQU8sRUFBQyxPQUFPLEVBQWUsTUFBTSxRQUFRLENBQUM7OztBQUc3Qzs7O0dBR0c7QUFDSCxNQUFlLGNBQWM7SUFFM0IsWUFBWSxXQUF1QixJQUFHLENBQUM7Q0FDeEM7QUFDRCxNQUFNLG9CQUFvQixHQUFHLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUUzRDs7OztHQUlHO0FBaUJILE1BQU0sT0FBTyxVQUNYLFNBQVEsb0JBQW9CO0lBZTVCLCtEQUErRDtJQUMvRCxJQUFJLGdCQUFnQjtRQUNsQixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELGdFQUFnRTtJQUNo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Q0FBQztZQUVwRCxJQUFJLFdBQVcsQ0FBQyxRQUFRLEVBQUU7Z0JBQ3hCLGtFQUFrRTtnQkFDbEUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7b0JBQzVCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztpQkFDZDtxQkFBTTtvQkFDTCxJQUFJLENBQUMsV0FBVyxDQUFDLHFCQUFxQixFQUFFLENBQUM7aUJBQzFDO2FBQ0Y7aUJBQU07Z0JBQ0wsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQ3JCO1NBQ0Y7YUFBTTtZQUNMLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUNkO1FBRUQsSUFBSSxDQUFDLDhCQUE4QixHQUFHLElBQUksQ0FBQztJQUM3QyxDQUFDOzhHQS9RVSxVQUFVO2tHQUFWLFVBQVUseVJBK0RKLE9BQU8sdUVBN0VkOzs7O0dBSVQ7OzJGQVVVLFVBQVU7a0JBaEJ0QixTQUFTOytCQUNFLGNBQWMsWUFDZDs7OztHQUlULFFBRUs7d0JBQ0osT0FBTyxFQUFFLHlDQUF5Qzt3QkFDbEQsV0FBVyxFQUFFLHdCQUF3Qjt3QkFDckMsYUFBYSxFQUFFLE1BQU07cUJBQ3RCLGlCQUNjLGlCQUFpQixDQUFDLElBQUksbUJBQ3BCLHVCQUF1QixDQUFDLE1BQU07OzBCQThFNUMsUUFBUTs0Q0FoRFAsUUFBUTtzQkFEWCxLQUFLO2dCQWlCRixJQUFJO3NCQURQLEtBQUs7Z0JBeUJOLE1BQU07c0JBTEwsZUFBZTt1QkFBQyxPQUFPLEVBQUU7d0JBQ3hCLHVFQUF1RTt3QkFDdkUsOENBQThDO3dCQUM5QyxXQUFXLEVBQUUsSUFBSTtxQkFDbEIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtGb2N1c0tleU1hbmFnZXJ9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7RGlyZWN0aW9uYWxpdHl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9iaWRpJztcbmltcG9ydCB7Qm9vbGVhbklucHV0LCBjb2VyY2VCb29sZWFuUHJvcGVydHl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBFbGVtZW50UmVmLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgUXVlcnlMaXN0LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0hhc1RhYkluZGV4LCBtaXhpblRhYkluZGV4fSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jb3JlJztcbmltcG9ydCB7bWVyZ2UsIE9ic2VydmFibGUsIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtzdGFydFdpdGgsIHN3aXRjaE1hcCwgdGFrZVVudGlsfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge01hdENoaXAsIE1hdENoaXBFdmVudH0gZnJvbSAnLi9jaGlwJztcbmltcG9ydCB7TWF0Q2hpcEFjdGlvbn0gZnJvbSAnLi9jaGlwLWFjdGlvbic7XG5cbi8qKlxuICogQm9pbGVycGxhdGUgZm9yIGFwcGx5aW5nIG1peGlucyB0byBNYXRDaGlwU2V0LlxuICogQGRvY3MtcHJpdmF0ZVxuICovXG5hYnN0cmFjdCBjbGFzcyBNYXRDaGlwU2V0QmFzZSB7XG4gIGFic3RyYWN0IGRpc2FibGVkOiBib29sZWFuO1xuICBjb25zdHJ1Y3RvcihfZWxlbWVudFJlZjogRWxlbWVudFJlZikge31cbn1cbmNvbnN0IF9NYXRDaGlwU2V0TWl4aW5CYXNlID0gbWl4aW5UYWJJbmRleChNYXRDaGlwU2V0QmFzZSk7XG5cbi8qKlxuICogQmFzaWMgY29udGFpbmVyIGNvbXBvbmVudCBmb3IgdGhlIE1hdENoaXAgY29tcG9uZW50LlxuICpcbiAqIEV4dGVuZGVkIGJ5IE1hdENoaXBMaXN0Ym94IGFuZCBNYXRDaGlwR3JpZCBmb3IgZGlmZmVyZW50IGludGVyYWN0aW9uIHBhdHRlcm5zLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdtYXQtY2hpcC1zZXQnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJtZGMtZXZvbHV0aW9uLWNoaXAtc2V0X19jaGlwc1wiIHJvbGU9XCJwcmVzZW50YXRpb25cIj5cbiAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJ2NoaXAtc2V0LmNzcyddLFxuICBob3N0OiB7XG4gICAgJ2NsYXNzJzogJ21hdC1tZGMtY2hpcC1zZXQgbWRjLWV2b2x1dGlvbi1jaGlwLXNldCcsXG4gICAgJyhrZXlkb3duKSc6ICdfaGFuZGxlS2V5ZG93bigkZXZlbnQpJyxcbiAgICAnW2F0dHIucm9sZV0nOiAncm9sZScsXG4gIH0sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBNYXRDaGlwU2V0XG4gIGV4dGVuZHMgX01hdENoaXBTZXRNaXhpbkJhc2VcbiAgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBIYXNUYWJJbmRleCwgT25EZXN0cm95XG57XG4gIC8qKiBJbmRleCBvZiB0aGUgbGFzdCBkZXN0cm95ZWQgY2hpcCB0aGF0IGhhZCBmb2N1cy4gKi9cbiAgcHJpdmF0ZSBfbGFzdERlc3Ryb3llZEZvY3VzZWRDaGlwSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBVc2VkIHRvIG1hbmFnZSBmb2N1cyB3aXRoaW4gdGhlIGNoaXAgbGlzdC4gKi9cbiAgcHJvdGVjdGVkIF9rZXlNYW5hZ2VyOiBGb2N1c0tleU1hbmFnZXI8TWF0Q2hpcEFjdGlvbj47XG5cbiAgLyoqIFN1YmplY3QgdGhhdCBlbWl0cyB3aGVuIHRoZSBjb21wb25lbnQgaGFzIGJlZW4gZGVzdHJveWVkLiAqL1xuICBwcm90ZWN0ZWQgX2Rlc3Ryb3llZCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgLyoqIFJvbGUgdG8gdXNlIGlmIGl0IGhhc24ndCBiZWVuIG92ZXJ3cml0dGVuIGJ5IHRoZSB1c2VyLiAqL1xuICBwcm90ZWN0ZWQgX2RlZmF1bHRSb2xlID0gJ3ByZXNlbnRhdGlvbic7XG5cbiAgLyoqIENvbWJpbmVkIHN0cmVhbSBvZiBhbGwgb2YgdGhlIGNoaWxkIGNoaXBzJyBmb2N1cyBldmVudHMuICovXG4gIGdldCBjaGlwRm9jdXNDaGFuZ2VzKCk6IE9ic2VydmFibGU8TWF0Q2hpcEV2ZW50PiB7XG4gICAgcmV0dXJuIHRoaXMuX2dldENoaXBTdHJlYW0oY2hpcCA9PiBjaGlwLl9vbkZvY3VzKTtcbiAgfVxuXG4gIC8qKiBDb21iaW5lZCBzdHJlYW0gb2YgYWxsIG9mIHRoZSBjaGlsZCBjaGlwcycgcmVtb3ZlIGV2ZW50cy4gKi9cbiAgZ2V0IGNoaXBEZXN0cm95ZWRDaGFuZ2VzKCk6IE9ic2VydmFibGU8TWF0Q2hpcEV2ZW50PiB7XG4gICAgcmV0dXJuIHRoaXMuX2dldENoaXBTdHJlYW0oY2hpcCA9PiBjaGlwLmRlc3Ryb3llZCk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgY2hpcCBzZXQgaXMgZGlzYWJsZWQuICovXG4gIEBJbnB1dCgpXG4gIGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZGlzYWJsZWQ7XG4gIH1cbiAgc2V0IGRpc2FibGVkKHZhbHVlOiBCb29sZWFuSW5wdXQpIHtcbiAgICB0aGlzLl9kaXNhYmxlZCA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gICAgdGhpcy5fc3luY0NoaXBzU3RhdGUoKTtcbiAgfVxuICBwcm90ZWN0ZWQgX2Rpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGNoaXAgbGlzdCBjb250YWlucyBjaGlwcyBvciBub3QuICovXG4gIGdldCBlbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMuX2NoaXBzIHx8IHRoaXMuX2NoaXBzLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIC8qKiBUaGUgQVJJQSByb2xlIGFwcGxpZWQgdG8gdGhlIGNoaXAgc2V0LiAqL1xuICBASW5wdXQoKVxuICBnZXQgcm9sZSgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAodGhpcy5fZXhwbGljaXRSb2xlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZXhwbGljaXRSb2xlO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmVtcHR5ID8gbnVsbCA6IHRoaXMuX2RlZmF1bHRSb2xlO1xuICB9XG5cbiAgc2V0IHJvbGUodmFsdWU6IHN0cmluZyB8IG51bGwpIHtcbiAgICB0aGlzLl9leHBsaWNpdFJvbGUgPSB2YWx1ZTtcbiAgfVxuICBwcml2YXRlIF9leHBsaWNpdFJvbGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBXaGV0aGVyIGFueSBvZiB0aGUgY2hpcHMgaW5zaWRlIG9mIHRoaXMgY2hpcC1zZXQgaGFzIGZvY3VzLiAqL1xuICBnZXQgZm9jdXNlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faGFzRm9jdXNlZENoaXAoKTtcbiAgfVxuXG4gIC8qKiBUaGUgY2hpcHMgdGhhdCBhcmUgcGFydCBvZiB0aGlzIGNoaXAgc2V0LiAqL1xuICBAQ29udGVudENoaWxkcmVuKE1hdENoaXAsIHtcbiAgICAvLyBXZSBuZWVkIHRvIHVzZSBgZGVzY2VuZGFudHM6IHRydWVgLCBiZWNhdXNlIEl2eSB3aWxsIG5vIGxvbmdlciBtYXRjaFxuICAgIC8vIGluZGlyZWN0IGRlc2NlbmRhbnRzIGlmIGl0J3MgbGVmdCBhcyBmYWxzZS5cbiAgICBkZXNjZW5kYW50czogdHJ1ZSxcbiAgfSlcbiAgX2NoaXBzOiBRdWVyeUxpc3Q8TWF0Q2hpcD47XG5cbiAgLyoqIEZsYXQgbGlzdCBvZiBhbGwgdGhlIGFjdGlvbnMgY29udGFpbmVkIHdpdGhpbiB0aGUgY2hpcHMuICovXG4gIF9jaGlwQWN0aW9ucyA9IG5ldyBRdWVyeUxpc3Q8TWF0Q2hpcEFjdGlvbj4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICAgIHByb3RlY3RlZCBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgX2RpcjogRGlyZWN0aW9uYWxpdHksXG4gICkge1xuICAgIHN1cGVyKF9lbGVtZW50UmVmKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLl9zZXRVcEZvY3VzTWFuYWdlbWVudCgpO1xuICAgIHRoaXMuX3RyYWNrQ2hpcFNldENoYW5nZXMoKTtcbiAgICB0aGlzLl90cmFja0Rlc3Ryb3llZEZvY3VzZWRDaGlwKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLl9rZXlNYW5hZ2VyPy5kZXN0cm95KCk7XG4gICAgdGhpcy5fY2hpcEFjdGlvbnMuZGVzdHJveSgpO1xuICAgIHRoaXMuX2Rlc3Ryb3llZC5uZXh0KCk7XG4gICAgdGhpcy5fZGVzdHJveWVkLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKiogQ2hlY2tzIHdoZXRoZXIgYW55IG9mIHRoZSBjaGlwcyBpcyBmb2N1c2VkLiAqL1xuICBwcm90ZWN0ZWQgX2hhc0ZvY3VzZWRDaGlwKCkge1xuICAgIHJldHVybiB0aGlzLl9jaGlwcyAmJiB0aGlzLl9jaGlwcy5zb21lKGNoaXAgPT4gY2hpcC5faGFzRm9jdXMoKSk7XG4gIH1cblxuICAvKiogU3luY3MgdGhlIGNoaXAtc2V0J3Mgc3RhdGUgd2l0aCB0aGUgaW5kaXZpZHVhbCBjaGlwcy4gKi9cbiAgcHJvdGVjdGVkIF9zeW5jQ2hpcHNTdGF0ZSgpIHtcbiAgICBpZiAodGhpcy5fY2hpcHMpIHtcbiAgICAgIHRoaXMuX2NoaXBzLmZvckVhY2goY2hpcCA9PiB7XG4gICAgICAgIGNoaXAuZGlzYWJsZWQgPSB0aGlzLl9kaXNhYmxlZDtcbiAgICAgICAgY2hpcC5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogRHVtbXkgbWV0aG9kIGZvciBzdWJjbGFzc2VzIHRvIG92ZXJyaWRlLiBCYXNlIGNoaXAgc2V0IGNhbm5vdCBiZSBmb2N1c2VkLiAqL1xuICBmb2N1cygpIHt9XG5cbiAgLyoqIEhhbmRsZXMga2V5Ym9hcmQgZXZlbnRzIG9uIHRoZSBjaGlwIHNldC4gKi9cbiAgX2hhbmRsZUtleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICBpZiAodGhpcy5fb3JpZ2luYXRlc0Zyb21DaGlwKGV2ZW50KSkge1xuICAgICAgdGhpcy5fa2V5TWFuYWdlci5vbktleWRvd24oZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVdGlsaXR5IHRvIGVuc3VyZSBhbGwgaW5kZXhlcyBhcmUgdmFsaWQuXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gYmUgY2hlY2tlZC5cbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgaW5kZXggaXMgdmFsaWQgZm9yIG91ciBsaXN0IG9mIGNoaXBzLlxuICAgKi9cbiAgcHJvdGVjdGVkIF9pc1ZhbGlkSW5kZXgoaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpbmRleCA+PSAwICYmIGluZGV4IDwgdGhpcy5fY2hpcHMubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgdGhlIGB0YWJpbmRleGAgZnJvbSB0aGUgY2hpcCBzZXQgYW5kIHJlc2V0cyBpdCBiYWNrIGFmdGVyd2FyZHMsIGFsbG93aW5nIHRoZVxuICAgKiB1c2VyIHRvIHRhYiBvdXQgb2YgaXQuIFRoaXMgcHJldmVudHMgdGhlIHNldCBmcm9tIGNhcHR1cmluZyBmb2N1cyBhbmQgcmVkaXJlY3RpbmdcbiAgICogaXQgYmFjayB0byB0aGUgZmlyc3QgY2hpcCwgY3JlYXRpbmcgYSBmb2N1cyB0cmFwLCBpZiBpdCB1c2VyIHRyaWVzIHRvIHRhYiBhd2F5LlxuICAgKi9cbiAgcHJvdGVjdGVkIF9hbGxvd0ZvY3VzRXNjYXBlKCkge1xuICAgIGlmICh0aGlzLnRhYkluZGV4ICE9PSAtMSkge1xuICAgICAgY29uc3QgcHJldmlvdXNUYWJJbmRleCA9IHRoaXMudGFiSW5kZXg7XG4gICAgICB0aGlzLnRhYkluZGV4ID0gLTE7XG5cbiAgICAgIC8vIE5vdGUgdGhhdCB0aGlzIG5lZWRzIHRvIGJlIGEgYHNldFRpbWVvdXRgLCBiZWNhdXNlIGEgYFByb21pc2UucmVzb2x2ZWBcbiAgICAgIC8vIGRvZXNuJ3QgYWxsb3cgZW5vdWdoIHRpbWUgZm9yIHRoZSBmb2N1cyB0byBlc2NhcGUuXG4gICAgICBzZXRUaW1lb3V0KCgpID0+ICh0aGlzLnRhYkluZGV4ID0gcHJldmlvdXNUYWJJbmRleCkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGEgc3RyZWFtIG9mIGV2ZW50cyBmcm9tIGFsbCB0aGUgY2hpcHMgd2l0aGluIHRoZSBzZXQuXG4gICAqIFRoZSBzdHJlYW0gd2lsbCBhdXRvbWF0aWNhbGx5IGluY29ycG9yYXRlIGFueSBuZXdseS1hZGRlZCBjaGlwcy5cbiAgICovXG4gIHByb3RlY3RlZCBfZ2V0Q2hpcFN0cmVhbTxULCBDIGV4dGVuZHMgTWF0Q2hpcCA9IE1hdENoaXA+KFxuICAgIG1hcHBpbmdGdW5jdGlvbjogKGNoaXA6IEMpID0+IE9ic2VydmFibGU8VD4sXG4gICk6IE9ic2VydmFibGU8VD4ge1xuICAgIHJldHVybiB0aGlzLl9jaGlwcy5jaGFuZ2VzLnBpcGUoXG4gICAgICBzdGFydFdpdGgobnVsbCksXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4gbWVyZ2UoLi4uKHRoaXMuX2NoaXBzIGFzIFF1ZXJ5TGlzdDxDPikubWFwKG1hcHBpbmdGdW5jdGlvbikpKSxcbiAgICApO1xuICB9XG5cbiAgLyoqIENoZWNrcyB3aGV0aGVyIGFuIGV2ZW50IGNvbWVzIGZyb20gaW5zaWRlIGEgY2hpcCBlbGVtZW50LiAqL1xuICBwcm90ZWN0ZWQgX29yaWdpbmF0ZXNGcm9tQ2hpcChldmVudDogRXZlbnQpOiBib29sZWFuIHtcbiAgICBsZXQgY3VycmVudEVsZW1lbnQgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQgfCBudWxsO1xuXG4gICAgd2hpbGUgKGN1cnJlbnRFbGVtZW50ICYmIGN1cnJlbnRFbGVtZW50ICE9PSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIGlmIChjdXJyZW50RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ21hdC1tZGMtY2hpcCcpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgY3VycmVudEVsZW1lbnQgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKiogU2V0cyB1cCB0aGUgY2hpcCBzZXQncyBmb2N1cyBtYW5hZ2VtZW50IGxvZ2ljLiAqL1xuICBwcml2YXRlIF9zZXRVcEZvY3VzTWFuYWdlbWVudCgpIHtcbiAgICAvLyBDcmVhdGUgYSBmbGF0IGBRdWVyeUxpc3RgIGNvbnRhaW5pbmcgdGhlIGFjdGlvbnMgb2YgYWxsIG9mIHRoZSBjaGlwcy5cbiAgICAvLyBUaGlzIGFsbG93cyB1cyB0byBuYXZpZ2F0ZSBib3RoIHdpdGhpbiB0aGUgY2hpcCBhbmQgbW92ZSB0byB0aGUgbmV4dC9wcmV2aW91c1xuICAgIC8vIG9uZSB1c2luZyB0aGUgZXhpc3RpbmcgYExpc3RLZXlNYW5hZ2VyYC5cbiAgICB0aGlzLl9jaGlwcy5jaGFuZ2VzLnBpcGUoc3RhcnRXaXRoKHRoaXMuX2NoaXBzKSkuc3Vic2NyaWJlKChjaGlwczogUXVlcnlMaXN0PE1hdENoaXA+KSA9PiB7XG4gICAgICBjb25zdCBhY3Rpb25zOiBNYXRDaGlwQWN0aW9uW10gPSBbXTtcbiAgICAgIGNoaXBzLmZvckVhY2goY2hpcCA9PiBjaGlwLl9nZXRBY3Rpb25zKCkuZm9yRWFjaChhY3Rpb24gPT4gYWN0aW9ucy5wdXNoKGFjdGlvbikpKTtcbiAgICAgIHRoaXMuX2NoaXBBY3Rpb25zLnJlc2V0KGFjdGlvbnMpO1xuICAgICAgdGhpcy5fY2hpcEFjdGlvbnMubm90aWZ5T25DaGFuZ2VzKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLl9rZXlNYW5hZ2VyID0gbmV3IEZvY3VzS2V5TWFuYWdlcih0aGlzLl9jaGlwQWN0aW9ucylcbiAgICAgIC53aXRoVmVydGljYWxPcmllbnRhdGlvbigpXG4gICAgICAud2l0aEhvcml6b250YWxPcmllbnRhdGlvbih0aGlzLl9kaXIgPyB0aGlzLl9kaXIudmFsdWUgOiAnbHRyJylcbiAgICAgIC53aXRoSG9tZUFuZEVuZCgpXG4gICAgICAuc2tpcFByZWRpY2F0ZShhY3Rpb24gPT4gdGhpcy5fc2tpcFByZWRpY2F0ZShhY3Rpb24pKTtcblxuICAgIC8vIEtlZXAgdGhlIG1hbmFnZXIgYWN0aXZlIGluZGV4IGluIHN5bmMgc28gdGhhdCBuYXZpZ2F0aW9uIHBpY2tzXG4gICAgLy8gdXAgZnJvbSB0aGUgY3VycmVudCBjaGlwIGlmIHRoZSB1c2VyIGNsaWNrcyBpbnRvIHRoZSBsaXN0IGRpcmVjdGx5LlxuICAgIHRoaXMuY2hpcEZvY3VzQ2hhbmdlcy5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95ZWQpKS5zdWJzY3JpYmUoKHtjaGlwfSkgPT4ge1xuICAgICAgY29uc3QgYWN0aW9uID0gY2hpcC5fZ2V0U291cmNlQWN0aW9uKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgYXMgRWxlbWVudCk7XG5cbiAgICAgIGlmIChhY3Rpb24pIHtcbiAgICAgICAgdGhpcy5fa2V5TWFuYWdlci51cGRhdGVBY3RpdmVJdGVtKGFjdGlvbik7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLl9kaXI/LmNoYW5nZVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCkpXG4gICAgICAuc3Vic2NyaWJlKGRpcmVjdGlvbiA9PiB0aGlzLl9rZXlNYW5hZ2VyLndpdGhIb3Jpem9udGFsT3JpZW50YXRpb24oZGlyZWN0aW9uKSk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyBpZiBrZXkgbWFuYWdlciBzaG91bGQgYXZvaWQgcHV0dGluZyBhIGdpdmVuIGNoaXAgYWN0aW9uIGluIHRoZSB0YWIgaW5kZXguIFNraXBcbiAgICogbm9uLWludGVyYWN0aXZlIGFuZCBkaXNhYmxlZCBhY3Rpb25zIHNpbmNlIHRoZSB1c2VyIGNhbid0IGRvIGFueXRoaW5nIHdpdGggdGhlbS5cbiAgICovXG4gIHByb3RlY3RlZCBfc2tpcFByZWRpY2F0ZShhY3Rpb246IE1hdENoaXBBY3Rpb24pOiBib29sZWFuIHtcbiAgICAvLyBTa2lwIGNoaXBzIHRoYXQgdGhlIHVzZXIgY2Fubm90IGludGVyYWN0IHdpdGguIGBtYXQtY2hpcC1zZXRgIGRvZXMgbm90IHBlcm1pdCBmb2N1c2luZyBkaXNhYmxlZFxuICAgIC8vIGNoaXBzLlxuICAgIHJldHVybiAhYWN0aW9uLmlzSW50ZXJhY3RpdmUgfHwgYWN0aW9uLmRpc2FibGVkO1xuICB9XG5cbiAgLyoqIExpc3RlbnMgdG8gY2hhbmdlcyBpbiB0aGUgY2hpcCBzZXQgYW5kIHN5bmNzIHVwIHRoZSBzdGF0ZSBvZiB0aGUgaW5kaXZpZHVhbCBjaGlwcy4gKi9cbiAgcHJpdmF0ZSBfdHJhY2tDaGlwU2V0Q2hhbmdlcygpIHtcbiAgICB0aGlzLl9jaGlwcy5jaGFuZ2VzLnBpcGUoc3RhcnRXaXRoKG51bGwpLCB0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgIC8vIFNpbmNlIHRoaXMgaGFwcGVucyBhZnRlciB0aGUgY29udGVudCBoYXMgYmVlblxuICAgICAgICAvLyBjaGVja2VkLCB3ZSBuZWVkIHRvIGRlZmVyIGl0IHRvIHRoZSBuZXh0IHRpY2suXG4gICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gdGhpcy5fc3luY0NoaXBzU3RhdGUoKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlZGlyZWN0RGVzdHJveWVkQ2hpcEZvY3VzKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogU3RhcnRzIHRyYWNraW5nIHRoZSBkZXN0cm95ZWQgY2hpcHMgaW4gb3JkZXIgdG8gY2FwdHVyZSB0aGUgZm9jdXNlZCBvbmUuICovXG4gIHByaXZhdGUgX3RyYWNrRGVzdHJveWVkRm9jdXNlZENoaXAoKSB7XG4gICAgdGhpcy5jaGlwRGVzdHJveWVkQ2hhbmdlcy5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95ZWQpKS5zdWJzY3JpYmUoKGV2ZW50OiBNYXRDaGlwRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IGNoaXBBcnJheSA9IHRoaXMuX2NoaXBzLnRvQXJyYXkoKTtcbiAgICAgIGNvbnN0IGNoaXBJbmRleCA9IGNoaXBBcnJheS5pbmRleE9mKGV2ZW50LmNoaXApO1xuXG4gICAgICAvLyBJZiB0aGUgZm9jdXNlZCBjaGlwIGlzIGRlc3Ryb3llZCwgc2F2ZSBpdHMgaW5kZXggc28gdGhhdCB3ZSBjYW4gbW92ZSBmb2N1cyB0byB0aGUgbmV4dFxuICAgICAgLy8gY2hpcC4gV2Ugb25seSBzYXZlIHRoZSBpbmRleCBoZXJlLCByYXRoZXIgdGhhbiBtb3ZlIHRoZSBmb2N1cyBpbW1lZGlhdGVseSwgYmVjYXVzZSB3ZSB3YW50XG4gICAgICAvLyB0byB3YWl0IHVudGlsIHRoZSBjaGlwIGlzIHJlbW92ZWQgZnJvbSB0aGUgY2hpcCBsaXN0IGJlZm9yZSBmb2N1c2luZyB0aGUgbmV4dCBvbmUuIFRoaXNcbiAgICAgIC8vIGFsbG93cyB1cyB0byBrZWVwIGZvY3VzIG9uIHRoZSBzYW1lIGluZGV4IGlmIHRoZSBjaGlwIGdldHMgc3dhcHBlZCBvdXQuXG4gICAgICBpZiAodGhpcy5faXNWYWxpZEluZGV4KGNoaXBJbmRleCkgJiYgZXZlbnQuY2hpcC5faGFzRm9jdXMoKSkge1xuICAgICAgICB0aGlzLl9sYXN0RGVzdHJveWVkRm9jdXNlZENoaXBJbmRleCA9IGNoaXBJbmRleDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgbmV4dCBhcHByb3ByaWF0ZSBjaGlwIHRvIG1vdmUgZm9jdXMgdG8sXG4gICAqIGlmIHRoZSBjdXJyZW50bHktZm9jdXNlZCBjaGlwIGlzIGRlc3Ryb3llZC5cbiAgICovXG4gIHByaXZhdGUgX3JlZGlyZWN0RGVzdHJveWVkQ2hpcEZvY3VzKCkge1xuICAgIGlmICh0aGlzLl9sYXN0RGVzdHJveWVkRm9jdXNlZENoaXBJbmRleCA9PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2NoaXBzLmxlbmd0aCkge1xuICAgICAgY29uc3QgbmV3SW5kZXggPSBNYXRoLm1pbih0aGlzLl9sYXN0RGVzdHJveWVkRm9jdXNlZENoaXBJbmRleCwgdGhpcy5fY2hpcHMubGVuZ3RoIC0gMSk7XG4gICAgICBjb25zdCBjaGlwVG9Gb2N1cyA9IHRoaXMuX2NoaXBzLnRvQXJyYXkoKVtuZXdJbmRleF07XG5cbiAgICAgIGlmIChjaGlwVG9Gb2N1cy5kaXNhYmxlZCkge1xuICAgICAgICAvLyBJZiB3ZSdyZSBkb3duIHRvIG9uZSBkaXNhYmxlZCBjaGlwLCBtb3ZlIGZvY3VzIGJhY2sgdG8gdGhlIHNldC5cbiAgICAgICAgaWYgKHRoaXMuX2NoaXBzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIHRoaXMuZm9jdXMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLl9rZXlNYW5hZ2VyLnNldFByZXZpb3VzSXRlbUFjdGl2ZSgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGlwVG9Gb2N1cy5mb2N1cygpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmZvY3VzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fbGFzdERlc3Ryb3llZEZvY3VzZWRDaGlwSW5kZXggPSBudWxsO1xuICB9XG59XG4iXX0=