@angular/router 12.2.8 → 13.0.0-next.11

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.
Files changed (111) hide show
  1. package/{esm2015/index.js → esm2020/index.mjs} +0 -0
  2. package/{esm2015/public_api.js → esm2020/public_api.mjs} +0 -0
  3. package/esm2020/router.mjs +5 -0
  4. package/{esm2015/src/apply_redirects.js → esm2020/src/apply_redirects.mjs} +0 -0
  5. package/esm2020/src/components/empty_outlet.mjs +29 -0
  6. package/esm2020/src/config.mjs +14 -0
  7. package/{esm2015/src/create_router_state.js → esm2020/src/create_router_state.mjs} +0 -0
  8. package/{esm2015/src/create_url_tree.js → esm2020/src/create_url_tree.mjs} +0 -0
  9. package/esm2020/src/directives/router_link.mjs +353 -0
  10. package/esm2020/src/directives/router_link_active.mjs +215 -0
  11. package/esm2020/src/directives/router_outlet.mjs +219 -0
  12. package/{esm2015/src/events.js → esm2020/src/events.mjs} +0 -0
  13. package/{esm2015/src/index.js → esm2020/src/index.mjs} +1 -1
  14. package/{esm2015/src/interfaces.js → esm2020/src/interfaces.mjs} +1 -1
  15. package/{esm2015/src/operators/activate_routes.js → esm2020/src/operators/activate_routes.mjs} +0 -0
  16. package/esm2020/src/operators/apply_redirects.mjs +14 -0
  17. package/esm2020/src/operators/check_guards.mjs +138 -0
  18. package/{esm2015/src/operators/prioritized_guard_value.js → esm2020/src/operators/prioritized_guard_value.mjs} +0 -0
  19. package/esm2020/src/operators/recognize.mjs +14 -0
  20. package/esm2020/src/operators/resolve_data.mjs +59 -0
  21. package/{esm2015/src/operators/switch_tap.js → esm2020/src/operators/switch_tap.mjs} +0 -0
  22. package/{esm2015/src/private_export.js → esm2020/src/private_export.mjs} +0 -0
  23. package/esm2020/src/recognize.mjs +262 -0
  24. package/{esm2015/src/route_reuse_strategy.js → esm2020/src/route_reuse_strategy.mjs} +0 -0
  25. package/esm2020/src/router.mjs +1009 -0
  26. package/esm2020/src/router_config_loader.mjs +71 -0
  27. package/esm2020/src/router_module.mjs +367 -0
  28. package/{esm2015/src/router_outlet_context.js → esm2020/src/router_outlet_context.mjs} +0 -0
  29. package/esm2020/src/router_preloader.mjs +127 -0
  30. package/esm2020/src/router_scroller.mjs +95 -0
  31. package/esm2020/src/router_state.mjs +404 -0
  32. package/{esm2015/src/shared.js → esm2020/src/shared.mjs} +0 -0
  33. package/{esm2015/src/url_handling_strategy.js → esm2020/src/url_handling_strategy.mjs} +0 -0
  34. package/{esm2015/src/url_tree.js → esm2020/src/url_tree.mjs} +2 -2
  35. package/{esm2015/src/utils/collection.js → esm2020/src/utils/collection.mjs} +0 -0
  36. package/{esm2015/src/utils/config.js → esm2020/src/utils/config.mjs} +2 -2
  37. package/esm2020/src/utils/config_matching.mjs +145 -0
  38. package/{esm2015/src/utils/preactivation.js → esm2020/src/utils/preactivation.mjs} +0 -0
  39. package/{esm2015/src/utils/tree.js → esm2020/src/utils/tree.mjs} +0 -0
  40. package/{esm2015/src/utils/type_guards.js → esm2020/src/utils/type_guards.mjs} +0 -0
  41. package/{esm2015/src/version.js → esm2020/src/version.mjs} +1 -1
  42. package/{esm2015/testing/index.js → esm2020/testing/index.mjs} +0 -0
  43. package/{esm2015/testing/public_api.js → esm2020/testing/public_api.mjs} +0 -0
  44. package/esm2020/testing/src/extra_router_testing_providers.mjs +10 -0
  45. package/esm2020/testing/src/router_testing_module.mjs +122 -0
  46. package/esm2020/testing/src/spy_ng_module_factory_loader.mjs +10 -0
  47. package/esm2020/testing/src/testing.mjs +15 -0
  48. package/{esm2015/testing/testing.js → esm2020/testing/testing.mjs} +0 -0
  49. package/{esm2015/upgrade/index.js → esm2020/upgrade/index.mjs} +0 -0
  50. package/{esm2015/upgrade/public_api.js → esm2020/upgrade/public_api.mjs} +0 -0
  51. package/esm2020/upgrade/src/upgrade.mjs +120 -0
  52. package/{esm2015/upgrade/upgrade.js → esm2020/upgrade/upgrade.mjs} +0 -0
  53. package/fesm2015/{router.js → router.mjs} +593 -588
  54. package/fesm2015/router.mjs.map +1 -0
  55. package/fesm2015/testing.mjs +179 -0
  56. package/fesm2015/testing.mjs.map +1 -0
  57. package/fesm2015/{upgrade.js → upgrade.mjs} +4 -5
  58. package/fesm2015/upgrade.mjs.map +1 -0
  59. package/fesm2020/router.mjs +6162 -0
  60. package/fesm2020/router.mjs.map +1 -0
  61. package/fesm2020/testing.mjs +179 -0
  62. package/fesm2020/testing.mjs.map +1 -0
  63. package/fesm2020/upgrade.mjs +150 -0
  64. package/fesm2020/upgrade.mjs.map +1 -0
  65. package/package.json +34 -10
  66. package/router.d.ts +149 -140
  67. package/testing/package.json +5 -5
  68. package/testing/testing.d.ts +9 -66
  69. package/upgrade/package.json +5 -5
  70. package/upgrade/upgrade.d.ts +1 -1
  71. package/bundles/router-testing.umd.js +0 -541
  72. package/bundles/router-testing.umd.js.map +0 -1
  73. package/bundles/router-upgrade.umd.js +0 -157
  74. package/bundles/router-upgrade.umd.js.map +0 -1
  75. package/bundles/router.umd.js +0 -6879
  76. package/bundles/router.umd.js.map +0 -1
  77. package/esm2015/router.externs.js +0 -6
  78. package/esm2015/router.js +0 -9
  79. package/esm2015/src/components/empty_outlet.js +0 -24
  80. package/esm2015/src/config.js +0 -14
  81. package/esm2015/src/directives/router_link.js +0 -293
  82. package/esm2015/src/directives/router_link_active.js +0 -190
  83. package/esm2015/src/directives/router_outlet.js +0 -193
  84. package/esm2015/src/operators/apply_redirects.js +0 -14
  85. package/esm2015/src/operators/check_guards.js +0 -138
  86. package/esm2015/src/operators/recognize.js +0 -14
  87. package/esm2015/src/operators/resolve_data.js +0 -56
  88. package/esm2015/src/recognize.js +0 -262
  89. package/esm2015/src/router.js +0 -1079
  90. package/esm2015/src/router_config_loader.js +0 -76
  91. package/esm2015/src/router_module.js +0 -363
  92. package/esm2015/src/router_preloader.js +0 -130
  93. package/esm2015/src/router_scroller.js +0 -95
  94. package/esm2015/src/router_state.js +0 -404
  95. package/esm2015/src/utils/config_matching.js +0 -145
  96. package/esm2015/testing/src/router_testing_module.js +0 -166
  97. package/esm2015/testing/src/testing.js +0 -14
  98. package/esm2015/testing/testing.externs.js +0 -6
  99. package/esm2015/upgrade/src/upgrade.js +0 -122
  100. package/esm2015/upgrade/upgrade.externs.js +0 -6
  101. package/fesm2015/router.js.map +0 -1
  102. package/fesm2015/testing.js +0 -204
  103. package/fesm2015/testing.js.map +0 -1
  104. package/fesm2015/upgrade.js.map +0 -1
  105. package/router.metadata.json +0 -1
  106. package/testing/testing.metadata.json +0 -1
  107. package/testing.d.ts +0 -7
  108. package/testing.metadata.json +0 -1
  109. package/upgrade/upgrade.metadata.json +0 -1
  110. package/upgrade.d.ts +0 -7
  111. package/upgrade.metadata.json +0 -1
