ng-virtual-list 16.0.1 → 16.0.2

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 (33) hide show
  1. package/esm2022/lib/components/ng-virtual-list-item.component.mjs +85 -0
  2. package/esm2022/lib/const/index.mjs +34 -0
  3. package/esm2022/lib/enums/direction.mjs +2 -0
  4. package/esm2022/lib/enums/directions.mjs +18 -0
  5. package/esm2022/lib/enums/index.mjs +3 -0
  6. package/esm2022/lib/models/collection.model.mjs +3 -0
  7. package/esm2022/lib/models/index.mjs +2 -0
  8. package/esm2022/lib/models/item.model.mjs +3 -0
  9. package/esm2022/lib/models/render-collection.model.mjs +3 -0
  10. package/esm2022/lib/models/render-item-config.model.mjs +2 -0
  11. package/esm2022/lib/models/render-item.model.mjs +3 -0
  12. package/esm2022/lib/models/sticky-map.model.mjs +2 -0
  13. package/esm2022/lib/ng-virtual-list.component.mjs +516 -0
  14. package/esm2022/lib/ng-virtual-list.module.mjs +20 -0
  15. package/esm2022/lib/types/id.mjs +2 -0
  16. package/esm2022/lib/types/index.mjs +2 -0
  17. package/esm2022/lib/types/rect.mjs +2 -0
  18. package/esm2022/lib/types/size.mjs +2 -0
  19. package/esm2022/lib/utils/cacheMap.mjs +52 -0
  20. package/esm2022/lib/utils/debounce.mjs +31 -0
  21. package/esm2022/lib/utils/eventEmitter.mjs +105 -0
  22. package/esm2022/lib/utils/index.mjs +7 -0
  23. package/esm2022/lib/utils/isDirection.mjs +15 -0
  24. package/esm2022/lib/utils/toggleClassName.mjs +15 -0
  25. package/esm2022/lib/utils/trackBox.mjs +355 -0
  26. package/esm2022/lib/utils/tracker.mjs +109 -0
  27. package/esm2022/ng-virtual-list.mjs +5 -0
  28. package/esm2022/public-api.mjs +8 -0
  29. package/fesm2022/ng-virtual-list.mjs +17 -16
  30. package/fesm2022/ng-virtual-list.mjs.map +1 -1
  31. package/lib/components/ng-virtual-list-item.component.d.ts +4 -4
  32. package/lib/const/index.d.ts +1 -1
  33. package/package.json +3 -1
