@angular/core
Version:
Angular - the core framework
253 lines • 32.1 kB
JavaScript
/**
* @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 { getEnsureDirtyViewsAreAlwaysReachable } from '../../change_detection/flags';
import { RuntimeError } from '../../errors';
import { assertDefined, assertGreaterThan, assertGreaterThanOrEqual, assertIndexInRange, assertLessThan } from '../../util/assert';
import { assertLView, assertTNode, assertTNodeForLView } from '../assert';
import { TYPE } from '../interfaces/container';
import { isLContainer, isLView } from '../interfaces/type_checks';
import { DECLARATION_VIEW, ENVIRONMENT, FLAGS, HEADER_OFFSET, HOST, ON_DESTROY_HOOKS, PARENT, PREORDER_HOOK_FLAGS, REACTIVE_TEMPLATE_CONSUMER } from '../interfaces/view';
/**
* For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
* in same location in `LView`. This is because we don't want to pre-allocate space for it
* because the storage is sparse. This file contains utilities for dealing with such data types.
*
* How do we know what is stored at a given location in `LView`.
* - `Array.isArray(value) === false` => `RNode` (The normal storage value)
* - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
* - `typeof value[TYPE] === 'object'` => `LView`
* - This happens when we have a component at a given location
* - `typeof value[TYPE] === true` => `LContainer`
* - This happens when we have `LContainer` binding at a given location.
*
*
* NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
*/
/**
* Returns `RNode`.
* @param value wrapped value of `RNode`, `LView`, `LContainer`
*/
export function unwrapRNode(value) {
while (Array.isArray(value)) {
value = value[HOST];
}
return value;
}
/**
* Returns `LView` or `null` if not found.
* @param value wrapped value of `RNode`, `LView`, `LContainer`
*/
export function unwrapLView(value) {
while (Array.isArray(value)) {
// This check is same as `isLView()` but we don't call at as we don't want to call
// `Array.isArray()` twice and give JITer more work for inlining.
if (typeof value[TYPE] === 'object')
return value;
value = value[HOST];
}
return null;
}
/**
* Retrieves an element value from the provided `viewData`, by unwrapping
* from any containers, component views, or style contexts.
*/
export function getNativeByIndex(index, lView) {
ngDevMode && assertIndexInRange(lView, index);
ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
return unwrapRNode(lView[index]);
}
/**
* Retrieve an `RNode` for a given `TNode` and `LView`.
*
* This function guarantees in dev mode to retrieve a non-null `RNode`.
*
* @param tNode
* @param lView
*/
export function getNativeByTNode(tNode, lView) {
ngDevMode && assertTNodeForLView(tNode, lView);
ngDevMode && assertIndexInRange(lView, tNode.index);
const node = unwrapRNode(lView[tNode.index]);
return node;
}
/**
* Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
*
* Some `TNode`s don't have associated `RNode`s. For example `Projection`
*
* @param tNode
* @param lView
*/
export function getNativeByTNodeOrNull(tNode, lView) {
const index = tNode === null ? -1 : tNode.index;
if (index !== -1) {
ngDevMode && assertTNodeForLView(tNode, lView);
const node = unwrapRNode(lView[index]);
return node;
}
return null;
}
// fixme(misko): The return Type should be `TNode|null`
export function getTNode(tView, index) {
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
const tNode = tView.data[index];
ngDevMode && tNode !== null && assertTNode(tNode);
return tNode;
}
/** Retrieves a value from any `LView` or `TData`. */
export function load(view, index) {
ngDevMode && assertIndexInRange(view, index);
return view[index];
}
export function getComponentLViewByIndex(nodeIndex, hostView) {
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
ngDevMode && assertIndexInRange(hostView, nodeIndex);
const slotValue = hostView[nodeIndex];
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
return lView;
}
/** Checks whether a given view is in creation mode */
export function isCreationMode(view) {
return (view[FLAGS] & 4 /* LViewFlags.CreationMode */) === 4 /* LViewFlags.CreationMode */;
}
/**
* Returns a boolean for whether the view is attached to the change detection tree.
*
* Note: This determines whether a view should be checked, not whether it's inserted
* into a container. For that, you'll want `viewAttachedToContainer` below.
*/
export function viewAttachedToChangeDetector(view) {
return (view[FLAGS] & 128 /* LViewFlags.Attached */) === 128 /* LViewFlags.Attached */;
}
/** Returns a boolean for whether the view is attached to a container. */
export function viewAttachedToContainer(view) {
return isLContainer(view[PARENT]);
}
export function getConstant(consts, index) {
if (index === null || index === undefined)
return null;
ngDevMode && assertIndexInRange(consts, index);
return consts[index];
}
/**
* Resets the pre-order hook flags of the view.
* @param lView the LView on which the flags are reset
*/
export function resetPreOrderHookFlags(lView) {
lView[PREORDER_HOOK_FLAGS] = 0;
}
/**
* Adds the `RefreshView` flag from the lView and updates HAS_CHILD_VIEWS_TO_REFRESH flag of
* parents.
*/
export function markViewForRefresh(lView) {
if (lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {
return;
}
lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
if (viewAttachedToChangeDetector(lView)) {
markAncestorsForTraversal(lView);
}
}
/**
* Walks up the LView hierarchy.
* @param nestingLevel Number of times to walk up in hierarchy.
* @param currentView View from which to start the lookup.
*/
export function walkUpViews(nestingLevel, currentView) {
while (nestingLevel > 0) {
ngDevMode &&
assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
currentView = currentView[DECLARATION_VIEW];
nestingLevel--;
}
return currentView;
}
export function requiresRefreshOrTraversal(lView) {
return lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */) ||
lView[REACTIVE_TEMPLATE_CONSUMER]?.dirty;
}
/**
* Updates the `HasChildViewsToRefresh` flag on the parents of the `LView` as well as the
* parents above.
*/
export function updateAncestorTraversalFlagsOnAttach(lView) {
// TODO(atscott): Simplify if...else cases once getEnsureDirtyViewsAreAlwaysReachable is always
// `true`. When we attach a view that's marked `Dirty`, we should ensure that it is reached during
// the next CD traversal so we add the `RefreshView` flag and mark ancestors accordingly.
if (requiresRefreshOrTraversal(lView)) {
markAncestorsForTraversal(lView);
}
else if (lView[FLAGS] & 64 /* LViewFlags.Dirty */) {
if (getEnsureDirtyViewsAreAlwaysReachable()) {
lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
markAncestorsForTraversal(lView);
}
else {
lView[ENVIRONMENT].changeDetectionScheduler?.notify();
}
}
}
/**
* Ensures views above the given `lView` are traversed during change detection even when they are
* not dirty.
*
* This is done by setting the `HAS_CHILD_VIEWS_TO_REFRESH` flag up to the root, stopping when the
* flag is already `true` or the `lView` is detached.
*/
export function markAncestorsForTraversal(lView) {
lView[ENVIRONMENT].changeDetectionScheduler?.notify();
let parent = getLViewParent(lView);
while (parent !== null) {
// We stop adding markers to the ancestors once we reach one that already has the marker. This
// is to avoid needlessly traversing all the way to the root when the marker already exists.
if (parent[FLAGS] & 8192 /* LViewFlags.HasChildViewsToRefresh */) {
break;
}
parent[FLAGS] |= 8192 /* LViewFlags.HasChildViewsToRefresh */;
if (!viewAttachedToChangeDetector(parent)) {
break;
}
parent = getLViewParent(parent);
}
}
/**
* Stores a LView-specific destroy callback.
*/
export function storeLViewOnDestroy(lView, onDestroyCallback) {
if ((lView[FLAGS] & 256 /* LViewFlags.Destroyed */) === 256 /* LViewFlags.Destroyed */) {
throw new RuntimeError(911 /* RuntimeErrorCode.VIEW_ALREADY_DESTROYED */, ngDevMode && 'View has already been destroyed.');
}
if (lView[ON_DESTROY_HOOKS] === null) {
lView[ON_DESTROY_HOOKS] = [];
}
lView[ON_DESTROY_HOOKS].push(onDestroyCallback);
}
/**
* Removes previously registered LView-specific destroy callback.
*/
export function removeLViewOnDestroy(lView, onDestroyCallback) {
if (lView[ON_DESTROY_HOOKS] === null)
return;
const destroyCBIdx = lView[ON_DESTROY_HOOKS].indexOf(onDestroyCallback);
if (destroyCBIdx !== -1) {
lView[ON_DESTROY_HOOKS].splice(destroyCBIdx, 1);
}
}
/**
* Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
* that LContainer, which is an LView
* @param lView the lView whose parent to get
*/
export function getLViewParent(lView) {
ngDevMode && assertLView(lView);
const parent = lView[PARENT];
return isLContainer(parent) ? parent[PARENT] : parent;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlld191dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvcmUvc3JjL3JlbmRlcjMvdXRpbC92aWV3X3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBQyxxQ0FBcUMsRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBQ25GLE9BQU8sRUFBQyxZQUFZLEVBQW1CLE1BQU0sY0FBYyxDQUFDO0FBQzVELE9BQU8sRUFBQyxhQUFhLEVBQUUsaUJBQWlCLEVBQUUsd0JBQXdCLEVBQUUsa0JBQWtCLEVBQUUsY0FBYyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDakksT0FBTyxFQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDeEUsT0FBTyxFQUFhLElBQUksRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBR3pELE9BQU8sRUFBQyxZQUFZLEVBQUUsT0FBTyxFQUFDLE1BQU0sMkJBQTJCLENBQUM7QUFDaEUsT0FBTyxFQUFDLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBcUIsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLG1CQUFtQixFQUFxQiwwQkFBMEIsRUFBZSxNQUFNLG9CQUFvQixDQUFDO0FBSTVOOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVIOzs7R0FHRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsS0FBNkI7SUFDdkQsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDNUIsS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQVEsQ0FBQztJQUM3QixDQUFDO0lBQ0QsT0FBTyxLQUFjLENBQUM7QUFDeEIsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsS0FBNkI7SUFDdkQsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDNUIsa0ZBQWtGO1FBQ2xGLGlFQUFpRTtRQUNqRSxJQUFJLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLFFBQVE7WUFBRSxPQUFPLEtBQWMsQ0FBQztRQUMzRCxLQUFLLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBUSxDQUFDO0lBQzdCLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBYSxFQUFFLEtBQVk7SUFDMUQsU0FBUyxJQUFJLGtCQUFrQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM5QyxTQUFTLElBQUksd0JBQXdCLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxtQ0FBbUMsQ0FBQyxDQUFDO0lBQ2pHLE9BQU8sV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ25DLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQVksRUFBRSxLQUFZO0lBQ3pELFNBQVMsSUFBSSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0MsU0FBUyxJQUFJLGtCQUFrQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEQsTUFBTSxJQUFJLEdBQVUsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNwRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUFDLEtBQWlCLEVBQUUsS0FBWTtJQUNwRSxNQUFNLEtBQUssR0FBRyxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztJQUNoRCxJQUFJLEtBQUssS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2pCLFNBQVMsSUFBSSxtQkFBbUIsQ0FBQyxLQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDaEQsTUFBTSxJQUFJLEdBQWUsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ25ELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUdELHVEQUF1RDtBQUN2RCxNQUFNLFVBQVUsUUFBUSxDQUFDLEtBQVksRUFBRSxLQUFhO0lBQ2xELFNBQVMsSUFBSSxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztJQUNuRSxTQUFTLElBQUksY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO0lBQy9FLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFVLENBQUM7SUFDekMsU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELHFEQUFxRDtBQUNyRCxNQUFNLFVBQVUsSUFBSSxDQUFJLElBQWlCLEVBQUUsS0FBYTtJQUN0RCxTQUFTLElBQUksa0JBQWtCLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzdDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3JCLENBQUM7QUFFRCxNQUFNLFVBQVUsd0JBQXdCLENBQUMsU0FBaUIsRUFBRSxRQUFlO0lBQ3pFLDJFQUEyRTtJQUMzRSxTQUFTLElBQUksa0JBQWtCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3JELE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN0QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9ELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVELHNEQUFzRDtBQUN0RCxNQUFNLFVBQVUsY0FBYyxDQUFDLElBQVc7SUFDeEMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsa0NBQTBCLENBQUMsb0NBQTRCLENBQUM7QUFDN0UsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLDRCQUE0QixDQUFDLElBQVc7SUFDdEQsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsZ0NBQXNCLENBQUMsa0NBQXdCLENBQUM7QUFDckUsQ0FBQztBQUVELHlFQUF5RTtBQUN6RSxNQUFNLFVBQVUsdUJBQXVCLENBQUMsSUFBVztJQUNqRCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBTUQsTUFBTSxVQUFVLFdBQVcsQ0FBSSxNQUF1QixFQUFFLEtBQTRCO0lBQ2xGLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3ZELFNBQVMsSUFBSSxrQkFBa0IsQ0FBQyxNQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEQsT0FBTyxNQUFPLENBQUMsS0FBSyxDQUFpQixDQUFDO0FBQ3hDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsc0JBQXNCLENBQUMsS0FBWTtJQUNqRCxLQUFLLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFzQixDQUFDO0FBQ3RELENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsS0FBWTtJQUM3QyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsb0NBQXlCLEVBQUUsQ0FBQztRQUMxQyxPQUFPO0lBQ1QsQ0FBQztJQUNELEtBQUssQ0FBQyxLQUFLLENBQUMscUNBQTBCLENBQUM7SUFDdkMsSUFBSSw0QkFBNEIsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3hDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25DLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsWUFBb0IsRUFBRSxXQUFrQjtJQUNsRSxPQUFPLFlBQVksR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN4QixTQUFTO1lBQ0wsYUFBYSxDQUNULFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUM3Qix3RUFBd0UsQ0FBQyxDQUFDO1FBQ2xGLFdBQVcsR0FBRyxXQUFXLENBQUMsZ0JBQWdCLENBQUUsQ0FBQztRQUM3QyxZQUFZLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBQ0QsT0FBTyxXQUFXLENBQUM7QUFDckIsQ0FBQztBQUVELE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxLQUFZO0lBQ3JELE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsZ0ZBQTBELENBQUM7UUFDOUUsS0FBSyxDQUFDLDBCQUEwQixDQUFDLEVBQUUsS0FBSyxDQUFDO0FBQy9DLENBQUM7QUFHRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsb0NBQW9DLENBQUMsS0FBWTtJQUMvRCwrRkFBK0Y7SUFDL0Ysa0dBQWtHO0lBQ2xHLHlGQUF5RjtJQUN6RixJQUFJLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdEMseUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQztTQUFNLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyw0QkFBbUIsRUFBRSxDQUFDO1FBQzNDLElBQUkscUNBQXFDLEVBQUUsRUFBRSxDQUFDO1lBQzVDLEtBQUssQ0FBQyxLQUFLLENBQUMscUNBQTBCLENBQUM7WUFDdkMseUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkMsQ0FBQzthQUFNLENBQUM7WUFDTixLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsd0JBQXdCLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDeEQsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLHlCQUF5QixDQUFDLEtBQVk7SUFDcEQsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLHdCQUF3QixFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQ3RELElBQUksTUFBTSxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuQyxPQUFPLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUN2Qiw4RkFBOEY7UUFDOUYsNEZBQTRGO1FBQzVGLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQywrQ0FBb0MsRUFBRSxDQUFDO1lBQ3RELE1BQU07UUFDUixDQUFDO1FBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxnREFBcUMsQ0FBQztRQUNuRCxJQUFJLENBQUMsNEJBQTRCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUMxQyxNQUFNO1FBQ1IsQ0FBQztRQUNELE1BQU0sR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsQ0FBQztBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxLQUFZLEVBQUUsaUJBQTZCO0lBQzdFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGlDQUF1QixDQUFDLG1DQUF5QixFQUFFLENBQUM7UUFDbkUsTUFBTSxJQUFJLFlBQVksb0RBQ3VCLFNBQVMsSUFBSSxrQ0FBa0MsQ0FBQyxDQUFDO0lBQ2hHLENBQUM7SUFDRCxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ3JDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBQ0QsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEtBQVksRUFBRSxpQkFBNkI7SUFDOUUsSUFBSSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxJQUFJO1FBQUUsT0FBTztJQUU3QyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUN4RSxJQUFJLFlBQVksS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3hCLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFZO0lBQ3pDLFNBQVMsSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdCLE9BQU8sWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUN4RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7Z2V0RW5zdXJlRGlydHlWaWV3c0FyZUFsd2F5c1JlYWNoYWJsZX0gZnJvbSAnLi4vLi4vY2hhbmdlX2RldGVjdGlvbi9mbGFncyc7XG5pbXBvcnQge1J1bnRpbWVFcnJvciwgUnVudGltZUVycm9yQ29kZX0gZnJvbSAnLi4vLi4vZXJyb3JzJztcbmltcG9ydCB7YXNzZXJ0RGVmaW5lZCwgYXNzZXJ0R3JlYXRlclRoYW4sIGFzc2VydEdyZWF0ZXJUaGFuT3JFcXVhbCwgYXNzZXJ0SW5kZXhJblJhbmdlLCBhc3NlcnRMZXNzVGhhbn0gZnJvbSAnLi4vLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHthc3NlcnRMVmlldywgYXNzZXJ0VE5vZGUsIGFzc2VydFROb2RlRm9yTFZpZXd9IGZyb20gJy4uL2Fzc2VydCc7XG5pbXBvcnQge0xDb250YWluZXIsIFRZUEV9IGZyb20gJy4uL2ludGVyZmFjZXMvY29udGFpbmVyJztcbmltcG9ydCB7VENvbnN0YW50cywgVE5vZGV9IGZyb20gJy4uL2ludGVyZmFjZXMvbm9kZSc7XG5pbXBvcnQge1JOb2RlfSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlbmRlcmVyX2RvbSc7XG5pbXBvcnQge2lzTENvbnRhaW5lciwgaXNMVmlld30gZnJvbSAnLi4vaW50ZXJmYWNlcy90eXBlX2NoZWNrcyc7XG5pbXBvcnQge0RFQ0xBUkFUSU9OX1ZJRVcsIEVOVklST05NRU5ULCBGTEFHUywgSEVBREVSX09GRlNFVCwgSE9TVCwgTFZpZXcsIExWaWV3RmxhZ3MsIE9OX0RFU1RST1lfSE9PS1MsIFBBUkVOVCwgUFJFT1JERVJfSE9PS19GTEFHUywgUHJlT3JkZXJIb29rRmxhZ3MsIFJFQUNUSVZFX1RFTVBMQVRFX0NPTlNVTUVSLCBURGF0YSwgVFZpZXd9IGZyb20gJy4uL2ludGVyZmFjZXMvdmlldyc7XG5cblxuXG4vKipcbiAqIEZvciBlZmZpY2llbmN5IHJlYXNvbnMgd2Ugb2Z0ZW4gcHV0IHNldmVyYWwgZGlmZmVyZW50IGRhdGEgdHlwZXMgKGBSTm9kZWAsIGBMVmlld2AsIGBMQ29udGFpbmVyYClcbiAqIGluIHNhbWUgbG9jYXRpb24gaW4gYExWaWV3YC4gVGhpcyBpcyBiZWNhdXNlIHdlIGRvbid0IHdhbnQgdG8gcHJlLWFsbG9jYXRlIHNwYWNlIGZvciBpdFxuICogYmVjYXVzZSB0aGUgc3RvcmFnZSBpcyBzcGFyc2UuIFRoaXMgZmlsZSBjb250YWlucyB1dGlsaXRpZXMgZm9yIGRlYWxpbmcgd2l0aCBzdWNoIGRhdGEgdHlwZXMuXG4gKlxuICogSG93IGRvIHdlIGtub3cgd2hhdCBpcyBzdG9yZWQgYXQgYSBnaXZlbiBsb2NhdGlvbiBpbiBgTFZpZXdgLlxuICogLSBgQXJyYXkuaXNBcnJheSh2YWx1ZSkgPT09IGZhbHNlYCA9PiBgUk5vZGVgIChUaGUgbm9ybWFsIHN0b3JhZ2UgdmFsdWUpXG4gKiAtIGBBcnJheS5pc0FycmF5KHZhbHVlKSA9PT0gdHJ1ZWAgPT4gdGhlbiB0aGUgYHZhbHVlWzBdYCByZXByZXNlbnRzIHRoZSB3cmFwcGVkIHZhbHVlLlxuICogICAtIGB0eXBlb2YgdmFsdWVbVFlQRV0gPT09ICdvYmplY3QnYCA9PiBgTFZpZXdgXG4gKiAgICAgIC0gVGhpcyBoYXBwZW5zIHdoZW4gd2UgaGF2ZSBhIGNvbXBvbmVudCBhdCBhIGdpdmVuIGxvY2F0aW9uXG4gKiAgIC0gYHR5cGVvZiB2YWx1ZVtUWVBFXSA9PT0gdHJ1ZWAgPT4gYExDb250YWluZXJgXG4gKiAgICAgIC0gVGhpcyBoYXBwZW5zIHdoZW4gd2UgaGF2ZSBgTENvbnRhaW5lcmAgYmluZGluZyBhdCBhIGdpdmVuIGxvY2F0aW9uLlxuICpcbiAqXG4gKiBOT1RFOiBpdCBpcyBhc3N1bWVkIHRoYXQgYEFycmF5LmlzQXJyYXlgIGFuZCBgdHlwZW9mYCBvcGVyYXRpb25zIGFyZSB2ZXJ5IGVmZmljaWVudC5cbiAqL1xuXG4vKipcbiAqIFJldHVybnMgYFJOb2RlYC5cbiAqIEBwYXJhbSB2YWx1ZSB3cmFwcGVkIHZhbHVlIG9mIGBSTm9kZWAsIGBMVmlld2AsIGBMQ29udGFpbmVyYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdW53cmFwUk5vZGUodmFsdWU6IFJOb2RlfExWaWV3fExDb250YWluZXIpOiBSTm9kZSB7XG4gIHdoaWxlIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHZhbHVlID0gdmFsdWVbSE9TVF0gYXMgYW55O1xuICB9XG4gIHJldHVybiB2YWx1ZSBhcyBSTm9kZTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGBMVmlld2Agb3IgYG51bGxgIGlmIG5vdCBmb3VuZC5cbiAqIEBwYXJhbSB2YWx1ZSB3cmFwcGVkIHZhbHVlIG9mIGBSTm9kZWAsIGBMVmlld2AsIGBMQ29udGFpbmVyYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdW53cmFwTFZpZXcodmFsdWU6IFJOb2RlfExWaWV3fExDb250YWluZXIpOiBMVmlld3xudWxsIHtcbiAgd2hpbGUgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgLy8gVGhpcyBjaGVjayBpcyBzYW1lIGFzIGBpc0xWaWV3KClgIGJ1dCB3ZSBkb24ndCBjYWxsIGF0IGFzIHdlIGRvbid0IHdhbnQgdG8gY2FsbFxuICAgIC8vIGBBcnJheS5pc0FycmF5KClgIHR3aWNlIGFuZCBnaXZlIEpJVGVyIG1vcmUgd29yayBmb3IgaW5saW5pbmcuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZVtUWVBFXSA9PT0gJ29iamVjdCcpIHJldHVybiB2YWx1ZSBhcyBMVmlldztcbiAgICB2YWx1ZSA9IHZhbHVlW0hPU1RdIGFzIGFueTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgYW4gZWxlbWVudCB2YWx1ZSBmcm9tIHRoZSBwcm92aWRlZCBgdmlld0RhdGFgLCBieSB1bndyYXBwaW5nXG4gKiBmcm9tIGFueSBjb250YWluZXJzLCBjb21wb25lbnQgdmlld3MsIG9yIHN0eWxlIGNvbnRleHRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TmF0aXZlQnlJbmRleChpbmRleDogbnVtYmVyLCBsVmlldzogTFZpZXcpOiBSTm9kZSB7XG4gIG5nRGV2TW9kZSAmJiBhc3NlcnRJbmRleEluUmFuZ2UobFZpZXcsIGluZGV4KTtcbiAgbmdEZXZNb2RlICYmIGFzc2VydEdyZWF0ZXJUaGFuT3JFcXVhbChpbmRleCwgSEVBREVSX09GRlNFVCwgJ0V4cGVjdGVkIHRvIGJlIHBhc3QgSEVBREVSX09GRlNFVCcpO1xuICByZXR1cm4gdW53cmFwUk5vZGUobFZpZXdbaW5kZXhdKTtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZSBhbiBgUk5vZGVgIGZvciBhIGdpdmVuIGBUTm9kZWAgYW5kIGBMVmlld2AuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBndWFyYW50ZWVzIGluIGRldiBtb2RlIHRvIHJldHJpZXZlIGEgbm9uLW51bGwgYFJOb2RlYC5cbiAqXG4gKiBAcGFyYW0gdE5vZGVcbiAqIEBwYXJhbSBsVmlld1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TmF0aXZlQnlUTm9kZSh0Tm9kZTogVE5vZGUsIGxWaWV3OiBMVmlldyk6IFJOb2RlIHtcbiAgbmdEZXZNb2RlICYmIGFzc2VydFROb2RlRm9yTFZpZXcodE5vZGUsIGxWaWV3KTtcbiAgbmdEZXZNb2RlICYmIGFzc2VydEluZGV4SW5SYW5nZShsVmlldywgdE5vZGUuaW5kZXgpO1xuICBjb25zdCBub2RlOiBSTm9kZSA9IHVud3JhcFJOb2RlKGxWaWV3W3ROb2RlLmluZGV4XSk7XG4gIHJldHVybiBub2RlO1xufVxuXG4vKipcbiAqIFJldHJpZXZlIGFuIGBSTm9kZWAgb3IgYG51bGxgIGZvciBhIGdpdmVuIGBUTm9kZWAgYW5kIGBMVmlld2AuXG4gKlxuICogU29tZSBgVE5vZGVgcyBkb24ndCBoYXZlIGFzc29jaWF0ZWQgYFJOb2RlYHMuIEZvciBleGFtcGxlIGBQcm9qZWN0aW9uYFxuICpcbiAqIEBwYXJhbSB0Tm9kZVxuICogQHBhcmFtIGxWaWV3XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXROYXRpdmVCeVROb2RlT3JOdWxsKHROb2RlOiBUTm9kZXxudWxsLCBsVmlldzogTFZpZXcpOiBSTm9kZXxudWxsIHtcbiAgY29uc3QgaW5kZXggPSB0Tm9kZSA9PT0gbnVsbCA/IC0xIDogdE5vZGUuaW5kZXg7XG4gIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICBuZ0Rldk1vZGUgJiYgYXNzZXJ0VE5vZGVGb3JMVmlldyh0Tm9kZSEsIGxWaWV3KTtcbiAgICBjb25zdCBub2RlOiBSTm9kZXxudWxsID0gdW53cmFwUk5vZGUobFZpZXdbaW5kZXhdKTtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuXG4vLyBmaXhtZShtaXNrbyk6IFRoZSByZXR1cm4gVHlwZSBzaG91bGQgYmUgYFROb2RlfG51bGxgXG5leHBvcnQgZnVuY3Rpb24gZ2V0VE5vZGUodFZpZXc6IFRWaWV3LCBpbmRleDogbnVtYmVyKTogVE5vZGUge1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0R3JlYXRlclRoYW4oaW5kZXgsIC0xLCAnd3JvbmcgaW5kZXggZm9yIFROb2RlJyk7XG4gIG5nRGV2TW9kZSAmJiBhc3NlcnRMZXNzVGhhbihpbmRleCwgdFZpZXcuZGF0YS5sZW5ndGgsICd3cm9uZyBpbmRleCBmb3IgVE5vZGUnKTtcbiAgY29uc3QgdE5vZGUgPSB0Vmlldy5kYXRhW2luZGV4XSBhcyBUTm9kZTtcbiAgbmdEZXZNb2RlICYmIHROb2RlICE9PSBudWxsICYmIGFzc2VydFROb2RlKHROb2RlKTtcbiAgcmV0dXJuIHROb2RlO1xufVxuXG4vKiogUmV0cmlldmVzIGEgdmFsdWUgZnJvbSBhbnkgYExWaWV3YCBvciBgVERhdGFgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvYWQ8VD4odmlldzogTFZpZXd8VERhdGEsIGluZGV4OiBudW1iZXIpOiBUIHtcbiAgbmdEZXZNb2RlICYmIGFzc2VydEluZGV4SW5SYW5nZSh2aWV3LCBpbmRleCk7XG4gIHJldHVybiB2aWV3W2luZGV4XTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbXBvbmVudExWaWV3QnlJbmRleChub2RlSW5kZXg6IG51bWJlciwgaG9zdFZpZXc6IExWaWV3KTogTFZpZXcge1xuICAvLyBDb3VsZCBiZSBhbiBMVmlldyBvciBhbiBMQ29udGFpbmVyLiBJZiBMQ29udGFpbmVyLCB1bndyYXAgdG8gZmluZCBMVmlldy5cbiAgbmdEZXZNb2RlICYmIGFzc2VydEluZGV4SW5SYW5nZShob3N0Vmlldywgbm9kZUluZGV4KTtcbiAgY29uc3Qgc2xvdFZhbHVlID0gaG9zdFZpZXdbbm9kZUluZGV4XTtcbiAgY29uc3QgbFZpZXcgPSBpc0xWaWV3KHNsb3RWYWx1ZSkgPyBzbG90VmFsdWUgOiBzbG90VmFsdWVbSE9TVF07XG4gIHJldHVybiBsVmlldztcbn1cblxuLyoqIENoZWNrcyB3aGV0aGVyIGEgZ2l2ZW4gdmlldyBpcyBpbiBjcmVhdGlvbiBtb2RlICovXG5leHBvcnQgZnVuY3Rpb24gaXNDcmVhdGlvbk1vZGUodmlldzogTFZpZXcpOiBib29sZWFuIHtcbiAgcmV0dXJuICh2aWV3W0ZMQUdTXSAmIExWaWV3RmxhZ3MuQ3JlYXRpb25Nb2RlKSA9PT0gTFZpZXdGbGFncy5DcmVhdGlvbk1vZGU7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGJvb2xlYW4gZm9yIHdoZXRoZXIgdGhlIHZpZXcgaXMgYXR0YWNoZWQgdG8gdGhlIGNoYW5nZSBkZXRlY3Rpb24gdHJlZS5cbiAqXG4gKiBOb3RlOiBUaGlzIGRldGVybWluZXMgd2hldGhlciBhIHZpZXcgc2hvdWxkIGJlIGNoZWNrZWQsIG5vdCB3aGV0aGVyIGl0J3MgaW5zZXJ0ZWRcbiAqIGludG8gYSBjb250YWluZXIuIEZvciB0aGF0LCB5b3UnbGwgd2FudCBgdmlld0F0dGFjaGVkVG9Db250YWluZXJgIGJlbG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlld0F0dGFjaGVkVG9DaGFuZ2VEZXRlY3Rvcih2aWV3OiBMVmlldyk6IGJvb2xlYW4ge1xuICByZXR1cm4gKHZpZXdbRkxBR1NdICYgTFZpZXdGbGFncy5BdHRhY2hlZCkgPT09IExWaWV3RmxhZ3MuQXR0YWNoZWQ7XG59XG5cbi8qKiBSZXR1cm5zIGEgYm9vbGVhbiBmb3Igd2hldGhlciB0aGUgdmlldyBpcyBhdHRhY2hlZCB0byBhIGNvbnRhaW5lci4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2aWV3QXR0YWNoZWRUb0NvbnRhaW5lcih2aWV3OiBMVmlldyk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNMQ29udGFpbmVyKHZpZXdbUEFSRU5UXSk7XG59XG5cbi8qKiBSZXR1cm5zIGEgY29uc3RhbnQgZnJvbSBgVENvbnN0YW50c2AgaW5zdGFuY2UuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29uc3RhbnQ8VD4oY29uc3RzOiBUQ29uc3RhbnRzfG51bGwsIGluZGV4OiBudWxsfHVuZGVmaW5lZCk6IG51bGw7XG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29uc3RhbnQ8VD4oY29uc3RzOiBUQ29uc3RhbnRzLCBpbmRleDogbnVtYmVyKTogVHxudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbnN0YW50PFQ+KGNvbnN0czogVENvbnN0YW50c3xudWxsLCBpbmRleDogbnVtYmVyfG51bGx8dW5kZWZpbmVkKTogVHxudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbnN0YW50PFQ+KGNvbnN0czogVENvbnN0YW50c3xudWxsLCBpbmRleDogbnVtYmVyfG51bGx8dW5kZWZpbmVkKTogVHxudWxsIHtcbiAgaWYgKGluZGV4ID09PSBudWxsIHx8IGluZGV4ID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsO1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0SW5kZXhJblJhbmdlKGNvbnN0cyEsIGluZGV4KTtcbiAgcmV0dXJuIGNvbnN0cyFbaW5kZXhdIGFzIHVua25vd24gYXMgVDtcbn1cblxuLyoqXG4gKiBSZXNldHMgdGhlIHByZS1vcmRlciBob29rIGZsYWdzIG9mIHRoZSB2aWV3LlxuICogQHBhcmFtIGxWaWV3IHRoZSBMVmlldyBvbiB3aGljaCB0aGUgZmxhZ3MgYXJlIHJlc2V0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNldFByZU9yZGVySG9va0ZsYWdzKGxWaWV3OiBMVmlldykge1xuICBsVmlld1tQUkVPUkRFUl9IT09LX0ZMQUdTXSA9IDAgYXMgUHJlT3JkZXJIb29rRmxhZ3M7XG59XG5cbi8qKlxuICogQWRkcyB0aGUgYFJlZnJlc2hWaWV3YCBmbGFnIGZyb20gdGhlIGxWaWV3IGFuZCB1cGRhdGVzIEhBU19DSElMRF9WSUVXU19UT19SRUZSRVNIIGZsYWcgb2ZcbiAqIHBhcmVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXJrVmlld0ZvclJlZnJlc2gobFZpZXc6IExWaWV3KSB7XG4gIGlmIChsVmlld1tGTEFHU10gJiBMVmlld0ZsYWdzLlJlZnJlc2hWaWV3KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGxWaWV3W0ZMQUdTXSB8PSBMVmlld0ZsYWdzLlJlZnJlc2hWaWV3O1xuICBpZiAodmlld0F0dGFjaGVkVG9DaGFuZ2VEZXRlY3RvcihsVmlldykpIHtcbiAgICBtYXJrQW5jZXN0b3JzRm9yVHJhdmVyc2FsKGxWaWV3KTtcbiAgfVxufVxuXG4vKipcbiAqIFdhbGtzIHVwIHRoZSBMVmlldyBoaWVyYXJjaHkuXG4gKiBAcGFyYW0gbmVzdGluZ0xldmVsIE51bWJlciBvZiB0aW1lcyB0byB3YWxrIHVwIGluIGhpZXJhcmNoeS5cbiAqIEBwYXJhbSBjdXJyZW50VmlldyBWaWV3IGZyb20gd2hpY2ggdG8gc3RhcnQgdGhlIGxvb2t1cC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhbGtVcFZpZXdzKG5lc3RpbmdMZXZlbDogbnVtYmVyLCBjdXJyZW50VmlldzogTFZpZXcpOiBMVmlldyB7XG4gIHdoaWxlIChuZXN0aW5nTGV2ZWwgPiAwKSB7XG4gICAgbmdEZXZNb2RlICYmXG4gICAgICAgIGFzc2VydERlZmluZWQoXG4gICAgICAgICAgICBjdXJyZW50Vmlld1tERUNMQVJBVElPTl9WSUVXXSxcbiAgICAgICAgICAgICdEZWNsYXJhdGlvbiB2aWV3IHNob3VsZCBiZSBkZWZpbmVkIGlmIG5lc3RpbmcgbGV2ZWwgaXMgZ3JlYXRlciB0aGFuIDAuJyk7XG4gICAgY3VycmVudFZpZXcgPSBjdXJyZW50Vmlld1tERUNMQVJBVElPTl9WSUVXXSE7XG4gICAgbmVzdGluZ0xldmVsLS07XG4gIH1cbiAgcmV0dXJuIGN1cnJlbnRWaWV3O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZXNSZWZyZXNoT3JUcmF2ZXJzYWwobFZpZXc6IExWaWV3KSB7XG4gIHJldHVybiBsVmlld1tGTEFHU10gJiAoTFZpZXdGbGFncy5SZWZyZXNoVmlldyB8IExWaWV3RmxhZ3MuSGFzQ2hpbGRWaWV3c1RvUmVmcmVzaCkgfHxcbiAgICAgIGxWaWV3W1JFQUNUSVZFX1RFTVBMQVRFX0NPTlNVTUVSXT8uZGlydHk7XG59XG5cblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBgSGFzQ2hpbGRWaWV3c1RvUmVmcmVzaGAgZmxhZyBvbiB0aGUgcGFyZW50cyBvZiB0aGUgYExWaWV3YCBhcyB3ZWxsIGFzIHRoZVxuICogcGFyZW50cyBhYm92ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUFuY2VzdG9yVHJhdmVyc2FsRmxhZ3NPbkF0dGFjaChsVmlldzogTFZpZXcpIHtcbiAgLy8gVE9ETyhhdHNjb3R0KTogU2ltcGxpZnkgaWYuLi5lbHNlIGNhc2VzIG9uY2UgZ2V0RW5zdXJlRGlydHlWaWV3c0FyZUFsd2F5c1JlYWNoYWJsZSBpcyBhbHdheXNcbiAgLy8gYHRydWVgLiBXaGVuIHdlIGF0dGFjaCBhIHZpZXcgdGhhdCdzIG1hcmtlZCBgRGlydHlgLCB3ZSBzaG91bGQgZW5zdXJlIHRoYXQgaXQgaXMgcmVhY2hlZCBkdXJpbmdcbiAgLy8gdGhlIG5leHQgQ0QgdHJhdmVyc2FsIHNvIHdlIGFkZCB0aGUgYFJlZnJlc2hWaWV3YCBmbGFnIGFuZCBtYXJrIGFuY2VzdG9ycyBhY2NvcmRpbmdseS5cbiAgaWYgKHJlcXVpcmVzUmVmcmVzaE9yVHJhdmVyc2FsKGxWaWV3KSkge1xuICAgIG1hcmtBbmNlc3RvcnNGb3JUcmF2ZXJzYWwobFZpZXcpO1xuICB9IGVsc2UgaWYgKGxWaWV3W0ZMQUdTXSAmIExWaWV3RmxhZ3MuRGlydHkpIHtcbiAgICBpZiAoZ2V0RW5zdXJlRGlydHlWaWV3c0FyZUFsd2F5c1JlYWNoYWJsZSgpKSB7XG4gICAgICBsVmlld1tGTEFHU10gfD0gTFZpZXdGbGFncy5SZWZyZXNoVmlldztcbiAgICAgIG1hcmtBbmNlc3RvcnNGb3JUcmF2ZXJzYWwobFZpZXcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsVmlld1tFTlZJUk9OTUVOVF0uY2hhbmdlRGV0ZWN0aW9uU2NoZWR1bGVyPy5ub3RpZnkoKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBFbnN1cmVzIHZpZXdzIGFib3ZlIHRoZSBnaXZlbiBgbFZpZXdgIGFyZSB0cmF2ZXJzZWQgZHVyaW5nIGNoYW5nZSBkZXRlY3Rpb24gZXZlbiB3aGVuIHRoZXkgYXJlXG4gKiBub3QgZGlydHkuXG4gKlxuICogVGhpcyBpcyBkb25lIGJ5IHNldHRpbmcgdGhlIGBIQVNfQ0hJTERfVklFV1NfVE9fUkVGUkVTSGAgZmxhZyB1cCB0byB0aGUgcm9vdCwgc3RvcHBpbmcgd2hlbiB0aGVcbiAqIGZsYWcgaXMgYWxyZWFkeSBgdHJ1ZWAgb3IgdGhlIGBsVmlld2AgaXMgZGV0YWNoZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXJrQW5jZXN0b3JzRm9yVHJhdmVyc2FsKGxWaWV3OiBMVmlldykge1xuICBsVmlld1tFTlZJUk9OTUVOVF0uY2hhbmdlRGV0ZWN0aW9uU2NoZWR1bGVyPy5ub3RpZnkoKTtcbiAgbGV0IHBhcmVudCA9IGdldExWaWV3UGFyZW50KGxWaWV3KTtcbiAgd2hpbGUgKHBhcmVudCAhPT0gbnVsbCkge1xuICAgIC8vIFdlIHN0b3AgYWRkaW5nIG1hcmtlcnMgdG8gdGhlIGFuY2VzdG9ycyBvbmNlIHdlIHJlYWNoIG9uZSB0aGF0IGFscmVhZHkgaGFzIHRoZSBtYXJrZXIuIFRoaXNcbiAgICAvLyBpcyB0byBhdm9pZCBuZWVkbGVzc2x5IHRyYXZlcnNpbmcgYWxsIHRoZSB3YXkgdG8gdGhlIHJvb3Qgd2hlbiB0aGUgbWFya2VyIGFscmVhZHkgZXhpc3RzLlxuICAgIGlmIChwYXJlbnRbRkxBR1NdICYgTFZpZXdGbGFncy5IYXNDaGlsZFZpZXdzVG9SZWZyZXNoKSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBwYXJlbnRbRkxBR1NdIHw9IExWaWV3RmxhZ3MuSGFzQ2hpbGRWaWV3c1RvUmVmcmVzaDtcbiAgICBpZiAoIXZpZXdBdHRhY2hlZFRvQ2hhbmdlRGV0ZWN0b3IocGFyZW50KSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHBhcmVudCA9IGdldExWaWV3UGFyZW50KHBhcmVudCk7XG4gIH1cbn1cblxuLyoqXG4gKiBTdG9yZXMgYSBMVmlldy1zcGVjaWZpYyBkZXN0cm95IGNhbGxiYWNrLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RvcmVMVmlld09uRGVzdHJveShsVmlldzogTFZpZXcsIG9uRGVzdHJveUNhbGxiYWNrOiAoKSA9PiB2b2lkKSB7XG4gIGlmICgobFZpZXdbRkxBR1NdICYgTFZpZXdGbGFncy5EZXN0cm95ZWQpID09PSBMVmlld0ZsYWdzLkRlc3Ryb3llZCkge1xuICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgICAgIFJ1bnRpbWVFcnJvckNvZGUuVklFV19BTFJFQURZX0RFU1RST1lFRCwgbmdEZXZNb2RlICYmICdWaWV3IGhhcyBhbHJlYWR5IGJlZW4gZGVzdHJveWVkLicpO1xuICB9XG4gIGlmIChsVmlld1tPTl9ERVNUUk9ZX0hPT0tTXSA9PT0gbnVsbCkge1xuICAgIGxWaWV3W09OX0RFU1RST1lfSE9PS1NdID0gW107XG4gIH1cbiAgbFZpZXdbT05fREVTVFJPWV9IT09LU10ucHVzaChvbkRlc3Ryb3lDYWxsYmFjayk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgTFZpZXctc3BlY2lmaWMgZGVzdHJveSBjYWxsYmFjay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUxWaWV3T25EZXN0cm95KGxWaWV3OiBMVmlldywgb25EZXN0cm95Q2FsbGJhY2s6ICgpID0+IHZvaWQpIHtcbiAgaWYgKGxWaWV3W09OX0RFU1RST1lfSE9PS1NdID09PSBudWxsKSByZXR1cm47XG5cbiAgY29uc3QgZGVzdHJveUNCSWR4ID0gbFZpZXdbT05fREVTVFJPWV9IT09LU10uaW5kZXhPZihvbkRlc3Ryb3lDYWxsYmFjayk7XG4gIGlmIChkZXN0cm95Q0JJZHggIT09IC0xKSB7XG4gICAgbFZpZXdbT05fREVTVFJPWV9IT09LU10uc3BsaWNlKGRlc3Ryb3lDQklkeCwgMSk7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBwYXJlbnQgTFZpZXcgb2YgdGhlIHBhc3NlZCBMVmlldywgaWYgdGhlIFBBUkVOVCBpcyBhbiBMQ29udGFpbmVyLCB3aWxsIGdldCB0aGUgcGFyZW50IG9mXG4gKiB0aGF0IExDb250YWluZXIsIHdoaWNoIGlzIGFuIExWaWV3XG4gKiBAcGFyYW0gbFZpZXcgdGhlIGxWaWV3IHdob3NlIHBhcmVudCB0byBnZXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldExWaWV3UGFyZW50KGxWaWV3OiBMVmlldyk6IExWaWV3fG51bGwge1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0TFZpZXcobFZpZXcpO1xuICBjb25zdCBwYXJlbnQgPSBsVmlld1tQQVJFTlRdO1xuICByZXR1cm4gaXNMQ29udGFpbmVyKHBhcmVudCkgPyBwYXJlbnRbUEFSRU5UXSA6IHBhcmVudDtcbn1cbiJdfQ==