@@ -1,1079 +0,0 @@
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 { Location } from '@angular/common';
9
- import { Compiler, Injectable, Injector, NgModuleFactoryLoader, NgModuleRef, NgZone, Type, ɵConsole as Console } from '@angular/core';
10
- import { BehaviorSubject, EMPTY, of, Subject } from 'rxjs';
11
- import { catchError, filter, finalize, map, switchMap, tap } from 'rxjs/operators';
12
- import { createRouterState } from './create_router_state';
13
- import { createUrlTree } from './create_url_tree';
14
- import { GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RoutesRecognized } from './events';
15
- import { activateRoutes } from './operators/activate_routes';
16
- import { applyRedirects } from './operators/apply_redirects';
17
- import { checkGuards } from './operators/check_guards';
18
- import { recognize } from './operators/recognize';
19
- import { resolveData } from './operators/resolve_data';
20
- import { switchTap } from './operators/switch_tap';
21
- import { DefaultRouteReuseStrategy } from './route_reuse_strategy';
22
- import { RouterConfigLoader } from './router_config_loader';
23
- import { ChildrenOutletContexts } from './router_outlet_context';
24
- import { createEmptyState } from './router_state';
25
- import { isNavigationCancelingError, navigationCancelingError } from './shared';
26
- import { DefaultUrlHandlingStrategy } from './url_handling_strategy';
27
- import { containsTree, createEmptyUrlTree, UrlSerializer } from './url_tree';
28
- import { standardizeConfig, validateConfig } from './utils/config';
29
- import { getAllRouteGuards } from './utils/preactivation';
30
- import { isUrlTree } from './utils/type_guards';
31
- function defaultErrorHandler(error) {
32
- throw error;
33
- }
34
- function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
35
- return urlSerializer.parse('/');
36
- }
37
- /**
38
- * @internal
39
- */
40
- function defaultRouterHook(snapshot, runExtras) {
41
- return of(null);
42
- }
43
- /**
44
- * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
45
- * (exact = true).
46
- */
47
- export const exactMatchOptions = {
48
- paths: 'exact',
49
- fragment: 'ignored',
50
- matrixParams: 'ignored',
51
- queryParams: 'exact'
52
- };
53
- /**
54
- * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
55
- * (exact = false).
56
- */
57
- export const subsetMatchOptions = {
58
- paths: 'subset',
59
- fragment: 'ignored',
60
- matrixParams: 'ignored',
61
- queryParams: 'subset'
62
- };
63
- /**
64
- * @description
65
- *
66
- * A service that provides navigation among views and URL manipulation capabilities.
67
- *
68
- * @see `Route`.
69
- * @see [Routing and Navigation Guide](guide/router).
70
- *
71
- * @ngModule RouterModule
72
- *
73
- * @publicApi
74
- */
75
- export class Router {
76
- /**
77
- * Creates the router service.
78
- */
79
- // TODO: vsavkin make internal after the final is out.
80
- constructor(rootComponentType, urlSerializer, rootContexts, location, injector, loader, compiler, config) {
81
- this.rootComponentType = rootComponentType;
82
- this.urlSerializer = urlSerializer;
83
- this.rootContexts = rootContexts;
84
- this.location = location;
85
- this.config = config;
86
- this.lastSuccessfulNavigation = null;
87
- this.currentNavigation = null;
88
- this.disposed = false;
89
- /**
90
- * Tracks the previously seen location change from the location subscription so we can compare
91
- * the two latest to see if they are duplicates. See setUpLocationChangeListener.
92
- */
93
- this.lastLocationChangeInfo = null;
94
- this.navigationId = 0;
95
- /**
96
- * The id of the currently active page in the router.
97
- * Updated to the transition's target id on a successful navigation.
98
- *
99
- * This is used to track what page the router last activated. When an attempted navigation fails,
100
- * the router can then use this to compute how to restore the state back to the previously active
101
- * page.
102
- */
103
- this.currentPageId = 0;
104
- this.isNgZoneEnabled = false;
105
- /**
106
- * An event stream for routing events in this NgModule.
107
- */
108
- this.events = new Subject();
109
- /**
110
- * A handler for navigation errors in this NgModule.
111
- */
112
- this.errorHandler = defaultErrorHandler;
113
- /**
114
- * A handler for errors thrown by `Router.parseUrl(url)`
115
- * when `url` contains an invalid character.
116
- * The most common case is a `%` sign
117
- * that's not encoded and is not part of a percent encoded sequence.
118
- */
119
- this.malformedUriErrorHandler = defaultMalformedUriErrorHandler;
120
- /**
121
- * True if at least one navigation event has occurred,
122
- * false otherwise.
123
- */
124
- this.navigated = false;
125
- this.lastSuccessfulId = -1;
126
- /**
127
- * Hooks that enable you to pause navigation,
128
- * either before or after the preactivation phase.
129
- * Used by `RouterModule`.
130
- *
131
- * @internal
132
- */
133
- this.hooks = { beforePreactivation: defaultRouterHook, afterPreactivation: defaultRouterHook };
134
- /**
135
- * A strategy for extracting and merging URLs.
136
- * Used for AngularJS to Angular migrations.
137
- */
138
- this.urlHandlingStrategy = new DefaultUrlHandlingStrategy();
139
- /**
140
- * A strategy for re-using routes.
141
- */
142
- this.routeReuseStrategy = new DefaultRouteReuseStrategy();
143
- /**
144
- * How to handle a navigation request to the current URL. One of:
145
- *
146
- * - `'ignore'` : The router ignores the request.
147
- * - `'reload'` : The router reloads the URL. Use to implement a "refresh" feature.
148
- *
149
- * Note that this only configures whether the Route reprocesses the URL and triggers related
150
- * action and events like redirects, guards, and resolvers. By default, the router re-uses a
151
- * component instance when it re-navigates to the same component type without visiting a different
152
- * component first. This behavior is configured by the `RouteReuseStrategy`. In order to reload
153
- * routed components on same url navigation, you need to set `onSameUrlNavigation` to `'reload'`
154
- * _and_ provide a `RouteReuseStrategy` which returns `false` for `shouldReuseRoute`.
155
- */
156
- this.onSameUrlNavigation = 'ignore';
157
- /**
158
- * How to merge parameters, data, and resolved data from parent to child
159
- * routes. One of:
160
- *
161
- * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data
162
- * for path-less or component-less routes.
163
- * - `'always'` : Inherit parent parameters, data, and resolved data
164
- * for all child routes.
165
- */
166
- this.paramsInheritanceStrategy = 'emptyOnly';
167
- /**
168
- * Determines when the router updates the browser URL.
169
- * By default (`"deferred"`), updates the browser URL after navigation has finished.
170
- * Set to `'eager'` to update the browser URL at the beginning of navigation.
171
- * You can choose to update early so that, if navigation fails,
172
- * you can show an error message with the URL that failed.
173
- */
174
- this.urlUpdateStrategy = 'deferred';
175
- /**
176
- * Enables a bug fix that corrects relative link resolution in components with empty paths.
177
- * @see `RouterModule`
178
- */
179
- this.relativeLinkResolution = 'corrected';
180
- /**
181
- * Configures how the Router attempts to restore state when a navigation is cancelled.
182
- *
183
- * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
184
- * router before the navigation started.
185
- *
186
- * 'computed' - Will always return to the same state that corresponds to the actual Angular route
187
- * when the navigation gets cancelled right after triggering a `popstate` event.
188
- *
189
- * The default value is `replace`
190
- *
191
- * @internal
192
- */
193
- // TODO(atscott): Determine how/when/if to make this public API
194
- // This shouldn’t be an option at all but may need to be in order to allow migration without a
195
- // breaking change. We need to determine if it should be made into public api (or if we forgo
196
- // the option and release as a breaking change bug fix in a major version).
197
- this.canceledNavigationResolution = 'replace';
198
- const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
199
- const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
200
- this.ngModule = injector.get(NgModuleRef);
201
- this.console = injector.get(Console);
202
- const ngZone = injector.get(NgZone);
203
- this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone();
204
- this.resetConfig(config);
205
- this.currentUrlTree = createEmptyUrlTree();
206
- this.rawUrlTree = this.currentUrlTree;
207
- this.browserUrlTree = this.currentUrlTree;
208
- this.configLoader = new RouterConfigLoader(loader, compiler, onLoadStart, onLoadEnd);
209
- this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
210
- this.transitions = new BehaviorSubject({
211
- id: 0,
212
- targetPageId: 0,
213
- currentUrlTree: this.currentUrlTree,
214
- currentRawUrl: this.currentUrlTree,
215
- extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
216
- urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree),
217
- rawUrl: this.currentUrlTree,
218
- extras: {},
219
- resolve: null,
220
- reject: null,
221
- promise: Promise.resolve(true),
222
- source: 'imperative',
223
- restoredState: null,
224
- currentSnapshot: this.routerState.snapshot,
225
- targetSnapshot: null,
226
- currentRouterState: this.routerState,
227
- targetRouterState: null,
228
- guards: { canActivateChecks: [], canDeactivateChecks: [] },
229
- guardsResult: null,
230
- });
231
- this.navigations = this.setupNavigations(this.transitions);
232
- this.processNavigations();
233
- }
234
- /**
235
- * The ɵrouterPageId of whatever page is currently active in the browser history. This is
236
- * important for computing the target page id for new navigations because we need to ensure each
237
- * page id in the browser history is 1 more than the previous entry.
238
- */
239
- get browserPageId() {
240
- var _a;
241
- return (_a = this.location.getState()) === null || _a === void 0 ? void 0 : _a.ɵrouterPageId;
242
- }
243
- setupNavigations(transitions) {
244
- const eventsSubject = this.events;
245
- return transitions.pipe(filter(t => t.id !== 0),
246
- // Extract URL
247
- map(t => (Object.assign(Object.assign({}, t), { extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) }))),
248
- // Using switchMap so we cancel executing navigations when a new one comes in
249
- switchMap(t => {
250
- let completed = false;
251
- let errored = false;
252
- return of(t).pipe(
253
- // Store the Navigation object
254
- tap(t => {
255
- this.currentNavigation = {
256
- id: t.id,
257
- initialUrl: t.currentRawUrl,
258
- extractedUrl: t.extractedUrl,
259
- trigger: t.source,
260
- extras: t.extras,
261
- previousNavigation: this.lastSuccessfulNavigation ? Object.assign(Object.assign({}, this.lastSuccessfulNavigation), { previousNavigation: null }) :
262
- null
263
- };
264
- }), switchMap(t => {
265
- const browserUrlTree = this.browserUrlTree.toString();
266
- const urlTransition = !this.navigated ||
267
- t.extractedUrl.toString() !== browserUrlTree ||
268
- // Navigations which succeed or ones which fail and are cleaned up
269
- // correctly should result in `browserUrlTree` and `currentUrlTree`
270
- // matching. If this is not the case, assume something went wrong and try
271
- // processing the URL again.
272
- browserUrlTree !== this.currentUrlTree.toString();
273
- const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
274
- this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
275
- if (processCurrentUrl) {
276
- // If the source of the navigation is from a browser event, the URL is
277
- // already updated. We already need to sync the internal state.
278
- if (isBrowserTriggeredNavigation(t.source)) {
279
- this.browserUrlTree = t.extractedUrl;
280
- }
281
- return of(t).pipe(
282
- // Fire NavigationStart event
283
- switchMap(t => {
284
- const transition = this.transitions.getValue();
285
- eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.restoredState));
286
- if (transition !== this.transitions.getValue()) {
287
- return EMPTY;
288
- }
289
- // This delay is required to match old behavior that forced
290
- // navigation to always be async
291
- return Promise.resolve(t);
292
- }),
293
- // ApplyRedirects
294
- applyRedirects(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config),
295
- // Update the currentNavigation
296
- tap(t => {
297
- this.currentNavigation = Object.assign(Object.assign({}, this.currentNavigation), { finalUrl: t.urlAfterRedirects });
298
- }),
299
- // Recognize
300
- recognize(this.rootComponentType, this.config, (url) => this.serializeUrl(url), this.paramsInheritanceStrategy, this.relativeLinkResolution),
301
- // Update URL if in `eager` update mode
302
- tap(t => {
303
- if (this.urlUpdateStrategy === 'eager') {
304
- if (!t.extras.skipLocationChange) {
305
- this.setBrowserUrl(t.urlAfterRedirects, t);
306
- // TODO(atscott): The above line is incorrect. It sets the url to
307
- // only the part that is handled by the router. It should merge
308
- // that with the rawUrl so the url includes segments not handled
309
- // by the router:
310
- // const rawUrl = this.urlHandlingStrategy.merge(
311
- // t.urlAfterRedirects, t.rawUrl);
312
- // this.setBrowserUrl(rawUrl, t);
313
- }
314
- this.browserUrlTree = t.urlAfterRedirects;
315
- }
316
- // Fire RoutesRecognized
317
- const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
318
- eventsSubject.next(routesRecognized);
319
- }));
320
- }
321
- else {
322
- const processPreviousUrl = urlTransition && this.rawUrlTree &&
323
- this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree);
324
- /* When the current URL shouldn't be processed, but the previous one was,
325
- * we handle this "error condition" by navigating to the previously
326
- * successful URL, but leaving the URL intact.*/
327
- if (processPreviousUrl) {
328
- const { id, extractedUrl, source, restoredState, extras } = t;
329
- const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, restoredState);
330
- eventsSubject.next(navStart);
331
- const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
332
- return of(Object.assign(Object.assign({}, t), { targetSnapshot, urlAfterRedirects: extractedUrl, extras: Object.assign(Object.assign({}, extras), { skipLocationChange: false, replaceUrl: false }) }));
333
- }
334
- else {
335
- /* When neither the current or previous URL can be processed, do nothing
336
- * other than update router's internal reference to the current "settled"
337
- * URL. This way the next navigation will be coming from the current URL
338
- * in the browser.
339
- */
340
- this.rawUrlTree = t.rawUrl;
341
- this.browserUrlTree = t.urlAfterRedirects;
342
- t.resolve(null);
343
- return EMPTY;
344
- }
345
- }
346
- }),
347
- // Before Preactivation
348
- switchTap(t => {
349
- const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
350
- return this.hooks.beforePreactivation(targetSnapshot, {
351
- navigationId,
352
- appliedUrlTree,
353
- rawUrlTree,
354
- skipLocationChange: !!skipLocationChange,
355
- replaceUrl: !!replaceUrl,
356
- });
357
- }),
358
- // --- GUARDS ---
359
- tap(t => {
360
- const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
361
- this.triggerEvent(guardsStart);
362
- }), map(t => (Object.assign(Object.assign({}, t), { guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts) }))), checkGuards(this.ngModule.injector, (evt) => this.triggerEvent(evt)), tap(t => {
363
- if (isUrlTree(t.guardsResult)) {
364
- const error = navigationCancelingError(`Redirecting to "${this.serializeUrl(t.guardsResult)}"`);
365
- error.url = t.guardsResult;
366
- throw error;
367
- }
368
- const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
369
- this.triggerEvent(guardsEnd);
370
- }), filter(t => {
371
- if (!t.guardsResult) {
372
- this.restoreHistory(t);
373
- this.cancelNavigationTransition(t, '');
374
- return false;
375
- }
376
- return true;
377
- }),
378
- // --- RESOLVE ---
379
- switchTap(t => {
380
- if (t.guards.canActivateChecks.length) {
381
- return of(t).pipe(tap(t => {
382
- const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
383
- this.triggerEvent(resolveStart);
384
- }), switchMap(t => {
385
- let dataResolved = false;
386
- return of(t).pipe(resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), tap({
387
- next: () => dataResolved = true,
388
- complete: () => {
389
- if (!dataResolved) {
390
- this.restoreHistory(t);
391
- this.cancelNavigationTransition(t, `At least one route resolver didn't emit any value.`);
392
- }
393
- }
394
- }));
395
- }), tap(t => {
396
- const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
397
- this.triggerEvent(resolveEnd);
398
- }));
399
- }
400
- return undefined;
401
- }),
402
- // --- AFTER PREACTIVATION ---
403
- switchTap((t) => {
404
- const { targetSnapshot, id: navigationId, extractedUrl: appliedUrlTree, rawUrl: rawUrlTree, extras: { skipLocationChange, replaceUrl } } = t;
405
- return this.hooks.afterPreactivation(targetSnapshot, {
406
- navigationId,
407
- appliedUrlTree,
408
- rawUrlTree,
409
- skipLocationChange: !!skipLocationChange,
410
- replaceUrl: !!replaceUrl,
411
- });
412
- }), map((t) => {
413
- const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
414
- return (Object.assign(Object.assign({}, t), { targetRouterState }));
415
- }),
416
- /* Once here, we are about to activate syncronously. The assumption is this
417
- will succeed, and user code may read from the Router service. Therefore
418
- before activation, we need to update router properties storing the current
419
- URL and the RouterState, as well as updated the browser URL. All this should
420
- happen *before* activating. */
421
- tap((t) => {
422
- this.currentUrlTree = t.urlAfterRedirects;
423
- this.rawUrlTree =
424
- this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
425
- this.routerState = t.targetRouterState;
426
- if (this.urlUpdateStrategy === 'deferred') {
427
- if (!t.extras.skipLocationChange) {
428
- this.setBrowserUrl(this.rawUrlTree, t);
429
- }
430
- this.browserUrlTree = t.urlAfterRedirects;
431
- }
432
- }), activateRoutes(this.rootContexts, this.routeReuseStrategy, (evt) => this.triggerEvent(evt)), tap({
433
- next() {
434
- completed = true;
435
- },
436
- complete() {
437
- completed = true;
438
- }
439
- }), finalize(() => {
440
- /* When the navigation stream finishes either through error or success, we
441
- * set the `completed` or `errored` flag. However, there are some situations
442
- * where we could get here without either of those being set. For instance, a
443
- * redirect during NavigationStart. Therefore, this is a catch-all to make
444
- * sure the NavigationCancel
445
- * event is fired when a navigation gets cancelled but not caught by other
446
- * means. */
447
- if (!completed && !errored) {
448
- const cancelationReason = `Navigation ID ${t.id} is not equal to the current navigation id ${this.navigationId}`;
449
- if (this.canceledNavigationResolution === 'replace') {
450
- // Must reset to current URL tree here to ensure history.state is set. On
451
- // a fresh page load, if a new navigation comes in before a successful
452
- // navigation completes, there will be nothing in
453
- // history.state.navigationId. This can cause sync problems with
454
- // AngularJS sync code which looks for a value here in order to determine
455
- // whether or not to handle a given popstate event or to leave it to the
456
- // Angular router.
457
- this.restoreHistory(t);
458
- this.cancelNavigationTransition(t, cancelationReason);
459
- }
460
- else {
461
- // We cannot trigger a `location.historyGo` if the
462
- // cancellation was due to a new navigation before the previous could
463
- // complete. This is because `location.historyGo` triggers a `popstate`
464
- // which would also trigger another navigation. Instead, treat this as a
465
- // redirect and do not reset the state.
466
- this.cancelNavigationTransition(t, cancelationReason);
467
- // TODO(atscott): The same problem happens here with a fresh page load
468
- // and a new navigation before that completes where we won't set a page
469
- // id.
470
- }
471
- }
472
- // currentNavigation should always be reset to null here. If navigation was
473
- // successful, lastSuccessfulTransition will have already been set. Therefore
474
- // we can safely set currentNavigation to null here.
475
- this.currentNavigation = null;
476
- }), catchError((e) => {
477
- // TODO(atscott): The NavigationTransition `t` used here does not accurately
478
- // reflect the current state of the whole transition because some operations
479
- // return a new object rather than modifying the one in the outermost
480
- // `switchMap`.
481
- // The fix can likely be to:
482
- // 1. Rename the outer `t` variable so it's not shadowed all the time and
483
- // confusing
484
- // 2. Keep reassigning to the outer variable after each stage to ensure it
485
- // gets updated. Or change the implementations to not return a copy.
486
- // Not changed yet because it affects existing code and would need to be
487
- // tested more thoroughly.
488
- errored = true;
489
- /* This error type is issued during Redirect, and is handled as a
490
- * cancellation rather than an error. */
491
- if (isNavigationCancelingError(e)) {
492
- const redirecting = isUrlTree(e.url);
493
- if (!redirecting) {
494
- // Set property only if we're not redirecting. If we landed on a page and
495
- // redirect to `/` route, the new navigation is going to see the `/`
496
- // isn't a change from the default currentUrlTree and won't navigate.
497
- // This is only applicable with initial navigation, so setting
498
- // `navigated` only when not redirecting resolves this scenario.
499
- this.navigated = true;
500
- this.restoreHistory(t, true);
501
- }
502
- const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), e.message);
503
- eventsSubject.next(navCancel);
504
- // When redirecting, we need to delay resolving the navigation
505
- // promise and push it to the redirect navigation
506
- if (!redirecting) {
507
- t.resolve(false);
508
- }
509
- else {
510
- // setTimeout is required so this navigation finishes with
511
- // the return EMPTY below. If it isn't allowed to finish
512
- // processing, there can be multiple navigations to the same
513
- // URL.
514
- setTimeout(() => {
515
- const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
516
- const extras = {
517
- skipLocationChange: t.extras.skipLocationChange,
518
- // The URL is already updated at this point if we have 'eager' URL
519
- // updates or if the navigation was triggered by the browser (back
520
- // button, URL bar, etc). We want to replace that item in history if
521
- // the navigation is rejected.
522
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
523
- isBrowserTriggeredNavigation(t.source)
524
- };
525
- this.scheduleNavigation(mergedTree, 'imperative', null, extras, { resolve: t.resolve, reject: t.reject, promise: t.promise });
526
- }, 0);
527
- }
528
- /* All other errors should reset to the router's internal URL reference to
529
- * the pre-error state. */
530
- }
531
- else {
532
- this.restoreHistory(t, true);
533
- const navError = new NavigationError(t.id, this.serializeUrl(t.extractedUrl), e);
534
- eventsSubject.next(navError);
535
- try {
536
- t.resolve(this.errorHandler(e));
537
- }
538
- catch (ee) {
539
- t.reject(ee);
540
- }
541
- }
542
- return EMPTY;
543
- }));
544
- // TODO(jasonaden): remove cast once g3 is on updated TypeScript
545
- }));
546
- }
547
- /**
548
- * @internal
549
- * TODO: this should be removed once the constructor of the router made internal
550
- */
551
- resetRootComponentType(rootComponentType) {
552
- this.rootComponentType = rootComponentType;
553
- // TODO: vsavkin router 4.0 should make the root component set to null
554
- // this will simplify the lifecycle of the router.
555
- this.routerState.root.component = this.rootComponentType;
556
- }
557
- getTransition() {
558
- const transition = this.transitions.value;
559
- // TODO(atscott): This comment doesn't make it clear why this value needs to be set. In the case
560
- // described below (where we don't handle previous or current url), the `browserUrlTree` is set
561
- // to the `urlAfterRedirects` value. However, these values *are already the same* because of the
562
- // line below. So it seems that we should be able to remove the line below and the line where
563
- // `browserUrlTree` is updated when we aren't handling any part of the navigation url.
564
- // Run TGP to confirm that this can be done.
565
- // This value needs to be set. Other values such as extractedUrl are set on initial navigation
566
- // but the urlAfterRedirects may not get set if we aren't processing the new URL *and* not
567
- // processing the previous URL.
568
- transition.urlAfterRedirects = this.browserUrlTree;
569
- return transition;
570
- }
571
- setTransition(t) {
572
- this.transitions.next(Object.assign(Object.assign({}, this.getTransition()), t));
573
- }
574
- /**
575
- * Sets up the location change listener and performs the initial navigation.
576
- */
577
- initialNavigation() {
578
- this.setUpLocationChangeListener();
579
- if (this.navigationId === 0) {
580
- this.navigateByUrl(this.location.path(true), { replaceUrl: true });
581
- }
582
- }
583
- /**
584
- * Sets up the location change listener. This listener detects navigations triggered from outside
585
- * the Router (the browser back/forward buttons, for example) and schedules a corresponding Router
586
- * navigation so that the correct events, guards, etc. are triggered.
587
- */
588
- setUpLocationChangeListener() {
589
- // Don't need to use Zone.wrap any more, because zone.js
590
- // already patch onPopState, so location change callback will
591
- // run into ngZone
592
- if (!this.locationSubscription) {
593
- this.locationSubscription = this.location.subscribe(event => {
594
- const currentChange = this.extractLocationChangeInfoFromEvent(event);
595
- // The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
596
- // hybrid apps.
597
- if (this.shouldScheduleNavigation(this.lastLocationChangeInfo, currentChange)) {
598
- setTimeout(() => {
599
- const { source, state, urlTree } = currentChange;
600
- const extras = { replaceUrl: true };
601
- if (state) {
602
- const stateCopy = Object.assign({}, state);
603
- delete stateCopy.navigationId;
604
- delete stateCopy.ɵrouterPageId;
605
- if (Object.keys(stateCopy).length !== 0) {
606
- extras.state = stateCopy;
607
- }
608
- }
609
- this.scheduleNavigation(urlTree, source, state, extras);
610
- }, 0);
611
- }
612
- this.lastLocationChangeInfo = currentChange;
613
- });
614
- }
615
- }
616
- /** Extracts router-related information from a `PopStateEvent`. */
617
- extractLocationChangeInfoFromEvent(change) {
618
- var _a;
619
- return {
620
- source: change['type'] === 'popstate' ? 'popstate' : 'hashchange',
621
- urlTree: this.parseUrl(change['url']),
622
- // Navigations coming from Angular router have a navigationId state
623
- // property. When this exists, restore the state.
624
- state: ((_a = change.state) === null || _a === void 0 ? void 0 : _a.navigationId) ? change.state : null,
625
- transitionId: this.getTransition().id
626
- };
627
- }
628
- /**
629
- * Determines whether two events triggered by the Location subscription are due to the same
630
- * navigation. The location subscription can fire two events (popstate and hashchange) for a
631
- * single navigation. The second one should be ignored, that is, we should not schedule another
632
- * navigation in the Router.
633
- */
634
- shouldScheduleNavigation(previous, current) {
635
- if (!previous)
636
- return true;
637
- const sameDestination = current.urlTree.toString() === previous.urlTree.toString();
638
- const eventsOccurredAtSameTime = current.transitionId === previous.transitionId;
639
- if (!eventsOccurredAtSameTime || !sameDestination) {
640
- return true;
641
- }
642
- if ((current.source === 'hashchange' && previous.source === 'popstate') ||
643
- (current.source === 'popstate' && previous.source === 'hashchange')) {
644
- return false;
645
- }
646
- return true;
647
- }
648
- /** The current URL. */
649
- get url() {
650
- return this.serializeUrl(this.currentUrlTree);
651
- }
652
- /**
653
- * Returns the current `Navigation` object when the router is navigating,
654
- * and `null` when idle.
655
- */
656
- getCurrentNavigation() {
657
- return this.currentNavigation;
658
- }
659
- /** @internal */
660
- triggerEvent(event) {
661
- this.events.next(event);
662
- }
663
- /**
664
- * Resets the route configuration used for navigation and generating links.
665
- *
666
- * @param config The route array for the new configuration.
667
- *
668
- * @usageNotes
669
- *
670
- * ```
671
- * router.resetConfig([
672
- * { path: 'team/:id', component: TeamCmp, children: [
673
- * { path: 'simple', component: SimpleCmp },
674
- * { path: 'user/:name', component: UserCmp }
675
- * ]}
676
- * ]);
677
- * ```
678
- */
679
- resetConfig(config) {
680
- validateConfig(config);
681
- this.config = config.map(standardizeConfig);
682
- this.navigated = false;
683
- this.lastSuccessfulId = -1;
684
- }
685
- /** @nodoc */
686
- ngOnDestroy() {
687
- this.dispose();
688
- }
689
- /** Disposes of the router. */
690
- dispose() {
691
- this.transitions.complete();
692
- if (this.locationSubscription) {
693
- this.locationSubscription.unsubscribe();
694
- this.locationSubscription = undefined;
695
- }
696
- this.disposed = true;
697
- }
698
- /**
699
- * Appends URL segments to the current URL tree to create a new URL tree.
700
- *
701
- * @param commands An array of URL fragments with which to construct the new URL tree.
702
- * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
703
- * segments, followed by the parameters for each segment.
704
- * The fragments are applied to the current URL tree or the one provided in the `relativeTo`
705
- * property of the options object, if supplied.
706
- * @param navigationExtras Options that control the navigation strategy.
707
- * @returns The new URL tree.
708
- *
709
- * @usageNotes
710
- *
711
- * ```
712
- * // create /team/33/user/11
713
- * router.createUrlTree(['/team', 33, 'user', 11]);
714
- *
715
- * // create /team/33;expand=true/user/11
716
- * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
717
- *
718
- * // you can collapse static segments like this (this works only with the first passed-in value):
719
- * router.createUrlTree(['/team/33/user', userId]);
720
- *
721
- * // If the first segment can contain slashes, and you do not want the router to split it,
722
- * // you can do the following:
723
- * router.createUrlTree([{segmentPath: '/one/two'}]);
724
- *
725
- * // create /team/33/(user/11//right:chat)
726
- * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
727
- *
728
- * // remove the right secondary node
729
- * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
730
- *
731
- * // assuming the current url is `/team/33/user/11` and the route points to `user/11`
732
- *
733
- * // navigate to /team/33/user/11/details
734
- * router.createUrlTree(['details'], {relativeTo: route});
735
- *
736
- * // navigate to /team/33/user/22
737
- * router.createUrlTree(['../22'], {relativeTo: route});
738
- *
739
- * // navigate to /team/44/user/22
740
- * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
741
- *
742
- * Note that a value of `null` or `undefined` for `relativeTo` indicates that the
743
- * tree should be created relative to the root.
744
- * ```
745
- */
746
- createUrlTree(commands, navigationExtras = {}) {
747
- const { relativeTo, queryParams, fragment, queryParamsHandling, preserveFragment } = navigationExtras;
748
- const a = relativeTo || this.routerState.root;
749
- const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
750
- let q = null;
751
- switch (queryParamsHandling) {
752
- case 'merge':
753
- q = Object.assign(Object.assign({}, this.currentUrlTree.queryParams), queryParams);
754
- break;
755
- case 'preserve':
756
- q = this.currentUrlTree.queryParams;
757
- break;
758
- default:
759
- q = queryParams || null;
760
- }
761
- if (q !== null) {
762
- q = this.removeEmptyProps(q);
763
- }
764
- return createUrlTree(a, this.currentUrlTree, commands, q, f !== null && f !== void 0 ? f : null);
765
- }
766
- /**
767
- * Navigates to a view using an absolute route path.
768
- *
769
- * @param url An absolute path for a defined route. The function does not apply any delta to the
770
- * current URL.
771
- * @param extras An object containing properties that modify the navigation strategy.
772
- *
773
- * @returns A Promise that resolves to 'true' when navigation succeeds,
774
- * to 'false' when navigation fails, or is rejected on error.
775
- *
776
- * @usageNotes
777
- *
778
- * The following calls request navigation to an absolute path.
779
- *
780
- * ```
781
- * router.navigateByUrl("/team/33/user/11");
782
- *
783
- * // Navigate without updating the URL
784
- * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
785
- * ```
786
- *
787
- * @see [Routing and Navigation guide](guide/router)
788
- *
789
- */
790
- navigateByUrl(url, extras = {
791
- skipLocationChange: false
792
- }) {
793
- if (typeof ngDevMode === 'undefined' ||
794
- ngDevMode && this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
795
- this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
796
- }
797
- const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
798
- const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
799
- return this.scheduleNavigation(mergedTree, 'imperative', null, extras);
800
- }
801
- /**
802
- * Navigate based on the provided array of commands and a starting point.
803
- * If no starting route is provided, the navigation is absolute.
804
- *
805
- * @param commands An array of URL fragments with which to construct the target URL.
806
- * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
807
- * segments, followed by the parameters for each segment.
808
- * The fragments are applied to the current URL or the one provided in the `relativeTo` property
809
- * of the options object, if supplied.
810
- * @param extras An options object that determines how the URL should be constructed or
811
- * interpreted.
812
- *
813
- * @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation
814
- * fails,
815
- * or is rejected on error.
816
- *
817
- * @usageNotes
818
- *
819
- * The following calls request navigation to a dynamic route path relative to the current URL.
820
- *
821
- * ```
822
- * router.navigate(['team', 33, 'user', 11], {relativeTo: route});
823
- *
824
- * // Navigate without updating the URL, overriding the default behavior
825
- * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
826
- * ```
827
- *
828
- * @see [Routing and Navigation guide](guide/router)
829
- *
830
- */
831
- navigate(commands, extras = { skipLocationChange: false }) {
832
- validateCommands(commands);
833
- return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
834
- }
835
- /** Serializes a `UrlTree` into a string */
836
- serializeUrl(url) {
837
- return this.urlSerializer.serialize(url);
838
- }
839
- /** Parses a string into a `UrlTree` */
840
- parseUrl(url) {
841
- let urlTree;
842
- try {
843
- urlTree = this.urlSerializer.parse(url);
844
- }
845
- catch (e) {
846
- urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url);
847
- }
848
- return urlTree;
849
- }
850
- isActive(url, matchOptions) {
851
- let options;
852
- if (matchOptions === true) {
853
- options = Object.assign({}, exactMatchOptions);
854
- }
855
- else if (matchOptions === false) {
856
- options = Object.assign({}, subsetMatchOptions);
857
- }
858
- else {
859
- options = matchOptions;
860
- }
861
- if (isUrlTree(url)) {
862
- return containsTree(this.currentUrlTree, url, options);
863
- }
864
- const urlTree = this.parseUrl(url);
865
- return containsTree(this.currentUrlTree, urlTree, options);
866
- }
867
- removeEmptyProps(params) {
868
- return Object.keys(params).reduce((result, key) => {
869
- const value = params[key];
870
- if (value !== null && value !== undefined) {
871
- result[key] = value;
872
- }
873
- return result;
874
- }, {});
875
- }
876
- processNavigations() {
877
- this.navigations.subscribe(t => {
878
- this.navigated = true;
879
- this.lastSuccessfulId = t.id;
880
- this.currentPageId = t.targetPageId;
881
- this.events
882
- .next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
883
- this.lastSuccessfulNavigation = this.currentNavigation;
884
- t.resolve(true);
885
- }, e => {
886
- this.console.warn(`Unhandled Navigation Error: ${e}`);
887
- });
888
- }
889
- scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
890
- var _a, _b;
891
- if (this.disposed) {
892
- return Promise.resolve(false);
893
- }
894
- // * Imperative navigations (router.navigate) might trigger additional navigations to the same
895
- // URL via a popstate event and the locationChangeListener. We should skip these duplicate
896
- // navs. Duplicates may also be triggered by attempts to sync AngularJS and Angular router
897
- // states.
898
- // * Imperative navigations can be cancelled by router guards, meaning the URL won't change. If
899
- // the user follows that with a navigation using the back/forward button or manual URL change,
900
- // the destination may be the same as the previous imperative attempt. We should not skip
901
- // these navigations because it's a separate case from the one above -- it's not a duplicate
902
- // navigation.
903
- const lastNavigation = this.getTransition();
904
- // We don't want to skip duplicate successful navs if they're imperative because
905
- // onSameUrlNavigation could be 'reload' (so the duplicate is intended).
906
- const browserNavPrecededByRouterNav = isBrowserTriggeredNavigation(source) && lastNavigation &&
907
- !isBrowserTriggeredNavigation(lastNavigation.source);
908
- const lastNavigationSucceeded = this.lastSuccessfulId === lastNavigation.id;
909
- // If the last navigation succeeded or is in flight, we can use the rawUrl as the comparison.
910
- // However, if it failed, we should compare to the final result (urlAfterRedirects).
911
- const lastNavigationUrl = (lastNavigationSucceeded || this.currentNavigation) ?
912
- lastNavigation.rawUrl :
913
- lastNavigation.urlAfterRedirects;
914
- const duplicateNav = lastNavigationUrl.toString() === rawUrl.toString();
915
- if (browserNavPrecededByRouterNav && duplicateNav) {
916
- return Promise.resolve(true); // return value is not used
917
- }
918
- let resolve;
919
- let reject;
920
- let promise;
921
- if (priorPromise) {
922
- resolve = priorPromise.resolve;
923
- reject = priorPromise.reject;
924
- promise = priorPromise.promise;
925
- }
926
- else {
927
- promise = new Promise((res, rej) => {
928
- resolve = res;
929
- reject = rej;
930
- });
931
- }
932
- const id = ++this.navigationId;
933
- let targetPageId;
934
- if (this.canceledNavigationResolution === 'computed') {
935
- const isInitialPage = this.currentPageId === 0;
936
- if (isInitialPage) {
937
- restoredState = this.location.getState();
938
- }
939
- // If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
940
- // `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
941
- // target id to the previously set value for that page.
942
- if (restoredState && restoredState.ɵrouterPageId) {
943
- targetPageId = restoredState.ɵrouterPageId;
944
- }
945
- else {
946
- // If we're replacing the URL or doing a silent navigation, we do not want to increment the
947
- // page id because we aren't pushing a new entry to history.
948
- if (extras.replaceUrl || extras.skipLocationChange) {
949
- targetPageId = (_a = this.browserPageId) !== null && _a !== void 0 ? _a : 0;
950
- }
951
- else {
952
- targetPageId = ((_b = this.browserPageId) !== null && _b !== void 0 ? _b : 0) + 1;
953
- }
954
- }
955
- }
956
- else {
957
- // This is unused when `canceledNavigationResolution` is not computed.
958
- targetPageId = 0;
959
- }
960
- this.setTransition({
961
- id,
962
- targetPageId,
963
- source,
964
- restoredState,
965
- currentUrlTree: this.currentUrlTree,
966
- currentRawUrl: this.rawUrlTree,
967
- rawUrl,
968
- extras,
969
- resolve,
970
- reject,
971
- promise,
972
- currentSnapshot: this.routerState.snapshot,
973
- currentRouterState: this.routerState
974
- });
975
- // Make sure that the error is propagated even though `processNavigations` catch
976
- // handler does not rethrow
977
- return promise.catch((e) => {
978
- return Promise.reject(e);
979
- });
980
- }
981
- setBrowserUrl(url, t) {
982
- const path = this.urlSerializer.serialize(url);
983
- const state = Object.assign(Object.assign({}, t.extras.state), this.generateNgRouterState(t.id, t.targetPageId));
984
- if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) {
985
- this.location.replaceState(path, '', state);
986
- }
987
- else {
988
- this.location.go(path, '', state);
989
- }
990
- }
991
- /**
992
- * Performs the necessary rollback action to restore the browser URL to the
993
- * state before the transition.
994
- */
995
- restoreHistory(t, restoringFromCaughtError = false) {
996
- var _a, _b;
997
- if (this.canceledNavigationResolution === 'computed') {
998
- const targetPagePosition = this.currentPageId - t.targetPageId;
999
- // The navigator change the location before triggered the browser event,
1000
- // so we need to go back to the current url if the navigation is canceled.
1001
- // Also, when navigation gets cancelled while using url update strategy eager, then we need to
1002
- // go back. Because, when `urlUpdateSrategy` is `eager`; `setBrowserUrl` method is called
1003
- // before any verification.
1004
- const browserUrlUpdateOccurred = (t.source === 'popstate' || this.urlUpdateStrategy === 'eager' ||
1005
- this.currentUrlTree === ((_a = this.currentNavigation) === null || _a === void 0 ? void 0 : _a.finalUrl));
1006
- if (browserUrlUpdateOccurred && targetPagePosition !== 0) {
1007
- this.location.historyGo(targetPagePosition);
1008
- }
1009
- else if (this.currentUrlTree === ((_b = this.currentNavigation) === null || _b === void 0 ? void 0 : _b.finalUrl) && targetPagePosition === 0) {
1010
- // We got to the activation stage (where currentUrlTree is set to the navigation's
1011
- // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
1012
- // We still need to reset the router state back to what it was when the navigation started.
1013
- this.resetState(t);
1014
- // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
1015
- // Investigate if this can be done by running TGP.
1016
- this.browserUrlTree = t.currentUrlTree;
1017
- this.resetUrlToCurrentUrlTree();
1018
- }
1019
- else {
1020
- // The browser URL and router state was not updated before the navigation cancelled so
1021
- // there's no restoration needed.
1022
- }
1023
- }
1024
- else if (this.canceledNavigationResolution === 'replace') {
1025
- // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
1026
- // for `deferred` navigations that haven't change the internal state yet because guards
1027
- // reject. For 'eager' navigations, it seems like we also really should reset the state
1028
- // because the navigation was cancelled. Investigate if this can be done by running TGP.
1029
- if (restoringFromCaughtError) {
1030
- this.resetState(t);
1031
- }
1032
- this.resetUrlToCurrentUrlTree();
1033
- }
1034
- }
1035
- resetState(t) {
1036
- this.routerState = t.currentRouterState;
1037
- this.currentUrlTree = t.currentUrlTree;
1038
- this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
1039
- }
1040
- resetUrlToCurrentUrlTree() {
1041
- this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
1042
- }
1043
- cancelNavigationTransition(t, reason) {
1044
- const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason);
1045
- this.triggerEvent(navCancel);
1046
- t.resolve(false);
1047
- }
1048
- generateNgRouterState(navigationId, routerPageId) {
1049
- if (this.canceledNavigationResolution === 'computed') {
1050
- return { navigationId, ɵrouterPageId: routerPageId };
1051
- }
1052
- return { navigationId };
1053
- }
1054
- }
1055
- Router.decorators = [
1056
- { type: Injectable }
1057
- ];
1058
- Router.ctorParameters = () => [
1059
- { type: Type },
1060
- { type: UrlSerializer },
1061
- { type: ChildrenOutletContexts },
1062
- { type: Location },
1063
- { type: Injector },
1064
- { type: NgModuleFactoryLoader },
1065
- { type: Compiler },
1066
- { type: undefined }
1067
- ];
1068
- function validateCommands(commands) {
1069
- for (let i = 0; i < commands.length; i++) {
1070
- const cmd = commands[i];
1071
- if (cmd == null) {
1072
- throw new Error(`The requested path contains ${cmd} segment at index ${i}`);
1073
- }
1074
- }
1075
- }
1076
- function isBrowserTriggeredNavigation(source) {
1077
- return source !== 'imperative';
1078
- }
1079
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFFBQVEsRUFBZ0IsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUscUJBQXFCLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsUUFBUSxJQUFJLE9BQU8sRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNwSSxPQUFPLEVBQUMsZUFBZSxFQUFFLEtBQUssRUFBYyxFQUFFLEVBQUUsT0FBTyxFQUFtQixNQUFNLE1BQU0sQ0FBQztBQUN2RixPQUFPLEVBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUdqRixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDaEQsT0FBTyxFQUFRLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBcUIsVUFBVSxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxvQkFBb0IsRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUM3TyxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLDZCQUE2QixDQUFDO0FBQzNELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDaEQsT0FB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QUksRUFBRTtZQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLEdBQUcscUJBQXFCLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDN0U7S0FDRjtBQUNILENBQUM7QUFFRCxTQUFTLDRCQUE0QixDQUFDLE1BQTRDO0lBQ2hGLE9BQU8sTUFBTSxLQUFLLFlBQVksQ0FBQztBQUNqQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7TG9jYXRpb24sIFBvcFN0YXRlRXZlbnR9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge0NvbXBpbGVyLCBJbmplY3RhYmxlLCBJbmplY3RvciwgTmdNb2R1bGVGYWN0b3J5TG9hZGVyLCBOZ01vZHVsZVJlZiwgTmdab25lLCBUeXBlLCDJtUNvbnNvbGUgYXMgQ29uc29sZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgRU1QVFksIE9ic2VydmFibGUsIG9mLCBTdWJqZWN0LCBTdWJzY3JpcHRpb25MaWtlfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Y2F0Y2hFcnJvciwgZmlsdGVyLCBmaW5hbGl6ZSwgbWFwLCBzd2l0Y2hNYXAsIHRhcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge1F1ZXJ5UGFyYW1zSGFuZGxpbmcsIFJvdXRlLCBSb3V0ZXN9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7Y3JlYXRlUm91dGVyU3RhdGV9IGZyb20gJy4vY3JlYXRlX3JvdXRlcl9zdGF0ZSc7XG5pbXBvcnQge2NyZWF0ZVVybFRyZWV9IGZyb20gJy4vY3JlYXRlX3VybF90cmVlJztcbmltcG9ydCB7RXZlbnQsIEd1YXJkc0NoZWNrRW5kLCBHdWFyZHNDaGVja1N0YXJ0LCBOYXZpZ2F0aW9uQ2FuY2VsLCBOYXZpZ2F0aW9uRW5kLCBOYXZpZ2F0aW9uRXJyb3IsIE5hdmlnYXRpb25TdGFydCwgTmF2aWdhdGlvblRyaWdnZXIsIFJlc29sdmVFbmQsIFJlc29sdmVTdGFydCwgUm91dGVDb25maWdMb2FkRW5kLCBSb3V0ZUNvbmZpZ0xvYWRTdGFydCwgUm91dGVzUmVjb2duaXplZH0gZnJvbSAnLi9ldmVudHMnO1xuaW1wb3J0IHthY3RpdmF0ZVJvdXRlc30gZnJvbSAnLi9vcGVyYXRvcnMvYWN0aXZhdGVfcm91dGVzJztcbmltcG9ydCB7YXBwbHlSZWRpcmVjdHN9IGZyb20gJy4vb3BlcmF0b3JzL2FwcGx5X3JlZGlyZWN0cyc7XG5pbXBvcnQge2NoZWNrR3VhcmRzfSBmcm9tICcuL29wZXJhdG9ycy9jaGVja19ndWFyZHMnO1xuaW1wb3J0IHtyZWNvZ25pemV9IGZyb20gJy4vb3BlcmF0b3JzL3JlY29nbml6ZSc7XG5pbXBvcnQge3Jlc29sdmVEYXRhfSBmcm9tICcuL29wZXJhdG9ycy9yZXNvbHZlX2RhdGEnO1xuaW1wb3J0IHtzd2l0Y2hUYXB9IGZyb20gJy4vb3BlcmF0b3JzL3N3aXRjaF90YXAnO1xuaW1wb3J0IHtEZWZhdWx0Um91dGVSZXVzZVN0cmF0ZWd5LCBSb3V0ZVJldXNlU3RyYXRlZ3l9IGZyb20gJy4vcm91dGVfcmV1c2Vfc3RyYXRlZ3knO1xuaW1wb3J0IHtSb3V0ZXJDb25maWdMb2FkZXJ9IGZyb20gJy4vcm91dGVyX2NvbmZpZ19sb2FkZXInO1xuaW1wb3J0IHtDaGlsZHJlbk91dGxldENvbnRleHRzfSBmcm9tICcuL3JvdXRlcl9vdXRsZXRfY29udGV4dCc7XG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBjcmVhdGVFbXB0eVN0YXRlLCBSb3V0ZXJTdGF0ZSwgUm91dGVyU3RhdGVTbmFwc2hvdH0gZnJvbSAnLi9yb3V0ZXJfc3RhdGUnO1xuaW1wb3J0IHtpc05hdmlnYXRpb25DYW5jZWxpbmdFcnJvciwgbmF2aWdhdGlvbkNhbmNlbGluZ0Vycm9yLCBQYXJhbXN9IGZyb20gJy4vc2hhcmVkJztcbmltcG9ydCB7RGVmYXVsdFVybEhhbmRsaW5nU3RyYXRlZ3ksIFVybEhhbmRsaW5nU3RyYXRlZ3l9IGZyb20gJy4vdXJsX2hhbmRsaW5nX3N0cmF0ZWd5JztcbmltcG9ydCB7Y29udGFpbnNUcmVlLCBjcmVhdGVFbXB0eVVybFRyZWUsIElzQWN0aXZlTWF0Y2hPcHRpb25zLCBVcmxTZXJpYWxpemVyLCBVcmxUcmVlfSBmcm9tICcuL3VybF90cmVlJztcbmltcG9ydCB7c3RhbmRhcmRpemVDb25maWcsIHZhbGlkYXRlQ29uZmlnfSBmcm9tICcuL3V0aWxzL2NvbmZpZyc7XG5pbXBvcnQge0NoZWNrcywgZ2V0QWxsUm91dGVHdWFyZHN9IGZyb20gJy4vdXRpbHMvcHJlYWN0aXZhdGlvbic7XG5pbXBvcnQge2lzVXJsVHJlZX0gZnJvbSAnLi91dGlscy90eXBlX2d1YXJkcyc7XG5cblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBPcHRpb25zIHRoYXQgbW9kaWZ5IHRoZSBgUm91dGVyYCBVUkwuXG4gKiBTdXBwbHkgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYW55IG9mIHRoZXNlIHByb3BlcnRpZXMgdG8gYSBgUm91dGVyYCBuYXZpZ2F0aW9uIGZ1bmN0aW9uIHRvXG4gKiBjb250cm9sIGhvdyB0aGUgdGFyZ2V0IFVSTCBzaG91bGQgYmUgY29uc3RydWN0ZWQuXG4gKlxuICogQHNlZSBbUm91dGVyLm5hdmlnYXRlKCkgbWV0aG9kXShhcGkvcm91dGVyL1JvdXRlciNuYXZpZ2F0ZSlcbiAqIEBzZWUgW1JvdXRlci5jcmVhdGVVcmxUcmVlKCkgbWV0aG9kXShhcGkvcm91dGVyL1JvdXRlciNjcmVhdGV1cmx0cmVlKVxuICogQHNlZSBbUm91dGluZyBhbmQgTmF2aWdhdGlvbiBndWlkZV0oZ3VpZGUvcm91dGVyKVxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVcmxDcmVhdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogU3BlY2lmaWVzIGEgcm9vdCBVUkkgdG8gdXNlIGZvciByZWxhdGl2ZSBuYXZpZ2F0aW9uLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgY29uc2lkZXIgdGhlIGZvbGxvd2luZyByb3V0ZSBjb25maWd1cmF0aW9uIHdoZXJlIHRoZSBwYXJlbnQgcm91dGVcbiAgICogaGFzIHR3byBjaGlsZHJlbi5cbiAgICpcbiAgICogYGBgXG4gICAqIFt7XG4gICAqICAgcGF0aDogJ3BhcmVudCcsXG4gICAqICAgY29tcG9uZW50OiBQYXJlbnRDb21wb25lbnQsXG4gICAqICAgY2hpbGRyZW46IFt7XG4gICAqICAgICBwYXRoOiAnbGlzdCcsXG4gICAqICAgICBjb21wb25lbnQ6IExpc3RDb21wb25lbnRcbiAgICogICB9LHtcbiAgICogICAgIHBhdGg6ICdjaGlsZCcsXG4gICAqICAgICBjb21wb25lbnQ6IENoaWxkQ29tcG9uZW50XG4gICAqICAgfV1cbiAgICogfV1cbiAgICogYGBgXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgYGdvKClgIGZ1bmN0aW9uIG5hdmlnYXRlcyB0byB0aGUgYGxpc3RgIHJvdXRlIGJ5XG4gICAqIGludGVycHJldGluZyB0aGUgZGVzdGluYXRpb24gVVJJIGFzIHJlbGF0aXZlIHRvIHRoZSBhY3RpdmF0ZWQgYGNoaWxkYCAgcm91dGVcbiAgICpcbiAgICogYGBgXG4gICAqICBAQ29tcG9uZW50KHsuLi59KVxuICAgKiAgY2xhc3MgQ2hpbGRDb21wb25lbnQge1xuICAgKiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJvdXRlcjogUm91dGVyLCBwcml2YXRlIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSkge31cbiAgICpcbiAgICogICAgZ28oKSB7XG4gICAqICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycuLi9saXN0J10sIHsgcmVsYXRpdmVUbzogdGhpcy5yb3V0ZSB9KTtcbiAgICogICAgfVxuICAgKiAgfVxuICAgKiBgYGBcbiAgICpcbiAgICogQSB2YWx1ZSBvZiBgbnVsbGAgb3IgYHVuZGVmaW5lZGAgaW5kaWNhdGVzIHRoYXQgdGhlIG5hdmlnYXRpb24gY29tbWFuZHMgc2hvdWxkIGJlIGFwcGxpZWRcbiAgICogcmVsYXRpdmUgdG8gdGhlIHJvb3QuXG4gICAqL1xuICByZWxhdGl2ZVRvPzogQWN0aXZhdGVkUm91dGV8bnVsbDtcblxuICAvKipcbiAgICogU2V0cyBxdWVyeSBwYXJhbWV0ZXJzIHRvIHRoZSBVUkwuXG4gICAqXG4gICAqIGBgYFxuICAgKiAvLyBOYXZpZ2F0ZSB0byAvcmVzdWx0cz9wYWdlPTFcbiAgICogdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvcmVzdWx0cyddLCB7IHF1ZXJ5UGFyYW1zOiB7IHBhZ2U6IDEgfSB9KTtcbiAgICogYGBgXG4gICAqL1xuICBxdWVyeVBhcmFtcz86IFBhcmFtc3xudWxsO1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBoYXNoIGZyYWdtZW50IGZvciB0aGUgVVJMLlxuICAgKlxuICAgKiBgYGBcbiAgICogLy8gTmF2aWdhdGUgdG8gL3Jlc3VsdHMjdG9wXG4gICAqIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL3Jlc3VsdHMnXSwgeyBmcmFnbWVudDogJ3RvcCcgfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgZnJhZ21lbnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvdyB0byBoYW5kbGUgcXVlcnkgcGFyYW1ldGVycyBpbiB0aGUgcm91dGVyIGxpbmsgZm9yIHRoZSBuZXh0IG5hdmlnYXRpb24uXG4gICAqIE9uZSBvZjpcbiAgICogKiBgcHJlc2VydmVgIDogUHJlc2VydmUgY3VycmVudCBwYXJhbWV0ZXJzLlxuICAgKiAqIGBtZXJnZWAgOiBNZXJnZSBuZXcgd2l0aCBjdXJyZW50IHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIFRoZSBcInByZXNlcnZlXCIgb3B0aW9uIGRpc2NhcmRzIGFueSBuZXcgcXVlcnkgcGFyYW1zOlxuICAgKiBgYGBcbiAgICogLy8gZnJvbSAvdmlldzE/cGFnZT0xIHRvL3ZpZXcyP3BhZ2U9MVxuICAgKiB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy92aWV3MiddLCB7IHF1ZXJ5UGFyYW1zOiB7IHBhZ2U6IDIgfSwgIHF1ZXJ5UGFyYW1zSGFuZGxpbmc6IFwicHJlc2VydmVcIlxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqIFRoZSBcIm1lcmdlXCIgb3B0aW9uIGFwcGVuZHMgbmV3IHF1ZXJ5IHBhcmFtcyB0byB0aGUgcGFyYW1zIGZyb20gdGhlIGN1cnJlbnQgVVJMOlxuICAgKiBgYGBcbiAgICogLy8gZnJvbSAvdmlldzE/cGFnZT0xIHRvL3ZpZXcyP3BhZ2U9MSZvdGhlcktleT0yXG4gICAqIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL3ZpZXcyJ10sIHsgcXVlcnlQYXJhbXM6IHsgb3RoZXJLZXk6IDIgfSwgIHF1ZXJ5UGFyYW1zSGFuZGxpbmc6IFwibWVyZ2VcIlxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqIEluIGNhc2Ugb2YgYSBrZXkgY29sbGlzaW9uIGJldHdlZW4gY3VycmVudCBwYXJhbWV0ZXJzIGFuZCB0aG9zZSBpbiB0aGUgYHF1ZXJ5UGFyYW1zYCBvYmplY3QsXG4gICAqIHRoZSBuZXcgdmFsdWUgaXMgdXNlZC5cbiAgICpcbiAgICovXG4gIHF1ZXJ5UGFyYW1zSGFuZGxpbmc/OiBRdWVyeVBhcmFtc0hhbmRsaW5nfG51bGw7XG5cbiAgLyoqXG4gICAqIFdoZW4gdHJ1ZSwgcHJlc2VydmVzIHRoZSBVUkwgZnJhZ21lbnQgZm9yIHRoZSBuZXh0IG5hdmlnYXRpb25cbiAgICpcbiAgICogYGBgXG4gICAqIC8vIFByZXNlcnZlIGZyYWdtZW50IGZyb20gL3Jlc3VsdHMjdG9wIHRvIC92aWV3I3RvcFxuICAgKiB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy92aWV3J10sIHsgcHJlc2VydmVGcmFnbWVudDogdHJ1ZSB9KTtcbiAgICogYGBgXG4gICAqL1xuICBwcmVzZXJ2ZUZyYWdtZW50PzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBPcHRpb25zIHRoYXQgbW9kaWZ5IHRoZSBgUm91dGVyYCBuYXZpZ2F0aW9uIHN0cmF0ZWd5LlxuICogU3VwcGx5IGFuIG9iamVjdCBjb250YWluaW5nIGFueSBvZiB0aGVzZSBwcm9wZXJ0aWVzIHRvIGEgYFJvdXRlcmAgbmF2aWdhdGlvbiBmdW5jdGlvbiB0b1xuICogY29udHJvbCBob3cgdGhlIG5hdmlnYXRpb24gc2hvdWxkIGJlIGhhbmRsZWQuXG4gKlxuICogQHNlZSBbUm91dGVyLm5hdmlnYXRlKCkgbWV0aG9kXShhcGkvcm91dGVyL1JvdXRlciNuYXZpZ2F0ZSlcbiAqIEBzZWUgW1JvdXRlci5uYXZpZ2F0ZUJ5VXJsKCkgbWV0aG9kXShhcGkvcm91dGVyL1JvdXRlciNuYXZpZ2F0ZWJ5dXJsKVxuICogQHNlZSBbUm91dGluZyBhbmQgTmF2aWdhdGlvbiBndWlkZV0oZ3VpZGUvcm91dGVyKVxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOYXZpZ2F0aW9uQmVoYXZpb3JPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZW4gdHJ1ZSwgbmF2aWdhdGVzIHdpdGhvdXQgcHVzaGluZyBhIG5ldyBzdGF0ZSBpbnRvIGhpc3RvcnkuXG4gICAqXG4gICAqIGBgYFxuICAgKiAvLyBOYXZpZ2F0ZSBzaWxlbnRseSB0byAvdmlld1xuICAgKiB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy92aWV3J10sIHsgc2tpcExvY2F0aW9uQ2hhbmdlOiB0cnVlIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIHNraXBMb2NhdGlvbkNoYW5nZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZW4gdHJ1ZSwgbmF2aWdhdGVzIHdoaWxlIHJlcGxhY2luZyB0aGUgY3VycmVudCBzdGF0ZSBpbiBoaXN0b3J5LlxuICAgKlxuICAgKiBgYGBcbiAgICogLy8gTmF2aWdhdGUgdG8gL3ZpZXdcbiAgICogdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvdmlldyddLCB7IHJlcGxhY2VVcmw6IHRydWUgfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcmVwbGFjZVVybD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIERldmVsb3Blci1kZWZpbmVkIHN0YXRlIHRoYXQgY2FuIGJlIHBhc3NlZCB0byBhbnkgbmF2aWdhdGlvbi5cbiAgICogQWNjZXNzIHRoaXMgdmFsdWUgdGhyb3VnaCB0aGUgYE5hdmlnYXRpb24uZXh0cmFzYCBvYmplY3RcbiAgICogcmV0dXJuZWQgZnJvbSB0aGUgW1JvdXRlci5nZXRDdXJyZW50TmF2aWdhdGlvbigpXG4gICAqIG1ldGhvZF0oYXBpL3JvdXRlci9Sb3V0ZXIjZ2V0Y3VycmVudG5hdmlnYXRpb24pIHdoaWxlIGEgbmF2aWdhdGlvbiBpcyBleGVjdXRpbmcuXG4gICAqXG4gICAqIEFmdGVyIGEgbmF2aWdhdGlvbiBjb21wbGV0ZXMsIHRoZSByb3V0ZXIgd3JpdGVzIGFuIG9iamVjdCBjb250YWluaW5nIHRoaXNcbiAgICogdmFsdWUgdG9nZXRoZXIgd2l0aCBhIGBuYXZpZ2F0aW9uSWRgIHRvIGBoaXN0b3J5LnN0YXRlYC5cbiAgICogVGhlIHZhbHVlIGlzIHdyaXR0ZW4gd2hlbiBgbG9jYXRpb24uZ28oKWAgb3IgYGxvY2F0aW9uLnJlcGxhY2VTdGF0ZSgpYFxuICAgKiBpcyBjYWxsZWQgYmVmb3JlIGFjdGl2YXRpbmcgdGhpcyByb3V0ZS5cbiAgICpcbiAgICogTm90ZSB0aGF0IGBoaXN0b3J5LnN0YXRlYCBkb2VzIG5vdCBwYXNzIGFuIG9iamVjdCBlcXVhbGl0eSB0ZXN0IGJlY2F1c2VcbiAgICogdGhlIHJvdXRlciBhZGRzIHRoZSBgbmF2aWdhdGlvbklkYCBvbiBlYWNoIG5hdmlnYXRpb24uXG4gICAqXG4gICAqL1xuICBzdGF0ZT86IHtbazogc3RyaW5nXTogYW55fTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBPcHRpb25zIHRoYXQgbW9kaWZ5IHRoZSBgUm91dGVyYCBuYXZpZ2F0aW9uIHN0cmF0ZWd5LlxuICogU3VwcGx5IGFuIG9iamVjdCBjb250YWluaW5nIGFueSBvZiB0aGVzZSBwcm9wZXJ0aWVzIHRvIGEgYFJvdXRlcmAgbmF2aWdhdGlvbiBmdW5jdGlvbiB0b1xuICogY29udHJvbCBob3cgdGhlIHRhcmdldCBVUkwgc2hvdWxkIGJlIGNvbnN0cnVjdGVkIG9yIGludGVycHJldGVkLlxuICpcbiAqIEBzZWUgW1JvdXRlci5uYXZpZ2F0ZSgpIG1ldGhvZF0oYXBpL3JvdXRlci9Sb3V0ZXIjbmF2aWdhdGUpXG4gKiBAc2VlIFtSb3V0ZXIubmF2aWdhdGVCeVVybCgpIG1ldGhvZF0oYXBpL3JvdXRlci9Sb3V0ZXIjbmF2aWdhdGVieXVybClcbiAqIEBzZWUgW1JvdXRlci5jcmVhdGVVcmxUcmVlKCkgbWV0aG9kXShhcGkvcm91dGVyL1JvdXRlciNjcmVhdGV1cmx0cmVlKVxuICogQHNlZSBbUm91dGluZyBhbmQgTmF2aWdhdGlvbiBndWlkZV0oZ3VpZGUvcm91dGVyKVxuICogQHNlZSBVcmxDcmVhdGlvbk9wdGlvbnNcbiAqIEBzZWUgTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9uc1xuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOYXZpZ2F0aW9uRXh0cmFzIGV4dGVuZHMgVXJsQ3JlYXRpb25PcHRpb25zLCBOYXZpZ2F0aW9uQmVoYXZpb3JPcHRpb25zIHt9XG5cbi8qKlxuICogRXJyb3IgaGFuZGxlciB0aGF0IGlzIGludm9rZWQgd2hlbiBhIG5hdmlnYXRpb24gZXJyb3Igb2NjdXJzLlxuICpcbiAqIElmIHRoZSBoYW5kbGVyIHJldHVybnMgYSB2YWx1ZSwgdGhlIG5hdmlnYXRpb24gUHJvbWlzZSBpcyByZXNvbHZlZCB3aXRoIHRoaXMgdmFsdWUuXG4gKiBJZiB0aGUgaGFuZGxlciB0aHJvd3MgYW4gZXhjZXB0aW9uLCB0aGUgbmF2aWdhdGlvbiBQcm9taXNlIGlzIHJlamVjdGVkIHdpdGhcbiAqIHRoZSBleGNlcHRpb24uXG4gKlxuICogQHB1YmxpY0FwaVxuICovXG5leHBvcnQgdHlwZSBFcnJvckhhbmRsZXIgPSAoZXJyb3I6IGFueSkgPT4gYW55O1xuXG5mdW5jdGlvbiBkZWZhdWx0RXJyb3JIYW5kbGVyKGVycm9yOiBhbnkpOiBhbnkge1xuICB0aHJvdyBlcnJvcjtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdE1hbGZvcm1lZFVyaUVycm9ySGFuZGxlcihcbiAgICBlcnJvcjogVVJJRXJyb3IsIHVybFNlcmlhbGl6ZXI6IFVybFNlcmlhbGl6ZXIsIHVybDogc3RyaW5nKTogVXJsVHJlZSB7XG4gIHJldHVybiB1cmxTZXJpYWxpemVyLnBhcnNlKCcvJyk7XG59XG5cbmV4cG9ydCB0eXBlIFJlc3RvcmVkU3RhdGUgPSB7XG4gIFtrOiBzdHJpbmddOiBhbnksXG4gIC8vIFRPRE8oIzI3NjA3KTogUmVtb3ZlIGBuYXZpZ2F0aW9uSWRgIGFuZCBgybVyb3V0ZXJQYWdlSWRgIGFuZCBtb3ZlIHRvIGBuZ2Agb3IgYMm1YCBuYW1lc3BhY2UuXG4gIG5hdmlnYXRpb25JZDogbnVtYmVyLFxuICAvLyBUaGUgYMm1YCBwcmVmaXggaXMgdGhlcmUgdG8gcmVkdWNlIHRoZSBjaGFuY2Ugb2YgY29sbGlkaW5nIHdpdGggYW55IGV4aXN0aW5nIHVzZXIgcHJvcGVydGllcyBvblxuICAvLyB0aGUgaGlzdG9yeSBzdGF0ZS5cbiAgybVyb3V0ZXJQYWdlSWQ/OiBudW1iZXIsXG59O1xuXG4vKipcbiAqIEluZm9ybWF0aW9uIGFib3V0IGEgbmF2aWdhdGlvbiBvcGVyYXRpb24uXG4gKiBSZXRyaWV2ZSB0aGUgbW9zdCByZWNlbnQgbmF2aWdhdGlvbiBvYmplY3Qgd2l0aCB0aGVcbiAqIFtSb3V0ZXIuZ2V0Q3VycmVudE5hdmlnYXRpb24oKSBtZXRob2RdKGFwaS9yb3V0ZXIvUm91dGVyI2dldGN1cnJlbnRuYXZpZ2F0aW9uKSAuXG4gKlxuICogKiAqaWQqIDogVGhlIHVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjdXJyZW50IG5hdmlnYXRpb24uXG4gKiAqICppbml0aWFsVXJsKiA6IFRoZSB0YXJnZXQgVVJMIHBhc3NlZCBpbnRvIHRoZSBgUm91dGVyI25hdmlnYXRlQnlVcmwoKWAgY2FsbCBiZWZvcmUgbmF2aWdhdGlvbi5cbiAqIFRoaXMgaXMgdGhlIHZhbHVlIGJlZm9yZSB0aGUgcm91dGVyIGhhcyBwYXJzZWQgb3IgYXBwbGllZCByZWRpcmVjdHMgdG8gaXQuXG4gKiAqICpleHRyYWN0ZWRVcmwqIDogVGhlIGluaXRpYWwgdGFyZ2V0IFVSTCBhZnRlciBiZWluZyBwYXJzZWQgd2l0aCBgVXJsU2VyaWFsaXplci5leHRyYWN0KClgLlxuICogKiAqZmluYWxVcmwqIDogVGhlIGV4dHJhY3RlZCBVUkwgYWZ0ZXIgcmVkaXJlY3RzIGhhdmUgYmVlbiBhcHBsaWVkLlxuICogVGhpcyBVUkwgbWF5IG5vdCBiZSBhdmFpbGFibGUgaW1tZWRpYXRlbHksIHRoZXJlZm9yZSB0aGlzIHByb3BlcnR5IGNhbiBiZSBgdW5kZWZpbmVkYC5cbiAqIEl0IGlzIGd1YXJhbnRlZWQgdG8gYmUgc2V0IGFmdGVyIHRoZSBgUm91dGVzUmVjb2duaXplZGAgZXZlbnQgZmlyZXMuXG4gKiAqICp0cmlnZ2VyKiA6IElkZW50aWZpZXMgaG93IHRoaXMgbmF2aWdhdGlvbiB3YXMgdHJpZ2dlcmVkLlxuICogLS0gJ2ltcGVyYXRpdmUnLS1UcmlnZ2VyZWQgYnkgYHJvdXRlci5uYXZpZ2F0ZUJ5VXJsYCBvciBgcm91dGVyLm5hdmlnYXRlYC5cbiAqIC0tICdwb3BzdGF0ZSctLVRyaWdnZXJlZCBieSBhIHBvcHN0YXRlIGV2ZW50LlxuICogLS0gJ2hhc2hjaGFuZ2UnLS1UcmlnZ2VyZWQgYnkgYSBoYXNoY2hhbmdlIGV2ZW50LlxuICogKiAqZXh0cmFzKiA6IEEgYE5hdmlnYXRpb25FeHRyYXNgIG9wdGlvbnMgb2JqZWN0IHRoYXQgY29udHJvbGxlZCB0aGUgc3RyYXRlZ3kgdXNlZCBmb3IgdGhpc1xuICogbmF2aWdhdGlvbi5cbiAqICogKnByZXZpb3VzTmF2aWdhdGlvbiogOiBUaGUgcHJldmlvdXNseSBzdWNjZXNzZnVsIGBOYXZpZ2F0aW9uYCBvYmplY3QuIE9ubHkgb25lIHByZXZpb3VzXG4gKiBuYXZpZ2F0aW9uIGlzIGF2YWlsYWJsZSwgdGhlcmVmb3JlIHRoaXMgcHJldmlvdXMgYE5hdmlnYXRpb25gIG9iamVjdCBoYXMgYSBgbnVsbGAgdmFsdWUgZm9yIGl0c1xuICogb3duIGBwcmV2aW91c05hdmlnYXRpb25gLlxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOYXZpZ2F0aW9uIHtcbiAgLyoqXG4gICAqIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgY3VycmVudCBuYXZpZ2F0aW9uLlxuICAgKi9cbiAgaWQ6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB0YXJnZXQgVVJMIHBhc3NlZCBpbnRvIHRoZSBgUm91dGVyI25hdmlnYXRlQnlVcmwoKWAgY2FsbCBiZWZvcmUgbmF2aWdhdGlvbi4gVGhpcyBpc1xuICAgKiB0aGUgdmFsdWUgYmVmb3JlIHRoZSByb3V0ZXIgaGFzIHBhcnNlZCBvciBhcHBsaWVkIHJlZGlyZWN0cyB0byBpdC5cbiAgICovXG4gIGluaXRpYWxVcmw6IHN0cmluZ3xVcmxUcmVlO1xuICAvKipcbiAgICogVGhlIGluaXRpYWwgdGFyZ2V0IFVSTCBhZnRlciBiZWluZyBwYXJzZWQgd2l0aCBgVXJsU2VyaWFsaXplci5leHRyYWN0KClgLlxuICAgKi9cbiAgZXh0cmFjdGVkVXJsOiBVcmxUcmVlO1xuICAvKipcbiAgICogVGhlIGV4dHJhY3RlZCBVUkwgYWZ0ZXIgcmVkaXJlY3RzIGhhdmUgYmVlbiBhcHBsaWVkLlxuICAgKiBUaGlzIFVSTCBtYXkgbm90IGJlIGF2YWlsYWJsZSBpbW1lZGlhdGVseSwgdGhlcmVmb3JlIHRoaXMgcHJvcGVydHkgY2FuIGJlIGB1bmRlZmluZWRgLlxuICAgKiBJdCBpcyBndWFyYW50ZWVkIHRvIGJlIHNldCBhZnRlciB0aGUgYFJvdXRlc1JlY29nbml6ZWRgIGV2ZW50IGZpcmVzLlxuICAgKi9cbiAgZmluYWxVcmw/OiBVcmxUcmVlO1xuICAvKipcbiAgICogSWRlbnRpZmllcyBob3cgdGhpcyBuYXZpZ2F0aW9uIHdhcyB0cmlnZ2VyZWQuXG4gICAqXG4gICAqICogJ2ltcGVyYXRpdmUnLS1UcmlnZ2VyZWQgYnkgYHJvdXRlci5uYXZpZ2F0ZUJ5VXJsYCBvciBgcm91dGVyLm5hdmlnYXRlYC5cbiAgICogKiAncG9wc3RhdGUnLS1UcmlnZ2VyZWQgYnkgYSBwb3BzdGF0ZSBldmVudC5cbiAgICogKiAnaGFzaGNoYW5nZSctLVRyaWdnZXJlZCBieSBhIGhhc2hjaGFuZ2UgZXZlbnQuXG4gICAqL1xuICB0cmlnZ2VyOiAnaW1wZXJhdGl2ZSd8J3BvcHN0YXRlJ3wnaGFzaGNoYW5nZSc7XG4gIC8qKlxuICAgKiBPcHRpb25zIHRoYXQgY29udHJvbGxlZCB0aGUgc3RyYXRlZ3kgdXNlZCBmb3IgdGhpcyBuYXZpZ2F0aW9uLlxuICAgKiBTZWUgYE5hdmlnYXRpb25FeHRyYXNgLlxuICAgKi9cbiAgZXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzO1xuICAvKipcbiAgICogVGhlIHByZXZpb3VzbHkgc3VjY2Vzc2Z1bCBgTmF2aWdhdGlvbmAgb2JqZWN0LiBPbmx5IG9uZSBwcmV2aW91cyBuYXZpZ2F0aW9uXG4gICAqIGlzIGF2YWlsYWJsZSwgdGhlcmVmb3JlIHRoaXMgcHJldmlvdXMgYE5hdmlnYXRpb25gIG9iamVjdCBoYXMgYSBgbnVsbGAgdmFsdWVcbiAgICogZm9yIGl0cyBvd24gYHByZXZpb3VzTmF2aWdhdGlvbmAuXG4gICAqL1xuICBwcmV2aW91c05hdmlnYXRpb246IE5hdmlnYXRpb258bnVsbDtcbn1cblxuZXhwb3J0IHR5cGUgTmF2aWdhdGlvblRyYW5zaXRpb24gPSB7XG4gIGlkOiBudW1iZXIsXG4gIHRhcmdldFBhZ2VJZDogbnVtYmVyLFxuICBjdXJyZW50VXJsVHJlZTogVXJsVHJlZSxcbiAgY3VycmVudFJhd1VybDogVXJsVHJlZSxcbiAgZXh0cmFjdGVkVXJsOiBVcmxUcmVlLFxuICB1cmxBZnRlclJlZGlyZWN0czogVXJsVHJlZSxcbiAgcmF3VXJsOiBVcmxUcmVlLFxuICBleHRyYXM6IE5hdmlnYXRpb25FeHRyYXMsXG4gIHJlc29sdmU6IGFueSxcbiAgcmVqZWN0OiBhbnksXG4gIHByb21pc2U6IFByb21pc2U8Ym9vbGVhbj4sXG4gIHNvdXJjZTogTmF2aWdhdGlvblRyaWdnZXIsXG4gIHJlc3RvcmVkU3RhdGU6IFJlc3RvcmVkU3RhdGV8bnVsbCxcbiAgY3VycmVudFNuYXBzaG90OiBSb3V0ZXJTdGF0ZVNuYXBzaG90LFxuICB0YXJnZXRTbmFwc2hvdDogUm91dGVyU3RhdGVTbmFwc2hvdHxudWxsLFxuICBjdXJyZW50Um91dGVyU3RhdGU6IFJvdXRlclN0YXRlLFxuICB0YXJnZXRSb3V0ZXJTdGF0ZTogUm91dGVyU3RhdGV8bnVsbCxcbiAgZ3VhcmRzOiBDaGVja3MsXG4gIGd1YXJkc1Jlc3VsdDogYm9vbGVhbnxVcmxUcmVlfG51bGwsXG59O1xuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgdHlwZSBSb3V0ZXJIb29rID0gKHNuYXBzaG90OiBSb3V0ZXJTdGF0ZVNuYXBzaG90LCBydW5FeHRyYXM6IHtcbiAgYXBwbGllZFVybFRyZWU6IFVybFRyZWUsXG4gIHJhd1VybFRyZWU6IFVybFRyZWUsXG4gIHNraXBMb2NhdGlvbkNoYW5nZTogYm9vbGVhbixcbiAgcmVwbGFjZVVybDogYm9vbGVhbixcbiAgbmF2aWdhdGlvbklkOiBudW1iZXJcbn0pID0+IE9ic2VydmFibGU8dm9pZD47XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRSb3V0ZXJIb29rKHNuYXBzaG90OiBSb3V0ZXJTdGF0ZVNuYXBzaG90LCBydW5FeHRyYXM6IHtcbiAgYXBwbGllZFVybFRyZWU6IFVybFRyZWUsXG4gIHJhd1VybFRyZWU6IFVybFRyZWUsXG4gIHNraXBMb2NhdGlvbkNoYW5nZTogYm9vbGVhbixcbiAgcmVwbGFjZVVybDogYm9vbGVhbixcbiAgbmF2aWdhdGlvbklkOiBudW1iZXJcbn0pOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgcmV0dXJuIG9mKG51bGwpIGFzIGFueTtcbn1cblxuLyoqXG4gKiBJbmZvcm1hdGlvbiByZWxhdGVkIHRvIGEgbG9jYXRpb24gY2hhbmdlLCBuZWNlc3NhcnkgZm9yIHNjaGVkdWxpbmcgZm9sbG93LXVwIFJvdXRlciBuYXZpZ2F0aW9ucy5cbiAqL1xudHlwZSBMb2NhdGlvbkNoYW5nZUluZm8gPSB7XG4gIHNvdXJjZTogJ3BvcHN0YXRlJ3wnaGFzaGNoYW5nZScsXG4gIHVybFRyZWU6IFVybFRyZWUsXG4gIHN0YXRlOiBSZXN0b3JlZFN0YXRlfG51bGwsXG4gIHRyYW5zaXRpb25JZDogbnVtYmVyXG59O1xuXG4vKipcbiAqIFRoZSBlcXVpdmFsZW50IGBJc0FjdGl2ZU1hdGNoT3B0aW9uc2Agb3B0aW9ucyBmb3IgYFJvdXRlci5pc0FjdGl2ZWAgaXMgY2FsbGVkIHdpdGggYHRydWVgXG4gKiAoZXhhY3QgPSB0cnVlKS5cbiAqL1xuZXhwb3J0IGNvbnN0IGV4YWN0TWF0Y2hPcHRpb25zOiBJc0FjdGl2ZU1hdGNoT3B0aW9ucyA9IHtcbiAgcGF0aHM6ICdleGFjdCcsXG4gIGZyYWdtZW50OiAnaWdub3JlZCcsXG4gIG1hdHJpeFBhcmFtczogJ2lnbm9yZWQnLFxuICBxdWVyeVBhcmFtczogJ2V4YWN0J1xufTtcblxuLyoqXG4gKiBUaGUgZXF1aXZhbGVudCBgSXNBY3RpdmVNYXRjaE9wdGlvbnNgIG9wdGlvbnMgZm9yIGBSb3V0ZXIuaXNBY3RpdmVgIGlzIGNhbGxlZCB3aXRoIGBmYWxzZWBcbiAqIChleGFjdCA9IGZhbHNlKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHN1YnNldE1hdGNoT3B0aW9uczogSXNBY3RpdmVNYXRjaE9wdGlvbnMgPSB7XG4gIHBhdGhzOiAnc3Vic2V0JyxcbiAgZnJhZ21lbnQ6ICdpZ25vcmVkJyxcbiAgbWF0cml4UGFyYW1zOiAnaWdub3JlZCcsXG4gIHF1ZXJ5UGFyYW1zOiAnc3Vic2V0J1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBBIHNlcnZpY2UgdGhhdCBwcm92aWRlcyBuYXZpZ2F0aW9uIGFtb25nIHZpZXdzIGFuZCBVUkwgbWFuaXB1bGF0aW9uIGNhcGFiaWxpdGllcy5cbiAqXG4gKiBAc2VlIGBSb3V0ZWAuXG4gKiBAc2VlIFtSb3V0aW5nIGFuZCBOYXZpZ2F0aW9uIEd1aWRlXShndWlkZS9yb3V0ZXIpLlxuICpcbiAqIEBuZ01vZHVsZSBSb3V0ZXJNb2R1bGVcbiAqXG4gKiBAcHVibGljQXBpXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSb3V0ZXIge1xuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgYWN0aXZhdGVkIGBVcmxUcmVlYCB0aGF0IHRoZSBgUm91dGVyYCBpcyBjb25maWd1cmVkIHRvIGhhbmRsZSAodGhyb3VnaFxuICAgKiBgVXJsSGFuZGxpbmdTdHJhdGVneWApLiBUaGF0IGlzLCBhZnRlciB3ZSBmaW5kIHRoZSByb3V0ZSBjb25maWcgdHJlZSB0aGF0IHdlJ3JlIGdvaW5nIHRvXG4gICAqIGFjdGl2YXRlLCBydW4gZ3VhcmRzLCBhbmQgYXJlIGp1c3QgYWJvdXQgdG8gYWN0aXZhdGUgdGhlIHJvdXRlLCB3ZSBzZXQgdGhlIGN1cnJlbnRVcmxUcmVlLlxuICAgKlxuICAgKiBUaGlzIHNob3VsZCBtYXRjaCB0aGUgYGJyb3dzZXJVcmxUcmVlYCB3aGVuIGEgbmF2aWdhdGlvbiBzdWNjZWVkcy4gSWYgdGhlXG4gICAqIGBVcmxIYW5kbGluZ1N0cmF0ZWd5LnNob3VsZFByb2Nlc3NVcmxgIGlzIGBmYWxzZWAsIG9ubHkgdGhlIGBicm93c2VyVXJsVHJlZWAgaXMgdXBkYXRlZC5cbiAgICovXG4gIHByaXZhdGUgY3VycmVudFVybFRyZWU6IFVybFRyZWU7XG4gIC8qKlxuICAgKiBNZWFudCB0byByZXByZXNlbnQgdGhlIGVudGlyZSBicm93c2VyIHVybCBhZnRlciBhIHN1Y2Nlc3NmdWwgbmF2aWdhdGlvbi4gSW4gdGhlIGxpZmUgb2YgYVxuICAgKiBuYXZpZ2F0aW9uIHRyYW5zaXRpb246XG4gICAqIDEuIFRoZSByYXdVcmwgcmVwcmVzZW50cyB0aGUgZnVsbCBVUkwgdGhhdCdzIGJlaW5nIG5hdmlnYXRlZCB0b1xuICAgKiAyLiBXZSBhcHBseSByZWRpcmVjdHMsIHdoaWNoIG1pZ2h0IG9ubHkgYXBwbHkgdG8gX3BhcnRfIG9mIHRoZSBVUkwgKGR1ZSB0b1xuICAgKiBgVXJsSGFuZGxpbmdTdHJhdGVneWApLlxuICAgKiAzLiBSaWdodCBiZWZvcmUgYWN0aXZhdGlvbiAoYmVjYXVzZSB3ZSBhc3N1bWUgYWN0aXZhdGlvbiB3aWxsIHN1Y2NlZWQpLCB3ZSB1cGRhdGUgdGhlXG4gICAqIHJhd1VybFRyZWUgdG8gYmUgYSBjb21iaW5hdGlvbiBvZiB0aGUgdXJsQWZ0ZXJSZWRpcmVjdHMgKGFnYWluLCB0aGlzIG1pZ2h0IG9ubHkgYXBwbHkgdG8gcGFydFxuICAgKiBvZiB0aGUgaW5pdGlhbCB1cmwpIGFuZCB0aGUgcmF3VXJsIG9mIHRoZSB0cmFuc2l0aW9uICh3aGljaCB3YXMgdGhlIG9yaWdpbmFsIG5hdmlnYXRpb24gdXJsIGluXG4gICAqIGl0cyBmdWxsIGZvcm0pLlxuICAgKi9cbiAgcHJpdmF0ZSByYXdVcmxUcmVlOiBVcmxUcmVlO1xuICAvKipcbiAgICogTWVhbnQgdG8gcmVwcmVzZW50IHRoZSBwYXJ0IG9mIHRoZSBicm93c2VyIHVybCB0aGF0IHRoZSBgUm91dGVyYCBpcyBzZXQgdXAgdG8gaGFuZGxlICh2aWEgdGhlXG4gICAqIGBVcmxIYW5kbGluZ1N0cmF0ZWd5YCkuIFRoaXMgdmFsdWUgaXMgdXBkYXRlZCBpbW1lZGlhdGVseSBhZnRlciB0aGUgYnJvd3NlciB1cmwgaXMgdXBkYXRlZCAob3JcbiAgICogdGhlIGJyb3dzZXIgdXJsIHVwZGF0ZSBpcyBza2lwcGVkIHZpYSBgc2tpcExvY2F0aW9uQ2hhbmdlYCkuIFdpdGggdGhhdCwgbm90ZSB0aGF0XG4gICAqIGBicm93c2VyVXJsVHJlZWAgX21heSBub3RfIHJlZmxlY3QgdGhlIGFjdHVhbCBicm93c2VyIFVSTCBmb3IgdHdvIHJlYXNvbnM6XG4gICAqXG4gICAqIDEuIGBVcmxIYW5kbGluZ1N0cmF0ZWd5YCBvbmx5IGhhbmRsZXMgcGFydCBvZiB0aGUgVVJMXG4gICAqIDIuIGBza2lwTG9jYXRpb25DaGFuZ2VgIGRvZXMgbm90IHVwZGF0ZSB0aGUgYnJvd3NlciB1cmwuXG4gICAqXG4gICAqIFNvIHRvIHJlaXRlcmF0ZSwgYGJyb3dzZXJVcmxUcmVlYCBvbmx5IHJlcHJlc2VudHMgdGhlIFJvdXRlcidzIGludGVybmFsIHVuZGVyc3RhbmRpbmcgb2YgdGhlXG4gICAqIGN1cnJlbnQgcm91dGUsIGVpdGhlciBiZWZvcmUgZ3VhcmRzIHdpdGggYHVybFVwZGF0ZVN0cmF0ZWd5ID09PSAnZWFnZXInYCBvciByaWdodCBiZWZvcmVcbiAgICogYWN0aXZhdGlvbiB3aXRoIGAnZGVmZXJyZWQnYC5cbiAgICpcbiAgICogVGhpcyBzaG91bGQgbWF0Y2ggdGhlIGBjdXJyZW50VXJsVHJlZWAgd2hlbiB0aGUgbmF2aWdhdGlvbiBzdWNjZWVkcy5cbiAgICovXG4gIHByaXZhdGUgYnJvd3NlclVybFRyZWU6IFVybFRyZWU7XG4gIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNpdGlvbnM6IEJlaGF2aW9yU3ViamVjdDxOYXZpZ2F0aW9uVHJhbnNpdGlvbj47XG4gIHByaXZhdGUgbmF2aWdhdGlvbnM6IE9ic2VydmFibGU8TmF2aWdhdGlvblRyYW5zaXRpb24+O1xuICBwcml2YXRlIGxhc3RTdWNjZXNzZnVsTmF2aWdhdGlvbjogTmF2aWdhdGlvbnxudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjdXJyZW50TmF2aWdhdGlvbjogTmF2aWdhdGlvbnxudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBkaXNwb3NlZCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgbG9jYXRpb25TdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb25MaWtlO1xuICAvKipcbiAgICogVHJhY2tzIHRoZSBwcmV2aW91c2x5IHNlZW4gbG9jYXRpb24gY2hhbmdlIGZyb20gdGhlIGxvY2F0aW9uIHN1YnNjcmlwdGlvbiBzbyB3ZSBjYW4gY29tcGFyZVxuICAgKiB0aGUgdHdvIGxhdGVzdCB0byBzZWUgaWYgdGhleSBhcmUgZHVwbGljYXRlcy4gU2VlIHNldFVwTG9jYXRpb25DaGFuZ2VMaXN0ZW5lci5cbiAgICovXG4gIHByaXZhdGUgbGFzdExvY2F0aW9uQ2hhbmdlSW5mbzogTG9jYXRpb25DaGFuZ2VJbmZvfG51bGwgPSBudWxsO1xuICBwcml2YXRlIG5hdmlnYXRpb25JZDogbnVtYmVyID0gMDtcblxuICAvKipcbiAgICogVGhlIGlkIG9mIHRoZSBjdXJyZW50bHkgYWN0aXZlIHBhZ2UgaW4gdGhlIHJvdXRlci5cbiAgICogVXBkYXRlZCB0byB0aGUgdHJhbnNpdGlvbidzIHRhcmdldCBpZCBvbiBhIHN1Y2Nlc3NmdWwgbmF2aWdhdGlvbi5cbiAgICpcbiAgICogVGhpcyBpcyB1c2VkIHRvIHRyYWNrIHdoYXQgcGFnZSB0aGUgcm91dGVyIGxhc3QgYWN0aXZhdGVkLiBXaGVuIGFuIGF0dGVtcHRlZCBuYXZpZ2F0aW9uIGZhaWxzLFxuICAgKiB0aGUgcm91dGVyIGNhbiB0aGVuIHVzZSB0aGlzIHRvIGNvbXB1dGUgaG93IHRvIHJlc3RvcmUgdGhlIHN0YXRlIGJhY2sgdG8gdGhlIHByZXZpb3VzbHkgYWN0aXZlXG4gICAqIHBhZ2UuXG4gICAqL1xuICBwcml2YXRlIGN1cnJlbnRQYWdlSWQ6IG51bWJlciA9IDA7XG4gIC8qKlxuICAgKiBUaGUgybVyb3V0ZXJQYWdlSWQgb2Ygd2hhdGV2ZXIgcGFnZSBpcyBjdXJyZW50bHkgYWN0aXZlIGluIHRoZSBicm93c2VyIGhpc3RvcnkuIFRoaXMgaXNcbiAgICogaW1wb3J0YW50IGZvciBjb21wdXRpbmcgdGhlIHRhcmdldCBwYWdlIGlkIGZvciBuZXcgbmF2aWdhdGlvbnMgYmVjYXVzZSB3ZSBuZWVkIHRvIGVuc3VyZSBlYWNoXG4gICAqIHBhZ2UgaWQgaW4gdGhlIGJyb3dzZXIgaGlzdG9yeSBpcyAxIG1vcmUgdGhhbiB0aGUgcHJldmlvdXMgZW50cnkuXG4gICAqL1xuICBwcml2YXRlIGdldCBicm93c2VyUGFnZUlkKCk6IG51bWJlcnx1bmRlZmluZWQge1xuICAgIHJldHVybiAodGhpcy5sb2NhdGlvbi5nZXRTdGF0ZSgpIGFzIFJlc3RvcmVkU3RhdGUgfCBudWxsKT8uybVyb3V0ZXJQYWdlSWQ7XG4gIH1cbiAgcHJpdmF0ZSBjb25maWdMb2FkZXI6IFJvdXRlckNvbmZpZ0xvYWRlcjtcbiAgcHJpdmF0ZSBuZ01vZHVsZTogTmdNb2R1bGVSZWY8YW55PjtcbiAgcHJpdmF0ZSBjb25zb2xlOiBDb25zb2xlO1xuICBwcml2YXRlIGlzTmdab25lRW5hYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBBbiBldmVudCBzdHJlYW0gZm9yIHJvdXRpbmcgZXZlbnRzIGluIHRoaXMgTmdNb2R1bGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZXZlbnRzOiBPYnNlcnZhYmxlPEV2ZW50PiA9IG5ldyBTdWJqZWN0PEV2ZW50PigpO1xuICAvKipcbiAgICogVGhlIGN1cnJlbnQgc3RhdGUgb2Ygcm91dGluZyBpbiB0aGlzIE5nTW9kdWxlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJvdXRlclN0YXRlOiBSb3V0ZXJTdGF0ZTtcblxuICAvKipcbiAgICogQSBoYW5kbGVyIGZvciBuYXZpZ2F0aW9uIGVycm9ycyBpbiB0aGlzIE5nTW9kdWxlLlxuICAgKi9cbiAgZXJyb3JIYW5kbGVyOiBFcnJvckhhbmRsZXIgPSBkZWZhdWx0RXJyb3JIYW5kbGVyO1xuXG4gIC8qKlxuICAgKiBBIGhhbmRsZXIgZm9yIGVycm9ycyB0aHJvd24gYnkgYFJvdXRlci5wYXJzZVVybCh1cmwpYFxuICAgKiB3aGVuIGB1cmxgIGNvbnRhaW5zIGFuIGludmFsaWQgY2hhcmFjdGVyLlxuICAgKiBUaGUgbW9zdCBjb21tb24gY2FzZSBpcyBhIGAlYCBzaWduXG4gICAqIHRoYXQncyBub3QgZW5jb2RlZCBhbmQgaXMgbm90IHBhcnQgb2YgYSBwZXJjZW50IGVuY29kZWQgc2VxdWVuY2UuXG4gICAqL1xuICBtYWxmb3JtZWRVcmlFcnJvckhhbmRsZXI6XG4gICAgICAoZXJyb3I6IFVSSUVycm9yLCB1cmxTZXJpYWxpemVyOiBVcmxTZXJpYWxpemVyLFxuICAgICAgIHVybDogc3RyaW5nKSA9PiBVcmxUcmVlID0gZGVmYXVsdE1hbGZvcm1lZFVyaUVycm9ySGFuZGxlcjtcblxuICAvKipcbiAgICogVHJ1ZSBpZiBhdCBsZWFzdCBvbmUgbmF2aWdhdGlvbiBldmVudCBoYXMgb2NjdXJyZWQsXG4gICAqIGZhbHNlIG90aGVyd2lzZS5cbiAgICovXG4gIG5hdmlnYXRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIGxhc3RTdWNjZXNzZnVsSWQ6IG51bWJlciA9IC0xO1xuXG4gIC8qKlxuICAgKiBIb29rcyB0aGF0IGVuYWJsZSB5b3UgdG8gcGF1c2UgbmF2aWdhdGlvbixcbiAgICogZWl0aGVyIGJlZm9yZSBvciBhZnRlciB0aGUgcHJlYWN0aXZhdGlvbiBwaGFzZS5cbiAgICogVXNlZCBieSBgUm91dGVyTW9kdWxlYC5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBob29rczoge1xuICAgIGJlZm9yZVByZWFjdGl2YXRpb246IFJvdXRlckhvb2ssXG4gICAgYWZ0ZXJQcmVhY3RpdmF0aW9uOiBSb3V0ZXJIb29rXG4gIH0gPSB7YmVmb3JlUHJlYWN0aXZhdGlvbjogZGVmYXVsdFJvdXRlckhvb2ssIGFmdGVyUHJlYWN0aXZhdGlvbjogZGVmYXVsdFJvdXRlckhvb2t9O1xuXG4gIC8qKlxuICAgKiBBIHN0cmF0ZWd5IGZvciBleHRyYWN0aW5nIGFuZCBtZXJnaW5nIFVSTHMuXG4gICAqIFVzZWQgZm9yIEFuZ3VsYXJKUyB0byBBbmd1bGFyIG1pZ3JhdGlvbnMuXG4gICAqL1xuICB1cmxIYW5kbGluZ1N0cmF0ZWd5OiBVcmxIYW5kbGluZ1N0cmF0ZWd5ID0gbmV3IERlZmF1bHRVcmxIYW5kbGluZ1N0cmF0ZWd5KCk7XG5cbiAgLyoqXG4gICAqIEEgc3RyYXRlZ3kgZm9yIHJlLXVzaW5nIHJvdXRlcy5cbiAgICovXG4gIHJvdXRlUmV1c2VTdHJhdGVneTogUm91dGVSZXVzZVN0cmF0ZWd5ID0gbmV3IERlZmF1bHRSb3V0ZVJldXNlU3RyYXRlZ3koKTtcblxuICAvKipcbiAgICogSG93IHRvIGhhbmRsZSBhIG5hdmlnYXRpb24gcmVxdWVzdCB0byB0aGUgY3VycmVudCBVUkwuIE9uZSBvZjpcbiAgICpcbiAgICogLSBgJ2lnbm9yZSdgIDogIFRoZSByb3V0ZXIgaWdub3JlcyB0aGUgcmVxdWVzdC5cbiAgICogLSBgJ3JlbG9hZCdgIDogVGhlIHJvdXRlciByZWxvYWRzIHRoZSBVUkwuIFVzZSB0byBpbXBsZW1lbnQgYSBcInJlZnJlc2hcIiBmZWF0dXJlLlxuICAgKlxuICAgKiBOb3RlIHRoYXQgdGhpcyBvbmx5IGNvbmZpZ3VyZXMgd2hldGhlciB0aGUgUm91dGUgcmVwcm9jZXNzZXMgdGhlIFVSTCBhbmQgdHJpZ2dlcnMgcmVsYXRlZFxuICAgKiBhY3Rpb24gYW5kIGV2ZW50cyBsaWtlIHJlZGlyZWN0cywgZ3VhcmRzLCBhbmQgcmVzb2x2ZXJzLiBCeSBkZWZhdWx0LCB0aGUgcm91dGVyIHJlLXVzZXMgYVxuICAgKiBjb21wb25lbnQgaW5zdGFuY2Ugd2hlbiBpdCByZS1uYXZpZ2F0ZXMgdG8gdGhlIHNhbWUgY29tcG9uZW50IHR5cGUgd2l0aG91dCB2aXNpdGluZyBhIGRpZmZlcmVudFxuICAgKiBjb21wb25lbnQgZmlyc3QuIFRoaXMgYmVoYXZpb3IgaXMgY29uZmlndXJlZCBieSB0aGUgYFJvdXRlUmV1c2VTdHJhdGVneWAuIEluIG9yZGVyIHRvIHJlbG9hZFxuICAgKiByb3V0ZWQgY29tcG9uZW50cyBvbiBzYW1lIHVybCBuYXZpZ2F0aW9uLCB5b3UgbmVlZCB0byBzZXQgYG9uU2FtZVVybE5hdmlnYXRpb25gIHRvIGAncmVsb2FkJ2BcbiAgICogX2FuZF8gcHJvdmlkZSBhIGBSb3V0ZVJldXNlU3RyYXRlZ3lgIHdoaWNoIHJldHVybnMgYGZhbHNlYCBmb3IgYHNob3VsZFJldXNlUm91dGVgLlxuICAgKi9cbiAgb25TYW1lVXJsTmF2aWdhdGlvbjogJ3JlbG9hZCd8J2lnbm9yZScgPSAnaWdub3JlJztcblxuICAvKipcbiAgICogSG93IHRvIG1lcmdlIHBhcmFtZXRlcnMsIGRhdGEsIGFuZCByZXNvbHZlZCBkYXRhIGZyb20gcGFyZW50IHRvIGNoaWxkXG4gICAqIHJvdXRlcy4gT25lIG9mOlxuICAgKlxuICAgKiAtIGAnZW1wdHlPbmx5J2AgOiBJbmhlcml0IHBhcmVudCBwYXJhbWV0ZXJzLCBkYXRhLCBhbmQgcmVzb2x2ZWQgZGF0YVxuICAgKiBmb3IgcGF0aC1sZXNzIG9yIGNvbXBvbmVudC1sZXNzIHJvdXRlcy5cbiAgICogLSBgJ2Fsd2F5cydgIDogSW5oZXJpdCBwYXJlbnQgcGFyYW1ldGVycywgZGF0YSwgYW5kIHJlc29sdmVkIGRhdGFcbiAgICogZm9yIGFsbCBjaGlsZCByb3V0ZXMuXG4gICAqL1xuICBwYXJhbXNJbmhlcml0YW5jZVN0cmF0ZWd5OiAnZW1wdHlPbmx5J3wnYWx3YXlzJyA9ICdlbXB0eU9ubHknO1xuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZW4gdGhlIHJvdXRlciB1cGRhdGVzIHRoZSBicm93c2VyIFVSTC5cbiAgICogQnkgZGVmYXVsdCAoYFwiZGVmZXJyZWRcImApLCB1cGRhdGVzIHRoZSBicm93c2VyIFVSTCBhZnRlciBuYXZpZ2F0aW9uIGhhcyBmaW5pc2hlZC5cbiAgICogU2V0IHRvIGAnZWFnZXInYCB0byB1cGRhdGUgdGhlIGJyb3dzZXIgVVJMIGF0IHRoZSBiZWdpbm5pbmcgb2YgbmF2aWdhdGlvbi5cbiAgICogWW91IGNhbiBjaG9vc2UgdG8gdXBkYXRlIGVhcmx5IHNvIHRoYXQsIGlmIG5hdmlnYXRpb24gZmFpbHMsXG4gICAqIHlvdSBjYW4gc2hvdyBhbiBlcnJvciBtZXNzYWdlIHdpdGggdGhlIFVSTCB0aGF0IGZhaWxlZC5cbiAgICovXG4gIHVybFVwZGF0ZVN0cmF0ZWd5OiAnZGVmZXJyZWQnfCdlYWdlcicgPSAnZGVmZXJyZWQnO1xuXG4gIC8qKlxuICAgKiBFbmFibGVzIGEgYnVnIGZpeCB0aGF0IGNvcnJlY3RzIHJlbGF0aXZlIGxpbmsgcmVzb2x1dGlvbiBpbiBjb21wb25lbnRzIHdpdGggZW1wdHkgcGF0aHMuXG4gICAqIEBzZWUgYFJvdXRlck1vZHVsZWBcbiAgICovXG4gIHJlbGF0aXZlTGlua1Jlc29sdXRpb246ICdsZWdhY3knfCdjb3JyZWN0ZWQnID0gJ2NvcnJlY3RlZCc7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZXMgaG93IHRoZSBSb3V0ZXIgYXR0ZW1wdHMgdG8gcmVzdG9yZSBzdGF0ZSB3aGVuIGEgbmF2aWdhdGlvbiBpcyBjYW5jZWxsZWQuXG4gICAqXG4gICAqICdyZXBsYWNlJyAtIEFsd2F5cyB1c2VzIGBsb2NhdGlvbi5yZXBsYWNlU3RhdGVgIHRvIHNldCB0aGUgYnJvd3NlciBzdGF0ZSB0byB0aGUgc3RhdGUgb2YgdGhlXG4gICAqIHJvdXRlciBiZWZvcmUgdGhlIG5hdmlnYXRpb24gc3RhcnRlZC5cbiAgICpcbiAgICogJ2NvbXB1dGVkJyAtIFdpbGwgYWx3YXlzIHJldHVybiB0byB0aGUgc2FtZSBzdGF0ZSB0aGF0IGNvcnJlc3BvbmRzIHRvIHRoZSBhY3R1YWwgQW5ndWxhciByb3V0ZVxuICAgKiB3aGVuIHRoZSBuYXZpZ2F0aW9uIGdldHMgY2FuY2VsbGVkIHJpZ2h0IGFmdGVyIHRyaWdnZXJpbmcgYSBgcG9wc3RhdGVgIGV2ZW50LlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyBgcmVwbGFjZWBcbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICAvLyBUT0RPKGF0c2NvdHQpOiBEZXRlcm1pbmUgaG93L3doZW4vaWYgdG8gbWFrZSB0aGlzIHB1YmxpYyBBUElcbiAgLy8gVGhpcyBzaG91bGRu4oCZdCBiZSBhbiBvcHRpb24gYXQgYWxsIGJ1dCBtYXkgbmVlZCB0byBiZSBpbiBvcmRlciB0byBhbGxvdyBtaWdyYXRpb24gd2l0aG91dCBhXG4gIC8vIGJyZWFraW5nIGNoYW5nZS4gV2UgbmVlZCB0byBkZXRlcm1pbmUgaWYgaXQgc2hvdWxkIGJlIG1hZGUgaW50byBwdWJsaWMgYXBpIChvciBpZiB3ZSBmb3Jnb1xuICAvLyB0aGUgb3B0aW9uIGFuZCByZWxlYXNlIGFzIGEgYnJlYWtpbmcgY2hhbmdlIGJ1ZyBmaXggaW4gYSBtYWpvciB2ZXJzaW9uKS5cbiAgY2FuY2VsZWROYXZpZ2F0aW9uUmVzb2x1dGlvbjogJ3JlcGxhY2UnfCdjb21wdXRlZCcgPSAncmVwbGFjZSc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIHJvdXRlciBzZXJ2aWNlLlxuICAgKi9cbiAgLy8gVE9ETzogdnNhdmtpbiBtYWtlIGludGVybmFsIGFmdGVyIHRoZSBmaW5hbCBpcyBvdXQuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSByb290Q29tcG9uZW50VHlwZTogVHlwZTxhbnk+fG51bGwsIHByaXZhdGUgdXJsU2VyaWFsaXplcjogVXJsU2VyaWFsaXplcixcbiAgICAgIHByaXZhdGUgcm9vdENvbnRleHRzOiBDaGlsZHJlbk91dGxldENvbnRleHRzLCBwcml2YXRlIGxvY2F0aW9uOiBMb2NhdGlvbiwgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgICAgbG9hZGVyOiBOZ01vZHVsZUZhY3RvcnlMb2FkZXIsIGNvbXBpbGVyOiBDb21waWxlciwgcHVibGljIGNvbmZpZzogUm91dGVzKSB7XG4gICAgY29uc3Qgb25Mb2FkU3RhcnQgPSAocjogUm91dGUpID0+IHRoaXMudHJpZ2dlckV2ZW50KG5ldyBSb3V0ZUNvbmZpZ0xvYWRTdGFydChyKSk7XG4gICAgY29uc3Qgb25Mb2FkRW5kID0gKHI6IFJvdXRlKSA9PiB0aGlzLnRyaWdnZXJFdmVudChuZXcgUm91dGVDb25maWdMb2FkRW5kKHIpKTtcblxuICAgIHRoaXMubmdNb2R1bGUgPSBpbmplY3Rvci5nZXQoTmdNb2R1bGVSZWYpO1xuICAgIHRoaXMuY29uc29sZSA9IGluamVjdG9yLmdldChDb25zb2xlKTtcbiAgICBjb25zdCBuZ1pvbmUgPSBpbmplY3Rvci5nZXQoTmdab25lKTtcbiAgICB0aGlzLmlzTmdab25lRW5hYmxlZCA9IG5nWm9uZSBpbnN0YW5jZW9mIE5nWm9uZSAmJiBOZ1pvbmUuaXNJbkFuZ3VsYXJab25lKCk7XG5cbiAgICB0aGlzLnJlc2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgdGhpcy5jdXJyZW50VXJsVHJlZSA9IGNyZWF0ZUVtcHR5VXJsVHJlZSgpO1xuICAgIHRoaXMucmF3VXJsVHJlZSA9IHRoaXMuY3VycmVudFVybFRyZWU7XG4gICAgdGhpcy5icm93c2VyVXJsVHJlZSA9IHRoaXMuY3VycmVudFVybFRyZWU7XG5cbiAgICB0aGlzLmNvbmZpZ0xvYWRlciA9IG5ldyBSb3V0ZXJDb25maWdMb2FkZXIobG9hZGVyLCBjb21waWxlciwgb25Mb2FkU3RhcnQsIG9uTG9hZEVuZCk7XG4gICAgdGhpcy5yb3V0ZXJTdGF0ZSA9IGNyZWF0ZUVtcHR5U3RhdGUodGhpcy5jdXJyZW50VXJsVHJlZSwgdGhpcy5yb290Q29tcG9uZW50VHlwZSk7XG5cbiAgICB0aGlzLnRyYW5zaXRpb25zID0gbmV3IEJlaGF2aW9yU3ViamVjdDxOYXZpZ2F0aW9uVHJhbnNpdGlvbj4oe1xuICAgICAgaWQ6IDAsXG4gICAgICB0YXJnZXRQYWdlSWQ6IDAsXG4gICAgICBjdXJyZW50VXJsVHJlZTogdGhpcy5jdXJyZW50VXJsVHJlZSxcbiAgICAgIGN1cnJlbnRSYXdVcmw6IHRoaXMuY3VycmVudFVybFRyZWUsXG4gICAgICBleHRyYWN0ZWRVcmw6IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5leHRyYWN0KHRoaXMuY3VycmVudFVybFRyZWUpLFxuICAgICAgdXJsQWZ0ZXJSZWRpcmVjdHM6IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5leHRyYWN0KHRoaXMuY3VycmVudFVybFRyZWUpLFxuICAgICAgcmF3VXJsOiB0aGlzLmN1cnJlbnRVcmxUcmVlLFxuICAgICAgZXh0cmFzOiB7fSxcbiAgICAgIHJlc29sdmU6IG51bGwsXG4gICAgICByZWplY3Q6IG51bGwsXG4gICAgICBwcm9taXNlOiBQcm9taXNlLnJlc29sdmUodHJ1ZSksXG4gICAgICBzb3VyY2U6ICdpbXBlcmF0aXZlJyxcbiAgICAgIHJlc3RvcmVkU3RhdGU6IG51bGwsXG4gICAgICBjdXJyZW50U25hcHNob3Q6IHRoaXMucm91dGVyU3RhdGUuc25hcHNob3QsXG4gICAgICB0YXJnZXRTbmFwc2hvdDogbnVsbCxcbiAgICAgIGN1cnJlbnRSb3V0ZXJTdGF0ZTogdGhpcy5yb3V0ZXJTdGF0ZSxcbiAgICAgIHRhcmdldFJvdXRlclN0YXRlOiBudWxsLFxuICAgICAgZ3VhcmRzOiB7Y2FuQWN0aXZhdGVDaGVja3M6IFtdLCBjYW5EZWFjdGl2YXRlQ2hlY2tzOiBbXX0sXG4gICAgICBndWFyZHNSZXN1bHQ6IG51bGwsXG4gICAgfSk7XG4gICAgdGhpcy5uYXZpZ2F0aW9ucyA9IHRoaXMuc2V0dXBOYXZpZ2F0aW9ucyh0aGlzLnRyYW5zaXRpb25zKTtcblxuICAgIHRoaXMucHJvY2Vzc05hdmlnYXRpb25zKCk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwTmF2aWdhdGlvbnModHJhbnNpdGlvbnM6IE9ic2VydmFibGU8TmF2aWdhdGlvblRyYW5zaXRpb24+KTpcbiAgICAgIE9ic2VydmFibGU8TmF2aWdhdGlvblRyYW5zaXRpb24+IHtcbiAgICBjb25zdCBldmVudHNTdWJqZWN0ID0gKHRoaXMuZXZlbnRzIGFzIFN1YmplY3Q8RXZlbnQ+KTtcbiAgICByZXR1cm4gdHJhbnNpdGlvbnMucGlwZShcbiAgICAgICAgICAgICAgIGZpbHRlcih0ID0+IHQuaWQgIT09IDApLFxuXG4gICAgICAgICAgICAgICAvLyBFeHRyYWN0IFVSTFxuICAgICAgICAgICAgICAgbWFwKHQgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgKHsuLi50LCBleHRyYWN0ZWRVcmw6IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5leHRyYWN0KHQucmF3VXJsKX0gYXNcbiAgICAgICAgICAgICAgICAgICAgICAgIE5hdmlnYXRpb25UcmFuc2l0aW9uKSksXG5cbiAgICAgICAgICAgICAgIC8vIFVzaW5nIHN3aXRjaE1hcCBzbyB3ZSBjYW5jZWwgZXhlY3V0aW5nIG5hdmlnYXRpb25zIHdoZW4gYSBuZXcgb25lIGNvbWVzIGluXG4gICAgICAgICAgICAgICBzd2l0Y2hNYXAodCA9PiB7XG4gICAgICAgICAgICAgICAgIGxldCBjb21wbGV0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgbGV0IGVycm9yZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKHQpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAvLyBTdG9yZSB0aGUgTmF2aWdhdGlvbiBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgIHRhcCh0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TmF2aWdhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICBpZDogdC5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsVXJsOiB0LmN1cnJlbnRSYXdVcmwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgZXh0cmFjdGVkVXJsOiB0LmV4dHJhY3RlZFVybCxcbiAgICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyOiB0LnNvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYXM6IHQuZXh0cmFzLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzTmF2aWdhdGlvbjogdGhpcy5sYXN0U3VjY2Vzc2Z1bE5hdmlnYXRpb24gP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7Li4udGhpcy5sYXN0U3VjY2Vzc2Z1bE5hdmlnYXRpb24sIHByZXZpb3VzTmF2aWdhdGlvbjogbnVsbH0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWxsXG4gICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCh0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYnJvd3NlclVybFRyZWUgPSB0aGlzLmJyb3dzZXJVcmxUcmVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVybFRyYW5zaXRpb24gPSAhdGhpcy5uYXZpZ2F0ZWQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHQuZXh0cmFjdGVkVXJsLnRvU3RyaW5nKCkgIT09IGJyb3dzZXJVcmxUcmVlIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOYXZpZ2F0aW9ucyB3aGljaCBzdWNjZWVkIG9yIG9uZXMgd2hpY2ggZmFpbCBhbmQgYXJlIGNsZWFuZWQgdXBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvcnJlY3RseSBzaG91bGQgcmVzdWx0IGluIGBicm93c2VyVXJsVHJlZWAgYW5kIGBjdXJyZW50VXJsVHJlZWBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1hdGNoaW5nLiBJZiB0aGlzIGlzIG5vdCB0aGUgY2FzZSwgYXNzdW1lIHNvbWV0aGluZyB3ZW50IHdyb25nIGFuZCB0cnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByb2Nlc3NpbmcgdGhlIFVSTCBhZ2Fpbi5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyb3dzZXJVcmxUcmVlICE9PSB0aGlzLmN1cnJlbnRVcmxUcmVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NDdXJyZW50VXJsID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLm9uU2FtZVVybE5hdmlnYXRpb24gPT09ICdyZWxvYWQnID8gdHJ1ZSA6IHVybFRyYW5zaXRpb24pICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVybEhhbmRsaW5nU3RyYXRlZ3kuc2hvdWxkUHJvY2Vzc1VybCh0LnJhd1VybCk7XG5cblxuICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvY2Vzc0N1cnJlbnRVcmwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgc291cmNlIG9mIHRoZSBuYXZpZ2F0aW9uIGlzIGZyb20gYSBicm93c2VyIGV2ZW50LCB0aGUgVVJMIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxyZWFkeSB1cGRhdGVkLiBXZSBhbHJlYWR5IG5lZWQgdG8gc3luYyB0aGUgaW50ZXJuYWwgc3RhdGUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQnJvd3NlclRyaWdnZXJlZE5hdmlnYXRpb24odC5zb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJyb3dzZXJVcmxUcmVlID0gdC5leHRyYWN0ZWRVcmw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZih0KS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXJlIE5hdmlnYXRpb25TdGFydCBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhbnNpdGlvbiA9IHRoaXMudHJhbnNpdGlvbnMuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHNTdWJqZWN0Lm5leHQobmV3IE5hdmlnYXRpb25TdGFydChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLCB0LnNvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5yZXN0b3JlZFN0YXRlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyYW5zaXRpb24gIT09IHRoaXMudHJhbnNpdGlvbnMuZ2V0VmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEVNUFRZO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgZGVsYXkgaXMgcmVxdWlyZWQgdG8gbWF0Y2ggb2xkIGJlaGF2aW9yIHRoYXQgZm9yY2VkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmF2aWdhdGlvbiB0byBhbHdheXMgYmUgYXN5bmNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBcHBseVJlZGlyZWN0c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseVJlZGlyZWN0cyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmdNb2R1bGUuaW5qZWN0b3IsIHRoaXMuY29uZmlnTG9hZGVyLCB0aGlzLnVybFNlcmlhbGl6ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZyksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBjdXJyZW50TmF2aWdhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TmF2aWdhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnRoaXMuY3VycmVudE5hdmlnYXRpb24hLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxVcmw6IHQudXJsQWZ0ZXJSZWRpcmVjdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWNvZ25pemVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb2duaXplKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yb290Q29tcG9uZW50VHlwZSwgdGhpcy5jb25maWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodXJsKSA9PiB0aGlzLnNlcmlhbGl6ZVVybCh1cmwpLCB0aGlzLnBhcmFtc0luaGVyaXRhbmNlU3RyYXRlZ3ksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbGF0aXZlTGlua1Jlc29sdXRpb24pLFxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBVUkwgaWYgaW4gYGVhZ2VyYCB1cGRhdGUgbW9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudXJsVXBkYXRlU3RyYXRlZ3kgPT09ICdlYWdlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdC5leHRyYXMuc2tpcExvY2F0aW9uQ2hhbmdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0QnJvd3NlclVybCh0LnVybEFmdGVyUmVkaXJlY3RzLCB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETyhhdHNjb3R0KTogVGhlIGFib3ZlIGxpbmUgaXMgaW5jb3JyZWN0LiBJdCBzZXRzIHRoZSB1cmwgdG9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb25seSB0aGUgcGFydCB0aGF0IGlzIGhhbmRsZWQgYnkgdGhlIHJvdXRlci4gSXQgc2hvdWxkIG1lcmdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgd2l0aCB0aGUgcmF3VXJsIHNvIHRoZSB1cmwgaW5jbHVkZXMgc2VnbWVudHMgbm90IGhhbmRsZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYnkgdGhlIHJvdXRlcjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gIGNvbnN0IHJhd1VybCA9IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5tZXJnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICB0LnVybEFmdGVyUmVkaXJlY3RzLCB0LnJhd1VybCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICB0aGlzLnNldEJyb3dzZXJVcmwocmF3VXJsLCB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnJvd3NlclVybFRyZWUgPSB0LnVybEFmdGVyUmVkaXJlY3RzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpcmUgUm91dGVzUmVjb2duaXplZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvdXRlc1JlY29nbml6ZWQgPSBuZXcgUm91dGVzUmVjb2duaXplZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcmlhbGl6ZVVybCh0LnVybEFmdGVyUmVkaXJlY3RzKSwgdC50YXJnZXRTbmFwc2hvdCEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c1N1YmplY3QubmV4dChyb3V0ZXNSZWNvZ25pemVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NQcmV2aW91c1VybCA9IHVybFRyYW5zaXRpb24gJiYgdGhpcy5yYXdVcmxUcmVlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5zaG91bGRQcm9jZXNzVXJsKHRoaXMucmF3VXJsVHJlZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgLyogV2hlbiB0aGUgY3VycmVudCBVUkwgc2hvdWxkbid0IGJlIHByb2Nlc3NlZCwgYnV0IHRoZSBwcmV2aW91cyBvbmUgd2FzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAqIHdlIGhhbmRsZSB0aGlzIFwiZXJyb3IgY29uZGl0aW9uXCIgYnkgbmF2aWdhdGluZyB0byB0aGUgcHJldmlvdXNseVxuICAgICAgICAgICAgICAgICAgICAgICAgICAqIHN1Y2Nlc3NmdWwgVVJMLCBidXQgbGVhdmluZyB0aGUgVVJMIGludGFjdC4qL1xuICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzUHJldmlvdXNVcmwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHtpZCwgZXh0cmFjdGVkVXJsLCBzb3VyY2UsIHJlc3RvcmVkU3RhdGUsIGV4dHJhc30gPSB0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmF2U3RhcnQgPSBuZXcgTmF2aWdhdGlvblN0YXJ0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkLCB0aGlzLnNlcmlhbGl6ZVVybChleHRyYWN0ZWRVcmwpLCBzb3VyY2UsIHJlc3RvcmVkU3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzU3ViamVjdC5uZXh0KG5hdlN0YXJ0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldFNuYXBzaG90ID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbXB0eVN0YXRlKGV4dHJhY3RlZFVybCwgdGhpcy5yb290Q29tcG9uZW50VHlwZSkuc25hcHNob3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldFNuYXBzaG90LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmxBZnRlclJlZGlyZWN0czogZXh0cmFjdGVkVXJsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYXM6IHsuLi5leHRyYXMsIHNraXBMb2NhdGlvbkNoYW5nZTogZmFsc2UsIHJlcGxhY2VVcmw6IGZhbHNlfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBXaGVuIG5laXRoZXIgdGhlIGN1cnJlbnQgb3IgcHJldmlvdXMgVVJMIGNhbiBiZSBwcm9jZXNzZWQsIGRvIG5vdGhpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIG90aGVyIHRoYW4gdXBkYXRlIHJvdXRlcidzIGludGVybmFsIHJlZmVyZW5jZSB0byB0aGUgY3VycmVudCBcInNldHRsZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICogVVJMLiBUaGlzIHdheSB0aGUgbmV4dCBuYXZpZ2F0aW9uIHdpbGwgYmUgY29taW5nIGZyb20gdGhlIGN1cnJlbnQgVVJMXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBpbiB0aGUgYnJvd3Nlci5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yYXdVcmxUcmVlID0gdC5yYXdVcmw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJyb3dzZXJVcmxUcmVlID0gdC51cmxBZnRlclJlZGlyZWN0cztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHQucmVzb2x2ZShudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBFTVBUWTtcbiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgIH0pLFxuXG4gICAgICAgICAgICAgICAgICAgICAvLyBCZWZvcmUgUHJlYWN0aXZhdGlvblxuICAgICAgICAgICAgICAgICAgICAgc3dpdGNoVGFwKHQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0U25hcHNob3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IG5hdmlnYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYWN0ZWRVcmw6IGFwcGxpZWRVcmxUcmVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHJhd1VybDogcmF3VXJsVHJlZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYXM6IHtza2lwTG9jYXRpb25DaGFuZ2UsIHJlcGxhY2VVcmx9XG4gICAgICAgICAgICAgICAgICAgICAgIH0gPSB0O1xuICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5ob29rcy5iZWZvcmVQcmVhY3RpdmF0aW9uKHRhcmdldFNuYXBzaG90ISwge1xuICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBhcHBsaWVkVXJsVHJlZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICByYXdVcmxUcmVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHNraXBMb2NhdGlvbkNoYW5nZTogISFza2lwTG9jYXRpb25DaGFuZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZVVybDogISFyZXBsYWNlVXJsLFxuICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgIH0pLFxuXG4gICAgICAgICAgICAgICAgICAgICAvLyAtLS0gR1VBUkRTIC0tLVxuICAgICAgICAgICAgICAgICAgICAgdGFwKHQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBndWFyZHNTdGFydCA9IG5ldyBHdWFyZHNDaGVja1N0YXJ0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXJpYWxpemVVcmwodC51cmxBZnRlclJlZGlyZWN0cyksIHQudGFyZ2V0U25hcHNob3QhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnQoZ3VhcmRzU3RhcnQpO1xuICAgICAgICAgICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICAgICAgICAgICAgIG1hcCh0ID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAuLi50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3VhcmRzOiBnZXRBbGxSb3V0ZUd1YXJkcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0LnRhcmdldFNuYXBzaG90ISwgdC5jdXJyZW50U25hcHNob3QsIHRoaXMucm9vdENvbnRleHRzKVxuICAgICAgICAgICAgICAgICAgICAgICAgIH0pKSxcblxuICAgICAgICAgICAgICAgICAgICAgY2hlY2tHdWFyZHModGhpcy5uZ01vZHVsZS5pbmplY3RvciwgKGV2dDogRXZlbnQpID0+IHRoaXMudHJpZ2dlckV2ZW50KGV2dCkpLFxuICAgICAgICAgICAgICAgICAgICAgdGFwKHQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNVcmxUcmVlKHQuZ3VhcmRzUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yOiBFcnJvciZ7dXJsPzogVXJsVHJlZX0gPSBuYXZpZ2F0aW9uQ2FuY2VsaW5nRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBSZWRpcmVjdGluZyB0byBcIiR7dGhpcy5zZXJpYWxpemVVcmwodC5ndWFyZHNSZXN1bHQpfVwiYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IudXJsID0gdC5ndWFyZHNSZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBndWFyZHNFbmQgPSBuZXcgR3VhcmRzQ2hlY2tFbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0LmlkLCB0aGlzLnNlcmlhbGl6ZVVybCh0LmV4dHJhY3RlZFVybCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcmlhbGl6ZVVybCh0LnVybEFmdGVyUmVkaXJlY3RzKSwgdC50YXJnZXRTbmFwc2hvdCEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAhIXQuZ3VhcmRzUmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnQoZ3VhcmRzRW5kKTtcbiAgICAgICAgICAgICAgICAgICAgIH0pLFxuXG4gICAgICAgICAgICAgICAgICAgICBmaWx0ZXIodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgIGlmICghdC5ndWFyZHNSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVIaXN0b3J5KHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsTmF2aWdhdGlvblRyYW5zaXRpb24odCwgJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgIH0pLFxuXG4gICAgICAgICAgICAgICAgICAgICAvLyAtLS0gUkVTT0xWRSAtLS1cbiAgICAgICAgICAgICAgICAgICAgIHN3aXRjaFRhcCh0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgaWYgKHQuZ3VhcmRzLmNhbkFjdGl2YXRlQ2hlY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZih0KS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZVN0YXJ0ID0gbmV3IFJlc29sdmVTdGFydChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcmlhbGl6ZVVybCh0LnVybEFmdGVyUmVkaXJlY3RzKSwgdC50YXJnZXRTbmFwc2hvdCEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlckV2ZW50KHJlc29sdmVTdGFydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGFSZXNvbHZlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZih0KS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlRGF0YShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyYW1zSW5oZXJpdGFuY2VTdHJhdGVneSwgdGhpcy5uZ01vZHVsZS5pbmplY3RvciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dDogKCkgPT4gZGF0YVJlc29sdmVkID0gdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkYXRhUmVzb2x2ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN0b3JlSGlzdG9yeSh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW5jZWxOYXZpZ2F0aW9uVHJhbnNpdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQXQgbGVhc3Qgb25lIHJvdXRlIHJlc29sdmVyIGRpZG4ndCBlbWl0IGFueSB2YWx1ZS5gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXAodCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZUVuZCA9IG5ldyBSZXNvbHZlRW5kKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0LmlkLCB0aGlzLnNlcmlhbGl6ZVVybCh0LmV4dHJhY3RlZFVybCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VyaWFsaXplVXJsKHQudXJsQWZ0ZXJSZWRpcmVjdHMpLCB0LnRhcmdldFNuYXBzaG90ISk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyRXZlbnQocmVzb2x2ZUVuZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICAgICAgICAgICAgIC8vIC0tLSBBRlRFUiBQUkVBQ1RJVkFUSU9OIC0tLVxuICAgICAgICAgICAgICAgICAgICAgc3dpdGNoVGFwKCh0OiBOYXZpZ2F0aW9uVHJhbnNpdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0U25hcHNob3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IG5hdmlnYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYWN0ZWRVcmw6IGFwcGxpZWRVcmxUcmVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHJhd1VybDogcmF3VXJsVHJlZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICBleHRyYXM6IHtza2lwTG9jYXRpb25DaGFuZ2UsIHJlcGxhY2VVcmx9XG4gICAgICAgICAgICAgICAgICAgICAgIH0gPSB0O1xuICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5ob29rcy5hZnRlclByZWFjdGl2YXRpb24odGFyZ2V0U25hcHNob3QhLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGxpZWRVcmxUcmVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHJhd1VybFRyZWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgc2tpcExvY2F0aW9uQ2hhbmdlOiAhIXNraXBMb2NhdGlvbkNoYW5nZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlVXJsOiAhIXJlcGxhY2VVcmwsXG4gICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICAgICAgICAgICAgIG1hcCgodDogTmF2aWdhdGlvblRyYW5zaXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0Um91dGVyU3RhdGUgPSBjcmVhdGVSb3V0ZXJTdGF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucm91dGVSZXVzZVN0cmF0ZWd5LCB0LnRhcmdldFNuYXBzaG90ISwgdC5jdXJyZW50Um91dGVyU3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHsuLi50LCB0YXJnZXRSb3V0ZXJTdGF0ZX0pO1xuICAgICAgICAgICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICAgICAgICAgICAgIC8qIE9uY2UgaGVyZSwgd2UgYXJlIGFib3V0IHRvIGFjdGl2YXRlIHN5bmNyb25vdXNseS4gVGhlIGFzc3VtcHRpb24gaXMgdGhpc1xuICAgICAgICAgICAgICAgICAgICAgICAgd2lsbCBzdWNjZWVkLCBhbmQgdXNlciBjb2RlIG1heSByZWFkIGZyb20gdGhlIFJvdXRlciBzZXJ2aWNlLiBUaGVyZWZvcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZm9yZSBhY3RpdmF0aW9uLCB3ZSBuZWVkIHRvIHVwZGF0ZSByb3V0ZXIgcHJvcGVydGllcyBzdG9yaW5nIHRoZSBjdXJyZW50XG4gICAgICAgICAgICAgICAgICAgICAgICBVUkwgYW5kIHRoZSBSb3V0ZXJTdGF0ZSwgYXMgd2VsbCBhcyB1cGRhdGVkIHRoZSBicm93c2VyIFVSTC4gQWxsIHRoaXMgc2hvdWxkXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXBwZW4gKmJlZm9yZSogYWN0aXZhdGluZy4gKi9cbiAgICAgICAgICAgICAgICAgICAgIHRhcCgodDogTmF2aWdhdGlvblRyYW5zaXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50VXJsVHJlZSA9IHQudXJsQWZ0ZXJSZWRpcmVjdHM7XG4gICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmF3VXJsVHJlZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVybEhhbmRsaW5nU3RyYXRlZ3kubWVyZ2UodC51cmxBZnRlclJlZGlyZWN0cywgdC5yYXdVcmwpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICh0aGlzIGFzIHtyb3V0ZXJTdGF0ZTogUm91dGVyU3RhdGV9KS5yb3V0ZXJTdGF0ZSA9IHQudGFyZ2V0Um91dGVyU3RhdGUhO1xuXG4gICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnVybFVwZGF0ZVN0cmF0ZWd5ID09PSAnZGVmZXJyZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0LmV4dHJhcy5za2lwTG9jYXRpb25DaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0QnJvd3NlclVybCh0aGlzLnJhd1VybFRyZWUsIHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJyb3dzZXJVcmxUcmVlID0gdC51cmxBZnRlclJlZGlyZWN0cztcbiAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICAgICAgICAgICAgIGFjdGl2YXRlUm91dGVzKFxuICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucm9vdENvbnRleHRzLCB0aGlzLnJvdXRlUmV1c2VTdHJhdGVneSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAoZXZ0OiBFdmVudCkgPT4gdGhpcy50cmlnZ2VyRXZlbnQoZXZ0KSksXG5cbiAgICAgICAgICAgICAgICAgICAgIHRhcCh7XG4gICAgICAgICAgICAgICAgICAgICAgIG5leHQoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGUoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICBmaW5hbGl6ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgIC8qIFdoZW4gdGhlIG5hdmlnYXRpb24gc3RyZWFtIGZpbmlzaGVzIGVpdGhlciB0aHJvdWdoIGVycm9yIG9yIHN1Y2Nlc3MsIHdlXG4gICAgICAgICAgICAgICAgICAgICAgICAqIHNldCB0aGUgYGNvbXBsZXRlZGAgb3IgYGVycm9yZWRgIGZsYWcuIEhvd2V2ZXIsIHRoZXJlIGFyZSBzb21lIHNpdHVhdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgICAgICogd2hlcmUgd2UgY291bGQgZ2V0IGhlcmUgd2l0aG91dCBlaXRoZXIgb2YgdGhvc2UgYmVpbmcgc2V0LiBGb3IgaW5zdGFuY2UsIGFcbiAgICAgICAgICAgICAgICAgICAgICAgICogcmVkaXJlY3QgZHVyaW5nIE5hdmlnYXRpb25TdGFydC4gVGhlcmVmb3JlLCB0aGlzIGlzIGEgY2F0Y2gtYWxsIHRvIG1ha2VcbiAgICAgICAgICAgICAgICAgICAgICAgICogc3VyZSB0aGUgTmF2aWdhdGlvbkNhbmNlbFxuICAgICAgICAgICAgICAgICAgICAgICAgKiBldmVudCBpcyBmaXJlZCB3aGVuIGEgbmF2aWdhdGlvbiBnZXRzIGNhbmNlbGxlZCBidXQgbm90IGNhdWdodCBieSBvdGhlclxuICAgICAgICAgICAgICAgICAgICAgICAgKiBtZWFucy4gKi9cbiAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGV0ZWQgJiYgIWVycm9yZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5jZWxhdGlvblJlYXNvbiA9IGBOYXZpZ2F0aW9uIElEICR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQuaWR9IGlzIG5vdCBlcXVhbCB0byB0aGUgY3VycmVudCBuYXZpZ2F0aW9uIGlkICR7dGhpcy5uYXZpZ2F0aW9uSWR9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAncmVwbGFjZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE11c3QgcmVzZXQgdG8gY3VycmVudCBVUkwgdHJlZSBoZXJlIHRvIGVuc3VyZSBoaXN0b3J5LnN0YXRlIGlzIHNldC4gT25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEgZnJlc2ggcGFnZSBsb2FkLCBpZiBhIG5ldyBuYXZpZ2F0aW9uIGNvbWVzIGluIGJlZm9yZSBhIHN1Y2Nlc3NmdWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5hdmlnYXRpb24gY29tcGxldGVzLCB0aGVyZSB3aWxsIGJlIG5vdGhpbmcgaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhpc3Rvcnkuc3RhdGUubmF2aWdhdGlvbklkLiBUaGlzIGNhbiBjYXVzZSBzeW5jIHByb2JsZW1zIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFuZ3VsYXJKUyBzeW5jIGNvZGUgd2hpY2ggbG9va3MgZm9yIGEgdmFsdWUgaGVyZSBpbiBvcmRlciB0byBkZXRlcm1pbmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdoZXRoZXIgb3Igbm90IHRvIGhhbmRsZSBhIGdpdmVuIHBvcHN0YXRlIGV2ZW50IG9yIHRvIGxlYXZlIGl0IHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQW5ndWxhciByb3V0ZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVIaXN0b3J5KHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW5jZWxOYXZpZ2F0aW9uVHJhbnNpdGlvbih0LCBjYW5jZWxhdGlvblJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbm5vdCB0cmlnZ2VyIGEgYGxvY2F0aW9uLmhpc3RvcnlHb2AgaWYgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjYW5jZWxsYXRpb24gd2FzIGR1ZSB0byBhIG5ldyBuYXZpZ2F0aW9uIGJlZm9yZSB0aGUgcHJldmlvdXMgY291bGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbXBsZXRlLiBUaGlzIGlzIGJlY2F1c2UgYGxvY2F0aW9uLmhpc3RvcnlHb2AgdHJpZ2dlcnMgYSBgcG9wc3RhdGVgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGljaCB3b3VsZCBhbHNvIHRyaWdnZXIgYW5vdGhlciBuYXZpZ2F0aW9uLiBJbnN0ZWFkLCB0cmVhdCB0aGlzIGFzIGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlZGlyZWN0IGFuZCBkbyBub3QgcmVzZXQgdGhlIHN0YXRlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW5jZWxOYXZpZ2F0aW9uVHJhbnNpdGlvbih0LCBjYW5jZWxhdGlvblJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGF0c2NvdHQpOiBUaGUgc2FtZSBwcm9ibGVtIGhhcHBlbnMgaGVyZSB3aXRoIGEgZnJlc2ggcGFnZSBsb2FkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbmQgYSBuZXcgbmF2aWdhdGlvbiBiZWZvcmUgdGhhdCBjb21wbGV0ZXMgd2hlcmUgd2Ugd29uJ3Qgc2V0IGEgcGFnZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgIC8vIGN1cnJlbnROYXZpZ2F0aW9uIHNob3VsZCBhbHdheXMgYmUgcmVzZXQgdG8gbnVsbCBoZXJlLiBJZiBuYXZpZ2F0aW9uIHdhc1xuICAgICAgICAgICAgICAgICAgICAgICAvLyBzdWNjZXNzZnVsLCBsYXN0U3VjY2Vzc2Z1bFRyYW5zaXRpb24gd2lsbCBoYXZlIGFscmVhZHkgYmVlbiBzZXQuIFRoZXJlZm9yZVxuICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBjYW4gc2FmZWx5IHNldCBjdXJyZW50TmF2aWdhdGlvbiB0byBudWxsIGhlcmUuXG4gICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudE5hdmlnYXRpb24gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICBjYXRjaEVycm9yKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE8oYXRzY290dCk6IFRoZSBOYXZpZ2F0aW9uVHJhbnNpdGlvbiBgdGAgdXNlZCBoZXJlIGRvZXMgbm90IGFjY3VyYXRlbHlcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVmbGVjdCB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgd2hvbGUgdHJhbnNpdGlvbiBiZWNhdXNlIHNvbWUgb3BlcmF0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm4gYSBuZXcgb2JqZWN0IHJhdGhlciB0aGFuIG1vZGlmeWluZyB0aGUgb25lIGluIHRoZSBvdXRlcm1vc3RcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gYHN3aXRjaE1hcGAuXG4gICAgICAgICAgICAgICAgICAgICAgIC8vICBUaGUgZml4IGNhbiBsaWtlbHkgYmUgdG86XG4gICAgICAgICAgICAgICAgICAgICAgIC8vICAxLiBSZW5hbWUgdGhlIG91dGVyIGB0YCB2YXJpYWJsZSBzbyBpdCdzIG5vdCBzaGFkb3dlZCBhbGwgdGhlIHRpbWUgYW5kXG4gICAgICAgICAgICAgICAgICAgICAgIC8vICBjb25mdXNpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gIDIuIEtlZXAgcmVhc3NpZ25pbmcgdG8gdGhlIG91dGVyIHZhcmlhYmxlIGFmdGVyIGVhY2ggc3RhZ2UgdG8gZW5zdXJlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgIC8vICBnZXRzIHVwZGF0ZWQuIE9yIGNoYW5nZSB0aGUgaW1wbGVtZW50YXRpb25zIHRvIG5vdCByZXR1cm4gYSBjb3B5LlxuICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3QgY2hhbmdlZCB5ZXQgYmVjYXVzZSBpdCBhZmZlY3RzIGV4aXN0aW5nIGNvZGUgYW5kIHdvdWxkIG5lZWQgdG8gYmVcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gdGVzdGVkIG1vcmUgdGhvcm91Z2hseS5cbiAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgIC8qIFRoaXMgZXJyb3IgdHlwZSBpcyBpc3N1ZWQgZHVyaW5nIFJlZGlyZWN0LCBhbmQgaXMgaGFuZGxlZCBhcyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAqIGNhbmNlbGxhdGlvbiByYXRoZXIgdGhhbiBhbiBlcnJvci4gKi9cbiAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmF2aWdhdGlvbkNhbmNlbGluZ0Vycm9yKGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVkaXJlY3RpbmcgPSBpc1VybFRyZWUoZS51cmwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcmVkaXJlY3RpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBwcm9wZXJ0eSBvbmx5IGlmIHdlJ3JlIG5vdCByZWRpcmVjdGluZy4gSWYgd2UgbGFuZGVkIG9uIGEgcGFnZSBhbmRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlZGlyZWN0IHRvIGAvYCByb3V0ZSwgdGhlIG5ldyBuYXZpZ2F0aW9uIGlzIGdvaW5nIHRvIHNlZSB0aGUgYC9gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpc24ndCBhIGNoYW5nZSBmcm9tIHRoZSBkZWZhdWx0IGN1cnJlbnRVcmxUcmVlIGFuZCB3b24ndCBuYXZpZ2F0ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgb25seSBhcHBsaWNhYmxlIHdpdGggaW5pdGlhbCBuYXZpZ2F0aW9uLCBzbyBzZXR0aW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBgbmF2aWdhdGVkYCBvbmx5IHdoZW4gbm90IHJlZGlyZWN0aW5nIHJlc29sdmVzIHRoaXMgc2NlbmFyaW8uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdmlnYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVIaXN0b3J5KHQsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuYXZDYW5jZWwgPSBuZXcgTmF2aWdhdGlvbkNhbmNlbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLCBlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c1N1YmplY3QubmV4dChuYXZDYW5jZWwpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiByZWRpcmVjdGluZywgd2UgbmVlZCB0byBkZWxheSByZXNvbHZpbmcgdGhlIG5hdmlnYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwcm9taXNlIGFuZCBwdXNoIGl0IHRvIHRoZSByZWRpcmVjdCBuYXZpZ2F0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZWRpcmVjdGluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5yZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2V0VGltZW91dCBpcyByZXF1aXJlZCBzbyB0aGlzIG5hdmlnYXRpb24gZmluaXNoZXMgd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHJldHVybiBFTVBUWSBiZWxvdy4gSWYgaXQgaXNuJ3QgYWxsb3dlZCB0byBmaW5pc2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByb2Nlc3NpbmcsIHRoZXJlIGNhbiBiZSBtdWx0aXBsZSBuYXZpZ2F0aW9ucyB0byB0aGUgc2FtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVVJMLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1lcmdlZFRyZWUgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51cmxIYW5kbGluZ1N0cmF0ZWd5Lm1lcmdlKGUudXJsLCB0aGlzLnJhd1VybFRyZWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRyYXMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcExvY2F0aW9uQ2hhbmdlOiB0LmV4dHJhcy5za2lwTG9jYXRpb25DaGFuZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIFVSTCBpcyBhbHJlYWR5IHVwZGF0ZWQgYXQgdGhpcyBwb2ludCBpZiB3ZSBoYXZlICdlYWdlcicgVVJMXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdXBkYXRlcyBvciBpZiB0aGUgbmF2aWdhdGlvbiB3YXMgdHJpZ2dlcmVkIGJ5IHRoZSBicm93c2VyIChiYWNrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0dG9uLCBVUkwgYmFyLCBldGMpLiBXZSB3YW50IHRvIHJlcGxhY2UgdGhhdCBpdGVtIGluIGhpc3RvcnkgaWZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbmF2aWdhdGlvbiBpcyByZWplY3RlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlVXJsOiB0aGlzLnVybFVwZGF0ZVN0cmF0ZWd5ID09PSAnZWFnZXInIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQnJvd3NlclRyaWdnZXJlZE5hdmlnYXRpb24odC5zb3VyY2UpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zY2hlZHVsZU5hdmlnYXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZWRUcmVlLCAnaW1wZXJhdGl2ZScsIG51bGwsIGV4dHJhcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtyZXNvbHZlOiB0LnJlc29sdmUsIHJlamVjdDogdC5yZWplY3QsIHByb21pc2U6IHQucHJvbWlzZX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgLyogQWxsIG90aGVyIGVycm9ycyBzaG91bGQgcmVzZXQgdG8gdGhlIHJvdXRlcidzIGludGVybmFsIFVSTCByZWZlcmVuY2UgdG9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKiB0aGUgcHJlLWVycm9yIHN0YXRlLiAqL1xuICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZUhpc3RvcnkodCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmF2RXJyb3IgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgTmF2aWdhdGlvbkVycm9yKHQuaWQsIHRoaXMuc2VyaWFsaXplVXJsKHQuZXh0cmFjdGVkVXJsKSwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzU3ViamVjdC5uZXh0KG5hdkVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5yZXNvbHZlKHRoaXMuZXJyb3JIYW5kbGVyKGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgdC5yZWplY3QoZWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRU1QVFk7XG4gICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgIC8vIFRPRE8oamFzb25hZGVuKTogcmVtb3ZlIGNhc3Qgb25jZSBnMyBpcyBvbiB1cGRhdGVkIFR5cGVTY3JpcHRcbiAgICAgICAgICAgICAgIH0pKSBhcyBhbnkgYXMgT2JzZXJ2YWJsZTxOYXZpZ2F0aW9uVHJhbnNpdGlvbj47XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqIFRPRE86IHRoaXMgc2hvdWxkIGJlIHJlbW92ZWQgb25jZSB0aGUgY29uc3RydWN0b3Igb2YgdGhlIHJvdXRlciBtYWRlIGludGVybmFsXG4gICAqL1xuICByZXNldFJvb3RDb21wb25lbnRUeXBlKHJvb3RDb21wb25lbnRUeXBlOiBUeXBlPGFueT4pOiB2b2lkIHtcbiAgICB0aGlzLnJvb3RDb21wb25lbnRUeXBlID0gcm9vdENvbXBvbmVudFR5cGU7XG4gICAgLy8gVE9ETzogdnNhdmtpbiByb3V0ZXIgNC4wIHNob3VsZCBtYWtlIHRoZSByb290IGNvbXBvbmVudCBzZXQgdG8gbnVsbFxuICAgIC8vIHRoaXMgd2lsbCBzaW1wbGlmeSB0aGUgbGlmZWN5Y2xlIG9mIHRoZSByb3V0ZXIuXG4gICAgdGhpcy5yb3V0ZXJTdGF0ZS5yb290LmNvbXBvbmVudCA9IHRoaXMucm9vdENvbXBvbmVudFR5cGU7XG4gIH1cblxuICBwcml2YXRlIGdldFRyYW5zaXRpb24oKTogTmF2aWdhdGlvblRyYW5zaXRpb24ge1xuICAgIGNvbnN0IHRyYW5zaXRpb24gPSB0aGlzLnRyYW5zaXRpb25zLnZhbHVlO1xuICAgIC8vIFRPRE8oYXRzY290dCk6IFRoaXMgY29tbWVudCBkb2Vzbid0IG1ha2UgaXQgY2xlYXIgd2h5IHRoaXMgdmFsdWUgbmVlZHMgdG8gYmUgc2V0LiBJbiB0aGUgY2FzZVxuICAgIC8vIGRlc2NyaWJlZCBiZWxvdyAod2hlcmUgd2UgZG9uJ3QgaGFuZGxlIHByZXZpb3VzIG9yIGN1cnJlbnQgdXJsKSwgdGhlIGBicm93c2VyVXJsVHJlZWAgaXMgc2V0XG4gICAgLy8gdG8gdGhlIGB1cmxBZnRlclJlZGlyZWN0c2AgdmFsdWUuIEhvd2V2ZXIsIHRoZXNlIHZhbHVlcyAqYXJlIGFscmVhZHkgdGhlIHNhbWUqIGJlY2F1c2Ugb2YgdGhlXG4gICAgLy8gbGluZSBiZWxvdy4gU28gaXQgc2VlbXMgdGhhdCB3ZSBzaG91bGQgYmUgYWJsZSB0byByZW1vdmUgdGhlIGxpbmUgYmVsb3cgYW5kIHRoZSBsaW5lIHdoZXJlXG4gICAgLy8gYGJyb3dzZXJVcmxUcmVlYCBpcyB1cGRhdGVkIHdoZW4gd2UgYXJlbid0IGhhbmRsaW5nIGFueSBwYXJ0IG9mIHRoZSBuYXZpZ2F0aW9uIHVybC5cbiAgICAvLyBSdW4gVEdQIHRvIGNvbmZpcm0gdGhhdCB0aGlzIGNhbiBiZSBkb25lLlxuXG4gICAgLy8gVGhpcyB2YWx1ZSBuZWVkcyB0byBiZSBzZXQuIE90aGVyIHZhbHVlcyBzdWNoIGFzIGV4dHJhY3RlZFVybCBhcmUgc2V0IG9uIGluaXRpYWwgbmF2aWdhdGlvblxuICAgIC8vIGJ1dCB0aGUgdXJsQWZ0ZXJSZWRpcmVjdHMgbWF5IG5vdCBnZXQgc2V0IGlmIHdlIGFyZW4ndCBwcm9jZXNzaW5nIHRoZSBuZXcgVVJMICphbmQqIG5vdFxuICAgIC8vIHByb2Nlc3NpbmcgdGhlIHByZXZpb3VzIFVSTC5cbiAgICB0cmFuc2l0aW9uLnVybEFmdGVyUmVkaXJlY3RzID0gdGhpcy5icm93c2VyVXJsVHJlZTtcbiAgICByZXR1cm4gdHJhbnNpdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgc2V0VHJhbnNpdGlvbih0OiBQYXJ0aWFsPE5hdmlnYXRpb25UcmFuc2l0aW9uPik6IHZvaWQge1xuICAgIHRoaXMudHJhbnNpdGlvbnMubmV4dCh7Li4udGhpcy5nZXRUcmFuc2l0aW9uKCksIC4uLnR9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHVwIHRoZSBsb2NhdGlvbiBjaGFuZ2UgbGlzdGVuZXIgYW5kIHBlcmZvcm1zIHRoZSBpbml0aWFsIG5hdmlnYXRpb24uXG4gICAqL1xuICBpbml0aWFsTmF2aWdhdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLnNldFVwTG9jYXRpb25DaGFuZ2VMaXN0ZW5lcigpO1xuICAgIGlmICh0aGlzLm5hdmlnYXRpb25JZCA9PT0gMCkge1xuICAgICAgdGhpcy5uYXZpZ2F0ZUJ5VXJsKHRoaXMubG9jYXRpb24ucGF0aCh0cnVlKSwge3JlcGxhY2VVcmw6IHRydWV9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCB0aGUgbG9jYXRpb24gY2hhbmdlIGxpc3RlbmVyLiBUaGlzIGxpc3RlbmVyIGRldGVjdHMgbmF2aWdhdGlvbnMgdHJpZ2dlcmVkIGZyb20gb3V0c2lkZVxuICAgKiB0aGUgUm91dGVyICh0aGUgYnJvd3NlciBiYWNrL2ZvcndhcmQgYnV0dG9ucywgZm9yIGV4YW1wbGUpIGFuZCBzY2hlZHVsZXMgYSBjb3JyZXNwb25kaW5nIFJvdXRlclxuICAgKiBuYXZpZ2F0aW9uIHNvIHRoYXQgdGhlIGNvcnJlY3QgZXZlbnRzLCBndWFyZHMsIGV0Yy4gYXJlIHRyaWdnZXJlZC5cbiAgICovXG4gIHNldFVwTG9jYXRpb25DaGFuZ2VMaXN0ZW5lcigpOiB2b2lkIHtcbiAgICAvLyBEb24ndCBuZWVkIHRvIHVzZSBab25lLndyYXAgYW55IG1vcmUsIGJlY2F1c2Ugem9uZS5qc1xuICAgIC8vIGFscmVhZHkgcGF0Y2ggb25Qb3BTdGF0ZSwgc28gbG9jYXRpb24gY2hhbmdlIGNhbGxiYWNrIHdpbGxcbiAgICAvLyBydW4gaW50byBuZ1pvbmVcbiAgICBpZiAoIXRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24gPSB0aGlzLmxvY2F0aW9uLnN1YnNjcmliZShldmVudCA9PiB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRDaGFuZ2UgPSB0aGlzLmV4dHJhY3RMb2NhdGlvbkNoYW5nZUluZm9Gcm9tRXZlbnQoZXZlbnQpO1xuICAgICAgICAvLyBUaGUgYHNldFRpbWVvdXRgIHdhcyBhZGRlZCBpbiAjMTIxNjAgYW5kIGlzIGxpa2VseSB0byBzdXBwb3J0IEFuZ3VsYXIvQW5ndWxhckpTXG4gICAgICAgIC8vIGh5YnJpZCBhcHBzLlxuICAgICAgICBpZiAodGhpcy5zaG91bGRTY2hlZHVsZU5hdmlnYXRpb24odGhpcy5sYXN0TG9jYXRpb25DaGFuZ2VJbmZvLCBjdXJyZW50Q2hhbmdlKSkge1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qge3NvdXJjZSwgc3RhdGUsIHVybFRyZWV9ID0gY3VycmVudENoYW5nZTtcbiAgICAgICAgICAgIGNvbnN0IGV4dHJhczogTmF2aWdhdGlvbkV4dHJhcyA9IHtyZXBsYWNlVXJsOiB0cnVlfTtcbiAgICAgICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgICAgICBjb25zdCBzdGF0ZUNvcHkgPSB7Li4uc3RhdGV9IGFzIFBhcnRpYWw8UmVzdG9yZWRTdGF0ZT47XG4gICAgICAgICAgICAgIGRlbGV0ZSBzdGF0ZUNvcHkubmF2aWdhdGlvbklkO1xuICAgICAgICAgICAgICBkZWxldGUgc3RhdGVDb3B5Lsm1cm91dGVyUGFnZUlkO1xuICAgICAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoc3RhdGVDb3B5KS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICBleHRyYXMuc3RhdGUgPSBzdGF0ZUNvcHk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2NoZWR1bGVOYXZpZ2F0aW9uKHVybFRyZWUsIHNvdXJjZSwgc3RhdGUsIGV4dHJhcyk7XG4gICAgICAgICAgfSwgMCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sYXN0TG9jYXRpb25DaGFuZ2VJbmZvID0gY3VycmVudENoYW5nZTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBFeHRyYWN0cyByb3V0ZXItcmVsYXRlZCBpbmZvcm1hdGlvbiBmcm9tIGEgYFBvcFN0YXRlRXZlbnRgLiAqL1xuICBwcml2YXRlIGV4dHJhY3RMb2NhdGlvbkNoYW5nZUluZm9Gcm9tRXZlbnQoY2hhbmdlOiBQb3BTdGF0ZUV2ZW50KTogTG9jYXRpb25DaGFuZ2VJbmZvIHtcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlOiBjaGFuZ2VbJ3R5cGUnXSA9PT0gJ3BvcHN0YXRlJyA/ICdwb3BzdGF0ZScgOiAnaGFzaGNoYW5nZScsXG4gICAgICB1cmxUcmVlOiB0aGlzLnBhcnNlVXJsKGNoYW5nZVsndXJsJ10hKSxcbiAgICAgIC8vIE5hdmlnYXRpb25zIGNvbWluZyBmcm9tIEFuZ3VsYXIgcm91dGVyIGhhdmUgYSBuYXZpZ2F0aW9uSWQgc3RhdGVcbiAgICAgIC8vIHByb3BlcnR5LiBXaGVuIHRoaXMgZXhpc3RzLCByZXN0b3JlIHRoZSBzdGF0ZS5cbiAgICAgIHN0YXRlOiBjaGFuZ2Uuc3RhdGU/Lm5hdmlnYXRpb25JZCA/IGNoYW5nZS5zdGF0ZSA6IG51bGwsXG4gICAgICB0cmFuc2l0aW9uSWQ6IHRoaXMuZ2V0VHJhbnNpdGlvbigpLmlkXG4gICAgfSBhcyBjb25zdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdHdvIGV2ZW50cyB0cmlnZ2VyZWQgYnkgdGhlIExvY2F0aW9uIHN1YnNjcmlwdGlvbiBhcmUgZHVlIHRvIHRoZSBzYW1lXG4gICAqIG5hdmlnYXRpb24uIFRoZSBsb2NhdGlvbiBzdWJzY3JpcHRpb24gY2FuIGZpcmUgdHdvIGV2ZW50cyAocG9wc3RhdGUgYW5kIGhhc2hjaGFuZ2UpIGZvciBhXG4gICAqIHNpbmdsZSBuYXZpZ2F0aW9uLiBUaGUgc2Vjb25kIG9uZSBzaG91bGQgYmUgaWdub3JlZCwgdGhhdCBpcywgd2Ugc2hvdWxkIG5vdCBzY2hlZHVsZSBhbm90aGVyXG4gICAqIG5hdmlnYXRpb24gaW4gdGhlIFJvdXRlci5cbiAgICovXG4gIHByaXZhdGUgc2hvdWxkU2NoZWR1bGVOYXZpZ2F0aW9uKHByZXZpb3VzOiBMb2NhdGlvbkNoYW5nZUluZm98bnVsbCwgY3VycmVudDogTG9jYXRpb25DaGFuZ2VJbmZvKTpcbiAgICAgIGJvb2xlYW4ge1xuICAgIGlmICghcHJldmlvdXMpIHJldHVybiB0cnVlO1xuXG4gICAgY29uc3Qgc2FtZURlc3RpbmF0aW9uID0gY3VycmVudC51cmxUcmVlLnRvU3RyaW5nKCkgPT09IHByZXZpb3VzLnVybFRyZWUudG9TdHJpbmcoKTtcbiAgICBjb25zdCBldmVudHNPY2N1cnJlZEF0U2FtZVRpbWUgPSBjdXJyZW50LnRyYW5zaXRpb25JZCA9PT0gcHJldmlvdXMudHJhbnNpdGlvbklkO1xuICAgIGlmICghZXZlbnRzT2NjdXJyZWRBdFNhbWVUaW1lIHx8ICFzYW1lRGVzdGluYXRpb24pIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmICgoY3VycmVudC5zb3VyY2UgPT09ICdoYXNoY2hhbmdlJyAmJiBwcmV2aW91cy5zb3VyY2UgPT09ICdwb3BzdGF0ZScpIHx8XG4gICAgICAgIChjdXJyZW50LnNvdXJjZSA9PT0gJ3BvcHN0YXRlJyAmJiBwcmV2aW91cy5zb3VyY2UgPT09ICdoYXNoY2hhbmdlJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBUaGUgY3VycmVudCBVUkwuICovXG4gIGdldCB1cmwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVVcmwodGhpcy5jdXJyZW50VXJsVHJlZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBgTmF2aWdhdGlvbmAgb2JqZWN0IHdoZW4gdGhlIHJvdXRlciBpcyBuYXZpZ2F0aW5nLFxuICAgKiBhbmQgYG51bGxgIHdoZW4gaWRsZS5cbiAgICovXG4gIGdldEN1cnJlbnROYXZpZ2F0aW9uKCk6IE5hdmlnYXRpb258bnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudE5hdmlnYXRpb247XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHRyaWdnZXJFdmVudChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICAodGhpcy5ldmVudHMgYXMgU3ViamVjdDxFdmVudD4pLm5leHQoZXZlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgcm91dGUgY29uZmlndXJhdGlvbiB1c2VkIGZvciBuYXZpZ2F0aW9uIGFuZCBnZW5lcmF0aW5nIGxpbmtzLlxuICAgKlxuICAgKiBAcGFyYW0gY29uZmlnIFRoZSByb3V0ZSBhcnJheSBmb3IgdGhlIG5ldyBjb25maWd1cmF0aW9uLlxuICAgKlxuICAgKiBAdXNhZ2VOb3Rlc1xuICAgKlxuICAgKiBgYGBcbiAgICogcm91dGVyLnJlc2V0Q29uZmlnKFtcbiAgICogIHsgcGF0aDogJ3RlYW0vOmlkJywgY29tcG9uZW50OiBUZWFtQ21wLCBjaGlsZHJlbjogW1xuICAgKiAgICB7IHBhdGg6ICdzaW1wbGUnLCBjb21wb25lbnQ6IFNpbXBsZUNtcCB9LFxuICAgKiAgICB7IHBhdGg6ICd1c2VyLzpuYW1lJywgY29tcG9uZW50OiBVc2VyQ21wIH1cbiAgICogIF19XG4gICAqIF0pO1xuICAgKiBgYGBcbiAgICovXG4gIHJlc2V0Q29uZmlnKGNvbmZpZzogUm91dGVzKTogdm9pZCB7XG4gICAgdmFsaWRhdGVDb25maWcoY29uZmlnKTtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZy5tYXAoc3RhbmRhcmRpemVDb25maWcpO1xuICAgIHRoaXMubmF2aWdhdGVkID0gZmFsc2U7XG4gICAgdGhpcy5sYXN0U3VjY2Vzc2Z1bElkID0gLTE7XG4gIH1cblxuICAvKiogQG5vZG9jICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGlzcG9zZSgpO1xuICB9XG5cbiAgLyoqIERpc3Bvc2VzIG9mIHRoZSByb3V0ZXIuICovXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy50cmFuc2l0aW9ucy5jb21wbGV0ZSgpO1xuICAgIGlmICh0aGlzLmxvY2F0aW9uU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLmxvY2F0aW9uU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLmxvY2F0aW9uU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmRzIFVSTCBzZWdtZW50cyB0byB0aGUgY3VycmVudCBVUkwgdHJlZSB0byBjcmVhdGUgYSBuZXcgVVJMIHRyZWUuXG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kcyBBbiBhcnJheSBvZiBVUkwgZnJhZ21lbnRzIHdpdGggd2hpY2ggdG8gY29uc3RydWN0IHRoZSBuZXcgVVJMIHRyZWUuXG4gICAqIElmIHRoZSBwYXRoIGlzIHN0YXRpYywgY2FuIGJlIHRoZSBsaXRlcmFsIFVSTCBzdHJpbmcuIEZvciBhIGR5bmFtaWMgcGF0aCwgcGFzcyBhbiBhcnJheSBvZiBwYXRoXG4gICAqIHNlZ21lbnRzLCBmb2xsb3dlZCBieSB0aGUgcGFyYW1ldGVycyBmb3IgZWFjaCBzZWdtZW50LlxuICAgKiBUaGUgZnJhZ21lbnRzIGFyZSBhcHBsaWVkIHRvIHRoZSBjdXJyZW50IFVSTCB0cmVlIG9yIHRoZSBvbmUgcHJvdmlkZWQgIGluIHRoZSBgcmVsYXRpdmVUb2BcbiAgICogcHJvcGVydHkgb2YgdGhlIG9wdGlvbnMgb2JqZWN0LCBpZiBzdXBwbGllZC5cbiAgICogQHBhcmFtIG5hdmlnYXRpb25FeHRyYXMgT3B0aW9ucyB0aGF0IGNvbnRyb2wgdGhlIG5hdmlnYXRpb24gc3RyYXRlZ3kuXG4gICAqIEByZXR1cm5zIFRoZSBuZXcgVVJMIHRyZWUuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqXG4gICAqIGBgYFxuICAgKiAvLyBjcmVhdGUgL3RlYW0vMzMvdXNlci8xMVxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy90ZWFtJywgMzMsICd1c2VyJywgMTFdKTtcbiAgICpcbiAgICogLy8gY3JlYXRlIC90ZWFtLzMzO2V4cGFuZD10cnVlL3VzZXIvMTFcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycvdGVhbScsIDMzLCB7ZXhwYW5kOiB0cnVlfSwgJ3VzZXInLCAxMV0pO1xuICAgKlxuICAgKiAvLyB5b3UgY2FuIGNvbGxhcHNlIHN0YXRpYyBzZWdtZW50cyBsaWtlIHRoaXMgKHRoaXMgd29ya3Mgb25seSB3aXRoIHRoZSBmaXJzdCBwYXNzZWQtaW4gdmFsdWUpOlxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy90ZWFtLzMzL3VzZXInLCB1c2VySWRdKTtcbiAgICpcbiAgICogLy8gSWYgdGhlIGZpcnN0IHNlZ21lbnQgY2FuIGNvbnRhaW4gc2xhc2hlcywgYW5kIHlvdSBkbyBub3Qgd2FudCB0aGUgcm91dGVyIHRvIHNwbGl0IGl0LFxuICAgKiAvLyB5b3UgY2FuIGRvIHRoZSBmb2xsb3dpbmc6XG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFt7c2VnbWVudFBhdGg6ICcvb25lL3R3byd9XSk7XG4gICAqXG4gICAqIC8vIGNyZWF0ZSAvdGVhbS8zMy8odXNlci8xMS8vcmlnaHQ6Y2hhdClcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycvdGVhbScsIDMzLCB7b3V0bGV0czoge3ByaW1hcnk6ICd1c2VyLzExJywgcmlnaHQ6ICdjaGF0J319XSk7XG4gICAqXG4gICAqIC8vIHJlbW92ZSB0aGUgcmlnaHQgc2Vjb25kYXJ5IG5vZGVcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycvdGVhbScsIDMzLCB7b3V0bGV0czoge3ByaW1hcnk6ICd1c2VyLzExJywgcmlnaHQ6IG51bGx9fV0pO1xuICAgKlxuICAgKiAvLyBhc3N1bWluZyB0aGUgY3VycmVudCB1cmwgaXMgYC90ZWFtLzMzL3VzZXIvMTFgIGFuZCB0aGUgcm91dGUgcG9pbnRzIHRvIGB1c2VyLzExYFxuICAgKlxuICAgKiAvLyBuYXZpZ2F0ZSB0byAvdGVhbS8zMy91c2VyLzExL2RldGFpbHNcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWydkZXRhaWxzJ10sIHtyZWxhdGl2ZVRvOiByb3V0ZX0pO1xuICAgKlxuICAgKiAvLyBuYXZpZ2F0ZSB0byAvdGVhbS8zMy91c2VyLzIyXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnLi4vMjInXSwge3JlbGF0aXZlVG86IHJvdXRlfSk7XG4gICAqXG4gICAqIC8vIG5hdmlnYXRlIHRvIC90ZWFtLzQ0L3VzZXIvMjJcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycuLi8uLi90ZWFtLzQ0L3VzZXIvMjInXSwge3JlbGF0aXZlVG86IHJvdXRlfSk7XG4gICAqXG4gICAqIE5vdGUgdGhhdCBhIHZhbHVlIG9mIGBudWxsYCBvciBgdW5kZWZpbmVkYCBmb3IgYHJlbGF0aXZlVG9gIGluZGljYXRlcyB0aGF0IHRoZVxuICAgKiB0cmVlIHNob3VsZCBiZSBjcmVhdGVkIHJlbGF0aXZlIHRvIHRoZSByb290LlxuICAgKiBgYGBcbiAgICovXG4gIGNyZWF0ZVVybFRyZWUoY29tbWFuZHM6IGFueVtdLCBuYXZpZ2F0aW9uRXh0cmFzOiBVcmxDcmVhdGlvbk9wdGlvbnMgPSB7fSk6IFVybFRyZWUge1xuICAgIGNvbnN0IHtyZWxhdGl2ZVRvLCBxdWVyeVBhcmFtcywgZnJhZ21lbnQsIHF1ZXJ5UGFyYW1zSGFuZGxpbmcsIHByZXNlcnZlRnJhZ21lbnR9ID1cbiAgICAgICAgbmF2aWdhdGlvbkV4dHJhcztcbiAgICBjb25zdCBhID0gcmVsYXRpdmVUbyB8fCB0aGlzLnJvdXRlclN0YXRlLnJvb3Q7XG4gICAgY29uc3QgZiA9IHByZXNlcnZlRnJhZ21lbnQgPyB0aGlzLmN1cnJlbnRVcmxUcmVlLmZyYWdtZW50IDogZnJhZ21lbnQ7XG4gICAgbGV0IHE6IFBhcmFtc3xudWxsID0gbnVsbDtcbiAgICBzd2l0Y2ggKHF1ZXJ5UGFyYW1zSGFuZGxpbmcpIHtcbiAgICAgIGNhc2UgJ21lcmdlJzpcbiAgICAgICAgcSA9IHsuLi50aGlzLmN1cnJlbnRVcmxUcmVlLnF1ZXJ5UGFyYW1zLCAuLi5xdWVyeVBhcmFtc307XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncHJlc2VydmUnOlxuICAgICAgICBxID0gdGhpcy5jdXJyZW50VXJsVHJlZS5xdWVyeVBhcmFtcztcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBxID0gcXVlcnlQYXJhbXMgfHwgbnVsbDtcbiAgICB9XG4gICAgaWYgKHEgIT09IG51bGwpIHtcbiAgICAgIHEgPSB0aGlzLnJlbW92ZUVtcHR5UHJvcHMocSk7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVVcmxUcmVlKGEsIHRoaXMuY3VycmVudFVybFRyZWUsIGNvbW1hbmRzLCBxLCBmID8/IG51bGwpO1xuICB9XG5cbiAgLyoqXG4gICAqIE5hdmlnYXRlcyB0byBhIHZpZXcgdXNpbmcgYW4gYWJzb2x1dGUgcm91dGUgcGF0aC5cbiAgICpcbiAgICogQHBhcmFtIHVybCBBbiBhYnNvbHV0ZSBwYXRoIGZvciBhIGRlZmluZWQgcm91dGUuIFRoZSBmdW5jdGlvbiBkb2VzIG5vdCBhcHBseSBhbnkgZGVsdGEgdG8gdGhlXG4gICAqICAgICBjdXJyZW50IFVSTC5cbiAgICogQHBhcmFtIGV4dHJhcyBBbiBvYmplY3QgY29udGFpbmluZyBwcm9wZXJ0aWVzIHRoYXQgbW9kaWZ5IHRoZSBuYXZpZ2F0aW9uIHN0cmF0ZWd5LlxuICAgKlxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byAndHJ1ZScgd2hlbiBuYXZpZ2F0aW9uIHN1Y2NlZWRzLFxuICAgKiB0byAnZmFsc2UnIHdoZW4gbmF2aWdhdGlvbiBmYWlscywgb3IgaXMgcmVqZWN0ZWQgb24gZXJyb3IuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgY2FsbHMgcmVxdWVzdCBuYXZpZ2F0aW9uIHRvIGFuIGFic29sdXRlIHBhdGguXG4gICAqXG4gICAqIGBgYFxuICAgKiByb3V0ZXIubmF2aWdhdGVCeVVybChcIi90ZWFtLzMzL3VzZXIvMTFcIik7XG4gICAqXG4gICAqIC8vIE5hdmlnYXRlIHdpdGhvdXQgdXBkYXRpbmcgdGhlIFVSTFxuICAgKiByb3V0ZXIubmF2aWdhdGVCeVVybChcIi90ZWFtLzMzL3VzZXIvMTFcIiwgeyBza2lwTG9jYXRpb25DaGFuZ2U6IHRydWUgfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAc2VlIFtSb3V0aW5nIGFuZCBOYXZpZ2F0aW9uIGd1aWRlXShndWlkZS9yb3V0ZXIpXG4gICAqXG4gICAqL1xuICBuYXZpZ2F0ZUJ5VXJsKHVybDogc3RyaW5nfFVybFRyZWUsIGV4dHJhczogTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9ucyA9IHtcbiAgICBza2lwTG9jYXRpb25DaGFuZ2U6IGZhbHNlXG4gIH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgbmdEZXZNb2RlICYmIHRoaXMuaXNOZ1pvbmVFbmFibGVkICYmICFOZ1pvbmUuaXNJbkFuZ3VsYXJab25lKCkpIHtcbiAgICAgIHRoaXMuY29uc29sZS53YXJuKFxuICAgICAgICAgIGBOYXZpZ2F0aW9uIHRyaWdnZXJlZCBvdXRzaWRlIEFuZ3VsYXIgem9uZSwgZGlkIHlvdSBmb3JnZXQgdG8gY2FsbCAnbmdab25lLnJ1bigpJz9gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1cmxUcmVlID0gaXNVcmxUcmVlKHVybCkgPyB1cmwgOiB0aGlzLnBhcnNlVXJsKHVybCk7XG4gICAgY29uc3QgbWVyZ2VkVHJlZSA9IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5tZXJnZSh1cmxUcmVlLCB0aGlzLnJhd1VybFRyZWUpO1xuXG4gICAgcmV0dXJuIHRoaXMuc2NoZWR1bGVOYXZpZ2F0aW9uKG1lcmdlZFRyZWUsICdpbXBlcmF0aXZlJywgbnVsbCwgZXh0cmFzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBOYXZpZ2F0ZSBiYXNlZCBvbiB0aGUgcHJvdmlkZWQgYXJyYXkgb2YgY29tbWFuZHMgYW5kIGEgc3RhcnRpbmcgcG9pbnQuXG4gICAqIElmIG5vIHN0YXJ0aW5nIHJvdXRlIGlzIHByb3ZpZGVkLCB0aGUgbmF2aWdhdGlvbiBpcyBhYnNvbHV0ZS5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1hbmRzIEFuIGFycmF5IG9mIFVSTCBmcmFnbWVudHMgd2l0aCB3aGljaCB0byBjb25zdHJ1Y3QgdGhlIHRhcmdldCBVUkwuXG4gICAqIElmIHRoZSBwYXRoIGlzIHN0YXRpYywgY2FuIGJlIHRoZSBsaXRlcmFsIFVSTCBzdHJpbmcuIEZvciBhIGR5bmFtaWMgcGF0aCwgcGFzcyBhbiBhcnJheSBvZiBwYXRoXG4gICAqIHNlZ21lbnRzLCBmb2xsb3dlZCBieSB0aGUgcGFyYW1ldGVycyBmb3IgZWFjaCBzZWdtZW50LlxuICAgKiBUaGUgZnJhZ21lbnRzIGFyZSBhcHBsaWVkIHRvIHRoZSBjdXJyZW50IFVSTCBvciB0aGUgb25lIHByb3ZpZGVkICBpbiB0aGUgYHJlbGF0aXZlVG9gIHByb3BlcnR5XG4gICAqIG9mIHRoZSBvcHRpb25zIG9iamVjdCwgaWYgc3VwcGxpZWQuXG4gICAqIEBwYXJhbSBleHRyYXMgQW4gb3B0aW9ucyBvYmplY3QgdGhhdCBkZXRlcm1pbmVzIGhvdyB0aGUgVVJMIHNob3VsZCBiZSBjb25zdHJ1Y3RlZCBvclxuICAgKiAgICAgaW50ZXJwcmV0ZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGB0cnVlYCB3aGVuIG5hdmlnYXRpb24gc3VjY2VlZHMsIHRvIGBmYWxzZWAgd2hlbiBuYXZpZ2F0aW9uXG4gICAqICAgICBmYWlscyxcbiAgICogb3IgaXMgcmVqZWN0ZWQgb24gZXJyb3IuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgY2FsbHMgcmVxdWVzdCBuYXZpZ2F0aW9uIHRvIGEgZHluYW1pYyByb3V0ZSBwYXRoIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IFVSTC5cbiAgICpcbiAgICogYGBgXG4gICAqIHJvdXRlci5uYXZpZ2F0ZShbJ3RlYW0nLCAzMywgJ3VzZXInLCAxMV0sIHtyZWxhdGl2ZVRvOiByb3V0ZX0pO1xuICAgKlxuICAgKiAvLyBOYXZpZ2F0ZSB3aXRob3V0IHVwZGF0aW5nIHRoZSBVUkwsIG92ZXJyaWRpbmcgdGhlIGRlZmF1bHQgYmVoYXZpb3JcbiAgICogcm91dGVyLm5hdmlnYXRlKFsndGVhbScsIDMzLCAndXNlcicsIDExXSwge3JlbGF0aXZlVG86IHJvdXRlLCBza2lwTG9jYXRpb25DaGFuZ2U6IHRydWV9KTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBzZWUgW1JvdXRpbmcgYW5kIE5hdmlnYXRpb24gZ3VpZGVdKGd1aWRlL3JvdXRlcilcbiAgICpcbiAgICovXG4gIG5hdmlnYXRlKGNvbW1hbmRzOiBhbnlbXSwgZXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzID0ge3NraXBMb2NhdGlvbkNoYW5nZTogZmFsc2V9KTpcbiAgICAgIFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHZhbGlkYXRlQ29tbWFuZHMoY29tbWFuZHMpO1xuICAgIHJldHVybiB0aGlzLm5hdmlnYXRlQnlVcmwodGhpcy5jcmVhdGVVcmxUcmVlKGNvbW1hbmRzLCBleHRyYXMpLCBleHRyYXMpO1xuICB9XG5cbiAgLyoqIFNlcmlhbGl6ZXMgYSBgVXJsVHJlZWAgaW50byBhIHN0cmluZyAqL1xuICBzZXJpYWxpemVVcmwodXJsOiBVcmxUcmVlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy51cmxTZXJpYWxpemVyLnNlcmlhbGl6ZSh1cmwpO1xuICB9XG5cbiAgLyoqIFBhcnNlcyBhIHN0cmluZyBpbnRvIGEgYFVybFRyZWVgICovXG4gIHBhcnNlVXJsKHVybDogc3RyaW5nKTogVXJsVHJlZSB7XG4gICAgbGV0IHVybFRyZWU6IFVybFRyZWU7XG4gICAgdHJ5IHtcbiAgICAgIHVybFRyZWUgPSB0aGlzLnVybFNlcmlhbGl6ZXIucGFyc2UodXJsKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB1cmxUcmVlID0gdGhpcy5tYWxmb3JtZWRVcmlFcnJvckhhbmRsZXIoZSwgdGhpcy51cmxTZXJpYWxpemVyLCB1cmwpO1xuICAgIH1cbiAgICByZXR1cm4gdXJsVHJlZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHVybCBpcyBhY3RpdmF0ZWQuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkXG4gICAqIFVzZSBgSXNBY3RpdmVNYXRjaE9wdGlvbnNgIGluc3RlYWQuXG4gICAqXG4gICAqIC0gVGhlIGVxdWl2YWxlbnQgYElzQWN0aXZlTWF0Y2hPcHRpb25zYCBmb3IgYHRydWVgIGlzXG4gICAqIGB7cGF0aHM6ICdleGFjdCcsIHF1ZXJ5UGFyYW1zOiAnZXhhY3QnLCBmcmFnbWVudDogJ2lnbm9yZWQnLCBtYXRyaXhQYXJhbXM6ICdpZ25vcmVkJ31gLlxuICAgKiAtIFRoZSBlcXVpdmFsZW50IGZvciBgZmFsc2VgIGlzXG4gICAqIGB7cGF0aHM6ICdzdWJzZXQnLCBxdWVyeVBhcmFtczogJ3N1YnNldCcsIGZyYWdtZW50OiAnaWdub3JlZCcsIG1hdHJpeFBhcmFtczogJ2lnbm9yZWQnfWAuXG4gICAqL1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBleGFjdDogYm9vbGVhbik6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHVybCBpcyBhY3RpdmF0ZWQuXG4gICAqL1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBtYXRjaE9wdGlvbnM6IElzQWN0aXZlTWF0Y2hPcHRpb25zKTogYm9vbGVhbjtcbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBtYXRjaE9wdGlvbnM6IGJvb2xlYW58SXNBY3RpdmVNYXRjaE9wdGlvbnMpOiBib29sZWFuO1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBtYXRjaE9wdGlvbnM6IGJvb2xlYW58SXNBY3RpdmVNYXRjaE9wdGlvbnMpOiBib29sZWFuIHtcbiAgICBsZXQgb3B0aW9uczogSXNBY3RpdmVNYXRjaE9wdGlvbnM7XG4gICAgaWYgKG1hdGNoT3B0aW9ucyA9PT0gdHJ1ZSkge1xuICAgICAgb3B0aW9ucyA9IHsuLi5leGFjdE1hdGNoT3B0aW9uc307XG4gICAgfSBlbHNlIGlmIChtYXRjaE9wdGlvbnMgPT09IGZhbHNlKSB7XG4gICAgICBvcHRpb25zID0gey4uLnN1YnNldE1hdGNoT3B0aW9uc307XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wdGlvbnMgPSBtYXRjaE9wdGlvbnM7XG4gICAgfVxuICAgIGlmIChpc1VybFRyZWUodXJsKSkge1xuICAgICAgcmV0dXJuIGNvbnRhaW5zVHJlZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCB1cmwsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGNvbnN0IHVybFRyZWUgPSB0aGlzLnBhcnNlVXJsKHVybCk7XG4gICAgcmV0dXJuIGNvbnRhaW5zVHJlZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCB1cmxUcmVlLCBvcHRpb25zKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlRW1wdHlQcm9wcyhwYXJhbXM6IFBhcmFtcyk6IFBhcmFtcyB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHBhcmFtcykucmVkdWNlKChyZXN1bHQ6IFBhcmFtcywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlOiBhbnkgPSBwYXJhbXNba2V5XTtcbiAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIHt9KTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc05hdmlnYXRpb25zKCk6IHZvaWQge1xuICAgIHRoaXMubmF2aWdhdGlvbnMuc3Vic2NyaWJlKFxuICAgICAgICB0ID0+IHtcbiAgICAgICAgICB0aGlzLm5hdmlnYXRlZCA9IHRydWU7XG4gICAgICAgICAgdGhpcy5sYXN0U3VjY2Vzc2Z1bElkID0gdC5pZDtcbiAgICAgICAgICB0aGlzLmN1cnJlbnRQYWdlSWQgPSB0LnRhcmdldFBhZ2VJZDtcbiAgICAgICAgICAodGhpcy5ldmVudHMgYXMgU3ViamVjdDxFdmVudD4pXG4gICAgICAgICAgICAgIC5uZXh0KG5ldyBOYXZpZ2F0aW9uRW5kKFxuICAgICAgICAgICAgICAgICAgdC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLCB0aGlzLnNlcmlhbGl6ZVVybCh0aGlzLmN1cnJlbnRVcmxUcmVlKSkpO1xuICAgICAgICAgIHRoaXMubGFzdFN1Y2Nlc3NmdWxOYXZpZ2F0aW9uID0gdGhpcy5jdXJyZW50TmF2aWdhdGlvbjtcbiAgICAgICAgICB0LnJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0sXG4gICAgICAgIGUgPT4ge1xuICAgICAgICAgIHRoaXMuY29uc29sZS53YXJuKGBVbmhhbmRsZWQgTmF2aWdhdGlvbiBFcnJvcjogJHtlfWApO1xuICAgICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2NoZWR1bGVOYXZpZ2F0aW9uKFxuICAgICAgcmF3VXJsOiBVcmxUcmVlLCBzb3VyY2U6IE5hdmlnYXRpb25UcmlnZ2VyLCByZXN0b3JlZFN0YXRlOiBSZXN0b3JlZFN0YXRlfG51bGwsXG4gICAgICBleHRyYXM6IE5hdmlnYXRpb25FeHRyYXMsXG4gICAgICBwcmlvclByb21pc2U/OiB7cmVzb2x2ZTogYW55LCByZWplY3Q6IGFueSwgcHJvbWlzZTogUHJvbWlzZTxib29sZWFuPn0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5kaXNwb3NlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuXG4gICAgLy8gKiBJbXBlcmF0aXZlIG5hdmlnYXRpb25zIChyb3V0ZXIubmF2aWdhdGUpIG1pZ2h0IHRyaWdnZXIgYWRkaXRpb25hbCBuYXZpZ2F0aW9ucyB0byB0aGUgc2FtZVxuICAgIC8vICAgVVJMIHZpYSBhIHBvcHN0YXRlIGV2ZW50IGFuZCB0aGUgbG9jYXRpb25DaGFuZ2VMaXN0ZW5lci4gV2Ugc2hvdWxkIHNraXAgdGhlc2UgZHVwbGljYXRlXG4gICAgLy8gICBuYXZzLiBEdXBsaWNhdGVzIG1heSBhbHNvIGJlIHRyaWdnZXJlZCBieSBhdHRlbXB0cyB0byBzeW5jIEFuZ3VsYXJKUyBhbmQgQW5ndWxhciByb3V0ZXJcbiAgICAvLyAgIHN0YXRlcy5cbiAgICAvLyAqIEltcGVyYXRpdmUgbmF2aWdhdGlvbnMgY2FuIGJlIGNhbmNlbGxlZCBieSByb3V0ZXIgZ3VhcmRzLCBtZWFuaW5nIHRoZSBVUkwgd29uJ3QgY2hhbmdlLiBJZlxuICAgIC8vICAgdGhlIHVzZXIgZm9sbG93cyB0aGF0IHdpdGggYSBuYXZpZ2F0aW9uIHVzaW5nIHRoZSBiYWNrL2ZvcndhcmQgYnV0dG9uIG9yIG1hbnVhbCBVUkwgY2hhbmdlLFxuICAgIC8vICAgdGhlIGRlc3RpbmF0aW9uIG1heSBiZSB0aGUgc2FtZSBhcyB0aGUgcHJldmlvdXMgaW1wZXJhdGl2ZSBhdHRlbXB0LiBXZSBzaG91bGQgbm90IHNraXBcbiAgICAvLyAgIHRoZXNlIG5hdmlnYXRpb25zIGJlY2F1c2UgaXQncyBhIHNlcGFyYXRlIGNhc2UgZnJvbSB0aGUgb25lIGFib3ZlIC0tIGl0J3Mgbm90IGEgZHVwbGljYXRlXG4gICAgLy8gICBuYXZpZ2F0aW9uLlxuICAgIGNvbnN0IGxhc3ROYXZpZ2F0aW9uID0gdGhpcy5nZXRUcmFuc2l0aW9uKCk7XG4gICAgLy8gV2UgZG9uJ3Qgd2FudCB0byBza2lwIGR1cGxpY2F0ZSBzdWNjZXNzZnVsIG5hdnMgaWYgdGhleSdyZSBpbXBlcmF0aXZlIGJlY2F1c2VcbiAgICAvLyBvblNhbWVVcmxOYXZpZ2F0aW9uIGNvdWxkIGJlICdyZWxvYWQnIChzbyB0aGUgZHVwbGljYXRlIGlzIGludGVuZGVkKS5cbiAgICBjb25zdCBicm93c2VyTmF2UHJlY2VkZWRCeVJvdXRlck5hdiA9IGlzQnJvd3NlclRyaWdnZXJlZE5hdmlnYXRpb24oc291cmNlKSAmJiBsYXN0TmF2aWdhdGlvbiAmJlxuICAgICAgICAhaXNCcm93c2VyVHJpZ2dlcmVkTmF2aWdhdGlvbihsYXN0TmF2aWdhdGlvbi5zb3VyY2UpO1xuICAgIGNvbnN0IGxhc3ROYXZpZ2F0aW9uU3VjY2VlZGVkID0gdGhpcy5sYXN0U3VjY2Vzc2Z1bElkID09PSBsYXN0TmF2aWdhdGlvbi5pZDtcbiAgICAvLyBJZiB0aGUgbGFzdCBuYXZpZ2F0aW9uIHN1Y2NlZWRlZCBvciBpcyBpbiBmbGlnaHQsIHdlIGNhbiB1c2UgdGhlIHJhd1VybCBhcyB0aGUgY29tcGFyaXNvbi5cbiAgICAvLyBIb3dldmVyLCBpZiBpdCBmYWlsZWQsIHdlIHNob3VsZCBjb21wYXJlIHRvIHRoZSBmaW5hbCByZXN1bHQgKHVybEFmdGVyUmVkaXJlY3RzKS5cbiAgICBjb25zdCBsYXN0TmF2aWdhdGlvblVybCA9IChsYXN0TmF2aWdhdGlvblN1Y2NlZWRlZCB8fCB0aGlzLmN1cnJlbnROYXZpZ2F0aW9uKSA/XG4gICAgICAgIGxhc3ROYXZpZ2F0aW9uLnJhd1VybCA6XG4gICAgICAgIGxhc3ROYXZpZ2F0aW9uLnVybEFmdGVyUmVkaXJlY3RzO1xuICAgIGNvbnN0IGR1cGxpY2F0ZU5hdiA9IGxhc3ROYXZpZ2F0aW9uVXJsLnRvU3RyaW5nKCkgPT09IHJhd1VybC50b1N0cmluZygpO1xuICAgIGlmIChicm93c2VyTmF2UHJlY2VkZWRCeVJvdXRlck5hdiAmJiBkdXBsaWNhdGVOYXYpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7ICAvLyByZXR1cm4gdmFsdWUgaXMgbm90IHVzZWRcbiAgICB9XG5cbiAgICBsZXQgcmVzb2x2ZTogYW55O1xuICAgIGxldCByZWplY3Q6IGFueTtcbiAgICBsZXQgcHJvbWlzZTogUHJvbWlzZTxib29sZWFuPjtcbiAgICBpZiAocHJpb3JQcm9taXNlKSB7XG4gICAgICByZXNvbHZlID0gcHJpb3JQcm9taXNlLnJlc29sdmU7XG4gICAgICByZWplY3QgPSBwcmlvclByb21pc2UucmVqZWN0O1xuICAgICAgcHJvbWlzZSA9IHByaW9yUHJvbWlzZS5wcm9taXNlO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgIHByb21pc2UgPSBuZXcgUHJvbWlzZTxib29sZWFuPigocmVzLCByZWopID0+IHtcbiAgICAgICAgcmVzb2x2ZSA9IHJlcztcbiAgICAgICAgcmVqZWN0ID0gcmVqO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSArK3RoaXMubmF2aWdhdGlvbklkO1xuICAgIGxldCB0YXJnZXRQYWdlSWQ6IG51bWJlcjtcbiAgICBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAnY29tcHV0ZWQnKSB7XG4gICAgICBjb25zdCBpc0luaXRpYWxQYWdlID0gdGhpcy5jdXJyZW50UGFnZUlkID09PSAwO1xuICAgICAgaWYgKGlzSW5pdGlhbFBhZ2UpIHtcbiAgICAgICAgcmVzdG9yZWRTdGF0ZSA9IHRoaXMubG9jYXRpb24uZ2V0U3RhdGUoKSBhcyBSZXN0b3JlZFN0YXRlIHwgbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vIElmIHRoZSBgybVyb3V0ZXJQYWdlSWRgIGV4aXN0IGluIHRoZSBzdGF0ZSB0aGVuIGB0YXJnZXRwYWdlSWRgIHNob3VsZCBoYXZlIHRoZSB2YWx1ZSBvZlxuICAgICAgLy8gYMm1cm91dGVyUGFnZUlkYC4gVGhpcyBpcyB0aGUgY2FzZSBmb3Igc29tZXRoaW5nIGxpa2UgYSBwYWdlIHJlZnJlc2ggd2hlcmUgd2UgYXNzaWduIHRoZVxuICAgICAgLy8gdGFyZ2V0IGlkIHRvIHRoZSBwcmV2aW91c2x5IHNldCB2YWx1ZSBmb3IgdGhhdCBwYWdlLlxuICAgICAgaWYgKHJlc3RvcmVkU3RhdGUgJiYgcmVzdG9yZWRTdGF0ZS7JtXJvdXRlclBhZ2VJZCkge1xuICAgICAgICB0YXJnZXRQYWdlSWQgPSByZXN0b3JlZFN0YXRlLsm1cm91dGVyUGFnZUlkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgd2UncmUgcmVwbGFjaW5nIHRoZSBVUkwgb3IgZG9pbmcgYSBzaWxlbnQgbmF2aWdhdGlvbiwgd2UgZG8gbm90IHdhbnQgdG8gaW5jcmVtZW50IHRoZVxuICAgICAgICAvLyBwYWdlIGlkIGJlY2F1c2Ugd2UgYXJlbid0IHB1c2hpbmcgYSBuZXcgZW50cnkgdG8gaGlzdG9yeS5cbiAgICAgICAgaWYgKGV4dHJhcy5yZXBsYWNlVXJsIHx8IGV4dHJhcy5za2lwTG9jYXRpb25DaGFuZ2UpIHtcbiAgICAgICAgICB0YXJnZXRQYWdlSWQgPSB0aGlzLmJyb3dzZXJQYWdlSWQgPz8gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0YXJnZXRQYWdlSWQgPSAodGhpcy5icm93c2VyUGFnZUlkID8/IDApICsgMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUaGlzIGlzIHVudXNlZCB3aGVuIGBjYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uYCBpcyBub3QgY29tcHV0ZWQuXG4gICAgICB0YXJnZXRQYWdlSWQgPSAwO1xuICAgIH1cblxuICAgIHRoaXMuc2V0VHJhbnNpdGlvbih7XG4gICAgICBpZCxcbiAgICAgIHRhcmdldFBhZ2VJZCxcbiAgICAgIHNvdXJjZSxcbiAgICAgIHJlc3RvcmVkU3RhdGUsXG4gICAgICBjdXJyZW50VXJsVHJlZTogdGhpcy5jdXJyZW50VXJsVHJlZSxcbiAgICAgIGN1cnJlbnRSYXdVcmw6IHRoaXMucmF3VXJsVHJlZSxcbiAgICAgIHJhd1VybCxcbiAgICAgIGV4dHJhcyxcbiAgICAgIHJlc29sdmUsXG4gICAgICByZWplY3QsXG4gICAgICBwcm9taXNlLFxuICAgICAgY3VycmVudFNuYXBzaG90OiB0aGlzLnJvdXRlclN0YXRlLnNuYXBzaG90LFxuICAgICAgY3VycmVudFJvdXRlclN0YXRlOiB0aGlzLnJvdXRlclN0YXRlXG4gICAgfSk7XG5cbiAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgZXJyb3IgaXMgcHJvcGFnYXRlZCBldmVuIHRob3VnaCBgcHJvY2Vzc05hdmlnYXRpb25zYCBjYXRjaFxuICAgIC8vIGhhbmRsZXIgZG9lcyBub3QgcmV0aHJvd1xuICAgIHJldHVybiBwcm9taXNlLmNhdGNoKChlOiBhbnkpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0QnJvd3NlclVybCh1cmw6IFVybFRyZWUsIHQ6IE5hdmlnYXRpb25UcmFuc2l0aW9uKSB7XG4gICAgY29uc3QgcGF0aCA9IHRoaXMudXJsU2VyaWFsaXplci5zZXJpYWxpemUodXJsKTtcbiAgICBjb25zdCBzdGF0ZSA9IHsuLi50LmV4dHJhcy5zdGF0ZSwgLi4udGhpcy5nZW5lcmF0ZU5nUm91dGVyU3RhdGUodC5pZCwgdC50YXJnZXRQYWdlSWQpfTtcbiAgICBpZiAodGhpcy5sb2NhdGlvbi5pc0N1cnJlbnRQYXRoRXF1YWxUbyhwYXRoKSB8fCAhIXQuZXh0cmFzLnJlcGxhY2VVcmwpIHtcbiAgICAgIHRoaXMubG9jYXRpb24ucmVwbGFjZVN0YXRlKHBhdGgsICcnLCBzdGF0ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9jYXRpb24uZ28ocGF0aCwgJycsIHN0YXRlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgdGhlIG5lY2Vzc2FyeSByb2xsYmFjayBhY3Rpb24gdG8gcmVzdG9yZSB0aGUgYnJvd3NlciBVUkwgdG8gdGhlXG4gICAqIHN0YXRlIGJlZm9yZSB0aGUgdHJhbnNpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgcmVzdG9yZUhpc3RvcnkodDogTmF2aWdhdGlvblRyYW5zaXRpb24sIHJlc3RvcmluZ0Zyb21DYXVnaHRFcnJvciA9IGZhbHNlKSB7XG4gICAgaWYgKHRoaXMuY2FuY2VsZWROYXZpZ2F0aW9uUmVzb2x1dGlvbiA9PT0gJ2NvbXB1dGVkJykge1xuICAgICAgY29uc3QgdGFyZ2V0UGFnZVBvc2l0aW9uID0gdGhpcy5jdXJyZW50UGFnZUlkIC0gdC50YXJnZXRQYWdlSWQ7XG4gICAgICAvLyBUaGUgbmF2aWdhdG9yIGNoYW5nZSB0aGUgbG9jYXRpb24gYmVmb3JlIHRyaWdnZXJlZCB0aGUgYnJvd3NlciBldmVudCxcbiAgICAgIC8vIHNvIHdlIG5lZWQgdG8gZ28gYmFjayB0byB0aGUgY3VycmVudCB1cmwgaWYgdGhlIG5hdmlnYXRpb24gaXMgY2FuY2VsZWQuXG4gICAgICAvLyBBbHNvLCB3aGVuIG5hdmlnYXRpb24gZ2V0cyBjYW5jZWxsZWQgd2hpbGUgdXNpbmcgdXJsIHVwZGF0ZSBzdHJhdGVneSBlYWdlciwgdGhlbiB3ZSBuZWVkIHRvXG4gICAgICAvLyBnbyBiYWNrLiBCZWNhdXNlLCB3aGVuIGB1cmxVcGRhdGVTcmF0ZWd5YCBpcyBgZWFnZXJgOyBgc2V0QnJvd3NlclVybGAgbWV0aG9kIGlzIGNhbGxlZFxuICAgICAgLy8gYmVmb3JlIGFueSB2ZXJpZmljYXRpb24uXG4gICAgICBjb25zdCBicm93c2VyVXJsVXBkYXRlT2NjdXJyZWQgPVxuICAgICAgICAgICh0LnNvdXJjZSA9PT0gJ3BvcHN0YXRlJyB8fCB0aGlzLnVybFVwZGF0ZVN0cmF0ZWd5ID09PSAnZWFnZXInIHx8XG4gICAgICAgICAgIHRoaXMuY3VycmVudFVybFRyZWUgPT09IHRoaXMuY3VycmVudE5hdmlnYXRpb24/LmZpbmFsVXJsKTtcbiAgICAgIGlmIChicm93c2VyVXJsVXBkYXRlT2NjdXJyZWQgJiYgdGFyZ2V0UGFnZVBvc2l0aW9uICE9PSAwKSB7XG4gICAgICAgIHRoaXMubG9jYXRpb24uaGlzdG9yeUdvKHRhcmdldFBhZ2VQb3NpdGlvbik7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgIHRoaXMuY3VycmVudFVybFRyZWUgPT09IHRoaXMuY3VycmVudE5hdmlnYXRpb24/LmZpbmFsVXJsICYmIHRhcmdldFBhZ2VQb3NpdGlvbiA9PT0gMCkge1xuICAgICAgICAvLyBXZSBnb3QgdG8gdGhlIGFjdGl2YXRpb24gc3RhZ2UgKHdoZXJlIGN1cnJlbnRVcmxUcmVlIGlzIHNldCB0byB0aGUgbmF2aWdhdGlvbidzXG4gICAgICAgIC8vIGZpbmFsVXJsKSwgYnV0IHdlIHdlcmVuJ3QgbW92aW5nIGFueXdoZXJlIGluIGhpc3RvcnkgKHNraXBMb2NhdGlvbkNoYW5nZSBvciByZXBsYWNlVXJsKS5cbiAgICAgICAgLy8gV2Ugc3RpbGwgbmVlZCB0byByZXNldCB0aGUgcm91dGVyIHN0YXRlIGJhY2sgdG8gd2hhdCBpdCB3YXMgd2hlbiB0aGUgbmF2aWdhdGlvbiBzdGFydGVkLlxuICAgICAgICB0aGlzLnJlc2V0U3RhdGUodCk7XG4gICAgICAgIC8vIFRPRE8oYXRzY290dCk6IHJlc2V0dGluZyB0aGUgYGJyb3dzZXJVcmxUcmVlYCBzaG91bGQgcmVhbGx5IGJlIGRvbmUgaW4gYHJlc2V0U3RhdGVgLlxuICAgICAgICAvLyBJbnZlc3RpZ2F0ZSBpZiB0aGlzIGNhbiBiZSBkb25lIGJ5IHJ1bm5pbmcgVEdQLlxuICAgICAgICB0aGlzLmJyb3dzZXJVcmxUcmVlID0gdC5jdXJyZW50VXJsVHJlZTtcbiAgICAgICAgdGhpcy5yZXNldFVybFRvQ3VycmVudFVybFRyZWUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRoZSBicm93c2VyIFVSTCBhbmQgcm91dGVyIHN0YXRlIHdhcyBub3QgdXBkYXRlZCBiZWZvcmUgdGhlIG5hdmlnYXRpb24gY2FuY2VsbGVkIHNvXG4gICAgICAgIC8vIHRoZXJlJ3Mgbm8gcmVzdG9yYXRpb24gbmVlZGVkLlxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAncmVwbGFjZScpIHtcbiAgICAgIC8vIFRPRE8oYXRzY290dCk6IEl0IHNlZW1zIGxpa2Ugd2Ugc2hvdWxkIF9hbHdheXNfIHJlc2V0IHRoZSBzdGF0ZSBoZXJlLiBJdCB3b3VsZCBiZSBhIG5vLW9wXG4gICAgICAvLyBmb3IgYGRlZmVycmVkYCBuYXZpZ2F0aW9ucyB0aGF0IGhhdmVuJ3QgY2hhbmdlIHRoZSBpbnRlcm5hbCBzdGF0ZSB5ZXQgYmVjYXVzZSBndWFyZHNcbiAgICAgIC8vIHJlamVjdC4gRm9yICdlYWdlcicgbmF2aWdhdGlvbnMsIGl0IHNlZW1zIGxpa2Ugd2UgYWxzbyByZWFsbHkgc2hvdWxkIHJlc2V0IHRoZSBzdGF0ZVxuICAgICAgLy8gYmVjYXVzZSB0aGUgbmF2aWdhdGlvbiB3YXMgY2FuY2VsbGVkLiBJbnZlc3RpZ2F0ZSBpZiB0aGlzIGNhbiBiZSBkb25lIGJ5IHJ1bm5pbmcgVEdQLlxuICAgICAgaWYgKHJlc3RvcmluZ0Zyb21DYXVnaHRFcnJvcikge1xuICAgICAgICB0aGlzLnJlc2V0U3RhdGUodCk7XG4gICAgICB9XG4gICAgICB0aGlzLnJlc2V0VXJsVG9DdXJyZW50VXJsVHJlZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRTdGF0ZSh0OiBOYXZpZ2F0aW9uVHJhbnNpdGlvbik6IHZvaWQge1xuICAgICh0aGlzIGFzIHtyb3V0ZXJTdGF0ZTogUm91dGVyU3RhdGV9KS5yb3V0ZXJTdGF0ZSA9IHQuY3VycmVudFJvdXRlclN0YXRlO1xuICAgIHRoaXMuY3VycmVudFVybFRyZWUgPSB0LmN1cnJlbnRVcmxUcmVlO1xuICAgIHRoaXMucmF3VXJsVHJlZSA9IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5tZXJnZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCB0LnJhd1VybCk7XG4gIH1cblxuICBwcml2YXRlIHJlc2V0VXJsVG9DdXJyZW50VXJsVHJlZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxvY2F0aW9uLnJlcGxhY2VTdGF0ZShcbiAgICAgICAgdGhpcy51cmxTZXJpYWxpemVyLnNlcmlhbGl6ZSh0aGlzLnJhd1VybFRyZWUpLCAnJyxcbiAgICAgICAgdGhpcy5nZW5lcmF0ZU5nUm91dGVyU3RhdGUodGhpcy5sYXN0U3VjY2Vzc2Z1bElkLCB0aGlzLmN1cnJlbnRQYWdlSWQpKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FuY2VsTmF2aWdhdGlvblRyYW5zaXRpb24odDogTmF2aWdhdGlvblRyYW5zaXRpb24sIHJlYXNvbjogc3RyaW5nKSB7XG4gICAgY29uc3QgbmF2Q2FuY2VsID0gbmV3IE5hdmlnYXRpb25DYW5jZWwodC5pZCwgdGhpcy5zZXJpYWxpemVVcmwodC5leHRyYWN0ZWRVcmwpLCByZWFzb24pO1xuICAgIHRoaXMudHJpZ2dlckV2ZW50KG5hdkNhbmNlbCk7XG4gICAgdC5yZXNvbHZlKGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2VuZXJhdGVOZ1JvdXRlclN0YXRlKG5hdmlnYXRpb25JZDogbnVtYmVyLCByb3V0ZXJQYWdlSWQ/OiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAnY29tcHV0ZWQnKSB7XG4gICAgICByZXR1cm4ge25hdmlnYXRpb25JZCwgybVyb3V0ZXJQYWdlSWQ6IHJvdXRlclBhZ2VJZH07XG4gICAgfVxuICAgIHJldHVybiB7bmF2aWdhdGlvbklkfTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUNvbW1hbmRzKGNvbW1hbmRzOiBzdHJpbmdbXSk6IHZvaWQge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbW1hbmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgY21kID0gY29tbWFuZHNbaV07XG4gICAgaWYgKGNtZCA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSByZXF1ZXN0ZWQgcGF0aCBjb250YWlucyAke2NtZH0gc2VnbWVudCBhdCBpbmRleCAke2l9YCk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGlzQnJvd3NlclRyaWdnZXJlZE5hdmlnYXRpb24oc291cmNlOiAnaW1wZXJhdGl2ZSd8J3BvcHN0YXRlJ3wnaGFzaGNoYW5nZScpIHtcbiAgcmV0dXJuIHNvdXJjZSAhPT0gJ2ltcGVyYXRpdmUnO1xufVxuIl19