UNPKG

@angular/cdk

Version:

Angular Material Component Development Kit

642 lines 56.8 kB
/** * @fileoverview added by tsickle * Generated from: src/cdk/drag-drop/directives/drag.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @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 { DOCUMENT } from '@angular/common'; import { ContentChild, ContentChildren, Directive, ElementRef, EventEmitter, Inject, InjectionToken, Input, NgZone, Optional, Output, QueryList, SkipSelf, ViewContainerRef, ChangeDetectorRef, isDevMode, } from '@angular/core'; import { coerceBooleanProperty, coerceNumberProperty, coerceElement } from '@angular/cdk/coercion'; import { Observable, Subject, merge } from 'rxjs'; import { startWith, take, map, takeUntil, switchMap, tap } from 'rxjs/operators'; import { CdkDragHandle } from './drag-handle'; import { CdkDragPlaceholder } from './drag-placeholder'; import { CdkDragPreview } from './drag-preview'; import { CDK_DRAG_PARENT } from '../drag-parent'; import { DragDrop } from '../drag-drop'; /** * Injection token that is used to provide a CdkDropList instance to CdkDrag. * Used for avoiding circular imports. * @type {?} */ export const CDK_DROP_LIST = new InjectionToken('CDK_DROP_LIST'); /** * Injection token that can be used to configure the behavior of `CdkDrag`. * @type {?} */ export const CDK_DRAG_CONFIG = new InjectionToken('CDK_DRAG_CONFIG', { providedIn: 'root', factory: CDK_DRAG_CONFIG_FACTORY }); /** * \@docs-private * @return {?} */ export function CDK_DRAG_CONFIG_FACTORY() { return { dragStartThreshold: 5, pointerDirectionChangeThreshold: 5 }; } /** * Element that can be moved inside a CdkDropList container. * @template T */ export class CdkDrag { /** * @param {?} element * @param {?} dropContainer * @param {?} _document * @param {?} _ngZone * @param {?} _viewContainerRef * @param {?} config * @param {?} _dir * @param {?} dragDrop * @param {?} _changeDetectorRef */ constructor(element, dropContainer, _document, _ngZone, _viewContainerRef, config, _dir, dragDrop, _changeDetectorRef) { this.element = element; this.dropContainer = dropContainer; this._document = _document; this._ngZone = _ngZone; this._viewContainerRef = _viewContainerRef; this._dir = _dir; this._changeDetectorRef = _changeDetectorRef; this._destroyed = new Subject(); /** * Amount of milliseconds to wait after the user has put their * pointer down before starting to drag the element. */ this.dragStartDelay = 0; this._disabled = false; /** * Emits when the user starts dragging the item. */ this.started = new EventEmitter(); /** * Emits when the user has released a drag item, before any animations have started. */ this.released = new EventEmitter(); /** * Emits when the user stops dragging an item in the container. */ this.ended = new EventEmitter(); /** * Emits when the user has moved the item into a new container. */ this.entered = new EventEmitter(); /** * Emits when the user removes the item its container by dragging it into another container. */ this.exited = new EventEmitter(); /** * Emits when the user drops the item inside a container. */ this.dropped = new EventEmitter(); /** * Emits as the user is dragging the item. Use with caution, * because this event will fire for every pixel that the user has dragged. */ this.moved = new Observable((/** * @param {?} observer * @return {?} */ (observer) => { /** @type {?} */ const subscription = this._dragRef.moved.pipe(map((/** * @param {?} movedEvent * @return {?} */ movedEvent => ({ source: this, pointerPosition: movedEvent.pointerPosition, event: movedEvent.event, delta: movedEvent.delta, distance: movedEvent.distance })))).subscribe(observer); return (/** * @return {?} */ () => { subscription.unsubscribe(); }); })); this._dragRef = dragDrop.createDrag(element, config); this._dragRef.data = this; this._syncInputs(this._dragRef); this._handleEvents(this._dragRef); } /** * Whether starting to drag this element is disabled. * @return {?} */ get disabled() { return this._disabled || (this.dropContainer && this.dropContainer.disabled); } /** * @param {?} value * @return {?} */ set disabled(value) { this._disabled = coerceBooleanProperty(value); this._dragRef.disabled = this._disabled; } /** * Returns the element that is being used as a placeholder * while the current element is being dragged. * @return {?} */ getPlaceholderElement() { return this._dragRef.getPlaceholderElement(); } /** * Returns the root draggable element. * @return {?} */ getRootElement() { return this._dragRef.getRootElement(); } /** * Resets a standalone drag item to its initial position. * @return {?} */ reset() { this._dragRef.reset(); } /** * Gets the pixel coordinates of the draggable outside of a drop container. * @return {?} */ getFreeDragPosition() { return this._dragRef.getFreeDragPosition(); } /** * @return {?} */ ngAfterViewInit() { // We need to wait for the zone to stabilize, in order for the reference // element to be in the proper place in the DOM. This is mostly relevant // for draggable elements inside portals since they get stamped out in // their original DOM position and then they get transferred to the portal. this._ngZone.onStable.asObservable() .pipe(take(1), takeUntil(this._destroyed)) .subscribe((/** * @return {?} */ () => { this._updateRootElement(); // Listen for any newly-added handles. this._handles.changes.pipe(startWith(this._handles), // Sync the new handles with the DragRef. tap((/** * @param {?} handles * @return {?} */ (handles) => { /** @type {?} */ const childHandleElements = handles .filter((/** * @param {?} handle * @return {?} */ handle => handle._parentDrag === this)) .map((/** * @param {?} handle * @return {?} */ handle => handle.element)); this._dragRef.withHandles(childHandleElements); })), // Listen if the state of any of the handles changes. switchMap((/** * @param {?} handles * @return {?} */ (handles) => { return (/** @type {?} */ (merge(...handles.map((/** * @param {?} item * @return {?} */ item => { return item._stateChanges.pipe(startWith(item)); }))))); })), takeUntil(this._destroyed)).subscribe((/** * @param {?} handleInstance * @return {?} */ handleInstance => { // Enabled/disable the handle that changed in the DragRef. /** @type {?} */ const dragRef = this._dragRef; /** @type {?} */ const handle = handleInstance.element.nativeElement; handleInstance.disabled ? dragRef.disableHandle(handle) : dragRef.enableHandle(handle); })); if (this.freeDragPosition) { this._dragRef.setFreeDragPosition(this.freeDragPosition); } })); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { /** @type {?} */ const rootSelectorChange = changes['rootElementSelector']; /** @type {?} */ const positionChange = changes['freeDragPosition']; // We don't have to react to the first change since it's being // handled in `ngAfterViewInit` where it needs to be deferred. if (rootSelectorChange && !rootSelectorChange.firstChange) { this._updateRootElement(); } // Skip the first change since it's being handled in `ngAfterViewInit`. if (positionChange && !positionChange.firstChange && this.freeDragPosition) { this._dragRef.setFreeDragPosition(this.freeDragPosition); } } /** * @return {?} */ ngOnDestroy() { this._destroyed.next(); this._destroyed.complete(); this._dragRef.dispose(); } /** * Syncs the root element with the `DragRef`. * @private * @return {?} */ _updateRootElement() { /** @type {?} */ const element = this.element.nativeElement; /** @type {?} */ const rootElement = this.rootElementSelector ? getClosestMatchingAncestor(element, this.rootElementSelector) : element; if (rootElement && rootElement.nodeType !== this._document.ELEMENT_NODE) { throw Error(`cdkDrag must be attached to an element node. ` + `Currently attached to "${rootElement.nodeName}".`); } this._dragRef.withRootElement(rootElement || element); } /** * Gets the boundary element, based on the `boundaryElement` value. * @private * @return {?} */ _getBoundaryElement() { /** @type {?} */ const boundary = this.boundaryElement; if (!boundary) { return null; } if (typeof boundary === 'string') { return getClosestMatchingAncestor(this.element.nativeElement, boundary); } /** @type {?} */ const element = coerceElement(boundary); if (isDevMode() && !element.contains(this.element.nativeElement)) { throw Error('Draggable element is not inside of the node passed into cdkDragBoundary.'); } return element; } /** * Syncs the inputs of the CdkDrag with the options of the underlying DragRef. * @private * @param {?} ref * @return {?} */ _syncInputs(ref) { ref.beforeStarted.subscribe((/** * @return {?} */ () => { if (!ref.isDragging()) { /** @type {?} */ const dir = this._dir; /** @type {?} */ const dragStartDelay = this.dragStartDelay; /** @type {?} */ const placeholder = this._placeholderTemplate ? { template: this._placeholderTemplate.templateRef, context: this._placeholderTemplate.data, viewContainer: this._viewContainerRef } : null; /** @type {?} */ const preview = this._previewTemplate ? { template: this._previewTemplate.templateRef, context: this._previewTemplate.data, viewContainer: this._viewContainerRef } : null; ref.disabled = this.disabled; ref.lockAxis = this.lockAxis; ref.dragStartDelay = (typeof dragStartDelay === 'object' && dragStartDelay) ? dragStartDelay : coerceNumberProperty(dragStartDelay); ref.constrainPosition = this.constrainPosition; ref.previewClass = this.previewClass; ref .withBoundaryElement(this._getBoundaryElement()) .withPlaceholderTemplate(placeholder) .withPreviewTemplate(preview); if (dir) { ref.withDirection(dir.value); } } })); } /** * Handles the events from the underlying `DragRef`. * @private * @param {?} ref * @return {?} */ _handleEvents(ref) { ref.started.subscribe((/** * @return {?} */ () => { this.started.emit({ source: this }); // Since all of these events run outside of change detection, // we need to ensure that everything is marked correctly. this._changeDetectorRef.markForCheck(); })); ref.released.subscribe((/** * @return {?} */ () => { this.released.emit({ source: this }); })); ref.ended.subscribe((/** * @param {?} event * @return {?} */ event => { this.ended.emit({ source: this, distance: event.distance }); // Since all of these events run outside of change detection, // we need to ensure that everything is marked correctly. this._changeDetectorRef.markForCheck(); })); ref.entered.subscribe((/** * @param {?} event * @return {?} */ event => { this.entered.emit({ container: event.container.data, item: this, currentIndex: event.currentIndex }); })); ref.exited.subscribe((/** * @param {?} event * @return {?} */ event => { this.exited.emit({ container: event.container.data, item: this }); })); ref.dropped.subscribe((/** * @param {?} event * @return {?} */ event => { this.dropped.emit({ previousIndex: event.previousIndex, currentIndex: event.currentIndex, previousContainer: event.previousContainer.data, container: event.container.data, isPointerOverContainer: event.isPointerOverContainer, item: this, distance: event.distance }); })); } } CdkDrag.decorators = [ { type: Directive, args: [{ selector: '[cdkDrag]', exportAs: 'cdkDrag', host: { 'class': 'cdk-drag', '[class.cdk-drag-disabled]': 'disabled', '[class.cdk-drag-dragging]': '_dragRef.isDragging()', }, providers: [{ provide: CDK_DRAG_PARENT, useExisting: CdkDrag }] },] } ]; /** @nocollapse */ CdkDrag.ctorParameters = () => [ { type: ElementRef }, { type: undefined, decorators: [{ type: Inject, args: [CDK_DROP_LIST,] }, { type: Optional }, { type: SkipSelf }] }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, { type: NgZone }, { type: ViewContainerRef }, { type: undefined, decorators: [{ type: Inject, args: [CDK_DRAG_CONFIG,] }] }, { type: Directionality, decorators: [{ type: Optional }] }, { type: DragDrop }, { type: ChangeDetectorRef } ]; CdkDrag.propDecorators = { _handles: [{ type: ContentChildren, args: [CdkDragHandle, { descendants: true },] }], _previewTemplate: [{ type: ContentChild, args: [CdkDragPreview,] }], _placeholderTemplate: [{ type: ContentChild, args: [CdkDragPlaceholder,] }], data: [{ type: Input, args: ['cdkDragData',] }], lockAxis: [{ type: Input, args: ['cdkDragLockAxis',] }], rootElementSelector: [{ type: Input, args: ['cdkDragRootElement',] }], boundaryElement: [{ type: Input, args: ['cdkDragBoundary',] }], dragStartDelay: [{ type: Input, args: ['cdkDragStartDelay',] }], freeDragPosition: [{ type: Input, args: ['cdkDragFreeDragPosition',] }], disabled: [{ type: Input, args: ['cdkDragDisabled',] }], constrainPosition: [{ type: Input, args: ['cdkDragConstrainPosition',] }], previewClass: [{ type: Input, args: ['cdkDragPreviewClass',] }], started: [{ type: Output, args: ['cdkDragStarted',] }], released: [{ type: Output, args: ['cdkDragReleased',] }], ended: [{ type: Output, args: ['cdkDragEnded',] }], entered: [{ type: Output, args: ['cdkDragEntered',] }], exited: [{ type: Output, args: ['cdkDragExited',] }], dropped: [{ type: Output, args: ['cdkDragDropped',] }], moved: [{ type: Output, args: ['cdkDragMoved',] }] }; if (false) { /** @type {?} */ CdkDrag.ngAcceptInputType_disabled; /** * @type {?} * @private */ CdkDrag.prototype._destroyed; /** * Reference to the underlying drag instance. * @type {?} */ CdkDrag.prototype._dragRef; /** * Elements that can be used to drag the draggable item. * @type {?} */ CdkDrag.prototype._handles; /** * Element that will be used as a template to create the draggable item's preview. * @type {?} */ CdkDrag.prototype._previewTemplate; /** * Template for placeholder element rendered to show where a draggable would be dropped. * @type {?} */ CdkDrag.prototype._placeholderTemplate; /** * Arbitrary data to attach to this drag instance. * @type {?} */ CdkDrag.prototype.data; /** * Locks the position of the dragged element along the specified axis. * @type {?} */ CdkDrag.prototype.lockAxis; /** * Selector that will be used to determine the root draggable element, starting from * the `cdkDrag` element and going up the DOM. Passing an alternate root element is useful * when trying to enable dragging on an element that you might not have access to. * @type {?} */ CdkDrag.prototype.rootElementSelector; /** * Node or selector that will be used to determine the element to which the draggable's * position will be constrained. If a string is passed in, it'll be used as a selector that * will be matched starting from the element's parent and going up the DOM until a match * has been found. * @type {?} */ CdkDrag.prototype.boundaryElement; /** * Amount of milliseconds to wait after the user has put their * pointer down before starting to drag the element. * @type {?} */ CdkDrag.prototype.dragStartDelay; /** * Sets the position of a `CdkDrag` that is outside of a drop container. * Can be used to restore the element's position for a returning user. * @type {?} */ CdkDrag.prototype.freeDragPosition; /** * @type {?} * @private */ CdkDrag.prototype._disabled; /** * Function that can be used to customize the logic of how the position of the drag item * is limited while it's being dragged. Gets called with a point containing the current position * of the user's pointer on the page and should return a point describing where the item should * be rendered. * @type {?} */ CdkDrag.prototype.constrainPosition; /** * Class to be added to the preview element. * @type {?} */ CdkDrag.prototype.previewClass; /** * Emits when the user starts dragging the item. * @type {?} */ CdkDrag.prototype.started; /** * Emits when the user has released a drag item, before any animations have started. * @type {?} */ CdkDrag.prototype.released; /** * Emits when the user stops dragging an item in the container. * @type {?} */ CdkDrag.prototype.ended; /** * Emits when the user has moved the item into a new container. * @type {?} */ CdkDrag.prototype.entered; /** * Emits when the user removes the item its container by dragging it into another container. * @type {?} */ CdkDrag.prototype.exited; /** * Emits when the user drops the item inside a container. * @type {?} */ CdkDrag.prototype.dropped; /** * Emits as the user is dragging the item. Use with caution, * because this event will fire for every pixel that the user has dragged. * @type {?} */ CdkDrag.prototype.moved; /** * Element that the draggable is attached to. * @type {?} */ CdkDrag.prototype.element; /** * Droppable container that the draggable is a part of. * @type {?} */ CdkDrag.prototype.dropContainer; /** * @type {?} * @private */ CdkDrag.prototype._document; /** * @type {?} * @private */ CdkDrag.prototype._ngZone; /** * @type {?} * @private */ CdkDrag.prototype._viewContainerRef; /** * @type {?} * @private */ CdkDrag.prototype._dir; /** * @type {?} * @private */ CdkDrag.prototype._changeDetectorRef; } /** * Gets the closest ancestor of an element that matches a selector. * @param {?} element * @param {?} selector * @return {?} */ function getClosestMatchingAncestor(element, selector) { /** @type {?} */ let currentElement = (/** @type {?} */ (element.parentElement)); while (currentElement) { // IE doesn't support `matches` so we have to fall back to `msMatchesSelector`. if (currentElement.matches ? currentElement.matches(selector) : ((/** @type {?} */ (currentElement))).msMatchesSelector(selector)) { return currentElement; } currentElement = currentElement.parentElement; } return null; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jZGsvZHJhZy1kcm9wL2RpcmVjdGl2ZXMvZHJhZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFRQSxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDakQsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFFTCxZQUFZLEVBQ1osZUFBZSxFQUNmLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixjQUFjLEVBQ2QsS0FBSyxFQUNMLE1BQU0sRUFFTixRQUFRLEVBQ1IsTUFBTSxFQUNOLFNBQVMsRUFDVCxRQUFRLEVBQ1IsZ0JBQWdCLEVBR2hCLGlCQUFpQixFQUNqQixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLHFCQUFxQixFQUNyQixvQkFBb0IsRUFDcEIsYUFBYSxFQUVkLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFDLFVBQVUsRUFBWSxPQUFPLEVBQUUsS0FBSyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzFELE9BQU8sRUFBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBVS9FLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDNUMsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDdEQsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUcvQyxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sY0FBYyxDQUFDOzs7Ozs7QUFNdEMsTUFBTSxPQUFPLGFBQWEsR0FB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QUMsYUFBYSxDQUFDO0tBQy9DO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7RGlyZWN0aW9uYWxpdHl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9iaWRpJztcbmltcG9ydCB7RE9DVU1FTlR9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDb250ZW50Q2hpbGQsXG4gIENvbnRlbnRDaGlsZHJlbixcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEluamVjdCxcbiAgSW5qZWN0aW9uVG9rZW4sXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uRGVzdHJveSxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBTa2lwU2VsZixcbiAgVmlld0NvbnRhaW5lclJlZixcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgaXNEZXZNb2RlLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSxcbiAgY29lcmNlTnVtYmVyUHJvcGVydHksXG4gIGNvZXJjZUVsZW1lbnQsXG4gIEJvb2xlYW5JbnB1dFxufSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBPYnNlcnZlciwgU3ViamVjdCwgbWVyZ2V9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtzdGFydFdpdGgsIHRha2UsIG1hcCwgdGFrZVVudGlsLCBzd2l0Y2hNYXAsIHRhcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgQ2RrRHJhZ0Ryb3AsXG4gIENka0RyYWdFbmQsXG4gIENka0RyYWdFbnRlcixcbiAgQ2RrRHJhZ0V4aXQsXG4gIENka0RyYWdNb3ZlLFxuICBDZGtEcmFnU3RhcnQsXG4gIENka0RyYWdSZWxlYXNlLFxufSBmcm9tICcuLi9kcmFnLWV2ZW50cyc7XG5pbXBvcnQge0Nka0RyYWdIYW5kbGV9IGZyb20gJy4vZHJhZy1oYW5kbGUnO1xuaW1wb3J0IHtDZGtEcmFnUGxhY2Vob2xkZXJ9IGZyb20gJy4vZHJhZy1wbGFjZWhvbGRlcic7XG5pbXBvcnQge0Nka0RyYWdQcmV2aWV3fSBmcm9tICcuL2RyYWctcHJldmlldyc7XG5pbXBvcnQge0NES19EUkFHX1BBUkVOVH0gZnJvbSAnLi4vZHJhZy1wYXJlbnQnO1xuaW1wb3J0IHtEcmFnUmVmLCBEcmFnUmVmQ29uZmlnLCBQb2ludH0gZnJvbSAnLi4vZHJhZy1yZWYnO1xuaW1wb3J0IHtDZGtEcm9wTGlzdEludGVybmFsIGFzIENka0Ryb3BMaXN0fSBmcm9tICcuL2Ryb3AtbGlzdCc7XG5pbXBvcnQge0RyYWdEcm9wfSBmcm9tICcuLi9kcmFnLWRyb3AnO1xuXG4vKipcbiAqIEluamVjdGlvbiB0b2tlbiB0aGF0IGlzIHVzZWQgdG8gcHJvdmlkZSBhIENka0Ryb3BMaXN0IGluc3RhbmNlIHRvIENka0RyYWcuXG4gKiBVc2VkIGZvciBhdm9pZGluZyBjaXJjdWxhciBpbXBvcnRzLlxuICovXG5leHBvcnQgY29uc3QgQ0RLX0RST1BfTElTVCA9IG5ldyBJbmplY3Rpb25Ub2tlbjxDZGtEcm9wTGlzdD4oJ0NES19EUk9QX0xJU1QnKTtcblxuLyoqIEluamVjdGlvbiB0b2tlbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgYmVoYXZpb3Igb2YgYENka0RyYWdgLiAqL1xuZXhwb3J0IGNvbnN0IENES19EUkFHX0NPTkZJRyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxEcmFnUmVmQ29uZmlnPignQ0RLX0RSQUdfQ09ORklHJywge1xuICBwcm92aWRlZEluOiAncm9vdCcsXG4gIGZhY3Rvcnk6IENES19EUkFHX0NPTkZJR19GQUNUT1JZXG59KTtcblxuLyoqIEBkb2NzLXByaXZhdGUgKi9cbmV4cG9ydCBmdW5jdGlvbiBDREtfRFJBR19DT05GSUdfRkFDVE9SWSgpOiBEcmFnUmVmQ29uZmlnIHtcbiAgcmV0dXJuIHtkcmFnU3RhcnRUaHJlc2hvbGQ6IDUsIHBvaW50ZXJEaXJlY3Rpb25DaGFuZ2VUaHJlc2hvbGQ6IDV9O1xufVxuXG4vKiogRWxlbWVudCB0aGF0IGNhbiBiZSBtb3ZlZCBpbnNpZGUgYSBDZGtEcm9wTGlzdCBjb250YWluZXIuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbY2RrRHJhZ10nLFxuICBleHBvcnRBczogJ2Nka0RyYWcnLFxuICBob3N0OiB7XG4gICAgJ2NsYXNzJzogJ2Nkay1kcmFnJyxcbiAgICAnW2NsYXNzLmNkay1kcmFnLWRpc2FibGVkXSc6ICdkaXNhYmxlZCcsXG4gICAgJ1tjbGFzcy5jZGstZHJhZy1kcmFnZ2luZ10nOiAnX2RyYWdSZWYuaXNEcmFnZ2luZygpJyxcbiAgfSxcbiAgcHJvdmlkZXJzOiBbe3Byb3ZpZGU6IENES19EUkFHX1BBUkVOVCwgdXNlRXhpc3Rpbmc6IENka0RyYWd9XVxufSlcbmV4cG9ydCBjbGFzcyBDZGtEcmFnPFQgPSBhbnk+IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIF9kZXN0cm95ZWQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHVuZGVybHlpbmcgZHJhZyBpbnN0YW5jZS4gKi9cbiAgX2RyYWdSZWY6IERyYWdSZWY8Q2RrRHJhZzxUPj47XG5cbiAgLyoqIEVsZW1lbnRzIHRoYXQgY2FuIGJlIHVzZWQgdG8gZHJhZyB0aGUgZHJhZ2dhYmxlIGl0ZW0uICovXG4gIEBDb250ZW50Q2hpbGRyZW4oQ2RrRHJhZ0hhbmRsZSwge2Rlc2NlbmRhbnRzOiB0cnVlfSkgX2hhbmRsZXM6IFF1ZXJ5TGlzdDxDZGtEcmFnSGFuZGxlPjtcblxuICAvKiogRWxlbWVudCB0aGF0IHdpbGwgYmUgdXNlZCBhcyBhIHRlbXBsYXRlIHRvIGNyZWF0ZSB0aGUgZHJhZ2dhYmxlIGl0ZW0ncyBwcmV2aWV3LiAqL1xuICBAQ29udGVudENoaWxkKENka0RyYWdQcmV2aWV3KSBfcHJldmlld1RlbXBsYXRlOiBDZGtEcmFnUHJldmlldztcblxuICAvKiogVGVtcGxhdGUgZm9yIHBsYWNlaG9sZGVyIGVsZW1lbnQgcmVuZGVyZWQgdG8gc2hvdyB3aGVyZSBhIGRyYWdnYWJsZSB3b3VsZCBiZSBkcm9wcGVkLiAqL1xuICBAQ29udGVudENoaWxkKENka0RyYWdQbGFjZWhvbGRlcikgX3BsYWNlaG9sZGVyVGVtcGxhdGU6IENka0RyYWdQbGFjZWhvbGRlcjtcblxuICAvKiogQXJiaXRyYXJ5IGRhdGEgdG8gYXR0YWNoIHRvIHRoaXMgZHJhZyBpbnN0YW5jZS4gKi9cbiAgQElucHV0KCdjZGtEcmFnRGF0YScpIGRhdGE6IFQ7XG5cbiAgLyoqIExvY2tzIHRoZSBwb3NpdGlvbiBvZiB0aGUgZHJhZ2dlZCBlbGVtZW50IGFsb25nIHRoZSBzcGVjaWZpZWQgYXhpcy4gKi9cbiAgQElucHV0KCdjZGtEcmFnTG9ja0F4aXMnKSBsb2NrQXhpczogJ3gnIHwgJ3knO1xuXG4gIC8qKlxuICAgKiBTZWxlY3RvciB0aGF0IHdpbGwgYmUgdXNlZCB0byBkZXRlcm1pbmUgdGhlIHJvb3QgZHJhZ2dhYmxlIGVsZW1lbnQsIHN0YXJ0aW5nIGZyb21cbiAgICogdGhlIGBjZGtEcmFnYCBlbGVtZW50IGFuZCBnb2luZyB1cCB0aGUgRE9NLiBQYXNzaW5nIGFuIGFsdGVybmF0ZSByb290IGVsZW1lbnQgaXMgdXNlZnVsXG4gICAqIHdoZW4gdHJ5aW5nIHRvIGVuYWJsZSBkcmFnZ2luZyBvbiBhbiBlbGVtZW50IHRoYXQgeW91IG1pZ2h0IG5vdCBoYXZlIGFjY2VzcyB0by5cbiAgICovXG4gIEBJbnB1dCgnY2RrRHJhZ1Jvb3RFbGVtZW50Jykgcm9vdEVsZW1lbnRTZWxlY3Rvcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBOb2RlIG9yIHNlbGVjdG9yIHRoYXQgd2lsbCBiZSB1c2VkIHRvIGRldGVybWluZSB0aGUgZWxlbWVudCB0byB3aGljaCB0aGUgZHJhZ2dhYmxlJ3NcbiAgICogcG9zaXRpb24gd2lsbCBiZSBjb25zdHJhaW5lZC4gSWYgYSBzdHJpbmcgaXMgcGFzc2VkIGluLCBpdCdsbCBiZSB1c2VkIGFzIGEgc2VsZWN0b3IgdGhhdFxuICAgKiB3aWxsIGJlIG1hdGNoZWQgc3RhcnRpbmcgZnJvbSB0aGUgZWxlbWVudCdzIHBhcmVudCBhbmQgZ29pbmcgdXAgdGhlIERPTSB1bnRpbCBhIG1hdGNoXG4gICAqIGhhcyBiZWVuIGZvdW5kLlxuICAgKi9cbiAgQElucHV0KCdjZGtEcmFnQm91bmRhcnknKSBib3VuZGFyeUVsZW1lbnQ6IHN0cmluZyB8IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+IHwgSFRNTEVsZW1lbnQ7XG5cbiAgLyoqXG4gICAqIEFtb3VudCBvZiBtaWxsaXNlY29uZHMgdG8gd2FpdCBhZnRlciB0aGUgdXNlciBoYXMgcHV0IHRoZWlyXG4gICAqIHBvaW50ZXIgZG93biBiZWZvcmUgc3RhcnRpbmcgdG8gZHJhZyB0aGUgZWxlbWVudC5cbiAgICovXG4gIEBJbnB1dCgnY2RrRHJhZ1N0YXJ0RGVsYXknKSBkcmFnU3RhcnREZWxheTogbnVtYmVyIHwge3RvdWNoOiBudW1iZXIsIG1vdXNlOiBudW1iZXJ9ID0gMDtcblxuICAvKipcbiAgICogU2V0cyB0aGUgcG9zaXRpb24gb2YgYSBgQ2RrRHJhZ2AgdGhhdCBpcyBvdXRzaWRlIG9mIGEgZHJvcCBjb250YWluZXIuXG4gICAqIENhbiBiZSB1c2VkIHRvIHJlc3RvcmUgdGhlIGVsZW1lbnQncyBwb3NpdGlvbiBmb3IgYSByZXR1cm5pbmcgdXNlci5cbiAgICovXG4gIEBJbnB1dCgnY2RrRHJhZ0ZyZWVEcmFnUG9zaXRpb24nKSBmcmVlRHJhZ1Bvc2l0aW9uOiB7eDogbnVtYmVyLCB5OiBudW1iZXJ9O1xuXG4gIC8qKiBXaGV0aGVyIHN0YXJ0aW5nIHRvIGRyYWcgdGhpcyBlbGVtZW50IGlzIGRpc2FibGVkLiAqL1xuICBASW5wdXQoJ2Nka0RyYWdEaXNhYmxlZCcpXG4gIGdldCBkaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZGlzYWJsZWQgfHwgKHRoaXMuZHJvcENvbnRhaW5lciAmJiB0aGlzLmRyb3BDb250YWluZXIuZGlzYWJsZWQpO1xuICB9XG4gIHNldCBkaXNhYmxlZCh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuX2Rpc2FibGVkID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgICB0aGlzLl9kcmFnUmVmLmRpc2FibGVkID0gdGhpcy5fZGlzYWJsZWQ7XG4gIH1cbiAgcHJpdmF0ZSBfZGlzYWJsZWQgPSBmYWxzZTtcblxuICAvKipcbiAgICogRnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCB0byBjdXN0b21pemUgdGhlIGxvZ2ljIG9mIGhvdyB0aGUgcG9zaXRpb24gb2YgdGhlIGRyYWcgaXRlbVxuICAgKiBpcyBsaW1pdGVkIHdoaWxlIGl0J3MgYmVpbmcgZHJhZ2dlZC4gR2V0cyBjYWxsZWQgd2l0aCBhIHBvaW50IGNvbnRhaW5pbmcgdGhlIGN1cnJlbnQgcG9zaXRpb25cbiAgICogb2YgdGhlIHVzZXIncyBwb2ludGVyIG9uIHRoZSBwYWdlIGFuZCBzaG91bGQgcmV0dXJuIGEgcG9pbnQgZGVzY3JpYmluZyB3aGVyZSB0aGUgaXRlbSBzaG91bGRcbiAgICogYmUgcmVuZGVyZWQuXG4gICAqL1xuICBASW5wdXQoJ2Nka0RyYWdDb25zdHJhaW5Qb3NpdGlvbicpIGNvbnN0cmFpblBvc2l0aW9uPzogKHBvaW50OiBQb2ludCwgZHJhZ1JlZjogRHJhZ1JlZikgPT4gUG9pbnQ7XG5cbiAgLyoqIENsYXNzIHRvIGJlIGFkZGVkIHRvIHRoZSBwcmV2aWV3IGVsZW1lbnQuICovXG4gIEBJbnB1dCgnY2RrRHJhZ1ByZXZpZXdDbGFzcycpIHByZXZpZXdDbGFzczogc3RyaW5nIHwgc3RyaW5nW107XG5cbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHVzZXIgc3RhcnRzIGRyYWdnaW5nIHRoZSBpdGVtLiAqL1xuICBAT3V0cHV0KCdjZGtEcmFnU3RhcnRlZCcpIHN0YXJ0ZWQ6IEV2ZW50RW1pdHRlcjxDZGtEcmFnU3RhcnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxDZGtEcmFnU3RhcnQ+KCk7XG5cbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHVzZXIgaGFzIHJlbGVhc2VkIGEgZHJhZyBpdGVtLCBiZWZvcmUgYW55IGFuaW1hdGlvbnMgaGF2ZSBzdGFydGVkLiAqL1xuICBAT3V0cHV0KCdjZGtEcmFnUmVsZWFzZWQnKSByZWxlYXNlZDogRXZlbnRFbWl0dGVyPENka0RyYWdSZWxlYXNlPiA9XG4gICAgICBuZXcgRXZlbnRFbWl0dGVyPENka0RyYWdSZWxlYXNlPigpO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHN0b3BzIGRyYWdnaW5nIGFuIGl0ZW0gaW4gdGhlIGNvbnRhaW5lci4gKi9cbiAgQE91dHB1dCgnY2RrRHJhZ0VuZGVkJykgZW5kZWQ6IEV2ZW50RW1pdHRlcjxDZGtEcmFnRW5kPiA9IG5ldyBFdmVudEVtaXR0ZXI8Q2RrRHJhZ0VuZD4oKTtcblxuICAvKiogRW1pdHMgd2hlbiB0aGUgdXNlciBoYXMgbW92ZWQgdGhlIGl0ZW0gaW50byBhIG5ldyBjb250YWluZXIuICovXG4gIEBPdXRwdXQoJ2Nka0RyYWdFbnRlcmVkJykgZW50ZXJlZDogRXZlbnRFbWl0dGVyPENka0RyYWdFbnRlcjxhbnk+PiA9XG4gICAgICBuZXcgRXZlbnRFbWl0dGVyPENka0RyYWdFbnRlcjxhbnk+PigpO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIHJlbW92ZXMgdGhlIGl0ZW0gaXRzIGNvbnRhaW5lciBieSBkcmFnZ2luZyBpdCBpbnRvIGFub3RoZXIgY29udGFpbmVyLiAqL1xuICBAT3V0cHV0KCdjZGtEcmFnRXhpdGVkJykgZXhpdGVkOiBFdmVudEVtaXR0ZXI8Q2RrRHJhZ0V4aXQ8YW55Pj4gPVxuICAgICAgbmV3IEV2ZW50RW1pdHRlcjxDZGtEcmFnRXhpdDxhbnk+PigpO1xuXG4gIC8qKiBFbWl0cyB3aGVuIHRoZSB1c2VyIGRyb3BzIHRoZSBpdGVtIGluc2lkZSBhIGNvbnRhaW5lci4gKi9cbiAgQE91dHB1dCgnY2RrRHJhZ0Ryb3BwZWQnKSBkcm9wcGVkOiBFdmVudEVtaXR0ZXI8Q2RrRHJhZ0Ryb3A8YW55Pj4gPVxuICAgICAgbmV3IEV2ZW50RW1pdHRlcjxDZGtEcmFnRHJvcDxhbnk+PigpO1xuXG4gIC8qKlxuICAgKiBFbWl0cyBhcyB0aGUgdXNlciBpcyBkcmFnZ2luZyB0aGUgaXRlbS4gVXNlIHdpdGggY2F1dGlvbixcbiAgICogYmVjYXVzZSB0aGlzIGV2ZW50IHdpbGwgZmlyZSBmb3IgZXZlcnkgcGl4ZWwgdGhhdCB0aGUgdXNlciBoYXMgZHJhZ2dlZC5cbiAgICovXG4gIEBPdXRwdXQoJ2Nka0RyYWdNb3ZlZCcpIG1vdmVkOiBPYnNlcnZhYmxlPENka0RyYWdNb3ZlPFQ+PiA9XG4gICAgICBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXI6IE9ic2VydmVyPENka0RyYWdNb3ZlPFQ+PikgPT4ge1xuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0aGlzLl9kcmFnUmVmLm1vdmVkLnBpcGUobWFwKG1vdmVkRXZlbnQgPT4gKHtcbiAgICAgICAgICBzb3VyY2U6IHRoaXMsXG4gICAgICAgICAgcG9pbnRlclBvc2l0aW9uOiBtb3ZlZEV2ZW50LnBvaW50ZXJQb3NpdGlvbixcbiAgICAgICAgICBldmVudDogbW92ZWRFdmVudC5ldmVudCxcbiAgICAgICAgICBkZWx0YTogbW92ZWRFdmVudC5kZWx0YSxcbiAgICAgICAgICBkaXN0YW5jZTogbW92ZWRFdmVudC5kaXN0YW5jZVxuICAgICAgICB9KSkpLnN1YnNjcmliZShvYnNlcnZlcik7XG5cbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgLyoqIEVsZW1lbnQgdGhhdCB0aGUgZHJhZ2dhYmxlIGlzIGF0dGFjaGVkIHRvLiAqL1xuICAgICAgcHVibGljIGVsZW1lbnQ6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICAgICAgLyoqIERyb3BwYWJsZSBjb250YWluZXIgdGhhdCB0aGUgZHJhZ2dhYmxlIGlzIGEgcGFydCBvZi4gKi9cbiAgICAgIEBJbmplY3QoQ0RLX0RST1BfTElTVCkgQE9wdGlvbmFsKCkgQFNraXBTZWxmKCkgcHVibGljIGRyb3BDb250YWluZXI6IENka0Ryb3BMaXN0LFxuICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBfZG9jdW1lbnQ6IGFueSwgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmUsXG4gICAgICBwcml2YXRlIF92aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLCBASW5qZWN0KENES19EUkFHX0NPTkZJRykgY29uZmlnOiBEcmFnUmVmQ29uZmlnLFxuICAgICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBfZGlyOiBEaXJlY3Rpb25hbGl0eSwgZHJhZ0Ryb3A6IERyYWdEcm9wLFxuICAgICAgcHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgdGhpcy5fZHJhZ1JlZiA9IGRyYWdEcm9wLmNyZWF0ZURyYWcoZWxlbWVudCwgY29uZmlnKTtcbiAgICB0aGlzLl9kcmFnUmVmLmRhdGEgPSB0aGlzO1xuICAgIHRoaXMuX3N5bmNJbnB1dHModGhpcy5fZHJhZ1JlZik7XG4gICAgdGhpcy5faGFuZGxlRXZlbnRzKHRoaXMuX2RyYWdSZWYpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGVsZW1lbnQgdGhhdCBpcyBiZWluZyB1c2VkIGFzIGEgcGxhY2Vob2xkZXJcbiAgICogd2hpbGUgdGhlIGN1cnJlbnQgZWxlbWVudCBpcyBiZWluZyBkcmFnZ2VkLlxuICAgKi9cbiAgZ2V0UGxhY2Vob2xkZXJFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5fZHJhZ1JlZi5nZXRQbGFjZWhvbGRlckVsZW1lbnQoKTtcbiAgfVxuXG4gIC8qKiBSZXR1cm5zIHRoZSByb290IGRyYWdnYWJsZSBlbGVtZW50LiAqL1xuICBnZXRSb290RWxlbWVudCgpOiBIVE1MRWxlbWVudCB7XG4gICAgcmV0dXJuIHRoaXMuX2RyYWdSZWYuZ2V0Um9vdEVsZW1lbnQoKTtcbiAgfVxuXG4gIC8qKiBSZXNldHMgYSBzdGFuZGFsb25lIGRyYWcgaXRlbSB0byBpdHMgaW5pdGlhbCBwb3NpdGlvbi4gKi9cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5fZHJhZ1JlZi5yZXNldCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHBpeGVsIGNvb3JkaW5hdGVzIG9mIHRoZSBkcmFnZ2FibGUgb3V0c2lkZSBvZiBhIGRyb3AgY29udGFpbmVyLlxuICAgKi9cbiAgZ2V0RnJlZURyYWdQb3NpdGlvbigpOiB7cmVhZG9ubHkgeDogbnVtYmVyLCByZWFkb25seSB5OiBudW1iZXJ9IHtcbiAgICByZXR1cm4gdGhpcy5fZHJhZ1JlZi5nZXRGcmVlRHJhZ1Bvc2l0aW9uKCk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgLy8gV2UgbmVlZCB0byB3YWl0IGZvciB0aGUgem9uZSB0byBzdGFiaWxpemUsIGluIG9yZGVyIGZvciB0aGUgcmVmZXJlbmNlXG4gICAgLy8gZWxlbWVudCB0byBiZSBpbiB0aGUgcHJvcGVyIHBsYWNlIGluIHRoZSBET00uIFRoaXMgaXMgbW9zdGx5IHJlbGV2YW50XG4gICAgLy8gZm9yIGRyYWdnYWJsZSBlbGVtZW50cyBpbnNpZGUgcG9ydGFscyBzaW5jZSB0aGV5IGdldCBzdGFtcGVkIG91dCBpblxuICAgIC8vIHRoZWlyIG9yaWdpbmFsIERPTSBwb3NpdGlvbiBhbmQgdGhlbiB0aGV5IGdldCB0cmFuc2ZlcnJlZCB0byB0aGUgcG9ydGFsLlxuICAgIHRoaXMuX25nWm9uZS5vblN0YWJsZS5hc09ic2VydmFibGUoKVxuICAgICAgLnBpcGUodGFrZSgxKSwgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCkpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUm9vdEVsZW1lbnQoKTtcblxuICAgICAgICAvLyBMaXN0ZW4gZm9yIGFueSBuZXdseS1hZGRlZCBoYW5kbGVzLlxuICAgICAgICB0aGlzLl9oYW5kbGVzLmNoYW5nZXMucGlwZShcbiAgICAgICAgICBzdGFydFdpdGgodGhpcy5faGFuZGxlcyksXG4gICAgICAgICAgLy8gU3luYyB0aGUgbmV3IGhhbmRsZXMgd2l0aCB0aGUgRHJhZ1JlZi5cbiAgICAgICAgICB0YXAoKGhhbmRsZXM6IFF1ZXJ5TGlzdDxDZGtEcmFnSGFuZGxlPikgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2hpbGRIYW5kbGVFbGVtZW50cyA9IGhhbmRsZXNcbiAgICAgICAgICAgICAgLmZpbHRlcihoYW5kbGUgPT4gaGFuZGxlLl9wYXJlbnREcmFnID09PSB0aGlzKVxuICAgICAgICAgICAgICAubWFwKGhhbmRsZSA9PiBoYW5kbGUuZWxlbWVudCk7XG4gICAgICAgICAgICB0aGlzLl9kcmFnUmVmLndpdGhIYW5kbGVzKGNoaWxkSGFuZGxlRWxlbWVudHMpO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIC8vIExpc3RlbiBpZiB0aGUgc3RhdGUgb2YgYW55IG9mIHRoZSBoYW5kbGVzIGNoYW5nZXMuXG4gICAgICAgICAgc3dpdGNoTWFwKChoYW5kbGVzOiBRdWVyeUxpc3Q8Q2RrRHJhZ0hhbmRsZT4pID0+IHtcbiAgICAgICAgICAgIHJldHVybiBtZXJnZSguLi5oYW5kbGVzLm1hcChpdGVtID0+IHtcbiAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uX3N0YXRlQ2hhbmdlcy5waXBlKHN0YXJ0V2l0aChpdGVtKSk7XG4gICAgICAgICAgICB9KSkgYXMgT2JzZXJ2YWJsZTxDZGtEcmFnSGFuZGxlPjtcbiAgICAgICAgICB9KSxcbiAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKVxuICAgICAgICApLnN1YnNjcmliZShoYW5kbGVJbnN0YW5jZSA9PiB7XG4gICAgICAgICAgLy8gRW5hYmxlZC9kaXNhYmxlIHRoZSBoYW5kbGUgdGhhdCBjaGFuZ2VkIGluIHRoZSBEcmFnUmVmLlxuICAgICAgICAgIGNvbnN0IGRyYWdSZWYgPSB0aGlzLl9kcmFnUmVmO1xuICAgICAgICAgIGNvbnN0IGhhbmRsZSA9IGhhbmRsZUluc3RhbmNlLmVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICBoYW5kbGVJbnN0YW5jZS5kaXNhYmxlZCA/IGRyYWdSZWYuZGlzYWJsZUhhbmRsZShoYW5kbGUpIDogZHJhZ1JlZi5lbmFibGVIYW5kbGUoaGFuZGxlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRoaXMuZnJlZURyYWdQb3NpdGlvbikge1xuICAgICAgICAgIHRoaXMuX2RyYWdSZWYuc2V0RnJlZURyYWdQb3NpdGlvbih0aGlzLmZyZWVEcmFnUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBjb25zdCByb290U2VsZWN0b3JDaGFuZ2UgPSBjaGFuZ2VzWydyb290RWxlbWVudFNlbGVjdG9yJ107XG4gICAgY29uc3QgcG9zaXRpb25DaGFuZ2UgPSBjaGFuZ2VzWydmcmVlRHJhZ1Bvc2l0aW9uJ107XG5cbiAgICAvLyBXZSBkb24ndCBoYXZlIHRvIHJlYWN0IHRvIHRoZSBmaXJzdCBjaGFuZ2Ugc2luY2UgaXQncyBiZWluZ1xuICAgIC8vIGhhbmRsZWQgaW4gYG5nQWZ0ZXJWaWV3SW5pdGAgd2hlcmUgaXQgbmVlZHMgdG8gYmUgZGVmZXJyZWQuXG4gICAgaWYgKHJvb3RTZWxlY3RvckNoYW5nZSAmJiAhcm9vdFNlbGVjdG9yQ2hhbmdlLmZpcnN0Q2hhbm