UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

567 lines 65.5 kB
'use strict';"use strict"; var core_1 = require('angular2/core'); var lang_1 = require('angular2/src/facade/lang'); var async_1 = require('angular2/src/facade/async'); var browser_1 = require('angular2/platform/browser'); var metadata_1 = require('./metadata'); var util_1 = require('./util'); var constants_1 = require('./constants'); var downgrade_ng2_adapter_1 = require('./downgrade_ng2_adapter'); var upgrade_ng1_adapter_1 = require('./upgrade_ng1_adapter'); var angular = require('./angular_js'); var upgradeCount = 0; /** * Use `UpgradeAdapter` to allow AngularJS v1 and Angular v2 to coexist in a single application. * * The `UpgradeAdapter` allows: * 1. creation of Angular v2 component from AngularJS v1 component directive * (See [UpgradeAdapter#upgradeNg1Component()]) * 2. creation of AngularJS v1 directive from Angular v2 component. * (See [UpgradeAdapter#downgradeNg2Component()]) * 3. Bootstrapping of a hybrid Angular application which contains both of the frameworks * coexisting in a single application. * * ## Mental Model * * When reasoning about how a hybrid application works it is useful to have a mental model which * describes what is happening and explains what is happening at the lowest level. * * 1. There are two independent frameworks running in a single application, each framework treats * the other as a black box. * 2. Each DOM element on the page is owned exactly by one framework. Whichever framework * instantiated the element is the owner. Each framework only updates/interacts with its own * DOM elements and ignores others. * 3. AngularJS v1 directives always execute inside AngularJS v1 framework codebase regardless of * where they are instantiated. * 4. Angular v2 components always execute inside Angular v2 framework codebase regardless of * where they are instantiated. * 5. An AngularJS v1 component can be upgraded to an Angular v2 component. This creates an * Angular v2 directive, which bootstraps the AngularJS v1 component directive in that location. * 6. An Angular v2 component can be downgraded to an AngularJS v1 component directive. This creates * an AngularJS v1 directive, which bootstraps the Angular v2 component in that location. * 7. Whenever an adapter component is instantiated the host element is owned by the framework * doing the instantiation. The other framework then instantiates and owns the view for that * component. This implies that component bindings will always follow the semantics of the * instantiation framework. The syntax is always that of Angular v2 syntax. * 8. AngularJS v1 is always bootstrapped first and owns the bottom most view. * 9. The new application is running in Angular v2 zone, and therefore it no longer needs calls to * `$apply()`. * * ### Example * * ``` * var adapter = new UpgradeAdapter(); * var module = angular.module('myExample', []); * module.directive('ng2', adapter.downgradeNg2Component(Ng2)); * * module.directive('ng1', function() { * return { * scope: { title: '=' }, * template: 'ng1[Hello {{title}}!](<span ng-transclude></span>)' * }; * }); * * * @Component({ * selector: 'ng2', * inputs: ['name'], * template: 'ng2[<ng1 [title]="name">transclude</ng1>](<ng-content></ng-content>)', * directives: [adapter.upgradeNg1Component('ng1')] * }) * class Ng2 { * } * * document.body.innerHTML = '<ng2 name="World">project</ng2>'; * * adapter.bootstrap(document.body, ['myExample']).ready(function() { * expect(document.body.textContent).toEqual( * "ng2[ng1[Hello World!](transclude)](project)"); * }); * ``` */ var UpgradeAdapter = (function () { function UpgradeAdapter() { /* @internal */ this.idPrefix = "NG2_UPGRADE_" + upgradeCount++ + "_"; /* @internal */ this.upgradedComponents = []; /* @internal */ this.downgradedComponents = {}; /* @internal */ this.providers = []; } /** * Allows Angular v2 Component to be used from AngularJS v1. * * Use `downgradeNg2Component` to create an AngularJS v1 Directive Definition Factory from * Angular v2 Component. The adapter will bootstrap Angular v2 component from within the * AngularJS v1 template. * * ## Mental Model * * 1. The component is instantiated by being listed in AngularJS v1 template. This means that the * host element is controlled by AngularJS v1, but the component's view will be controlled by * Angular v2. * 2. Even thought the component is instantiated in AngularJS v1, it will be using Angular v2 * syntax. This has to be done, this way because we must follow Angular v2 components do not * declare how the attributes should be interpreted. * * ## Supported Features * * - Bindings: * - Attribute: `<comp name="World">` * - Interpolation: `<comp greeting="Hello {{name}}!">` * - Expression: `<comp [name]="username">` * - Event: `<comp (close)="doSomething()">` * - Content projection: yes * * ### Example * * ``` * var adapter = new UpgradeAdapter(); * var module = angular.module('myExample', []); * module.directive('greet', adapter.downgradeNg2Component(Greeter)); * * @Component({ * selector: 'greet', * template: '{{salutation}} {{name}}! - <ng-content></ng-content>' * }) * class Greeter { * @Input() salutation: string; * @Input() name: string; * } * * document.body.innerHTML = * 'ng1 template: <greet salutation="Hello" [name]="world">text</greet>'; * * adapter.bootstrap(document.body, ['myExample']).ready(function() { * expect(document.body.textContent).toEqual("ng1 template: Hello world! - text"); * }); * ``` */ UpgradeAdapter.prototype.downgradeNg2Component = function (type) { this.upgradedComponents.push(type); var info = metadata_1.getComponentInfo(type); return ng1ComponentDirective(info, "" + this.idPrefix + info.selector + "_c"); }; /** * Allows AngularJS v1 Component to be used from Angular v2. * * Use `upgradeNg1Component` to create an Angular v2 component from AngularJS v1 Component * directive. The adapter will bootstrap AngularJS v1 component from within the Angular v2 * template. * * ## Mental Model * * 1. The component is instantiated by being listed in Angular v2 template. This means that the * host element is controlled by Angular v2, but the component's view will be controlled by * AngularJS v1. * * ## Supported Features * * - Bindings: * - Attribute: `<comp name="World">` * - Interpolation: `<comp greeting="Hello {{name}}!">` * - Expression: `<comp [name]="username">` * - Event: `<comp (close)="doSomething()">` * - Transclusion: yes * - Only some of the features of * [Directive Definition Object](https://docs.angularjs.org/api/ng/service/$compile) are * supported: * - `compile`: not supported because the host element is owned by Angular v2, which does * not allow modifying DOM structure during compilation. * - `controller`: supported. (NOTE: injection of `$attrs` and `$transclude` is not supported.) * - `controllerAs': supported. * - `bindToController': supported. * - `link': supported. (NOTE: only pre-link function is supported.) * - `name': supported. * - `priority': ignored. * - `replace': not supported. * - `require`: supported. * - `restrict`: must be set to 'E'. * - `scope`: supported. * - `template`: supported. * - `templateUrl`: supported. * - `terminal`: ignored. * - `transclude`: supported. * * * ### Example * * ``` * var adapter = new UpgradeAdapter(); * var module = angular.module('myExample', []); * * module.directive('greet', function() { * return { * scope: {salutation: '=', name: '=' }, * template: '{{salutation}} {{name}}! - <span ng-transclude></span>' * }; * }); * * module.directive('ng2', adapter.downgradeNg2Component(Ng2)); * * @Component({ * selector: 'ng2', * template: 'ng2 template: <greet salutation="Hello" [name]="world">text</greet>' * directives: [adapter.upgradeNg1Component('greet')] * }) * class Ng2 { * } * * document.body.innerHTML = '<ng2></ng2>'; * * adapter.bootstrap(document.body, ['myExample']).ready(function() { * expect(document.body.textContent).toEqual("ng2 template: Hello world! - text"); * }); * ``` */ UpgradeAdapter.prototype.upgradeNg1Component = function (name) { if (this.downgradedComponents.hasOwnProperty(name)) { return this.downgradedComponents[name].type; } else { return (this.downgradedComponents[name] = new upgrade_ng1_adapter_1.UpgradeNg1ComponentAdapterBuilder(name)).type; } }; /** * Bootstrap a hybrid AngularJS v1 / Angular v2 application. * * This `bootstrap` method is a direct replacement (takes same arguments) for AngularJS v1 * [`bootstrap`](https://docs.angularjs.org/api/ng/function/angular.bootstrap) method. Unlike * AngularJS v1, this bootstrap is asynchronous. * * ### Example * * ``` * var adapter = new UpgradeAdapter(); * var module = angular.module('myExample', []); * module.directive('ng2', adapter.downgradeNg2Component(Ng2)); * * module.directive('ng1', function() { * return { * scope: { title: '=' }, * template: 'ng1[Hello {{title}}!](<span ng-transclude></span>)' * }; * }); * * * @Component({ * selector: 'ng2', * inputs: ['name'], * template: 'ng2[<ng1 [title]="name">transclude</ng1>](<ng-content></ng-content>)', * directives: [adapter.upgradeNg1Component('ng1')] * }) * class Ng2 { * } * * document.body.innerHTML = '<ng2 name="World">project</ng2>'; * * adapter.bootstrap(document.body, ['myExample']).ready(function() { * expect(document.body.textContent).toEqual( * "ng2[ng1[Hello World!](transclude)](project)"); * }); * ``` */ UpgradeAdapter.prototype.bootstrap = function (element, modules, config) { var _this = this; var upgrade = new UpgradeAdapterRef(); var ng1Injector = null; var platformRef = browser_1.browserPlatform(); var applicationRef = core_1.ReflectiveInjector.resolveAndCreate([ browser_1.BROWSER_APP_PROVIDERS, core_1.provide(constants_1.NG1_INJECTOR, { useFactory: function () { return ng1Injector; } }), core_1.provide(constants_1.NG1_COMPILE, { useFactory: function () { return ng1Injector.get(constants_1.NG1_COMPILE); } }), this.providers ], platformRef.injector) .get(core_1.ApplicationRef); var injector = applicationRef.injector; var ngZone = injector.get(core_1.NgZone); var compiler = injector.get(core_1.ComponentResolver); var delayApplyExps = []; var original$applyFn; var rootScopePrototype; var rootScope; var componentFactoryRefMap = {}; var ng1Module = angular.module(this.idPrefix, modules); var ng1BootstrapPromise = null; var ng1compilePromise = null; ng1Module.value(constants_1.NG2_INJECTOR, injector) .value(constants_1.NG2_ZONE, ngZone) .value(constants_1.NG2_COMPILER, compiler) .value(constants_1.NG2_COMPONENT_FACTORY_REF_MAP, componentFactoryRefMap) .config([ '$provide', function (provide) { provide.decorator(constants_1.NG1_ROOT_SCOPE, [ '$delegate', function (rootScopeDelegate) { rootScopePrototype = rootScopeDelegate.constructor.prototype; if (rootScopePrototype.hasOwnProperty('$apply')) { original$applyFn = rootScopePrototype.$apply; rootScopePrototype.$apply = function (exp) { return delayApplyExps.push(exp); }; } else { throw new Error("Failed to find '$apply' on '$rootScope'!"); } return rootScope = rootScopeDelegate; } ]); provide.decorator(constants_1.NG1_TESTABILITY, [ '$delegate', function (testabilityDelegate) { var _this = this; var ng2Testability = injector.get(core_1.Testability); var origonalWhenStable = testabilityDelegate.whenStable; var newWhenStable = function (callback) { var whenStableContext = _this; origonalWhenStable.call(_this, function () { if (ng2Testability.isStable()) { callback.apply(this, arguments); } else { ng2Testability.whenStable(newWhenStable.bind(whenStableContext, callback)); } }); }; testabilityDelegate.whenStable = newWhenStable; return testabilityDelegate; } ]); } ]); ng1compilePromise = new Promise(function (resolve, reject) { ng1Module.run([ '$injector', '$rootScope', function (injector, rootScope) { ng1Injector = injector; async_1.ObservableWrapper.subscribe(ngZone.onMicrotaskEmpty, function (_) { return ngZone.runOutsideAngular(function () { return rootScope.$apply(); }); }); upgrade_ng1_adapter_1.UpgradeNg1ComponentAdapterBuilder.resolve(_this.downgradedComponents, injector) .then(resolve, reject); } ]); }); // Make sure resumeBootstrap() only exists if the current bootstrap is deferred var windowAngular = lang_1.global.angular; windowAngular.resumeBootstrap = undefined; angular.element(element).data(util_1.controllerKey(constants_1.NG2_INJECTOR), injector); ngZone.run(function () { angular.bootstrap(element, [_this.idPrefix], config); }); ng1BootstrapPromise = new Promise(function (resolve, reject) { if (windowAngular.resumeBootstrap) { var originalResumeBootstrap = windowAngular.resumeBootstrap; windowAngular.resumeBootstrap = function () { windowAngular.resumeBootstrap = originalResumeBootstrap; windowAngular.resumeBootstrap.apply(this, arguments); resolve(); }; } else { resolve(); } }); Promise.all([ this.compileNg2Components(compiler, componentFactoryRefMap), ng1BootstrapPromise, ng1compilePromise ]) .then(function () { ngZone.run(function () { if (rootScopePrototype) { rootScopePrototype.$apply = original$applyFn; // restore original $apply while (delayApplyExps.length) { rootScope.$apply(delayApplyExps.shift()); } upgrade._bootstrapDone(applicationRef, ng1Injector); rootScopePrototype = null; } }); }, util_1.onError); return upgrade; }; /** * Adds a provider to the top level environment of a hybrid AngularJS v1 / Angular v2 application. * * In hybrid AngularJS v1 / Angular v2 application, there is no one root Angular v2 component, * for this reason we provide an application global way of registering providers which is * consistent with single global injection in AngularJS v1. * * ### Example * * ``` * class Greeter { * greet(name) { * alert('Hello ' + name + '!'); * } * } * * @Component({ * selector: 'app', * template: '' * }) * class App { * constructor(greeter: Greeter) { * this.greeter('World'); * } * } * * var adapter = new UpgradeAdapter(); * adapter.addProvider(Greeter); * * var module = angular.module('myExample', []); * module.directive('app', adapter.downgradeNg2Component(App)); * * document.body.innerHTML = '<app></app>' * adapter.bootstrap(document.body, ['myExample']); *``` */ UpgradeAdapter.prototype.addProvider = function (provider) { this.providers.push(provider); }; /** * Allows AngularJS v1 service to be accessible from Angular v2. * * * ### Example * * ``` * class Login { ... } * class Server { ... } * * @Injectable() * class Example { * constructor(@Inject('server') server, login: Login) { * ... * } * } * * var module = angular.module('myExample', []); * module.service('server', Server); * module.service('login', Login); * * var adapter = new UpgradeAdapter(); * adapter.upgradeNg1Provider('server'); * adapter.upgradeNg1Provider('login', {asToken: Login}); * adapter.addProvider(Example); * * adapter.bootstrap(document.body, ['myExample']).ready((ref) => { * var example: Example = ref.ng2Injector.get(Example); * }); * * ``` */ UpgradeAdapter.prototype.upgradeNg1Provider = function (name, options) { var token = options && options.asToken || name; this.providers.push(core_1.provide(token, { useFactory: function (ng1Injector) { return ng1Injector.get(name); }, deps: [constants_1.NG1_INJECTOR] })); }; /** * Allows Angular v2 service to be accessible from AngularJS v1. * * * ### Example * * ``` * class Example { * } * * var adapter = new UpgradeAdapter(); * adapter.addProvider(Example); * * var module = angular.module('myExample', []); * module.factory('example', adapter.downgradeNg2Provider(Example)); * * adapter.bootstrap(document.body, ['myExample']).ready((ref) => { * var example: Example = ref.ng1Injector.get('example'); * }); * * ``` */ UpgradeAdapter.prototype.downgradeNg2Provider = function (token) { var factory = function (injector) { return injector.get(token); }; factory.$inject = [constants_1.NG2_INJECTOR]; return factory; }; /* @internal */ UpgradeAdapter.prototype.compileNg2Components = function (compiler, componentFactoryRefMap) { var _this = this; var promises = []; var types = this.upgradedComponents; for (var i = 0; i < types.length; i++) { promises.push(compiler.resolveComponent(types[i])); } return Promise.all(promises).then(function (componentFactories) { var types = _this.upgradedComponents; for (var i = 0; i < componentFactories.length; i++) { componentFactoryRefMap[metadata_1.getComponentInfo(types[i]).selector] = componentFactories[i]; } return componentFactoryRefMap; }, util_1.onError); }; return UpgradeAdapter; }()); exports.UpgradeAdapter = UpgradeAdapter; function ng1ComponentDirective(info, idPrefix) { directiveFactory.$inject = [constants_1.NG2_COMPONENT_FACTORY_REF_MAP, constants_1.NG1_PARSE]; function directiveFactory(componentFactoryRefMap, parse) { var componentFactory = componentFactoryRefMap[info.selector]; if (!componentFactory) throw new Error('Expecting ComponentFactory for: ' + info.selector); var idCount = 0; return { restrict: 'E', require: constants_1.REQUIRE_INJECTOR, link: { post: function (scope, element, attrs, parentInjector, transclude) { var domElement = element[0]; var facade = new downgrade_ng2_adapter_1.DowngradeNg2ComponentAdapter(idPrefix + (idCount++), info, element, attrs, scope, parentInjector, parse, componentFactory); facade.setupInputs(); facade.bootstrapNg2(); facade.projectContent(); facade.setupOutputs(); facade.registerCleanup(); } } }; } return directiveFactory; } /** * Use `UgradeAdapterRef` to control a hybrid AngularJS v1 / Angular v2 application. */ var UpgradeAdapterRef = (function () { function UpgradeAdapterRef() { /* @internal */ this._readyFn = null; this.ng1RootScope = null; this.ng1Injector = null; this.ng2ApplicationRef = null; this.ng2Injector = null; } /* @internal */ UpgradeAdapterRef.prototype._bootstrapDone = function (applicationRef, ng1Injector) { this.ng2ApplicationRef = applicationRef; this.ng2Injector = applicationRef.injector; this.ng1Injector = ng1Injector; this.ng1RootScope = ng1Injector.get(constants_1.NG1_ROOT_SCOPE); this._readyFn && this._readyFn(this); }; /** * Register a callback function which is notified upon successful hybrid AngularJS v1 / Angular v2 * application has been bootstrapped. * * The `ready` callback function is invoked inside the Angular v2 zone, therefore it does not * require a call to `$apply()`. */ UpgradeAdapterRef.prototype.ready = function (fn) { this._readyFn = fn; }; /** * Dispose of running hybrid AngularJS v1 / Angular v2 application. */ UpgradeAdapterRef.prototype.dispose = function () { this.ng1Injector.get(constants_1.NG1_ROOT_SCOPE).$destroy(); this.ng2ApplicationRef.dispose(); }; return UpgradeAdapterRef; }()); exports.UpgradeAdapterRef = UpgradeAdapterRef; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBncmFkZV9hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGlmZmluZ19wbHVnaW5fd3JhcHBlci1vdXRwdXRfcGF0aC10c1F1cWp2Ri50bXAvYW5ndWxhcjIvc3JjL3VwZ3JhZGUvdXBncmFkZV9hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxxQkFhTyxlQUFlLENBQUMsQ0FBQTtBQUN2QixxQkFBcUIsMEJBQTBCLENBQUMsQ0FBQTtBQUNoRCxzQkFBZ0MsMkJBQTJCLENBQUMsQ0FBQTtBQUM1RCx3QkFBd0UsMkJBQTJCLENBQUMsQ0FBQTtBQUVwRyx5QkFBOEMsWUFBWSxDQUFDLENBQUE7QUFDM0QscUJBQXFDLFFBQVEsQ0FBQyxDQUFBO0FBQzlDLDBCQVlPLGFBQWEsQ0FBQyxDQUFBO0FBQ3JCLHNDQUEyQyx5QkFBeUIsQ0FBQyxDQUFBO0FBQ3JFLG9DQUFnRCx1QkFBdUIsQ0FBQyxDQUFBO0FBQ3hFLElBQVksT0FBTyxXQUFNLGNBQWMsQ0FBQyxDQUFBO0FBRXhDLElBQUksWUFBWSxHQUFXLENBQUMsQ0FBQztBQUU3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvRUc7QUFDSDtJQUFBO1FBQ0UsZUFBZTtRQUNQLGFBQVEsR0FBVyxpQkFBZSxZQUFZLEVBQUUsTUFBRyxDQUFDO1FBQzVELGVBQWU7UUFDUCx1QkFBa0IsR0FBVyxFQUFFLENBQUM7UUFDeEMsZUFBZTtRQUNQLHlCQUFvQixHQUF3RCxFQUFFLENBQUM7UUFDdkYsZUFBZTtRQUNQLGNBQVMsR0FBbUMsRUFBRSxDQUFDO0lBdWF6RCxDQUFDO0lBcmFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FnREc7SUFDSCw4Q0FBcUIsR0FBckIsVUFBc0IsSUFBVTtRQUM5QixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFD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ZTtJQUNQLDBDQUFjLEdBQXRCLFVBQXVCLGNBQThCLEVBQUUsV0FBcUM7UUFDMUYsSUFBSSxDQUFDLGlCQUFpQixHQUFHLGNBQWMsQ0FBQztRQUN4QyxJQUFJLENBQUMsV0FBVyxHQUFHLGNBQWMsQ0FBQyxRQUFRLENBQUM7UUFDM0MsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLDBCQUFjLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLGlDQUFLLEdBQVosVUFBYSxFQUFtRCxJQUFJLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUV6Rjs7T0FFRztJQUNJLG1DQUFPLEdBQWQ7UUFDRSxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQywwQkFBYyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDaEQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ25DLENBQUM7SUFDSCx3QkFBQztBQUFELENBQUMsQUFsQ0QsSUFrQ0M7QUFsQ1kseUJBQWlCLG9CQWtDN0IsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIHByb3ZpZGUsXG4gIEFwcGxpY2F0aW9uUmVmLFxuICBDb21wb25lbnRSZXNvbHZlcixcbiAgSW5qZWN0b3IsXG4gIE5nWm9uZSxcbiAgUGxhdGZvcm1SZWYsXG4gIFJlZmxlY3RpdmVJbmplY3RvcixcbiAgQ29tcG9uZW50RmFjdG9yeSxcbiAgUHJvdmlkZXIsXG4gIFR5cGUsXG4gIFRlc3RhYmlsaXR5LFxuICBBUFBMSUNBVElPTl9DT01NT05fUFJPVklERVJTXG59IGZyb20gJ2FuZ3VsYXIyL2NvcmUnO1xuaW1wb3J0IHtnbG9iYWx9IGZyb20gJ2FuZ3VsYXIyL3NyYy9mYWNhZGUvbGFuZyc7XG5pbXBvcnQge09ic2VydmFibGVXcmFwcGVyfSBmcm9tICdhbmd1bGFyMi9zcmMvZmFjYWRlL2FzeW5jJztcbmltcG9ydCB7QlJPV1NFUl9QUk9WSURFUlMsIEJST1dTRVJfQVBQX1BST1ZJREVSUywgYnJvd3NlclBsYXRmb3JtfSBmcm9tICdhbmd1bGFyMi9wbGF0Zm9ybS9icm93c2VyJztcblxuaW1wb3J0IHtnZXRDb21wb25lbnRJbmZvLCBDb21wb25lbnRJbmZvfSBmcm9tICcuL21ldGFkYXRhJztcbmltcG9ydCB7b25FcnJvciwgY29udHJvbGxlcktleX0gZnJvbSAnLi91dGlsJztcbmltcG9ydCB7XG4gIE5HMV9DT01QSUxFLFxuICBORzFfSU5KRUNUT1IsXG4gIE5HMV9QQVJTRSxcbiAgTkcxX1JPT1RfU0NPUEUsXG4gIE5HMV9TQ09QRSxcbiAgTkcxX1RFU1RBQklMSVRZLFxuICBORzJfQ09NUElMRVIsXG4gIE5HMl9JTkpFQ1RPUixcbiAgTkcyX0NPTVBPTkVOVF9GQUNUT1JZX1JFRl9NQVAsXG4gIE5HMl9aT05FLFxuICBSRVFVSVJFX0lOSkVDVE9SXG59IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7RG93bmdyYWRlTmcyQ29tcG9uZW50QWRhcHRlcn0gZnJvbSAnLi9kb3duZ3JhZGVfbmcyX2FkYXB0ZXInO1xuaW1wb3J0IHtVcGdyYWRlTmcxQ29tcG9uZW50QWRhcHRlckJ1aWxkZXJ9IGZyb20gJy4vdXBncmFkZV9uZzFfYWRhcHRlcic7XG5pbXBvcnQgKiBhcyBhbmd1bGFyIGZyb20gJy4vYW5ndWxhcl9qcyc7XG5cbnZhciB1cGdyYWRlQ291bnQ6IG51bWJlciA9IDA7XG5cbi8qKlxuICogVXNlIGBVcGdyYWRlQWRhcHRlcmAgdG8gYWxsb3cgQW5ndWxhckpTIHYxIGFuZCBBbmd1bGFyIHYyIHRvIGNvZXhpc3QgaW4gYSBzaW5nbGUgYXBwbGljYXRpb24uXG4gKlxuICogVGhlIGBVcGdyYWRlQWRhcHRlcmAgYWxsb3dzOlxuICogMS4gY3JlYXRpb24gb2YgQW5ndWxhciB2MiBjb21wb25lbnQgZnJvbSBBbmd1bGFySlMgdjEgY29tcG9uZW50IGRpcmVjdGl2ZVxuICogICAgKFNlZSBbVXBncmFkZUFkYXB0ZXIjdXBncmFkZU5nMUNvbXBvbmVudCgpXSlcbiAqIDIuIGNyZWF0aW9uIG9mIEFuZ3VsYXJKUyB2MSBkaXJlY3RpdmUgZnJvbSBBbmd1bGFyIHYyIGNvbXBvbmVudC5cbiAqICAgIChTZWUgW1VwZ3JhZGVBZGFwdGVyI2Rvd25ncmFkZU5nMkNvbXBvbmVudCgpXSlcbiAqIDMuIEJvb3RzdHJhcHBpbmcgb2YgYSBoeWJyaWQgQW5ndWxhciBhcHBsaWNhdGlvbiB3aGljaCBjb250YWlucyBib3RoIG9mIHRoZSBmcmFtZXdvcmtzXG4gKiAgICBjb2V4aXN0aW5nIGluIGEgc2luZ2xlIGFwcGxpY2F0aW9uLlxuICpcbiAqICMjIE1lbnRhbCBNb2RlbFxuICpcbiAqIFdoZW4gcmVhc29uaW5nIGFib3V0IGhvdyBhIGh5YnJpZCBhcHBsaWNhdGlvbiB3b3JrcyBpdCBpcyB1c2VmdWwgdG8gaGF2ZSBhIG1lbnRhbCBtb2RlbCB3aGljaFxuICogZGVzY3JpYmVzIHdoYXQgaXMgaGFwcGVuaW5nIGFuZCBleHBsYWlucyB3aGF0IGlzIGhhcHBlbmluZyBhdCB0aGUgbG93ZXN0IGxldmVsLlxuICpcbiAqIDEuIFRoZXJlIGFyZSB0d28gaW5kZXBlbmRlbnQgZnJhbWV3b3JrcyBydW5uaW5nIGluIGEgc2luZ2xlIGFwcGxpY2F0aW9uLCBlYWNoIGZyYW1ld29yayB0cmVhdHNcbiAqICAgIHRoZSBvdGhlciBhcyBhIGJsYWNrIGJveC5cbiAqIDIuIEVhY2ggRE9NIGVsZW1lbnQgb24gdGhlIHBhZ2UgaXMgb3duZWQgZXhhY3RseSBieSBvbmUgZnJhbWV3b3JrLiBXaGljaGV2ZXIgZnJhbWV3b3JrXG4gKiAgICBpbnN0YW50aWF0ZWQgdGhlIGVsZW1lbnQgaXMgdGhlIG93bmVyLiBFYWNoIGZyYW1ld29yayBvbmx5IHVwZGF0ZXMvaW50ZXJhY3RzIHdpdGggaXRzIG93blxuICogICAgRE9NIGVsZW1lbnRzIGFuZCBpZ25vcmVzIG90aGVycy5cbiAqIDMuIEFuZ3VsYXJKUyB2MSBkaXJlY3RpdmVzIGFsd2F5cyBleGVjdXRlIGluc2lkZSBBbmd1bGFySlMgdjEgZnJhbWV3b3JrIGNvZGViYXNlIHJlZ2FyZGxlc3Mgb2ZcbiAqICAgIHdoZXJlIHRoZXkgYXJlIGluc3RhbnRpYXRlZC5cbiAqIDQuIEFuZ3VsYXIgdjIgY29tcG9uZW50cyBhbHdheXMgZXhlY3V0ZSBpbnNpZGUgQW5ndWxhciB2MiBmcmFtZXdvcmsgY29kZWJhc2UgcmVnYXJkbGVzcyBvZlxuICogICAgd2hlcmUgdGhleSBhcmUgaW5zdGFudGlhdGVkLlxuICogNS4gQW4gQW5ndWxhckpTIHYxIGNvbXBvbmVudCBjYW4gYmUgdXBncmFkZWQgdG8gYW4gQW5ndWxhciB2MiBjb21wb25lbnQuIFRoaXMgY3JlYXRlcyBhblxuICogICAgQW5ndWxhciB2MiBkaXJlY3RpdmUsIHdoaWNoIGJvb3RzdHJhcHMgdGhlIEFuZ3VsYXJKUyB2MSBjb21wb25lbnQgZGlyZWN0aXZlIGluIHRoYXQgbG9jYXRpb24uXG4gKiA2LiBBbiBBbmd1bGFyIHYyIGNvbXBvbmVudCBjYW4gYmUgZG93bmdyYWRlZCB0byBhbiBBbmd1bGFySlMgdjEgY29tcG9uZW50IGRpcmVjdGl2ZS4gVGhpcyBjcmVhdGVzXG4gKiAgICBhbiBBbmd1bGFySlMgdjEgZGlyZWN0aXZlLCB3aGljaCBib290c3RyYXBzIHRoZSBBbmd1bGFyIHYyIGNvbXBvbmVudCBpbiB0aGF0IGxvY2F0aW9uLlxuICogNy4gV2hlbmV2ZXIgYW4gYWRhcHRlciBjb21wb25lbnQgaXMgaW5zdGFudGlhdGVkIHRoZSBob3N0IGVsZW1lbnQgaXMgb3duZWQgYnkgdGhlIGZyYW1ld29ya1xuICogICAgZG9pbmcgdGhlIGluc3RhbnRpYXRpb24uIFRoZSBvdGhlciBmcmFtZXdvcmsgdGhlbiBpbnN0YW50aWF0ZXMgYW5kIG93bnMgdGhlIHZpZXcgZm9yIHRoYXRcbiAqICAgIGNvbXBvbmVudC4gVGhpcyBpbXBsaWVzIHRoYXQgY29tcG9uZW50IGJpbmRpbmdzIHdpbGwgYWx3YXlzIGZvbGxvdyB0aGUgc2VtYW50aWNzIG9mIHRoZVxuICogICAgaW5zdGFudGlhdGlvbiBmcmFtZXdvcmsuIFRoZSBzeW50YXggaXMgYWx3YXlzIHRoYXQgb2YgQW5ndWxhciB2MiBzeW50YXguXG4gKiA4LiBBbmd1bGFySlMgdjEgaXMgYWx3YXlzIGJvb3RzdHJhcHBlZCBmaXJzdCBhbmQgb3ducyB0aGUgYm90dG9tIG1vc3Qgdmlldy5cbiAqIDkuIFRoZSBuZXcgYXBwbGljYXRpb24gaXMgcnVubmluZyBpbiBBbmd1bGFyIHYyIHpvbmUsIGFuZCB0aGVyZWZvcmUgaXQgbm8gbG9uZ2VyIG5lZWRzIGNhbGxzIHRvXG4gKiAgICBgJGFwcGx5KClgLlxuICpcbiAqICMjIyBFeGFtcGxlXG4gKlxuICogYGBgXG4gKiB2YXIgYWRhcHRlciA9IG5ldyBVcGdyYWRlQWRhcHRlcigpO1xuICogdmFyIG1vZHVsZSA9IGFuZ3VsYXIubW9kdWxlKCdteUV4YW1wbGUnLCBbXSk7XG4gKiBtb2R1bGUuZGlyZWN0aXZlKCduZzInLCBhZGFwdGVyLmRvd25ncmFkZU5nMkNvbXBvbmVudChOZzIpKTtcbiAqXG4gKiBtb2R1bGUuZGlyZWN0aXZlKCduZzEnLCBmdW5jdGlvbigpIHtcbiAqICAgcmV0dXJuIHtcbiAqICAgICAgc2NvcGU6IHsgdGl0bGU6ICc9JyB9LFxuICogICAgICB0ZW1wbGF0ZTogJ25nMVtIZWxsbyB7e3RpdGxlfX0hXSg8c3BhbiBuZy10cmFuc2NsdWRlPjwvc3Bhbj4pJ1xuICogICB9O1xuICogfSk7XG4gKlxuICpcbiAqIEBDb21wb25lbnQoe1xuICogICBzZWxlY3RvcjogJ25nMicsXG4gKiAgIGlucHV0czogWyduYW1lJ10sXG4gKiAgIHRlbXBsYXRlOiAnbmcyWzxuZzEgW3RpdGxlXT1cIm5hbWVcIj50cmFuc2NsdWRlPC9uZzE+XSg8bmctY29udGVudD48L25nLWNvbnRlbnQ+KScsXG4gKiAgIGRpcmVjdGl2ZXM6IFthZGFwdGVyLnVwZ3JhZGVOZzFDb21wb25lbnQoJ25nMScpXVxuICogfSlcbiAqIGNsYXNzIE5nMiB7XG4gKiB9XG4gKlxuICogZG9jdW1lbnQuYm9keS5pbm5lckhUTUwgPSAnPG5nMiBuYW1lPVwiV29ybGRcIj5wcm9qZWN0PC9uZzI+JztcbiAqXG4gKiBhZGFwdGVyLmJvb3RzdHJhcChkb2N1bWVudC5ib2R5LCBbJ215RXhhbXBsZSddKS5yZWFkeShmdW5jdGlvbigpIHtcbiAqICAgZXhwZWN0KGRvY3VtZW50LmJvZHkudGV4dENvbnRlbnQpLnRvRXF1YWwoXG4gKiAgICAgICBcIm5nMltuZzFbSGVsbG8gV29ybGQhXSh0cmFuc2NsdWRlKV0ocHJvamVjdClcIik7XG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgVXBncmFkZUFkYXB0ZXIge1xuICAvKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBpZFByZWZpeDogc3RyaW5nID0gYE5HMl9VUEdSQURFXyR7dXBncmFkZUNvdW50Kyt9X2A7XG4gIC8qIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIHVwZ3JhZGVkQ29tcG9uZW50czogVHlwZVtdID0gW107XG4gIC8qIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIGRvd25ncmFkZWRDb21wb25lbnRzOiB7W25hbWU6IHN0cmluZ106IFVwZ3JhZGVOZzFDb21wb25lbnRBZGFwdGVyQnVpbGRlcn0gPSB7fTtcbiAgLyogQGludGVybmFsICovXG4gIHByaXZhdGUgcHJvdmlkZXJzOiBBcnJheTxUeXBlIHwgUHJvdmlkZXIgfCBhbnlbXT4gPSBbXTtcblxuICAvKipcbiAgICogQWxsb3dzIEFuZ3VsYXIgdjIgQ29tcG9uZW50IHRvIGJlIHVzZWQgZnJvbSBBbmd1bGFySlMgdjEuXG4gICAqXG4gICAqIFVzZSBgZG93bmdyYWRlTmcyQ29tcG9uZW50YCB0byBjcmVhdGUgYW4gQW5ndWxhckpTIHYxIERpcmVjdGl2ZSBEZWZpbml0aW9uIEZhY3RvcnkgZnJvbVxuICAgKiBBbmd1bGFyIHYyIENvbXBvbmVudC4gVGhlIGFkYXB0ZXIgd2lsbCBib290c3RyYXAgQW5ndWxhciB2MiBjb21wb25lbnQgZnJvbSB3aXRoaW4gdGhlXG4gICAqIEFuZ3VsYXJKUyB2MSB0ZW1wbGF0ZS5cbiAgICpcbiAgICogIyMgTWVudGFsIE1vZGVsXG4gICAqXG4gICAqIDEuIFRoZSBjb21wb25lbnQgaXMgaW5zdGFudGlhdGVkIGJ5IGJlaW5nIGxpc3RlZCBpbiBBbmd1bGFySlMgdjEgdGVtcGxhdGUuIFRoaXMgbWVhbnMgdGhhdCB0aGVcbiAgICogICAgaG9zdCBlbGVtZW50IGlzIGNvbnRyb2xsZWQgYnkgQW5ndWxhckpTIHYxLCBidXQgdGhlIGNvbXBvbmVudCdzIHZpZXcgd2lsbCBiZSBjb250cm9sbGVkIGJ5XG4gICAqICAgIEFuZ3VsYXIgdjIuXG4gICAqIDIuIEV2ZW4gdGhvdWdodCB0aGUgY29tcG9uZW50IGlzIGluc3RhbnRpYXRlZCBpbiBBbmd1bGFySlMgdjEsIGl0IHdpbGwgYmUgdXNpbmcgQW5ndWxhciB2MlxuICAgKiAgICBzeW50YXguIFRoaXMgaGFzIHRvIGJlIGRvbmUsIHRoaXMgd2F5IGJlY2F1c2Ugd2UgbXVzdCBmb2xsb3cgQW5ndWxhciB2MiBjb21wb25lbnRzIGRvIG5vdFxuICAgKiAgICBkZWNsYXJlIGhvdyB0aGUgYXR0cmlidXRlcyBzaG91bGQgYmUgaW50ZXJwcmV0ZWQuXG4gICAqXG4gICAqICMjIFN1cHBvcnRlZCBGZWF0dXJlc1xuICAgKlxuICAgKiAtIEJpbmRpbmdzOlxuICAgKiAgIC0gQXR0cmlidXRlOiBgPGNvbXAgbmFtZT1cIldvcmxkXCI+YFxuICAgKiAgIC0gSW50ZXJwb2xhdGlvbjogIGA8Y29tcCBncmVldGluZz1cIkhlbGxvIHt7bmFtZX19IVwiPmBcbiAgICogICAtIEV4cHJlc3Npb246ICBgPGNvbXAgW25hbWVdPVwidXNlcm5hbWVcIj5gXG4gICAqICAgLSBFdmVudDogIGA8Y29tcCAoY2xvc2UpPVwiZG9Tb21ldGhpbmcoKVwiPmBcbiAgICogLSBDb250ZW50IHByb2plY3Rpb246IHllc1xuICAgKlxuICAgKiAjIyMgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBcbiAgICogdmFyIGFkYXB0ZXIgPSBuZXcgVXBncmFkZUFkYXB0ZXIoKTtcbiAgICogdmFyIG1vZHVsZSA9IGFuZ3VsYXIubW9kdWxlKCdteUV4YW1wbGUnLCBbXSk7XG4gICAqIG1vZHVsZS5kaXJlY3RpdmUoJ2dyZWV0JywgYWRhcHRlci5kb3duZ3JhZGVOZzJDb21wb25lbnQoR3JlZXRlcikpO1xuICAgKlxuICAgKiBAQ29tcG9uZW50KHtcbiAgICogICBzZWxlY3RvcjogJ2dyZWV0JyxcbiAgICogICB0ZW1wbGF0ZTogJ3t7c2FsdXRhdGlvbn19IHt7bmFtZX19ISAtIDxuZy1jb250ZW50PjwvbmctY29udGVudD4nXG4gICAqIH0pXG4gICAqIGNsYXNzIEdyZWV0ZXIge1xuICAgKiAgIEBJbnB1dCgpIHNhbHV0YXRpb246IHN0cmluZztcbiAgICogICBASW5wdXQoKSBuYW1lOiBzdHJpbmc7XG4gICAqIH1cbiAgICpcbiAgICogZG9jdW1lbnQuYm9keS5pbm5lckhUTUwgPVxuICAgKiAgICduZzEgdGVtcGxhdGU6IDxncmVldCBzYWx1dGF0aW9uPVwiSGVsbG9cIiBbbmFtZV09XCJ3b3JsZFwiPnRleHQ8L2dyZWV0Pic7XG4gICAqXG4gICAqIGFkYXB0ZXIuYm9vdHN0cmFwKGRvY3VtZW50LmJvZHksIFsnbXlFeGFtcGxlJ10pLnJlYWR5KGZ1bmN0aW9uKCkge1xuICAgKiAgIGV4cGVjdChkb2N1bWVudC5ib2R5LnRleHRDb250ZW50KS50b0VxdWFsKFwibmcxIHRlbXBsYXRlOiBIZWxsbyB3b3JsZCEgLSB0ZXh0XCIpO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBkb3duZ3JhZGVOZzJDb21wb25lbnQodHlwZTogVHlwZSk6IEZ1bmN0aW9uIHtcbiAgICB0aGlzLnVwZ3JhZGVkQ29tcG9uZW50cy5wdXNoKHR5cGUpO1xuICAgIHZhciBpbmZvOiBDb21wb25lbnRJbmZvID0gZ2V0Q29tcG9uZW50SW5mbyh0eXBlKTtcbiAgICByZXR1cm4gbmcxQ29tcG9uZW50RGlyZWN0aXZlKGluZm8sIGAke3RoaXMuaWRQcmVmaXh9JHtpbmZvLnNlbGVjdG9yfV9jYCk7XG4gIH1cblxuICAvKipcbiAgICogQWxsb3dzIEFuZ3VsYXJKUyB2MSBDb21wb25lbnQgdG8gYmUgdXNlZCBmcm9tIEFuZ3VsYXIgdjIuXG4gICAqXG4gICAqIFVzZSBgdXBncmFkZU5nMUNvbXBvbmVudGAgdG8gY3JlYXRlIGFuIEFuZ3VsYXIgdjIgY29tcG9uZW50IGZyb20gQW5ndWxhckpTIHYxIENvbXBvbmVudFxuICAgKiBkaXJlY3RpdmUuIFRoZSBhZGFwdGVyIHdpbGwgYm9vdHN0cmFwIEFuZ3VsYXJKUyB2MSBjb21wb25lbnQgZnJvbSB3aXRoaW4gdGhlIEFuZ3VsYXIgdjJcbiAgICogdGVtcGxhdGUuXG4gICAqXG4gICAqICMjIE1lbnRhbCBNb2RlbFxuICAgKlxuICAgKiAxLiBUaGUgY29tcG9uZW50IGlzIGluc3RhbnRpYXRlZCBieSBiZWluZyBsaXN0ZWQgaW4gQW5ndWxhciB2MiB0ZW1wbGF0ZS4gVGhpcyBtZWFucyB0aGF0IHRoZVxuICAgKiAgICBob3N0IGVsZW1lbnQgaXMgY29udHJvbGxlZCBieSBBbmd1bGFyIHYyLCBidXQgdGhlIGNvbXBvbmVudCdzIHZpZXcgd2lsbCBiZSBjb250cm9sbGVkIGJ5XG4gICAqICAgIEFuZ3VsYXJKUyB2MS5cbiAgICpcbiAgICogIyMgU3VwcG9ydGVkIEZlYXR1cmVzXG4gICAqXG4gICAqIC0gQmluZGluZ3M6XG4gICAqICAgLSBBdHRyaWJ1dGU6IGA8Y29tcCBuYW1lPVwiV29ybGRcIj5gXG4gICAqICAgLSBJbnRlcnBvbGF0aW9uOiAgYDxjb21wIGdyZWV0aW5nPVwiSGVsbG8ge3tuYW1lfX0hXCI+YFxuICAgKiAgIC0gRXhwcmVzc2lvbjogIGA8Y29tcCBbbmFtZV09XCJ1c2VybmFtZVwiPmBcbiAgICogICAtIEV2ZW50OiAgYDxjb21wIChjbG9zZSk9XCJkb1NvbWV0aGluZygpXCI+YFxuICAgKiAtIFRyYW5zY2x1c2lvbjogeWVzXG4gICAqIC0gT25seSBzb21lIG9mIHRoZSBmZWF0dXJlcyBvZlxuICAgKiAgIFtEaXJlY3RpdmUgRGVmaW5pdGlvbiBPYmplY3RdKGh0dHBzOi8vZG9jcy5hbmd1bGFyanMub3JnL2FwaS9uZy9zZXJ2aWNlLyRjb21waWxlKSBhcmVcbiAgICogICBzdXBwb3J0ZWQ6XG4gICAqICAgLSBgY29tcGlsZWA6IG5vdCBzdXBwb3J0ZWQgYmVjYXVzZSB0aGUgaG9zdCBlbGVtZW50IGlzIG93bmVkIGJ5IEFuZ3VsYXIgdjIsIHdoaWNoIGRvZXNcbiAgICogICAgIG5vdCBhbGxvdyBtb2RpZnlpbmcgRE9NIHN0cnVjdHVyZSBkdXJpbmcgY29tcGlsYXRpb24uXG4gICAqICAgLSBgY29udHJvbGxlcmA6IHN1cHBvcnRlZC4gKE5PVEU6IGluamVjdGlvbiBvZiBgJGF0dHJzYCBhbmQgYCR0cmFuc2NsdWRlYCBpcyBub3Qgc3VwcG9ydGVkLilcbiAgICogICAtIGBjb250cm9sbGVyQXMnOiBzdXBwb3J0ZWQuXG4gICAqICAgLSBgYmluZFRvQ29udHJvbGxlcic6IHN1cHBvcnRlZC5cbiAgICogICAtIGBsaW5rJzogc3VwcG9ydGVkLiAoTk9URTogb25seSBwcmUtbGluayBmdW5jdGlvbiBpcyBzdXBwb3J0ZWQuKVxuICAgKiAgIC0gYG5hbWUnOiBzdXBwb3J0ZWQuXG4gICAqICAgLSBgcHJpb3JpdHknOiBpZ25vcmVkLlxuICAgKiAgIC0gYHJlcGxhY2UnOiBub3Qgc3VwcG9ydGVkLlxuICAgKiAgIC0gYHJlcXVpcmVgOiBzdXBwb3J0ZWQuXG4gICAqICAgLSBgcmVzdHJpY3RgOiBtdXN0IGJlIHNldCB0byAnRScuXG4gICAqICAgLSBgc2NvcGVgOiBzdXBwb3J0ZWQuXG4gICAqICAgLSBgdGVtcGxhdGVgOiBzdXBwb3J0ZWQuXG4gICAqICAgLSBgdGVtcGxhdGVVcmxgOiBzdXBwb3J0ZWQuXG4gICAqICAgLSBgdGVybWluYWxgOiBpZ25vcmVkLlxuICAgKiAgIC0gYHRyYW5zY2x1ZGVgOiBzdXBwb3J0ZWQuXG4gICAqXG4gICAqXG4gICAqICMjIyBFeGFtcGxlXG4gICAqXG4gICAqIGBgYFxuICAgKiB2YXIgYWRhcHRlciA9IG5ldyBVcGdyYWRlQWRhcHRlcigpO1xuICAgKiB2YXIgbW9kdWxlID0gYW5ndWxhci5tb2R1bGUoJ215RXhhbXBsZScsIFtdKTtcbiAgICpcbiAgICogbW9kdWxlLmRpcmVjdGl2ZSgnZ3JlZXQnLCBmdW5jdGlvbigpIHtcbiAgICogICByZXR1cm4ge1xuICAgKiAgICAgc2NvcGU6IHtzYWx1dGF0aW9uOiAnPScsIG5hbWU6ICc9JyB9LFxuICAgKiAgICAgdGVtcGxhdGU6ICd7e3NhbHV0YXRpb259fSB7e25hbWV9fSEgLSA8c3BhbiBuZy10cmFuc2NsdWRlPjwvc3Bhbj4nXG4gICAqICAgfTtcbiAgICogfSk7XG4gICAqXG4gICAqIG1vZHVsZS5kaXJlY3RpdmUoJ25nMicsIGFkYXB0ZXIuZG93bmdyYWRlTmcyQ29tcG9uZW50KE5nMikpO1xuICAgKlxuICAgKiBAQ29tcG9uZW50KHtcbiAgICogICBzZWxlY3RvcjogJ25nMicsXG4gICAqICAgdGVtcGxhdGU6ICduZzIgdGVtcGxhdGU6IDxncmVldCBzYWx1dGF0aW9uPVwiSGVsbG9cIiBbbmFtZV09XCJ3b3JsZFwiPnRleHQ8L2dyZWV0PidcbiAgICogICBkaXJlY3RpdmVzOiBbYWRhcHRlci51cGdyYWRlTmcxQ29tcG9uZW50KCdncmVldCcpXVxuICAgKiB9KVxuICAgKiBjbGFzcyBOZzIge1xuICAgKiB9XG4gICAqXG4gICAqIGRvY3VtZW50LmJvZHkuaW5uZXJIVE1MID0gJzxuZzI+PC9uZzI+JztcbiAgICpcbiAgICogYWRhcHRlci5ib290c3RyYXAoZG9jdW1lbnQuYm9keSwgWydteUV4YW1wbGUnXSkucmVhZHkoZnVuY3Rpb24oKSB7XG4gICAqICAgZXhwZWN0KGRvY3VtZW50LmJvZHkudGV4dENvbnRlbnQpLnRvRXF1YWwoXCJuZzIgdGVtcGxhdGU6IEhlbGxvIHdvcmxkISAtIHRleHRcIik7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIHVwZ3JhZGVOZzFDb21wb25lbnQobmFtZTogc3RyaW5nKTogVHlwZSB7XG4gICAgaWYgKCg8YW55PnRoaXMuZG93bmdyYWRlZENvbXBvbmVudHMpLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICByZXR1cm4gdGhpcy5kb3duZ3JhZGVkQ29tcG9uZW50c1tuYW1lXS50eXBlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gKHRoaXMuZG93bmdyYWRlZENvbXBvbmVudHNbbmFtZV0gPSBuZXcgVXBncmFkZU5nMUNvbXBvbmVudEFkYXB0ZXJCdWlsZGVyKG5hbWUpKS50eXBlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBCb290c3RyYXAgYSBoeWJyaWQgQW5ndWxhckpTIHYxIC8gQW5ndWxhciB2MiBhcHBsaWNhdGlvbi5cbiAgICpcbiAgICogVGhpcyBgYm9vdHN0cmFwYCBtZXRob2QgaXMgYSBkaXJlY3QgcmVwbGFjZW1lbnQgKHRha2VzIHNhbWUgYXJndW1lbnRzKSBmb3IgQW5ndWxhckpTIHYxXG4gICAqIFtgYm9vdHN0cmFwYF0oaHR0cHM6Ly9kb2NzLmFuZ3VsYXJqcy5vcmcvYXBpL25nL2Z1bmN0aW9uL2FuZ3VsYXIuYm9vdHN0cmFwKSBtZXRob2QuIFVubGlrZVxuICAgKiBBbmd1bGFySlMgdjEsIHRoaXMgYm9vdHN0cmFwIGlzIGFzeW5jaHJvbm91cy5cbiAgICpcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBgXG4gICAqIHZhciBhZGFwdGVyID0gbmV3IFVwZ3JhZGVBZGFwdGVyKCk7XG4gICAqIHZhciBtb2R1bGUgPSBhbmd1bGFyLm1vZHVsZSgnbXlFeGFtcGxlJywgW10pO1xuICAgKiBtb2R1bGUuZGlyZWN0aXZlKCduZzInLCBhZGFwdGVyLmRvd25ncmFkZU5nMkNvbXBvbmVudChOZzIpKTtcbiAgICpcbiAgICogbW9kdWxlLmRpcmVjdGl2ZSgnbmcxJywgZnVuY3Rpb24oKSB7XG4gICAqICAgcmV0dXJuIHtcbiAgICogICAgICBzY29wZTogeyB0aXRsZTogJz0nIH0sXG4gICAqICAgICAgdGVtcGxhdGU6ICduZzFbSGVsbG8ge3t0aXRsZX19IV0oPHNwYW4gbmctdHJhbnNjbHVkZT48L3NwYW4+KSdcbiAgICogICB9O1xuICAgKiB9KTtcbiAgICpcbiAgICpcbiAgICogQENvbXBvbmVudCh7XG4gICAqICAgc2VsZWN0b3I6ICduZzInLFxuICAgKiAgIGlucHV0czogWyduYW1lJ10sXG4gICAqICAgdGVtcGxhdGU6ICduZzJbPG5nMSBbdGl0bGVdPVwibmFtZVwiPnRyYW5zY2x1ZGU8L25nMT5dKDxuZy1jb250ZW50PjwvbmctY29udGVudD4pJyxcbiAgICogICBkaXJlY3RpdmVzOiBbYWRhcHRlci51cGdyYWRlTmcxQ29tcG9uZW50KCduZzEnKV1cbiAgICogfSlcbiAgICogY2xhc3MgTmcyIHtcbiAgICogfVxuICAgKlxuICAgKiBkb2N1bWVudC5ib2R5LmlubmVySFRNTCA9ICc8bmcyIG5hbWU9XCJXb3JsZFwiPnByb2plY3Q8L25nMj4nO1xuICAgKlxuICAgKiBhZGFwdGVyLmJvb3RzdHJhcChkb2N1bWVudC5ib2R5LCBbJ215RXhhbXBsZSddKS5yZWFkeShmdW5jdGlvbigpIHtcbiAgICogICBleHBlY3QoZG9jdW1lbnQuYm9keS50ZXh0Q29udGVudCkudG9FcXVhbChcbiAgICogICAgICAgXCJuZzJbbmcxW0hlbGxvIFdvcmxkIV0odHJhbnNjbHVkZSldKHByb2plY3QpXCIpO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBib290c3RyYXAoZWxlbWVudDogRWxlbWVudCwgbW9kdWxlcz86IGFueVtdLFxuICAgICAgICAgICAgY29uZmlnPzogYW5ndWxhci5JQW5ndWxhckJvb3RzdHJhcENvbmZpZyk6IFVwZ3JhZGVBZGFwdGVyUmVmIHtcbiAgICB2YXIgdXBncmFkZSA9IG5ldyBVcGdyYWRlQWRhcHRlclJlZigpO1xuICAgIHZhciBuZzFJbmplY3RvcjogYW5ndWxhci5JSW5qZWN0b3JTZXJ2aWNlID0gbnVsbDtcbiAgICB2YXIgcGxhdGZvcm1SZWY6IFBsYXRmb3JtUmVmID0gYnJvd3NlclBsYXRmb3JtKCk7XG4gICAgdmFyIGFwcGxpY2F0aW9uUmVmOiBBcHBsaWNhdGlvblJlZiA9XG4g