@angular/upgrade 13.0.0-next.6 → 13.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{esm2015/index.js → esm2020/index.mjs} +0 -0
- package/{esm2015/public_api.js → esm2020/public_api.mjs} +0 -0
- package/{esm2015/src/common/src/angular1.js → esm2020/src/common/src/angular1.mjs} +2 -2
- package/{esm2015/src/common/src/component_info.js → esm2020/src/common/src/component_info.mjs} +0 -0
- package/{esm2015/src/common/src/constants.js → esm2020/src/common/src/constants.mjs} +0 -0
- package/{esm2015/src/common/src/downgrade_component.js → esm2020/src/common/src/downgrade_component.mjs} +0 -0
- package/{esm2015/src/common/src/downgrade_component_adapter.js → esm2020/src/common/src/downgrade_component_adapter.mjs} +0 -0
- package/{esm2015/src/common/src/downgrade_injectable.js → esm2020/src/common/src/downgrade_injectable.mjs} +0 -0
- package/{esm2015/src/common/src/promise_util.js → esm2020/src/common/src/promise_util.mjs} +0 -0
- package/{esm2015/src/common/src/upgrade_helper.js → esm2020/src/common/src/upgrade_helper.mjs} +0 -0
- package/{esm2015/src/common/src/util.js → esm2020/src/common/src/util.mjs} +0 -0
- package/{esm2015/src/common/src/version.js → esm2020/src/common/src/version.mjs} +1 -1
- package/esm2020/src/dynamic/src/upgrade_adapter.mjs +683 -0
- package/esm2020/src/dynamic/src/upgrade_ng1_adapter.mjs +223 -0
- package/{esm2015/static/index.js → esm2020/static/index.mjs} +0 -0
- package/{esm2015/static/public_api.js → esm2020/static/public_api.mjs} +0 -0
- package/{esm2015/static/src/angular1_providers.js → esm2020/static/src/angular1_providers.mjs} +0 -0
- package/{esm2015/static/src/downgrade_module.js → esm2020/static/src/downgrade_module.mjs} +0 -0
- package/esm2020/static/src/upgrade_component.mjs +240 -0
- package/esm2020/static/src/upgrade_module.mjs +291 -0
- package/{esm2015/static/src/util.js → esm2020/static/src/util.mjs} +0 -0
- package/esm2020/static/static.mjs +5 -0
- package/{esm2015/static/testing/index.js → esm2020/static/testing/index.mjs} +0 -0
- package/{esm2015/static/testing/public_api.js → esm2020/static/testing/public_api.mjs} +0 -0
- package/esm2020/static/testing/src/create_angular_testing_module.mjs +101 -0
- package/{esm2015/static/testing/src/create_angularjs_testing_module.js → esm2020/static/testing/src/create_angularjs_testing_module.mjs} +0 -0
- package/esm2020/static/testing/testing.mjs +5 -0
- package/{esm2015/upgrade.js → esm2020/upgrade.mjs} +0 -0
- package/fesm2015/static/{testing.js → testing.mjs} +16 -14
- package/fesm2015/static/testing.mjs.map +1 -0
- package/fesm2015/{static.js → static.mjs} +23 -26
- package/fesm2015/static.mjs.map +1 -0
- package/fesm2015/upgrade.mjs +2061 -0
- package/fesm2015/upgrade.mjs.map +1 -0
- package/fesm2020/static/testing.mjs +325 -0
- package/fesm2020/static/testing.mjs.map +1 -0
- package/fesm2020/static.mjs +1931 -0
- package/fesm2020/static.mjs.map +1 -0
- package/{fesm2015/upgrade.js → fesm2020/upgrade.mjs} +32 -48
- package/fesm2020/upgrade.mjs.map +1 -0
- package/package.json +42 -12
- package/static/package.json +5 -5
- package/static/static.d.ts +7 -20
- package/static/testing/package.json +5 -5
- package/static/testing/testing.d.ts +1 -133
- package/upgrade.d.ts +1 -1
- package/bundles/upgrade-static-testing.umd.js +0 -335
- package/bundles/upgrade-static-testing.umd.js.map +0 -1
- package/bundles/upgrade-static.umd.js +0 -2303
- package/bundles/upgrade-static.umd.js.map +0 -1
- package/bundles/upgrade.umd.js +0 -2423
- package/bundles/upgrade.umd.js.map +0 -1
- package/esm2015/src/common/common.externs.js +0 -0
- package/esm2015/src/dynamic/src/upgrade_adapter.js +0 -682
- package/esm2015/src/dynamic/src/upgrade_ng1_adapter.js +0 -231
- package/esm2015/static/src/upgrade_component.js +0 -242
- package/esm2015/static/src/upgrade_module.js +0 -291
- package/esm2015/static/static.externs.js +0 -6
- package/esm2015/static/static.js +0 -6
- package/esm2015/static/testing/src/create_angular_testing_module.js +0 -99
- package/esm2015/static/testing/testing.externs.js +0 -6
- package/esm2015/static/testing/testing.js +0 -7
- package/esm2015/upgrade.externs.js +0 -6
- package/fesm2015/static/testing.js.map +0 -1
- package/fesm2015/static.js.map +0 -1
- package/fesm2015/upgrade.js.map +0 -1
- package/static/static.metadata.json +0 -1
- package/static/testing/testing.metadata.json +0 -1
- package/static/testing.d.ts +0 -7
- package/static/testing.metadata.json +0 -1
- package/static.d.ts +0 -7
- package/static.metadata.json +0 -1
- package/upgrade.metadata.json +0 -1
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { __decorate, __metadata } from "tslib";
|
|
9
|
+
import { Compiler, Injector, isDevMode, NgModule, NgZone, resolveForwardRef, Testability } from '@angular/core';
|
|
10
|
+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
11
|
+
import { bootstrap, element as angularElement, module_ as angularModule } from '../../common/src/angular1';
|
|
12
|
+
import { $$TESTABILITY, $COMPILE, $INJECTOR, $ROOT_SCOPE, COMPILER_KEY, INJECTOR_KEY, LAZY_MODULE_REF, NG_ZONE_KEY, UPGRADE_APP_TYPE_KEY } from '../../common/src/constants';
|
|
13
|
+
import { downgradeComponent } from '../../common/src/downgrade_component';
|
|
14
|
+
import { downgradeInjectable } from '../../common/src/downgrade_injectable';
|
|
15
|
+
import { controllerKey, Deferred, destroyApp, onError } from '../../common/src/util';
|
|
16
|
+
import { UpgradeNg1ComponentAdapterBuilder } from './upgrade_ng1_adapter';
|
|
17
|
+
let upgradeCount = 0;
|
|
18
|
+
/**
|
|
19
|
+
* Use `UpgradeAdapter` to allow AngularJS and Angular to coexist in a single application.
|
|
20
|
+
*
|
|
21
|
+
* The `UpgradeAdapter` allows:
|
|
22
|
+
* 1. creation of Angular component from AngularJS component directive
|
|
23
|
+
* (See [UpgradeAdapter#upgradeNg1Component()])
|
|
24
|
+
* 2. creation of AngularJS directive from Angular component.
|
|
25
|
+
* (See [UpgradeAdapter#downgradeNg2Component()])
|
|
26
|
+
* 3. Bootstrapping of a hybrid Angular application which contains both of the frameworks
|
|
27
|
+
* coexisting in a single application.
|
|
28
|
+
*
|
|
29
|
+
* @usageNotes
|
|
30
|
+
* ### Mental Model
|
|
31
|
+
*
|
|
32
|
+
* When reasoning about how a hybrid application works it is useful to have a mental model which
|
|
33
|
+
* describes what is happening and explains what is happening at the lowest level.
|
|
34
|
+
*
|
|
35
|
+
* 1. There are two independent frameworks running in a single application, each framework treats
|
|
36
|
+
* the other as a black box.
|
|
37
|
+
* 2. Each DOM element on the page is owned exactly by one framework. Whichever framework
|
|
38
|
+
* instantiated the element is the owner. Each framework only updates/interacts with its own
|
|
39
|
+
* DOM elements and ignores others.
|
|
40
|
+
* 3. AngularJS directives always execute inside AngularJS framework codebase regardless of
|
|
41
|
+
* where they are instantiated.
|
|
42
|
+
* 4. Angular components always execute inside Angular framework codebase regardless of
|
|
43
|
+
* where they are instantiated.
|
|
44
|
+
* 5. An AngularJS component can be upgraded to an Angular component. This creates an
|
|
45
|
+
* Angular directive, which bootstraps the AngularJS component directive in that location.
|
|
46
|
+
* 6. An Angular component can be downgraded to an AngularJS component directive. This creates
|
|
47
|
+
* an AngularJS directive, which bootstraps the Angular component in that location.
|
|
48
|
+
* 7. Whenever an adapter component is instantiated the host element is owned by the framework
|
|
49
|
+
* doing the instantiation. The other framework then instantiates and owns the view for that
|
|
50
|
+
* component. This implies that component bindings will always follow the semantics of the
|
|
51
|
+
* instantiation framework. The syntax is always that of Angular syntax.
|
|
52
|
+
* 8. AngularJS is always bootstrapped first and owns the bottom most view.
|
|
53
|
+
* 9. The new application is running in Angular zone, and therefore it no longer needs calls to
|
|
54
|
+
* `$apply()`.
|
|
55
|
+
*
|
|
56
|
+
* ### Example
|
|
57
|
+
*
|
|
58
|
+
* ```
|
|
59
|
+
* const adapter = new UpgradeAdapter(forwardRef(() => MyNg2Module), myCompilerOptions);
|
|
60
|
+
* const module = angular.module('myExample', []);
|
|
61
|
+
* module.directive('ng2Comp', adapter.downgradeNg2Component(Ng2Component));
|
|
62
|
+
*
|
|
63
|
+
* module.directive('ng1Hello', function() {
|
|
64
|
+
* return {
|
|
65
|
+
* scope: { title: '=' },
|
|
66
|
+
* template: 'ng1[Hello {{title}}!](<span ng-transclude></span>)'
|
|
67
|
+
* };
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
*
|
|
71
|
+
* @Component({
|
|
72
|
+
* selector: 'ng2-comp',
|
|
73
|
+
* inputs: ['name'],
|
|
74
|
+
* template: 'ng2[<ng1-hello [title]="name">transclude</ng1-hello>](<ng-content></ng-content>)',
|
|
75
|
+
* directives:
|
|
76
|
+
* })
|
|
77
|
+
* class Ng2Component {
|
|
78
|
+
* }
|
|
79
|
+
*
|
|
80
|
+
* @NgModule({
|
|
81
|
+
* declarations: [Ng2Component, adapter.upgradeNg1Component('ng1Hello')],
|
|
82
|
+
* imports: [BrowserModule]
|
|
83
|
+
* })
|
|
84
|
+
* class MyNg2Module {}
|
|
85
|
+
*
|
|
86
|
+
*
|
|
87
|
+
* document.body.innerHTML = '<ng2-comp name="World">project</ng2-comp>';
|
|
88
|
+
*
|
|
89
|
+
* adapter.bootstrap(document.body, ['myExample']).ready(function() {
|
|
90
|
+
* expect(document.body.textContent).toEqual(
|
|
91
|
+
* "ng2[ng1[Hello World!](transclude)](project)");
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @deprecated Deprecated since v5. Use `upgrade/static` instead, which also supports
|
|
97
|
+
* [Ahead-of-Time compilation](guide/aot-compiler).
|
|
98
|
+
* @publicApi
|
|
99
|
+
*/
|
|
100
|
+
export class UpgradeAdapter {
|
|
101
|
+
constructor(ng2AppModule, compilerOptions) {
|
|
102
|
+
this.ng2AppModule = ng2AppModule;
|
|
103
|
+
this.compilerOptions = compilerOptions;
|
|
104
|
+
this.idPrefix = `NG2_UPGRADE_${upgradeCount++}_`;
|
|
105
|
+
this.downgradedComponents = [];
|
|
106
|
+
/**
|
|
107
|
+
* An internal map of ng1 components which need to up upgraded to ng2.
|
|
108
|
+
*
|
|
109
|
+
* We can't upgrade until injector is instantiated and we can retrieve the component metadata.
|
|
110
|
+
* For this reason we keep a list of components to upgrade until ng1 injector is bootstrapped.
|
|
111
|
+
*
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
this.ng1ComponentsToBeUpgraded = {};
|
|
115
|
+
this.upgradedProviders = [];
|
|
116
|
+
this.moduleRef = null;
|
|
117
|
+
if (!ng2AppModule) {
|
|
118
|
+
throw new Error('UpgradeAdapter cannot be instantiated without an NgModule of the Angular app.');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Allows Angular Component to be used from AngularJS.
|
|
123
|
+
*
|
|
124
|
+
* Use `downgradeNg2Component` to create an AngularJS Directive Definition Factory from
|
|
125
|
+
* Angular Component. The adapter will bootstrap Angular component from within the
|
|
126
|
+
* AngularJS template.
|
|
127
|
+
*
|
|
128
|
+
* @usageNotes
|
|
129
|
+
* ### Mental Model
|
|
130
|
+
*
|
|
131
|
+
* 1. The component is instantiated by being listed in AngularJS template. This means that the
|
|
132
|
+
* host element is controlled by AngularJS, but the component's view will be controlled by
|
|
133
|
+
* Angular.
|
|
134
|
+
* 2. Even thought the component is instantiated in AngularJS, it will be using Angular
|
|
135
|
+
* syntax. This has to be done, this way because we must follow Angular components do not
|
|
136
|
+
* declare how the attributes should be interpreted.
|
|
137
|
+
* 3. `ng-model` is controlled by AngularJS and communicates with the downgraded Angular component
|
|
138
|
+
* by way of the `ControlValueAccessor` interface from @angular/forms. Only components that
|
|
139
|
+
* implement this interface are eligible.
|
|
140
|
+
*
|
|
141
|
+
* ### Supported Features
|
|
142
|
+
*
|
|
143
|
+
* - Bindings:
|
|
144
|
+
* - Attribute: `<comp name="World">`
|
|
145
|
+
* - Interpolation: `<comp greeting="Hello {{name}}!">`
|
|
146
|
+
* - Expression: `<comp [name]="username">`
|
|
147
|
+
* - Event: `<comp (close)="doSomething()">`
|
|
148
|
+
* - ng-model: `<comp ng-model="name">`
|
|
149
|
+
* - Content projection: yes
|
|
150
|
+
*
|
|
151
|
+
* ### Example
|
|
152
|
+
*
|
|
153
|
+
* ```
|
|
154
|
+
* const adapter = new UpgradeAdapter(forwardRef(() => MyNg2Module));
|
|
155
|
+
* const module = angular.module('myExample', []);
|
|
156
|
+
* module.directive('greet', adapter.downgradeNg2Component(Greeter));
|
|
157
|
+
*
|
|
158
|
+
* @Component({
|
|
159
|
+
* selector: 'greet',
|
|
160
|
+
* template: '{{salutation}} {{name}}! - <ng-content></ng-content>'
|
|
161
|
+
* })
|
|
162
|
+
* class Greeter {
|
|
163
|
+
* @Input() salutation: string;
|
|
164
|
+
* @Input() name: string;
|
|
165
|
+
* }
|
|
166
|
+
*
|
|
167
|
+
* @NgModule({
|
|
168
|
+
* declarations: [Greeter],
|
|
169
|
+
* imports: [BrowserModule]
|
|
170
|
+
* })
|
|
171
|
+
* class MyNg2Module {}
|
|
172
|
+
*
|
|
173
|
+
* document.body.innerHTML =
|
|
174
|
+
* 'ng1 template: <greet salutation="Hello" [name]="world">text</greet>';
|
|
175
|
+
*
|
|
176
|
+
* adapter.bootstrap(document.body, ['myExample']).ready(function() {
|
|
177
|
+
* expect(document.body.textContent).toEqual("ng1 template: Hello world! - text");
|
|
178
|
+
* });
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
downgradeNg2Component(component) {
|
|
182
|
+
this.downgradedComponents.push(component);
|
|
183
|
+
return downgradeComponent({ component });
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Allows AngularJS Component to be used from Angular.
|
|
187
|
+
*
|
|
188
|
+
* Use `upgradeNg1Component` to create an Angular component from AngularJS Component
|
|
189
|
+
* directive. The adapter will bootstrap AngularJS component from within the Angular
|
|
190
|
+
* template.
|
|
191
|
+
*
|
|
192
|
+
* @usageNotes
|
|
193
|
+
* ### Mental Model
|
|
194
|
+
*
|
|
195
|
+
* 1. The component is instantiated by being listed in Angular template. This means that the
|
|
196
|
+
* host element is controlled by Angular, but the component's view will be controlled by
|
|
197
|
+
* AngularJS.
|
|
198
|
+
*
|
|
199
|
+
* ### Supported Features
|
|
200
|
+
*
|
|
201
|
+
* - Bindings:
|
|
202
|
+
* - Attribute: `<comp name="World">`
|
|
203
|
+
* - Interpolation: `<comp greeting="Hello {{name}}!">`
|
|
204
|
+
* - Expression: `<comp [name]="username">`
|
|
205
|
+
* - Event: `<comp (close)="doSomething()">`
|
|
206
|
+
* - Transclusion: yes
|
|
207
|
+
* - Only some of the features of
|
|
208
|
+
* [Directive Definition Object](https://docs.angularjs.org/api/ng/service/$compile) are
|
|
209
|
+
* supported:
|
|
210
|
+
* - `compile`: not supported because the host element is owned by Angular, which does
|
|
211
|
+
* not allow modifying DOM structure during compilation.
|
|
212
|
+
* - `controller`: supported. (NOTE: injection of `$attrs` and `$transclude` is not supported.)
|
|
213
|
+
* - `controllerAs`: supported.
|
|
214
|
+
* - `bindToController`: supported.
|
|
215
|
+
* - `link`: supported. (NOTE: only pre-link function is supported.)
|
|
216
|
+
* - `name`: supported.
|
|
217
|
+
* - `priority`: ignored.
|
|
218
|
+
* - `replace`: not supported.
|
|
219
|
+
* - `require`: supported.
|
|
220
|
+
* - `restrict`: must be set to 'E'.
|
|
221
|
+
* - `scope`: supported.
|
|
222
|
+
* - `template`: supported.
|
|
223
|
+
* - `templateUrl`: supported.
|
|
224
|
+
* - `terminal`: ignored.
|
|
225
|
+
* - `transclude`: supported.
|
|
226
|
+
*
|
|
227
|
+
*
|
|
228
|
+
* ### Example
|
|
229
|
+
*
|
|
230
|
+
* ```
|
|
231
|
+
* const adapter = new UpgradeAdapter(forwardRef(() => MyNg2Module));
|
|
232
|
+
* const module = angular.module('myExample', []);
|
|
233
|
+
*
|
|
234
|
+
* module.directive('greet', function() {
|
|
235
|
+
* return {
|
|
236
|
+
* scope: {salutation: '=', name: '=' },
|
|
237
|
+
* template: '{{salutation}} {{name}}! - <span ng-transclude></span>'
|
|
238
|
+
* };
|
|
239
|
+
* });
|
|
240
|
+
*
|
|
241
|
+
* module.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
|
|
242
|
+
*
|
|
243
|
+
* @Component({
|
|
244
|
+
* selector: 'ng2',
|
|
245
|
+
* template: 'ng2 template: <greet salutation="Hello" [name]="world">text</greet>'
|
|
246
|
+
* })
|
|
247
|
+
* class Ng2Component {
|
|
248
|
+
* }
|
|
249
|
+
*
|
|
250
|
+
* @NgModule({
|
|
251
|
+
* declarations: [Ng2Component, adapter.upgradeNg1Component('greet')],
|
|
252
|
+
* imports: [BrowserModule]
|
|
253
|
+
* })
|
|
254
|
+
* class MyNg2Module {}
|
|
255
|
+
*
|
|
256
|
+
* document.body.innerHTML = '<ng2></ng2>';
|
|
257
|
+
*
|
|
258
|
+
* adapter.bootstrap(document.body, ['myExample']).ready(function() {
|
|
259
|
+
* expect(document.body.textContent).toEqual("ng2 template: Hello world! - text");
|
|
260
|
+
* });
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
upgradeNg1Component(name) {
|
|
264
|
+
if (this.ng1ComponentsToBeUpgraded.hasOwnProperty(name)) {
|
|
265
|
+
return this.ng1ComponentsToBeUpgraded[name].type;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
return (this.ng1ComponentsToBeUpgraded[name] = new UpgradeNg1ComponentAdapterBuilder(name))
|
|
269
|
+
.type;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Registers the adapter's AngularJS upgrade module for unit testing in AngularJS.
|
|
274
|
+
* Use this instead of `angular.mock.module()` to load the upgrade module into
|
|
275
|
+
* the AngularJS testing injector.
|
|
276
|
+
*
|
|
277
|
+
* @usageNotes
|
|
278
|
+
* ### Example
|
|
279
|
+
*
|
|
280
|
+
* ```
|
|
281
|
+
* const upgradeAdapter = new UpgradeAdapter(MyNg2Module);
|
|
282
|
+
*
|
|
283
|
+
* // configure the adapter with upgrade/downgrade components and services
|
|
284
|
+
* upgradeAdapter.downgradeNg2Component(MyComponent);
|
|
285
|
+
*
|
|
286
|
+
* let upgradeAdapterRef: UpgradeAdapterRef;
|
|
287
|
+
* let $compile, $rootScope;
|
|
288
|
+
*
|
|
289
|
+
* // We must register the adapter before any calls to `inject()`
|
|
290
|
+
* beforeEach(() => {
|
|
291
|
+
* upgradeAdapterRef = upgradeAdapter.registerForNg1Tests(['heroApp']);
|
|
292
|
+
* });
|
|
293
|
+
*
|
|
294
|
+
* beforeEach(inject((_$compile_, _$rootScope_) => {
|
|
295
|
+
* $compile = _$compile_;
|
|
296
|
+
* $rootScope = _$rootScope_;
|
|
297
|
+
* }));
|
|
298
|
+
*
|
|
299
|
+
* it("says hello", (done) => {
|
|
300
|
+
* upgradeAdapterRef.ready(() => {
|
|
301
|
+
* const element = $compile("<my-component></my-component>")($rootScope);
|
|
302
|
+
* $rootScope.$apply();
|
|
303
|
+
* expect(element.html()).toContain("Hello World");
|
|
304
|
+
* done();
|
|
305
|
+
* })
|
|
306
|
+
* });
|
|
307
|
+
*
|
|
308
|
+
* ```
|
|
309
|
+
*
|
|
310
|
+
* @param modules any AngularJS modules that the upgrade module should depend upon
|
|
311
|
+
* @returns an `UpgradeAdapterRef`, which lets you register a `ready()` callback to
|
|
312
|
+
* run assertions once the Angular components are ready to test through AngularJS.
|
|
313
|
+
*/
|
|
314
|
+
registerForNg1Tests(modules) {
|
|
315
|
+
const windowNgMock = window['angular'].mock;
|
|
316
|
+
if (!windowNgMock || !windowNgMock.module) {
|
|
317
|
+
throw new Error('Failed to find \'angular.mock.module\'.');
|
|
318
|
+
}
|
|
319
|
+
this.declareNg1Module(modules);
|
|
320
|
+
windowNgMock.module(this.ng1Module.name);
|
|
321
|
+
const upgrade = new UpgradeAdapterRef();
|
|
322
|
+
this.ng2BootstrapDeferred.promise.then((ng1Injector) => {
|
|
323
|
+
upgrade._bootstrapDone(this.moduleRef, ng1Injector);
|
|
324
|
+
}, onError);
|
|
325
|
+
return upgrade;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Bootstrap a hybrid AngularJS / Angular application.
|
|
329
|
+
*
|
|
330
|
+
* This `bootstrap` method is a direct replacement (takes same arguments) for AngularJS
|
|
331
|
+
* [`bootstrap`](https://docs.angularjs.org/api/ng/function/angular.bootstrap) method. Unlike
|
|
332
|
+
* AngularJS, this bootstrap is asynchronous.
|
|
333
|
+
*
|
|
334
|
+
* @usageNotes
|
|
335
|
+
* ### Example
|
|
336
|
+
*
|
|
337
|
+
* ```
|
|
338
|
+
* const adapter = new UpgradeAdapter(MyNg2Module);
|
|
339
|
+
* const module = angular.module('myExample', []);
|
|
340
|
+
* module.directive('ng2', adapter.downgradeNg2Component(Ng2));
|
|
341
|
+
*
|
|
342
|
+
* module.directive('ng1', function() {
|
|
343
|
+
* return {
|
|
344
|
+
* scope: { title: '=' },
|
|
345
|
+
* template: 'ng1[Hello {{title}}!](<span ng-transclude></span>)'
|
|
346
|
+
* };
|
|
347
|
+
* });
|
|
348
|
+
*
|
|
349
|
+
*
|
|
350
|
+
* @Component({
|
|
351
|
+
* selector: 'ng2',
|
|
352
|
+
* inputs: ['name'],
|
|
353
|
+
* template: 'ng2[<ng1 [title]="name">transclude</ng1>](<ng-content></ng-content>)'
|
|
354
|
+
* })
|
|
355
|
+
* class Ng2 {
|
|
356
|
+
* }
|
|
357
|
+
*
|
|
358
|
+
* @NgModule({
|
|
359
|
+
* declarations: [Ng2, adapter.upgradeNg1Component('ng1')],
|
|
360
|
+
* imports: [BrowserModule]
|
|
361
|
+
* })
|
|
362
|
+
* class MyNg2Module {}
|
|
363
|
+
*
|
|
364
|
+
* document.body.innerHTML = '<ng2 name="World">project</ng2>';
|
|
365
|
+
*
|
|
366
|
+
* adapter.bootstrap(document.body, ['myExample']).ready(function() {
|
|
367
|
+
* expect(document.body.textContent).toEqual(
|
|
368
|
+
* "ng2[ng1[Hello World!](transclude)](project)");
|
|
369
|
+
* });
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
bootstrap(element, modules, config) {
|
|
373
|
+
this.declareNg1Module(modules);
|
|
374
|
+
const upgrade = new UpgradeAdapterRef();
|
|
375
|
+
// Make sure resumeBootstrap() only exists if the current bootstrap is deferred
|
|
376
|
+
const windowAngular = window /** TODO #???? */['angular'];
|
|
377
|
+
windowAngular.resumeBootstrap = undefined;
|
|
378
|
+
this.ngZone.run(() => {
|
|
379
|
+
bootstrap(element, [this.ng1Module.name], config);
|
|
380
|
+
});
|
|
381
|
+
const ng1BootstrapPromise = new Promise((resolve) => {
|
|
382
|
+
if (windowAngular.resumeBootstrap) {
|
|
383
|
+
const originalResumeBootstrap = windowAngular.resumeBootstrap;
|
|
384
|
+
windowAngular.resumeBootstrap = function () {
|
|
385
|
+
windowAngular.resumeBootstrap = originalResumeBootstrap;
|
|
386
|
+
const r = windowAngular.resumeBootstrap.apply(this, arguments);
|
|
387
|
+
resolve();
|
|
388
|
+
return r;
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
resolve();
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
Promise.all([this.ng2BootstrapDeferred.promise, ng1BootstrapPromise]).then(([ng1Injector]) => {
|
|
396
|
+
angularElement(element).data(controllerKey(INJECTOR_KEY), this.moduleRef.injector);
|
|
397
|
+
this.moduleRef.injector.get(NgZone).run(() => {
|
|
398
|
+
upgrade._bootstrapDone(this.moduleRef, ng1Injector);
|
|
399
|
+
});
|
|
400
|
+
}, onError);
|
|
401
|
+
return upgrade;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Allows AngularJS service to be accessible from Angular.
|
|
405
|
+
*
|
|
406
|
+
* @usageNotes
|
|
407
|
+
* ### Example
|
|
408
|
+
*
|
|
409
|
+
* ```
|
|
410
|
+
* class Login { ... }
|
|
411
|
+
* class Server { ... }
|
|
412
|
+
*
|
|
413
|
+
* @Injectable()
|
|
414
|
+
* class Example {
|
|
415
|
+
* constructor(@Inject('server') server, login: Login) {
|
|
416
|
+
* ...
|
|
417
|
+
* }
|
|
418
|
+
* }
|
|
419
|
+
*
|
|
420
|
+
* const module = angular.module('myExample', []);
|
|
421
|
+
* module.service('server', Server);
|
|
422
|
+
* module.service('login', Login);
|
|
423
|
+
*
|
|
424
|
+
* const adapter = new UpgradeAdapter(MyNg2Module);
|
|
425
|
+
* adapter.upgradeNg1Provider('server');
|
|
426
|
+
* adapter.upgradeNg1Provider('login', {asToken: Login});
|
|
427
|
+
*
|
|
428
|
+
* adapter.bootstrap(document.body, ['myExample']).ready((ref) => {
|
|
429
|
+
* const example: Example = ref.ng2Injector.get(Example);
|
|
430
|
+
* });
|
|
431
|
+
*
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
upgradeNg1Provider(name, options) {
|
|
435
|
+
const token = options && options.asToken || name;
|
|
436
|
+
this.upgradedProviders.push({
|
|
437
|
+
provide: token,
|
|
438
|
+
useFactory: ($injector) => $injector.get(name),
|
|
439
|
+
deps: [$INJECTOR]
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Allows Angular service to be accessible from AngularJS.
|
|
444
|
+
*
|
|
445
|
+
* @usageNotes
|
|
446
|
+
* ### Example
|
|
447
|
+
*
|
|
448
|
+
* ```
|
|
449
|
+
* class Example {
|
|
450
|
+
* }
|
|
451
|
+
*
|
|
452
|
+
* const adapter = new UpgradeAdapter(MyNg2Module);
|
|
453
|
+
*
|
|
454
|
+
* const module = angular.module('myExample', []);
|
|
455
|
+
* module.factory('example', adapter.downgradeNg2Provider(Example));
|
|
456
|
+
*
|
|
457
|
+
* adapter.bootstrap(document.body, ['myExample']).ready((ref) => {
|
|
458
|
+
* const example: Example = ref.ng1Injector.get('example');
|
|
459
|
+
* });
|
|
460
|
+
*
|
|
461
|
+
* ```
|
|
462
|
+
*/
|
|
463
|
+
downgradeNg2Provider(token) {
|
|
464
|
+
return downgradeInjectable(token);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Declare the AngularJS upgrade module for this adapter without bootstrapping the whole
|
|
468
|
+
* hybrid application.
|
|
469
|
+
*
|
|
470
|
+
* This method is automatically called by `bootstrap()` and `registerForNg1Tests()`.
|
|
471
|
+
*
|
|
472
|
+
* @param modules The AngularJS modules that this upgrade module should depend upon.
|
|
473
|
+
* @returns The AngularJS upgrade module that is declared by this method
|
|
474
|
+
*
|
|
475
|
+
* @usageNotes
|
|
476
|
+
* ### Example
|
|
477
|
+
*
|
|
478
|
+
* ```
|
|
479
|
+
* const upgradeAdapter = new UpgradeAdapter(MyNg2Module);
|
|
480
|
+
* upgradeAdapter.declareNg1Module(['heroApp']);
|
|
481
|
+
* ```
|
|
482
|
+
*/
|
|
483
|
+
declareNg1Module(modules = []) {
|
|
484
|
+
const delayApplyExps = [];
|
|
485
|
+
let original$applyFn;
|
|
486
|
+
let rootScopePrototype;
|
|
487
|
+
const upgradeAdapter = this;
|
|
488
|
+
const ng1Module = this.ng1Module = angularModule(this.idPrefix, modules);
|
|
489
|
+
const platformRef = platformBrowserDynamic();
|
|
490
|
+
this.ngZone = new NgZone({ enableLongStackTrace: Zone.hasOwnProperty('longStackTraceZoneSpec') });
|
|
491
|
+
this.ng2BootstrapDeferred = new Deferred();
|
|
492
|
+
ng1Module.constant(UPGRADE_APP_TYPE_KEY, 1 /* Dynamic */)
|
|
493
|
+
.factory(INJECTOR_KEY, () => this.moduleRef.injector.get(Injector))
|
|
494
|
+
.factory(LAZY_MODULE_REF, [INJECTOR_KEY, (injector) => ({ injector })])
|
|
495
|
+
.constant(NG_ZONE_KEY, this.ngZone)
|
|
496
|
+
.factory(COMPILER_KEY, () => this.moduleRef.injector.get(Compiler))
|
|
497
|
+
.config([
|
|
498
|
+
'$provide', '$injector',
|
|
499
|
+
(provide, ng1Injector) => {
|
|
500
|
+
provide.decorator($ROOT_SCOPE, [
|
|
501
|
+
'$delegate',
|
|
502
|
+
function (rootScopeDelegate) {
|
|
503
|
+
// Capture the root apply so that we can delay first call to $apply until we
|
|
504
|
+
// bootstrap Angular and then we replay and restore the $apply.
|
|
505
|
+
rootScopePrototype = rootScopeDelegate.constructor.prototype;
|
|
506
|
+
if (rootScopePrototype.hasOwnProperty('$apply')) {
|
|
507
|
+
original$applyFn = rootScopePrototype.$apply;
|
|
508
|
+
rootScopePrototype.$apply = (exp) => delayApplyExps.push(exp);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
throw new Error('Failed to find \'$apply\' on \'$rootScope\'!');
|
|
512
|
+
}
|
|
513
|
+
return rootScopeDelegate;
|
|
514
|
+
}
|
|
515
|
+
]);
|
|
516
|
+
if (ng1Injector.has($$TESTABILITY)) {
|
|
517
|
+
provide.decorator($$TESTABILITY, [
|
|
518
|
+
'$delegate',
|
|
519
|
+
function (testabilityDelegate) {
|
|
520
|
+
const originalWhenStable = testabilityDelegate.whenStable;
|
|
521
|
+
// Cannot use arrow function below because we need the context
|
|
522
|
+
const newWhenStable = function (callback) {
|
|
523
|
+
originalWhenStable.call(this, function () {
|
|
524
|
+
const ng2Testability = upgradeAdapter.moduleRef.injector.get(Testability);
|
|
525
|
+
if (ng2Testability.isStable()) {
|
|
526
|
+
callback.apply(this, arguments);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
ng2Testability.whenStable(newWhenStable.bind(this, callback));
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
testabilityDelegate.whenStable = newWhenStable;
|
|
534
|
+
return testabilityDelegate;
|
|
535
|
+
}
|
|
536
|
+
]);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
]);
|
|
540
|
+
ng1Module.run([
|
|
541
|
+
'$injector', '$rootScope',
|
|
542
|
+
(ng1Injector, rootScope) => {
|
|
543
|
+
UpgradeNg1ComponentAdapterBuilder.resolve(this.ng1ComponentsToBeUpgraded, ng1Injector)
|
|
544
|
+
.then(() => {
|
|
545
|
+
// Note: There is a bug in TS 2.4 that prevents us from
|
|
546
|
+
// inlining this into @NgModule
|
|
547
|
+
// TODO(tbosch): find or file a bug against TypeScript for this.
|
|
548
|
+
const ngModule = {
|
|
549
|
+
providers: [
|
|
550
|
+
{ provide: $INJECTOR, useFactory: () => ng1Injector },
|
|
551
|
+
{ provide: $COMPILE, useFactory: () => ng1Injector.get($COMPILE) },
|
|
552
|
+
this.upgradedProviders
|
|
553
|
+
],
|
|
554
|
+
imports: [resolveForwardRef(this.ng2AppModule)],
|
|
555
|
+
entryComponents: this.downgradedComponents
|
|
556
|
+
};
|
|
557
|
+
// At this point we have ng1 injector and we have prepared
|
|
558
|
+
// ng1 components to be upgraded, we now can bootstrap ng2.
|
|
559
|
+
let DynamicNgUpgradeModule = class DynamicNgUpgradeModule {
|
|
560
|
+
constructor() { }
|
|
561
|
+
ngDoBootstrap() { }
|
|
562
|
+
};
|
|
563
|
+
DynamicNgUpgradeModule = __decorate([
|
|
564
|
+
NgModule({ jit: true, ...ngModule }),
|
|
565
|
+
__metadata("design:paramtypes", [])
|
|
566
|
+
], DynamicNgUpgradeModule);
|
|
567
|
+
platformRef
|
|
568
|
+
.bootstrapModule(DynamicNgUpgradeModule, [this.compilerOptions, { ngZone: this.ngZone }])
|
|
569
|
+
.then((ref) => {
|
|
570
|
+
this.moduleRef = ref;
|
|
571
|
+
this.ngZone.run(() => {
|
|
572
|
+
if (rootScopePrototype) {
|
|
573
|
+
rootScopePrototype.$apply = original$applyFn; // restore original $apply
|
|
574
|
+
while (delayApplyExps.length) {
|
|
575
|
+
rootScope.$apply(delayApplyExps.shift());
|
|
576
|
+
}
|
|
577
|
+
rootScopePrototype = null;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
})
|
|
581
|
+
.then(() => this.ng2BootstrapDeferred.resolve(ng1Injector), onError)
|
|
582
|
+
.then(() => {
|
|
583
|
+
let subscription = this.ngZone.onMicrotaskEmpty.subscribe({
|
|
584
|
+
next: () => {
|
|
585
|
+
if (rootScope.$$phase) {
|
|
586
|
+
if (isDevMode()) {
|
|
587
|
+
console.warn('A digest was triggered while one was already in progress. This may mean that something is triggering digests outside the Angular zone.');
|
|
588
|
+
}
|
|
589
|
+
return rootScope.$evalAsync(() => { });
|
|
590
|
+
}
|
|
591
|
+
return rootScope.$digest();
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
rootScope.$on('$destroy', () => {
|
|
595
|
+
subscription.unsubscribe();
|
|
596
|
+
});
|
|
597
|
+
// Destroy the AngularJS app once the Angular `PlatformRef` is destroyed.
|
|
598
|
+
// This does not happen in a typical SPA scenario, but it might be useful for
|
|
599
|
+
// other use-cases where disposing of an Angular/AngularJS app is necessary
|
|
600
|
+
// (such as Hot Module Replacement (HMR)).
|
|
601
|
+
// See https://github.com/angular/angular/issues/39935.
|
|
602
|
+
platformRef.onDestroy(() => destroyApp(ng1Injector));
|
|
603
|
+
});
|
|
604
|
+
})
|
|
605
|
+
.catch((e) => this.ng2BootstrapDeferred.reject(e));
|
|
606
|
+
}
|
|
607
|
+
]);
|
|
608
|
+
return ng1Module;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Synchronous promise-like object to wrap parent injectors,
|
|
613
|
+
* to preserve the synchronous nature of AngularJS's $compile.
|
|
614
|
+
*/
|
|
615
|
+
class ParentInjectorPromise {
|
|
616
|
+
constructor(element) {
|
|
617
|
+
this.element = element;
|
|
618
|
+
this.callbacks = [];
|
|
619
|
+
// store the promise on the element
|
|
620
|
+
element.data(controllerKey(INJECTOR_KEY), this);
|
|
621
|
+
}
|
|
622
|
+
then(callback) {
|
|
623
|
+
if (this.injector) {
|
|
624
|
+
callback(this.injector);
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
this.callbacks.push(callback);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
resolve(injector) {
|
|
631
|
+
this.injector = injector;
|
|
632
|
+
// reset the element data to point to the real injector
|
|
633
|
+
this.element.data(controllerKey(INJECTOR_KEY), injector);
|
|
634
|
+
// clean out the element to prevent memory leaks
|
|
635
|
+
this.element = null;
|
|
636
|
+
// run all the queued callbacks
|
|
637
|
+
this.callbacks.forEach((callback) => callback(injector));
|
|
638
|
+
this.callbacks.length = 0;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Use `UpgradeAdapterRef` to control a hybrid AngularJS / Angular application.
|
|
643
|
+
*
|
|
644
|
+
* @deprecated Deprecated since v5. Use `upgrade/static` instead, which also supports
|
|
645
|
+
* [Ahead-of-Time compilation](guide/aot-compiler).
|
|
646
|
+
* @publicApi
|
|
647
|
+
*/
|
|
648
|
+
export class UpgradeAdapterRef {
|
|
649
|
+
constructor() {
|
|
650
|
+
/* @internal */
|
|
651
|
+
this._readyFn = null;
|
|
652
|
+
this.ng1RootScope = null;
|
|
653
|
+
this.ng1Injector = null;
|
|
654
|
+
this.ng2ModuleRef = null;
|
|
655
|
+
this.ng2Injector = null;
|
|
656
|
+
}
|
|
657
|
+
/* @internal */
|
|
658
|
+
_bootstrapDone(ngModuleRef, ng1Injector) {
|
|
659
|
+
this.ng2ModuleRef = ngModuleRef;
|
|
660
|
+
this.ng2Injector = ngModuleRef.injector;
|
|
661
|
+
this.ng1Injector = ng1Injector;
|
|
662
|
+
this.ng1RootScope = ng1Injector.get($ROOT_SCOPE);
|
|
663
|
+
this._readyFn && this._readyFn(this);
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Register a callback function which is notified upon successful hybrid AngularJS / Angular
|
|
667
|
+
* application has been bootstrapped.
|
|
668
|
+
*
|
|
669
|
+
* The `ready` callback function is invoked inside the Angular zone, therefore it does not
|
|
670
|
+
* require a call to `$apply()`.
|
|
671
|
+
*/
|
|
672
|
+
ready(fn) {
|
|
673
|
+
this._readyFn = fn;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Dispose of running hybrid AngularJS / Angular application.
|
|
677
|
+
*/
|
|
678
|
+
dispose() {
|
|
679
|
+
this.ng1Injector.get($ROOT_SCOPE).$destroy();
|
|
680
|
+
this.ng2ModuleRef.destroy();
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBncmFkZV9hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvdXBncmFkZS9zcmMvZHluYW1pYy9zcmMvdXBncmFkZV9hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRzs7QUFFSCxPQUFPLEVBQUMsUUFBUSxFQUFtQixRQUFRLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBZSxNQUFNLEVBQUUsaUJBQWlCLEVBQWtCLFdBQVcsRUFBTyxNQUFNLGVBQWUsQ0FBQztBQUNsSyxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUV6RSxPQUFPLEVBQUMsU0FBUyxFQUFFLE9BQU8sSUFBSSxjQUFjLEVBQWlJLE9BQU8sSUFBSSxhQUFhLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUN4TyxPQUFPLEVBQUMsYUFBYSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLFdBQVcsRUFBRSxvQkFBb0IsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQzNLLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLHNDQUFzQyxDQUFDO0FBQ3hFLE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLHVDQUF1QyxDQUFDO0FBQzFFLE9BQU8sRUFBQyxhQUFhLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBaUIsT0FBTyxFQUFpQixNQUFNLHVCQUF1QixDQUFDO0FBRWxILE9BQU8sRUFBQyxpQ0FBaUMsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBRXhFLElBQUksWUFBWSxHQUFXLENBQUMsQ0FBQztBQUU3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUZHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFx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O1FBQ3hDLGdCQUFXLEdBQXFCLElBQUssQ0FBQztRQUN0QyxpQkFBWSxHQUFxQixJQUFLLENBQUM7UUFDdkMsZ0JBQVcsR0FBYSxJQUFLLENBQUM7SUE2QnZDLENBQUM7SUEzQkMsZUFBZTtJQUNQLGNBQWMsQ0FBQyxXQUE2QixFQUFFLFdBQTZCO1FBQ2pGLElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDLFFBQVEsQ0FBQztRQUN4QyxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUMvQixJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxLQUFLLENBQUMsRUFBa0Q7UUFDN0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksT0FBTztRQUNaLElBQUksQ0FBQyxXQUFZLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzlDLElBQUksQ0FBQyxZQUFhLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDL0IsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7Q29tcGlsZXIsIENvbXBpbGVyT3B0aW9ucywgSW5qZWN0b3IsIGlzRGV2TW9kZSwgTmdNb2R1bGUsIE5nTW9kdWxlUmVmLCBOZ1pvbmUsIHJlc29sdmVGb3J3YXJkUmVmLCBTdGF0aWNQcm92aWRlciwgVGVzdGFiaWxpdHksIFR5cGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtwbGF0Zm9ybUJyb3dzZXJEeW5hbWljfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyLWR5bmFtaWMnO1xuXG5pbXBvcnQge2Jvb3RzdHJhcCwgZWxlbWVudCBhcyBhbmd1bGFyRWxlbWVudCwgSUFuZ3VsYXJCb290c3RyYXBDb25maWcsIElBdWdtZW50ZWRKUXVlcnksIElJbmplY3RvclNlcnZpY2UsIElNb2R1bGUsIElQcm92aWRlU2VydmljZSwgSVJvb3RTY29wZVNlcnZpY2UsIElUZXN0YWJpbGl0eVNlcnZpY2UsIG1vZHVsZV8gYXMgYW5ndWxhck1vZHVsZX0gZnJvbSAnLi4vLi4vY29tbW9uL3NyYy9hbmd1bGFyMSc7XG5pbXBvcnQgeyQkVEVTVEFCSUxJVFksICRDT01QSUxFLCAkSU5KRUNUT1IsICRST09UX1NDT1BFLCBDT01QSUxFUl9LRVksIElOSkVDVE9SX0tFWSwgTEFaWV9NT0RVTEVfUkVGLCBOR19aT05FX0tFWSwgVVBHUkFERV9BUFBfVFlQRV9LRVl9IGZyb20gJy4uLy4uL2NvbW1vbi9zcmMvY29uc3RhbnRzJztcbmltcG9ydCB7ZG93bmdyYWRlQ29tcG9uZW50fSBmcm9tICcuLi8uLi9jb21tb24vc3JjL2Rvd25ncmFkZV9jb21wb25lbnQnO1xuaW1wb3J0IHtkb3duZ3JhZGVJbmplY3RhYmxlfSBmcm9tICcuLi8uLi9jb21tb24vc3JjL2Rvd25ncmFkZV9pbmplY3RhYmxlJztcbmltcG9ydCB7Y29udHJvbGxlcktleSwgRGVmZXJyZWQsIGRlc3Ryb3lBcHAsIExhenlNb2R1bGVSZWYsIG9uRXJyb3IsIFVwZ3JhZGVBcHBUeXBlfSBmcm9tICcuLi8uLi9jb21tb24vc3JjL3V0aWwnO1xuXG5pbXBvcnQge1VwZ3JhZGVOZzFDb21wb25lbnRBZGFwdGVyQnVpbGRlcn0gZnJvbSAnLi91cGdyYWRlX25nMV9hZGFwdGVyJztcblxubGV0IHVwZ3JhZGVDb3VudDogbnVtYmVyID0gMDtcblxuLyoqXG4gKiBVc2UgYFVwZ3JhZGVBZGFwdGVyYCB0byBhbGxvdyBBbmd1bGFySlMgYW5kIEFuZ3VsYXIgdG8gY29leGlzdCBpbiBhIHNpbmdsZSBhcHBsaWNhdGlvbi5cbiAqXG4gKiBUaGUgYFVwZ3JhZGVBZGFwdGVyYCBhbGxvd3M6XG4gKiAxLiBjcmVhdGlvbiBvZiBBbmd1bGFyIGNvbXBvbmVudCBmcm9tIEFuZ3VsYXJKUyBjb21wb25lbnQgZGlyZWN0aXZlXG4gKiAgICAoU2VlIFtVcGdyYWRlQWRhcHRlciN1cGdyYWRlTmcxQ29tcG9uZW50KCldKVxuICogMi4gY3JlYXRpb24gb2YgQW5ndWxhckpTIGRpcmVjdGl2ZSBmcm9tIEFuZ3VsYXIgY29tcG9uZW50LlxuICogICAgKFNlZSBbVXBncmFkZUFkYXB0ZXIjZG93bmdyYWRlTmcyQ29tcG9uZW50KCldKVxuICogMy4gQm9vdHN0cmFwcGluZyBvZiBhIGh5YnJpZCBBbmd1bGFyIGFwcGxpY2F0aW9uIHdoaWNoIGNvbnRhaW5zIGJvdGggb2YgdGhlIGZyYW1ld29ya3NcbiAqICAgIGNvZXhpc3RpbmcgaW4gYSBzaW5nbGUgYXBwbGljYXRpb24uXG4gKlxuICogQHVzYWdlTm90ZXNcbiAqICMjIyBNZW50YWwgTW9kZWxcbiAqXG4gKiBXaGVuIHJlYXNvbmluZyBhYm91dCBob3cgYSBoeWJyaWQgYXBwbGljYXRpb24gd29ya3MgaXQgaXMgdXNlZnVsIHRvIGhhdmUgYSBtZW50YWwgbW9kZWwgd2hpY2hcbiAqIGRlc2NyaWJlcyB3aGF0IGlzIGhhcHBlbmluZyBhbmQgZXhwbGFpbnMgd2hhdCBpcyBoYXBwZW5pbmcgYXQgdGhlIGxvd2VzdCBsZXZlbC5cbiAqXG4gKiAxLiBUaGVyZSBhcmUgdHdvIGluZGVwZW5kZW50IGZyYW1ld29ya3MgcnVubmluZyBpbiBhIHNpbmdsZSBhcHBsaWNhdGlvbiwgZWFjaCBmcmFtZXdvcmsgdHJlYXRzXG4gKiAgICB0aGUgb3RoZXIgYXMgYSBibGFjayBib3guXG4gKiAyLiBFYWNoIERPTSBlbGVtZW50IG9uIHRoZSBwYWdlIGlzIG93bmVkIGV4YWN0bHkgYnkgb25lIGZyYW1ld29yay4gV2hpY2hldmVyIGZyYW1ld29ya1xuICogICAgaW5zdGFudGlhdGVkIHRoZSBlbGVtZW50IGlzIHRoZSBvd25lci4gRWFjaCBmcmFtZXdvcmsgb25seSB1cGRhdGVzL2ludGVyYWN0cyB3aXRoIGl0cyBvd25cbiAqICAgIERPTSBlbGVtZW50cyBhbmQgaWdub3JlcyBvdGhlcnMuXG4gKiAzLiBBbmd1bGFySlMgZGlyZWN0aXZlcyBhbHdheXMgZXhlY3V0ZSBpbnNpZGUgQW5ndWxhckpTIGZyYW1ld29yayBjb2RlYmFzZSByZWdhcmRsZXNzIG9mXG4gKiAgICB3aGVyZSB0aGV5IGFyZSBpbnN0YW50aWF0ZWQuXG4gKiA0LiBBbmd1bGFyIGNvbXBvbmVudHMgYWx3YXlzIGV4ZWN1dGUgaW5zaWRlIEFuZ3VsYXIgZnJhbWV3b3JrIGNvZGViYXNlIHJlZ2FyZGxlc3Mgb2ZcbiAqICAgIHdoZXJlIHRoZXkgYXJlIGluc3RhbnRpYXRlZC5cbiAqIDUuIEFuIEFuZ3VsYXJKUyBjb21wb25lbnQgY2FuIGJlIHVwZ3JhZGVkIHRvIGFuIEFuZ3VsYXIgY29tcG9uZW50LiBUaGlzIGNyZWF0ZXMgYW5cbiAqICAgIEFuZ3VsYXIgZGlyZWN0aXZlLCB3aGljaCBib290c3RyYXBzIHRoZSBBbmd1bGFySlMgY29tcG9uZW50IGRpcmVjdGl2ZSBpbiB0aGF0IGxvY2F0aW9uLlxuICogNi4gQW4gQW5ndWxhciBjb21wb25lbnQgY2FuIGJlIGRvd25ncmFkZWQgdG8gYW4gQW5ndWxhckpTIGNvbXBvbmVudCBkaXJlY3RpdmUuIFRoaXMgY3JlYXRlc1xuICogICAgYW4gQW5ndWxhckpTIGRpcmVjdGl2ZSwgd2hpY2ggYm9vdHN0cmFwcyB0aGUgQW5ndWxhciBjb21wb25lbnQgaW4gdGhhdCBsb2NhdGlvbi5cbiAqIDcuIFdoZW5ldmVyIGFuIGFkYXB0ZXIgY29tcG9uZW50IGlzIGluc3RhbnRpYXRlZCB0aGUgaG9zdCBlbGVtZW50IGlzIG93bmVkIGJ5IHRoZSBmcmFtZXdvcmtcbiAqICAgIGRvaW5nIHRoZSBpbnN0YW50aWF0aW9uLiBUaGUgb3RoZXIgZnJhbWV3b3JrIHRoZW4gaW5zdGFudGlhdGVzIGFuZCBvd25zIHRoZSB2aWV3IGZvciB0aGF0XG4gKiAgICBjb21wb25lbnQuIFRoaXMgaW1wbGllcyB0aGF0IGNvbXBvbmVudCBiaW5kaW5ncyB3aWxsIGFsd2F5cyBmb2xsb3cgdGhlIHNlbWFudGljcyBvZiB0aGVcbiAqICAgIGluc3RhbnRpYXRpb24gZnJhbWV3b3JrLiBUaGUgc3ludGF4IGlzIGFsd2F5cyB0aGF0IG9mIEFuZ3VsYXIgc3ludGF4LlxuICogOC4gQW5ndWxhckpTIGlzIGFsd2F5cyBib290c3RyYXBwZWQgZmlyc3QgYW5kIG93bnMgdGhlIGJvdHRvbSBtb3N0IHZpZXcuXG4gKiA5LiBUaGUgbmV3IGFwcGxpY2F0aW9uIGlzIHJ1bm5pbmcgaW4gQW5ndWxhciB6b25lLCBhbmQgdGhlcmVmb3JlIGl0IG5vIGxvbmdlciBuZWVkcyBjYWxscyB0b1xuICogICAgYCRhcHBseSgpYC5cbiAqXG4gKiAjIyMgRXhhbXBsZVxuICpcbiAqIGBgYFxuICogY29uc3QgYWRhcHRlciA9IG5ldyBVcGdyYWRlQWRhcHRlcihmb3J3YXJkUmVmKCgpID0+IE15TmcyTW9kdWxlKSwgbXlDb21waWxlck9wdGlvbnMpO1xuICogY29uc3QgbW9kdWxlID0gYW5ndWxhci5tb2R1bGUoJ215RXhhbXBsZScsIFtdKTtcbiAqIG1vZHVsZS5kaXJlY3RpdmUoJ25nMkNvbXAnLCBhZGFwdGVyLmRvd25ncmFkZU5nMkNvbXBvbmVudChOZzJDb21wb25lbnQpKTtcbiAqXG4gKiBtb2R1bGUuZGlyZWN0aXZlKCduZzFIZWxsbycsIGZ1bmN0aW9uKCkge1xuICogICByZXR1cm4ge1xuICogICAgICBzY29wZTogeyB0aXRsZTogJz0nIH0sXG4gKiAgICAgIHRlbXBsYXRlOiAnbmcxW0hlbGxvIHt7dGl0bGV9fSFdKDxzcGFuIG5nLXRyYW5zY2x1ZGU+PC9zcGFuPiknXG4gKiAgIH07XG4gKiB9KTtcbiAqXG4gKlxuICogQENvbXBvbmVudCh7XG4gKiAgIHNlbGVjdG9yOiAnbmcyLWNvbXAnLFxuICogICBpbnB1dHM6IFsnbmFtZSddLFxuICogICB0ZW1wbGF0ZTogJ25nMls8bmcxLWhlbGxvIFt0aXRsZV09XCJuYW1lXCI+dHJhbnNjbHVkZTwvbmcxLWhlbGxvPl0oPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PiknLFxuICogICBkaXJlY3RpdmVzOlxuICogfSlcbiAqIGNsYXNzIE5nMkNvbXBvbmVudCB7XG4gKiB9XG4gKlxuICogQE5nTW9kdWxlKHtcbiAqICAgZGVjbGFyYXRpb25zOiBbTmcyQ29tcG9uZW50LCBhZGFwdGVyLnVwZ3JhZGVOZzFDb21wb25lbnQoJ25nMUhlbGxvJyldLFxuICogICBpbXBvcnRzOiBbQnJvd3Nlck1vZHVsZV1cbiAqIH0pXG4gKiBjbGFzcyBNeU5nMk1vZHVsZSB7fVxuICpcbiAqXG4gKiBkb2N1bWVudC5ib2R5LmlubmVySFRNTCA9ICc8bmcyLWNvbXAgbmFtZT1cIldvcmxkXCI+cHJvamVjdDwvbmcyLWNvbXA+JztcbiAqXG4gKiBhZGFwdGVyLmJvb3RzdHJhcChkb2N1bWVudC5ib2R5LCBbJ215RXhhbXBsZSddKS5yZWFkeShmdW5jdGlvbigpIHtcbiAqICAgZXhwZWN0KGRvY3VtZW50LmJvZHkudGV4dENvbnRlbnQpLnRvRXF1YWwoXG4gKiAgICAgICBcIm5nMltuZzFbSGVsbG8gV29ybGQhXSh0cmFuc2NsdWRlKV0ocHJvamVjdClcIik7XG4gKiB9KTtcbiAqXG4gKiBgYGBcbiAqXG4gKiBAZGVwcmVjYXRlZCBEZXByZWNhdGVkIHNpbmNlIHY1LiBVc2UgYHVwZ3JhZGUvc3RhdGljYCBpbnN0ZWFkLCB3aGljaCBhbHNvIHN1cHBvcnRzXG4gKiBbQWhlYWQtb2YtVGltZSBjb21waWxhdGlvbl0oZ3VpZGUvYW90LWNvbXBpbGVyKS5cbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGNsYXNzIFVwZ3JhZGVBZGFwdGVyIHtcbiAgcHJpdmF0ZSBpZFByZWZpeDogc3RyaW5nID0gYE5HMl9VUEdSQURFXyR7dXBncmFkZUNvdW50Kyt9X2A7XG4gIHByaXZhdGUgZG93bmdyYWRlZENvbXBvbmVudHM6IFR5cGU8YW55PltdID0gW107XG4gIC8qKlxuICAgKiBBbiBpbnRlcm5hbCBtYXAgb2YgbmcxIGNvbXBvbmVudHMgd2hpY2ggbmVlZCB0byB1cCB1cGdyYWRlZCB0byBuZzIuXG4gICAqXG4gICAqIFdlIGNhbid0IHVwZ3JhZGUgdW50aWwgaW5qZWN0b3IgaXMgaW5zdGFudGlhdGVkIGFuZCB3ZSBjYW4gcmV0cmlldmUgdGhlIGNvbXBvbmVudCBtZXRhZGF0YS5cbiAgICogRm9yIHRoaXMgcmVhc29uIHdlIGtlZXAgYSBsaXN0IG9mIGNvbXBvbmVudHMgdG8gdXBncmFkZSB1bnRpbCBuZzEgaW5qZWN0b3IgaXMgYm9vdHN0cmFwcGVkLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgbmcxQ29tcG9uZW50c1RvQmVVcGdyYWRlZDoge1tuYW1lOiBzdHJpbmddOiBVcGdyYWRlTmcxQ29tcG9uZW50QWRhcHRlckJ1aWxkZXJ9ID0ge307XG4gIHByaXZhdGUgdXBncmFkZWRQcm92aWRlcnM6IFN0YXRpY1Byb3ZpZGVyW10gPSBbXTtcbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIHByaXZhdGUgbmdab25lITogTmdab25lO1xuICAvLyBUT0RPKGlzc3VlLzI0NTcxKTogcmVtb3ZlICchJy5cbiAgcHJpdmF0ZSBuZzFNb2R1bGUhOiBJTW9kdWxlO1xuICBwcml2YXRlIG1vZHVsZVJlZjogTmdNb2R1bGVSZWY8YW55PnxudWxsID0gbnVsbDtcbiAgLy8gVE9ETyhpc3N1ZS8yNDU3MSk6IHJlbW92ZSAnIScuXG4gIHByaXZhdGUgbmcyQm9vdHN0cmFwRGVmZXJyZWQhOiBEZWZlcnJlZDxJSW5qZWN0b3JTZXJ2aWNlPjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5nMkFwcE1vZHVsZTogVHlwZTxhbnk+LCBwcml2YXRlIGNvbXBpbGVyT3B0aW9ucz86IENvbXBpbGVyT3B0aW9ucykge1xuICAgIGlmICghbmcyQXBwTW9kdWxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ1VwZ3JhZGVBZGFwdGVyIGNhbm5vdCBiZSBpbnN0YW50aWF0ZWQgd2l0aG91dCBhbiBOZ01vZHVsZSBvZiB0aGUgQW5ndWxhciBhcHAuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93cyBBbmd1bGFyIENvbXBvbmVudCB0byBiZSB1c2VkIGZyb20gQW5ndWxhckpTLlxuICAgKlxuICAgKiBVc2UgYGRvd25ncmFkZU5nMkNvbXBvbmVudGAgdG8gY3JlYXRlIGFuIEFuZ3VsYXJKUyBEaXJlY3RpdmUgRGVmaW5pdGlvbiBGYWN0b3J5IGZyb21cbiAgICogQW5ndWxhciBDb21wb25lbnQuIFRoZSBhZGFwdGVyIHdpbGwgYm9vdHN0cmFwIEFuZ3VsYXIgY29tcG9uZW50IGZyb20gd2l0aGluIHRoZVxuICAgKiBBbmd1bGFySlMgdGVtcGxhdGUuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqICMjIyBNZW50YWwgTW9kZWxcbiAgICpcbiAgICogMS4gVGhlIGNvbXBvbmVudCBpcyBpbnN0YW50aWF0ZWQgYnkgYmVpbmcgbGlzdGVkIGluIEFuZ3VsYXJKUyB0ZW1wbGF0ZS4gVGhpcyBtZWFucyB0aGF0IHRoZVxuICAgKiAgICBob3N0IGVsZW1lbnQgaXMgY29udHJvbGxlZCBieSBBbmd1bGFySlMsIGJ1dCB0aGUgY29tcG9uZW50J3MgdmlldyB3aWxsIGJlIGNvbnRyb2xsZWQgYnlcbiAgICogICAgQW5ndWxhci5cbiAgICogMi4gRXZlbiB0aG91Z2h0IHRoZSBjb21wb25lbnQgaXMgaW5zdGFudGlhdGVkIGluIEFuZ3VsYXJKUywgaXQgd2lsbCBiZSB1c2luZyBBbmd1bGFyXG4gICAqICAgIHN5bnRheC4gVGhpcyBoYXMgdG8gYmUgZG9uZSwgdGhpcyB3YXkgYmVjYXVzZSB3ZSBtdXN0IGZvbGxvdyBBbmd1bGFyIGNvbXBvbmVudHMgZG8gbm90XG4gICAqICAgIGRlY2xhcmUgaG93IHRoZSBhdHRyaWJ1dGVzIHNob3VsZCBiZSBpbnRlcnByZXRlZC5cbiAgICogMy4gYG5nLW1vZGVsYCBpcyBjb250cm9sbGVkIGJ5IEFuZ3VsYXJKUyBhbmQgY29tbXVuaWNhdGVzIHdpdGggdGhlIGRvd25ncmFkZWQgQW5ndWxhciBjb21wb25lbnRcbiAgICogICAgYnkgd2F5IG9mIHRoZSBgQ29udHJvbFZhbHVlQWNjZXNzb3JgIGludGVyZmFjZSBmcm9tIEBhbmd1bGFyL2Zvcm1zLiBPbmx5IGNvbXBvbmVudHMgdGhhdFxuICAgKiAgICBpbXBsZW1lbnQgdGhpcyBpbnRlcmZhY2UgYXJlIGVsaWdpYmxlLlxuICAgKlxuICAgKiAjIyMgU3VwcG9ydGVkIEZlYXR1cmVzXG4gICAqXG4gICAqIC0gQmluZGluZ3M6XG4gICAqICAgLSBBdHRyaWJ1dGU6IGA8Y29tcCBuYW1lPVwiV29ybGRcIj5gXG4gICAqICAgLSBJbnRlcnBvbGF0aW9uOiAgYDxjb21wIGdyZWV0aW5nPVwiSGVsbG8ge3tuYW1lfX0hXCI+YFxuICAgKiAgIC0gRXhwcmVzc2lvbjogIGA8Y29tcCBbbmFtZV09XCJ1c2VybmFtZVwiPmBcbiAgICogICAtIEV2ZW50OiAgYDxjb21wIChjbG9zZSk9XCJkb1NvbWV0aGluZygpXCI+YFxuICAgKiAgIC0gbmctbW9kZWw6IGA8Y29tcCBuZy1tb2RlbD1cIm5hbWVcIj5gXG4gICAqIC0gQ29udGVudCBwcm9qZWN0aW9uOiB5ZXNcbiAgICpcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBgXG4gICAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgVXBncmFkZUFkYXB0ZXIoZm9yd2FyZFJlZigoKSA9PiBNeU5nMk1vZHVsZSkpO1xuICAgKiBjb25zdCBtb2R1bGUgPSBhbmd1bGFyLm1vZHVsZSgnbXlFeGFtcGxlJywgW10pO1xuICAgKiBtb2R1bGUuZGlyZWN0aXZlKCdncmVldCcsIGFkYXB0ZXIuZG93bmdyYWRlTmcyQ29tcG9uZW50KEdyZWV0ZXIpKTtcbiAgICpcbiAgICogQENvbXBvbmVudCh7XG4gICAqICAgc2VsZWN0b3I6ICdncmVldCcsXG4gICAqICAgdGVtcGxhdGU6ICd7e3NhbHV0YXRpb259fSB7e25hbWV9fSEgLSA8bmctY29udGVudD48L25nLWNvbnRlbnQ+J1xuICAgKiB9KVxuICAgKiBjbGFzcyBHcmVldGVyIHtcbiAgICogICBASW5wdXQoKSBzYWx1dGF0aW9uOiBzdHJpbmc7XG4gICAqICAgQElucHV0KCkgbmFtZTogc3RyaW5nO1xuICAgKiB9XG4gICAqXG4gICAqIEBOZ01vZHVsZSh7XG4gICAqICAgZGVjbGFyYXRpb25zOiBbR3JlZXRlcl0sXG4gICAqICAgaW1wb3J0czogW0Jyb3dzZXJNb2R1bGVdXG4gICAqIH0pXG4gICAqIGNsYXNzIE15TmcyTW9kdWxlIHt9XG4gICAqXG4gICAqIGRvY3VtZW50LmJvZHkuaW5uZXJIVE1MID1cbiAgICogICAnbmcxIHRlbXBsYXRlOiA8Z3JlZXQgc2FsdXRhdGlvbj1cIkhlbGxvXCIgW25hbWVdPVwid29ybGRcIj50ZXh0PC9ncmVldD4nO1xuICAgKlxuICAgKiBhZGFwdGVyLmJvb3RzdHJhcChkb2N1bWVudC5ib2R5LCBbJ215RXhhbXBsZSddKS5yZWFkeShmdW5jdGlvbigpIHtcbiAgICogICBleHBlY3QoZG9jdW1lbnQuYm9keS50ZXh0Q29udGVudCkudG9FcXVhbChcIm5nMSB0ZW1wbGF0ZTogSGVsbG8gd29ybGQhIC0gdGV4dFwiKTtcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgZG93bmdyYWRlTmcyQ29tcG9uZW50KGNvbXBvbmVudDogVHlwZTxhbnk+KTogRnVuY3Rpb24ge1xuICAgIHRoaXMuZG93bmdyYWRlZENvbXBvbmVudHMucHVzaChjb21wb25lbnQpO1xuXG4gICAgcmV0dXJuIGRvd25ncmFkZUNvbXBvbmVudCh7Y29tcG9uZW50fSk7XG4gIH1cblxuICAvKipcbiAgICogQWxsb3dzIEFuZ3VsYXJKUyBDb21wb25lbnQgdG8gYmUgdXNlZCBmcm9tIEFuZ3VsYXIuXG4gICAqXG4gICAqIFVzZSBgdXBncmFkZU5nMUNvbXBvbmVudGAgdG8gY3JlYXRlIGFuIEFuZ3VsYXIgY29tcG9uZW50IGZyb20gQW5ndWxhckpTIENvbXBvbmVudFxuICAgKiBkaXJlY3RpdmUuIFRoZSBhZGFwdGVyIHdpbGwgYm9vdHN0cmFwIEFuZ3VsYXJKUyBjb21wb25lbnQgZnJvbSB3aXRoaW4gdGhlIEFuZ3VsYXJcbiAgICogdGVtcGxhdGUuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqICMjIyBNZW50YWwgTW9kZWxcbiAgICpcbiAgICogMS4gVGhlIGNvbXBvbmVudCBpcyBpbnN0YW50aWF0ZWQgYnkgYmVpbmcgbGlzdGVkIGluIEFuZ3VsYXIgdGVtcGxhdGUuIFRoaXMgbWVhbnMgdGhhdCB0aGVcbiAgICogICAgaG9zdCBlbGVtZW50IGlzIGNvbnRyb2xsZWQgYnkgQW5ndWxhciwgYnV0IHRoZSBjb21wb25lbnQncyB2aWV3IHdpbGwgYmUgY29udHJvbGxlZCBieVxuICAgKiAgICBBbmd1bGFySlMuXG4gICAqXG4gICAqICMjIyBTdXBwb3J0ZWQgRmVhdHVyZXNcbiAgICpcbiAgICogLSBCaW5kaW5nczpcbiAgICogICAtIEF0dHJpYnV0ZTogYDxjb21wIG5hbWU9XCJXb3JsZFwiPmBcbiAgICogICAtIEludGVycG9sYXRpb246ICBgPGNvbXAgZ3JlZXRpbmc9XCJIZWxsbyB7e25hbWV9fSFcIj5gXG4gICAqICAgLSBFeHByZXNzaW9uOiAgYDxjb21wIFtuYW1lXT1cInVzZXJuYW1lXCI+YFxuICAgKiAgIC0gRXZlbnQ6ICBgPGNvbXAgKGNsb3NlKT1cImRvU29tZXRoaW5nKClcIj5gXG4gICAqIC0gVHJhbnNjbHVzaW9uOiB5ZXNcbiAgICogLSBPbmx5IHNvbWUgb2YgdGhlIGZlYXR1cmVzIG9mXG4gICAqICAgW0RpcmVjdGl2ZSBEZWZpbml0aW9uIE9iamVjdF0oaHR0cHM6Ly9kb2NzLmFuZ3VsYXJqcy5vcmcvYXBpL25nL3NlcnZpY2UvJGNvbXBpbGUpIGFyZVxuICAgKiAgIHN1cHBvcnRlZDpcbiAgICogICAtIGBjb21waWxlYDogbm90IHN1cHBvcnRlZCBiZWNhdXNlIHRoZSBob3N0IGVsZW1lbnQgaXMgb3duZWQgYnkgQW5ndWxhciwgd2hpY2ggZG9lc1xuICAgKiAgICAgbm90IGFsbG93IG1vZGlmeWluZyBET00gc3RydWN0dXJlIGR1cmluZyBjb21waWxhdGlvbi5cbiAgICogICAtIGBjb250cm9sbGVyYDogc3VwcG9ydGVkLiAoTk9URTogaW5qZWN0aW9uIG9mIGAkYXR0cnNgIGFuZCBgJHRyYW5zY2x1ZGVgIGlzIG5vdCBzdXBwb3J0ZWQuKVxuICAgKiAgIC0gYGNvbnRyb2xsZXJBc2A6IHN1cHBvcnRlZC5cbiAgICogICAtIGBiaW5kVG9Db250cm9sbGVyYDogc3VwcG9ydGVkLlxuICAgKiAgIC0gYGxpbmtgOiBzdXBwb3J0ZWQuIChOT1RFOiBvbmx5IHByZS1saW5rIGZ1bmN0aW9uIGlzIHN1cHBvcnRlZC4pXG4gICAqICAgLSBgbmFtZWA6IHN1cHBvcnRlZC5cbiAgICogICAtIGBwcmlvcml0eWA6IGlnbm9yZWQuXG4gICAqICAgLSBgcmVwbGFjZWA6IG5vdCBzdXBwb3J0ZWQuXG4gICAqICAgLSBgcmVxdWlyZWA6IHN1cHBvcnRlZC5cbiAgICogICAtIGByZXN0cmljdGA6IG11c3QgYmUgc2V0IHRvICdFJy5cbiAgICogICAtIGBzY29wZWA6IHN1cHBvcnRlZC5cbiAgICogICAtIGB0ZW1wbGF0ZWA6IHN1cHBvcnRlZC5cbiAgICogICAtIGB0ZW1wbGF0ZVVybGA6IHN1cHBvcnRlZC5cbiAgICogICAtIGB0ZXJtaW5hbGA6IGlnbm9yZWQuXG4gICAqICAgLSBgdHJhbnNjbHVkZWA6IHN1cHBvcnRlZC5cbiAgICpcbiAgICpcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBgXG4gICAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgVXBncmFkZUFkYXB0ZXIoZm9yd2FyZFJlZigoKSA9PiBNeU5nMk1vZHVsZSkpO1xuICAgKiBjb25zdCBtb2R1bGUgPSBhbmd1bGFyLm1vZHVsZSgnbXlFeGFtcGxlJywgW10pO1xuICAgKlxuICAgKiBtb2R1bGUuZGlyZWN0aXZlKCdncmVldCcsIGZ1bmN0aW9uKCkge1xuICAgKiAgIHJldHVybiB7XG4gICAqICAgICBzY29wZToge3NhbHV0YXRpb246ICc9JywgbmFtZTogJz0nIH0sXG4gICAqICAgICB0ZW1wbGF0ZTogJ3t7c2FsdXRhdGlvbn19IHt7bmFtZX19ISAtIDxzcGFuIG5nLXRyYW5zY2x1ZGU+PC9zcGFuPidcbiAgICogICB9O1xuICAgKiB9KTtcbiAgICpcbiAgICogbW9kdWxlLmRpcmVjdGl2ZSgnbmcyJywgYWRhcHRlci5kb3duZ3JhZGVOZzJDb21wb25lbnQoTmcyQ29tcG9uZW50KSk7XG4gICAqXG4gICAqIEBDb21wb25lbnQoe1xuICAgKiAgIHNlbGVjdG9yOiAnbmcyJyxcbiAgICogICB0ZW1wbGF0ZTogJ25nMiB0ZW1wbGF0ZTogPGdyZWV0IHNhbHV0YXRpb249XCJIZWxsb1wiIFtuYW1lXT1cIndvcmxkXCI+dGV4dDwvZ3JlZXQ+J1xuICAgKiB9KVxuICAgKiBjbGFzcyBOZzJDb21wb25lbnQge1xuICAgKiB9XG4gICAqXG4gICAqIEBOZ01vZHVsZSh7XG4gICAqICAgZGVjbGFyYXRpb25zOiBbTmcyQ29tcG9uZW50LCBhZGFwdGVyLnVwZ3JhZGVOZzFDb21wb25lbnQoJ2dyZWV0JyldLFxuICAgKiAgIGltcG9ydHM6IFtCcm93c2VyTW9kdWxlXVxuICAgKiB9KVxuICAgKiBjbGFzcyBNeU5nMk1vZHVsZSB7fVxuICAgKlxuICAgKiBkb2N1bWVudC5ib2R5LmlubmVySFRNTCA9ICc8bmcyPjwvbmcyPic7XG4gICAqXG4gICAqIGFkYXB0ZXIuYm9vdHN0cmFwKGRvY3VtZW50LmJvZHksIFsnbXlFeGFtcGxlJ10pLnJlYWR5KGZ1bmN0aW9uKCkge1xuICAgKiAgIGV4cGVjdChkb2N1bWVudC5ib2R5LnRleHRDb250ZW50KS50b0VxdWFsKFwibmcyIHRlbXBsYXRlOiBIZWxsbyB3b3JsZCEgLSB0ZXh0XCIpO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICB1cGdyYWRlTmcxQ29tcG9uZW50KG5hbWU6IHN0cmluZyk6IFR5cGU8YW55PiB7XG4gICAgaWYgKCg8YW55PnRoaXMubmcxQ29tcG9uZW50c1RvQmVVcGdyYWRlZCkuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgIHJldHVybiB0aGlzLm5nMUNvbXBvbmVudHNUb0JlVXBncmFkZWRbbmFtZV0udHlwZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICh0aGlzLm5nMUNvbXBvbmVudHNUb0JlVXBncmFkZWRbbmFtZV0gPSBuZXcgVXBncmFkZU5nMUNvbXBvbmVudEFkYXB0ZXJCdWlsZGVyKG5hbWUpKVxuICAgICAgICAgIC50eXBlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIGFkYXB0ZXIncyBBbmd1bGFySlMgdXBncmFkZSBtb2R1bGUgZm9yIHVuaXQgdGVzdGluZyBpbiBBbmd1bGFySlMuXG4gICAqIFVzZSB0aGlzIGluc3RlYWQgb2YgYGFuZ3VsYXIubW9jay5tb2R1bGUoKWAgdG8gbG9hZCB0aGUgdXBncmFkZSBtb2R1bGUgaW50b1xuICAgKiB0aGUgQW5ndWxhckpTIHRlc3RpbmcgaW5qZWN0b3IuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqICMjIyBFeGFtcGxlXG4gICAqXG4gICAqIGBgYFxuICAgKiBjb25zdCB1cGdyYWRlQWRhcHRlciA9IG5ldyBVcGdyYWRlQWRhcHRlcihNeU5nMk1vZHVsZSk7XG4gICAqXG4gICAqIC8vIGNvbmZpZ3VyZSB0aGUgYWRhcHRlciB3aXRoIHVwZ3JhZGUvZG93bmdyYWRlIGNvbXBvbmVudHMgYW5kIHNlcnZpY2VzXG4gICAqIHVwZ3JhZGVBZGFwdGVyLmRvd25ncmFkZU5nMkNvbXBvbmVudChNeUNvbXBvbmVudCk7XG4gICAqXG4gICAqIGxldCB1cGdyYWRlQWRhcHRlclJlZjogVXBncmFkZUFkYXB0ZXJSZWY7XG4gICAqIGxldCAkY29tcGlsZSwgJHJvb3RTY29wZTtcbiAgICpcbiAgICogLy8gV2UgbXVzdCByZWdpc3RlciB0aGUgYWRhcHRlciBiZWZvcmUgYW55IGNhbGxzIHRvIGBpbmplY3QoKWBcbiAgICogYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAqICAgdXBncmFkZUFkYXB0ZXJSZWYgPSB1cGdyYWRlQWRhcHRlci5yZWdpc3RlckZvck5nMVRlc3RzKFsnaGVyb0FwcCddKTtcbiAgICogfSk7XG4gICAqXG4gICAqIGJlZm9yZUVhY2goaW5qZWN0KChfJGNvbXBpbGVfLCBfJHJvb3RTY29wZV8pID0+IHtcbiAgICogICAkY29tcGlsZSA9IF8kY29tcGlsZV87XG4gICAqICAgJHJvb3RTY29wZSA9IF8kcm9vdFNjb3BlXztcbiAgICogfSkpO1xuICAgKlxuICAgKiBpdChcInNheXMgaGVsbG9cIiwgKGRvbmUpID0+IHtcbiAgICogICB1cGdyYWRlQWRhcHRlclJlZi5yZWFkeSgoKSA9PiB7XG4gICAqICAgICBjb25zdCBlbGVtZW50ID0gJGNvbXBpbGUoXCI8bXktY29tcG9uZW50PjwvbXktY29tcG9uZW50PlwiKSgkcm9vdFNjb3BlKTtcbiAgICogICAgICRyb290U2NvcGUuJGFwcGx5KCk7XG4gICAqICAgICBleHBlY3QoZWxlbWVudC5odG1sKCkpLnRvQ29udGFpbihcIkhlbGxvIFdvcmxkXCIpO1xuICAgKiAgICAgZG9uZSgpO1xuICAgKiAgIH0pXG4gICAqIH0pO1xuICAgKlxuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIG1vZHVsZXMgYW55IEFuZ3VsYXJKUyBtb2R1bGVzIHRoYXQgdGhlIHVwZ3JhZGUgbW9kdWxlIHNob3VsZCBkZXBlbmQgdXBvblxuICAgKiBAcmV0dXJucyBhbiBgVXBncmFkZUFkYXB0ZXJSZWZgLCB3aGljaCBsZXRzIHlvdSByZWdpc3RlciBhIGByZWFkeSgpYCBjYWxsYmFjayB0b1xuICAgKiBydW4gYXNzZXJ0aW9ucyBvbmNlIHRoZSBBbmd1bGFyIGNvbXBvbmVudHMgYXJlIHJlYWR5IHRvIHRlc3QgdGhyb3VnaCBBbmd1bGFySlMuXG4gICAqL1xuICByZWdpc3RlckZvck5nMVRlc3RzKG1vZHVsZXM/OiBzdHJpbmdbXSk6IFVwZ3JhZGVBZGFwdGVyUmVmIHtcbiAgICBjb25zdCB3aW5kb3dOZ01vY2sgPSAod2luZG93IGFzIGFueSlbJ2FuZ3VsYXInXS5tb2NrO1xuICAgIGlmICghd2luZG93TmdNb2NrIHx8ICF3aW5kb3dOZ01vY2subW9kdWxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBmaW5kIFxcJ2FuZ3VsYXIubW9jay5tb2R1bGVcXCcuJyk7XG4gICAgfVxuICAgIHRoaXMuZGVjbGFyZU5nMU1vZHVsZShtb2R1bGVzKTtcbiAgICB3aW5kb3dOZ01vY2subW9kdWxlKHRoaXMubmcxTW9kdWxlLm5hbWUpO1xuICAgIGNvbnN0IHVwZ3JhZGUgPSBuZXcgVXBncmFkZUFkYXB0ZXJSZWYoKTtcbiAgICB0aGlzLm5nMkJvb3RzdHJhcERlZmVycmVkLnByb21pc2UudGhlbigobmcxSW5qZWN0b3IpID0+IHtcbiAgICAgICg8YW55PnVwZ3JhZGUpLl9ib290c3RyYXBEb25lKHRoaXMubW9kdWxlUmVmLCBuZzFJbmplY3Rvcik7XG4gICAgfSwgb25FcnJvcik7XG4gICAgcmV0dXJuIHVwZ3JhZGU7XG4gIH1cblxuICAvKipcbiAgICogQm9vdHN0cmFwIGEgaHlicmlkIEFuZ3VsYXJKUyAvIEFuZ3VsYXIgYXBwbGljYXRpb24uXG4gICAqXG4gICAqIFRoaXMgYGJvb3RzdHJhcGAgbWV0aG9kIGlzIGEgZGlyZWN0IHJlcGxhY2VtZW50ICh0YWtlcyBzYW1lIGFyZ3VtZW50cykgZm9yIEFuZ3VsYXJKU1xuICAgKiBbYGJvb3RzdHJhcGBdKGh0dHBzOi8vZG9jcy5hbmd1bGFyanMub3JnL2FwaS9uZy9mdW5jdGlvbi9hbmd1bGFyLmJvb3RzdHJhcCkgbWV0aG9kLiBVbmxpa2VcbiAgICogQW5ndWxhckpTLCB0aGlzIGJvb3RzdHJhcCBpcyBhc3luY2hyb25vdXMuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqICMjIyBFeGFtcGxlXG4gICAqXG4gICAqIGBgYFxuICAgKiBjb25zdCBhZGFwdGVyID0gbmV3IFVwZ3JhZGVBZGFwdGVyKE15TmcyTW9kdWxlKTtcbiAgICogY29uc3QgbW9kdWxlID0gYW5ndWxhci5tb2R1bGUoJ215RXhhbXBsZScsIFtdKTtcbiAgICogbW9kdWxlLmRpcmVjdGl2ZSgnbmcyJywgYWRhcHRlci5kb3duZ3JhZGVOZzJDb21wb25lbnQoTmcyKSk7XG4gICAqXG4gICAqIG1vZHVsZS5kaXJlY3RpdmUoJ25nMScsIGZ1bmN0aW9uKCkge1xuICAgKiAgIHJldHVybiB7XG4gICAqICAgICAgc2NvcGU6IHsgdGl0bGU6ICc9JyB9LFxuICAgKiAgICAgIHRlbXBsYXRlOiAnbmcxW0hlbGxvIHt7dGl0bGV9fSFdKDxzcGFuIG5nLXRyYW5zY2x1ZGU+PC9zcGFuPiknXG4gICAqICAgfTtcbiAgICogfSk7XG4gICAqXG4gICAqXG4gICAqIEBDb21wb25lbnQoe1xuICAgKiAgIHNlbGVjdG9yOiAnbmcyJyxcbiAgICogICBpbnB1dHM6IFsnbmFtZSddLFxuICAgKiAgIHRlbXBsYXRlOiAnbmcyWzxuZzEgW3RpdGxlXT1cIm5hbWVcIj50cmFuc2NsdWRlPC9uZzE+XSg8bmctY29udGVudD48L25nLWNvbnRlbnQ+KSdcbiAgICogfSlcbiAgICogY2xhc3MgTmcyIHtcbiAgICogfVxuICAgKlxuICAgKiBATmdNb2R1bGUoe1xuICAgKiAgIGRlY2xhcmF0aW9uczogW05nMiwgYWRhcHRlci51cGdyYWRlTmcxQ29tcG9uZW50KCduZzEnKV0sXG4gICAqICAgaW1wb3J0czogW0Jyb3dzZXJNb2R1bGVdXG4gICAqIH0pXG4gICAqIGNsYXNzIE15TmcyTW9kdWxlIHt9XG4gICAqXG4gICAqIGRvY3VtZW50LmJvZHkuaW5uZXJIVE1MID0gJzxuZzIgbmFtZT1cIldvcmxkXCI+cHJvamVjdDwvbmcyPic7XG4gICAqXG4gICAqIGFkYXB0ZXIuYm9vdHN0cmFwKGRvY3VtZW50LmJvZHksIFsnbXlFeGFtcGxlJ10pLnJlYWR5KGZ1bmN0aW9uKCkge1xuICAgKiAgIGV4cGVjdChkb2N1bWVudC5ib2R5LnRleHRDb250ZW50KS50b0VxdWFsKFxuICAgKiAgICAgICBcIm5nMltuZzFbSGVsbG8gV29ybGQhXSh0cmFuc2NsdWRlKV0ocHJvamVjdClcIik7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGJvb3RzdHJhcChlbGVtZW50OiBFbGVtZW50LCBtb2R1bGVzPzogYW55W10sIGNvbmZpZz86IElBbmd1bGFyQm9vdHN0cmFwQ29uZmlnKTpcbiAgICAgIFVwZ3JhZGVBZGFwdGVyUmVmIHtcbiAgICB0aGlzLmRlY2xhcmVOZzFNb2R1bGUobW9kdWxlcyk7XG5cbiAgICBjb25zdCB1cGdyYWRlID0gbmV3IFVwZ3JhZGVBZGFwdGVyUmVmKCk7XG5cbiAgICAvLyBNYWtlIHN1cmUgcmVzdW1lQm9vdHN0cmFwKCkgb25seSBleGlzdHMgaWYgdGhlIGN1cnJlbnQgYm9vdHN0cmFwIGlzIGRlZmVycmVkXG4gICAgY29uc3Qgd2luZG93QW5ndWxhciA9ICh3aW5kb3cgYXMgYW55IC8qKiBUT0RPICM/Pz8/ICovKVsnYW5ndWxhciddO1xuICAgIHdpbmRvd0FuZ3VsYXIucmVzdW1lQm9vdHN0cmFwID0gdW5kZWZpbmVkO1xuXG4gICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgIGJvb3RzdHJhcChlbGVtZW50LCBbdGhpcy5uZzFNb2R1bGUubmFtZV0sIGNvbmZpZyEpO1xuICAgIH0pO1xuICAgIGNvbnN0IG5nMUJvb3RzdHJhcFByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgaWYgKHdpbmRvd0FuZ3VsYXIucmVzdW1lQm9vdHN0cmFwKSB7XG4gICAgICAgIGNvbnN0IG9yaWdpbmFsUmVzdW1lQm9vdHN0cmFwOiAoKSA9PiB2b2lkID0gd2luZG93QW5ndWxhci5yZXN1bWVCb290c3RyYXA7XG4gICAgICAgIHdpbmRvd0FuZ3VsYXIucmVzdW1lQm9vdHN0cmFwID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgd2luZG93QW5ndWxhci5yZXN1bWVCb290c3RyYXAgPSBvcmlnaW5hbFJlc3VtZUJvb3RzdHJhcDtcbiAgICAgICAgICBjb25zdCByID0gd2luZG93QW5ndWxhci5yZXN1bWVCb290c3RyYXAuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBQcm9taXNlLmFsbChbdGhpcy5uZzJCb290c3RyYXBEZWZlcnJlZC5wcm9taXNlLCBuZzFCb290c3RyYXBQcm9taXNlXSkudGhlbigoW25nMUluamVjdG9yXSkgPT4ge1xuICAgICAgYW5ndWxhckVsZW1lbnQoZWxlbWVudCkuZGF0YSEoY29udHJvbGxlcktleShJTkpFQ1RPUl9LRVkpLCB0aGlzLm1vZHVsZVJlZiEuaW5qZWN0b3IpO1xuICAgICAgdGhpcy5tb2R1bGVSZWYhLmluamVjdG9yLmdldDxOZ1pvbmU+KE5nWm9uZSkucnVuKCgpID0+IHtcbiAgICAgICAgKDxhbnk+dXBncmFkZSkuX2Jvb3RzdHJhcERvbmUodGhpcy5tb2R1bGVSZWYsIG5nMUluamVjdG9yKTtcbiAgICAgIH0pO1xuICAgIH0sIG9uRXJyb3IpO1xuICAgIHJldHVybiB1cGdyYWRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93cyBBbmd1bGFySlMgc2VydmljZSB0byBiZSBhY2Nlc3NpYmxlIGZyb20gQW5ndWxhci5cbiAgICpcbiAgICogQHVzYWdlTm90ZXNcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBgXG4gICAqIGNsYXNzIExvZ2luIHsgLi4uIH1cbiAgICogY2xhc3MgU2VydmVyIHsgLi4uIH1cbiAgICpcbiAgICogQEluamVjdGFibGUoKVxuICAgKiBjbGFzcyBFeGFtcGxlIHtcbiAgICogICBjb25zdHJ1Y3RvcihASW5qZWN0KCdzZXJ2ZXInKSBzZXJ2ZXIsIGxvZ2luOiBMb2dpbikge1xuICAgKiAgICAgLi4uXG4gICAqICAgfVxuICAgKiB9XG4gICAqXG4gICAqIGNvbnN0IG1vZHVsZSA9IGFuZ3VsYXIubW9kdWxlKCdteUV4YW1wbGUnLCBbXSk7XG4gICAqIG1vZHVsZS5zZXJ2aWNlKCdzZXJ2ZXInLCBTZXJ2ZXIpO1xuICAgKiBtb2R1bGUuc2VydmljZSgnbG9naW4nLCBMb2dpbik7XG4gICAqXG4gICAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgVXBncmFkZUFkYXB0ZXIoTXlOZzJNb2R1bGUpO1xuICAgKiBhZGFwdGVyLnVwZ3JhZGVOZzFQcm92aWRlcignc2VydmVyJyk7XG4gICAqIGFkYXB0ZXIudXBncmFkZU5nMVByb3ZpZGVyKCdsb2dpbicsIHthc1Rva2VuOiBMb2dpbn0pO1xuICAgKlxuICAgKiBhZGFwdGVyLmJvb3RzdHJhcChkb2N1bWVudC5ib2R5LCBbJ215RXhhbXBsZSddKS5yZWFkeSgocmVmKSA9PiB7XG4gICAqICAgY29uc3QgZXhhbXBsZTogRXhhbXBsZSA9IHJlZi5uZzJJbmplY3Rvci5nZXQoRXhhbXBsZSk7XG4gICAqIH0pO1xuICAgKlxuICAgKiBgYGBcbiAgICovXG4gIHVwZ3JhZGVOZzFQcm92aWRlcihuYW1lOiBzdHJpbmcsIG9wdGlvbnM/OiB7YXNUb2tlbjogYW55fSkge1xuICAgIGNvbnN0IHRva2VuID0gb3B0aW9ucyAmJiBvcHRpb25zLmFzVG9rZW4gfHwgbmFtZTtcbiAgICB0aGlzLnVwZ3JhZGVkUHJvdmlkZXJzLnB1c2goe1xuICAgICAgcHJvdmlkZTogdG9rZW4sXG4gICAgICB1c2VGYWN0b3J5OiAoJGluamVjdG9yOiBJSW5qZWN0b3JTZXJ2aWNlKSA9PiAkaW5qZWN0b3IuZ2V0KG5hbWUpLFxuICAgICAgZGVwczogWyRJTkpFQ1RPUl1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvd3MgQW5ndWxhciBzZXJ2aWNlIHRvIGJlIGFjY2Vzc2libGUgZnJvbSBBbmd1bGFySlMuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqICMjIyBFeGFtcGxlXG4gICAqXG4gICAqIGBgYFxuICAgKiBjbGFzcyBFeGFtcGxlIHtcbiAgICogfVxuICAgKlxuICAgKiBjb25zdCBhZGFwdGVyID0gbmV3IFVwZ3JhZGVBZGFwdGVyKE15TmcyTW9kdWxlKTtcbiAgICpcbiAgICogY29uc3QgbW9kdWxlID0gYW5ndWxhci5tb2R1bGUoJ215RXhhbXBsZScsIFtdKTtcbiAgICogbW9kdWxlLmZhY3RvcnkoJ2V4YW1wbGUnLCBhZGFwdGVyLmRvd25ncmFkZU5nMlByb3ZpZGVyKEV4YW1wbGUpKTtcbiAgICpcbiAgICogYWRhcHRlci5ib290c3RyYXAoZG9jdW1lbnQuYm9keSwgWydteUV4YW1wbGUnXSkucmVhZHkoKHJlZikgPT4ge1xuICAgKiAgIGNvbnN0IGV4YW1wbGU6IEV4YW1wbGUgPSByZWYubmcxSW5qZWN0b3IuZ2V0KCdleGFtcGxlJyk7XG4gICAqIH0pO1xuICAgKlxuICAgKiBgYGBcbiAgICovXG4gIGRvd25ncmFkZU5nMlByb3ZpZGVyKHRva2VuOiBhbnkpOiBGdW5jdGlvbiB7XG4gICAgcmV0dXJuIGRvd25ncmFkZUluamVjdGFibGUodG9rZW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY2xhcmUgdGhlIEFuZ3VsYXJKUyB1cGdyYWRlIG1vZHVsZSBmb3IgdGhpcyBhZGFwdGVyIHdpdGhvdXQgYm9vdHN0cmFwcGluZyB0aGUgd2hvbGVcbiAgICogaHlicmlkIGFwcGxpY2F0aW9uLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBhdXRvbWF0aWNhbGx5IGNhbGxlZCBieSBgYm9vdHN0cmFwKClgIGFuZCBgcmVnaXN0ZXJGb3JOZzFUZXN0cygpYC5cbiAgICpcbiAgICogQHBhcmFtIG1vZHVsZXMgVGhlIEFuZ3VsYXJKUyBtb2R1bGVzIHRoYXQgdGhpcyB1cGdyYWRlIG1vZHVsZSBzaG91bGQgZGVwZW5kIHVwb24uXG4gICAqIEByZXR1cm5zIFRoZSBBbmd1bGFySlMgdXBncmFkZSBtb2R1bGUgdGhhdCBpcyBkZWNsYXJlZCBieSB0aGlzIG1ldGhvZFxuICAgKlxuICAgKiBAdXNhZ2VOb3Rlc1xuICAgKiAjIyMgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBcbiAgICogY29uc3QgdXBncmFkZUFkYXB0ZXIgPSBuZXcgVXBncmFkZUFkYXB0ZXIoTXlOZzJNb2R1bGUpO1xuICAgKiB1cGdyYWRlQWRhcHRlci5kZWNsYXJlTmcxTW9kdWxlKFsnaGVyb0FwcCddKTtcbiAgICogYGBgXG4gICAqL1xuICBwcml2YXRlIGRlY2xhcmVOZzFNb2R1bGUobW9kdWxlczogc3RyaW5nW10gPSBbXSk6IElNb2R1bGUge1xuICAgIGNvbnN0IGRlbGF5QXBwbHlFeHBzOiBGdW5jdGlvbltdID0gW107XG4gICAgbGV0IG9yaWdpbmFsJGFwcGx5Rm46IEZ1bmN0aW9uO1xuICAgIGxldCByb290U2NvcGVQcm90b3R5cGU6IGFueTtcbiAgICBjb25zdCB1cGdyYWRlQWRhcHRlciA9IHRoaXM7XG4gICAgY29uc3QgbmcxTW9kdWxlID0gdGhpcy5uZzFNb2R1bGUgPSBhbmd1bGFyTW9kdWxlKHRoaXMuaWRQcmVmaXgsIG1vZHVsZXMpO1xuICAgIGNvbnN0IHBsYXRmb3JtUmVmID0gcGxhdGZvcm1Ccm93c2VyRHluYW1pYygpO1xuXG4gICAgdGhpcy5uZ1pvbmUgPSBuZXcgTmdab25lKHtlbmFibGVMb25nU3RhY2tUcmFjZTogWm9uZS5oYXNPd25Qcm9wZXJ0eSgnbG9uZ1N0YWNrVHJhY2Vab25lU3BlYycpfSk7XG4gICAgdGhpcy5uZzJCb290c3RyYXBEZWZlcnJlZCA9IG5ldyBEZWZlcnJlZCgpO1xuICAgIG5nMU1vZHVsZS5jb25zdGFudChVUEdSQURFX0FQUF9UWVBFX0tFWSwgVXBncmFkZUFwcFR5cGUuRHluYW1pYylcbiAgICAgICAgLmZhY3RvcnkoSU5KRUNUT1JfS0VZLCAoKSA9PiB0aGlzLm1vZHVsZVJlZiEuaW5qZWN0b3IuZ2V0KEluamVjdG9yKSlcbiAgICAgICAgLmZhY3RvcnkoXG4gICAgICAgICAgICBMQVpZX01PRFVMRV9SRUYsIFtJTkpFQ1RPUl9LRVksIChpbmplY3RvcjogSW5qZWN0b3IpID0+ICh7aW5qZWN0b3J9IGFzIExhenlNb2R1bGVSZWYpXSlcbiAgICAgICAgLmNvbnN0YW50KE5HX1pPTkVfS0VZLCB0aGlzLm5nWm9uZSlcbiAgICAgICAgLmZhY3RvcnkoQ09NUElMRVJfS0VZLCAoKSA9PiB0aGlzLm1vZHVsZVJlZiEuaW5qZWN0b3IuZ2V0KENvbXBpbGVyKSlcbiAgICAgICAgLmNvbmZpZyhbXG4gICAgICAgICAgJyRwcm92aWRlJywgJyRpbmplY3RvcicsXG4gICAgICAgICAgKHByb3ZpZGU6IElQcm92aWRlU2VydmljZSwgbmcxSW5qZWN0b3I6IElJbmplY3RvclNlcnZpY2UpID0+IHtcbiAgICAgICAgICAgIHByb3ZpZGUuZGVjb3JhdG9yKCRST09UX1NDT1BFLCBbXG4gICAgICAgICAgICAgICckZGVsZWdhdGUnLFxuICAgICAgICAgICAgICBmdW5jdGlvbihyb290U2NvcGVEZWxlZ2F0ZTogSVJvb3RTY29wZVNlcnZpY2UpIHtcbiAgICAgICAgICAgICAgICAvLyBDYXB0dXJlIHRoZSByb290IGFwcGx5IHNvIHRoYXQgd2UgY2FuIGRlbGF5IGZpcnN0IGNhbGwgdG8gJGFwcGx5IHVudGlsIHdlXG4gICAgICAgICAgICAgICAgLy8gYm9vdHN0cmFwIEFuZ3VsYXIgYW5kIHRoZW4gd2UgcmVwbGF5IGFuZCByZXN0b3JlIHRoZSAkYXBwbHkuXG4gICAgICAgICAgICAgICAgcm9vdFNjb3BlUHJvdG90eXBlID0gcm9vdFNjb3BlRGVsZWdhdGUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIGlmIChyb290U2NvcGVQcm90b3R5cGUuaGFzT3duUHJvcGVydHkoJyRhcHBseScpKSB7XG4gICAgICAgICAgICAgICAgICBvcmlnaW5hbCRhcHBseUZuID0gcm9vdFNjb3BlUHJvdG90eXBlLiRhcHBseTtcbiAgICAgICAgICAgICAgICAgIHJvb3RTY29wZVByb3RvdHlwZS4kYXBwbHkgPSAoZXhwOiBhbnkpID0+IGRlbGF5QXBwbHlFeHBzLnB1c2goZXhwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZmluZCBcXCckYXBwbHlcXCcgb24gXFwnJHJvb3RTY29wZVxcJyEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3RTY29wZURlbGVnYXRlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIGlmIChuZzFJbmplY3Rvci5oYXMoJCRURVNUQUJJTElUWSkpIHtcbiAgICAgICAgICAgICAgcHJvdmlkZS5kZWNvcmF0b3IoJCRURVNUQUJJTElUWSwgW1xuICAgICAgICAgICAgICAgICckZGVsZWdhdGUnLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHRlc3RhYmlsaXR5RGVsZWdhdGU6IElUZXN0YWJpbGl0eVNlcnZpY2UpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsV2hlblN0YWJsZTogRnVuY3Rpb24gPSB0ZXN0YWJpbGl0eURlbGVnYXRlLndoZW5TdGFibGU7XG4gICAgICAgICAgICAgICAgICAvLyBDYW5ub3QgdXNlIGFycm93IGZ1bmN0aW9uIGJlbG93IGJlY2F1c2Ugd2UgbmVlZCB0aGUgY29udGV4dFxuICAgICAgICAgICAgICAgICAgY29uc3QgbmV3V2hlblN0YWJsZSA9IGZ1bmN0aW9uKHRoaXM6IHVua25vd24sIGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbFdoZW5TdGFibGUuY2FsbCh0aGlzLCBmdW5jdGlvbih0aGlzOiB1bmtub3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmcyVGVzdGFiaWxpdHk6IFRlc3RhYmlsaXR5ID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdXBncmFkZUFkYXB0ZXIubW9kdWxlUmVmIS5pbmplY3Rvci5nZXQoVGVzdGFiaWxpdHkpO1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChuZzJUZXN0YWJpbGl0eS5pc1N0YWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjay5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZzJUZXN0YWJpbGl0eS53aGVuU3RhYmxlKG5ld1doZW5TdGFibGUuYmluZCh0aGlzLCBjYWxsYmFjaykpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICB0ZXN0YWJpbGl0eURlbGVnYXRlLndoZW5TdGFibGUgPSBuZXdXaGVuU3RhYmxlO1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlc3RhYmlsaXR5RGVsZWdhdGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIF0pO1xuXG4gICAgbmcxTW9kdWxlLnJ1bihbXG4gICAgICAnJGluamVjdG9yJywgJyRyb290U2NvcGUnLFxuICAgICAgKG5nMUluamVjdG9yOiBJSW5qZWN0b3JTZXJ2aWNlLCByb290U2NvcGU6IElSb290U2NvcGVTZXJ2aWNlKSA9PiB7XG4gICAgICAgIFVwZ3JhZGVOZzFDb21wb25lbnRBZGFwdGVyQnVpbGRlci5yZXNvbHZlKHRoaXMubmcxQ29tcG9uZW50c1RvQmVVcGdyYWRlZCwgbmcxSW5qZWN0b3IpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIC8vIE5vdGU6IFRoZXJlIGlzIGEgYnVnIGluIFRTIDIuNCB0aGF0IHByZXZlbnRzIHVzIGZyb21cbiAgICAgICAgICAgICAgLy8gaW5saW5pbmcgdGhpcyBpbnRvIEBOZ01vZHVsZVxuICAgICAgICAgICAgICAvLyBUT0RPKHRib3NjaCk6IGZpbmQgb3IgZmlsZSBhIGJ1ZyBhZ2FpbnN0IFR5cGVTY3JpcHQgZm9yIHRoaXMuXG4gICAgICAgICAgICAgIGNvbnN0IG5nTW9kdWxlID0ge1xuICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAgICAgICAge3Byb3ZpZGU6ICRJTkpFQ1RPUiwgdXNlRmFjdG9yeTogKCkgPT4gbmcxSW5qZWN0b3J9LFxuICAgICAgICAgICAgICAgICAge3Byb3ZpZGU6ICRDT01QSUxFLCB1c2VGYWN0b3J5OiAoKSA9PiBuZzFJbmplY3Rvci5nZXQoJENPTVBJTEUpfSxcbiAgICAgICAgICAgICAgICAgIHRoaXMudXBncmFkZWRQcm92aWRlcnNcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIGltcG9ydHM6IFtyZXNvbHZlRm9yd2FyZFJlZih0aGlzLm5nMkFwcE1vZHVsZSldLFxuICAgICAgICAgICAgICAgIGVudHJ5Q29tcG9uZW50czogdGhpcy5kb3duZ3JhZGVkQ29tcG9uZW50c1xuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAvLyBBdCB0aGlzIHBvaW50IHdlIGhhdmUgbmcxIGluamVjdG9yIGFuZCB3ZSBoYXZlIHByZXBhcmVkXG4gICAgICAgICAgICAgIC8vIG5nMSBjb21wb25lbnRzIHRvIGJlIHVwZ3JhZGVkLCB3ZSBub3cgY2FuIGJvb3RzdHJhcCBuZzIuXG4gICAgICAgICAgICAgIEBOZ01vZHVsZSh7aml0OiB0cnVlLCAuLi5uZ01vZHVsZX0pXG4gICAgICAgICAgICAgIGNsYXNzIER5bmFtaWNOZ1VwZ3JhZGVNb2R1bGUge1xuICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkge31cbiAgICAgICAgICAgICAgICBuZ0RvQm9vdHN0cmFwKCkge31cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBwbGF0Zm9ybVJlZlxuICAgICAgICAgICAgICAgICAgLmJvb3RzdHJhcE1vZHVsZShcbiAgICAgICAgICAgICAgICAgICAgICBEeW5hbWljTmdVcGdyYWRlTW9kdWxlLCBbdGhpcy5jb21waWxlck9wdGlvbnMhLCB7bmdab25lOiB0aGlzLm5nWm9uZX1dKVxuICAgICAgICAgICAgICAgICAgLnRoZW4oKHJlZjogTmdNb2R1bGVSZWY8YW55PikgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1vZHVsZVJlZiA9IHJlZjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAocm9vdFNjb3BlUHJvdG90eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290U2NvcGVQcm90b3R5cGUuJGFwcGx5ID0gb3JpZ2luYWwkYXBwbHlGbjsgIC8vIHJlc3RvcmUgb3JpZ2luYWwgJGFwcGx5XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZGVsYXlBcHBseUV4cHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RTY29wZS4kYXBwbHkoZGVsYXlBcHBseUV4cHMuc2hpZnQoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByb290U2NvcGVQcm90b3R5cGUgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5uZzJCb290c3RyYXBEZWZlcnJlZC5yZXNvbHZlKG5nMUluamVjdG9yKSwgb25FcnJvcilcbiAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN1YnNjcmlwdGlvbiA9IHRoaXMubmdab25lLm9uTWljcm90YXNrRW1wdHkuc3Vic2NyaWJlKHtcbiAgICAgICAgICAgICAgICAgICAgICBuZXh0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocm9vdFNjb3BlLiQkcGhhc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRGV2TW9kZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQSBkaWdlc3Qgd2FzIHRyaWdnZXJlZCB3aGlsZSBvbmUgd2FzIGFscmVhZHkgaW4gcHJvZ3Jlc3MuIFRoaXMgbWF5IG1lYW4gdGhhdCBzb21ldGhpbmcgaXMgdHJpZ2dlcmluZyBkaWdlc3RzIG91dHNpZGUgdGhlIEFuZ3VsYXIgem9uZS4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290U2NvcGUuJGV2YWxBc3luYygoKSA9PiB7fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290U2NvcGUuJGRpZ2VzdCgpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJvb3RTY29wZS4kb24oJyRkZXN0cm95JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBEZXN0cm95IHRoZSBBbmd1bGFySlMgYXBwIG9uY2UgdGhlIEFuZ3VsYXIgYFBsYXRmb3JtUmVmYCBpcyBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgZG9lcyBub3QgaGFwcGVuIGluIGEgdHlwaWNhbCBTUEEgc2NlbmFyaW8sIGJ1dCBpdCBtaWdodCBiZSB1c2VmdWwgZm9yXG4gICAgICAgICAgICAgICAgICAgIC8vIG90aGVyIHVzZS1jYXNlcyB3aGVyZSBkaXNwb3Npbmcgb2YgYW4gQW5ndWxhci9Bbmd1bGFySlMgYXBwIGlzIG5lY2Vzc2FyeVxuICAgICAgICAgICAgICAgICAgICAvLyAoc3VjaCBhcyBIb3QgTW9kdWxlIFJlcGxhY2VtZW50IChITVIpKS5cbiAgICAgICAgICAgICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvaXNzdWVzLzM5OTM1LlxuICAgICAgICAgICAgICAgICAgICBwbGF0Zm9ybVJlZi5vbkRlc3Ryb3koKCkgPT4gZGVzdHJveUFwcChuZzFJbmplY3RvcikpO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB0aGlzLm5nMkJvb3RzdHJhcERlZmVycmVkLnJlamVjdChlKSk7XG4gICAgICB9XG4gICAgXSk7XG5cbiAgICByZXR1cm4gbmcxTW9kdWxlO1xuICB9XG59XG5cbi8qKlxuICogU3luY2hyb25vdXMgcHJvbWlzZS1saWtlIG9iamVjdCB0byB3cmFwIHBhcmVudCBpbmplY3RvcnMsXG4gKiB0byBwcmVzZXJ2ZSB0aGUgc3luY2hyb25vdXMgbmF0dXJlIG9mIEFuZ3VsYXJKUydzICRjb21waWxlLlxuICovXG5jbGFzcyBQYXJlbnRJbmplY3RvclByb21pc2Uge1xuICAvLyBUT0RPKGlzc3VlLzI0NTcxKTogcmVtb3ZlICchJy5cbiAgcHJpdmF0ZSBpbmplY3RvciE6IEluamVjdG9yO1xuICBwcml2YXRlIGNhbGxiYWNrczogKChpbmplY3RvcjogSW5qZWN0b3IpID0+IGFueSlbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudDogSUF1Z21lbnRlZEpRdWVyeSkge1xuICAgIC8vIHN0b3JlIHRoZSBwcm9taXNlIG9uIHRoZSBlbGVtZW50XG4gICAgZWxlbWVudC5kYXRhIShjb250cm9sbGVyS2V5KElOSkVDVE9SX0tFWSksIHRoaXMpO1xuICB9XG5cbiAgdGhlbihjYWxsYmFjazogKGluamVjdG9yOiBJbmplY3RvcikgPT4gYW55KSB7XG4gICAgaWYgKHRoaXMuaW5qZWN0b3IpIHtcbiAgICAgIGNhbGxiYWNrKHRoaXMuaW5qZWN0b3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTtcbiAgICB9XG4gIH1cblxuICByZXNvbHZlKGluamVjdG9yOiBJbmplY3Rvcikge1xuICAgIHRoaXMuaW5qZWN0b3IgPSBpbmplY3RvcjtcblxuICAgIC8vIHJlc2V0IHRoZSBlbGVtZW50IGRhdGEgdG8gcG9pbnQgdG8gdGhlIHJlYWwgaW5qZWN0b3JcbiAgICB0aGlzLmVsZW1lbnQuZGF0YSEoY29udHJvbGxlcktleShJTkpFQ1RPUl9LRVkpLCBpbmplY3Rvcik7XG5cbiAgICAvLyBjbGVhbiBvdXQgdGhlIGVsZW1lbnQgdG8gcHJldmVudCBtZW1vcnkgbGVha3NcbiAgICB0aGlzLmVsZW1lbnQgPSBudWxsITtcblxuICAgIC8vIHJ1biBhbGwgdGhlIHF1ZXVlZCBjYWxsYmFja3NcbiAgICB0aGlzLmNhbGxiYWNrcy5mb3JFYWNoKChjYWxsYmFjaykgPT4gY2FsbGJhY2soaW5qZWN0b3IpKTtcbiAgICB0aGlzLmNhbGxiYWNrcy5sZW5ndGggPSAwO1xuICB9XG59XG5cblxuLyoqXG4gKiBVc2UgYFVwZ3JhZGVBZGFwdGVyUmVmYCB0byBjb250cm9sIGEgaHlicmlkIEFuZ3VsYXJKUyAvIEFuZ3VsYXIgYXBwbGljYXRpb24uXG4gKlxuICogQGRlcHJlY2F0ZWQgRGVwcmVjYXRlZCBzaW5jZSB2NS4gVXNlIGB1cGdyYWRlL3N0YXRpY2AgaW5zdGVhZCwgd2hpY2ggYWxzbyBzdXBwb3J0c1xuICogW0FoZWFkLW9mLVRpbWUgY29tcGlsYXRpb25dKGd1aWRlL2FvdC1jb21waWxlcikuXG4gKiBAcHVibGljQXBpXG4gKi9cbmV4cG9ydCBjbGFzcyBVcGdyYWRlQWRhcHRlclJlZiB7XG4gIC8qIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIF9yZWFkeUZuOiAoKHVwZ3JhZGVBZGFwdGVyUmVmOiBVcGdyYWRlQWRhcHRlclJlZikgPT4gdm9pZCl8bnVsbCA9IG51bGw7XG5cbiAgcHVibGljIG5nMVJvb3RTY29wZTogSVJvb3RTY29wZVNlcnZpY2UgPSBudWxsITtcbiAgcHVibGljIG5nMUluamVjdG9yOiBJSW5qZWN0b3JTZXJ2aWNlID0gbnVsbCE7XG4gIHB1YmxpYyBuZzJNb2R1bGVSZWY6IE5nTW9kdWxlUmVmPGFueT4gPSBudWxsITtcbiAgcHVibGljIG5nMkluamVjdG9yOiBJbmplY3RvciA9IG51bGwhO1xuXG4gIC8qIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIF9ib290c3RyYXBEb25lKG5nTW9kdWxlUmVmOiBOZ01vZHVsZVJlZjxhbnk+LCBuZzFJbmplY3RvcjogSUluamVjdG9yU2VydmljZSkge1xuICAgIHRoaXMubmcyTW9kdWxlUmVmID0gbmdNb2R1bGVSZWY7XG4gICAgdGhpcy5uZzJJbmplY3RvciA9IG5nTW9kdWxlUmVmLmluamVjdG9yO1xuICAgIHRoaXMubmcxSW5qZWN0b3IgPSBuZzFJbmplY3RvcjtcbiAgICB0aGlzLm5nMVJvb3RTY29wZSA9IG5nMUluamVjdG9yLmdldCgkUk9PVF9TQ09QRSk7XG4gICAgdGhpcy5fcmVhZHlGbiAmJiB0aGlzLl9yZWFkeUZuKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gd2hpY2ggaXMgbm90aWZpZWQgdXBvbiBzdWNjZXNzZnVsIGh5YnJpZCBBbmd1bGFySlMgLyBBbmd1bGFyXG4gICAqIGFwcGxpY2F0aW9uIGhhcyBiZWVuIGJvb3RzdHJhcHBlZC5cbiAgICpcbiAgICogVGhlIGByZWFkeWAgY2FsbGJhY2sgZnVuY3Rpb24gaXMgaW52b2tlZCBpbnNpZGUgdGhlIEFuZ3VsYXIgem9uZSwgdGhlcmVmb3JlIGl0IGRvZXMgbm90XG4gICAqIHJlcXVpcmUgYSBjYWxsIHRvIGAkYXBwbHkoKWAuXG4gICAqL1xuICBwdWJsaWMgcmVhZHkoZm46ICh1cGdyYWRlQWRhcHRlclJlZjogVXBncmFkZUFkYXB0ZXJSZWYpID0+IHZvaWQpIHtcbiAgICB0aGlzLl9yZWFkeUZuID0gZm47XG4gIH1cblxuICAvKipcbiAgICogRGlzcG9zZSBvZiBydW5uaW5nIGh5YnJpZCBBbmd1bGFySlMgLyBBbmd1bGFyIGFwcGxpY2F0aW9uLlxuICAgKi9cbiAgcHVibGljIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5uZzFJbmplY3RvciEuZ2V0KCRST09UX1NDT1BFKS4kZGVzdHJveSgpO1xuICAgIHRoaXMubmcyTW9kdWxlUmVmIS5kZXN0cm95KCk7XG4gIH1cbn1cbiJdfQ==
|