@angular/forms
Version:
Angular - directives and services for creating forms
331 lines • 40.1 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 { booleanAttribute, ChangeDetectorRef, Directive, EventEmitter, forwardRef, Host, Inject, Input, Optional, Output, Self } from '@angular/core';
import { FormControl } from '../model/form_control';
import { NG_ASYNC_VALIDATORS, NG_VALIDATORS } from '../validators';
import { AbstractFormGroupDirective } from './abstract_form_group_directive';
import { ControlContainer } from './control_container';
import { NG_VALUE_ACCESSOR } from './control_value_accessor';
import { NgControl } from './ng_control';
import { NgForm } from './ng_form';
import { NgModelGroup } from './ng_model_group';
import { CALL_SET_DISABLED_STATE, controlPath, isPropertyUpdated, selectValueAccessor, setUpControl } from './shared';
import { formGroupNameException, missingNameException, modelParentException } from './template_driven_errors';
import * as i0 from "@angular/core";
import * as i1 from "./control_container";
const formControlBinding = {
provide: NgControl,
useExisting: forwardRef(() => NgModel)
};
/**
* `ngModel` forces an additional change detection run when its inputs change:
* E.g.:
* ```
* <div>{{myModel.valid}}</div>
* <input [(ngModel)]="myValue" #myModel="ngModel">
* ```
* I.e. `ngModel` can export itself on the element and then be used in the template.
* Normally, this would result in expressions before the `input` that use the exported directive
* to have an old value as they have been
* dirty checked before. As this is a very common case for `ngModel`, we added this second change
* detection run.
*
* Notes:
* - this is just one extra run no matter how many `ngModel`s have been changed.
* - this is a general problem when using `exportAs` for directives!
*/
const resolvedPromise = (() => Promise.resolve())();
/**
* @description
* Creates a `FormControl` instance from a [domain
* model](https://en.wikipedia.org/wiki/Domain_model) and binds it to a form control element.
*
* The `FormControl` instance tracks the value, user interaction, and
* validation status of the control and keeps the view synced with the model. If used
* within a parent form, the directive also registers itself with the form as a child
* control.
*
* This directive is used by itself or as part of a larger form. Use the
* `ngModel` selector to activate it.
*
* It accepts a domain model as an optional `Input`. If you have a one-way binding
* to `ngModel` with `[]` syntax, changing the domain model's value in the component
* class sets the value in the view. If you have a two-way binding with `[()]` syntax
* (also known as 'banana-in-a-box syntax'), the value in the UI always syncs back to
* the domain model in your class.
*
* To inspect the properties of the associated `FormControl` (like the validity state),
* export the directive into a local template variable using `ngModel` as the key (ex:
* `#myVar="ngModel"`). You can then access the control using the directive's `control` property.
* However, the most commonly used properties (like `valid` and `dirty`) also exist on the control
* for direct access. See a full list of properties directly available in
* `AbstractControlDirective`.
*
* @see {@link RadioControlValueAccessor}
* @see {@link SelectControlValueAccessor}
*
* @usageNotes
*
* ### Using ngModel on a standalone control
*
* The following examples show a simple standalone control using `ngModel`:
*
* {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'}
*
* When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute
* so that the control can be registered with the parent form under that name.
*
* In the context of a parent form, it's often unnecessary to include one-way or two-way binding,
* as the parent form syncs the value for you. You access its properties by exporting it into a
* local template variable using `ngForm` such as (`#f="ngForm"`). Use the variable where
* needed on form submission.
*
* If you do need to populate initial values into your form, using a one-way binding for
* `ngModel` tends to be sufficient as long as you use the exported form's value rather
* than the domain model's value on submit.
*
* ### Using ngModel within a form
*
* The following example shows controls using `ngModel` within a form:
*
* {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
*
* ### Using a standalone ngModel within a group
*
* The following example shows you how to use a standalone ngModel control
* within a form. This controls the display of the form, but doesn't contain form data.
*
* ```html
* <form>
* <input name="login" ngModel placeholder="Login">
* <input type="checkbox" ngModel [ngModelOptions]="{standalone: true}"> Show more options?
* </form>
* <!-- form value: {login: ''} -->
* ```
*
* ### Setting the ngModel `name` attribute through options
*
* The following example shows you an alternate way to set the name attribute. Here,
* an attribute identified as name is used within a custom form control component. To still be able
* to specify the NgModel's name, you must specify it using the `ngModelOptions` input instead.
*
* ```html
* <form>
* <my-custom-form-control name="Nancy" ngModel [ngModelOptions]="{name: 'user'}">
* </my-custom-form-control>
* </form>
* <!-- form value: {user: ''} -->
* ```
*
* @ngModule FormsModule
* @publicApi
*/
export class NgModel extends NgControl {
constructor(parent, validators, asyncValidators, valueAccessors, _changeDetectorRef, callSetDisabledState) {
super();
this._changeDetectorRef = _changeDetectorRef;
this.callSetDisabledState = callSetDisabledState;
this.control = new FormControl();
/** @internal */
this._registered = false;
/**
* @description
* Tracks the name bound to the directive. If a parent form exists, it
* uses this name as a key to retrieve this control's value.
*/
this.name = '';
/**
* @description
* Event emitter for producing the `ngModelChange` event after
* the view model updates.
*/
this.update = new EventEmitter();
this._parent = parent;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
this.valueAccessor = selectValueAccessor(this, valueAccessors);
}
/** @nodoc */
ngOnChanges(changes) {
this._checkForErrors();
if (!this._registered || 'name' in changes) {
if (this._registered) {
this._checkName();
if (this.formDirective) {
// We can't call `formDirective.removeControl(this)`, because the `name` has already been
// changed. We also can't reset the name temporarily since the logic in `removeControl`
// is inside a promise and it won't run immediately. We work around it by giving it an
// object with the same shape instead.
const oldName = changes['name'].previousValue;
this.formDirective.removeControl({ name: oldName, path: this._getPath(oldName) });
}
}
this._setUpControl();
}
if ('isDisabled' in changes) {
this._updateDisabled(changes);
}
if (isPropertyUpdated(changes, this.viewModel)) {
this._updateValue(this.model);
this.viewModel = this.model;
}
}
/** @nodoc */
ngOnDestroy() {
this.formDirective && this.formDirective.removeControl(this);
}
/**
* @description
* Returns an array that represents the path from the top-level form to this control.
* Each index is the string name of the control on that level.
*/
get path() {
return this._getPath(this.name);
}
/**
* @description
* The top-level directive for this control if present, otherwise null.
*/
get formDirective() {
return this._parent ? this._parent.formDirective : null;
}
/**
* @description
* Sets the new value for the view model and emits an `ngModelChange` event.
*
* @param newValue The new value emitted by `ngModelChange`.
*/
viewToModelUpdate(newValue) {
this.viewModel = newValue;
this.update.emit(newValue);
}
_setUpControl() {
this._setUpdateStrategy();
this._isStandalone() ? this._setUpStandalone() : this.formDirective.addControl(this);
this._registered = true;
}
_setUpdateStrategy() {
if (this.options && this.options.updateOn != null) {
this.control._updateOn = this.options.updateOn;
}
}
_isStandalone() {
return !this._parent || !!(this.options && this.options.standalone);
}
_setUpStandalone() {
setUpControl(this.control, this, this.callSetDisabledState);
this.control.updateValueAndValidity({ emitEvent: false });
}
_checkForErrors() {
if (!this._isStandalone()) {
this._checkParentType();
}
this._checkName();
}
_checkParentType() {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (!(this._parent instanceof NgModelGroup) &&
this._parent instanceof AbstractFormGroupDirective) {
throw formGroupNameException();
}
else if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm)) {
throw modelParentException();
}
}
}
_checkName() {
if (this.options && this.options.name)
this.name = this.options.name;
if (!this._isStandalone() && !this.name && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw missingNameException();
}
}
_updateValue(value) {
resolvedPromise.then(() => {
this.control.setValue(value, { emitViewToModelChange: false });
this._changeDetectorRef?.markForCheck();
});
}
_updateDisabled(changes) {
const disabledValue = changes['isDisabled'].currentValue;
// checking for 0 to avoid breaking change
const isDisabled = disabledValue !== 0 && booleanAttribute(disabledValue);
resolvedPromise.then(() => {
if (isDisabled && !this.control.disabled) {
this.control.disable();
}
else if (!isDisabled && this.control.disabled) {
this.control.enable();
}
this._changeDetectorRef?.markForCheck();
});
}
_getPath(controlName) {
return this._parent ? controlPath(controlName, this._parent) : [controlName];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NgModel, deps: [{ token: i1.ControlContainer, host: true, optional: true }, { token: NG_VALIDATORS, optional: true, self: true }, { token: NG_ASYNC_VALIDATORS, optional: true, self: true }, { token: NG_VALUE_ACCESSOR, optional: true, self: true }, { token: ChangeDetectorRef, optional: true }, { token: CALL_SET_DISABLED_STATE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.5", type: NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: { name: "name", isDisabled: ["disabled", "isDisabled"], model: ["ngModel", "model"], options: ["ngModelOptions", "options"] }, outputs: { update: "ngModelChange" }, providers: [formControlBinding], exportAs: ["ngModel"], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: NgModel, decorators: [{
type: Directive,
args: [{
selector: '[ngModel]:not([formControlName]):not([formControl])',
providers: [formControlBinding],
exportAs: 'ngModel'
}]
}], ctorParameters: () => [{ type: i1.ControlContainer, decorators: [{
type: Optional
}, {
type: Host
}] }, { 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: Self
}, {
type: Inject,
args: [NG_VALUE_ACCESSOR]
}] }, { type: i0.ChangeDetectorRef, decorators: [{
type: Optional
}, {
type: Inject,
args: [ChangeDetectorRef]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [CALL_SET_DISABLED_STATE]
}] }], propDecorators: { name: [{
type: Input
}], isDisabled: [{
type: Input,
args: ['disabled']
}], model: [{
type: Input,
args: ['ngModel']
}], options: [{
type: Input,
args: ['ngModelOptions']
}], update: [{
type: Output,
args: ['ngModelChange']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdfbW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9mb3Jtcy9zcmMvZGlyZWN0aXZlcy9uZ19tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQXdCLFFBQVEsRUFBRSxNQUFNLEVBQVksSUFBSSxFQUFnQixNQUFNLGVBQWUsQ0FBQztBQUduTSxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDbEQsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGFBQWEsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUVqRSxPQUFPLEVBQUMsMEJBQTBCLEVBQUMsTUFBTSxpQ0FBaUMsQ0FBQztBQUMzRSxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQXVCLGlCQUFpQixFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDakYsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUN2QyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUM5QyxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLG1CQUFtQixFQUEwQixZQUFZLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDNUksT0FBTyxFQUFDLHNCQUFzQixFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUFDLE1BQU0sMEJBQTBCLENBQUM7OztBQUc1RyxNQUFNLGtCQUFrQixHQUFhO0lBQ25DLE9BQU8sRUFBRSxTQUFTO0lBQ2xCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FB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QkFBQztvQkFDVCxRQUFRLEVBQUUscURBQXFEO29CQUMvRCxTQUFTLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQztvQkFDL0IsUUFBUSxFQUFFLFNBQVM7aUJBQ3BCOzswQkFxRU0sUUFBUTs7MEJBQUksSUFBSTs7MEJBQ2hCLFFBQVE7OzBCQUFJLElBQUk7OzBCQUFJLE1BQU07MkJBQUMsYUFBYTs7MEJBQ3hDLFFBQVE7OzBCQUFJLElBQUk7OzBCQUFJLE1BQU07MkJBQUMsbUJBQW1COzswQkFFOUMsUUFBUTs7MEJBQUksSUFBSTs7MEJBQUksTUFBTTsyQkFBQyxpQkFBaUI7OzBCQUM1QyxRQUFROzswQkFBSSxNQUFNOzJCQUFDLGlCQUFpQjs7MEJBQ3BDLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsdUJBQXVCO3lDQWhEN0IsSUFBSTtzQkFBckIsS0FBSztnQkFPYSxVQUFVO3NCQUE1QixLQUFLO3VCQUFDLFVBQVU7Z0JBTUMsS0FBSztzQkFBdEIsS0FBSzt1QkFBQyxTQUFTO2dCQW1CUyxPQUFPO3NCQUEvQixLQUFLO3VCQUFDLGdCQUFnQjtnQkFPRSxNQUFNO3NCQUE5QixNQUFNO3VCQUFDLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtib29sZWFuQXR0cmlidXRlLCBDaGFuZ2VEZXRlY3RvclJlZiwgRGlyZWN0aXZlLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIEhvc3QsIEluamVjdCwgSW5wdXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPcHRpb25hbCwgT3V0cHV0LCBQcm92aWRlciwgU2VsZiwgU2ltcGxlQ2hhbmdlc30gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7Rm9ybUhvb2tzfSBmcm9tICcuLi9tb2RlbC9hYnN0cmFjdF9tb2RlbCc7XG5pbXBvcnQge0Zvcm1Db250cm9sfSBmcm9tICcuLi9tb2RlbC9mb3JtX2NvbnRyb2wnO1xuaW1wb3J0IHtOR19BU1lOQ19WQUxJREFUT1JTLCBOR19WQUxJREFUT1JTfSBmcm9tICcuLi92YWxpZGF0b3JzJztcblxuaW1wb3J0IHtBYnN0cmFjdEZvcm1Hcm91cERpcmVjdGl2ZX0gZnJvbSAnLi9hYnN0cmFjdF9mb3JtX2dyb3VwX2RpcmVjdGl2ZSc7XG5pbXBvcnQge0NvbnRyb2xDb250YWluZXJ9IGZyb20gJy4vY29udHJvbF9jb250YWluZXInO1xuaW1wb3J0IHtDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1J9IGZyb20gJy4vY29udHJvbF92YWx1ZV9hY2Nlc3Nvcic7XG5pbXBvcnQge05nQ29udHJvbH0gZnJvbSAnLi9uZ19jb250cm9sJztcbmltcG9ydCB7TmdGb3JtfSBmcm9tICcuL25nX2Zvcm0nO1xuaW1wb3J0IHtOZ01vZGVsR3JvdXB9IGZyb20gJy4vbmdfbW9kZWxfZ3JvdXAnO1xuaW1wb3J0IHtDQUxMX1NFVF9ESVNBQkxFRF9TVEFURSwgY29udHJvbFBhdGgsIGlzUHJvcGVydHlVcGRhdGVkLCBzZWxlY3RWYWx1ZUFjY2Vzc29yLCBTZXREaXNhYmxlZFN0YXRlT3B0aW9uLCBzZXRVcENvbnRyb2x9IGZyb20gJy4vc2hhcmVkJztcbmltcG9ydCB7Zm9ybUdyb3VwTmFtZUV4Y2VwdGlvbiwgbWlzc2luZ05hbWVFeGNlcHRpb24sIG1vZGVsUGFyZW50RXhjZXB0aW9ufSBmcm9tICcuL3RlbXBsYXRlX2RyaXZlbl9lcnJvcnMnO1xuaW1wb3J0IHtBc3luY1ZhbGlkYXRvciwgQXN5bmNWYWxpZGF0b3JGbiwgVmFsaWRhdG9yLCBWYWxpZGF0b3JGbn0gZnJvbSAnLi92YWxpZGF0b3JzJztcblxuY29uc3QgZm9ybUNvbnRyb2xCaW5kaW5nOiBQcm92aWRlciA9IHtcbiAgcHJvdmlkZTogTmdDb250cm9sLFxuICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ01vZGVsKVxufTtcblxuLyoqXG4gKiBgbmdNb2RlbGAgZm9yY2VzIGFuIGFkZGl0aW9uYWwgY2hhbmdlIGRldGVjdGlvbiBydW4gd2hlbiBpdHMgaW5wdXRzIGNoYW5nZTpcbiAqIEUuZy46XG4gKiBgYGBcbiAqIDxkaXY+e3tteU1vZGVsLnZhbGlkfX08L2Rpdj5cbiAqIDxpbnB1dCBbKG5nTW9kZWwpXT1cIm15VmFsdWVcIiAjbXlNb2RlbD1cIm5nTW9kZWxcIj5cbiAqIGBgYFxuICogSS5lLiBgbmdNb2RlbGAgY2FuIGV4cG9ydCBpdHNlbGYgb24gdGhlIGVsZW1lbnQgYW5kIHRoZW4gYmUgdXNlZCBpbiB0aGUgdGVtcGxhdGUuXG4gKiBOb3JtYWxseSwgdGhpcyB3b3VsZCByZXN1bHQgaW4gZXhwcmVzc2lvbnMgYmVmb3JlIHRoZSBgaW5wdXRgIHRoYXQgdXNlIHRoZSBleHBvcnRlZCBkaXJlY3RpdmVcbiAqIHRvIGhhdmUgYW4gb2xkIHZhbHVlIGFzIHRoZXkgaGF2ZSBiZWVuXG4gKiBkaXJ0eSBjaGVja2VkIGJlZm9yZS4gQXMgdGhpcyBpcyBhIHZlcnkgY29tbW9uIGNhc2UgZm9yIGBuZ01vZGVsYCwgd2UgYWRkZWQgdGhpcyBzZWNvbmQgY2hhbmdlXG4gKiBkZXRlY3Rpb24gcnVuLlxuICpcbiAqIE5vdGVzOlxuICogLSB0aGlzIGlzIGp1c3Qgb25lIGV4dHJhIHJ1biBubyBtYXR0ZXIgaG93IG1hbnkgYG5nTW9kZWxgcyBoYXZlIGJlZW4gY2hhbmdlZC5cbiAqIC0gdGhpcyBpcyBhIGdlbmVyYWwgcHJvYmxlbSB3aGVuIHVzaW5nIGBleHBvcnRBc2AgZm9yIGRpcmVjdGl2ZXMhXG4gKi9cbmNvbnN0IHJlc29sdmVkUHJvbWlzZSA9ICgoKSA9PiBQcm9taXNlLnJlc29sdmUoKSkoKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqIENyZWF0ZXMgYSBgRm9ybUNvbnRyb2xgIGluc3RhbmNlIGZyb20gYSBbZG9tYWluXG4gKiBtb2RlbF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRG9tYWluX21vZGVsKSBhbmQgYmluZHMgaXQgdG8gYSBmb3JtIGNvbnRyb2wgZWxlbWVudC5cbiAqXG4gKiBUaGUgYEZvcm1Db250cm9sYCBpbnN0YW5jZSB0cmFja3MgdGhlIHZhbHVlLCB1c2VyIGludGVyYWN0aW9uLCBhbmRcbiAqIHZhbGlkYXRpb24gc3RhdHVzIG9mIHRoZSBjb250cm9sIGFuZCBrZWVwcyB0aGUgdmlldyBzeW5jZWQgd2l0aCB0aGUgbW9kZWwuIElmIHVzZWRcbiAqIHdpdGhpbiBhIHBhcmVudCBmb3JtLCB0aGUgZGlyZWN0aXZlIGFsc28gcmVnaXN0ZXJzIGl0c2VsZiB3aXRoIHRoZSBmb3JtIGFzIGEgY2hpbGRcbiAqIGNvbnRyb2wuXG4gKlxuICogVGhpcyBkaXJlY3RpdmUgaXMgdXNlZCBieSBpdHNlbGYgb3IgYXMgcGFydCBvZiBhIGxhcmdlciBmb3JtLiBVc2UgdGhlXG4gKiBgbmdNb2RlbGAgc2VsZWN0b3IgdG8gYWN0aXZhdGUgaXQuXG4gKlxuICogSXQgYWNjZXB0cyBhIGRvbWFpbiBtb2RlbCBhcyBhbiBvcHRpb25hbCBgSW5wdXRgLiBJZiB5b3UgaGF2ZSBhIG9uZS13YXkgYmluZGluZ1xuICogdG8gYG5nTW9kZWxgIHdpdGggYFtdYCBzeW50YXgsIGNoYW5naW5nIHRoZSBkb21haW4gbW9kZWwncyB2YWx1ZSBpbiB0aGUgY29tcG9uZW50XG4gKiBjbGFzcyBzZXRzIHRoZSB2YWx1ZSBpbiB0aGUgdmlldy4gSWYgeW91IGhhdmUgYSB0d28td2F5IGJpbmRpbmcgd2l0aCBgWygpXWAgc3ludGF4XG4gKiAoYWxzbyBrbm93biBhcyAnYmFuYW5hLWluLWEtYm94IHN5bnRheCcpLCB0aGUgdmFsdWUgaW4gdGhlIFVJIGFsd2F5cyBzeW5jcyBiYWNrIHRvXG4gKiB0aGUgZG9tYWluIG1vZGVsIGluIHlvdXIgY2xhc3MuXG4gKlxuICogVG8gaW5zcGVjdCB0aGUgcHJvcGVydGllcyBvZiB0aGUgYXNzb2NpYXRlZCBgRm9ybUNvbnRyb2xgIChsaWtlIHRoZSB2YWxpZGl0eSBzdGF0ZSksXG4gKiBleHBvcnQgdGhlIGRpcmVjdGl2ZSBpbnRvIGEgbG9jYWwgdGVtcGxhdGUgdmFyaWFibGUgdXNpbmcgYG5nTW9kZWxgIGFzIHRoZSBrZXkgKGV4OlxuICogYCNteVZhcj1cIm5nTW9kZWxcImApLiBZb3UgY2FuIHRoZW4gYWNjZXNzIHRoZSBjb250cm9sIHVzaW5nIHRoZSBkaXJlY3RpdmUncyBgY29udHJvbGAgcHJvcGVydHkuXG4gKiBIb3dldmVyLCB0aGUgbW9zdCBjb21tb25seSB1c2VkIHByb3BlcnRpZXMgKGxpa2UgYHZhbGlkYCBhbmQgYGRpcnR5YCkgYWxzbyBleGlzdCBvbiB0aGUgY29udHJvbFxuICogZm9yIGRpcmVjdCBhY2Nlc3MuIFNlZSBhIGZ1bGwgbGlzdCBvZiBwcm9wZXJ0aWVzIGRpcmVjdGx5IGF2YWlsYWJsZSBpblxuICogYEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZWAuXG4gKlxuICogQHNlZSB7QGxpbmsgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvcn1cbiAqIEBzZWUge0BsaW5rIFNlbGVjdENvbnRyb2xWYWx1ZUFjY2Vzc29yfVxuICpcbiAqIEB1c2FnZU5vdGVzXG4gKlxuICogIyMjIFVzaW5nIG5nTW9kZWwgb24gYSBzdGFuZGFsb25lIGNvbnRyb2xcbiAqXG4gKiBUaGUgZm9sbG93aW5nIGV4YW1wbGVzIHNob3cgYSBzaW1wbGUgc3RhbmRhbG9uZSBjb250cm9sIHVzaW5nIGBuZ01vZGVsYDpcbiAqXG4gKiB7QGV4YW1wbGUgZm9ybXMvdHMvc2ltcGxlTmdNb2RlbC9zaW1wbGVfbmdfbW9kZWxfZXhhbXBsZS50cyByZWdpb249J0NvbXBvbmVudCd9XG4gKlxuICogV2hlbiB1c2luZyB0aGUgYG5nTW9kZWxgIHdpdGhpbiBgPGZvcm0+YCB0YWdzLCB5b3UnbGwgYWxzbyBuZWVkIHRvIHN1cHBseSBhIGBuYW1lYCBhdHRyaWJ1dGVcbiAqIHNvIHRoYXQgdGhlIGNvbnRyb2wgY2FuIGJlIHJlZ2lzdGVyZWQgd2l0aCB0aGUgcGFyZW50IGZvcm0gdW5kZXIgdGhhdCBuYW1lLlxuICpcbiAqIEluIHRoZSBjb250ZXh0IG9mIGEgcGFyZW50IGZvcm0sIGl0J3Mgb2Z0ZW4gdW5uZWNlc3NhcnkgdG8gaW5jbHVkZSBvbmUtd2F5IG9yIHR3by13YXkgYmluZGluZyxcbiAqIGFzIHRoZSBwYXJlbnQgZm9ybSBzeW5jcyB0aGUgdmFsdWUgZm9yIHlvdS4gWW91IGFjY2VzcyBpdHMgcHJvcGVydGllcyBieSBleHBvcnRpbmcgaXQgaW50byBhXG4gKiBsb2NhbCB0ZW1wbGF0ZSB2YXJpYWJsZSB1c2luZyBgbmdGb3JtYCBzdWNoIGFzIChgI2Y9XCJuZ0Zvcm1cImApLiBVc2UgdGhlIHZhcmlhYmxlIHdoZXJlXG4gKiBuZWVkZWQgb24gZm9ybSBzdWJtaXNzaW9uLlxuICpcbiAqIElmIHlvdSBkbyBuZWVkIHRvIHBvcHVsYXRlIGluaXRpYWwgdmFsdWVzIGludG8geW91ciBmb3JtLCB1c2luZyBhIG9uZS13YXkgYmluZGluZyBmb3JcbiAqIGBuZ01vZGVsYCB0ZW5kcyB0byBiZSBzdWZmaWNpZW50IGFzIGxvbmcgYXMgeW91IHVzZSB0aGUgZXhwb3J0ZWQgZm9ybSdzIHZhbHVlIHJhdGhlclxuICogdGhhbiB0aGUgZG9tYWluIG1vZGVsJ3MgdmFsdWUgb24gc3VibWl0LlxuICpcbiAqICMjIyBVc2luZyBuZ01vZGVsIHdpdGhpbiBhIGZvcm1cbiAqXG4gKiBUaGUgZm9sbG93aW5nIGV4YW1wbGUgc2hvd3MgY29udHJvbHMgdXNpbmcgYG5nTW9kZWxgIHdpdGhpbiBhIGZvcm06XG4gKlxuICoge0BleGFtcGxlIGZvcm1zL3RzL3NpbXBsZUZvcm0vc2ltcGxlX2Zvcm1fZXhhbXBsZS50cyByZWdpb249J0NvbXBvbmVudCd9XG4gKlxuICogIyMjIFVzaW5nIGEgc3RhbmRhbG9uZSBuZ01vZGVsIHdpdGhpbiBhIGdyb3VwXG4gKlxuICogVGhlIGZvbGxvd2luZyBleGFtcGxlIHNob3dzIHlvdSBob3cgdG8gdXNlIGEgc3RhbmRhbG9uZSBuZ01vZGVsIGNvbnRyb2xcbiAqIHdpdGhpbiBhIGZvcm0uIFRoaXMgY29udHJvbHMgdGhlIGRpc3BsYXkgb2YgdGhlIGZvcm0sIGJ1dCBkb2Vzbid0IGNvbnRhaW4gZm9ybSBkYXRhLlxuICpcbiAqIGBgYGh0bWxcbiAqIDxmb3JtPlxuICogICA8aW5wdXQgbmFtZT1cImxvZ2luXCIgbmdNb2RlbCBwbGFjZWhvbGRlcj1cIkxvZ2luXCI+XG4gKiAgIDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBuZ01vZGVsIFtuZ01vZGVsT3B0aW9uc109XCJ7c3RhbmRhbG9uZTogdHJ1ZX1cIj4gU2hvdyBtb3JlIG9wdGlvbnM/XG4gKiA8L2Zvcm0+XG4gKiA8IS0tIGZvcm0gdmFsdWU6IHtsb2dpbjogJyd9IC0tPlxuICogYGBgXG4gKlxuICogIyMjIFNldHRpbmcgdGhlIG5nTW9kZWwgYG5hbWVgIGF0dHJpYnV0ZSB0aHJvdWdoIG9wdGlvbnNcbiAqXG4gKiBUaGUgZm9sbG93aW5nIGV4YW1wbGUgc2hvd3MgeW91IGFuIGFsdGVybmF0ZSB3YXkgdG8gc2V0IHRoZSBuYW1lIGF0dHJpYnV0ZS4gSGVyZSxcbiAqIGFuIGF0dHJpYnV0ZSBpZGVudGlmaWVkIGFzIG5hbWUgaXMgdXNlZCB3aXRoaW4gYSBjdXN0b20gZm9ybSBjb250cm9sIGNvbXBvbmVudC4gVG8gc3RpbGwgYmUgYWJsZVxuICogdG8gc3BlY2lmeSB0aGUgTmdNb2RlbCdzIG5hbWUsIHlvdSBtdXN0IHNwZWNpZnkgaXQgdXNpbmcgdGhlIGBuZ01vZGVsT3B0aW9uc2AgaW5wdXQgaW5zdGVhZC5cbiAqXG4gKiBgYGBodG1sXG4gKiA8Zm9ybT5cbiAqICAgPG15LWN1c3RvbS1mb3JtLWNvbnRyb2wgbmFtZT1cIk5hbmN5XCIgbmdNb2RlbCBbbmdNb2RlbE9wdGlvbnNdPVwie25hbWU6ICd1c2VyJ31cIj5cbiAqICAgPC9teS1jdXN0b20tZm9ybS1jb250cm9sPlxuICogPC9mb3JtPlxuICogPCEtLSBmb3JtIHZhbHVlOiB7dXNlcjogJyd9IC0tPlxuICogYGBgXG4gKlxuICogQG5nTW9kdWxlIEZvcm1zTW9kdWxlXG4gKiBAcHVibGljQXBpXG4gKi9cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tuZ01vZGVsXTpub3QoW2Zvcm1Db250cm9sTmFtZV0pOm5vdChbZm9ybUNvbnRyb2xdKScsXG4gIHByb3ZpZGVyczogW2Zvcm1Db250cm9sQmluZGluZ10sXG4gIGV4cG9ydEFzOiAnbmdNb2RlbCdcbn0pXG5leHBvcnQgY2xhc3MgTmdNb2RlbCBleHRlbmRzIE5nQ29udHJvbCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgcHVibGljIG92ZXJyaWRlIHJlYWRvbmx5IGNvbnRyb2w6IEZvcm1Db250cm9sID0gbmV3IEZvcm1Db250cm9sKCk7XG5cbiAgLy8gQXQgcnVudGltZSB3ZSBjb2VyY2UgYXJiaXRyYXJ5IHZhbHVlcyBhc3NpZ25lZCB0byB0aGUgXCJkaXNhYmxlZFwiIGlucHV0IHRvIGEgXCJib29sZWFuXCIuXG4gIC8vIFRoaXMgaXMgbm90IHJlZmxlY3RlZCBpbiB0aGUgdHlwZSBvZiB0aGUgcHJvcGVydHkgYmVjYXVzZSBvdXRzaWRlIG9mIHRlbXBsYXRlcywgY29uc3VtZXJzXG4gIC8vIHNob3VsZCBvbmx5IGRlYWwgd2l0aCBib29sZWFucy4gSW4gdGVtcGxhdGVzLCBhIHN0cmluZyBpcyBhbGxvd2VkIGZvciBjb252ZW5pZW5jZSBhbmQgdG9cbiAgLy8gbWF0Y2ggdGhlIG5hdGl2ZSBcImRpc2FibGVkIGF0dHJpYnV0ZVwiIHNlbWFudGljcyB3aGljaCBjYW4gYmUgb2JzZXJ2ZWQgb24gaW5wdXQgZWxlbWVudHMuXG4gIC8vIFRoaXMgc3RhdGljIG1lbWJlciB0ZWxscyB0aGUgY29tcGlsZXIgdGhhdCB2YWx1ZXMgb2YgdHlwZSBcInN0cmluZ1wiIGNhbiBhbHNvIGJlIGFzc2lnbmVkXG4gIC8vIHRvIHRoZSBpbnB1dCBpbiBhIHRlbXBsYXRlLlxuICAvKiogQG5vZG9jICovXG4gIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9pc0Rpc2FibGVkOiBib29sZWFufHN0cmluZztcblxuICAvKiogQGludGVybmFsICovXG4gIF9yZWdpc3RlcmVkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEludGVybmFsIHJlZmVyZW5jZSB0byB0aGUgdmlldyBtb2RlbCB2YWx1ZS5cbiAgICogQG5vZG9jXG4gICAqL1xuICB2aWV3TW9kZWw6IGFueTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRyYWNrcyB0aGUgbmFtZSBib3VuZCB0byB0aGUgZGlyZWN0aXZlLiBJZiBhIHBhcmVudCBmb3JtIGV4aXN0cywgaXRcbiAgICogdXNlcyB0aGlzIG5hbWUgYXMgYSBrZXkgdG8gcmV0cmlldmUgdGhpcyBjb250cm9sJ3MgdmFsdWUuXG4gICAqL1xuICBASW5wdXQoKSBvdmVycmlkZSBuYW1lOiBzdHJpbmcgPSAnJztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRyYWNrcyB3aGV0aGVyIHRoZSBjb250cm9sIGlzIGRpc2FibGVkLlxuICAgKi9cbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIEBJbnB1dCgnZGlzYWJsZWQnKSBpc0Rpc2FibGVkITogYm9vbGVhbjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRyYWNrcyB0aGUgdmFsdWUgYm91bmQgdG8gdGhpcyBkaXJlY3RpdmUuXG4gICAqL1xuICBASW5wdXQoJ25nTW9kZWwnKSBtb2RlbDogYW55O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogVHJhY2tzIHRoZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoaXMgYG5nTW9kZWxgIGluc3RhbmNlLlxuICAgKlxuICAgKiAqKm5hbWUqKjogQW4gYWx0ZXJuYXRpdmUgdG8gc2V0dGluZyB0aGUgbmFtZSBhdHRyaWJ1dGUgb24gdGhlIGZvcm0gY29udHJvbCBlbGVtZW50LiBTZWVcbiAgICogdGhlIFtleGFtcGxlXShhcGkvZm9ybXMvTmdNb2RlbCN1c2luZy1uZ21vZGVsLW9uLWEtc3RhbmRhbG9uZS1jb250cm9sKSBmb3IgdXNpbmcgYE5nTW9kZWxgXG4gICAqIGFzIGEgc3RhbmRhbG9uZSBjb250cm9sLlxuICAgKlxuICAgKiAqKnN0YW5kYWxvbmUqKjogV2hlbiBzZXQgdG8gdHJ1ZSwgdGhlIGBuZ01vZGVsYCB3aWxsIG5vdCByZWdpc3RlciBpdHNlbGYgd2l0aCBpdHMgcGFyZW50IGZvcm0sXG4gICAqIGFuZCBhY3RzIGFzIGlmIGl0J3Mgbm90IGluIHRoZSBmb3JtLiBEZWZhdWx0cyB0byBmYWxzZS4gSWYgbm8gcGFyZW50IGZvcm0gZXhpc3RzLCB0aGlzIG9wdGlvblxuICAgKiBoYXMgbm8gZWZmZWN0LlxuICAgKlxuICAgKiAqKnVwZGF0ZU9uKio6IERlZmluZXMgdGhlIGV2ZW50IHVwb24gd2hpY2ggdGhlIGZvcm0gY29udHJvbCB2YWx1ZSBhbmQgdmFsaWRpdHkgdXBkYXRlLlxuICAgKiBEZWZhdWx0cyB0byAnY2hhbmdlJy4gUG9zc2libGUgdmFsdWVzOiBgJ2NoYW5nZSdgIHwgYCdibHVyJ2AgfCBgJ3N1Ym1pdCdgLlxuICAgKlxuICAgKi9cbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIEBJbnB1dCgnbmdNb2RlbE9wdGlvbnMnKSBvcHRpb25zIToge25hbWU/OiBzdHJpbmcsIHN0YW5kYWxvbmU/OiBib29sZWFuLCB1cGRhdGVPbj86IEZvcm1Ib29rc307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBFdmVudCBlbWl0dGVyIGZvciBwcm9kdWNpbmcgdGhlIGBuZ01vZGVsQ2hhbmdlYCBldmVudCBhZnRlclxuICAgKiB0aGUgdmlldyBtb2RlbCB1cGRhdGVzLlxuICAgKi9cbiAgQE91dHB1dCgnbmdNb2RlbENoYW5nZScpIHVwZGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIEBPcHRpb25hbCgpIEBIb3N0KCkgcGFyZW50OiBDb250cm9sQ29udGFpbmVyLFxuICAgICAgQE9wdGlvbmFsKCkgQFNlbGYoKSBASW5qZWN0KE5HX1ZBTElEQVRPUlMpIHZhbGlkYXRvcnM6IChWYWxpZGF0b3J8VmFsaWRhdG9yRm4pW10sXG4gICAgICBAT3B0aW9uYWwoKSBAU2VsZigpIEBJbmplY3QoTkdfQVNZTkNfVkFMSURBVE9SUykgYXN5bmNWYWxpZGF0b3JzOlxuICAgICAgICAgIChBc3luY1ZhbGlkYXRvcnxBc3luY1ZhbGlkYXRvckZuKVtdLFxuICAgICAgQE9wdGlvbmFsKCkgQFNlbGYoKSBASW5qZWN0KE5HX1ZBTFVFX0FDQ0VTU09SKSB2YWx1ZUFjY2Vzc29yczogQ29udHJvbFZhbHVlQWNjZXNzb3JbXSxcbiAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpIHByaXZhdGUgX2NoYW5nZURldGVjdG9yUmVmPzogQ2hhbmdlRGV0ZWN0b3JSZWZ8bnVsbCxcbiAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoQ0FMTF9TRVRfRElTQUJMRURfU1RBVEUpIHByaXZhdGUgY2FsbFNldERpc2FibGVkU3RhdGU/OlxuICAgICAgICAgIFNldERpc2FibGVkU3RhdGVPcHRpb24pIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudDtcbiAgICB0aGlzLl9zZXRWYWxpZGF0b3JzKHZhbGlkYXRvcnMpO1xuICAgIHRoaXMuX3NldEFzeW5jVmFsaWRhdG9ycyhhc3luY1ZhbGlkYXRvcnMpO1xuICAgIHRoaXMudmFsdWVBY2Nlc3NvciA9IHNlbGVjdFZhbHVlQWNjZXNzb3IodGhpcywgdmFsdWVBY2Nlc3NvcnMpO1xuICB9XG5cbiAgLyoqIEBub2RvYyAqL1xuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgdGhpcy5fY2hlY2tGb3JFcnJvcnMoKTtcbiAgICBpZiAoIXRoaXMuX3JlZ2lzdGVyZWQgfHwgJ25hbWUnIGluIGNoYW5nZXMpIHtcbiAgICAgIGlmICh0aGlzLl9yZWdpc3RlcmVkKSB7XG4gICAgICAgIHRoaXMuX2NoZWNrTmFtZSgpO1xuICAgICAgICBpZiAodGhpcy5mb3JtRGlyZWN0aXZlKSB7XG4gICAgICAgICAgLy8gV2UgY2FuJ3QgY2FsbCBgZm9ybURpcmVjdGl2ZS5yZW1vdmVDb250cm9sKHRoaXMpYCwgYmVjYXVzZSB0aGUgYG5hbWVgIGhhcyBhbHJlYWR5IGJlZW5cbiAgICAgICAgICAvLyBjaGFuZ2VkLiBXZSBhbHNvIGNhbid0IHJlc2V0IHRoZSBuYW1lIHRlbXBvcmFyaWx5IHNpbmNlIHRoZSBsb2dpYyBpbiBgcmVtb3ZlQ29udHJvbGBcbiAgICAgICAgICAvLyBpcyBpbnNpZGUgYSBwcm9taXNlIGFuZCBpdCB3b24ndCBydW4gaW1tZWRpYXRlbHkuIFdlIHdvcmsgYXJvdW5kIGl0IGJ5IGdpdmluZyBpdCBhblxuICAgICAgICAgIC8vIG9iamVjdCB3aXRoIHRoZSBzYW1lIHNoYXBlIGluc3RlYWQuXG4gICAgICAgICAgY29uc3Qgb2xkTmFtZSA9IGNoYW5nZXNbJ25hbWUnXS5wcmV2aW91c1ZhbHVlO1xuICAgICAgICAgIHRoaXMuZm9ybURpcmVjdGl2ZS5yZW1vdmVDb250cm9sKHtuYW1lOiBvbGROYW1lLCBwYXRoOiB0aGlzLl9nZXRQYXRoKG9sZE5hbWUpfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuX3NldFVwQ29udHJvbCgpO1xuICAgIH1cbiAgICBpZiAoJ2lzRGlzYWJsZWQnIGluIGNoYW5nZXMpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURpc2FibGVkKGNoYW5nZXMpO1xuICAgIH1cblxuICAgIGlmIChpc1Byb3BlcnR5VXBkYXRlZChjaGFuZ2VzLCB0aGlzLnZpZXdNb2RlbCkpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVZhbHVlKHRoaXMubW9kZWwpO1xuICAgICAgdGhpcy52aWV3TW9kZWwgPSB0aGlzLm1vZGVsO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAbm9kb2MgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5mb3JtRGlyZWN0aXZlICYmIHRoaXMuZm9ybURpcmVjdGl2ZS5yZW1vdmVDb250cm9sKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBSZXR1cm5zIGFuIGFycmF5IHRoYXQgcmVwcmVzZW50cyB0aGUgcGF0aCBmcm9tIHRoZSB0b3AtbGV2ZWwgZm9ybSB0byB0aGlzIGNvbnRyb2wuXG4gICAqIEVhY2ggaW5kZXggaXMgdGhlIHN0cmluZyBuYW1lIG9mIHRoZSBjb250cm9sIG9uIHRoYXQgbGV2ZWwuXG4gICAqL1xuICBvdmVycmlkZSBnZXQgcGF0aCgpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldFBhdGgodGhpcy5uYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogVGhlIHRvcC1sZXZlbCBkaXJlY3RpdmUgZm9yIHRoaXMgY29udHJvbCBpZiBwcmVzZW50LCBvdGhlcndpc2UgbnVsbC5cbiAgICovXG4gIGdldCBmb3JtRGlyZWN0aXZlKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhcmVudCA/IHRoaXMuX3BhcmVudC5mb3JtRGlyZWN0aXZlIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogU2V0cyB0aGUgbmV3IHZhbHVlIGZvciB0aGUgdmlldyBtb2RlbCBhbmQgZW1pdHMgYW4gYG5nTW9kZWxDaGFuZ2VgIGV2ZW50LlxuICAgKlxuICAgKiBAcGFyYW0gbmV3VmFsdWUgVGhlIG5ldyB2YWx1ZSBlbWl0dGVkIGJ5IGBuZ01vZGVsQ2hhbmdlYC5cbiAgICovXG4gIG92ZXJyaWRlIHZpZXdUb01vZGVsVXBkYXRlKG5ld1ZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdNb2RlbCA9IG5ld1ZhbHVlO1xuICAgIHRoaXMudXBkYXRlLmVtaXQobmV3VmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2V0VXBDb250cm9sKCk6IHZvaWQge1xuICAgIHRoaXMuX3NldFVwZGF0ZVN0cmF0ZWd5KCk7XG4gICAgdGhpcy5faXNTdGFuZGFsb25lKCkgPyB0aGlzLl9zZXRVcFN0YW5kYWxvbmUoKSA6IHRoaXMuZm9ybURpcmVjdGl2ZS5hZGRDb250cm9sKHRoaXMpO1xuICAgIHRoaXMuX3JlZ2lzdGVyZWQgPSB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2V0VXBkYXRlU3RyYXRlZ3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMudXBkYXRlT24gIT0gbnVsbCkge1xuICAgICAgdGhpcy5jb250cm9sLl91cGRhdGVPbiA9IHRoaXMub3B0aW9ucy51cGRhdGVPbjtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9pc1N0YW5kYWxvbmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLl9wYXJlbnQgfHwgISEodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5zdGFuZGFsb25lKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NldFVwU3RhbmRhbG9uZSgpOiB2b2lkIHtcbiAgICBzZXRVcENvbnRyb2wodGhpcy5jb250cm9sLCB0aGlzLCB0aGlzLmNhbGxTZXREaXNhYmxlZFN0YXRlKTtcbiAgICB0aGlzLmNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7ZW1pdEV2ZW50OiBmYWxzZX0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2hlY2tGb3JFcnJvcnMoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9pc1N0YW5kYWxvbmUoKSkge1xuICAgICAgdGhpcy5fY2hlY2tQYXJlbnRUeXBlKCk7XG4gICAgfVxuICAgIHRoaXMuX2NoZWNrTmFtZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2hlY2tQYXJlbnRUeXBlKCk6IHZvaWQge1xuICAgIGlmICh0eXBlb2YgbmdEZXZNb2RlID09PSAndW5kZWZpbmVkJyB8fCBuZ0Rldk1vZGUpIHtcbiAgICAgIGlmICghKHRoaXMuX3BhcmVudCBpbnN0YW5jZW9mIE5nTW9kZWxHcm91cCkgJiZcbiAgICAgICAgICB0aGlzLl9wYXJlbnQgaW5zdGFuY2VvZiBBYnN0cmFjdEZvcm1Hcm91cERpcmVjdGl2ZSkge1xuICAgICAgICB0aHJvdyBmb3JtR3JvdXBOYW1lRXhjZXB0aW9uKCk7XG4gICAgICB9IGVsc2UgaWYgKCEodGhpcy5fcGFyZW50IGluc3RhbmNlb2YgTmdNb2RlbEdyb3VwKSAmJiAhKHRoaXMuX3BhcmVudCBpbnN0YW5jZW9mIE5nRm9ybSkpIHtcbiAgICAgICAgdGhyb3cgbW9kZWxQYXJlbnRFeGNlcHRpb24oKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9jaGVja05hbWUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMubmFtZSkgdGhpcy5uYW1lID0gdGhpcy5vcHRpb25zLm5hbWU7XG5cbiAgICBpZiAoIXRoaXMuX2lzU3RhbmRhbG9uZSgpICYmICF0aGlzLm5hbWUgJiYgKHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8IG5nRGV2TW9kZSkpIHtcbiAgICAgIHRocm93IG1pc3NpbmdOYW1lRXhjZXB0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlVmFsdWUodmFsdWU6IGFueSk6IHZvaWQge1xuICAgIHJlc29sdmVkUHJvbWlzZS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMuY29udHJvbC5zZXRWYWx1ZSh2YWx1ZSwge2VtaXRWaWV3VG9Nb2RlbENoYW5nZTogZmFsc2V9KTtcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmPy5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3VwZGF0ZURpc2FibGVkKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBjb25zdCBkaXNhYmxlZFZhbHVlID0gY2hhbmdlc1snaXNEaXNhYmxlZCddLmN1cnJlbnRWYWx1ZTtcbiAgICAvLyBjaGVja2luZyBmb3IgMCB0byBhdm9pZCBicmVha2luZyBjaGFuZ2VcbiAgICBjb25zdCBpc0Rpc2FibGVkID0gZGlzYWJsZWRWYWx1ZSAhPT0gMCAmJiBib29sZWFuQXR0cmlidXRlKGRpc2FibGVkVmFsdWUpO1xuXG4gICAgcmVzb2x2ZWRQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgaWYgKGlzRGlzYWJsZWQgJiYgIXRoaXMuY29udHJvbC5kaXNhYmxlZCkge1xuICAgICAgICB0aGlzLmNvbnRyb2wuZGlzYWJsZSgpO1xuICAgICAgfSBlbHNlIGlmICghaXNEaXNhYmxlZCAmJiB0aGlzLmNvbnRyb2wuZGlzYWJsZWQpIHtcbiAgICAgICAgdGhpcy5jb250cm9sLmVuYWJsZSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZj8ubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9nZXRQYXRoKGNvbnRyb2xOYW1lOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhcmVudCA/IGNvbnRyb2xQYXRoKGNvbnRyb2xOYW1lLCB0aGlzLl9wYXJlbnQpIDogW2NvbnRyb2xOYW1lXTtcbiAgfVxufVxuIl19