@@ -0,0 +1,516 @@
1
+ import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild, ViewContainerRef, ViewEncapsulation, } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { BehaviorSubject, combineLatest, debounceTime, distinctUntilChanged, filter, map, of, switchMap, tap } from 'rxjs';
4
+ import { NgVirtualListItemComponent } from './components/ng-virtual-list-item.component';
5
+ import { BEHAVIOR_AUTO, BEHAVIOR_INSTANT, CLASS_LIST_HORIZONTAL, CLASS_LIST_VERTICAL, DEFAULT_DIRECTION, DEFAULT_DYNAMIC_SIZE, DEFAULT_ITEM_SIZE, DEFAULT_ITEMS_OFFSET, DEFAULT_SNAP, DEFAULT_SNAP_TO_ITEM, HEIGHT_PROP_NAME, LEFT_PROP_NAME, PX, SCROLL, SCROLL_END, TOP_PROP_NAME, TRACK_BY_PROPERTY_NAME, WIDTH_PROP_NAME, } from './const';
6
+ import { Directions } from './enums';
7
+ import { TrackBox, isDirection, toggleClassName } from './utils';
8
+ import { TRACK_BOX_CHANGE_EVENT_NAME } from './utils/trackBox';
9
+ import * as i0 from "@angular/core";
10
+ /**
11
+ * Virtual list component.
12
+ * Maximum performance for extremely large lists.
13
+ * It is based on algorithms for virtualization of screen objects.
14
+ * @link https://github.com/DjonnyX/ng-virtual-list/blob/main/projects/ng-virtual-list/src/lib/ng-virtual-list.component.ts
15
+ * @author Evgenii Grebennikov
16
+ * @email djonnyx@gmail.com
17
+ */
18
+ export class NgVirtualListComponent {
19
+ _cdr;
20
+ _elementRef;
21
+ static __nextId = 0;
22
+ _id = NgVirtualListComponent.__nextId;
23
+ /**
24
+ * Readonly. Returns the unique identifier of the component.
25
+ */
26
+ get id() { return this._id; }
27
+ _listContainerRef;
28
+ _container;
29
+ _list;
30
+ /**
31
+ * Fires when the list has been scrolled.
32
+ */
33
+ onScroll = new EventEmitter();
34
+ /**
35
+ * Fires when the list has completed scrolling.
36
+ */
37
+ onScrollEnd = new EventEmitter();
38
+ _$items = new BehaviorSubject(undefined);
39
+ $items = this._$items.asObservable();
40
+ /**
41
+ * Collection of list items.
42
+ */
43
+ set items(v) {
44
+ if (this._$items.getValue() === v) {
45
+ return;
46
+ }
47
+ this._$items.next(v);
48
+ this._cdr.markForCheck();
49
+ }
50
+ ;
51
+ get items() { return this._$items.getValue(); }
52
+ _$snap = new BehaviorSubject(DEFAULT_SNAP);
53
+ $snap = this._$snap.asObservable();
54
+ /**
55
+ * Determines whether elements will snap. Default value is "true".
56
+ */
57
+ set snap(v) {
58
+ if (this._$snap.getValue() === v) {
59
+ return;
60
+ }
61
+ this._$snap.next(v);
62
+ this._cdr.markForCheck();
63
+ }
64
+ ;
65
+ get snap() { return this._$snap.getValue(); }
66
+ _$snapToItem = new BehaviorSubject(DEFAULT_SNAP_TO_ITEM);
67
+ $snapToItem = this._$snapToItem.asObservable();
68
+ /**
69
+ * Determines whether scroll positions will be snapped to the element. Default value is "false".
70
+ */
71
+ set snapToItem(v) {
72
+ if (this._$snapToItem.getValue() === v) {
73
+ return;
74
+ }
75
+ this._$snapToItem.next(v);
76
+ this._cdr.markForCheck();
77
+ }
78
+ ;
79
+ get snapToItem() { return this._$snapToItem.getValue(); }
80
+ _$itemRenderer = new BehaviorSubject(undefined);
81
+ $itemRenderer = this._$itemRenderer.asObservable();
82
+ /**
83
+ * Rendering element template.
84
+ */
85
+ set itemRenderer(v) {
86
+ if (this._$itemRenderer.getValue() === v) {
87
+ return;
88
+ }
89
+ this._$itemRenderer.next(v);
90
+ this._cdr.markForCheck();
91
+ }
92
+ ;
93
+ get itemRenderer() { return this._$itemRenderer.getValue(); }
94
+ _$stickyMap = new BehaviorSubject({});
95
+ $stickyMap = this._$stickyMap.asObservable();
96
+ /**
97
+ * Dictionary zIndex by id of the list element. If the value is not set or equal to 0,
98
+ * then a simple element is displayed, if the value is greater than 0, then the sticky position mode is enabled for the element.
99
+ */
100
+ set stickyMap(v) {
101
+ if (this._$stickyMap.getValue() === v) {
102
+ return;
103
+ }
104
+ this._$stickyMap.next(v);
105
+ this._cdr.markForCheck();
106
+ }
107
+ ;
108
+ get stickyMap() { return this._$stickyMap.getValue(); }
109
+ _itemSizeOptions = (v) => {
110
+ if (v === undefined) {
111
+ return DEFAULT_ITEM_SIZE;
112
+ }
113
+ const val = Number(v);
114
+ return Number.isNaN(val) || val <= 0 ? DEFAULT_ITEM_SIZE : val;
115
+ };
116
+ _$itemSize = new BehaviorSubject(DEFAULT_ITEM_SIZE);
117
+ $itemSize = this._$itemSize.asObservable();
118
+ /**
119
+ * If direction = 'vertical', then the height of a typical element. If direction = 'horizontal', then the width of a typical element.
120
+ * Ignored if the dynamicSize property is true.
121
+ */
122
+ set itemSize(v) {
123
+ if (this._$itemSize.getValue() === v) {
124
+ return;
125
+ }
126
+ this._$itemSize.next(this._itemSizeOptions(v));
127
+ this._cdr.markForCheck();
128
+ }
129
+ ;
130
+ get itemSize() { return this._$itemSize.getValue(); }
131
+ _$dynamicSize = new BehaviorSubject(DEFAULT_DYNAMIC_SIZE);
132
+ $dynamicSize = this._$dynamicSize.asObservable();
133
+ /**
134
+ * If true then the items in the list can have different sizes and the itemSize property is ignored.
135
+ * If false then the items in the list have a fixed size specified by the itemSize property. The default value is false.
136
+ */
137
+ set dynamicSize(v) {
138
+ if (this._$dynamicSize.getValue() === v) {
139
+ return;
140
+ }
141
+ this._$dynamicSize.next(v);
142
+ this._cdr.markForCheck();
143
+ }
144
+ ;
145
+ get dynamicSize() { return this._$dynamicSize.getValue(); }
146
+ _$direction = new BehaviorSubject(DEFAULT_DIRECTION);
147
+ $direction = this._$direction.asObservable();
148
+ /**
149
+ * Determines the direction in which elements are placed. Default value is "vertical".
150
+ */
151
+ set direction(v) {
152
+ if (this._$direction.getValue() === v) {
153
+ return;
154
+ }
155
+ this._$direction.next(v);
156
+ this._cdr.markForCheck();
157
+ }
158
+ ;
159
+ get direction() { return this._$direction.getValue(); }
160
+ _$itemsOffset = new BehaviorSubject(DEFAULT_ITEMS_OFFSET);
161
+ $itemsOffset = this._$itemsOffset.asObservable();
162
+ /**
163
+ * Number of elements outside the scope of visibility. Default value is 2.
164
+ */
165
+ set itemsOffset(v) {
166
+ if (this._$itemsOffset.getValue() === v) {
167
+ return;
168
+ }
169
+ this._$itemsOffset.next(v);
170
+ }
171
+ ;
172
+ get itemsOffset() { return this._$itemsOffset.getValue(); }
173
+ _scrollToTimeout;
174
+ _isVertical = this.getIsVertical();
175
+ _displayComponents = [];
176
+ _$bounds = new BehaviorSubject(null);
177
+ _$scrollSize = new BehaviorSubject(0);
178
+ _resizeObserver = null;
179
+ /**
180
+ * only dynamic
181
+ */
182
+ _$scrolledItemId = new BehaviorSubject(undefined);
183
+ _onResizeHandler = () => {
184
+ this._$bounds.next(this._container?.nativeElement?.getBoundingClientRect() ?? null);
185
+ };
186
+ _scrollDirection = 0;
187
+ _onScrollHandler = (e) => {
188
+ this._$scrolledItemId.next(undefined);
189
+ const container = this._container?.nativeElement;
190
+ if (container) {
191
+ const dynamicSize = this.dynamicSize, delta = this._trackBox.delta, scrollSize = (this._isVertical ? container.scrollTop : container.scrollLeft), previouseScrollSize = this._$scrollSize.getValue();
192
+ let actualScrollSize = scrollSize;
193
+ this._scrollDirection = previouseScrollSize > scrollSize ? -1 : 1;
194
+ if (dynamicSize && delta !== 0) {
195
+ actualScrollSize = scrollSize + delta;
196
+ const params = {
197
+ [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: actualScrollSize,
198
+ behavior: BEHAVIOR_INSTANT
199
+ };
200
+ const container = this._container;
201
+ if (container) {
202
+ this.scrollImmediately(container, params);
203
+ this._trackBox.clearDelta();
204
+ }
205
+ }
206
+ this._$scrollSize.next(actualScrollSize);
207
+ this.onScroll.emit(actualScrollSize);
208
+ }
209
+ };
210
+ scrollImmediately(container, params) {
211
+ this.clearScrollImmediately();
212
+ container.nativeElement.removeEventListener(SCROLL_END, this._onScrollEndHandler);
213
+ const handler = () => {
214
+ if (container) {
215
+ container.nativeElement.removeEventListener(SCROLL_END, handler);
216
+ container.nativeElement.scroll(params);
217
+ container.nativeElement.addEventListener(SCROLL_END, this._onScrollEndHandler);
218
+ }
219
+ };
220
+ container.nativeElement.addEventListener(SCROLL_END, handler);
221
+ container.nativeElement.scroll(params);
222
+ this._scrollImmediatelyHandler = handler;
223
+ }
224
+ _scrollImmediatelyHandler = undefined;
225
+ clearScrollImmediately() {
226
+ if (this._scrollImmediatelyHandler === undefined) {
227
+ return;
228
+ }
229
+ const container = this._container;
230
+ if (container) {
231
+ container.nativeElement.removeEventListener(SCROLL_END, this._scrollImmediatelyHandler);
232
+ }
233
+ }
234
+ _onScrollEndHandler = (e, fireEvent = true) => {
235
+ const container = this._container;
236
+ if (container) {
237
+ const itemSize = this.itemSize, snapToItem = this.snapToItem, dynamicSize = this.dynamicSize, delta = this._trackBox.delta, scrollSize = (this._isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft);
238
+ let actualScrollSize = scrollSize;
239
+ if (dynamicSize && delta !== 0) {
240
+ actualScrollSize = scrollSize + delta;
241
+ if (scrollSize !== actualScrollSize) {
242
+ const params = {
243
+ [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: actualScrollSize,
244
+ behavior: BEHAVIOR_INSTANT
245
+ };
246
+ this._trackBox.clearDelta();
247
+ this._$scrollSize.next(actualScrollSize);
248
+ container.nativeElement.scroll(params);
249
+ return;
250
+ }
251
+ }
252
+ else {
253
+ const scrollItems = Math.round(scrollSize / itemSize);
254
+ actualScrollSize = snapToItem ? scrollItems * itemSize : scrollSize;
255
+ if (scrollSize !== actualScrollSize) {
256
+ const params = {
257
+ [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: actualScrollSize,
258
+ behavior: BEHAVIOR_INSTANT
259
+ };
260
+ container.nativeElement.scroll(params);
261
+ }
262
+ }
263
+ this._$scrollSize.next(actualScrollSize);
264
+ if (fireEvent) {
265
+ this.onScrollEnd.emit(actualScrollSize);
266
+ }
267
+ }
268
+ };
269
+ _$initialized = new BehaviorSubject(false);
270
+ $initialized;
271
+ /**
272
+ * Dictionary of element sizes by their id
273
+ */
274
+ _trackBox = new TrackBox(TRACK_BY_PROPERTY_NAME);
275
+ _onTrackBoxChangeHandler = (v) => {
276
+ this._$cacheVersion.next(v);
277
+ };
278
+ _$cacheVersion = new BehaviorSubject(-1);
279
+ get $cacheVersion() { return this._$cacheVersion.asObservable(); }
280
+ constructor(_cdr, _elementRef) {
281
+ this._cdr = _cdr;
282
+ this._elementRef = _elementRef;
283
+ NgVirtualListComponent.__nextId = NgVirtualListComponent.__nextId + 1 === Number.MAX_SAFE_INTEGER
284
+ ? 0 : NgVirtualListComponent.__nextId + 1;
285
+ this._id = NgVirtualListComponent.__nextId;
286
+ this._$initialized = new BehaviorSubject(false);
287
+ this.$initialized = this._$initialized.asObservable();
288
+ this._trackBox.displayComponents = this._displayComponents;
289
+ const $bounds = this._$bounds.asObservable().pipe(filter(b => !!b)), $items = this.$items.pipe(map(i => !i ? [] : i)), $scrollSize = this._$scrollSize.asObservable(), $itemSize = this.$itemSize.pipe(map(v => v <= 0 ? DEFAULT_ITEM_SIZE : v)), $itemsOffset = this.$itemsOffset.pipe(map(v => v < 0 ? DEFAULT_ITEMS_OFFSET : v)), $stickyMap = this.$stickyMap.pipe(map(v => !v ? {} : v)), $snap = this.$snap, $isVertical = this.$direction.pipe(map(v => this.getIsVertical(v || DEFAULT_DIRECTION))), $dynamicSize = this.$dynamicSize, $cacheVersion = this.$cacheVersion, $scrolledItemId = this._$scrolledItemId.asObservable();
290
+ $isVertical.pipe(takeUntilDestroyed(), tap(v => {
291
+ this._isVertical = v;
292
+ const el = this._elementRef.nativeElement;
293
+ toggleClassName(el, v ? CLASS_LIST_VERTICAL : CLASS_LIST_HORIZONTAL, true);
294
+ })).subscribe();
295
+ $dynamicSize.pipe(takeUntilDestroyed(), tap(dynamicSize => {
296
+ this.listenCacheChangesIfNeed(dynamicSize);
297
+ })).subscribe();
298
+ combineLatest([this.$initialized, $scrolledItemId, $bounds, $items, $stickyMap, $scrollSize, $itemSize,
299
+ $itemsOffset, $snap, $isVertical, $dynamicSize, $cacheVersion,
300
+ ]).pipe(takeUntilDestroyed(), distinctUntilChanged(), debounceTime(0), filter(([initialized]) => !!initialized), switchMap(([, scrolledItemId, bounds, items, stickyMap, scrollSize, itemSize, itemsOffset, snap, isVertical, dynamicSize, cacheVersion,]) => {
301
+ const { width, height } = bounds;
302
+ let actualScrollSize = scrollSize;
303
+ const opts = {
304
+ bounds: { width, height }, collection: items, dynamicSize, isVertical, itemSize,
305
+ itemsOffset, scrollSize: scrollSize, snap, fromItemId: scrolledItemId,
306
+ };
307
+ if (dynamicSize && scrolledItemId !== undefined) {
308
+ const scrollSize = this._trackBox.getItemPosition(scrolledItemId, stickyMap, { ...opts, scrollSize: actualScrollSize });
309
+ actualScrollSize = scrollSize;
310
+ this._$scrollSize.next(actualScrollSize);
311
+ }
312
+ const scrollDirection = this._scrollDirection, { displayItems, totalSize } = this._trackBox.updateCollection(items, stickyMap, {
313
+ ...opts, scrollSize: actualScrollSize, scrollDirection
314
+ });
315
+ this.resetBoundsSize(isVertical, totalSize);
316
+ this.createDisplayComponentsIfNeed(displayItems);
317
+ this.tracking();
318
+ if (dynamicSize && scrolledItemId !== undefined) {
319
+ const container = this._container;
320
+ if (container) {
321
+ const params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior: BEHAVIOR_AUTO };
322
+ this.scrollImmediately(container, params);
323
+ }
324
+ }
325
+ return of(displayItems);
326
+ })).subscribe();
327
+ combineLatest([this.$initialized, this.$itemRenderer]).pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(([initialized]) => !!initialized), tap(([, itemRenderer]) => {
328
+ this.resetRenderers(itemRenderer);
329
+ }));
330
+ }
331
+ ngOnInit() {
332
+ this._$initialized.next(true);
333
+ }
334
+ listenCacheChangesIfNeed(value) {
335
+ if (value) {
336
+ if (!this._trackBox.hasEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler)) {
337
+ this._trackBox.addEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler);
338
+ }
339
+ }
340
+ else {
341
+ if (this._trackBox.hasEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler)) {
342
+ this._trackBox.removeEventListener(TRACK_BOX_CHANGE_EVENT_NAME, this._onTrackBoxChangeHandler);
343
+ }
344
+ }
345
+ }
346
+ getIsVertical(d) {
347
+ const dir = d || this.direction;
348
+ return isDirection(dir, Directions.VERTICAL);
349
+ }
350
+ createDisplayComponentsIfNeed(displayItems) {
351
+ if (!displayItems || !this._listContainerRef) {
352
+ this._trackBox.setDisplayObjectIndexMapById({});
353
+ return;
354
+ }
355
+ this._trackBox.items = displayItems;
356
+ const _listContainerRef = this._listContainerRef;
357
+ while (this._displayComponents.length < displayItems.length) {
358
+ if (_listContainerRef) {
359
+ const comp = _listContainerRef.createComponent(NgVirtualListItemComponent);
360
+ this._displayComponents.push(comp);
361
+ }
362
+ }
363
+ const maxLength = displayItems.length;
364
+ while (this._displayComponents.length > maxLength) {
365
+ const comp = this._displayComponents.pop();
366
+ comp?.destroy();
367
+ const id = comp?.instance.item?.id;
368
+ if (id !== undefined) {
369
+ this._trackBox.untrackComponentByIdProperty(comp?.instance);
370
+ }
371
+ }
372
+ this.resetRenderers();
373
+ }
374
+ resetRenderers(itemRenderer) {
375
+ const doMap = {};
376
+ for (let i = 0, l = this._displayComponents.length; i < l; i++) {
377
+ const item = this._displayComponents[i];
378
+ item.instance.renderer = itemRenderer || this.itemRenderer;
379
+ doMap[item.instance.id] = i;
380
+ }
381
+ this._trackBox.setDisplayObjectIndexMapById(doMap);
382
+ }
383
+ /**
384
+ * Tracking by id
385
+ */
386
+ tracking() {
387
+ this._trackBox.track();
388
+ }
389
+ resetBoundsSize(isVertical, totalSize) {
390
+ const l = this._list;
391
+ if (l) {
392
+ l.nativeElement.style[isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME] = `${totalSize}${PX}`;
393
+ }
394
+ }
395
+ /**
396
+ * The method scrolls the list to the element with the given id and returns the value of the scrolled area.
397
+ * Behavior accepts the values ​​"auto", "instant" and "smooth".
398
+ */
399
+ scrollTo(id, behavior = BEHAVIOR_AUTO) {
400
+ const items = this.items;
401
+ if (!items || !items.length) {
402
+ return;
403
+ }
404
+ const dynamicSize = this.dynamicSize, container = this._container, itemSize = this.itemSize;
405
+ if (container) {
406
+ if (dynamicSize) {
407
+ if (container) {
408
+ container.nativeElement.removeEventListener(SCROLL, this._onScrollHandler);
409
+ container.nativeElement.removeEventListener(SCROLL_END, this._onScrollEndHandler);
410
+ }
411
+ const { width, height } = this._$bounds.getValue() || { width: 0, height: 0 }, stickyMap = this.stickyMap, items = this.items, opts = {
412
+ bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
413
+ itemsOffset: this.itemsOffset, scrollSize: this._isVertical ? container.nativeElement.scrollTop : container.nativeElement.scrollLeft,
414
+ snap: this.snap, fromItemId: id,
415
+ }, scrollSize = this._trackBox.getItemPosition(id, stickyMap, opts), params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
416
+ this._$scrolledItemId.next(id);
417
+ this._$scrollSize.next(scrollSize);
418
+ if (container) {
419
+ const handler = () => {
420
+ if (container) {
421
+ container.nativeElement.removeEventListener(SCROLL_END, handler);
422
+ clearTimeout(this._scrollToTimeout);
423
+ this._scrollToTimeout = setTimeout(() => {
424
+ container.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
425
+ container.nativeElement.addEventListener(SCROLL_END, this._onScrollEndHandler);
426
+ }, 100);
427
+ this.listenCacheChangesIfNeed(dynamicSize);
428
+ this.onScroll.emit(scrollSize);
429
+ }
430
+ };
431
+ container.nativeElement.addEventListener(SCROLL_END, handler);
432
+ }
433
+ container.nativeElement.scroll(params);
434
+ }
435
+ else {
436
+ const index = items.findIndex(item => item.id === id), scrollSize = index * this.itemSize;
437
+ const params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior };
438
+ container.nativeElement.scroll(params);
439
+ }
440
+ }
441
+ }
442
+ scrollToEnd(behavior = BEHAVIOR_INSTANT) {
443
+ const items = this.items, latItem = items[items.length > 0 ? items.length - 1 : 0];
444
+ this.scrollTo(latItem.id, behavior);
445
+ }
446
+ ngAfterViewInit() {
447
+ const containerEl = this._container;
448
+ if (containerEl) {
449
+ containerEl.nativeElement.addEventListener(SCROLL, this._onScrollHandler);
450
+ containerEl.nativeElement.addEventListener(SCROLL_END, this._onScrollEndHandler);
451
+ this._resizeObserver = new ResizeObserver(this._onResizeHandler);
452
+ this._resizeObserver.observe(containerEl.nativeElement);
453
+ this._onResizeHandler();
454
+ }
455
+ }
456
+ ngOnDestroy() {
457
+ if (this._scrollToTimeout) {
458
+ clearTimeout(this._scrollToTimeout);
459
+ }
460
+ if (this._trackBox) {
461
+ this._trackBox.dispose();
462
+ }
463
+ const containerEl = this._container;
464
+ if (containerEl) {
465
+ containerEl.nativeElement.removeEventListener(SCROLL, this._onScrollHandler);
466
+ containerEl.nativeElement.removeEventListener(SCROLL_END, this._onScrollEndHandler);
467
+ if (this._resizeObserver) {
468
+ this._resizeObserver.unobserve(containerEl.nativeElement);
469
+ }
470
+ }
471
+ if (this._displayComponents) {
472
+ while (this._displayComponents.length > 0) {
473
+ const comp = this._displayComponents.pop();
474
+ comp?.destroy();
475
+ }
476
+ }
477
+ }
478
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NgVirtualListComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
479
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NgVirtualListComponent, selector: "ng-virtual-list", inputs: { items: "items", snap: "snap", snapToItem: "snapToItem", itemRenderer: "itemRenderer", stickyMap: "stickyMap", itemSize: "itemSize", dynamicSize: "dynamicSize", direction: "direction", itemsOffset: "itemsOffset" }, outputs: { onScroll: "onScroll", onScrollEnd: "onScrollEnd" }, viewQueries: [{ propertyName: "_listContainerRef", first: true, predicate: ["renderersContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_container", first: true, predicate: ["container"], descendants: true, read: (ElementRef) }, { propertyName: "_list", first: true, predicate: ["list"], descendants: true, read: (ElementRef) }], ngImport: i0, template: "<div #container part=\"scroller\" class=\"ngvl__container\">\r\n <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.vertical){height:320px}.ngvl__container{overflow:auto;width:100%;height:100%}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.ShadowDom });
480
+ }
481
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NgVirtualListComponent, decorators: [{
482
+ type: Component,
483
+ args: [{ selector: 'ng-virtual-list', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.ShadowDom, template: "<div #container part=\"scroller\" class=\"ngvl__container\">\r\n <ul #list part=\"list\" class=\"ngvl__list\">\r\n <ng-container #renderersContainer></ng-container>\r\n </ul>\r\n</div>", styles: [":host{display:block;width:400px;overflow:hidden}:host(.horizontal){height:48px}:host(.vertical){height:320px}.ngvl__container{overflow:auto;width:100%;height:100%}.ngvl__list{position:relative;list-style:none;padding:0;margin:0;width:100%;height:100%}\n"] }]
484
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { _listContainerRef: [{
485
+ type: ViewChild,
486
+ args: ['renderersContainer', { read: ViewContainerRef }]
487
+ }], _container: [{
488
+ type: ViewChild,
489
+ args: ['container', { read: (ElementRef) }]
490
+ }], _list: [{
491
+ type: ViewChild,
492
+ args: ['list', { read: (ElementRef) }]
493
+ }], onScroll: [{
494
+ type: Output
495
+ }], onScrollEnd: [{
496
+ type: Output
497
+ }], items: [{
498
+ type: Input
499
+ }], snap: [{
500
+ type: Input
501
+ }], snapToItem: [{
502
+ type: Input
503
+ }], itemRenderer: [{
504
+ type: Input
505
+ }], stickyMap: [{
506
+ type: Input
507
+ }], itemSize: [{
508
+ type: Input
509
+ }], dynamicSize: [{
510
+ type: Input
511
+ }], direction: [{
512
+ type: Input
513
+ }], itemsOffset: [{
514
+ type: Input
515
+ }] } });
516
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctdmlydHVhbC1saXN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25nLXZpcnR1YWwtbGlzdC9zcmMvbGliL25nLXZpcnR1YWwtbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy12aXJ0dWFsLWxpc3Qvc3JjL2xpYi9uZy12aXJ0dWFsLWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNVLHVCQUF1QixFQUFxQixTQUFTLEVBQWdCLFVBQVUsRUFBRSxZQUFZLEVBQzVHLEtBQUssRUFBYSxNQUFNLEVBQWUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixHQUN0RixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBYyxFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2SSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUN6RixPQUFPLEVBQ0wsYUFBYSxFQUFFLGdCQUFnQixFQUFFLHFCQUFxQixFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLG9CQUFvQixFQUFFLGlCQUFpQixFQUN2SSxvQkFBb0IsRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFDakksc0JBQXNCLEVBQUUsZUFBZSxHQUN4QyxNQUFNLFNBQVMsQ0FBQztBQUlqQixPQUFPLEVBQWEsVUFBVSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2hELE9BQU8sRUFBRSxRQUFRLEVBQUUs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QVJsQyxTQUFTOytCQUNFLGlCQUFpQixjQUNmLEtBQUssbUJBR0EsdUJBQXVCLENBQUMsTUFBTSxpQkFDaEMsaUJBQWlCLENBQUMsU0FBUztpSUFZaEMsaUJBQWlCO3NCQUQxQixTQUFTO3VCQUFDLG9CQUFvQixFQUFFLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFO2dCQUlqRCxVQUFVO3NCQURuQixTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFBLFVBQTBCLENBQUEsRUFBRTtnQkFJbEQsS0FBSztzQkFEZCxTQUFTO3VCQUFDLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxDQUFBLFVBQTBCLENBQUEsRUFBRTtnQkFPdkQsUUFBUTtzQkFEUCxNQUFNO2dCQU9QLFdBQVc7c0JBRFYsTUFBTTtnQkFVSCxLQUFLO3NCQURSLEtBQUs7Z0JBbUJGLElBQUk7c0JBRFAsS0FBSztnQkFtQkYsVUFBVTtzQkFEYixLQUFLO2dCQWtCRixZQUFZO3NCQURmLEtBQUs7Z0JBb0JGLFNBQVM7c0JBRFosS0FBSztnQkE0QkYsUUFBUTtzQkFEWCxLQUFLO2dCQW9CRixXQUFXO3NCQURkLEtBQUs7Z0JBbUJGLFNBQVM7c0JBRFosS0FBSztnQkFtQkYsV0FBVztzQkFEZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBBZnRlclZpZXdJbml0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgQ29tcG9uZW50UmVmLCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsXHJcbiAgSW5wdXQsIE9uRGVzdHJveSwgT3V0cHV0LCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkLCBWaWV3Q29udGFpbmVyUmVmLCBWaWV3RW5jYXBzdWxhdGlvbixcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQsIGZpbHRlciwgbWFwLCBPYnNlcnZhYmxlLCBvZiwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgTmdWaXJ0dWFsTGlzdEl0ZW1Db21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvbmctdmlydHVhbC1saXN0LWl0ZW0uY29tcG9uZW50JztcclxuaW1wb3J0IHtcclxuICBCRUhBVklPUl9BVVRPLCBCRUhBVklPUl9JTlNUQU5ULCBDTEFTU19MSVNUX0hPUklaT05UQUwsIENMQVNTX0xJU1RfVkVSVElDQUwsIERFRkFVTFRfRElSRUNUSU9OLCBERUZBVUxUX0RZTkFNSUNfU0laRSwgREVGQVVMVF9JVEVNX1NJWkUsXHJcbiAgREVGQVVMVF9JVEVNU19PRkZTRVQsIERFRkFVTFRfU05BUCwgREVGQVVMVF9TTkFQX1RPX0lURU0sIEhFSUdIVF9QUk9QX05BTUUsIExFRlRfUFJPUF9OQU1FLCBQWCwgU0NST0xMLCBTQ1JPTExfRU5ELCBUT1BfUFJPUF9OQU1FLFxyXG4gIFRSQUNLX0JZX1BST1BFUlRZX05BTUUsIFdJRFRIX1BST1BfTkFNRSxcclxufSBmcm9tICcuL2NvbnN0JztcclxuaW1wb3J0IHsgSVZpcnR1YWxMaXN0Q29sbGVjdGlvbiwgSVZpcnR1YWxMaXN0SXRlbSwgSVZpcnR1YWxMaXN0U3RpY2t5TWFwIH0gZnJvbSAnLi9tb2RlbHMnO1xyXG5pbXBvcnQgeyBJZCB9IGZyb20gJy4vdHlwZXMnO1xyXG5pbXBvcnQgeyBJUmVuZGVyVmlydHVhbExpc3RDb2xsZWN0aW9uIH0gZnJvbSAnLi9tb2RlbHMvcmVuZGVyLWNvbGxlY3Rpb24ubW9kZWwnO1xyXG5pbXBvcnQgeyBEaXJlY3Rpb24sIERpcmVjdGlvbnMgfSBmcm9tICcuL2VudW1zJztcclxuaW1wb3J0IHsgVHJhY2tCb3gsIGlzRGlyZWN0aW9uLCB0b2dnbGVDbGFzc05hbWUgfSBmcm9tICcuL3V0aWxzJztcclxuaW1wb3J0IHsgSVJlY2FsY3VsYXRlTWV0cmljc09wdGlvbnMsIFNjcm9sbERpcmVjdGlvbiwgVFJBQ0tfQk9YX0NIQU5HRV9FVkVOVF9OQU1FIH0gZnJvbSAnLi91dGlscy90cmFja0JveCc7XHJcblxyXG4vKipcclxuICogVmlydHVhbCBsaXN0IGNvbXBvbmVudC5cclxuICogTWF4aW11bSBwZXJmb3JtYW5jZSBmb3IgZXh0cmVtZWx5IGxhcmdlIGxpc3RzLlxyXG4gKiBJdCBpcyBiYXNlZCBvbiBhbGdvcml0aG1zIGZvciB2aXJ0dWFsaXphdGlvbiBvZiBzY3JlZW4gb2JqZWN0cy5cclxuICogQGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL0Rqb25ueVgvbmctdmlydHVhbC1saXN0L2Jsb2IvbWFpbi9wcm9qZWN0cy9uZy12aXJ0dWFsLWxpc3Qvc3JjL2xpYi9uZy12aXJ0dWFsLWxpc3QuY29tcG9uZW50LnRzXHJcbiAqIEBhdXRob3IgRXZnZW5paSBHcmViZW5uaWtvdlxyXG4gKiBAZW1haWwgZGpvbm55eEBnbWFpbC5jb21cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmctdmlydHVhbC1saXN0JyxcclxuICBzdGFuZGFsb25lOiBmYWxzZSxcclxuICB0ZW1wbGF0ZVVybDogJy4vbmctdmlydHVhbC1saXN0LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9uZy12aXJ0dWFsLWxpc3QuY29tcG9uZW50LnNjc3MnXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5TaGFkb3dEb20sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBOZ1ZpcnR1YWxMaXN0Q29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICBwcml2YXRlIHN0YXRpYyBfX25leHRJZDogbnVtYmVyID0gMDtcclxuXHJcbiAgcHJpdmF0ZSBfaWQ6IG51bWJlciA9IE5nVmlydHVhbExpc3RDb21wb25lbnQuX19uZXh0SWQ7XHJcbiAgLyoqXHJcbiAgICogUmVhZG9ubHkuIFJldHVybnMgdGhlIHVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBjb21wb25lbnQuXHJcbiAgICovXHJcbiAgZ2V0IGlkKCkgeyByZXR1cm4gdGhpcy5faWQ7IH1cclxuXHJcbiAgQFZpZXdDaGlsZCgncmVuZGVyZXJzQ29udGFpbmVyJywgeyByZWFkOiBWaWV3Q29udGFpbmVyUmVmIH0pXHJcbiAgcHJvdGVjdGVkIF9saXN0Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmIHwgdW5kZWZpbmVkO1xyXG5cclxuICBAVmlld0NoaWxkKCdjb250YWluZXInLCB7IHJlYWQ6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+IH0pXHJcbiAgcHJvdGVjdGVkIF9jb250YWluZXI6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+IHwgdW5kZWZpbmVkO1xyXG5cclxuICBAVmlld0NoaWxkKCdsaXN0JywgeyByZWFkOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PiB9KVxyXG4gIHByb3RlY3RlZCBfbGlzdDogRWxlbWVudFJlZjxIVE1MVUxpc3RFbGVtZW50PiB8IHVuZGVmaW5lZDtcclxuXHJcbiAgLyoqXHJcbiAgICogRmlyZXMgd2hlbiB0aGUgbGlzdCBoYXMgYmVlbiBzY3JvbGxlZC5cclxuICAgKi9cclxuICBAT3V0cHV0KClcclxuICBvblNjcm9sbCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xyXG5cclxuICAvKipcclxuICAgKiBGaXJlcyB3aGVuIHRoZSBsaXN0IGhhcyBjb21wbGV0ZWQgc2Nyb2xsaW5nLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKVxyXG4gIG9uU2Nyb2xsRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XHJcblxyXG4gIHByaXZhdGUgXyRpdGVtcyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8SVZpcnR1YWxMaXN0Q29sbGVjdGlvbiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcclxuICByZWFkb25seSAkaXRlbXMgPSB0aGlzLl8kaXRlbXMuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbGxlY3Rpb24gb2YgbGlzdCBpdGVtcy5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHNldCBpdGVtcyh2OiBJVmlydHVhbExpc3RDb2xsZWN0aW9uKSB7XHJcbiAgICBpZiAodGhpcy5fJGl0ZW1zLmdldFZhbHVlKCkgPT09IHYpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuXyRpdGVtcy5uZXh0KHYpO1xyXG5cclxuICAgIHRoaXMuX2Nkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9O1xyXG4gIGdldCBpdGVtcygpIHsgcmV0dXJuIHRoaXMuXyRpdGVtcy5nZXRWYWx1ZSgpIGFzIElWaXJ0dWFsTGlzdENvbGxlY3Rpb247IH1cclxuXHJcbiAgcHJpdmF0ZSBfJHNuYXAgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KERFRkFVTFRfU05BUCk7XHJcbiAgcmVhZG9ubHkgJHNuYXAgPSB0aGlzLl8kc25hcC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIGVsZW1lbnRzIHdpbGwgc25hcC4gRGVmYXVsdCB2YWx1ZSBpcyBcInRydWVcIi5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHNldCBzbmFwKHY6IGJvb2xlYW4pIHtcclxuICAgIGlmICh0aGlzLl8kc25hcC5nZXRWYWx1ZSgpID09PSB2KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl8kc25hcC5uZXh0KHYpO1xyXG5cclxuICAgIHRoaXMuX2Nkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9O1xyXG4gIGdldCBzbmFwKCkgeyByZXR1cm4gdGhpcy5fJHNuYXAuZ2V0VmFsdWUoKTsgfVxyXG5cclxuICBwcml2YXRlIF8kc25hcFRvSXRlbSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oREVGQVVMVF9TTkFQX1RPX0lURU0pO1xyXG4gIHJlYWRvbmx5ICRzbmFwVG9JdGVtID0gdGhpcy5fJHNuYXBUb0l0ZW0uYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIERldGVybWluZXMgd2hldGhlciBzY3JvbGwgcG9zaXRpb25zIHdpbGwgYmUgc25hcHBlZCB0byB0aGUgZWxlbWVudC4gRGVmYXVsdCB2YWx1ZSBpcyBcImZhbHNlXCIuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBzZXQgc25hcFRvSXRlbSh2OiBib29sZWFuKSB7XHJcbiAgICBpZiAodGhpcy5fJHNuYXBUb0l0ZW0uZ2V0VmFsdWUoKSA9PT0gdikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fJHNuYXBUb0l0ZW0ubmV4dCh2KTtcclxuXHJcbiAgICB0aGlzLl9jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgfTtcclxuICBnZXQgc25hcFRvSXRlbSgpIHsgcmV0dXJuIHRoaXMuXyRzbmFwVG9JdGVtLmdldFZhbHVlKCk7IH1cclxuXHJcbiAgcHJpdmF0ZSBfJGl0ZW1SZW5kZXJlciA9IG5ldyBCZWhhdmlvclN1YmplY3Q8VGVtcGxhdGVSZWY8YW55PiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcclxuICByZWFkb25seSAkaXRlbVJlbmRlcmVyID0gdGhpcy5fJGl0ZW1SZW5kZXJlci5hc09ic2VydmFibGUoKTtcclxuICAvKipcclxuICAgKiBSZW5kZXJpbmcgZWxlbWVudCB0ZW1wbGF0ZS5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHNldCBpdGVtUmVuZGVyZXIodjogVGVtcGxhdGVSZWY8YW55Pikge1xyXG4gICAgaWYgKHRoaXMuXyRpdGVtUmVuZGVyZXIuZ2V0VmFsdWUoKSA9PT0gdikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fJGl0ZW1SZW5kZXJlci5uZXh0KHYpO1xyXG5cclxuICAgIHRoaXMuX2Nkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9O1xyXG4gIGdldCBpdGVtUmVuZGVyZXIoKSB7IHJldHVybiB0aGlzLl8kaXRlbVJlbmRlcmVyLmdldFZhbHVlKCkgYXMgVGVtcGxhdGVSZWY8YW55PjsgfVxyXG5cclxuICBwcml2YXRlIF8kc3RpY2t5TWFwID0gbmV3IEJlaGF2aW9yU3ViamVjdDxJVmlydHVhbExpc3RTdGlja3lNYXA+KHt9KTtcclxuICByZWFkb25seSAkc3RpY2t5TWFwID0gdGhpcy5fJHN0aWNreU1hcC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRGljdGlvbmFyeSB6SW5kZXggYnkgaWQgb2YgdGhlIGxpc3QgZWxlbWVudC4gSWYgdGhlIHZhbHVlIGlzIG5vdCBzZXQgb3IgZXF1YWwgdG8gMCxcclxuICAgKiB0aGVuIGEgc2ltcGxlIGVsZW1lbnQgaXMgZGlzcGxheWVkLCBpZiB0aGUgdmFsdWUgaXMgZ3JlYXRlciB0aGFuIDAsIHRoZW4gdGhlIHN0aWNreSBwb3NpdGlvbiBtb2RlIGlzIGVuYWJsZWQgZm9yIHRoZSBlbGVtZW50LlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IHN0aWNreU1hcCh2OiBJVmlydHVhbExpc3RTdGlja3lNYXApIHtcclxuICAgIGlmICh0aGlzLl8kc3RpY2t5TWFwLmdldFZhbHVlKCkgPT09IHYpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuXyRzdGlja3lNYXAubmV4dCh2KTtcclxuXHJcbiAgICB0aGlzLl9jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgfTtcclxuICBnZXQgc3RpY2t5TWFwKCkgeyByZXR1cm4gdGhpcy5fJHN0aWNreU1hcC5nZXRWYWx1ZSgpOyB9XHJcblxyXG4gIHByaXZhdGUgX2l0ZW1TaXplT3B0aW9ucyA9ICh2OiBudW1iZXIgfCB1bmRlZmluZWQpID0+IHtcclxuICAgIGlmICh2ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgcmV0dXJuIERFRkFVTFRfSVRFTV9TSVpFO1xyXG4gICAgfVxyXG4gICAgY29uc3QgdmFsID0gTnVtYmVyKHYpO1xyXG4gICAgcmV0dXJuIE51bWJlci5pc05hTih2YWwpIHx8IHZhbCA8PSAwID8gREVGQVVMVF9JVEVNX1NJWkUgOiB2YWw7XHJcbiAgfTtcclxuXHJcbiAgcHJpdmF0ZSBfJGl0ZW1TaXplID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KERFRkFVTFRfSVRFTV9TSVpFKTtcclxuICByZWFkb25seSAkaXRlbVNpemUgPSB0aGlzLl8kaXRlbVNpemUuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIElmIGRpcmVjdGlvbiA9ICd2ZXJ0aWNhbCcsIHRoZW4gdGhlIGhlaWdodCBvZiBhIHR5cGljYWwgZWxlbWVudC4gSWYgZGlyZWN0aW9uID0gJ2hvcml6b250YWwnLCB0aGVuIHRoZSB3aWR0aCBvZiBhIHR5cGljYWwgZWxlbWVudC5cclxuICAgKiBJZ25vcmVkIGlmIHRoZSBkeW5hbWljU2l6ZSBwcm9wZXJ0eSBpcyB0cnVlLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IGl0ZW1TaXplKHY6IG51bWJlcikge1xyXG4gICAgaWYgKHRoaXMuXyRpdGVtU2l6ZS5nZXRWYWx1ZSgpID09PSB2KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl8kaXRlbVNpemUubmV4dCh0aGlzLl9pdGVtU2l6ZU9wdGlvbnModikpO1xyXG5cclxuICAgIHRoaXMuX2Nkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9O1xyXG4gIGdldCBpdGVtU2l6ZSgpIHsgcmV0dXJuIHRoaXMuXyRpdGVtU2l6ZS5nZXRWYWx1ZSgpOyB9XHJcblxyXG4gIHByaXZhdGUgXyRkeW5hbWljU2l6ZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oREVGQVVMVF9EWU5BTUlDX1NJWkUpO1xyXG4gIHJlYWRvbmx5ICRkeW5hbWljU2l6ZSA9IHRoaXMuXyRkeW5hbWljU2l6ZS5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogSWYgdHJ1ZSB0aGVuIHRoZSBpdGVtcyBpbiB0aGUgbGlzdCBjYW4gaGF2ZSBkaWZmZXJlbnQgc2l6ZXMgYW5kIHRoZSBpdGVtU2l6ZSBwcm9wZXJ0eSBpcyBpZ25vcmVkLlxyXG4gICAqIElmIGZhbHNlIHRoZW4gdGhlIGl0ZW1zIGluIHRoZSBsaXN0IGhhdmUgYSBmaXhlZCBzaXplIHNwZWNpZmllZCBieSB0aGUgaXRlbVNpemUgcHJvcGVydHkuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIGZhbHNlLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IGR5bmFtaWNTaXplKHY6IGJvb2xlYW4pIHtcclxuICAgIGlmICh0aGlzLl8kZHluYW1pY1NpemUuZ2V0VmFsdWUoKSA9PT0gdikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fJGR5bmFtaWNTaXplLm5leHQodik7XHJcblxyXG4gICAgdGhpcy5fY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gIH07XHJcbiAgZ2V0IGR5bmFtaWNTaXplKCkgeyByZXR1cm4gdGhpcy5fJGR5bmFtaWNTaXplLmdldFZhbHVlKCk7IH1cclxuXHJcbiAgcHJpdmF0ZSBfJGRpcmVjdGlvbiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8RGlyZWN0aW9uPihERUZBVUxUX0RJUkVDVElPTik7XHJcbiAgcmVhZG9ubHkgJGRpcmVjdGlvbiA9IHRoaXMuXyRkaXJlY3Rpb24uYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIERldGVybWluZXMgdGhlIGRpcmVjdGlvbiBpbiB3aGljaCBlbGVtZW50cyBhcmUgcGxhY2VkLiBEZWZhdWx0IHZhbHVlIGlzIFwidmVydGljYWxcIi5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHNldCBkaXJlY3Rpb24odjogRGlyZWN0aW9uKSB7XHJcbiAgICBpZiAodGhpcy5fJGRpcmVjdGlvbi5nZXRWYWx1ZSgpID09PSB2KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl8kZGlyZWN0aW9uLm5leHQodik7XHJcblxyXG4gICAgdGhpcy5fY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gIH07XHJcbiAgZ2V0IGRpcmVjdGlvbigpIHsgcmV0dXJuIHRoaXMuXyRkaXJlY3Rpb24uZ2V0VmFsdWUoKTsgfVxyXG5cclxuICBwcml2YXRlIF8kaXRlbXNPZmZzZXQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PG51bWJlcj4oREVGQVVMVF9JVEVNU19PRkZTRVQpO1xyXG4gIHJlYWRvbmx5ICRpdGVtc09mZnNldCA9IHRoaXMuXyRpdGVtc09mZnNldC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogTnVtYmVyIG9mIGVsZW1lbnRzIG91dHNpZGUgdGhlIHNjb3BlIG9mIHZpc2liaWxpdHkuIERlZmF1bHQgdmFsdWUgaXMgMi5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHNldCBpdGVtc09mZnNldCh2OiBudW1iZXIpIHtcclxuICAgIGlmICh0aGlzLl8kaXRlbXNPZmZzZXQuZ2V0VmFsdWUoKSA9PT0gdikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fJGl0ZW1zT2Zmc2V0Lm5leHQodik7XHJcbiAgfTtcclxuICBnZXQgaXRlbXNPZmZzZXQoKSB7IHJldHVybiB0aGlzLl8kaXRlbXNPZmZzZXQuZ2V0VmFsdWUoKTsgfVxyXG5cclxuICBwcml2YXRlIF9zY3JvbGxUb1RpbWVvdXQ6IGFueTtcclxuXHJcbiAgcHJpdmF0ZSBfaXNWZXJ0aWNhbCA9IHRoaXMuZ2V0SXNWZXJ0aWNhbCgpO1xyXG5cclxuICBwcm90ZWN0ZWQgX2Rpc3BsYXlDb21wb25lbnRzOiBBcnJheTxDb21wb25lbnRSZWY8TmdWaXJ0dWFsTGlzdEl0ZW1Db21wb25lbnQ+PiA9IFtdO1xyXG5cclxuICBwcm90ZWN0ZWQgXyRib3VuZHMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PERPTVJlY3QgfCBudWxsPihudWxsKTtcclxuXHJcbiAgcHJvdGVjdGVkIF8kc2Nyb2xsU2l6ZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigwKTtcclxuXHJcbiAgcHJpdmF0ZSBfcmVzaXplT2JzZXJ2ZXI6IFJlc2l6ZU9ic2VydmVyIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIG9ubHkgZHluYW1pY1xyXG4gICAqL1xyXG4gIHByaXZhdGUgXyRzY3JvbGxlZEl0ZW1JZCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8SWQgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XHJcblxyXG4gIHByaXZhdGUgX29uUmVzaXplSGFuZGxlciA9ICgpID0+IHtcclxuICAgIHRoaXMuXyRib3VuZHMubmV4dCh0aGlzLl9jb250YWluZXI/Lm5hdGl2ZUVsZW1lbnQ/LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpID8/IG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfc2Nyb2xsRGlyZWN0aW9uOiBTY3JvbGxEaXJlY3Rpb24gPSAwO1xyXG5cclxuICBwcml2YXRlIF9vblNjcm9sbEhhbmRsZXIgPSAoZT86IEV2ZW50KSA9PiB7XHJcbiAgICB0aGlzLl8kc2Nyb2xsZWRJdGVtSWQubmV4dCh1bmRlZmluZWQpO1xyXG5cclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcj8ubmF0aXZlRWxlbWVudDtcclxuICAgIGlmIChjb250YWluZXIpIHtcclxuICAgICAgY29uc3QgZHluYW1pY1NpemUgPSB0aGlzLmR5bmFtaWNTaXplLCBkZWx0YSA9IHRoaXMuX3RyYWNrQm94LmRlbHRhLCBzY3JvbGxTaXplID0gKHRoaXMuX2lzVmVydGljYWwgPyBjb250YWluZXIuc2Nyb2xsVG9wIDogY29udGFpbmVyLnNjcm9sbExlZnQpLFxyXG4gICAgICAgIHByZXZpb3VzZVNjcm9sbFNpemUgPSB0aGlzLl8kc2Nyb2xsU2l6ZS5nZXRWYWx1ZSgpO1xyXG4gICAgICBsZXQgYWN0dWFsU2Nyb2xsU2l6ZSA9IHNjcm9sbFNpemU7XHJcblxyXG4gICAgICB0aGlzLl9zY3JvbGxEaXJlY3Rpb24gPSBwcmV2aW91c2VTY3JvbGxTaXplID4gc2Nyb2xsU2l6ZSA/IC0xIDogMTtcclxuXHJcbiAgICAgIGlmIChkeW5hbWljU2l6ZSAmJiBkZWx0YSAhPT0gMCkge1xyXG4gICAgICAgIGFjdHVhbFNjcm9sbFNpemUgPSBzY3JvbGxTaXplICsgZGVsdGE7XHJcbiAgICAgICAgY29uc3QgcGFyYW1zOiBTY3JvbGxUb09wdGlvbnMgPSB7XHJcbiAgICAgICAgICBbdGhpcy5faXNWZXJ0aWNhbCA/IFRPUF9QUk9QX05BTUUgOiBMRUZUX1BST1BfTkFNRV06IGFjdHVhbFNjcm9sbFNpemUsXHJcbiAgICAgICAgICBiZWhhdmlvcjogQkVIQVZJT1JfSU5TVEFOVFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lcjtcclxuICAgICAgICBpZiAoY29udGFpbmVyKSB7XHJcbiAgICAgICAgICB0aGlzLnNjcm9sbEltbWVkaWF0ZWx5KGNvbnRhaW5lciwgcGFyYW1zKTtcclxuXHJcbiAgICAgICAgICB0aGlzLl90cmFja0JveC5jbGVhckRlbHRhKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLl8kc2Nyb2xsU2l6ZS5uZXh0KGFjdHVhbFNjcm9sbFNpemUpO1xyXG5cclxuICAgICAgdGhpcy5vblNjcm9sbC5lbWl0KGFjdHVhbFNjcm9sbFNpemUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzY3JvbGxJbW1lZGlhdGVseShjb250YWluZXI6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+LCBwYXJhbXM6IFNjcm9sbE9wdGlvbnMpIHtcclxuICAgIHRoaXMuY2xlYXJTY3JvbGxJbW1lZGlhdGVseSgpO1xyXG5cclxuICAgIGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoU0NST0xMX0VORCwgdGhpcy5fb25TY3JvbGxFbmRIYW5kbGVyKTtcclxuICAgIGNvbnN0IGhhbmRsZXIgPSAoKSA9PiB7XHJcbiAgICAgIGlmIChjb250YWluZXIpIHtcclxuICAgICAgICBjb250YWluZXIubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFNDUk9MTF9FTkQsIGhhbmRsZXIpO1xyXG5cclxuICAgICAgICBjb250YWluZXIubmF0aXZlRWxlbWVudC5zY3JvbGwocGFyYW1zKTtcclxuXHJcbiAgICAgICAgY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihTQ1JPTExfRU5ELCB0aGlzLl9vblNjcm9sbEVuZEhhbmRsZXIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBjb250YWluZXIubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFNDUk9MTF9FTkQsIGhhbmRsZXIpO1xyXG5cclxuICAgIGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnNjcm9sbChwYXJhbXMpO1xyXG5cclxuICAgIHRoaXMuX3Njcm9sbEltbWVkaWF0ZWx5SGFuZGxlciA9IGhhbmRsZXI7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9zY3JvbGxJbW1lZGlhdGVseUhhbmRsZXI6ICgoLi4uYXJnczogQXJyYXk8YW55PikgPT4gdm9pZCkgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XHJcblxyXG4gIHByaXZhdGUgY2xlYXJTY3JvbGxJbW1lZGlhdGVseSgpIHtcclxuICAgIGlmICh0aGlzLl9zY3JvbGxJbW1lZGlhdGVseUhhbmRsZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyO1xyXG4gICAgaWYgKGNvbnRhaW5lcikge1xyXG4gICAgICBjb250YWluZXIubmF0aXZlRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFNDUk9MTF9FTkQsIHRoaXMuX3Njcm9sbEltbWVkaWF0ZWx5SGFuZGxlcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9vblNjcm9sbEVuZEhhbmRsZXIgPSAoZT86IEV2ZW50LCBmaXJlRXZlbnQ6IGJvb2xlYW4gPSB0cnVlKSA9PiB7XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXI7XHJcbiAgICBpZiAoY29udGFpbmVyKSB7XHJcbiAgICAgIGNvbnN0IGl0ZW1TaXplID0gdGhpcy5pdGVtU2l6ZSwgc25hcFRvSXRlbSA9IHRoaXMuc25hcFRvSXRlbSwgZHluYW1pY1NpemUgPSB0aGlzLmR5bmFtaWNTaXplLCBkZWx0YSA9IHRoaXMuX3RyYWNrQm94LmRlbHRhLFxyXG4gICAgICAgIHNjcm9sbFNpemUgPSAodGhpcy5faXNWZXJ0aWNhbCA/IGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnNjcm9sbFRvcCA6IGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQpO1xyXG4gICAgICBsZXQgYWN0dWFsU2Nyb2xsU2l6ZSA9IHNjcm9sbFNpemU7XHJcbiAgICAgIGlmIChkeW5hbWljU2l6ZSAmJiBkZWx0YSAhPT0gMCkge1xyXG4gICAgICAgIGFjdHVhbFNjcm9sbFNpemUgPSBzY3JvbGxTaXplICsgZGVsdGE7XHJcbiAgICAgICAgaWYgKHNjcm9sbFNpemUgIT09IGFjdHVhbFNjcm9sbFNpemUpIHtcclxuICAgICAgICAgIGNvbnN0IHBhcmFtczogU2Nyb2xsVG9PcHRpb25zID0ge1xyXG4gICAgICAgICAgICBbdGhpcy5faXNWZXJ0aWNhbCA/IFRPUF9QUk9QX05BTUUgOiBMRUZUX1BST1BfTkFNRV06IGFjdHVhbFNjcm9sbFNpemUsXHJcbiAgICAgICAgICAgIGJlaGF2aW9yOiBCRUhBVklPUl9JTlNUQU5UXHJcbiAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgIHRoaXMuX3RyYWNrQm94LmNsZWFyRGVsdGEoKTtcclxuXHJcbiAgICAgICAgICB0aGlzLl8kc2Nyb2xsU2l6ZS5uZXh0KGFjdHVhbFNjcm9sbFNpemUpO1xyXG5cclxuICAgICAgICAgIGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnNjcm9sbChwYXJhbXMpO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCBzY3JvbGxJdGVtcyA9IE1hdGgucm91bmQoc2Nyb2xsU2l6ZSAvIGl0ZW1TaXplKTtcclxuICAgICAgICBhY3R1YWxTY3JvbGxTaXplID0gc25hcFRvSXRlbSA/IHNjcm9sbEl0ZW1zICogaXRlbVNpemUgOiBzY3JvbGxTaXplO1xyXG5cclxuICAgICAgICBpZiAoc2Nyb2xsU2l6ZSAhPT0gYWN0dWFsU2Nyb2xsU2l6ZSkge1xyXG4gICAgICAgICAgY29uc3QgcGFyYW1zOiBTY3JvbGxUb09wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIFt0aGlzLl9pc1ZlcnRpY2FsID8gVE9QX1BST1BfTkFNRSA6IExFRlRfUFJPUF9OQU1FXTogYWN0dWFsU2Nyb2xsU2l6ZSxcclxuICAgICAgICAgICAgYmVoYXZpb3I6IEJFSEFWSU9SX0lOU1RBTlRcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsKHBhcmFtcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICB0aGlzLl8kc2Nyb2xsU2l6ZS5uZXh0KGFjdHVhbFNjcm9sbFNpemUpO1xyXG5cclxuICAgICAgaWYgKGZpcmVFdmVudCkge1xyXG4gICAgICAgIHRoaXMub25TY3JvbGxFbmQuZW1pdChhY3R1YWxTY3JvbGxTaXplKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfJGluaXRpYWxpemVkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XHJcblxyXG4gIHJlYWRvbmx5ICRpbml0aWFsaXplZDogT2JzZXJ2YWJsZTxib29sZWFuPjtcclxuXHJcbiAgLyoqXHJcbiAgICogRGljdGlvbmFyeSBvZiBlbGVtZW50IHNpemVzIGJ5IHRoZWlyIGlkXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBfdHJhY2tCb3ggPSBuZXcgVHJhY2tCb3goVFJBQ0tfQllfUFJPUEVSVFlfTkFNRSk7XHJcblxyXG4gIHByaXZhdGUgX29uVHJhY2tCb3hDaGFuZ2VIYW5kbGVyID0gKHY6IG51bWJlcikgPT4ge1xyXG4gICAgdGhpcy5fJGNhY2hlVmVyc2lvbi5uZXh0KHYpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfJGNhY2hlVmVyc2lvbiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigtMSk7XHJcbiAgZ2V0ICRjYWNoZVZlcnNpb24oKSB7IHJldHVybiB0aGlzLl8kY2FjaGVWZXJzaW9uLmFzT2JzZXJ2YWJsZSgpOyB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBfY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgIHByaXZhdGUgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+XHJcbiAgKSB7XHJcbiAgICBOZ1ZpcnR1YWxMaXN0Q29tcG9uZW50Ll9fbmV4dElkID0gTmdWaXJ0dWFsTGlzdENvbXBvbmVudC5fX25leHRJZCArIDEgPT09IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSXHJcbiAgICAgID8gMCA6IE5nVmlydHVhbExpc3RDb21wb25lbnQuX19uZXh0SWQgKyAxO1xyXG4gICAgdGhpcy5faWQgPSBOZ1ZpcnR1YWxMaXN0Q29tcG9uZW50Ll9fbmV4dElkO1xyXG5cclxuICAgIHRoaXMuXyRpbml0aWFsaXplZCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xyXG4gICAgdGhpcy4kaW5pdGlhbGl6ZWQgPSB0aGlzLl8kaW5pdGlhbGl6ZWQuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gICAgdGhpcy5fdHJhY2tCb3guZGlzcGxheUNvbXBvbmVudHMgPSB0aGlzLl9kaXNwbGF5Q29tcG9uZW50cztcclxuXHJcbiAgICBjb25zdCAkYm91bmRzID0gdGhpcy5fJGJvdW5kcy5hc09ic2VydmFibGUoKS5waXBlKFxyXG4gICAgICBmaWx0ZXIoYiA9PiAhIWIpLFxyXG4gICAgKSwgJGl0ZW1zID0gdGhpcy4kaXRlbXMucGlwZShcclxuICAgICAgbWFwKGkgPT4gIWkgPyBbXSA6IGkpLFxyXG4gICAgKSwgJHNjcm9sbFNpemUgPSB0aGlzLl8kc2Nyb2xsU2l6ZS5hc09ic2VydmFibGUoKSxcclxuICAgICAgJGl0ZW1TaXplID0gdGhpcy4kaXRlbVNpemUucGlwZShcclxuICAgICAgICBtYXAodiA9PiB2IDw9IDAgPyBERUZBVUxUX0lURU1fU0laRSA6IHYpLFxyXG4gICAgICApLFxyXG4gICAgICAkaXRlbXNPZmZzZXQgPSB0aGlzLiRpdGVtc09mZnNldC5waXBlKFxyXG4gICAgICAgIG1hcCh2ID0+IHYgPCAwID8gREVGQVVMVF9JVEVNU19PRkZTRVQgOiB2KSxcclxuICAgICAgKSxcclxuICAgICAgJHN0aWNreU1hcCA9IHRoaXMuJHN0aWNreU1hcC5waXBlKFxyXG4gICAgICAgIG1hcCh2ID0+ICF2ID8ge30gOiB2KSxcclxuICAgICAgKSxcclxuICAgICAgJHNuYXAgPSB0aGlzLiRzbmFwLFxyXG4gICAgICAkaXNWZXJ0aWNhbCA9IHRoaXMuJGRpcmVjdGlvbi5waXBlKFxyXG4gICAgICAgIG1hcCh2ID0+IHRoaXMuZ2V0SXNWZXJ0aWNhbCh2IHx8IERFRkFVTFRfRElSRUNUSU9OKSksXHJcbiAgICAgICksXHJcbiAgICAgICRkeW5hbWljU2l6ZSA9IHRoaXMuJGR5bmFtaWNTaXplLFxyXG4gICAgICAkY2FjaGVWZXJzaW9uID0gdGhpcy4kY2FjaGVWZXJzaW9uLFxyXG4gICAgICAkc2Nyb2xsZWRJdGVtSWQgPSB0aGlzLl8kc2Nyb2xsZWRJdGVtSWQuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gICAgJGlzVmVydGljYWwucGlwZShcclxuICAgICAgdGFrZVVudGlsRGVzdHJveWVkKCksXHJcbiAgICAgIHRhcCh2ID0+IHtcclxuICAgICAgICB0aGlzLl9pc1ZlcnRpY2FsID0gdjtcclxuICAgICAgICBjb25zdCBlbDogSFRNTEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgdG9nZ2xlQ2xhc3NOYW1lKGVsLCB2ID8gQ0xBU1NfTElTVF9WRVJUSUNBTCA6IENMQVNTX0xJU1RfSE9SSVpPTlRBTCwgdHJ1ZSk7XHJcbiAgICAgIH0pLFxyXG4gICAgKS5zdWJzY3JpYmUoKTtcclxuXHJcbiAgICAkZHluYW1pY1NpemUucGlwZShcclxuICAgICAgdGFrZVVudGlsRGVzdHJveWVkKCksXHJcbiAgICAgIHRhcChkeW5hbWljU2l6ZSA9PiB7XHJcbiAgICAgICAgdGhpcy5saXN0ZW5DYWNoZUNoYW5nZXNJZk5lZWQoZHluYW1pY1NpemUpO1xyXG4gICAgICB9KVxyXG4gICAgKS5zdWJzY3JpYmUoKTtcclxuXHJcbiAgICBjb21iaW5lTGF0ZXN0KFt0aGlzLiRpbml0aWFsaXplZCwgJHNjcm9sbGVkSXRlbUlkLCAkYm91bmRzLCAkaXRlbXMsICRzdGlja3lNYXAsICRzY3JvbGxTaXplLCAkaXRlbVNpemUsXHJcbiAgICAgICRpdGVtc09mZnNldCwgJHNuYXAsICRpc1ZlcnRpY2FsLCAkZHluYW1pY1NpemUsICRjYWNoZVZlcnNpb24sXHJcbiAgICBdKS5waXBlKFxyXG4gICAgICB0YWtlVW50aWxEZXN0cm95ZWQoKSxcclxuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcclxuICAgICAgZGVib3VuY2VUaW1lKDApLFxyXG4gICAgICBmaWx0ZXIoKFtpbml0aWFsaXplZF0pID0+ICEhaW5pdGlhbGl6ZWQpLFxyXG4gICAgICBzd2l0Y2hNYXAoKFssIHNjcm9sbGVkSXRlbUlkLFxyXG4gICAgICAgIGJvdW5kcywgaXRlbXMsIHN0aWNreU1hcCwgc2Nyb2xsU2l6ZSwgaXRlbVNpemUsXHJcbiAgICAgICAgaXRlbXNPZmZzZXQsIHNuYXAsIGlzVmVydGljYWwsIGR5bmFtaWNTaXplLCBjYWNoZVZlcnNpb24sXHJcbiAgICAgIF0pID0+IHtcclxuICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IGJvdW5kcyBhcyBET01SZWN0O1xyXG4gICAgICAgIGxldCBhY3R1YWxTY3JvbGxTaXplID0gc2Nyb2xsU2l6ZTtcclxuICAgICAgICBjb25zdCBvcHRzOiBJUmVjYWxjdWxhdGVNZXRyaWNzT3B0aW9uczxJVmlydHVhbExpc3RJdGVtLCBJVmlydHVhbExpc3RDb2xsZWN0aW9uPiA9IHtcclxuICAgICAgICAgIGJvdW5kczogeyB3aWR0aCwgaGVpZ2h0IH0sIGNvbGxlY3Rpb246IGl0ZW1zLCBkeW5hbWljU2l6ZSwgaXNWZXJ0aWNhbCwgaXRlbVNpemUsXHJcbiAgICAgICAgICBpdGVtc09mZnNldCwgc2Nyb2xsU2l6ZTogc2Nyb2xsU2l6ZSwgc25hcCwgZnJvbUl0ZW1JZDogc2Nyb2xsZWRJdGVtSWQsXHJcbiAgICAgICAgfTtcclxuICAgICAgICBpZiAoZHluYW1pY1NpemUgJiYgc2Nyb2xsZWRJdGVtSWQgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgY29uc3Qgc2Nyb2xsU2l6ZSA9IHRoaXMuX3RyYWNrQm94LmdldEl0ZW1Qb3NpdGlvbihzY3JvbGxlZEl0ZW1JZCwgc3RpY2t5TWFwLCB7IC4uLm9wdHMsIHNjcm9sbFNpemU6IGFjdHVhbFNjcm9sbFNpemUgfSk7XHJcbiAgICAgICAgICBhY3R1YWxTY3JvbGxTaXplID0gc2Nyb2xsU2l6ZTtcclxuXHJcbiAgICAgICAgICB0aGlzLl8kc2Nyb2xsU2l6ZS5uZXh0KGFjdHVhbFNjcm9sbFNpemUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgc2Nyb2xsRGlyZWN0aW9uID0gdGhpcy5fc2Nyb2xsRGlyZWN0aW9uLFxyXG4gICAgICAgICAgeyBkaXNwbGF5SXRlbXMsIHRvdGFsU2l6ZSB9ID0gdGhpcy5fdHJhY2tCb3gudXBkYXRlQ29sbGVjdGlvbihpdGVtcywgc3RpY2t5TWFwLCB7XHJcbiAgICAgICAgICAgIC4uLm9wdHMsIHNjcm9sbFNpemU6IGFjdHVhbFNjcm9sbFNpemUsIHNjcm9sbERpcmVjdGlvblxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMucmVzZXRCb3VuZHNTaXplKGlzVmVydGljYWwsIHRvdGFsU2l6ZSk7XHJcblxyXG4gICAgICAgIHRoaXMuY3JlYXRlRGlzcGxheUNvbXBvbmVudHNJZk5lZWQoZGlzcGxheUl0ZW1zKTtcclxuXHJcbiAgICAgICAgdGhpcy50cmFja2luZygpO1xyXG5cclxuICAgICAgICBpZiAoZHluYW1pY1NpemUgJiYgc2Nyb2xsZWRJdGVtSWQgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyO1xyXG4gICAgICAgICAgaWYgKGNvbnRhaW5lcikge1xyXG4gICAgICAgICAgICBjb25zdCBwYXJhbXM6IFNjcm9sbFRvT3B0aW9ucyA9IHsgW3RoaXMuX2lzVmVydGljYWwgPyBUT1BfUFJPUF9OQU1FIDogTEVGVF9QUk9QX05BTUVdOiBzY3JvbGxTaXplLCBiZWhhdmlvcjogQkVIQVZJT1JfQVVUTyB9O1xyXG5cclxuICAgICAgICAgICAgdGhpcy5zY3JvbGxJbW1lZGlhdGVseShjb250YWluZXIsIHBhcmFtcyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gb2YoZGlzcGxheUl0ZW1zKTtcclxuICAgICAgfSksXHJcbiAgICApLnN1YnNjcmliZSgpO1xyXG5cclxuICAgIGNvbWJpbmVMYXRlc3QoW3RoaXMuJGluaXRpYWxpemVkLCB0aGlzLiRpdGVtUmVuZGVyZXJdKS5waXBlKFxyXG4gICAgICB0YWtlVW50aWxEZXN0cm95ZWQoKSxcclxuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcclxuICAgICAgZmlsdGVyKChbaW5pdGlhbGl6ZWRdKSA9PiAhIWluaXRpYWxpemVkKSxcclxuICAgICAgdGFwKChbLCBpdGVtUmVuZGVyZXJdKSA9PiB7XHJcbiAgICAgICAgdGhpcy5yZXNldFJlbmRlcmVycyhpdGVtUmVuZGVyZXIpO1xyXG4gICAgICB9KVxyXG4gICAgKVxyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLl8kaW5pdGlhbGl6ZWQubmV4dCh0cnVlKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgbGlzdGVuQ2FjaGVDaGFuZ2VzSWZOZWVkKHZhbHVlOiBib29sZWFuKSB7XHJcbiAgICBpZiAodmFsdWUpIHtcclxuICAgICAgaWYgKCF0aGlzLl90cmFja0JveC5oYXNFdmVudExpc3RlbmVyKFRSQUNLX0JPWF9DSEFOR0VfRVZFTlRfTkFNRSwgdGhpcy5fb25UcmFja0JveENoYW5nZUhhbmRsZXIpKSB7XHJcbiAgICAgICAgdGhpcy5fdHJhY2tCb3guYWRkRXZlbnRMaXN0ZW5lcihUUkFDS19CT1hfQ0hBTkdFX0VWRU5UX05BTUUsIHRoaXMuX29uVHJhY2tCb3hDaGFuZ2VIYW5kbGVyKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHRoaXMuX3RyYWNrQm94Lmhhc0V2ZW50TGlzdGVuZXIoVFJBQ0tfQk9YX0NIQU5HRV9FVkVOVF9OQU1FLCB0aGlzLl9vblRyYWNrQm94Q2hhbmdlSGFuZGxlcikpIHtcclxuICAgICAgICB0aGlzLl90cmFja0JveC5yZW1vdmVFdmVudExpc3RlbmVyKFRSQUNLX0JPWF9DSEFOR0VfRVZFTlRfTkFNRSwgdGhpcy5fb25UcmFja0JveENoYW5nZUhhbmRsZXIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldElzVmVydGljYWwoZD86IERpcmVjdGlvbikge1xyXG4gICAgY29uc3QgZGlyID0gZCB8fCB0aGlzLmRpcmVjdGlvbjtcclxuICAgIHJldHVybiBpc0RpcmVjdGlvbihkaXIsIERpcmVjdGlvbnMuVkVSVElDQUwpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjcmVhdGVEaXNwbGF5Q29tcG9uZW50c0lmTmVlZChkaXNwbGF5SXRlbXM6IElSZW5kZXJWaXJ0dWFsTGlzdENvbGxlY3Rpb24gfCBudWxsKSB7XHJcbiAgICBpZiAoIWRpc3BsYXlJdGVtcyB8fCAhdGhpcy5fbGlzdENvbnRhaW5lclJlZikge1xyXG4gICAgICB0aGlzLl90cmFja0JveC5zZXREaXNwbGF5T2JqZWN0SW5kZXhNYXBCeUlkKHt9KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3RyYWNrQm94Lml0ZW1zID0gZGlzcGxheUl0ZW1zO1xyXG5cclxuICAgIGNvbnN0IF9saXN0Q29udGFpbmVyUmVmID0gdGhpcy5fbGlzdENvbnRhaW5lclJlZjtcclxuXHJcbiAgICB3aGlsZSAodGhpcy5fZGlzcGxheUNvbXBvbmVudHMubGVuZ3RoIDwgZGlzcGxheUl0ZW1zLmxlbmd0aCkge1xyXG4gICAgICBpZiAoX2xpc3RDb250YWluZXJSZWYpIHtcclxuICAgICAgICBjb25zdCBjb21wID0gX2xpc3RDb250YWluZXJSZWYuY3JlYXRlQ29tcG9uZW50KE5nVmlydHVhbExpc3RJdGVtQ29tcG9uZW50KTtcclxuICAgICAgICB0aGlzLl9kaXNwbGF5Q29tcG9uZW50cy5wdXNoKGNvbXApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbWF4TGVuZ3RoID0gZGlzcGxheUl0ZW1zLmxlbmd0aDtcclxuICAgIHdoaWxlICh0aGlzLl9kaXNwbGF5Q29tcG9uZW50cy5sZW5ndGggPiBtYXhMZW5ndGgpIHtcclxuICAgICAgY29uc3QgY29tcCA9IHRoaXMuX2Rpc3BsYXlDb21wb25lbnRzLnBvcCgpO1xyXG4gICAgICBjb21wPy5kZXN0cm95KCk7XHJcbiAgICAgIGNvbnN0IGlkID0gY29tcD8uaW5zdGFuY2UuaXRlbT8uaWQ7XHJcbiAgICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5fdHJhY2tCb3gudW50cmFja0NvbXBvbmVudEJ5SWRQcm9wZXJ0eShjb21wPy5pbnN0YW5jZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnJlc2V0UmVuZGVyZXJzKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc2V0UmVuZGVyZXJzKGl0ZW1SZW5kZXJlcj86IFRlbXBsYXRlUmVmPGFueT4pIHtcclxuICAgIGNvbnN0IGRvTWFwOiB7IFtpZDogbnVtYmVyXTogbnVtYmVyIH0gPSB7fTtcclxuICAgIGZvciAobGV0IGkgPSAwLCBsID0gdGhpcy5fZGlzcGxheUNvbXBvbmVudHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9kaXNwbGF5Q29tcG9uZW50c1tpXTtcclxuICAgICAgaXRlbS5pbnN0YW5jZS5yZW5kZXJlciA9IGl0ZW1SZW5kZXJlciB8fCB0aGlzLml0ZW1SZW5kZXJlcjtcclxuICAgICAgZG9NYXBbaXRlbS5pbnN0YW5jZS5pZF0gPSBpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuX3RyYWNrQm94LnNldERpc3BsYXlPYmplY3RJbmRleE1hcEJ5SWQoZG9NYXApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVHJhY2tpbmcgYnkgaWRcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgdHJhY2tpbmcoKSB7XHJcbiAgICB0aGlzLl90cmFja0JveC50cmFjaygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZXNldEJvdW5kc1NpemUoaXNWZXJ0aWNhbDogYm9vbGVhbiwgdG90YWxTaXplOiBudW1iZXIpIHtcclxuICAgIGNvbnN0IGwgPSB0aGlzLl9saXN0O1xyXG4gICAgaWYgKGwpIHtcclxuICAgICAgbC5uYXRpdmVFbGVtZW50LnN0eWxlW2lzVmVydGljYWwgPyBIRUlHSFRfUFJPUF9OQU1FIDogV0lEVEhfUFJPUF9OQU1FXSA9IGAke3RvdGFsU2l6ZX0ke1BYfWA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgbWV0aG9kIHNjcm9sbHMgdGhlIGxpc3QgdG8gdGhlIGVsZW1lbnQgd2l0aCB0aGUgZ2l2ZW4gaWQgYW5kIHJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSBzY3JvbGxlZCBhcmVhLlxyXG4gICAqIEJlaGF2aW9yIGFjY2VwdHMgdGhlIHZhbHVlcyDigIvigItcImF1dG9cIiwgXCJpbnN0YW50XCIgYW5kIFwic21vb3RoXCIuXHJcbiAgICovXHJcbiAgc2Nyb2xsVG8oaWQ6IElkLCBiZWhhdmlvcjogU2Nyb2xsQmVoYXZpb3IgPSBCRUhBVklPUl9BVVRPKSB7XHJcbiAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XHJcbiAgICBpZiAoIWl0ZW1zIHx8ICFpdGVtcy5sZW5ndGgpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGR5bmFtaWNTaXplID0gdGhpcy5keW5hbWljU2l6ZSwgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyLCBpdGVtU2l6ZSA9IHRoaXMuaXRlbVNpemU7XHJcbiAgICBpZiAoY29udGFpbmVyKSB7XHJcbiAgICAgIGlmIChkeW5hbWljU2l6ZSkge1xyXG4gICAgICAgIGlmIChjb250YWluZXIpIHtcclxuICAgICAgICAgIGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoU0NST0xMLCB0aGlzLl9vblNjcm9sbEhhbmRsZXIpO1xyXG4gICAgICAgICAgY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihTQ1JPTExfRU5ELCB0aGlzLl9vblNjcm9sbEVuZEhhbmRsZXIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSB0aGlzLl8kYm91bmRzLmdldFZhbHVlKCkgfHwgeyB3aWR0aDogMCwgaGVpZ2h0OiAwIH0sXHJcbiAgICAgICAgICBzdGlja3lNYXAgPSB0aGlzLnN0aWNreU1hcCwgaXRlbXMgPSB0aGlzLml0ZW1zLFxyXG4gICAgICAgICAgb3B0czogSVJlY2FsY3VsYXRlTWV0cmljc09wdGlvbnM8SVZpcnR1YWxMaXN0SXRlbSwgSVZpcnR1YWxMaXN0Q29sbGVjdGlvbj4gPSB7XHJcbiAgICAgICAgICAgIGJvdW5kczogeyB3aWR0aCwgaGVpZ2h0IH0sIGNvbGxlY3Rpb246IGl0ZW1zLCBkeW5hbWljU2l6ZSwgaXNWZXJ0aWNhbDogdGhpcy5faXNWZXJ0aWNhbCwgaXRlbVNpemUsXHJcbiAgICAgICAgICAgIGl0ZW1zT2Zmc2V0OiB0aGlzLml0ZW1zT2Zmc2V0LCBzY3JvbGxTaXplOiB0aGlzLl9pc1ZlcnRpY2FsID8gY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wIDogY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsTGVmdCxcclxuICAgICAgICAgICAgc25hcDogdGhpcy5zbmFwLCBmcm9tSXRlbUlkOiBpZCxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBzY3JvbGxTaXplID0gdGhpcy5fdHJhY2tCb3guZ2V0SXRlbVBvc2l0aW9uKGlkLCBzdGlja3lNYXAsIG9wdHMpLFxyXG4gICAgICAgICAgcGFyYW1zOiBTY3JvbGxUb09wdGlvbnMgPSB7IFt0aGlzLl9pc1ZlcnRpY2FsID8gVE9QX1BST1BfTkFNRSA6IExFRlRfUFJPUF9OQU1FXTogc2Nyb2xsU2l6ZSwgYmVoYXZpb3IgfTtcclxuXHJcbiAgICAgICAgdGhpcy5fJHNjcm9sbGVkSXRlbUlkLm5leHQoaWQpO1xyXG5cclxuICAgICAgICB0aGlzLl8kc2Nyb2xsU2l6ZS5uZXh0KHNjcm9sbFNpemUpO1xyXG5cclxuICAgICAgICBpZiAoY29udGFpbmVyKSB7XHJcbiAgICAgICAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoY29udGFpbmVyKSB7XHJcbiAgICAgICAgICAgICAgY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihTQ1JPTExfRU5ELCBoYW5kbGVyKTtcclxuICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fc2Nyb2xsVG9UaW1lb3V0KTtcclxuICAgICAgICAgICAgICB0aGlzLl9zY3JvbGxUb1RpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoU0NST0xMLCB0aGlzLl9vblNjcm9sbEhhbmRsZXIpO1xyXG4gICAgICAgICAgICAgICAgY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihTQ1JPTExfRU5ELCB0aGlzLl9vblNjcm9sbEVuZEhhbmRsZXIpO1xyXG4gICAgICAgICAgICAgIH0sIDEwMCk7XHJcblxyXG4gICAgICAgICAgICAgIHRoaXMubGlzdGVuQ2FjaGVDaGFuZ2VzSWZOZWVkKGR5bmFtaWNTaXplKTtcclxuXHJcbiAgICAgICAgICAgICAgdGhpcy5vblNjcm9sbC5lbWl0KHNjcm9sbFNpemUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBjb250YWluZXIubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFNDUk9MTF9FTkQsIGhhbmRsZXIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsKHBhcmFtcyk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpZCksIHNjcm9sbFNpemUgPSBpbmRleCAqIHRoaXMuaXRlbVNpemU7XHJcbiAgICAgICAgY29uc3QgcGFyYW1zOiBTY3JvbGxUb09wdGlvbnMgPSB7IFt0aGlzLl9pc1ZlcnRpY2FsID8gVE9QX1BST1BfTkFNRSA6IExFRlRfUFJPUF9OQU1FXTogc2Nyb2xsU2l6ZSwgYmVoYXZpb3IgfTtcclxuICAgICAgICBjb250YWluZXIubmF0aXZlRWxlbWVudC5zY3JvbGwocGFyYW1zKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2Nyb2xsVG9FbmQoYmVoYXZpb3I6IFNjcm9sbEJlaGF2aW9yID0gQkVIQVZJT1JfSU5TVEFOVCkge1xyXG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zLCBsYXRJdGVtID0gaXRlbXNbaXRlbXMubGVuZ3RoID4gMCA/IGl0ZW1zLmxlbmd0aCAtIDEgOiAwXTtcclxuICAgIHRoaXMuc2Nyb2xsVG8obGF0SXRlbS5pZCwgYmVoYXZpb3IpO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgY29uc3QgY29udGFpbmVyRWwgPSB0aGlzLl9jb250YWluZXI7XHJcbiAgICBpZiAoY29udGFpbmVyRWwpIHtcclxuICAgICAgY29udGFpbmVyRWwubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFNDUk9MTCwgdGhpcy5fb25TY3JvbGxIYW5kbGVyKTtcclxuICAgICAgY29udGFpbmVyRWwubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFNDUk9MTF9FTkQsIHRoaXMuX29uU2Nyb2xsRW5kSGFuZGxlcik7XHJcblxyXG4gICAgICB0aGlzLl9yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcih0aGlzLl9vblJlc2l6ZUhhbmRsZXIpO1xyXG4gICAgICB0aGlzLl9yZXNpemVPYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lckVsLm5hdGl2ZUVsZW1lbnQpO1xyXG5cclxuICAgICAgdGhpcy5fb25SZXNpemVIYW5kbGVyKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLl9zY3JvbGxUb1RpbWVvdXQpIHtcclxuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX3Njcm9sbFRvVGltZW91dCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuX3RyYWNrQm94KSB7XHJcbiAgICAgIHRoaXMuX3RyYWNrQm94LmRpc3Bvc2UoKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjb250YWluZXJFbCA9IHRoaXMuX2NvbnRhaW5lcjtcclxuICAgIGlmIChjb250YWluZXJFbCkge1xyXG4gICAgICBjb250YWluZXJFbC5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoU0NST0xMLCB0aGlzLl9vblNjcm9sbEhhbmRsZXIpO1xyXG4gICAgICBjb250YWluZXJFbC5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoU0NST0xMX0VORCwgdGhpcy5fb25TY3JvbGxFbmRIYW5kbGVyKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLl9yZXNpemVPYnNlcnZlcikge1xyXG4gICAgICAgIHRoaXMuX3Jlc2l6ZU9ic2VydmVyLnVub2JzZXJ2ZShjb250YWluZXJFbC5uYXRpdmVFbGVtZW50KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLl9kaXNwbGF5Q29tcG9uZW50cykge1xyXG4gICAgICB3aGlsZSAodGhpcy5fZGlzcGxheUNvbXBvbmVudHMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIGNvbnN0IGNvbXAgPSB0aGlzLl9kaXNwbGF5Q29tcG9uZW50cy5wb3AoKTtcclxuICAgICAgICBjb21wPy5kZXN0cm95KCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiPGRpdiAjY29udGFpbmVyIHBhcnQ9XCJzY3JvbGxlclwiIGNsYXNzPVwibmd2bF9fY29udGFpbmVyXCI+XHJcbiAgPHVsICNsaXN0IHBhcnQ9XCJsaXN0XCIgY2xhc3M9XCJuZ3ZsX19saXN0XCI+XHJcbiAgICA8bmctY29udGFpbmVyICNyZW5kZXJlcnNDb250YWluZXI+PC9uZy1jb250YWluZXI+XHJcbiAgPC91bD5cclxuPC9kaXY+Il19