@angular/forms
Version:
Angular - directives and services for creating forms
347 lines • 38.7 kB
JavaScript
/**
* @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 { Directive, EventEmitter, forwardRef, Inject, Input, Optional, Output, Self } from '@angular/core';
import { isFormControl } from '../../model/form_control';
import { FormGroup } from '../../model/form_group';
import { NG_ASYNC_VALIDATORS, NG_VALIDATORS } from '../../validators';
import { ControlContainer } from '../control_container';
import { missingFormException } from '../reactive_errors';
import { CALL_SET_DISABLED_STATE, cleanUpControl, cleanUpFormContainer, cleanUpValidators, removeListItem, setUpControl, setUpFormContainer, setUpValidators, syncPendingControls } from '../shared';
import * as i0 from "@angular/core";
const formDirectiveProvider = {
provide: ControlContainer,
useExisting: forwardRef(() => FormGroupDirective)
};
/**
* @description
*
* Binds an existing `FormGroup` or `FormRecord` to a DOM element.
*
* This directive accepts an existing `FormGroup` instance. It will then use this
* `FormGroup` instance to match any child `FormControl`, `FormGroup`/`FormRecord`,
* and `FormArray` instances to child `FormControlName`, `FormGroupName`,
* and `FormArrayName` directives.
*
* @see [Reactive Forms Guide](guide/reactive-forms)
* @see `AbstractControl`
*
* @usageNotes
* ### Register Form Group
*
* The following example registers a `FormGroup` with first name and last name controls,
* and listens for the *ngSubmit* event when the button is clicked.
*
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
*
* @ngModule ReactiveFormsModule
* @publicApi
*/
export class FormGroupDirective extends ControlContainer {
constructor(validators, asyncValidators, callSetDisabledState) {
super();
this.callSetDisabledState = callSetDisabledState;
/**
* @description
* Reports whether the form submission has been triggered.
*/
this.submitted = false;
/**
* Callback that should be invoked when controls in FormGroup or FormArray collection change
* (added or removed). This callback triggers corresponding DOM updates.
*/
this._onCollectionChange = () => this._updateDomValue();
/**
* @description
* Tracks the list of added `FormControlName` instances
*/
this.directives = [];
/**
* @description
* Tracks the `FormGroup` bound to this directive.
*/
this.form = null;
/**
* @description
* Emits an event when the form submission has been triggered.
*/
this.ngSubmit = new EventEmitter();
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
}
/** @nodoc */
ngOnChanges(changes) {
this._checkFormPresent();
if (changes.hasOwnProperty('form')) {
this._updateValidators();
this._updateDomValue();
this._updateRegistrations();
this._oldForm = this.form;
}
}
/** @nodoc */
ngOnDestroy() {
if (this.form) {
cleanUpValidators(this.form, this);
// Currently the `onCollectionChange` callback is rewritten each time the
// `_registerOnCollectionChange` function is invoked. The implication is that cleanup should
// happen *only* when the `onCollectionChange` callback was set by this directive instance.
// Otherwise it might cause overriding a callback of some other directive instances. We should
// consider updating this logic later to make it similar to how `onChange` callbacks are
// handled, see https://github.com/angular/angular/issues/39732 for additional info.
if (this.form._onCollectionChange === this._onCollectionChange) {
this.form._registerOnCollectionChange(() => { });
}
}
}
/**
* @description
* Returns this directive's instance.
*/
get formDirective() {
return this;
}
/**
* @description
* Returns the `FormGroup` bound to this directive.
*/
get control() {
return this.form;
}
/**
* @description
* Returns an array representing the path to this group. Because this directive
* always lives at the top level of a form, it always an empty array.
*/
get path() {
return [];
}
/**
* @description
* Method that sets up the control directive in this group, re-calculates its value
* and validity, and adds the instance to the internal list of directives.
*
* @param dir The `FormControlName` directive instance.
*/
addControl(dir) {
const ctrl = this.form.get(dir.path);
setUpControl(ctrl, dir, this.callSetDisabledState);
ctrl.updateValueAndValidity({ emitEvent: false });
this.directives.push(dir);
return ctrl;
}
/**
* @description
* Retrieves the `FormControl` instance from the provided `FormControlName` directive
*
* @param dir The `FormControlName` directive instance.
*/
getControl(dir) {
return this.form.get(dir.path);
}
/**
* @description
* Removes the `FormControlName` instance from the internal list of directives
*
* @param dir The `FormControlName` directive instance.
*/
removeControl(dir) {
cleanUpControl(dir.control || null, dir, /* validateControlPresenceOnChange */ false);
removeListItem(this.directives, dir);
}
/**
* Adds a new `FormGroupName` directive instance to the form.
*
* @param dir The `FormGroupName` directive instance.
*/
addFormGroup(dir) {
this._setUpFormContainer(dir);
}
/**
* Performs the necessary cleanup when a `FormGroupName` directive instance is removed from the
* view.
*
* @param dir The `FormGroupName` directive instance.
*/
removeFormGroup(dir) {
this._cleanUpFormContainer(dir);
}
/**
* @description
* Retrieves the `FormGroup` for a provided `FormGroupName` directive instance
*
* @param dir The `FormGroupName` directive instance.
*/
getFormGroup(dir) {
return this.form.get(dir.path);
}
/**
* Performs the necessary setup when a `FormArrayName` directive instance is added to the view.
*
* @param dir The `FormArrayName` directive instance.
*/
addFormArray(dir) {
this._setUpFormContainer(dir);
}
/**
* Performs the necessary cleanup when a `FormArrayName` directive instance is removed from the
* view.
*
* @param dir The `FormArrayName` directive instance.
*/
removeFormArray(dir) {
this._cleanUpFormContainer(dir);
}
/**
* @description
* Retrieves the `FormArray` for a provided `FormArrayName` directive instance.
*
* @param dir The `FormArrayName` directive instance.
*/
getFormArray(dir) {
return this.form.get(dir.path);
}
/**
* Sets the new value for the provided `FormControlName` directive.
*
* @param dir The `FormControlName` directive instance.
* @param value The new value for the directive's control.
*/
updateModel(dir, value) {
const ctrl = this.form.get(dir.path);
ctrl.setValue(value);
}
/**
* @description
* Method called with the "submit" event is triggered on the form.
* Triggers the `ngSubmit` emitter to emit the "submit" event as its payload.
*
* @param $event The "submit" event object
*/
onSubmit($event) {
this.submitted = true;
syncPendingControls(this.form, this.directives);
this.ngSubmit.emit($event);
// Forms with `method="dialog"` have some special behavior that won't reload the page and that
// shouldn't be prevented. Note that we need to null check the `event` and the `target`, because
// some internal apps call this method directly with the wrong arguments.
return $event?.target?.method === 'dialog';
}
/**
* @description
* Method called when the "reset" event is triggered on the form.
*/
onReset() {
this.resetForm();
}
/**
* @description
* Resets the form to an initial value and resets its submitted status.
*
* @param value The new value for the form.
*/
resetForm(value = undefined) {
this.form.reset(value);
this.submitted = false;
}
/** @internal */
_updateDomValue() {
this.directives.forEach(dir => {
const oldCtrl = dir.control;
const newCtrl = this.form.get(dir.path);
if (oldCtrl !== newCtrl) {
// Note: the value of the `dir.control` may not be defined, for example when it's a first
// `FormControl` that is added to a `FormGroup` instance (via `addControl` call).
cleanUpControl(oldCtrl || null, dir);
// Check whether new control at the same location inside the corresponding `FormGroup` is an
// instance of `FormControl` and perform control setup only if that's the case.
// Note: we don't need to clear the list of directives (`this.directives`) here, it would be
// taken care of in the `removeControl` method invoked when corresponding `formControlName`
// directive instance is being removed (invoked from `FormControlName.ngOnDestroy`).
if (isFormControl(newCtrl)) {
setUpControl(newCtrl, dir, this.callSetDisabledState);
dir.control = newCtrl;
}
}
});
this.form._updateTreeValidity({ emitEvent: false });
}
_setUpFormContainer(dir) {
const ctrl = this.form.get(dir.path);
setUpFormContainer(ctrl, dir);
// NOTE: this operation looks unnecessary in case no new validators were added in
// `setUpFormContainer` call. Consider updating this code to match the logic in
// `_cleanUpFormContainer` function.
ctrl.updateValueAndValidity({ emitEvent: false });
}
_cleanUpFormContainer(dir) {
if (this.form) {
const ctrl = this.form.get(dir.path);
if (ctrl) {
const isControlUpdated = cleanUpFormContainer(ctrl, dir);
if (isControlUpdated) {
// Run validity check only in case a control was updated (i.e. view validators were
// removed) as removing view validators might cause validity to change.
ctrl.updateValueAndValidity({ emitEvent: false });
}
}
}
}
_updateRegistrations() {
this.form._registerOnCollectionChange(this._onCollectionChange);
if (this._oldForm) {
this._oldForm._registerOnCollectionChange(() => { });
}
}
_updateValidators() {
setUpValidators(this.form, this);
if (this._oldForm) {
cleanUpValidators(this._oldForm, this);
}
}
_checkFormPresent() {
if (!this.form && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw missingFormException();
}
}
}
FormGroupDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: FormGroupDirective, deps: [{ token: NG_VALIDATORS, optional: true, self: true }, { token: NG_ASYNC_VALIDATORS, optional: true, self: true }, { token: CALL_SET_DISABLED_STATE, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
FormGroupDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.3", type: FormGroupDirective, selector: "[formGroup]", inputs: { form: ["formGroup", "form"] }, outputs: { ngSubmit: "ngSubmit" }, host: { listeners: { "submit": "onSubmit($event)", "reset": "onReset()" } }, providers: [formDirectiveProvider], exportAs: ["ngForm"], usesInheritance: true, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.3", ngImport: i0, type: FormGroupDirective, decorators: [{
type: Directive,
args: [{
selector: '[formGroup]',
providers: [formDirectiveProvider],
host: { '(submit)': 'onSubmit($event)', '(reset)': 'onReset()' },
exportAs: 'ngForm'
}]
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [CALL_SET_DISABLED_STATE]
}] }]; }, propDecorators: { form: [{
type: Input,
args: ['formGroup']
}], ngSubmit: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybV9ncm91cF9kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9mb3Jtcy9zcmMvZGlyZWN0aXZlcy9yZWFjdGl2ZV9kaXJlY3RpdmVzL2Zvcm1fZ3JvdXBfZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUF3QixRQUFRLEVBQUUsTUFBTSxFQUFZLElBQUksRUFBZ0IsTUFBTSxlQUFlLENBQUM7QUFHeEosT0FBTyxFQUFjLGFBQWEsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBQ3BFLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRCxPQUFPLEVBQUMsbUJBQW1CLEVBQUUsYUFBYSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDcEUsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFFdEQsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDeEQsT0FBTyxFQUFDLHVCQUF1QixFQUFFLGNBQWMsRUFBRSxvQkFBb0IsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQTBCLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsbUJBQW1CLEVBQUMsTUFBTSxXQUFXLENBQUM7O0FBTTNOLE1BQU0scUJBQXFCLEdBQWE7SUFDdEMsT0FBTyxFQUFFLGdCQUFnQjtJQUN6QixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFDO0NBQ2xELENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFPSCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsZ0JBQWdCO0lBcUN0RCxZQUMrQyxVQUFxQyxFQUMvQixlQUNWLEVBQ2Ms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QUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNqQyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN4QztJQUNILENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLFNBQVMsS0FBSyxXQUFXLElBQUksU0FBUyxDQUFDLEVBQUU7WUFDakUsTUFBTSxvQkFBb0IsRUFBRSxDQUFDO1NBQzlCO0lBQ0gsQ0FBQzs7MEhBcFRVLGtCQUFrQixrQkFzQ0csYUFBYSx5Q0FDYixtQkFBbUIseUNBRTNCLHVCQUF1Qjs4R0F6Q3BDLGtCQUFrQiwrTEFKbEIsQ0FBQyxxQkFBcUIsQ0FBQztzR0FJdkIsa0JBQWtCO2tCQU45QixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxhQUFhO29CQUN2QixTQUFTLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztvQkFDbEMsSUFBSSxFQUFFLEVBQUMsVUFBVSxFQUFFLGtCQUFrQixFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUM7b0JBQzlELFFBQVEsRUFBRSxRQUFRO2lCQUNuQjs7MEJBdUNNLFFBQVE7OzBCQUFJLElBQUk7OzBCQUFJLE1BQU07MkJBQUMsYUFBYTs7MEJBQ3hDLFFBQVE7OzBCQUFJLElBQUk7OzBCQUFJLE1BQU07MkJBQUMsbUJBQW1COzswQkFFOUMsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyx1QkFBdUI7NENBWjNCLElBQUk7c0JBQXZCLEtBQUs7dUJBQUMsV0FBVztnQkFNUixRQUFRO3NCQUFqQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7RGlyZWN0aXZlLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIEluamVjdCwgSW5wdXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPcHRpb25hbCwgT3V0cHV0LCBQcm92aWRlciwgU2VsZiwgU2ltcGxlQ2hhbmdlc30gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7Rm9ybUFycmF5fSBmcm9tICcuLi8uLi9tb2RlbC9mb3JtX2FycmF5JztcbmltcG9ydCB7Rm9ybUNvbnRyb2wsIGlzRm9ybUNvbnRyb2x9IGZyb20gJy4uLy4uL21vZGVsL2Zvcm1fY29udHJvbCc7XG5pbXBvcnQge0Zvcm1Hcm91cH0gZnJvbSAnLi4vLi4vbW9kZWwvZm9ybV9ncm91cCc7XG5pbXBvcnQge05HX0FTWU5DX1ZBTElEQVRPUlMsIE5HX1ZBTElEQVRPUlN9IGZyb20gJy4uLy4uL3ZhbGlkYXRvcnMnO1xuaW1wb3J0IHtDb250cm9sQ29udGFpbmVyfSBmcm9tICcuLi9jb250cm9sX2NvbnRhaW5lcic7XG5pbXBvcnQge0Zvcm19IGZyb20gJy4uL2Zvcm1faW50ZXJmYWNlJztcbmltcG9ydCB7bWlzc2luZ0Zvcm1FeGNlcHRpb259IGZyb20gJy4uL3JlYWN0aXZlX2Vycm9ycyc7XG5pbXBvcnQge0NBTExfU0VUX0RJU0FCTEVEX1NUQVRFLCBjbGVhblVwQ29udHJvbCwgY2xlYW5VcEZvcm1Db250YWluZXIsIGNsZWFuVXBWYWxpZGF0b3JzLCByZW1vdmVMaXN0SXRlbSwgU2V0RGlzYWJsZWRTdGF0ZU9wdGlvbiwgc2V0VXBDb250cm9sLCBzZXRVcEZvcm1Db250YWluZXIsIHNldFVwVmFsaWRhdG9ycywgc3luY1BlbmRpbmdDb250cm9sc30gZnJvbSAnLi4vc2hhcmVkJztcbmltcG9ydCB7QXN5bmNWYWxpZGF0b3IsIEFzeW5jVmFsaWRhdG9yRm4sIFZhbGlkYXRvciwgVmFsaWRhdG9yRm59IGZyb20gJy4uL3ZhbGlkYXRvcnMnO1xuXG5pbXBvcnQge0Zvcm1Db250cm9sTmFtZX0gZnJvbSAnLi9mb3JtX2NvbnRyb2xfbmFtZSc7XG5pbXBvcnQge0Zvcm1BcnJheU5hbWUsIEZvcm1Hcm91cE5hbWV9IGZyb20gJy4vZm9ybV9ncm91cF9uYW1lJztcblxuY29uc3QgZm9ybURpcmVjdGl2ZVByb3ZpZGVyOiBQcm92aWRlciA9IHtcbiAgcHJvdmlkZTogQ29udHJvbENvbnRhaW5lcixcbiAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRm9ybUdyb3VwRGlyZWN0aXZlKVxufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBCaW5kcyBhbiBleGlzdGluZyBgRm9ybUdyb3VwYCBvciBgRm9ybVJlY29yZGAgdG8gYSBET00gZWxlbWVudC5cbiAqXG4gKiBUaGlzIGRpcmVjdGl2ZSBhY2NlcHRzIGFuIGV4aXN0aW5nIGBGb3JtR3JvdXBgIGluc3RhbmNlLiBJdCB3aWxsIHRoZW4gdXNlIHRoaXNcbiAqIGBGb3JtR3JvdXBgIGluc3RhbmNlIHRvIG1hdGNoIGFueSBjaGlsZCBgRm9ybUNvbnRyb2xgLCBgRm9ybUdyb3VwYC9gRm9ybVJlY29yZGAsXG4gKiBhbmQgYEZvcm1BcnJheWAgaW5zdGFuY2VzIHRvIGNoaWxkIGBGb3JtQ29udHJvbE5hbWVgLCBgRm9ybUdyb3VwTmFtZWAsXG4gKiBhbmQgYEZvcm1BcnJheU5hbWVgIGRpcmVjdGl2ZXMuXG4gKlxuICogQHNlZSBbUmVhY3RpdmUgRm9ybXMgR3VpZGVdKGd1aWRlL3JlYWN0aXZlLWZvcm1zKVxuICogQHNlZSBgQWJzdHJhY3RDb250cm9sYFxuICpcbiAqIEB1c2FnZU5vdGVzXG4gKiAjIyMgUmVnaXN0ZXIgRm9ybSBHcm91cFxuICpcbiAqIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSByZWdpc3RlcnMgYSBgRm9ybUdyb3VwYCB3aXRoIGZpcnN0IG5hbWUgYW5kIGxhc3QgbmFtZSBjb250cm9scyxcbiAqIGFuZCBsaXN0ZW5zIGZvciB0aGUgKm5nU3VibWl0KiBldmVudCB3aGVuIHRoZSBidXR0b24gaXMgY2xpY2tlZC5cbiAqXG4gKiB7QGV4YW1wbGUgZm9ybXMvdHMvc2ltcGxlRm9ybUdyb3VwL3NpbXBsZV9mb3JtX2dyb3VwX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICpcbiAqIEBuZ01vZHVsZSBSZWFjdGl2ZUZvcm1zTW9kdWxlXG4gKiBAcHVibGljQXBpXG4gKi9cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tmb3JtR3JvdXBdJyxcbiAgcHJvdmlkZXJzOiBbZm9ybURpcmVjdGl2ZVByb3ZpZGVyXSxcbiAgaG9zdDogeycoc3VibWl0KSc6ICdvblN1Ym1pdCgkZXZlbnQpJywgJyhyZXNldCknOiAnb25SZXNldCgpJ30sXG4gIGV4cG9ydEFzOiAnbmdGb3JtJ1xufSlcbmV4cG9ydCBjbGFzcyBGb3JtR3JvdXBEaXJlY3RpdmUgZXh0ZW5kcyBDb250cm9sQ29udGFpbmVyIGltcGxlbWVudHMgRm9ybSwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFJlcG9ydHMgd2hldGhlciB0aGUgZm9ybSBzdWJtaXNzaW9uIGhhcyBiZWVuIHRyaWdnZXJlZC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzdWJtaXR0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogUmVmZXJlbmNlIHRvIGFuIG9sZCBmb3JtIGdyb3VwIGlucHV0IHZhbHVlLCB3aGljaCBpcyBuZWVkZWQgdG8gY2xlYW51cCBvbGQgaW5zdGFuY2UgaW4gY2FzZSBpdFxuICAgKiB3YXMgcmVwbGFjZWQgd2l0aCBhIG5ldyBvbmUuXG4gICAqL1xuICBwcml2YXRlIF9vbGRGb3JtOiBGb3JtR3JvdXB8dW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBDYWxsYmFjayB0aGF0IHNob3VsZCBiZSBpbnZva2VkIHdoZW4gY29udHJvbHMgaW4gRm9ybUdyb3VwIG9yIEZvcm1BcnJheSBjb2xsZWN0aW9uIGNoYW5nZVxuICAgKiAoYWRkZWQgb3IgcmVtb3ZlZCkuIFRoaXMgY2FsbGJhY2sgdHJpZ2dlcnMgY29ycmVzcG9uZGluZyBET00gdXBkYXRlcy5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX29uQ29sbGVjdGlvbkNoYW5nZSA9ICgpID0+IHRoaXMuX3VwZGF0ZURvbVZhbHVlKCk7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBUcmFja3MgdGhlIGxpc3Qgb2YgYWRkZWQgYEZvcm1Db250cm9sTmFtZWAgaW5zdGFuY2VzXG4gICAqL1xuICBkaXJlY3RpdmVzOiBGb3JtQ29udHJvbE5hbWVbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogVHJhY2tzIHRoZSBgRm9ybUdyb3VwYCBib3VuZCB0byB0aGlzIGRpcmVjdGl2ZS5cbiAgICovXG4gIEBJbnB1dCgnZm9ybUdyb3VwJykgZm9ybTogRm9ybUdyb3VwID0gbnVsbCE7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBFbWl0cyBhbiBldmVudCB3aGVuIHRoZSBmb3JtIHN1Ym1pc3Npb24gaGFzIGJlZW4gdHJpZ2dlcmVkLlxuICAgKi9cbiAgQE91dHB1dCgpIG5nU3VibWl0ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgQE9wdGlvbmFsKCkgQFNlbGYoKSBASW5qZWN0KE5HX1ZBTElEQVRPUlMpIHZhbGlkYXRvcnM6IChWYWxpZGF0b3J8VmFsaWRhdG9yRm4pW10sXG4gICAgICBAT3B0aW9uYWwoKSBAU2VsZigpIEBJbmplY3QoTkdfQVNZTkNfVkFMSURBVE9SUykgYXN5bmNWYWxpZGF0b3JzOlxuICAgICAgICAgIChBc3luY1ZhbGlkYXRvcnxBc3luY1ZhbGlkYXRvckZuKVtdLFxuICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChDQUxMX1NFVF9ESVNBQkxFRF9TVEFURSkgcHJpdmF0ZSBjYWxsU2V0RGlzYWJsZWRTdGF0ZT86XG4gICAgICAgICAgU2V0RGlzYWJsZWRTdGF0ZU9wdGlvbikge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5fc2V0VmFsaWRhdG9ycyh2YWxpZGF0b3JzKTtcbiAgICB0aGlzLl9zZXRBc3luY1ZhbGlkYXRvcnMoYXN5bmNWYWxpZGF0b3JzKTtcbiAgfVxuXG4gIC8qKiBAbm9kb2MgKi9cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMuX2NoZWNrRm9ybVByZXNlbnQoKTtcbiAgICBpZiAoY2hhbmdlcy5oYXNPd25Qcm9wZXJ0eSgnZm9ybScpKSB7XG4gICAgICB0aGlzLl91cGRhdGVWYWxpZGF0b3JzKCk7XG4gICAgICB0aGlzLl91cGRhdGVEb21WYWx1ZSgpO1xuICAgICAgdGhpcy5fdXBkYXRlUmVnaXN0cmF0aW9ucygpO1xuICAgICAgdGhpcy5fb2xkRm9ybSA9IHRoaXMuZm9ybTtcbiAgICB9XG4gIH1cblxuICAvKiogQG5vZG9jICovXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGlmICh0aGlzLmZvcm0pIHtcbiAgICAgIGNsZWFuVXBWYWxpZGF0b3JzKHRoaXMuZm9ybSwgdGhpcyk7XG5cbiAgICAgIC8vIEN1cnJlbnRseSB0aGUgYG9uQ29sbGVjdGlvbkNoYW5nZWAgY2FsbGJhY2sgaXMgcmV3cml0dGVuIGVhY2ggdGltZSB0aGVcbiAgICAgIC8vIGBfcmVnaXN0ZXJPbkNvbGxlY3Rpb25DaGFuZ2VgIGZ1bmN0aW9uIGlzIGludm9rZWQuIFRoZSBpbXBsaWNhdGlvbiBpcyB0aGF0IGNsZWFudXAgc2hvdWxkXG4gICAgICAvLyBoYXBwZW4gKm9ubHkqIHdoZW4gdGhlIGBvbkNvbGxlY3Rpb25DaGFuZ2VgIGNhbGxiYWNrIHdhcyBzZXQgYnkgdGhpcyBkaXJlY3RpdmUgaW5zdGFuY2UuXG4gICAgICAvLyBPdGhlcndpc2UgaXQgbWlnaHQgY2F1c2Ugb3ZlcnJpZGluZyBhIGNhbGxiYWNrIG9mIHNvbWUgb3RoZXIgZGlyZWN0aXZlIGluc3RhbmNlcy4gV2Ugc2hvdWxkXG4gICAgICAvLyBjb25zaWRlciB1cGRhdGluZyB0aGlzIGxvZ2ljIGxhdGVyIHRvIG1ha2UgaXQgc2ltaWxhciB0byBob3cgYG9uQ2hhbmdlYCBjYWxsYmFja3MgYXJlXG4gICAgICAvLyBoYW5kbGVkLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2FuZ3VsYXIvYW5ndWxhci9pc3N1ZXMvMzk3MzIgZm9yIGFkZGl0aW9uYWwgaW5mby5cbiAgICAgIGlmICh0aGlzLmZvcm0uX29uQ29sbGVjdGlvbkNoYW5nZSA9PT0gdGhpcy5fb25Db2xsZWN0aW9uQ2hhbmdlKSB7XG4gICAgICAgIHRoaXMuZm9ybS5fcmVnaXN0ZXJPbkNvbGxlY3Rpb25DaGFuZ2UoKCkgPT4ge30pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogUmV0dXJucyB0aGlzIGRpcmVjdGl2ZSdzIGluc3RhbmNlLlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IGZvcm1EaXJlY3RpdmUoKTogRm9ybSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFJldHVybnMgdGhlIGBGb3JtR3JvdXBgIGJvdW5kIHRvIHRoaXMgZGlyZWN0aXZlLlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IGNvbnRyb2woKTogRm9ybUdyb3VwIHtcbiAgICByZXR1cm4gdGhpcy5mb3JtO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZXR1cm5zIGFuIGFycmF5IHJlcHJlc2VudGluZyB0aGUgcGF0aCB0byB0aGlzIGdyb3VwLiBCZWNhdXNlIHRoaXMgZGlyZWN0aXZlXG4gICAqIGFsd2F5cyBsaXZlcyBhdCB0aGUgdG9wIGxldmVsIG9mIGEgZm9ybSwgaXQgYWx3YXlzIGFuIGVtcHR5IGFycmF5LlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IHBhdGgoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogTWV0aG9kIHRoYXQgc2V0cyB1cCB0aGUgY29udHJvbCBkaXJlY3RpdmUgaW4gdGhpcyBncm91cCwgcmUtY2FsY3VsYXRlcyBpdHMgdmFsdWVcbiAgICogYW5kIHZhbGlkaXR5LCBhbmQgYWRkcyB0aGUgaW5zdGFuY2UgdG8gdGhlIGludGVybmFsIGxpc3Qgb2YgZGlyZWN0aXZlcy5cbiAgICpcbiAgICogQHBhcmFtIGRpciBUaGUgYEZvcm1Db250cm9sTmFtZWAgZGlyZWN0aXZlIGluc3RhbmNlLlxuICAgKi9cbiAgYWRkQ29udHJvbChkaXI6IEZvcm1Db250cm9sTmFtZSk6IEZvcm1Db250cm9sIHtcbiAgICBjb25zdCBjdHJsOiBhbnkgPSB0aGlzLmZvcm0uZ2V0KGRpci5wYXRoKTtcbiAgICBzZXRVcENvbnRyb2woY3RybCwgZGlyLCB0aGlzLmNhbGxTZXREaXNhYmxlZFN0YXRlKTtcbiAgICBjdHJsLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoe2VtaXRFdmVudDogZmFsc2V9KTtcbiAgICB0aGlzLmRpcmVjdGl2ZXMucHVzaChkaXIpO1xuICAgIHJldHVybiBjdHJsO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZXRyaWV2ZXMgdGhlIGBGb3JtQ29udHJvbGAgaW5zdGFuY2UgZnJvbSB0aGUgcHJvdmlkZWQgYEZvcm1Db250cm9sTmFtZWAgZGlyZWN0aXZlXG4gICAqXG4gICAqIEBwYXJhbSBkaXIgVGhlIGBGb3JtQ29udHJvbE5hbWVgIGRpcmVjdGl2ZSBpbnN0YW5jZS5cbiAgICovXG4gIGdldENvbnRyb2woZGlyOiBGb3JtQ29udHJvbE5hbWUpOiBGb3JtQ29udHJvbCB7XG4gICAgcmV0dXJuIDxGb3JtQ29udHJvbD50aGlzLmZvcm0uZ2V0KGRpci5wYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogUmVtb3ZlcyB0aGUgYEZvcm1Db250cm9sTmFtZWAgaW5zdGFuY2UgZnJvbSB0aGUgaW50ZXJuYWwgbGlzdCBvZiBkaXJlY3RpdmVzXG4gICAqXG4gICAqIEBwYXJhbSBkaXIgVGhlIGBGb3JtQ29udHJvbE5hbWVgIGRpcmVjdGl2ZSBpbnN0YW5jZS5cbiAgICovXG4gIHJlbW92ZUNvbnRyb2woZGlyOiBGb3JtQ29udHJvbE5hbWUpOiB2b2lkIHtcbiAgICBjbGVhblVwQ29udHJvbChkaXIuY29udHJvbCB8fCBudWxsLCBkaXIsIC8qIHZhbGlkYXRlQ29udHJvbFByZXNlbmNlT25DaGFuZ2UgKi8gZmFsc2UpO1xuICAgIHJlbW92ZUxpc3RJdGVtKHRoaXMuZGlyZWN0aXZlcywgZGlyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgbmV3IGBGb3JtR3JvdXBOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2UgdG8gdGhlIGZvcm0uXG4gICAqXG4gICAqIEBwYXJhbSBkaXIgVGhlIGBGb3JtR3JvdXBOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2UuXG4gICAqL1xuICBhZGRGb3JtR3JvdXAoZGlyOiBGb3JtR3JvdXBOYW1lKTogdm9pZCB7XG4gICAgdGhpcy5fc2V0VXBGb3JtQ29udGFpbmVyKGRpcik7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgdGhlIG5lY2Vzc2FyeSBjbGVhbnVwIHdoZW4gYSBgRm9ybUdyb3VwTmFtZWAgZGlyZWN0aXZlIGluc3RhbmNlIGlzIHJlbW92ZWQgZnJvbSB0aGVcbiAgICogdmlldy5cbiAgICpcbiAgICogQHBhcmFtIGRpciBUaGUgYEZvcm1Hcm91cE5hbWVgIGRpcmVjdGl2ZSBpbnN0YW5jZS5cbiAgICovXG4gIHJlbW92ZUZvcm1Hcm91cChkaXI6IEZvcm1Hcm91cE5hbWUpOiB2b2lkIHtcbiAgICB0aGlzLl9jbGVhblVwRm9ybUNvbnRhaW5lcihkaXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZXRyaWV2ZXMgdGhlIGBGb3JtR3JvdXBgIGZvciBhIHByb3ZpZGVkIGBGb3JtR3JvdXBOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtIGRpciBUaGUgYEZvcm1Hcm91cE5hbWVgIGRpcmVjdGl2ZSBpbnN0YW5jZS5cbiAgICovXG4gIGdldEZvcm1Hcm91cChkaXI6IEZvcm1Hcm91cE5hbWUpOiBGb3JtR3JvdXAge1xuICAgIHJldHVybiA8Rm9ybUdyb3VwPnRoaXMuZm9ybS5nZXQoZGlyLnBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIHRoZSBuZWNlc3Nhcnkgc2V0dXAgd2hlbiBhIGBGb3JtQXJyYXlOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2UgaXMgYWRkZWQgdG8gdGhlIHZpZXcuXG4gICAqXG4gICAqIEBwYXJhbSBkaXIgVGhlIGBGb3JtQXJyYXlOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2UuXG4gICAqL1xuICBhZGRGb3JtQXJyYXkoZGlyOiBGb3JtQXJyYXlOYW1lKTogdm9pZCB7XG4gICAgdGhpcy5fc2V0VXBGb3JtQ29udGFpbmVyKGRpcik7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgdGhlIG5lY2Vzc2FyeSBjbGVhbnVwIHdoZW4gYSBgRm9ybUFycmF5TmFtZWAgZGlyZWN0aXZlIGluc3RhbmNlIGlzIHJlbW92ZWQgZnJvbSB0aGVcbiAgICogdmlldy5cbiAgICpcbiAgICogQHBhcmFtIGRpciBUaGUgYEZvcm1BcnJheU5hbWVgIGRpcmVjdGl2ZSBpbnN0YW5jZS5cbiAgICovXG4gIHJlbW92ZUZvcm1BcnJheShkaXI6IEZvcm1BcnJheU5hbWUpOiB2b2lkIHtcbiAgICB0aGlzLl9jbGVhblVwRm9ybUNvbnRhaW5lcihkaXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZXRyaWV2ZXMgdGhlIGBGb3JtQXJyYXlgIGZvciBhIHByb3ZpZGVkIGBGb3JtQXJyYXlOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSBkaXIgVGhlIGBGb3JtQXJyYXlOYW1lYCBkaXJlY3RpdmUgaW5zdGFuY2UuXG4gICAqL1xuICBnZXRGb3JtQXJyYXkoZGlyOiBGb3JtQXJyYXlOYW1lKTogRm9ybUFycmF5IHtcbiAgICByZXR1cm4gPEZvcm1BcnJheT50aGlzLmZvcm0uZ2V0KGRpci5wYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBuZXcgdmFsdWUgZm9yIHRoZSBwcm92aWRlZCBgRm9ybUNvbnRyb2xOYW1lYCBkaXJlY3RpdmUuXG4gICAqXG4gICAqIEBwYXJhbSBkaXIgVGhlIGBGb3JtQ29udHJvbE5hbWVgIGRpcmVjdGl2ZSBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHZhbHVlIFRoZSBuZXcgdmFsdWUgZm9yIHRoZSBkaXJlY3RpdmUncyBjb250cm9sLlxuICAgKi9cbiAgdXBkYXRlTW9kZWwoZGlyOiBGb3JtQ29udHJvbE5hbWUsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICBjb25zdCBjdHJsID0gPEZvcm1Db250cm9sPnRoaXMuZm9ybS5nZXQoZGlyLnBhdGgpO1xuICAgIGN0cmwuc2V0VmFsdWUodmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBNZXRob2QgY2FsbGVkIHdpdGggdGhlIFwic3VibWl0XCIgZXZlbnQgaXMgdHJpZ2dlcmVkIG9uIHRoZSBmb3JtLlxuICAgKiBUcmlnZ2VycyB0aGUgYG5nU3VibWl0YCBlbWl0dGVyIHRvIGVtaXQgdGhlIFwic3VibWl0XCIgZXZlbnQgYXMgaXRzIHBheWxvYWQuXG4gICAqXG4gICAqIEBwYXJhbSAkZXZlbnQgVGhlIFwic3VibWl0XCIgZXZlbnQgb2JqZWN0XG4gICAqL1xuICBvblN1Ym1pdCgkZXZlbnQ6IEV2ZW50KTogYm9vbGVhbiB7XG4gICAgKHRoaXMgYXMge3N1Ym1pdHRlZDogYm9vbGVhbn0pLnN1Ym1pdHRlZCA9IHRydWU7XG4gICAgc3luY1BlbmRpbmdDb250cm9scyh0aGlzLmZvcm0sIHRoaXMuZGlyZWN0aXZlcyk7XG4gICAgdGhpcy5uZ1N1Ym1pdC5lbWl0KCRldmVudCk7XG4gICAgLy8gRm9ybXMgd2l0aCBgbWV0aG9kPVwiZGlhbG9nXCJgIGhhdmUgc29tZSBzcGVjaWFsIGJlaGF2aW9yIHRoYXQgd29uJ3QgcmVsb2FkIHRoZSBwYWdlIGFuZCB0aGF0XG4gICAgLy8gc2hvdWxkbid0IGJlIHByZXZlbnRlZC4gTm90ZSB0aGF0IHdlIG5lZWQgdG8gbnVsbCBjaGVjayB0aGUgYGV2ZW50YCBhbmQgdGhlIGB0YXJnZXRgLCBiZWNhdXNlXG4gICAgLy8gc29tZSBpbnRlcm5hbCBhcHBzIGNhbGwgdGhpcyBtZXRob2QgZGlyZWN0bHkgd2l0aCB0aGUgd3JvbmcgYXJndW1lbnRzLlxuICAgIHJldHVybiAoJGV2ZW50Py50YXJnZXQgYXMgSFRNTEZvcm1FbGVtZW50IHwgbnVsbCk/Lm1ldGhvZCA9PT0gJ2RpYWxvZyc7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIE1ldGhvZCBjYWxsZWQgd2hlbiB0aGUgXCJyZXNldFwiIGV2ZW50IGlzIHRyaWdnZXJlZCBvbiB0aGUgZm9ybS5cbiAgICovXG4gIG9uUmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldEZvcm0oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogUmVzZXRzIHRoZSBmb3JtIHRvIGFuIGluaXRpYWwgdmFsdWUgYW5kIHJlc2V0cyBpdHMgc3VibWl0dGVkIHN0YXR1cy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIFRoZSBuZXcgdmFsdWUgZm9yIHRoZSBmb3JtLlxuICAgKi9cbiAgcmVzZXRGb3JtKHZhbHVlOiBhbnkgPSB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICB0aGlzLmZvcm0ucmVzZXQodmFsdWUpO1xuICAgICh0aGlzIGFzIHtzdWJtaXR0ZWQ6IGJvb2xlYW59KS5zdWJtaXR0ZWQgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX3VwZGF0ZURvbVZhbHVlKCkge1xuICAgIHRoaXMuZGlyZWN0aXZlcy5mb3JFYWNoKGRpciA9PiB7XG4gICAgICBjb25zdCBvbGRDdHJsID0gZGlyLmNvbnRyb2w7XG4gICAgICBjb25zdCBuZXdDdHJsID0gdGhpcy5mb3JtLmdldChkaXIucGF0aCk7XG4gICAgICBpZiAob2xkQ3RybCAhPT0gbmV3Q3RybCkge1xuICAgICAgICAvLyBOb3RlOiB0aGUgdmFsdWUgb2YgdGhlIGBkaXIuY29udHJvbGAgbWF5IG5vdCBiZSBkZWZpbmVkLCBmb3IgZXhhbXBsZSB3aGVuIGl0J3MgYSBmaXJzdFxuICAgICAgICAvLyBgRm9ybUNvbnRyb2xgIHRoYXQgaXMgYWRkZWQgdG8gYSBgRm9ybUdyb3VwYCBpbnN0YW5jZSAodmlhIGBhZGRDb250cm9sYCBjYWxsKS5cbiAgICAgICAgY2xlYW5VcENvbnRyb2wob2xkQ3RybCB8fCBudWxsLCBkaXIpO1xuXG4gICAgICAgIC8vIENoZWNrIHdoZXRoZXIgbmV3IGNvbnRyb2wgYXQgdGhlIHNhbWUgbG9jYXRpb24gaW5zaWRlIHRoZSBjb3JyZXNwb25kaW5nIGBGb3JtR3JvdXBgIGlzIGFuXG4gICAgICAgIC8vIGluc3RhbmNlIG9mIGBGb3JtQ29udHJvbGAgYW5kIHBlcmZvcm0gY29udHJvbCBzZXR1cCBvbmx5IGlmIHRoYXQncyB0aGUgY2FzZS5cbiAgICAgICAgLy8gTm90ZTogd2UgZG9uJ3QgbmVlZCB0byBjbGVhciB0aGUgbGlzdCBvZiBkaXJlY3RpdmVzIChgdGhpcy5kaXJlY3RpdmVzYCkgaGVyZSwgaXQgd291bGQgYmVcbiAgICAgICAgLy8gdGFrZW4gY2FyZSBvZiBpbiB0aGUgYHJlbW92ZUNvbnRyb2xgIG1ldGhvZCBpbnZva2VkIHdoZW4gY29ycmVzcG9uZGluZyBgZm9ybUNvbnRyb2xOYW1lYFxuICAgICAgICAvLyBkaXJlY3RpdmUgaW5zdGFuY2UgaXMgYmVpbmcgcmVtb3ZlZCAoaW52b2tlZCBmcm9tIGBGb3JtQ29udHJvbE5hbWUubmdPbkRlc3Ryb3lgKS5cbiAgICAgICAgaWYgKGlzRm9ybUNvbnRyb2wobmV3Q3RybCkpIHtcbiAgICAgICAgICBzZXRVcENvbnRyb2wobmV3Q3RybCwgZGlyLCB0aGlzLmNhbGxTZXREaXNhYmxlZFN0YXRlKTtcbiAgICAgICAgICAoZGlyIGFzIHtjb250cm9sOiBGb3JtQ29udHJvbH0pLmNvbnRyb2wgPSBuZXdDdHJsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmZvcm0uX3VwZGF0ZVRyZWVWYWxpZGl0eSh7ZW1pdEV2ZW50OiBmYWxzZX0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2V0VXBGb3JtQ29udGFpbmVyKGRpcjogRm9ybUFycmF5TmFtZXxGb3JtR3JvdXBOYW1lKTogdm9pZCB7XG4gICAgY29uc3QgY3RybDogYW55ID0gdGhpcy5mb3JtLmdldChkaXIucGF0aCk7XG4gICAgc2V0VXBGb3JtQ29udGFpbmVyKGN0cmwsIGRpcik7XG4gICAgLy8gTk9URTogdGhpcyBvcGVyYXRpb24gbG9va3MgdW5uZWNlc3NhcnkgaW4gY2FzZSBubyBuZXcgdmFsaWRhdG9ycyB3ZXJlIGFkZGVkIGluXG4gICAgLy8gYHNldFVwRm9ybUNvbnRhaW5lcmAgY2FsbC4gQ29uc2lkZXIgdXBkYXRpbmcgdGhpcyBjb2RlIHRvIG1hdGNoIHRoZSBsb2dpYyBpblxuICAgIC8vIGBfY2xlYW5VcEZvcm1Db250YWluZXJgIGZ1bmN0aW9uLlxuICAgIGN0cmwudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7ZW1pdEV2ZW50OiBmYWxzZX0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2xlYW5VcEZvcm1Db250YWluZXIoZGlyOiBGb3JtQXJyYXlOYW1lfEZvcm1Hcm91cE5hbWUpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICBjb25zdCBjdHJsOiBhbnkgPSB0aGlzLmZvcm0uZ2V0KGRpci5wYXRoKTtcbiAgICAgIGlmIChjdHJsKSB7XG4gICAgICAgIGNvbnN0IGlzQ29udHJvbFVwZGF0ZWQgPSBjbGVhblVwRm9ybUNvbnRhaW5lcihjdHJsLCBkaXIpO1xuICAgICAgICBpZiAoaXNDb250cm9sVXBkYXRlZCkge1xuICAgICAgICAgIC8vIFJ1biB2YWxpZGl0eSBjaGVjayBvbmx5IGluIGNhc2UgYSBjb250cm9sIHdhcyB1cGRhdGVkIChpLmUuIHZpZXcgdmFsaWRhdG9ycyB3ZXJlXG4gICAgICAgICAgLy8gcmVtb3ZlZCkgYXMgcmVtb3ZpbmcgdmlldyB2YWxpZGF0b3JzIG1pZ2h0IGNhdXNlIHZhbGlkaXR5IHRvIGNoYW5nZS5cbiAgICAgICAgICBjdHJsLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoe2VtaXRFdmVudDogZmFsc2V9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3VwZGF0ZVJlZ2lzdHJhdGlvbnMoKSB7XG4gICAgdGhpcy5mb3JtLl9yZWdpc3Rlck9uQ29sbGVjdGlvbkNoYW5nZSh0aGlzLl9vbkNvbGxlY3Rpb25DaGFuZ2UpO1xuICAgIGlmICh0aGlzLl9vbGRGb3JtKSB7XG4gICAgICB0aGlzLl9vbGRGb3JtLl9yZWdpc3Rlck9uQ29sbGVjdGlvbkNoYW5nZSgoKSA9PiB7fSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlVmFsaWRhdG9ycygpIHtcbiAgICBzZXRVcFZhbGlkYXRvcnModGhpcy5mb3JtLCB0aGlzKTtcbiAgICBpZiAodGhpcy5fb2xkRm9ybSkge1xuICAgICAgY2xlYW5VcFZhbGlkYXRvcnModGhpcy5fb2xkRm9ybSwgdGhpcyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfY2hlY2tGb3JtUHJlc2VudCgpIHtcbiAgICBpZiAoIXRoaXMuZm9ybSAmJiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSkge1xuICAgICAgdGhyb3cgbWlzc2luZ0Zvcm1FeGNlcHRpb24oKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==