@angular/forms
Version:
Angular - directives and services for creating forms
199 lines • 24.6 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, ElementRef, forwardRef, inject, Injectable, Injector, Input, Renderer2, ɵRuntimeError as RuntimeError } from '@angular/core';
import { BuiltInControlValueAccessor, NG_VALUE_ACCESSOR } from './control_value_accessor';
import { NgControl } from './ng_control';
import { CALL_SET_DISABLED_STATE, setDisabledStateDefault } from './shared';
import * as i0 from "@angular/core";
const RADIO_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioControlValueAccessor),
multi: true
};
function throwNameError() {
throw new RuntimeError(1202 /* RuntimeErrorCode.NAME_AND_FORM_CONTROL_NAME_MUST_MATCH */, `
If you define both a name and a formControlName attribute on your radio button, their values
must match. Ex: <input type="radio" formControlName="food" name="food">
`);
}
/**
* @description
* Class used by Angular to track radio buttons. For internal use only.
*/
export class RadioControlRegistry {
constructor() {
this._accessors = [];
}
/**
* @description
* Adds a control to the internal registry. For internal use only.
*/
add(control, accessor) {
this._accessors.push([control, accessor]);
}
/**
* @description
* Removes a control from the internal registry. For internal use only.
*/
remove(accessor) {
for (let i = this._accessors.length - 1; i >= 0; --i) {
if (this._accessors[i][1] === accessor) {
this._accessors.splice(i, 1);
return;
}
}
}
/**
* @description
* Selects a radio button. For internal use only.
*/
select(accessor) {
this._accessors.forEach((c) => {
if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
c[1].fireUncheck(accessor.value);
}
});
}
_isSameGroup(controlPair, accessor) {
if (!controlPair[0].control)
return false;
return controlPair[0]._parent === accessor._control._parent &&
controlPair[1].name === accessor.name;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: RadioControlRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: RadioControlRegistry, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: RadioControlRegistry, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
/**
* @description
* The `ControlValueAccessor` for writing radio control values and listening to radio control
* changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
* `NgModel` directives.
*
* @usageNotes
*
* ### Using radio buttons with reactive form directives
*
* The follow example shows how to use radio buttons in a reactive form. When using radio buttons in
* a reactive form, radio buttons in the same group should have the same `formControlName`.
* Providing a `name` attribute is optional.
*
* {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}
*
* @ngModule ReactiveFormsModule
* @ngModule FormsModule
* @publicApi
*/
export class RadioControlValueAccessor extends BuiltInControlValueAccessor {
constructor(renderer, elementRef, _registry, _injector) {
super(renderer, elementRef);
this._registry = _registry;
this._injector = _injector;
this.setDisabledStateFired = false;
/**
* The registered callback function called when a change event occurs on the input element.
* Note: we declare `onChange` here (also used as host listener) as a function with no arguments
* to override the `onChange` function (which expects 1 argument) in the parent
* `BaseControlValueAccessor` class.
* @nodoc
*/
this.onChange = () => { };
this.callSetDisabledState = inject(CALL_SET_DISABLED_STATE, { optional: true }) ?? setDisabledStateDefault;
}
/** @nodoc */
ngOnInit() {
this._control = this._injector.get(NgControl);
this._checkName();
this._registry.add(this._control, this);
}
/** @nodoc */
ngOnDestroy() {
this._registry.remove(this);
}
/**
* Sets the "checked" property value on the radio input element.
* @nodoc
*/
writeValue(value) {
this._state = value === this.value;
this.setProperty('checked', this._state);
}
/**
* Registers a function called when the control value changes.
* @nodoc
*/
registerOnChange(fn) {
this._fn = fn;
this.onChange = () => {
fn(this.value);
this._registry.select(this);
};
}
/** @nodoc */
setDisabledState(isDisabled) {
/**
* `setDisabledState` is supposed to be called whenever the disabled state of a control changes,
* including upon control creation. However, a longstanding bug caused the method to not fire
* when an *enabled* control was attached. This bug was fixed in v15 in #47576.
*
* This had a side effect: previously, it was possible to instantiate a reactive form control
* with `[attr.disabled]=true`, even though the corresponding control was enabled in the
* model. This resulted in a mismatch between the model and the DOM. Now, because
* `setDisabledState` is always called, the value in the DOM will be immediately overwritten
* with the "correct" enabled value.
*
* However, the fix also created an exceptional case: radio buttons. Because Reactive Forms
* models the entire group of radio buttons as a single `FormControl`, there is no way to
* control the disabled state for individual radios, so they can no longer be configured as
* disabled. Thus, we keep the old behavior for radio buttons, so that `[attr.disabled]`
* continues to work. Specifically, we drop the first call to `setDisabledState` if `disabled`
* is `false`, and we are not in legacy mode.
*/
if (this.setDisabledStateFired || isDisabled ||
this.callSetDisabledState === 'whenDisabledForLegacyCode') {
this.setProperty('disabled', isDisabled);
}
this.setDisabledStateFired = true;
}
/**
* Sets the "value" on the radio input element and unchecks it.
*
* @param value
*/
fireUncheck(value) {
this.writeValue(value);
}
_checkName() {
if (this.name && this.formControlName && this.name !== this.formControlName &&
(typeof ngDevMode === 'undefined' || ngDevMode)) {
throwNameError();
}
if (!this.name && this.formControlName)
this.name = this.formControlName;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: RadioControlValueAccessor, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: RadioControlRegistry }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.5", type: RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: { name: "name", formControlName: "formControlName", value: "value" }, host: { listeners: { "change": "onChange()", "blur": "onTouched()" } }, providers: [RADIO_VALUE_ACCESSOR], usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: RadioControlValueAccessor, decorators: [{
type: Directive,
args: [{
selector: 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]',
host: { '(change)': 'onChange()', '(blur)': 'onTouched()' },
providers: [RADIO_VALUE_ACCESSOR]
}]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: RadioControlRegistry }, { type: i0.Injector }], propDecorators: { name: [{
type: Input
}], formControlName: [{
type: Input
}], value: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFkaW9fY29udHJvbF92YWx1ZV9hY2Nlc3Nvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2Zvcm1zL3NyYy9kaXJlY3RpdmVzL3JhZGlvX2NvbnRyb2xfdmFsdWVfYWNjZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBK0IsU0FBUyxFQUFFLGFBQWEsSUFBSSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFJNUssT0FBTyxFQUFDLDJCQUEyQixFQUF3QixpQkFBaUIsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBQzlHLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxFQUFDLHVCQUF1QixFQUFFLHVCQUF1QixFQUFDLE1BQU0sVUFBVSxDQUFDOztBQUUxRSxNQUFNLG9CQUFvQixHQUFhO0lBQ3JDLE9BQU8sRUFBRSxpQkFBaUI7SUFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQztJQUN4RCxLQUFLLEVBQUUsSUFBSTtDQUNaLENBQUM7QUFFRixTQUFTLGNBQWM7SUFDckIsTUFBTSxJQUFJLFlBQVksb0VBQXlEOzs7S0FHNUUsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVEOzs7R0FHRztBQUVILE1BQU0sT0FBTyxvQkFBb0I7SUFEakM7UUFFVSxlQUFVLEdBQVUsRUFBRSxDQUFDO0tBMENoQztJQXhDQzs7O09BR0c7SUFDSCxHQUFHLENBQUMsT0FBa0IsRUFBRSxRQUFtQztRQUN6RCxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7O09B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O2tCQU5yQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFDSiw4RkFBOEY7b0JBQ2xHLElBQUksRUFBRSxFQUFDLFVBQVUsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBQztvQkFDekQsU0FBUyxFQUFFLENBQUMsb0JBQW9CLENBQUM7aUJBQ2xDOzhKQTZCVSxJQUFJO3NCQUFaLEtBQUs7Z0JBUUcsZUFBZTtzQkFBdkIsS0FBSztnQkFNRyxLQUFLO3NCQUFiLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIGZvcndhcmRSZWYsIGluamVjdCwgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgUHJvdmlkZXIsIFJlbmRlcmVyMiwgybVSdW50aW1lRXJyb3IgYXMgUnVudGltZUVycm9yfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtSdW50aW1lRXJyb3JDb2RlfSBmcm9tICcuLi9lcnJvcnMnO1xuXG5pbXBvcnQge0J1aWx0SW5Db250cm9sVmFsdWVBY2Nlc3NvciwgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SfSBmcm9tICcuL2NvbnRyb2xfdmFsdWVfYWNjZXNzb3InO1xuaW1wb3J0IHtOZ0NvbnRyb2x9IGZyb20gJy4vbmdfY29udHJvbCc7XG5pbXBvcnQge0NBTExfU0VUX0RJU0FCTEVEX1NUQVRFLCBzZXREaXNhYmxlZFN0YXRlRGVmYXVsdH0gZnJvbSAnLi9zaGFyZWQnO1xuXG5jb25zdCBSQURJT19WQUxVRV9BQ0NFU1NPUjogUHJvdmlkZXIgPSB7XG4gIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yKSxcbiAgbXVsdGk6IHRydWVcbn07XG5cbmZ1bmN0aW9uIHRocm93TmFtZUVycm9yKCkge1xuICB0aHJvdyBuZXcgUnVudGltZUVycm9yKFJ1bnRpbWVFcnJvckNvZGUuTkFNRV9BTkRfRk9STV9DT05UUk9MX05BTUVfTVVTVF9NQVRDSCwgYFxuICAgICAgSWYgeW91IGRlZmluZSBib3RoIGEgbmFtZSBhbmQgYSBmb3JtQ29udHJvbE5hbWUgYXR0cmlidXRlIG9uIHlvdXIgcmFkaW8gYnV0dG9uLCB0aGVpciB2YWx1ZXNcbiAgICAgIG11c3QgbWF0Y2guIEV4OiA8aW5wdXQgdHlwZT1cInJhZGlvXCIgZm9ybUNvbnRyb2xOYW1lPVwiZm9vZFwiIG5hbWU9XCJmb29kXCI+XG4gICAgYCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uXG4gKiBDbGFzcyB1c2VkIGJ5IEFuZ3VsYXIgdG8gdHJhY2sgcmFkaW8gYnV0dG9ucy4gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuICovXG5ASW5qZWN0YWJsZSh7cHJvdmlkZWRJbjogJ3Jvb3QnfSlcbmV4cG9ydCBjbGFzcyBSYWRpb0NvbnRyb2xSZWdpc3RyeSB7XG4gIHByaXZhdGUgX2FjY2Vzc29yczogYW55W10gPSBbXTtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIEFkZHMgYSBjb250cm9sIHRvIHRoZSBpbnRlcm5hbCByZWdpc3RyeS4gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuICAgKi9cbiAgYWRkKGNvbnRyb2w6IE5nQ29udHJvbCwgYWNjZXNzb3I6IFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IpIHtcbiAgICB0aGlzLl9hY2Nlc3NvcnMucHVzaChbY29udHJvbCwgYWNjZXNzb3JdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogUmVtb3ZlcyBhIGNvbnRyb2wgZnJvbSB0aGUgaW50ZXJuYWwgcmVnaXN0cnkuIEZvciBpbnRlcm5hbCB1c2Ugb25seS5cbiAgICovXG4gIHJlbW92ZShhY2Nlc3NvcjogUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvcikge1xuICAgIGZvciAobGV0IGkgPSB0aGlzLl9hY2Nlc3NvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIGlmICh0aGlzLl9hY2Nlc3NvcnNbaV1bMV0gPT09IGFjY2Vzc29yKSB7XG4gICAgICAgIHRoaXMuX2FjY2Vzc29ycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFNlbGVjdHMgYSByYWRpbyBidXR0b24uIEZvciBpbnRlcm5hbCB1c2Ugb25seS5cbiAgICovXG4gIHNlbGVjdChhY2Nlc3NvcjogUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvcikge1xuICAgIHRoaXMuX2FjY2Vzc29ycy5mb3JFYWNoKChjKSA9PiB7XG4gICAgICBpZiAodGhpcy5faXNTYW1lR3JvdXAoYywgYWNjZXNzb3IpICYmIGNbMV0gIT09IGFjY2Vzc29yKSB7XG4gICAgICAgIGNbMV0uZmlyZVVuY2hlY2soYWNjZXNzb3IudmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfaXNTYW1lR3JvdXAoXG4gICAgICBjb250cm9sUGFpcjogW05nQ29udHJvbCwgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvcl0sXG4gICAgICBhY2Nlc3NvcjogUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvcik6IGJvb2xlYW4ge1xuICAgIGlmICghY29udHJvbFBhaXJbMF0uY29udHJvbCkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBjb250cm9sUGFpclswXS5fcGFyZW50ID09PSBhY2Nlc3Nvci5fY29udHJvbC5fcGFyZW50ICYmXG4gICAgICAgIGNvbnRyb2xQYWlyWzFdLm5hbWUgPT09IGFjY2Vzc29yLm5hbWU7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqIFRoZSBgQ29udHJvbFZhbHVlQWNjZXNzb3JgIGZvciB3cml0aW5nIHJhZGlvIGNvbnRyb2wgdmFsdWVzIGFuZCBsaXN0ZW5pbmcgdG8gcmFkaW8gY29udHJvbFxuICogY2hhbmdlcy4gVGhlIHZhbHVlIGFjY2Vzc29yIGlzIHVzZWQgYnkgdGhlIGBGb3JtQ29udHJvbERpcmVjdGl2ZWAsIGBGb3JtQ29udHJvbE5hbWVgLCBhbmRcbiAqIGBOZ01vZGVsYCBkaXJlY3RpdmVzLlxuICpcbiAqIEB1c2FnZU5vdGVzXG4gKlxuICogIyMjIFVzaW5nIHJhZGlvIGJ1dHRvbnMgd2l0aCByZWFjdGl2ZSBmb3JtIGRpcmVjdGl2ZXNcbiAqXG4gKiBUaGUgZm9sbG93IGV4YW1wbGUgc2hvd3MgaG93IHRvIHVzZSByYWRpbyBidXR0b25zIGluIGEgcmVhY3RpdmUgZm9ybS4gV2hlbiB1c2luZyByYWRpbyBidXR0b25zIGluXG4gKiBhIHJlYWN0aXZlIGZvcm0sIHJhZGlvIGJ1dHRvbnMgaW4gdGhlIHNhbWUgZ3JvdXAgc2hvdWxkIGhhdmUgdGhlIHNhbWUgYGZvcm1Db250cm9sTmFtZWAuXG4gKiBQcm92aWRpbmcgYSBgbmFtZWAgYXR0cmlidXRlIGlzIG9wdGlvbmFsLlxuICpcbiAqIHtAZXhhbXBsZSBmb3Jtcy90cy9yZWFjdGl2ZVJhZGlvQnV0dG9ucy9yZWFjdGl2ZV9yYWRpb19idXR0b25fZXhhbXBsZS50cyByZWdpb249J1JlYWN0aXZlJ31cbiAqXG4gKiBAbmdNb2R1bGUgUmVhY3RpdmVGb3Jtc01vZHVsZVxuICogQG5nTW9kdWxlIEZvcm1zTW9kdWxlXG4gKiBAcHVibGljQXBpXG4gKi9cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjpcbiAgICAgICdpbnB1dFt0eXBlPXJhZGlvXVtmb3JtQ29udHJvbE5hbWVdLGlucHV0W3R5cGU9cmFkaW9dW2Zvcm1Db250cm9sXSxpbnB1dFt0eXBlPXJhZGlvXVtuZ01vZGVsXScsXG4gIGhvc3Q6IHsnKGNoYW5nZSknOiAnb25DaGFuZ2UoKScsICcoYmx1ciknOiAnb25Ub3VjaGVkKCknfSxcbiAgcHJvdmlkZXJzOiBbUkFESU9fVkFMVUVfQUNDRVNTT1JdXG59KVxuZXhwb3J0IGNsYXNzIFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IgZXh0ZW5kcyBCdWlsdEluQ29udHJvbFZhbHVlQWNjZXNzb3IgaW1wbGVtZW50c1xuICAgIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkRlc3Ryb3ksIE9uSW5pdCB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIF9zdGF0ZSE6IGJvb2xlYW47XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIF9jb250cm9sITogTmdDb250cm9sO1xuICAvKiogQGludGVybmFsICovXG4gIC8vIFRPRE8oaXNzdWUvMjQ1NzEpOiByZW1vdmUgJyEnLlxuICBfZm4hOiBGdW5jdGlvbjtcblxuICBwcml2YXRlIHNldERpc2FibGVkU3RhdGVGaXJlZCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVnaXN0ZXJlZCBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQgd2hlbiBhIGNoYW5nZSBldmVudCBvY2N1cnMgb24gdGhlIGlucHV0IGVsZW1lbnQuXG4gICAqIE5vdGU6IHdlIGRlY2xhcmUgYG9uQ2hhbmdlYCBoZXJlIChhbHNvIHVzZWQgYXMgaG9zdCBsaXN0ZW5lcikgYXMgYSBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50c1xuICAgKiB0byBvdmVycmlkZSB0aGUgYG9uQ2hhbmdlYCBmdW5jdGlvbiAod2hpY2ggZXhwZWN0cyAxIGFyZ3VtZW50KSBpbiB0aGUgcGFyZW50XG4gICAqIGBCYXNlQ29udHJvbFZhbHVlQWNjZXNzb3JgIGNsYXNzLlxuICAgKiBAbm9kb2NcbiAgICovXG4gIG92ZXJyaWRlIG9uQ2hhbmdlID0gKCkgPT4ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBUcmFja3MgdGhlIG5hbWUgb2YgdGhlIHJhZGlvIGlucHV0IGVsZW1lbnQuXG4gICAqL1xuICAvLyBUT0RPKGlzc3VlLzI0NTcxKTogcmVtb3ZlICchJy5cbiAgQElucHV0KCkgbmFtZSE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRyYWNrcyB0aGUgbmFtZSBvZiB0aGUgYEZvcm1Db250cm9sYCBib3VuZCB0byB0aGUgZGlyZWN0aXZlLiBUaGUgbmFtZSBjb3JyZXNwb25kc1xuICAgKiB0byBhIGtleSBpbiB0aGUgcGFyZW50IGBGb3JtR3JvdXBgIG9yIGBGb3JtQXJyYXlgLlxuICAgKi9cbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIEBJbnB1dCgpIGZvcm1Db250cm9sTmFtZSE6IHN0cmluZztcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFRyYWNrcyB0aGUgdmFsdWUgb2YgdGhlIHJhZGlvIGlucHV0IGVsZW1lbnRcbiAgICovXG4gIEBJbnB1dCgpIHZhbHVlOiBhbnk7XG5cbiAgcHJpdmF0ZSBjYWxsU2V0RGlzYWJsZWRTdGF0ZSA9XG4gICAgICBpbmplY3QoQ0FMTF9TRVRfRElTQUJMRURfU1RBVEUsIHtvcHRpb25hbDogdHJ1ZX0pID8/IHNldERpc2FibGVkU3RhdGVEZWZhdWx0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcmVuZGVyZXI6IFJlbmRlcmVyMiwgZWxlbWVudFJlZjogRWxlbWVudFJlZiwgcHJpdmF0ZSBfcmVnaXN0cnk6IFJhZGlvQ29udHJvbFJlZ2lzdHJ5LFxuICAgICAgcHJpdmF0ZSBfaW5qZWN0b3I6IEluamVjdG9yKSB7XG4gICAgc3VwZXIocmVuZGVyZXIsIGVsZW1lbnRSZWYpO1xuICB9XG5cbiAgLyoqIEBub2RvYyAqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLl9jb250cm9sID0gdGhpcy5faW5qZWN0b3IuZ2V0KE5nQ29udHJvbCk7XG4gICAgdGhpcy5fY2hlY2tOYW1lKCk7XG4gICAgdGhpcy5fcmVnaXN0cnkuYWRkKHRoaXMuX2NvbnRyb2wsIHRoaXMpO1xuICB9XG5cbiAgLyoqIEBub2RvYyAqL1xuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLl9yZWdpc3RyeS5yZW1vdmUodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgXCJjaGVja2VkXCIgcHJvcGVydHkgdmFsdWUgb24gdGhlIHJhZGlvIGlucHV0IGVsZW1lbnQuXG4gICAqIEBub2RvY1xuICAgKi9cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy5fc3RhdGUgPSB2YWx1ZSA9PT0gdGhpcy52YWx1ZTtcbiAgICB0aGlzLnNldFByb3BlcnR5KCdjaGVja2VkJywgdGhpcy5fc3RhdGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIGZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBjb250cm9sIHZhbHVlIGNoYW5nZXMuXG4gICAqIEBub2RvY1xuICAgKi9cbiAgb3ZlcnJpZGUgcmVnaXN0ZXJPbkNoYW5nZShmbjogKF86IGFueSkgPT4ge30pOiB2b2lkIHtcbiAgICB0aGlzLl9mbiA9IGZuO1xuICAgIHRoaXMub25DaGFuZ2UgPSAoKSA9PiB7XG4gICAgICBmbih0aGlzLnZhbHVlKTtcbiAgICAgIHRoaXMuX3JlZ2lzdHJ5LnNlbGVjdCh0aGlzKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqIEBub2RvYyAqL1xuICBvdmVycmlkZSBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAvKipcbiAgICAgKiBgc2V0RGlzYWJsZWRTdGF0ZWAgaXMgc3VwcG9zZWQgdG8gYmUgY2FsbGVkIHdoZW5ldmVyIHRoZSBkaXNhYmxlZCBzdGF0ZSBvZiBhIGNvbnRyb2wgY2hhbmdlcyxcbiAgICAgKiBpbmNsdWRpbmcgdXBvbiBjb250cm9sIGNyZWF0aW9uLiBIb3dldmVyLCBhIGxvbmdzdGFuZGluZyBidWcgY2F1c2VkIHRoZSBtZXRob2QgdG8gbm90IGZpcmVcbiAgICAgKiB3aGVuIGFuICplbmFibGVkKiBjb250cm9sIHdhcyBhdHRhY2hlZC4gVGhpcyBidWcgd2FzIGZpeGVkIGluIHYxNSBpbiAjNDc1NzYuXG4gICAgICpcbiAgICAgKiBUaGlzIGhhZCBhIHNpZGUgZWZmZWN0OiBwcmV2aW91c2x5LCBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYSByZWFjdGl2ZSBmb3JtIGNvbnRyb2xcbiAgICAgKiB3aXRoIGBbYXR0ci5kaXNhYmxlZF09dHJ1ZWAsIGV2ZW4gdGhvdWdoIHRoZSBjb3JyZXNwb25kaW5nIGNvbnRyb2wgd2FzIGVuYWJsZWQgaW4gdGhlXG4gICAgICogbW9kZWwuIFRoaXMgcmVzdWx0ZWQgaW4gYSBtaXNtYXRjaCBiZXR3ZWVuIHRoZSBtb2RlbCBhbmQgdGhlIERPTS4gTm93LCBiZWNhdXNlXG4gICAgICogYHNldERpc2FibGVkU3RhdGVgIGlzIGFsd2F5cyBjYWxsZWQsIHRoZSB2YWx1ZSBpbiB0aGUgRE9NIHdpbGwgYmUgaW1tZWRpYXRlbHkgb3ZlcndyaXR0ZW5cbiAgICAgKiB3aXRoIHRoZSBcImNvcnJlY3RcIiBlbmFibGVkIHZhbHVlLlxuICAgICAqXG4gICAgICogSG93ZXZlciwgdGhlIGZpeCBhbHNvIGNyZWF0ZWQgYW4gZXhjZXB0aW9uYWwgY2FzZTogcmFkaW8gYnV0dG9ucy4gQmVjYXVzZSBSZWFjdGl2ZSBGb3Jtc1xuICAgICAqIG1vZGVscyB0aGUgZW50aXJlIGdyb3VwIG9mIHJhZGlvIGJ1dHRvbnMgYXMgYSBzaW5nbGUgYEZvcm1Db250cm9sYCwgdGhlcmUgaXMgbm8gd2F5IHRvXG4gICAgICogY29udHJvbCB0aGUgZGlzYWJsZWQgc3RhdGUgZm9yIGluZGl2aWR1YWwgcmFkaW9zLCBzbyB0aGV5IGNhbiBubyBsb25nZXIgYmUgY29uZmlndXJlZCBhc1xuICAgICAqIGRpc2FibGVkLiBUaHVzLCB3ZSBrZWVwIHRoZSBvbGQgYmVoYXZpb3IgZm9yIHJhZGlvIGJ1dHRvbnMsIHNvIHRoYXQgYFthdHRyLmRpc2FibGVkXWBcbiAgICAgKiBjb250aW51ZXMgdG8gd29yay4gU3BlY2lmaWNhbGx5LCB3ZSBkcm9wIHRoZSBmaXJzdCBjYWxsIHRvIGBzZXREaXNhYmxlZFN0YXRlYCBpZiBgZGlzYWJsZWRgXG4gICAgICogaXMgYGZhbHNlYCwgYW5kIHdlIGFyZSBub3QgaW4gbGVnYWN5IG1vZGUuXG4gICAgICovXG4gICAgaWYgKHRoaXMuc2V0RGlzYWJsZWRTdGF0ZUZpcmVkIHx8IGlzRGlzYWJsZWQgfHxcbiAgICAgICAgdGhpcy5jYWxsU2V0RGlzYWJsZWRTdGF0ZSA9PT0gJ3doZW5EaXNhYmxlZEZvckxlZ2FjeUNvZGUnKSB7XG4gICAgICB0aGlzLnNldFByb3BlcnR5KCdkaXNhYmxlZCcsIGlzRGlzYWJsZWQpO1xuICAgIH1cbiAgICB0aGlzLnNldERpc2FibGVkU3RhdGVGaXJlZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgXCJ2YWx1ZVwiIG9uIHRoZSByYWRpbyBpbnB1dCBlbGVtZW50IGFuZCB1bmNoZWNrcyBpdC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlXG4gICAqL1xuICBmaXJlVW5jaGVjayh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZVZhbHVlKHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NoZWNrTmFtZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5uYW1lICYmIHRoaXMuZm9ybUNvbnRyb2xOYW1lICYmIHRoaXMubmFtZSAhPT0gdGhpcy5mb3JtQ29udHJvbE5hbWUgJiZcbiAgICAgICAgKHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8IG5nRGV2TW9kZSkpIHtcbiAgICAgIHRocm93TmFtZUVycm9yKCk7XG4gICAgfVxuICAgIGlmICghdGhpcy5uYW1lICYmIHRoaXMuZm9ybUNvbnRyb2xOYW1lKSB0aGlzLm5hbWUgPSB0aGlzLmZvcm1Db250cm9sTmFtZTtcbiAgfVxufVxuIl19