UNPKG

@angular/core

Version:

Angular - the core framework

668 lines • 81.9 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { RuntimeError } from '../../errors'; import { isListLikeIterable, iterateListLike } from '../../util/iterable'; import { stringify } from '../../util/stringify'; export class DefaultIterableDifferFactory { constructor() { } supports(obj) { return isListLikeIterable(obj); } create(trackByFn) { return new DefaultIterableDiffer(trackByFn); } } const trackByIdentity = (index, item) => item; /** * @deprecated v4.0.0 - Should not be part of public API. * @publicApi */ export class DefaultIterableDiffer { constructor(trackByFn) { this.length = 0; // Keeps track of the used records at any point in time (during & across `_check()` calls) this._linkedRecords = null; // Keeps track of the removed records at any point in time during `_check()` calls. this._unlinkedRecords = null; this._previousItHead = null; this._itHead = null; this._itTail = null; this._additionsHead = null; this._additionsTail = null; this._movesHead = null; this._movesTail = null; this._removalsHead = null; this._removalsTail = null; // Keeps track of records where custom track by is the same, but item identity has changed this._identityChangesHead = null; this._identityChangesTail = null; this._trackByFn = trackByFn || trackByIdentity; } forEachItem(fn) { let record; for (record = this._itHead; record !== null; record = record._next) { fn(record); } } forEachOperation(fn) { let nextIt = this._itHead; let nextRemove = this._removalsHead; let addRemoveOffset = 0; let moveOffsets = null; while (nextIt || nextRemove) { // Figure out which is the next record to process // Order: remove, add, move const record = !nextRemove || (nextIt && nextIt.currentIndex < getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets)) ? nextIt : nextRemove; const adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets); const currentIndex = record.currentIndex; // consume the item, and adjust the addRemoveOffset and update moveDistance if necessary if (record === nextRemove) { addRemoveOffset--; nextRemove = nextRemove._nextRemoved; } else { nextIt = nextIt._next; if (record.previousIndex == null) { addRemoveOffset++; } else { // INVARIANT: currentIndex < previousIndex if (!moveOffsets) moveOffsets = []; const localMovePreviousIndex = adjPreviousIndex - addRemoveOffset; const localCurrentIndex = currentIndex - addRemoveOffset; if (localMovePreviousIndex != localCurrentIndex) { for (let i = 0; i < localMovePreviousIndex; i++) { const offset = i < moveOffsets.length ? moveOffsets[i] : (moveOffsets[i] = 0); const index = offset + i; if (localCurrentIndex <= index && index < localMovePreviousIndex) { moveOffsets[i] = offset + 1; } } const previousIndex = record.previousIndex; moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex; } } } if (adjPreviousIndex !== currentIndex) { fn(record, adjPreviousIndex, currentIndex); } } } forEachPreviousItem(fn) { let record; for (record = this._previousItHead; record !== null; record = record._nextPrevious) { fn(record); } } forEachAddedItem(fn) { let record; for (record = this._additionsHead; record !== null; record = record._nextAdded) { fn(record); } } forEachMovedItem(fn) { let record; for (record = this._movesHead; record !== null; record = record._nextMoved) { fn(record); } } forEachRemovedItem(fn) { let record; for (record = this._removalsHead; record !== null; record = record._nextRemoved) { fn(record); } } forEachIdentityChange(fn) { let record; for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) { fn(record); } } diff(collection) { if (collection == null) collection = []; if (!isListLikeIterable(collection)) { throw new RuntimeError(900 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */, ngDevMode && `Error trying to diff '${stringify(collection)}'. Only arrays and iterables are allowed`); } if (this.check(collection)) { return this; } else { return null; } } onDestroy() { } check(collection) { this._reset(); let record = this._itHead; let mayBeDirty = false; let index; let item; let itemTrackBy; if (Array.isArray(collection)) { this.length = collection.length; for (let index = 0; index < this.length; index++) { item = collection[index]; itemTrackBy = this._trackByFn(index, item); if (record === null || !Object.is(record.trackById, itemTrackBy)) { record = this._mismatch(record, item, itemTrackBy, index); mayBeDirty = true; } else { if (mayBeDirty) { // TODO(misko): can we limit this to duplicates only? record = this._verifyReinsertion(record, item, itemTrackBy, index); } if (!Object.is(record.item, item)) this._addIdentityChange(record, item); } record = record._next; } } else { index = 0; iterateListLike(collection, (item) => { itemTrackBy = this._trackByFn(index, item); if (record === null || !Object.is(record.trackById, itemTrackBy)) { record = this._mismatch(record, item, itemTrackBy, index); mayBeDirty = true; } else { if (mayBeDirty) { // TODO(misko): can we limit this to duplicates only? record = this._verifyReinsertion(record, item, itemTrackBy, index); } if (!Object.is(record.item, item)) this._addIdentityChange(record, item); } record = record._next; index++; }); this.length = index; } this._truncate(record); this.collection = collection; return this.isDirty; } /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity * changes. */ get isDirty() { return (this._additionsHead !== null || this._movesHead !== null || this._removalsHead !== null || this._identityChangesHead !== null); } /** * Reset the state of the change objects to show no changes. This means set previousKey to * currentKey, and clear all of the queues (additions, moves, removals). * Set the previousIndexes of moved and added items to their currentIndexes * Reset the list of additions, moves and removals * * @internal */ _reset() { if (this.isDirty) { let record; for (record = this._previousItHead = this._itHead; record !== null; record = record._next) { record._nextPrevious = record._next; } for (record = this._additionsHead; record !== null; record = record._nextAdded) { record.previousIndex = record.currentIndex; } this._additionsHead = this._additionsTail = null; for (record = this._movesHead; record !== null; record = record._nextMoved) { record.previousIndex = record.currentIndex; } this._movesHead = this._movesTail = null; this._removalsHead = this._removalsTail = null; this._identityChangesHead = this._identityChangesTail = null; // TODO(vicb): when assert gets supported // assert(!this.isDirty); } } /** * This is the core function which handles differences between collections. * * - `record` is the record which we saw at this position last time. If null then it is a new * item. * - `item` is the current item in the collection * - `index` is the position of the item in the collection * * @internal */ _mismatch(record, item, itemTrackBy, index) { // The previous record after which we will append the current one. let previousRecord; if (record === null) { previousRecord = this._itTail; } else { previousRecord = record._prev; // Remove the record from the collection since we know it does not match the item. this._remove(record); } // See if we have evicted the item, which used to be at some anterior position of _itHead list. record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null); if (record !== null) { // It is an item which we have evicted earlier: reinsert it back into the list. // But first we need to check if identity changed, so we can update in view if necessary. if (!Object.is(record.item, item)) this._addIdentityChange(record, item); this._reinsertAfter(record, previousRecord, index); } else { // Attempt to see if the item is at some posterior position of _itHead list. record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index); if (record !== null) { // We have the item in _itHead at/after `index` position. We need to move it forward in the // collection. // But first we need to check if identity changed, so we can update in view if necessary. if (!Object.is(record.item, item)) this._addIdentityChange(record, item); this._moveAfter(record, previousRecord, index); } else { // It is a new item: add it. record = this._addAfter(new IterableChangeRecord_(item, itemTrackBy), previousRecord, index); } } return record; } /** * This check is only needed if an array contains duplicates. (Short circuit of nothing dirty) * * Use case: `[a, a]` => `[b, a, a]` * * If we did not have this check then the insertion of `b` would: * 1) evict first `a` * 2) insert `b` at `0` index. * 3) leave `a` at index `1` as is. <-- this is wrong! * 3) reinsert `a` at index 2. <-- this is wrong! * * The correct behavior is: * 1) evict first `a` * 2) insert `b` at `0` index. * 3) reinsert `a` at index 1. * 3) move `a` at from `1` to `2`. * * * Double check that we have not evicted a duplicate item. We need to check if the item type may * have already been removed: * The insertion of b will evict the first 'a'. If we don't reinsert it now it will be reinserted * at the end. Which will show up as the two 'a's switching position. This is incorrect, since a * better way to think of it is as insert of 'b' rather then switch 'a' with 'b' and then add 'a' * at the end. * * @internal */ _verifyReinsertion(record, item, itemTrackBy, index) { let reinsertRecord = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null); if (reinsertRecord !== null) { record = this._reinsertAfter(reinsertRecord, record._prev, index); } else if (record.currentIndex != index) { record.currentIndex = index; this._addToMoves(record, index); } return record; } /** * Get rid of any excess {@link IterableChangeRecord_}s from the previous collection * * - `record` The first excess {@link IterableChangeRecord_}. * * @internal */ _truncate(record) { // Anything after that needs to be removed; while (record !== null) { const nextRecord = record._next; this._addToRemovals(this._unlink(record)); record = nextRecord; } if (this._unlinkedRecords !== null) { this._unlinkedRecords.clear(); } if (this._additionsTail !== null) { this._additionsTail._nextAdded = null; } if (this._movesTail !== null) { this._movesTail._nextMoved = null; } if (this._itTail !== null) { this._itTail._next = null; } if (this._removalsTail !== null) { this._removalsTail._nextRemoved = null; } if (this._identityChangesTail !== null) { this._identityChangesTail._nextIdentityChange = null; } } /** @internal */ _reinsertAfter(record, prevRecord, index) { if (this._unlinkedRecords !== null) { this._unlinkedRecords.remove(record); } const prev = record._prevRemoved; const next = record._nextRemoved; if (prev === null) { this._removalsHead = next; } else { prev._nextRemoved = next; } if (next === null) { this._removalsTail = prev; } else { next._prevRemoved = prev; } this._insertAfter(record, prevRecord, index); this._addToMoves(record, index); return record; } /** @internal */ _moveAfter(record, prevRecord, index) { this._unlink(record); this._insertAfter(record, prevRecord, index); this._addToMoves(record, index); return record; } /** @internal */ _addAfter(record, prevRecord, index) { this._insertAfter(record, prevRecord, index); if (this._additionsTail === null) { // TODO(vicb): // assert(this._additionsHead === null); this._additionsTail = this._additionsHead = record; } else { // TODO(vicb): // assert(_additionsTail._nextAdded === null); // assert(record._nextAdded === null); this._additionsTail = this._additionsTail._nextAdded = record; } return record; } /** @internal */ _insertAfter(record, prevRecord, index) { // TODO(vicb): // assert(record != prevRecord); // assert(record._next === null); // assert(record._prev === null); const next = prevRecord === null ? this._itHead : prevRecord._next; // TODO(vicb): // assert(next != record); // assert(prevRecord != record); record._next = next; record._prev = prevRecord; if (next === null) { this._itTail = record; } else { next._prev = record; } if (prevRecord === null) { this._itHead = record; } else { prevRecord._next = record; } if (this._linkedRecords === null) { this._linkedRecords = new _DuplicateMap(); } this._linkedRecords.put(record); record.currentIndex = index; return record; } /** @internal */ _remove(record) { return this._addToRemovals(this._unlink(record)); } /** @internal */ _unlink(record) { if (this._linkedRecords !== null) { this._linkedRecords.remove(record); } const prev = record._prev; const next = record._next; // TODO(vicb): // assert((record._prev = null) === null); // assert((record._next = null) === null); if (prev === null) { this._itHead = next; } else { prev._next = next; } if (next === null) { this._itTail = prev; } else { next._prev = prev; } return record; } /** @internal */ _addToMoves(record, toIndex) { // TODO(vicb): // assert(record._nextMoved === null); if (record.previousIndex === toIndex) { return record; } if (this._movesTail === null) { // TODO(vicb): // assert(_movesHead === null); this._movesTail = this._movesHead = record; } else { // TODO(vicb): // assert(_movesTail._nextMoved === null); this._movesTail = this._movesTail._nextMoved = record; } return record; } _addToRemovals(record) { if (this._unlinkedRecords === null) { this._unlinkedRecords = new _DuplicateMap(); } this._unlinkedRecords.put(record); record.currentIndex = null; record._nextRemoved = null; if (this._removalsTail === null) { // TODO(vicb): // assert(_removalsHead === null); this._removalsTail = this._removalsHead = record; record._prevRemoved = null; } else { // TODO(vicb): // assert(_removalsTail._nextRemoved === null); // assert(record._nextRemoved === null); record._prevRemoved = this._removalsTail; this._removalsTail = this._removalsTail._nextRemoved = record; } return record; } /** @internal */ _addIdentityChange(record, item) { record.item = item; if (this._identityChangesTail === null) { this._identityChangesTail = this._identityChangesHead = record; } else { this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record; } return record; } } export class IterableChangeRecord_ { constructor(item, trackById) { this.item = item; this.trackById = trackById; this.currentIndex = null; this.previousIndex = null; /** @internal */ this._nextPrevious = null; /** @internal */ this._prev = null; /** @internal */ this._next = null; /** @internal */ this._prevDup = null; /** @internal */ this._nextDup = null; /** @internal */ this._prevRemoved = null; /** @internal */ this._nextRemoved = null; /** @internal */ this._nextAdded = null; /** @internal */ this._nextMoved = null; /** @internal */ this._nextIdentityChange = null; } } // A linked list of IterableChangeRecords with the same IterableChangeRecord_.item class _DuplicateItemRecordList { constructor() { /** @internal */ this._head = null; /** @internal */ this._tail = null; } /** * Append the record to the list of duplicates. * * Note: by design all records in the list of duplicates hold the same value in record.item. */ add(record) { if (this._head === null) { this._head = this._tail = record; record._nextDup = null; record._prevDup = null; } else { // TODO(vicb): // assert(record.item == _head.item || // record.item is num && record.item.isNaN && _head.item is num && _head.item.isNaN); this._tail._nextDup = record; record._prevDup = this._tail; record._nextDup = null; this._tail = record; } } // Returns a IterableChangeRecord_ having IterableChangeRecord_.trackById == trackById and // IterableChangeRecord_.currentIndex >= atOrAfterIndex get(trackById, atOrAfterIndex) { let record; for (record = this._head; record !== null; record = record._nextDup) { if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex) && Object.is(record.trackById, trackById)) { return record; } } return null; } /** * Remove one {@link IterableChangeRecord_} from the list of duplicates. * * Returns whether the list of duplicates is empty. */ remove(record) { // TODO(vicb): // assert(() { // // verify that the record being removed is in the list. // for (IterableChangeRecord_ cursor = _head; cursor != null; cursor = cursor._nextDup) { // if (identical(cursor, record)) return true; // } // return false; //}); const prev = record._prevDup; const next = record._nextDup; if (prev === null) { this._head = next; } else { prev._nextDup = next; } if (next === null) { this._tail = prev; } else { next._prevDup = prev; } return this._head === null; } } class _DuplicateMap { constructor() { this.map = new Map(); } put(record) { const key = record.trackById; let duplicates = this.map.get(key); if (!duplicates) { duplicates = new _DuplicateItemRecordList(); this.map.set(key, duplicates); } duplicates.add(record); } /** * Retrieve the `value` using key. Because the IterableChangeRecord_ value may be one which we * have already iterated over, we use the `atOrAfterIndex` to pretend it is not there. * * Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we * have any more `a`s needs to return the second `a`. */ get(trackById, atOrAfterIndex) { const key = trackById; const recordList = this.map.get(key); return recordList ? recordList.get(trackById, atOrAfterIndex) : null; } /** * Removes a {@link IterableChangeRecord_} from the list of duplicates. * * The list of duplicates also is removed from the map if it gets empty. */ remove(record) { const key = record.trackById; const recordList = this.map.get(key); // Remove the list of duplicates when it gets empty if (recordList.remove(record)) { this.map.delete(key); } return record; } get isEmpty() { return this.map.size === 0; } clear() { this.map.clear(); } } function getPreviousIndex(item, addRemoveOffset, moveOffsets) { const previousIndex = item.previousIndex; if (previousIndex === null) return previousIndex; let moveOffset = 0; if (moveOffsets && previousIndex < moveOffsets.length) { moveOffset = moveOffsets[previousIndex]; } return previousIndex + addRemoveOffset + moveOffset; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmYXVsdF9pdGVyYWJsZV9kaWZmZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9jaGFuZ2VfZGV0ZWN0aW9uL2RpZmZlcnMvZGVmYXVsdF9pdGVyYWJsZV9kaWZmZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFlBQVksRUFBbUIsTUFBTSxjQUFjLENBQUM7QUFFNUQsT0FBTyxFQUFDLGtCQUFrQixFQUFFLGVBQWUsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQ3hFLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQVcvQyxNQUFNLE9BQU8sNEJBQTRCO0lBQ3ZDLGdCQUFlLENBQUM7SUFDaEIsUUFBUSxDQUFDLEdBQThCO1FBQ3JDLE9BQU8sa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVELE1BQU0sQ0FBSSxTQUE4QjtRQUN0QyxPQUFPLElBQUkscUJBQXFCLENBQUksU0FBUyxDQUFDLENBQUM7SUFDakQsQ0FBQztDQUNGO0FBRUQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxLQUFhLEVBQUUsSUFBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUM7QUFFM0Q7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHFCQUFxQjtJQXNCaEMsWUFBWSxTQUE4QjtRQXJCMUIsV0FBTSxHQUFXLENBQUMsQ0FBQztRQUduQywwRkFBMEY7UUFDbEYsbUJBQWMsR0FBNEIsSUFBSSxDQUFDO1FBQ3ZELG1GQUFtRjtRQUMzRSxxQkFBZ0IsR0FBNEIsSUFBSSxDQUFDO1FBQ2pELG9CQUFlLEdBQW9DLElBQUksQ0FBQztRQUN4RCxZQUFPLEdBQW9DLElBQUksQ0FBQztRQUNoRCxZQUFPLEdBQW9DLElBQUksQ0FBQztRQUNoRCxtQkFBYyxHQUFvQyxJQUFJLENBQUM7UUFDdkQsbUJBQWMsR0FBb0MsSUFB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LE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRUQsS0FBSztRQUNILElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDbkIsQ0FBQztDQUNGO0FBRUQsU0FBUyxnQkFBZ0IsQ0FDdkIsSUFBUyxFQUNULGVBQXVCLEVBQ3ZCLFdBQTRCO0lBRTVCLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDekMsSUFBSSxhQUFhLEtBQUssSUFBSTtRQUFFLE9BQU8sYUFBYSxDQUFDO0lBQ2pELElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztJQUNuQixJQUFJLFdBQVcsSUFBSSxhQUFhLEdBQUcsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3RELFVBQVUsR0FBRyxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUNELE9BQU8sYUFBYSxHQUFHLGVBQWUsR0FBRyxVQUFVLENBQUM7QUFDdEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge1J1bnRpbWVFcnJvciwgUnVudGltZUVycm9yQ29kZX0gZnJvbSAnLi4vLi4vZXJyb3JzJztcbmltcG9ydCB7V3JpdGFibGV9IGZyb20gJy4uLy4uL2ludGVyZmFjZS90eXBlJztcbmltcG9ydCB7aXNMaXN0TGlrZUl0ZXJhYmxlLCBpdGVyYXRlTGlzdExpa2V9IGZyb20gJy4uLy4uL3V0aWwvaXRlcmFibGUnO1xuaW1wb3J0IHtzdHJpbmdpZnl9IGZyb20gJy4uLy4uL3V0aWwvc3RyaW5naWZ5JztcblxuaW1wb3J0IHtcbiAgSXRlcmFibGVDaGFuZ2VSZWNvcmQsXG4gIEl0ZXJhYmxlQ2hhbmdlcyxcbiAgSXRlcmFibGVEaWZmZXIsXG4gIEl0ZXJhYmxlRGlmZmVyRmFjdG9yeSxcbiAgTmdJdGVyYWJsZSxcbiAgVHJhY2tCeUZ1bmN0aW9uLFxufSBmcm9tICcuL2l0ZXJhYmxlX2RpZmZlcnMnO1xuXG5leHBvcnQgY2xhc3MgRGVmYXVsdEl0ZXJhYmxlRGlmZmVyRmFjdG9yeSBpbXBsZW1lbnRzIEl0ZXJhYmxlRGlmZmVyRmFjdG9yeSB7XG4gIGNvbnN0cnVjdG9yKCkge31cbiAgc3VwcG9ydHMob2JqOiBPYmplY3QgfCBudWxsIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzTGlzdExpa2VJdGVyYWJsZShvYmopO1xuICB9XG5cbiAgY3JlYXRlPFY+KHRyYWNrQnlGbj86IFRyYWNrQnlGdW5jdGlvbjxWPik6IERlZmF1bHRJdGVyYWJsZURpZmZlcjxWPiB7XG4gICAgcmV0dXJuIG5ldyBEZWZhdWx0SXRlcmFibGVEaWZmZXI8Vj4odHJhY2tCeUZuKTtcbiAgfVxufVxuXG5jb25zdCB0cmFja0J5SWRlbnRpdHkgPSAoaW5kZXg6IG51bWJlciwgaXRlbTogYW55KSA9PiBpdGVtO1xuXG4vKipcbiAqIEBkZXByZWNhdGVkIHY0LjAuMCAtIFNob3VsZCBub3QgYmUgcGFydCBvZiBwdWJsaWMgQVBJLlxuICogQHB1YmxpY0FwaVxuICovXG5leHBvcnQgY2xhc3MgRGVmYXVsdEl0ZXJhYmxlRGlmZmVyPFY+IGltcGxlbWVudHMgSXRlcmFibGVEaWZmZXI8Vj4sIEl0ZXJhYmxlQ2hhbmdlczxWPiB7XG4gIHB1YmxpYyByZWFkb25seSBsZW5ndGg6IG51bWJlciA9IDA7XG4gIC8vIFRPRE86IGNvbmZpcm0gdGhlIHVzYWdlIG9mIGBjb2xsZWN0aW9uYCBhcyBpdCdzIHVudXNlZCwgcmVhZG9ubHkgYW5kIG9uIGEgbm9uIHB1YmxpYyBBUEkuXG4gIHB1YmxpYyByZWFkb25seSBjb2xsZWN0aW9uITogVltdIHwgSXRlcmFibGU8Vj4gfCBudWxsO1xuICAvLyBLZWVwcyB0cmFjayBvZiB0aGUgdXNlZCByZWNvcmRzIGF0IGFueSBwb2ludCBpbiB0aW1lIChkdXJpbmcgJiBhY3Jvc3MgYF9jaGVjaygpYCBjYWxscylcbiAgcHJpdmF0ZSBfbGlua2VkUmVjb3JkczogX0R1cGxpY2F0ZU1hcDxWPiB8IG51bGwgPSBudWxsO1xuICAvLyBLZWVwcyB0cmFjayBvZiB0aGUgcmVtb3ZlZCByZWNvcmRzIGF0IGFueSBwb2ludCBpbiB0aW1lIGR1cmluZyBgX2NoZWNrKClgIGNhbGxzLlxuICBwcml2YXRlIF91bmxpbmtlZFJlY29yZHM6IF9EdXBsaWNhdGVNYXA8Vj4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfcHJldmlvdXNJdEhlYWQ6IEl0ZXJhYmxlQ2hhbmdlUmVjb3JkXzxWPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9pdEhlYWQ6IEl0ZXJhYmxlQ2hhbmdlUmVjb3JkXzxWPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9pdFRhaWw6IEl0ZXJhY