@angular/core
Version:
Angular - the core framework
263 lines • 42.2 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 { resolveForwardRef } from '../di/forward_ref';
import { isClassProvider, isTypeProvider } from '../di/provider_collection';
import { providerToFactory } from '../di/r3_injector';
import { assertDefined } from '../util/assert';
import { emitProviderConfiguredEvent, runInInjectorProfilerContext } from './debug/injector_profiler';
import { diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode, NodeInjector } from './di';
import { ɵɵdirectiveInject } from './instructions/all';
import { NodeInjectorFactory } from './interfaces/injector';
import { isComponentDef } from './interfaces/type_checks';
import { TVIEW } from './interfaces/view';
import { getCurrentTNode, getLView, getTView } from './state';
/**
* Resolves the providers which are defined in the DirectiveDef.
*
* When inserting the tokens and the factories in their respective arrays, we can assume that
* this method is called first for the component (if any), and then for other directives on the same
* node.
* As a consequence,the providers are always processed in that order:
* 1) The view providers of the component
* 2) The providers of the component
* 3) The providers of the other directives
* This matches the structure of the injectables arrays of a view (for each node).
* So the tokens and the factories can be pushed at the end of the arrays, except
* in one case for multi providers.
*
* @param def the directive definition
* @param providers: Array of `providers`.
* @param viewProviders: Array of `viewProviders`.
*/
export function providersResolver(def, providers, viewProviders) {
const tView = getTView();
if (tView.firstCreatePass) {
const isComponent = isComponentDef(def);
// The list of view providers is processed first, and the flags are updated
resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true);
// Then, the list of providers is processed, and the flags are updated
resolveProvider(providers, tView.data, tView.blueprint, isComponent, false);
}
}
/**
* Resolves a provider and publishes it to the DI system.
*/
function resolveProvider(provider, tInjectables, lInjectablesBlueprint, isComponent, isViewProvider) {
provider = resolveForwardRef(provider);
if (Array.isArray(provider)) {
// Recursively call `resolveProvider`
// Recursion is OK in this case because this code will not be in hot-path once we implement
// cloning of the initial state.
for (let i = 0; i < provider.length; i++) {
resolveProvider(provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
}
}
else {
const tView = getTView();
const lView = getLView();
const tNode = getCurrentTNode();
let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
const providerFactory = providerToFactory(provider);
if (ngDevMode) {
const injector = new NodeInjector(tNode, lView);
runInInjectorProfilerContext(injector, token, () => {
emitProviderConfiguredEvent(provider, isViewProvider);
});
}
const beginIndex = tNode.providerIndexes & 1048575 /* TNodeProviderIndexes.ProvidersStartIndexMask */;
const endIndex = tNode.directiveStart;
const cptViewProvidersCount = tNode.providerIndexes >> 20 /* TNodeProviderIndexes.CptViewProvidersCountShift */;
if (isTypeProvider(provider) || !provider.multi) {
// Single provider case: the factory is created and pushed immediately
const factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject);
const existingFactoryIndex = indexOf(token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount, endIndex);
if (existingFactoryIndex === -1) {
diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
registerDestroyHooksIfSupported(tView, provider, tInjectables.length);
tInjectables.push(token);
tNode.directiveStart++;
tNode.directiveEnd++;
if (isViewProvider) {
tNode.providerIndexes += 1048576 /* TNodeProviderIndexes.CptViewProvidersCountShifter */;
}
lInjectablesBlueprint.push(factory);
lView.push(factory);
}
else {
lInjectablesBlueprint[existingFactoryIndex] = factory;
lView[existingFactoryIndex] = factory;
}
}
else {
// Multi provider case:
// We create a multi factory which is going to aggregate all the values.
// Since the output of such a factory depends on content or view injection,
// we create two of them, which are linked together.
//
// The first one (for view providers) is always in the first block of the injectables array,
// and the second one (for providers) is always in the second block.
// This is important because view providers have higher priority. When a multi token
// is being looked up, the view providers should be found first.
// Note that it is not possible to have a multi factory in the third block (directive block).
//
// The algorithm to process multi providers is as follows:
// 1) If the multi provider comes from the `viewProviders` of the component:
// a) If the special view providers factory doesn't exist, it is created and pushed.
// b) Else, the multi provider is added to the existing multi factory.
// 2) If the multi provider comes from the `providers` of the component or of another
// directive:
// a) If the multi factory doesn't exist, it is created and provider pushed into it.
// It is also linked to the multi factory for view providers, if it exists.
// b) Else, the multi provider is added to the existing multi factory.
const existingProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);
const existingViewProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);
const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 &&
lInjectablesBlueprint[existingProvidersFactoryIndex];
const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 &&
lInjectablesBlueprint[existingViewProvidersFactoryIndex];
if (isViewProvider && !doesViewProvidersFactoryExist ||
!isViewProvider && !doesProvidersFactoryExist) {
// Cases 1.a and 2.a
diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
const factory = multiFactory(isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver, lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory);
if (!isViewProvider && doesViewProvidersFactoryExist) {
lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory;
}
registerDestroyHooksIfSupported(tView, provider, tInjectables.length, 0);
tInjectables.push(token);
tNode.directiveStart++;
tNode.directiveEnd++;
if (isViewProvider) {
tNode.providerIndexes += 1048576 /* TNodeProviderIndexes.CptViewProvidersCountShifter */;
}
lInjectablesBlueprint.push(factory);
lView.push(factory);
}
else {
// Cases 1.b and 2.b
const indexInFactory = multiFactoryAdd(lInjectablesBlueprint[isViewProvider ? existingViewProvidersFactoryIndex :
existingProvidersFactoryIndex], providerFactory, !isViewProvider && isComponent);
registerDestroyHooksIfSupported(tView, provider, existingProvidersFactoryIndex > -1 ? existingProvidersFactoryIndex :
existingViewProvidersFactoryIndex, indexInFactory);
}
if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) {
lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders++;
}
}
}
}
/**
* Registers the `ngOnDestroy` hook of a provider, if the provider supports destroy hooks.
* @param tView `TView` in which to register the hook.
* @param provider Provider whose hook should be registered.
* @param contextIndex Index under which to find the context for the hook when it's being invoked.
* @param indexInFactory Only required for `multi` providers. Index of the provider in the multi
* provider factory.
*/
function registerDestroyHooksIfSupported(tView, provider, contextIndex, indexInFactory) {
const providerIsTypeProvider = isTypeProvider(provider);
const providerIsClassProvider = isClassProvider(provider);
if (providerIsTypeProvider || providerIsClassProvider) {
// Resolve forward references as `useClass` can hold a forward reference.
const classToken = providerIsClassProvider ? resolveForwardRef(provider.useClass) : provider;
const prototype = classToken.prototype;
const ngOnDestroy = prototype.ngOnDestroy;
if (ngOnDestroy) {
const hooks = tView.destroyHooks || (tView.destroyHooks = []);
if (!providerIsTypeProvider && provider.multi) {
ngDevMode &&
assertDefined(indexInFactory, 'indexInFactory when registering multi factory destroy hook');
const existingCallbacksIndex = hooks.indexOf(contextIndex);
if (existingCallbacksIndex === -1) {
hooks.push(contextIndex, [indexInFactory, ngOnDestroy]);
}
else {
hooks[existingCallbacksIndex + 1].push(indexInFactory, ngOnDestroy);
}
}
else {
hooks.push(contextIndex, ngOnDestroy);
}
}
}
}
/**
* Add a factory in a multi factory.
* @returns Index at which the factory was inserted.
*/
function multiFactoryAdd(multiFactory, factory, isComponentProvider) {
if (isComponentProvider) {
multiFactory.componentProviders++;
}
return multiFactory.multi.push(factory) - 1;
}
/**
* Returns the index of item in the array, but only in the begin to end range.
*/
function indexOf(item, arr, begin, end) {
for (let i = begin; i < end; i++) {
if (arr[i] === item)
return i;
}
return -1;
}
/**
* Use this with `multi` `providers`.
*/
function multiProvidersFactoryResolver(_, tData, lData, tNode) {
return multiResolve(this.multi, []);
}
/**
* Use this with `multi` `viewProviders`.
*
* This factory knows how to concatenate itself with the existing `multi` `providers`.
*/
function multiViewProvidersFactoryResolver(_, tData, lView, tNode) {
const factories = this.multi;
let result;
if (this.providerFactory) {
const componentCount = this.providerFactory.componentProviders;
const multiProviders = getNodeInjectable(lView, lView[TVIEW], this.providerFactory.index, tNode);
// Copy the section of the array which contains `multi` `providers` from the component
result = multiProviders.slice(0, componentCount);
// Insert the `viewProvider` instances.
multiResolve(factories, result);
// Copy the section of the array which contains `multi` `providers` from other directives
for (let i = componentCount; i < multiProviders.length; i++) {
result.push(multiProviders[i]);
}
}
else {
result = [];
// Insert the `viewProvider` instances.
multiResolve(factories, result);
}
return result;
}
/**
* Maps an array of factories into an array of values.
*/
function multiResolve(factories, result) {
for (let i = 0; i < factories.length; i++) {
const factory = factories[i];
result.push(factory());
}
return result;
}
/**
* Creates a multi factory.
*/
function multiFactory(factoryFn, index, isViewProvider, isComponent, f) {
const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject);
factory.multi = [];
factory.index = index;
factory.componentProviders = 0;
multiFactoryAdd(factory, f, isComponent && !isViewProvider);
return factory;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlfc2V0dXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXIzL2RpX3NldHVwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUdILE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE9BQU8sRUFBQyxlQUFlLEVBQUUsY0FBYyxFQUFpQixNQUFNLDJCQUEyQixDQUFDO0FBQzFGLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU3QyxPQUFPLEVBQUMsMkJBQTJCLEVBQUUsNEJBQTRCLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRyxPQUFPLEVBQUMsa0JBQWtCLEVBQUUsaUJBQWlCLEVBQUUsOEJBQThCLEVBQUUsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ3pHLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBRXJELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLEVBQWdDLEtBQUssRUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlFLE9BQU8sRUFBQyxlQUFlLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUk1RDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQzdCLEdBQW9CLEVBQUUsU0FBcUIsRUFBRSxhQUF5QjtJQUN4RSxNQUFNLEtBQUssR0FBRyxRQUFRLEVBQUUsQ0FBQztJQUN6QixJQUFJLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUMxQixNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFeEMsMkVBQTJFO1FBQzNFLGVBQWUsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUUvRSxzRUFBc0U7UUFDdEUsZUFBZSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlFLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGVBQWUsQ0FDcEIsUUFBa0IsRUFBRSxZQUFtQixFQUFFLHFCQUE0QyxFQUNyRixXQUFvQixFQUFFLGNBQXVCO0lBQy9DLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2QyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUM1QixxQ0FBcUM7UUFDckMsMkZBQTJGO1FBQzNGLGdDQUFnQztRQUNoQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3pDLGVBQWUsQ0FDWCxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsWUFBWSxFQUFFLHFCQUFxQixFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNyRixDQUFDO0lBQ0gsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLEtBQUssR0FBRyxRQUFRLEVBQUUsQ0FBQztRQUN6QixNQUFNLEtBQUssR0FBRyxRQUFRLEVBQUUsQ0FBQztRQUN6QixNQUFNLEtBQUssR0FBRyxlQUFlLEVBQUcsQ0FBQztRQUNqQyxJQUFJLEtBQUssR0FBUSxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTNGLE1BQU0sZUFBZSxHQUFHLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxNQUFNLFFBQVEsR0FDVixJQUFJLFlBQVksQ0FBQyxLQUE4RCxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzVGLDRCQUE0QixDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFO2dCQUNqRCwyQkFBMkIsQ0FBQyxRQUEwQixFQUFFLGNBQWMsQ0FBQyxDQUFDO1lBQzFFLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxlQUFlLDZEQUErQyxDQUFDO1FBQ3hGLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7UUFDdEMsTUFBTSxxQkFBcUIsR0FDdkIsS0FBSyxDQUFDLGVBQWUsNERBQW1ELENBQUM7UUFFN0UsSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEQsc0VBQXNFO1lBQ3RFLE1BQU0sT0FBTyxHQUFHLElBQUksbUJBQW1CLENBQUMsZUFBZSxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQzVGLE1BQU0sb0JBQW9CLEdBQUcsT0FBTyxDQUNoQyxLQUFLLEVBQUUsWUFBWSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLEdBQUcscUJBQXFCLEVBQ3JGLFFBQVEsQ0FBQyxDQUFDO1lBQ2QsSUFBSSxvQkFBb0IsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNoQyxrQkFBa0IsQ0FDZCw4QkFBOEIsQ0FDMUIsS0FBOEQsRUFBRSxLQUFLLENBQUMsRUFDMUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNsQiwrQkFBK0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDdEUsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDekIsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN2QixLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3JCLElBQUksY0FBYyxFQUFFLENBQUM7b0JBQ25CLEtBQUssQ0FBQyxlQUFlLG1FQUFxRCxDQUFDO2dCQUM3RSxDQUFDO2dCQUNELHFCQUFxQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDcEMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0QixDQUFDO2lCQUFNLENBQUM7Z0JBQ04scUJBQXFCLENBQUMsb0JBQW9CLENBQUMsR0FBRyxPQUFPLENBQUM7Z0JBQ3RELEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLE9BQU8sQ0FBQztZQUN4QyxDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTix1QkFBdUI7WUFDdkIsd0VBQXdFO1lBQ3hFLDJFQUEyRTtZQUMzRSxvREFBb0Q7WUFDcEQsRUFBRTtZQUNGLDRGQUE0RjtZQUM1RixvRUFBb0U7WUFDcEUsb0ZBQW9GO1lBQ3BGLGdFQUFnRTtZQUNoRSw2RkFBNkY7WUFDN0YsRUFBRTtZQUNGLDBEQUEwRDtZQUMxRCw0RUFBNEU7WUFDNUUsc0ZBQXNGO1lBQ3RGLHdFQUF3RTtZQUN4RSxxRkFBcUY7WUFDckYsYUFBYTtZQUNiLHNGQUFzRjtZQUN0RixnRkFBZ0Y7WUFDaEYsd0VBQXdFO1lBRXhFLE1BQU0sNkJBQTZCLEdBQy9CLE9BQU8sQ0FBQyxLQUFLLEVBQUUsWUFBWSxFQUFFLFVBQVUsR0FBRyxxQkFBcUIsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMvRSxNQUFNLGlDQUFpQyxHQUNuQyxPQUFPLENBQUMsS0FBSyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsVUFBVSxHQUFHLHFCQUFxQixDQUFDLENBQUM7WUFDakYsTUFBTSx5QkFBeUIsR0FBRyw2QkFBNkIsSUFBSSxDQUFDO2dCQUNoRSxxQkFBcUIsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQ3pELE1BQU0sNkJBQTZCLEdBQUcsaUNBQWlDLElBQUksQ0FBQztnQkFDeEUscUJBQXFCLENBQUMsaUNBQWlDLENBQUMsQ0FBQztZQUU3RCxJQUFJLGNBQWMsSUFBSSxDQUFDLDZCQUE2QjtnQkFDaEQsQ0FBQyxjQUFjLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO2dCQUNsRCxvQkFBb0I7Z0JBQ3BCLGtCQUFrQixDQUNkLDhCQUE4QixDQUMxQixLQUE4RCxFQUFFLEtBQUssQ0FBQyxFQUMxRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ2xCLE1BQU0sT0FBTyxHQUFHLFlBQVksQ0FDeEIsY0FBYyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsNkJBQTZCLEVBQ2xGLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLGVBQWUsQ0FBQyxDQUFDO2dCQUNoRixJQUFJLENBQUMsY0FBYyxJQUFJLDZCQUE2QixFQUFFLENBQUM7b0JBQ3JELHFCQUFxQixDQUFDLGlDQUFpQyxDQUFDLENBQUMsZUFBZSxHQUFHLE9BQU8sQ0FBQztnQkFDckYsQ0FBQztnQkFDRCwrQkFBK0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ3pFLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3pCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDdkIsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNyQixJQUFJLGNBQWMsRUFBRSxDQUFDO29CQUNuQixLQUFLLENBQUMsZUFBZSxtRUFBcUQsQ0FBQztnQkFDN0UsQ0FBQztnQkFDRCxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3BDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLG9CQUFvQjtnQkFDcEIsTUFBTSxjQUFjLEdBQUcsZUFBZSxDQUNsQyxxQkFBc0IsQ0FDakIsY0FBYyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO29CQUNuQyw2QkFBNkIsQ0FBQyxFQUNwRCxlQUFlLEVBQUUsQ0FBQyxjQUFjLElBQUksV0FBVyxDQUFDLENBQUM7Z0JBQ3JELCtCQUErQixDQUMzQixLQUFLLEVBQUUsUUFBUSxFQUNmLDZCQUE2QixHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO29CQUMvQixpQ0FBaUMsRUFDdEUsY0FBYyxDQUFDLENBQUM7WUFDdEIsQ0FBQztZQUNELElBQUksQ0FBQyxjQUFjLElBQUksV0FBVyxJQUFJLDZCQUE2QixFQUFFLENBQUM7Z0JBQ3BFLHFCQUFxQixDQUFDLGlDQUFpQyxDQUFDLENBQUMsa0JBQW1CLEVBQUUsQ0FBQztZQUNqRixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQVMsK0JBQStCLENBQ3BDLEtBQVksRUFBRSxRQUFrQyxFQUFFLFlBQW9CLEVBQ3RFLGNBQXVCO0lBQ3pCLE1BQU0sc0JBQXNCLEdBQUcsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sdUJBQXVCLEdBQUcsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRTFELElBQUksc0JBQXNCLElBQUksdUJBQXVCLEVBQUUsQ0FBQztRQUN0RCx5RUFBeUU7UUFDekUsTUFBTSxVQUFVLEdBQUcsdUJBQXVCLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO1FBQzdGLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFDdkMsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLFdBQVcsQ0FBQztRQUUxQyxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBRTlELElBQUksQ0FBQyxzQkFBc0IsSUFBTSxRQUEyQixDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNuRSxTQUFTO29CQUNMLGFBQWEsQ0FDVCxjQUFjLEVBQUUsNERBQTRELENBQUMsQ0FBQztnQkFDdEYsTUFBTSxzQkFBc0IsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUUzRCxJQUFJLHNCQUFzQixLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ2xDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsY0FBYyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7Z0JBQzFELENBQUM7cUJBQU0sQ0FBQztvQkFDTCxLQUFLLENBQUMsc0JBQXNCLEdBQUcsQ0FBQyxDQUFxQixDQUFDLElBQUksQ0FBQyxjQUFlLEVBQUUsV0FBVyxDQUFDLENBQUM7Z0JBQzVGLENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDeEMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsZUFBZSxDQUNwQixZQUFpQyxFQUFFLE9BQWtCLEVBQUUsbUJBQTRCO0lBQ3JGLElBQUksbUJBQW1CLEVBQUUsQ0FBQztRQUN4QixZQUFZLENBQUMsa0JBQW1CLEVBQUUsQ0FBQztJQUNyQyxDQUFDO0lBQ0QsT0FBTyxZQUFZLENBQUMsS0FBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxPQUFPLENBQUMsSUFBUyxFQUFFLEdBQVUsRUFBRSxLQUFhLEVBQUUsR0FBVztJQUNoRSxLQUFLLElBQUksQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDakMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtZQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ1osQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyw2QkFBNkIsQ0FDUCxDQUFZLEVBQUUsS0FBWSxFQUFFLEtBQVksRUFDbkUsS0FBeUI7SUFDM0IsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztBQUN2QyxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsaUNBQWlDLENBQ1gsQ0FBWSxFQUFFLEtBQVksRUFBRSxLQUFZLEVBQ25FLEtBQXlCO0lBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFNLENBQUM7SUFDOUIsSUFBSSxNQUFhLENBQUM7SUFDbEIsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDekIsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxrQkFBbUIsQ0FBQztRQUNoRSxNQUFNLGNBQWMsR0FDaEIsaUJBQWlCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsZUFBZ0IsQ0FBQyxLQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDaEYsc0ZBQXNGO1FBQ3RGLE1BQU0sR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNqRCx1Q0FBdUM7UUFDdkMsWUFBWSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNoQyx5RkFBeUY7UUFDekYsS0FBSyxJQUFJLENBQUMsR0FBRyxjQUFjLEVBQUUsQ0FBQyxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM1RCxNQUFNLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDWix1Q0FBdUM7UUFDdkMsWUFBWSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxZQUFZLENBQUMsU0FBMkIsRUFBRSxNQUFhO0lBQzlELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDMUMsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBZ0IsQ0FBQztRQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsWUFBWSxDQUNqQixTQUVxQyxFQUNyQyxLQUFhLEVBQUUsY0FBdUIsRUFBRSxXQUFvQixFQUM1RCxDQUFZO0lBQ2QsTUFBTSxPQUFPLEdBQUcsSUFBSSxtQkFBbUIsQ0FBQyxTQUFTLEVBQUUsY0FBYyxFQUFFLGlCQUFpQixDQUFDLENBQUM7SUFDdEYsT0FBTyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDbkIsT0FBTyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7SUFDdEIsT0FBTyxDQUFDLGtCQUFrQixHQUFHLENBQUMsQ0FBQztJQUMvQixlQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxXQUFXLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM1RCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cblxuaW1wb3J0IHtyZXNvbHZlRm9yd2FyZFJlZn0gZnJvbSAnLi4vZGkvZm9yd2FyZF9yZWYnO1xuaW1wb3J0IHtDbGFzc1Byb3ZpZGVyLCBQcm92aWRlcn0gZnJvbSAnLi4vZGkvaW50ZXJmYWNlL3Byb3ZpZGVyJztcbmltcG9ydCB7aXNDbGFzc1Byb3ZpZGVyLCBpc1R5cGVQcm92aWRlciwgU2luZ2xlUHJvdmlkZXJ9IGZyb20gJy4uL2RpL3Byb3ZpZGVyX2NvbGxlY3Rpb24nO1xuaW1wb3J0IHtwcm92aWRlclRvRmFjdG9yeX0gZnJvbSAnLi4vZGkvcjNfaW5qZWN0b3InO1xuaW1wb3J0IHthc3NlcnREZWZpbmVkfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5cbmltcG9ydCB7ZW1pdFByb3ZpZGVyQ29uZmlndXJlZEV2ZW50LCBydW5JbkluamVjdG9yUHJvZmlsZXJDb250ZXh0fSBmcm9tICcuL2RlYnVnL2luamVjdG9yX3Byb2ZpbGVyJztcbmltcG9ydCB7ZGlQdWJsaWNJbkluamVjdG9yLCBnZXROb2RlSW5qZWN0YWJsZSwgZ2V0T3JDcmVhdGVOb2RlSW5qZWN0b3JGb3JOb2RlLCBOb2RlSW5qZWN0b3J9IGZyb20gJy4vZGknO1xuaW1wb3J0IHvJtcm1ZGlyZWN0aXZlSW5qZWN0fSBmcm9tICcuL2luc3RydWN0aW9ucy9hbGwnO1xuaW1wb3J0IHtEaXJlY3RpdmVEZWZ9IGZyb20gJy4vaW50ZXJmYWNlcy9kZWZpbml0aW9uJztcbmltcG9ydCB7Tm9kZUluamVjdG9yRmFjdG9yeX0gZnJvbSAnLi9pbnRlcmZhY2VzL2luamVjdG9yJztcbmltcG9ydCB7VENvbnRhaW5lck5vZGUsIFREaXJlY3RpdmVIb3N0Tm9kZSwgVEVsZW1lbnRDb250YWluZXJOb2RlLCBURWxlbWVudE5vZGUsIFROb2RlUHJvdmlkZXJJbmRleGVzfSBmcm9tICcuL2ludGVyZmFjZXMvbm9kZSc7XG5pbXBvcnQge2lzQ29tcG9uZW50RGVmfSBmcm9tICcuL2ludGVyZmFjZXMvdHlwZV9jaGVja3MnO1xuaW1wb3J0IHtEZXN0cm95SG9va0RhdGEsIExWaWV3LCBURGF0YSwgVFZJRVcsIFRWaWV3fSBmcm9tICcuL2ludGVyZmFjZXMvdmlldyc7XG5pbXBvcnQge2dldEN1cnJlbnRUTm9kZSwgZ2V0TFZpZXcsIGdldFRWaWV3fSBmcm9tICcuL3N0YXRlJztcblxuXG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIHByb3ZpZGVycyB3aGljaCBhcmUgZGVmaW5lZCBpbiB0aGUgRGlyZWN0aXZlRGVmLlxuICpcbiAqIFdoZW4gaW5zZXJ0aW5nIHRoZSB0b2tlbnMgYW5kIHRoZSBmYWN0b3JpZXMgaW4gdGhlaXIgcmVzcGVjdGl2ZSBhcnJheXMsIHdlIGNhbiBhc3N1bWUgdGhhdFxuICogdGhpcyBtZXRob2QgaXMgY2FsbGVkIGZpcnN0IGZvciB0aGUgY29tcG9uZW50IChpZiBhbnkpLCBhbmQgdGhlbiBmb3Igb3RoZXIgZGlyZWN0aXZlcyBvbiB0aGUgc2FtZVxuICogbm9kZS5cbiAqIEFzIGEgY29uc2VxdWVuY2UsdGhlIHByb3ZpZGVycyBhcmUgYWx3YXlzIHByb2Nlc3NlZCBpbiB0aGF0IG9yZGVyOlxuICogMSkgVGhlIHZpZXcgcHJvdmlkZXJzIG9mIHRoZSBjb21wb25lbnRcbiAqIDIpIFRoZSBwcm92aWRlcnMgb2YgdGhlIGNvbXBvbmVudFxuICogMykgVGhlIHByb3ZpZGVycyBvZiB0aGUgb3RoZXIgZGlyZWN0aXZlc1xuICogVGhpcyBtYXRjaGVzIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGluamVjdGFibGVzIGFycmF5cyBvZiBhIHZpZXcgKGZvciBlYWNoIG5vZGUpLlxuICogU28gdGhlIHRva2VucyBhbmQgdGhlIGZhY3RvcmllcyBjYW4gYmUgcHVzaGVkIGF0IHRoZSBlbmQgb2YgdGhlIGFycmF5cywgZXhjZXB0XG4gKiBpbiBvbmUgY2FzZSBmb3IgbXVsdGkgcHJvdmlkZXJzLlxuICpcbiAqIEBwYXJhbSBkZWYgdGhlIGRpcmVjdGl2ZSBkZWZpbml0aW9uXG4gKiBAcGFyYW0gcHJvdmlkZXJzOiBBcnJheSBvZiBgcHJvdmlkZXJzYC5cbiAqIEBwYXJhbSB2aWV3UHJvdmlkZXJzOiBBcnJheSBvZiBgdmlld1Byb3ZpZGVyc2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlcnNSZXNvbHZlcjxUPihcbiAgICBkZWY6IERpcmVjdGl2ZURlZjxUPiwgcHJvdmlkZXJzOiBQcm92aWRlcltdLCB2aWV3UHJvdmlkZXJzOiBQcm92aWRlcltdKTogdm9pZCB7XG4gIGNvbnN0IHRWaWV3ID0gZ2V0VFZpZXcoKTtcbiAgaWYgKHRWaWV3LmZpcnN0Q3JlYXRlUGFzcykge1xuICAgIGNvbnN0IGlzQ29tcG9uZW50ID0gaXNDb21wb25lbnREZWYoZGVmKTtcblxuICAgIC8vIFRoZSBsaXN0IG9mIHZpZXcgcHJvdmlkZXJzIGlzIHByb2Nlc3NlZCBmaXJzdCwgYW5kIHRoZSBmbGFncyBhcmUgdXBkYXRlZFxuICAgIHJlc29sdmVQcm92aWRlcih2aWV3UHJvdmlkZXJzLCB0Vmlldy5kYXRhLCB0Vmlldy5ibHVlcHJpbnQsIGlzQ29tcG9uZW50LCB0cnVlKTtcblxuICAgIC8vIFRoZW4sIHRoZSBsaXN0IG9mIHByb3ZpZGVycyBpcyBwcm9jZXNzZWQsIGFuZCB0aGUgZmxhZ3MgYXJlIHVwZGF0ZWRcbiAgICByZXNvbHZlUHJvdmlkZXIocHJvdmlkZXJzLCB0Vmlldy5kYXRhLCB0Vmlldy5ibHVlcHJpbnQsIGlzQ29tcG9uZW50LCBmYWxzZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhIHByb3ZpZGVyIGFuZCBwdWJsaXNoZXMgaXQgdG8gdGhlIERJIHN5c3RlbS5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVByb3ZpZGVyKFxuICAgIHByb3ZpZGVyOiBQcm92aWRlciwgdEluamVjdGFibGVzOiBURGF0YSwgbEluamVjdGFibGVzQmx1ZXByaW50OiBOb2RlSW5qZWN0b3JGYWN0b3J5W10sXG4gICAgaXNDb21wb25lbnQ6IGJvb2xlYW4sIGlzVmlld1Byb3ZpZGVyOiBib29sZWFuKTogdm9pZCB7XG4gIHByb3ZpZGVyID0gcmVzb2x2ZUZvcndhcmRSZWYocHJvdmlkZXIpO1xuICBpZiAoQXJyYXkuaXNBcnJheShwcm92aWRlcikpIHtcbiAgICAvLyBSZWN1cnNpdmVseSBjYWxsIGByZXNvbHZlUHJvdmlkZXJgXG4gICAgLy8gUmVjdXJzaW9uIGlzIE9LIGluIHRoaXMgY2FzZSBiZWNhdXNlIHRoaXMgY29kZSB3aWxsIG5vdCBiZSBpbiBob3QtcGF0aCBvbmNlIHdlIGltcGxlbWVudFxuICAgIC8vIGNsb25pbmcgb2YgdGhlIGluaXRpYWwgc3RhdGUuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwcm92aWRlci5sZW5ndGg7IGkrKykge1xuICAgICAgcmVzb2x2ZVByb3ZpZGVyKFxuICAgICAgICAgIHByb3ZpZGVyW2ldLCB0SW5qZWN0YWJsZXMsIGxJbmplY3RhYmxlc0JsdWVwcmludCwgaXNDb21wb25lbnQsIGlzVmlld1Byb3ZpZGVyKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgdFZpZXcgPSBnZXRUVmlldygpO1xuICAgIGNvbnN0IGxWaWV3ID0gZ2V0TFZpZXcoKTtcbiAgICBjb25zdCB0Tm9kZSA9IGdldEN1cnJlbnRUTm9kZSgpITtcbiAgICBsZXQgdG9rZW46IGFueSA9IGlzVHlwZVByb3ZpZGVyKHByb3ZpZGVyKSA/IHByb3ZpZGVyIDogcmVzb2x2ZUZvcndhcmRSZWYocHJvdmlkZXIucHJvdmlkZSk7XG5cbiAgICBjb25zdCBwcm92aWRlckZhY3RvcnkgPSBwcm92aWRlclRvRmFjdG9yeShwcm92aWRlcik7XG4gICAgaWYgKG5nRGV2TW9kZSkge1xuICAgICAgY29uc3QgaW5qZWN0b3IgPVxuICAgICAgICAgIG5ldyBOb2RlSW5qZWN0b3IodE5vZGUgYXMgVEVsZW1lbnROb2RlIHwgVENvbnRhaW5lck5vZGUgfCBURWxlbWVudENvbnRhaW5lck5vZGUsIGxWaWV3KTtcbiAgICAgIHJ1bkluSW5qZWN0b3JQcm9maWxlckNvbnRleHQoaW5qZWN0b3IsIHRva2VuLCAoKSA9PiB7XG4gICAgICAgIGVtaXRQcm92aWRlckNvbmZpZ3VyZWRFdmVudChwcm92aWRlciBhcyBTaW5nbGVQcm92aWRlciwgaXNWaWV3UHJvdmlkZXIpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgYmVnaW5JbmRleCA9IHROb2RlLnByb3ZpZGVySW5kZXhlcyAmIFROb2RlUHJvdmlkZXJJbmRleGVzLlByb3ZpZGVyc1N0YXJ0SW5kZXhNYXNrO1xuICAgIGNvbnN0IGVuZEluZGV4ID0gdE5vZGUuZGlyZWN0aXZlU3RhcnQ7XG4gICAgY29uc3QgY3B0Vmlld1Byb3ZpZGVyc0NvdW50ID1cbiAgICAgICAgdE5vZGUucHJvdmlkZXJJbmRleGVzID4+IFROb2RlUHJvdmlkZXJJbmRleGVzLkNwdFZpZXdQcm92aWRlcnNDb3VudFNoaWZ0O1xuXG4gICAgaWYgKGlzVHlwZVByb3ZpZGVyKHByb3ZpZGVyKSB8fCAhcHJvdmlkZXIubXVsdGkpIHtcbiAgICAgIC8vIFNpbmdsZSBwcm92aWRlciBjYXNlOiB0aGUgZmFjdG9yeSBpcyBjcmVhdGVkIGFuZCBwdXNoZWQgaW1tZWRpYXRlbHlcbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgTm9kZUluamVjdG9yRmFjdG9yeShwcm92aWRlckZhY3RvcnksIGlzVmlld1Byb3ZpZGVyLCDJtcm1ZGlyZWN0aXZlSW5qZWN0KTtcbiAgICAgIGNvbnN0IGV4aXN0aW5nRmFjdG9yeUluZGV4ID0gaW5kZXhPZihcbiAgICAgICAgICB0b2tlbiwgdEluamVjdGFibGVzLCBpc1ZpZXdQcm92aWRlciA/IGJlZ2luSW5kZXggOiBiZWdpbkluZGV4ICsgY3B0Vmlld1Byb3ZpZGVyc0NvdW50LFxuICAgICAgICAgIGVuZEluZGV4KTtcbiAgICAgIGlmIChleGlzdGluZ0ZhY3RvcnlJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgZGlQdWJsaWNJbkluamVjdG9yKFxuICAgICAgICAgICAgZ2V0T3JDcmVhdGVOb2RlSW5qZWN0b3JGb3JOb2RlKFxuICAgICAgICAgICAgICAgIHROb2RlIGFzIFRFbGVtZW50Tm9kZSB8IFRDb250YWluZXJOb2RlIHwgVEVsZW1lbnRDb250YWluZXJOb2RlLCBsVmlldyksXG4gICAgICAgICAgICB0VmlldywgdG9rZW4pO1xuICAgICAgICByZWdpc3RlckRlc3Ryb3lIb29rc0lmU3VwcG9ydGVkKHRWaWV3LCBwcm92aWRlciwgdEluamVjdGFibGVzLmxlbmd0aCk7XG4gICAgICAgIHRJbmplY3RhYmxlcy5wdXNoKHRva2VuKTtcbiAgICAgICAgdE5vZGUuZGlyZWN0aXZlU3RhcnQrKztcbiAgICAgICAgdE5vZGUuZGlyZWN0aXZlRW5kKys7XG4gICAgICAgIGlmIChpc1ZpZXdQcm92aWRlcikge1xuICAgICAgICAgIHROb2RlLnByb3ZpZGVySW5kZXhlcyArPSBUTm9kZVByb3ZpZGVySW5kZXhlcy5DcHRWaWV3UHJvdmlkZXJzQ291bnRTaGlmdGVyO1xuICAgICAgICB9XG4gICAgICAgIGxJbmplY3RhYmxlc0JsdWVwcmludC5wdXNoKGZhY3RvcnkpO1xuICAgICAgICBsVmlldy5wdXNoKGZhY3RvcnkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbEluamVjdGFibGVzQmx1ZXByaW50W2V4aXN0aW5nRmFjdG9yeUluZGV4XSA9IGZhY3Rvcnk7XG4gICAgICAgIGxWaWV3W2V4aXN0aW5nRmFjdG9yeUluZGV4XSA9IGZhY3Rvcnk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE11bHRpIHByb3ZpZGVyIGNhc2U6XG4gICAgICAvLyBXZSBjcmVhdGUgYSBtdWx0aSBmYWN0b3J5IHdoaWNoIGlzIGdvaW5nIHRvIGFnZ3JlZ2F0ZSBhbGwgdGhlIHZhbHVlcy5cbiAgICAgIC8vIFNpbmNlIHRoZSBvdXRwdXQgb2Ygc3VjaCBhIGZhY3RvcnkgZGVwZW5kcyBvbiBjb250ZW50IG9yIHZpZXcgaW5qZWN0aW9uLFxuICAgICAgLy8gd2UgY3JlYXRlIHR3byBvZiB0aGVtLCB3aGljaCBhcmUgbGlua2VkIHRvZ2V0aGVyLlxuICAgICAgLy9cbiAgICAgIC8vIFRoZSBmaXJzdCBvbmUgKGZvciB2aWV3IHByb3ZpZGVycykgaXMgYWx3YXlzIGluIHRoZSBmaXJzdCBibG9jayBvZiB0aGUgaW5qZWN0YWJsZXMgYXJyYXksXG4gICAgICAvLyBhbmQgdGhlIHNlY29uZCBvbmUgKGZvciBwcm92aWRlcnMpIGlzIGFsd2F5cyBpbiB0aGUgc2Vjb25kIGJsb2NrLlxuICAgICAgLy8gVGhpcyBpcyBpbXBvcnRhbnQgYmVjYXVzZSB2aWV3IHByb3ZpZGVycyBoYXZlIGhpZ2hlciBwcmlvcml0eS4gV2hlbiBhIG11bHRpIHRva2VuXG4gICAgICAvLyBpcyBiZWluZyBsb29rZWQgdXAsIHRoZSB2aWV3IHByb3ZpZGVycyBzaG91bGQgYmUgZm91bmQgZmlyc3QuXG4gICAgICAvLyBOb3RlIHRoYXQgaXQgaXMgbm90IHBvc3NpYmxlIHRvIGhhdmUgYSBtdWx0aSBmYWN0b3J5IGluIHRoZSB0aGlyZCBibG9jayAoZGlyZWN0aXZlIGJsb2NrKS5cbiAgICAgIC8vXG4gICAgICAvLyBUaGUgYWxnb3JpdGhtIHRvIHByb2Nlc3MgbXVsdGkgcHJvdmlkZXJzIGlzIGFzIGZvbGxvd3M6XG4gICAgICAvLyAxKSBJZiB0aGUgbXVsdGkgcHJvdmlkZXIgY29tZXMgZnJvbSB0aGUgYHZpZXdQcm92aWRlcnNgIG9mIHRoZSBjb21wb25lbnQ6XG4gICAgICAvLyAgIGEpIElmIHRoZSBzcGVjaWFsIHZpZXcgcHJvdmlkZXJzIGZhY3RvcnkgZG9lc24ndCBleGlzdCwgaXQgaXMgY3JlYXRlZCBhbmQgcHVzaGVkLlxuICAgICAgLy8gICBiKSBFbHNlLCB0aGUgbXVsdGkgcHJvdmlkZXIgaXMgYWRkZWQgdG8gdGhlIGV4aXN0aW5nIG11bHRpIGZhY3RvcnkuXG4gICAgICAvLyAyKSBJZiB0aGUgbXVsdGkgcHJvdmlkZXIgY29tZXMgZnJvbSB0aGUgYHByb3ZpZGVyc2Agb2YgdGhlIGNvbXBvbmVudCBvciBvZiBhbm90aGVyXG4gICAgICAvLyBkaXJlY3RpdmU6XG4gICAgICAvLyAgIGEpIElmIHRoZSBtdWx0aSBmYWN0b3J5IGRvZXNuJ3QgZXhpc3QsIGl0IGlzIGNyZWF0ZWQgYW5kIHByb3ZpZGVyIHB1c2hlZCBpbnRvIGl0LlxuICAgICAgLy8gICAgICBJdCBpcyBhbHNvIGxpbmtlZCB0byB0aGUgbXVsdGkgZmFjdG9yeSBmb3IgdmlldyBwcm92aWRlcnMsIGlmIGl0IGV4aXN0cy5cbiAgICAgIC8vICAgYikgRWxzZSwgdGhlIG11bHRpIHByb3ZpZGVyIGlzIGFkZGVkIHRvIHRoZSBleGlzdGluZyBtdWx0aSBmYWN0b3J5LlxuXG4gICAgICBjb25zdCBleGlzdGluZ1Byb3ZpZGVyc0ZhY3RvcnlJbmRleCA9XG4gICAgICAgICAgaW5kZXhPZih0b2tlbiwgdEluamVjdGFibGVzLCBiZWdpbkluZGV4ICsgY3B0Vmlld1Byb3ZpZGVyc0NvdW50LCBlbmRJbmRleCk7XG4gICAgICBjb25zdCBleGlzdGluZ1ZpZXdQcm92aWRlcnNGYWN0b3J5SW5kZXggPVxuICAgICAgICAgIGluZGV4T2YodG9rZW4sIHRJbmplY3RhYmxlcywgYmVnaW5JbmRleCwgYmVnaW5JbmRleCArIGNwdFZpZXdQcm92aWRlcnNDb3VudCk7XG4gICAgICBjb25zdCBkb2VzUHJvdmlkZXJzRmFjdG9yeUV4aXN0ID0gZXhpc3RpbmdQcm92aWRlcnNGYWN0b3J5SW5kZXggPj0gMCAmJlxuICAgICAgICAgIGxJbmplY3RhYmxlc0JsdWVwcmludFtleGlzdGluZ1Byb3ZpZGVyc0ZhY3RvcnlJbmRleF07XG4gICAgICBjb25zdCBkb2VzVmlld1Byb3ZpZGVyc0ZhY3RvcnlFeGlzdCA9IGV4aXN0aW5nVmlld1Byb3ZpZGVyc0ZhY3RvcnlJbmRleCA+PSAwICYmXG4gICAgICAgICAgbEluamVjdGFibGVzQmx1ZXByaW50W2V4aXN0aW5nVmlld1Byb3ZpZGVyc0ZhY3RvcnlJbmRleF07XG5cbiAgICAgIGlmIChpc1ZpZXdQcm92aWRlciAmJiAhZG9lc1ZpZXdQcm92aWRlcnNGYWN0b3J5RXhpc3QgfHxcbiAgICAgICAgICAhaXNWaWV3UHJvdmlkZXIgJiYgIWRvZXNQcm92aWRlcnNGYWN0b3J5RXhpc3QpIHtcbiAgICAgICAgLy8gQ2FzZXMgMS5hIGFuZCAyLmFcbiAgICAgICAgZGlQdWJsaWNJbkluamVjdG9yKFxuICAgICAgICAgICAgZ2V0T3JDcmVhdGVOb2RlSW5qZWN0b3JGb3JOb2RlKFxuICAgICAgICAgICAgICAgIHROb2RlIGFzIFRFbGVtZW50Tm9kZSB8IFRDb250YWluZXJOb2RlIHwgVEVsZW1lbnRDb250YWluZXJOb2RlLCBsVmlldyksXG4gICAgICAgICAgICB0VmlldywgdG9rZW4pO1xuICAgICAgICBjb25zdCBmYWN0b3J5ID0gbXVsdGlGYWN0b3J5KFxuICAgICAgICAgICAgaXNWaWV3UHJvdmlkZXIgPyBtdWx0aVZpZXdQcm92aWRlcnNGYWN0b3J5UmVzb2x2ZXIgOiBtdWx0aVByb3ZpZGVyc0ZhY3RvcnlSZXNvbHZlcixcbiAgICAgICAgICAgIGxJbmplY3RhYmxlc0JsdWVwcmludC5sZW5ndGgsIGlzVmlld1Byb3ZpZGVyLCBpc0NvbXBvbmVudCwgcHJvdmlkZXJGYWN0b3J5KTtcbiAgICAgICAgaWYgKCFpc1ZpZXdQcm92aWRlciAmJiBkb2VzVmlld1Byb3ZpZGVyc0ZhY3RvcnlFeGlzdCkge1xuICAgICAgICAgIGxJbmplY3RhYmxlc0JsdWVwcmludFtleGlzdGluZ1ZpZXdQcm92aWRlcnNGYWN0b3J5SW5kZXhdLnByb3ZpZGVyRmFjdG9yeSA9IGZhY3Rvcnk7XG4gICAgICAgIH1cbiAgICAgICAgcmVnaXN0ZXJEZXN0cm95SG9va3NJZlN1cHBvcnRlZCh0VmlldywgcHJvdmlkZXIsIHRJbmplY3RhYmxlcy5sZW5ndGgsIDApO1xuICAgICAgICB0SW5qZWN0YWJsZXMucHVzaCh0b2tlbik7XG4gICAgICAgIHROb2RlLmRpcmVjdGl2ZVN0YXJ0Kys7XG4gICAgICAgIHROb2RlLmRpcmVjdGl2ZUVuZCsrO1xuICAgICAgICBpZiAoaXNWaWV3UHJvdmlkZXIpIHtcbiAgICAgICAgICB0Tm9kZS5wcm92aWRlckluZGV4ZXMgKz0gVE5vZGVQcm92aWRlckluZGV4ZXMuQ3B0Vmlld1Byb3ZpZGVyc0NvdW50U2hpZnRlcjtcbiAgICAgICAgfVxuICAgICAgICBsSW5qZWN0YWJsZXNCbHVlcHJpbnQucHVzaChmYWN0b3J5KTtcbiAgICAgICAgbFZpZXcucHVzaChmYWN0b3J5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIENhc2VzIDEuYiBhbmQgMi5iXG4gICAgICAgIGNvbnN0IGluZGV4SW5GYWN0b3J5ID0gbXVsdGlGYWN0b3J5QWRkKFxuICAgICAgICAgICAgbEluamVjdGFibGVzQmx1ZXByaW50IVxuICAgICAgICAgICAgICAgIFtpc1ZpZXdQcm92aWRlciA/IGV4aXN0aW5nVmlld1Byb3ZpZGVyc0ZhY3RvcnlJbmRleCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdQcm92aWRlcnNGYWN0b3J5SW5kZXhdLFxuICAgICAgICAgICAgcHJvdmlkZXJGYWN0b3J5LCAhaXNWaWV3UHJvdmlkZXIgJiYgaXNDb21wb25lbnQpO1xuICAgICAgICByZWdpc3RlckRlc3Ryb3lIb29rc0lmU3VwcG9ydGVkKFxuICAgICAgICAgICAgdFZpZXcsIHByb3ZpZGVyLFxuICAgICAgICAgICAgZXhpc3RpbmdQcm92aWRlcnNGYWN0b3J5SW5kZXggPiAtMSA/IGV4aXN0aW5nUHJvdmlkZXJzRmFjdG9yeUluZGV4IDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ1ZpZXdQcm92aWRlcnNGYWN0b3J5SW5kZXgsXG4gICAgICAgICAgICBpbmRleEluRmFjdG9yeSk7XG4gICAgICB9XG4gICAgICBpZiAoIWlzVmlld1Byb3ZpZGVyICYmIGlzQ29tcG9uZW50ICYmIGRvZXNWaWV3UHJvdmlkZXJzRmFjdG9yeUV4aXN0KSB7XG4gICAgICAgIGxJbmplY3RhYmxlc0JsdWVwcmludFtleGlzdGluZ1ZpZXdQcm92aWRlcnNGYWN0b3J5SW5kZXhdLmNvbXBvbmVudFByb3ZpZGVycyErKztcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGBuZ09uRGVzdHJveWAgaG9vayBvZiBhIHByb3ZpZGVyLCBpZiB0aGUgcHJvdmlkZXIgc3VwcG9ydHMgZGVzdHJveSBob29rcy5cbiAqIEBwYXJhbSB0VmlldyBgVFZpZXdgIGluIHdoaWNoIHRvIHJlZ2lzdGVyIHRoZSBob29rLlxuICogQHBhcmFtIHByb3ZpZGVyIFByb3ZpZGVyIHdob3NlIGhvb2sgc2hvdWxkIGJlIHJlZ2lzdGVyZWQuXG4gKiBAcGFyYW0gY29udGV4dEluZGV4IEluZGV4IHVuZGVyIHdoaWNoIHRvIGZpbmQgdGhlIGNvbnRleHQgZm9yIHRoZSBob29rIHdoZW4gaXQncyBiZWluZyBpbnZva2VkLlxuICogQHBhcmFtIGluZGV4SW5GYWN0b3J5IE9ubHkgcmVxdWlyZWQgZm9yIGBtdWx0aWAgcHJvdmlkZXJzLiBJbmRleCBvZiB0aGUgcHJvdmlkZXIgaW4gdGhlIG11bHRpXG4gKiBwcm92aWRlciBmYWN0b3J5LlxuICovXG5mdW5jdGlvbiByZWdpc3RlckRlc3Ryb3lIb29rc0lmU3VwcG9ydGVkKFxuICAgIHRWaWV3OiBUVmlldywgcHJvdmlkZXI6IEV4Y2x1ZGU8UHJvdmlkZXIsIGFueVtdPiwgY29udGV4dEluZGV4OiBudW1iZXIsXG4gICAgaW5kZXhJbkZhY3Rvcnk/OiBudW1iZXIpIHtcbiAgY29uc3QgcHJvdmlkZXJJc1R5cGVQcm92aWRlciA9IGlzVHlwZVByb3ZpZGVyKHByb3ZpZGVyKTtcbiAgY29uc3QgcHJvdmlkZXJJc0NsYXNzUHJvdmlkZXIgPSBpc0NsYXNzUHJvdmlkZXIocHJvdmlkZXIpO1xuXG4gIGlmIChwcm92aWRlcklzVHlwZVByb3ZpZGVyIHx8IHByb3ZpZGVySXNDbGFzc1Byb3ZpZGVyKSB7XG4gICAgLy8gUmVzb2x2ZSBmb3J3YXJkIHJlZmVyZW5jZXMgYXMgYHVzZUNsYXNzYCBjYW4gaG9sZCBhIGZvcndhcmQgcmVmZXJlbmNlLlxuICAgIGNvbnN0IGNsYXNzVG9rZW4gPSBwcm92aWRlcklzQ2xhc3NQcm92aWRlciA/IHJlc29sdmVGb3J3YXJkUmVmKHByb3ZpZGVyLnVzZUNsYXNzKSA6IHByb3ZpZGVyO1xuICAgIGNvbnN0IHByb3RvdHlwZSA9IGNsYXNzVG9rZW4ucHJvdG90eXBlO1xuICAgIGNvbnN0IG5nT25EZXN0cm95ID0gcHJvdG90eXBlLm5nT25EZXN0cm95O1xuXG4gICAgaWYgKG5nT25EZXN0cm95KSB7XG4gICAgICBjb25zdCBob29rcyA9IHRWaWV3LmRlc3Ryb3lIb29rcyB8fCAodFZpZXcuZGVzdHJveUhvb2tzID0gW10pO1xuXG4gICAgICBpZiAoIXByb3ZpZGVySXNUeXBlUHJvdmlkZXIgJiYgKChwcm92aWRlciBhcyBDbGFzc1Byb3ZpZGVyKSkubXVsdGkpIHtcbiAgICAgICAgbmdEZXZNb2RlICYmXG4gICAgICAgICAgICBhc3NlcnREZWZpbmVkKFxuICAgICAgICAgICAgICAgIGluZGV4SW5GYWN0b3J5LCAnaW5kZXhJbkZhY3Rvcnkgd2hlbiByZWdpc3RlcmluZyBtdWx0aSBmYWN0b3J5IGRlc3Ryb3kgaG9vaycpO1xuICAgICAgICBjb25zdCBleGlzdGluZ0NhbGxiYWNrc0luZGV4ID0gaG9va3MuaW5kZXhPZihjb250ZXh0SW5kZXgpO1xuXG4gICAgICAgIGlmIChleGlzdGluZ0NhbGxiYWNrc0luZGV4ID09PSAtMSkge1xuICAgICAgICAgIGhvb2tzLnB1c2goY29udGV4dEluZGV4LCBbaW5kZXhJbkZhY3RvcnksIG5nT25EZXN0cm95XSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgKGhvb2tzW2V4aXN0aW5nQ2FsbGJhY2tzSW5kZXggKyAxXSBhcyBEZXN0cm95SG9va0RhdGEpLnB1c2goaW5kZXhJbkZhY3RvcnkhLCBuZ09uRGVzdHJveSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhvb2tzLnB1c2goY29udGV4dEluZGV4LCBuZ09uRGVzdHJveSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQWRkIGEgZmFjdG9yeSBpbiBhIG11bHRpIGZhY3RvcnkuXG4gKiBAcmV0dXJucyBJbmRleCBhdCB3aGljaCB0aGUgZmFjdG9yeSB3YXMgaW5zZXJ0ZWQuXG4gKi9cbmZ1bmN0aW9uIG11bHRpRmFjdG9yeUFkZChcbiAgICBtdWx0aUZhY3Rvcnk6IE5vZGVJbmplY3RvckZhY3RvcnksIGZhY3Rvcnk6ICgpID0+IGFueSwgaXNDb21wb25lbnRQcm92aWRlcjogYm9vbGVhbik6IG51bWJlciB7XG4gIGlmIChpc0NvbXBvbmVudFByb3ZpZGVyKSB7XG4gICAgbXVsdGlGYWN0b3J5LmNvbXBvbmVudFByb3ZpZGVycyErKztcbiAgfVxuICByZXR1cm4gbXVsdGlGYWN0b3J5Lm11bHRpIS5wdXNoKGZhY3RvcnkpIC0gMTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbmRleCBvZiBpdGVtIGluIHRoZSBhcnJheSwgYnV0IG9ubHkgaW4gdGhlIGJlZ2luIHRvIGVuZCByYW5nZS5cbiAqL1xuZnVuY3Rpb24gaW5kZXhPZihpdGVtOiBhbnksIGFycjogYW55W10sIGJlZ2luOiBudW1iZXIsIGVuZDogbnVtYmVyKSB7XG4gIGZvciAobGV0IGkgPSBiZWdpbjsgaSA8IGVuZDsgaSsrKSB7XG4gICAgaWYgKGFycltpXSA9PT0gaXRlbSkgcmV0dXJuIGk7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG4vKipcbiAqIFVzZSB0aGlzIHdpdGggYG11bHRpYCBgcHJvdmlkZXJzYC5cbiAqL1xuZnVuY3Rpb24gbXVsdGlQcm92aWRlcnNGYWN0b3J5UmVzb2x2ZXIoXG4gICAgdGhpczogTm9kZUluamVjdG9yRmFjdG9yeSwgXzogdW5kZWZpbmVkLCB0RGF0YTogVERhdGEsIGxEYXRhOiBMVmlldyxcbiAgICB0Tm9kZTogVERpcmVjdGl2ZUhvc3ROb2RlKTogYW55W10ge1xuICByZXR1cm4gbXVsdGlSZXNvbHZlKHRoaXMubXVsdGkhLCBbXSk7XG59XG5cbi8qKlxuICogVXNlIHRoaXMgd2l0aCBgbXVsdGlgIGB2aWV3UHJvdmlkZXJzYC5cbiAqXG4gKiBUaGlzIGZhY3Rvcnkga25vd3MgaG93IHRvIGNvbmNhdGVuYXRlIGl0c2VsZiB3aXRoIHRoZSBleGlzdGluZyBgbXVsdGlgIGBwcm92aWRlcnNgLlxuICovXG5mdW5jdGlvbiBtdWx0aVZpZXdQcm92aWRlcnNGYWN0b3J5UmVzb2x2ZXIoXG4gICAgdGhpczogTm9kZUluamVjdG9yRmFjdG9yeSwgXzogdW5kZWZpbmVkLCB0RGF0YTogVERhdGEsIGxWaWV3OiBMVmlldyxcbiAgICB0Tm9kZTogVERpcmVjdGl2ZUhvc3ROb2RlKTogYW55W10ge1xuICBjb25zdCBmYWN0b3JpZXMgPSB0aGlzLm11bHRpITtcbiAgbGV0IHJlc3VsdDogYW55W107XG4gIGlmICh0aGlzLnByb3ZpZGVyRmFjdG9yeSkge1xuICAgIGNvbnN0IGNvbXBvbmVudENvdW50ID0gdGhpcy5wcm92aWRlckZhY3RvcnkuY29tcG9uZW50UHJvdmlkZXJzITtcbiAgICBjb25zdCBtdWx0aVByb3ZpZGVycyA9XG4gICAgICAgIGdldE5vZGVJbmplY3RhYmxlKGxWaWV3LCBsVmlld1tUVklFV10sIHRoaXMucHJvdmlkZXJGYWN0b3J5IS5pbmRleCEsIHROb2RlKTtcbiAgICAvLyBDb3B5IHRoZSBzZWN0aW9uIG9mIHRoZSBhcnJheSB3aGljaCBjb250YWlucyBgbXVsdGlgIGBwcm92aWRlcnNgIGZyb20gdGhlIGNvbXBvbmVudFxuICAgIHJlc3VsdCA9IG11bHRpUHJvdmlkZXJzLnNsaWNlKDAsIGNvbXBvbmVudENvdW50KTtcbiAgICAvLyBJbnNlcnQgdGhlIGB2aWV3UHJvdmlkZXJgIGluc3RhbmNlcy5cbiAgICBtdWx0aVJlc29sdmUoZmFjdG9yaWVzLCByZXN1bHQpO1xuICAgIC8vIENvcHkgdGhlIHNlY3Rpb24gb2YgdGhlIGFycmF5IHdoaWNoIGNvbnRhaW5zIGBtdWx0aWAgYHByb3ZpZGVyc2AgZnJvbSBvdGhlciBkaXJlY3RpdmVzXG4gICAgZm9yIChsZXQgaSA9IGNvbXBvbmVudENvdW50OyBpIDwgbXVsdGlQcm92aWRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdC5wdXNoKG11bHRpUHJvdmlkZXJzW2ldKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmVzdWx0ID0gW107XG4gICAgLy8gSW5zZXJ0IHRoZSBgdmlld1Byb3ZpZGVyYCBpbnN0YW5jZXMuXG4gICAgbXVsdGlSZXNvbHZlKGZhY3RvcmllcywgcmVzdWx0KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIE1hcHMgYW4gYXJyYXkgb2YgZmFjdG9yaWVzIGludG8gYW4gYXJyYXkgb2YgdmFsdWVzLlxuICovXG5mdW5jdGlvbiBtdWx0aVJlc29sdmUoZmFjdG9yaWVzOiBBcnJheTwoKSA9PiBhbnk+LCByZXN1bHQ6IGFueVtdKTogYW55W10ge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGZhY3Rvcmllcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGZhY3RvcnkgPSBmYWN0b3JpZXNbaV0hIGFzICgpID0+IG51bGw7XG4gICAgcmVzdWx0LnB1c2goZmFjdG9yeSgpKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBtdWx0aSBmYWN0b3J5LlxuICovXG5mdW5jdGlvbiBtdWx0aUZhY3RvcnkoXG4gICAgZmFjdG9yeUZuOiAoXG4gICAgICAgIHRoaXM6IE5vZGVJbmplY3RvckZhY3RvcnksIF86IHVuZGVmaW5lZCwgdERhdGE6IFREYXRhLCBsRGF0YTogTFZpZXcsXG4gICAgICAgIHROb2RlOiBURGlyZWN0aXZlSG9zdE5vZGUpID0+IGFueSxcbiAgICBpbmRleDogbnVtYmVyLCBpc1ZpZXdQcm92aWRlcjogYm9vbGVhbiwgaXNDb21wb25lbnQ6IGJvb2xlYW4sXG4gICAgZjogKCkgPT4gYW55KTogTm9kZUluamVjdG9yRmFjdG9yeSB7XG4gIGNvbnN0IGZhY3RvcnkgPSBuZXcgTm9kZUluamVjdG9yRmFjdG9yeShmYWN0b3J5Rm4sIGlzVmlld1Byb3ZpZGVyLCDJtcm1ZGlyZWN0aXZlSW5qZWN0KTtcbiAgZmFjdG9yeS5tdWx0aSA9IFtdO1xuICBmYWN0b3J5LmluZGV4ID0gaW5kZXg7XG4gIGZhY3RvcnkuY29tcG9uZW50UHJvdmlkZXJzID0gMDtcbiAgbXVsdGlGYWN0b3J5QWRkKGZhY3RvcnksIGYsIGlzQ29tcG9uZW50ICYmICFpc1ZpZXdQcm92aWRlcik7XG4gIHJldHVybiBmYWN0b3J5O1xufVxuIl19