UNPKG

@angular/core

Version:

Angular - the core framework

163 lines 28.4 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 { validateMatchingNode, validateNodeExists } from '../../hydration/error_handling'; import { TEMPLATES } from '../../hydration/interfaces'; import { locateNextRNode, siblingAfter } from '../../hydration/node_lookup_utils'; import { calcSerializedContainerSize, isDisconnectedNode, markRNodeAsClaimedByHydration, setSegmentHead, } from '../../hydration/utils'; import { isDetachedByI18n } from '../../i18n/utils'; import { populateDehydratedViewsInLContainer } from '../../linker/view_container_ref'; import { assertEqual } from '../../util/assert'; import { assertFirstCreatePass } from '../assert'; import { attachPatchData } from '../context_discovery'; import { registerPostOrderHooks } from '../hooks'; import { isDirectiveHost } from '../interfaces/type_checks'; import { HEADER_OFFSET, HYDRATION, RENDERER } from '../interfaces/view'; import { appendChild } from '../node_manipulation'; import { getLView, getTView, isInSkipHydrationBlock, lastNodeWasCreated, setCurrentTNode, wasLastNodeCreated, } from '../state'; import { getConstant } from '../util/view_utils'; import { addToViewTree, createDirectivesInstances, createLContainer, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData, } from './shared'; function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrs, localRefsIndex) { ngDevMode && assertFirstCreatePass(tView); ngDevMode && ngDevMode.firstCreatePass++; const tViewConsts = tView.consts; // TODO(pk): refactor getOrCreateTNode to have the "create" only version const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, attrs || null); resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex)); registerPostOrderHooks(tView, tNode); const embeddedTView = (tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts, null /* ssrId */)); if (tView.queries !== null) { tView.queries.template(tView, tNode); embeddedTView.queries = tView.queries.embeddedTView(tNode); } return tNode; } /** * Creates an LContainer for an embedded view. * * @param declarationLView LView in which the template was declared. * @param declarationTView TView in which the template wa declared. * @param index The index of the container in the data array * @param templateFn Inline template * @param decls The number of nodes, local refs, and pipes for this template * @param vars The number of bindings for this template * @param tagName The name of the container element, if applicable * @param attrsIndex Index of template attributes in the `consts` array. * @param localRefs Index of the local references in the `consts` array. * @param localRefExtractor A function which extracts local-refs values from the template. * Defaults to the current element associated with the local-ref. */ export function declareTemplate(declarationLView, declarationTView, index, templateFn, decls, vars, tagName, attrs, localRefsIndex, localRefExtractor) { const adjustedIndex = index + HEADER_OFFSET; const tNode = declarationTView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, declarationTView, declarationLView, templateFn, decls, vars, tagName, attrs, localRefsIndex) : declarationTView.data[adjustedIndex]; setCurrentTNode(tNode, false); const comment = _locateOrCreateContainerAnchor(declarationTView, declarationLView, tNode, index); if (wasLastNodeCreated()) { appendChild(declarationTView, declarationLView, comment, tNode); } attachPatchData(comment, declarationLView); const lContainer = createLContainer(comment, declarationLView, comment, tNode); declarationLView[adjustedIndex] = lContainer; addToViewTree(declarationLView, lContainer); // If hydration is enabled, looks up dehydrated views in the DOM // using hydration annotation info and stores those views on LContainer. // In client-only mode, this function is a noop. populateDehydratedViewsInLContainer(lContainer, tNode, declarationLView); if (isDirectiveHost(tNode)) { createDirectivesInstances(declarationTView, declarationLView, tNode); } if (localRefsIndex != null) { saveResolvedLocalsInData(declarationLView, tNode, localRefExtractor); } return tNode; } /** * Creates an LContainer for an ng-template (dynamically-inserted view), e.g. * * <ng-template #foo> * <div></div> * </ng-template> * * @param index The index of the container in the data array * @param templateFn Inline template * @param decls The number of nodes, local refs, and pipes for this template * @param vars The number of bindings for this template * @param tagName The name of the container element, if applicable * @param attrsIndex Index of template attributes in the `consts` array. * @param localRefs Index of the local references in the `consts` array. * @param localRefExtractor A function which extracts local-refs values from the template. * Defaults to the current element associated with the local-ref. * * @codeGenApi */ export function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) { const lView = getLView(); const tView = getTView(); const attrs = getConstant(tView.consts, attrsIndex); declareTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, localRefsIndex, localRefExtractor); return ɵɵtemplate; } let _locateOrCreateContainerAnchor = createContainerAnchorImpl; /** * Regular creation mode for LContainers and their anchor (comment) nodes. */ function createContainerAnchorImpl(tView, lView, tNode, index) { lastNodeWasCreated(true); return lView[RENDERER].createComment(ngDevMode ? 'container' : ''); } /** * Enables hydration code path (to lookup existing elements in DOM) * in addition to the regular creation mode for LContainers and their * anchor (comment) nodes. */ function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) { const hydrationInfo = lView[HYDRATION]; const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock() || isDetachedByI18n(tNode) || isDisconnectedNode(hydrationInfo, index); lastNodeWasCreated(isNodeCreationMode); // Regular creation mode. if (isNodeCreationMode) { return createContainerAnchorImpl(tView, lView, tNode, index); } const ssrId = hydrationInfo.data[TEMPLATES]?.[index] ?? null; // Apply `ssrId` value to the underlying TView if it was not previously set. // // There might be situations when the same component is present in a template // multiple times and some instances are opted-out of using hydration via // `ngSkipHydration` attribute. In this scenario, at the time a TView is created, // the `ssrId` might be `null` (if the first component is opted-out of hydration). // The code below makes sure that the `ssrId` is applied to the TView if it's still // `null` and verifies we never try to override it with a different value. if (ssrId !== null && tNode.tView !== null) { if (tNode.tView.ssrId === null) { tNode.tView.ssrId = ssrId; } else { ngDevMode && assertEqual(tNode.tView.ssrId, ssrId, 'Unexpected value of the `ssrId` for this TView'); } } // Hydration mode, looking up existing elements in DOM. const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode); ngDevMode && validateNodeExists(currentRNode, lView, tNode); setSegmentHead(hydrationInfo, index, currentRNode); const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index); const comment = siblingAfter(viewContainerSize, currentRNode); if (ngDevMode) { validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode); markRNodeAsClaimedByHydration(comment); } return comment; } export function enableLocateOrCreateContainerAnchorImpl() { _locateOrCreateContainerAnchor = locateOrCreateContainerAnchorImpl; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXIzL2luc3RydWN0aW9ucy90ZW1wbGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFDSCxPQUFPLEVBQUMsb0JBQW9CLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN4RixPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDckQsT0FBTyxFQUFDLGVBQWUsRUFBRSxZQUFZLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQztBQUNoRixPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLGtCQUFrQixFQUNsQiw2QkFBNkIsRUFDN0IsY0FBYyxHQUNmLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDbEQsT0FBTyxFQUFDLG1DQUFtQyxFQUFDLE1BQU0saUNBQWlDLENBQUM7QUFDcEYsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUNoRCxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDckQsT0FBTyxFQUFDLHNCQUFzQixFQUFDLE1BQU0sVUFBVSxDQUFDO0FBSWhELE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEVBQUMsYUFBYSxFQUFFLFNBQVMsRUFBUyxRQUFRLEVBQW1CLE1BQU0sb0JBQW9CLENBQUM7QUFDL0YsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ2pELE9BQU8sRUFDTCxRQUFRLEVBQ1IsUUFBUSxFQUNSLHNCQUFzQixFQUN0QixrQkFBa0IsRUFDbEIsZUFBZSxFQUNmLGtCQUFr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QUssSUFBSSxFQUFFLENBQUM7UUFDM0MsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUMvQixLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQzthQUFNLENBQUM7WUFDTixTQUFTO2dCQUNQLFdBQVcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsZ0RBQWdELENBQUMsQ0FBQztRQUM1RixDQUFDO0lBQ0gsQ0FBQztJQUVELHVEQUF1RDtJQUN2RCxNQUFNLFlBQVksR0FBRyxlQUFlLENBQUMsYUFBYSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFFLENBQUM7SUFDMUUsU0FBUyxJQUFJLGtCQUFrQixDQUFDLFlBQVksRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFNUQsY0FBYyxDQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDbkQsTUFBTSxpQkFBaUIsR0FBRywyQkFBMkIsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDNUUsTUFBTSxPQUFPLEdBQUcsWUFBWSxDQUFXLGlCQUFpQixFQUFFLFlBQVksQ0FBRSxDQUFDO0lBRXpFLElBQUksU0FBUyxFQUFFLENBQUM7UUFDZCxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3JFLDZCQUE2QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQsTUFBTSxVQUFVLHVDQUF1QztJQUNyRCw4QkFBOEIsR0FBRyxpQ0FBaUMsQ0FBQztBQUNyRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5pbXBvcnQge3ZhbGlkYXRlTWF0Y2hpbmdOb2RlLCB2YWxpZGF0ZU5vZGVFeGlzdHN9IGZyb20gJy4uLy4uL2h5ZHJhdGlvbi9lcnJvcl9oYW5kbGluZyc7XG5pbXBvcnQge1RFTVBMQVRFU30gZnJvbSAnLi4vLi4vaHlkcmF0aW9uL2ludGVyZmFjZXMnO1xuaW1wb3J0IHtsb2NhdGVOZXh0Uk5vZGUsIHNpYmxpbmdBZnRlcn0gZnJvbSAnLi4vLi4vaHlkcmF0aW9uL25vZGVfbG9va3VwX3V0aWxzJztcbmltcG9ydCB7XG4gIGNhbGNTZXJpYWxpemVkQ29udGFpbmVyU2l6ZSxcbiAgaXNEaXNjb25uZWN0ZWROb2RlLFxuICBtYXJrUk5vZGVBc0NsYWltZWRCeUh5ZHJhdGlvbixcbiAgc2V0U2VnbWVudEhlYWQsXG59IGZyb20gJy4uLy4uL2h5ZHJhdGlvbi91dGlscyc7XG5pbXBvcnQge2lzRGV0YWNoZWRCeUkxOG59IGZyb20gJy4uLy4uL2kxOG4vdXRpbHMnO1xuaW1wb3J0IHtwb3B1bGF0ZURlaHlkcmF0ZWRWaWV3c0luTENvbnRhaW5lcn0gZnJvbSAnLi4vLi4vbGlua2VyL3ZpZXdfY29udGFpbmVyX3JlZic7XG5pbXBvcnQge2Fzc2VydEVxdWFsfSBmcm9tICcuLi8uLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQge2Fzc2VydEZpcnN0Q3JlYXRlUGFzc30gZnJvbSAnLi4vYXNzZXJ0JztcbmltcG9ydCB7YXR0YWNoUGF0Y2hEYXRhfSBmcm9tICcuLi9jb250ZXh0X2Rpc2NvdmVyeSc7XG5pbXBvcnQge3JlZ2lzdGVyUG9zdE9yZGVySG9va3N9IGZyb20gJy4uL2hvb2tzJztcbmltcG9ydCB7Q29tcG9uZW50VGVtcGxhdGV9IGZyb20gJy4uL2ludGVyZmFjZXMvZGVmaW5pdGlvbic7XG5pbXBvcnQge0xvY2FsUmVmRXh0cmFjdG9yLCBUQXR0cmlidXRlcywgVENvbnRhaW5lck5vZGUsIFROb2RlLCBUTm9kZVR5cGV9IGZyb20gJy4uL2ludGVyZmFjZXMvbm9kZSc7XG5pbXBvcnQge1JDb21tZW50fSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlbmRlcmVyX2RvbSc7XG5pbXBvcnQge2lzRGlyZWN0aXZlSG9zdH0gZnJvbSAnLi4vaW50ZXJmYWNlcy90eXBlX2NoZWNrcyc7XG5pbXBvcnQge0hFQURFUl9PRkZTRVQsIEhZRFJBVElPTiwgTFZpZXcsIFJFTkRFUkVSLCBUVmlldywgVFZpZXdUeXBlfSBmcm9tICcuLi9pbnRlcmZhY2VzL3ZpZXcnO1xuaW1wb3J0IHthcHBlbmRDaGlsZH0gZnJvbSAnLi4vbm9kZV9tYW5pcHVsYXRpb24nO1xuaW1wb3J0IHtcbiAgZ2V0TFZpZXcsXG4gIGdldFRWaWV3LFxuICBpc0luU2tpcEh5ZHJhdGlvbkJsb2NrLFxuICBsYXN0Tm9kZVdhc0NyZWF0ZWQsXG4gIHNldEN1cnJlbnRUTm9kZSxcbiAgd2FzTGFzdE5vZGVDcmVhdGVkLFxufSBmcm9tICcuLi9zdGF0ZSc7XG5pbXBvcnQge2dldENvbnN0YW50fSBmcm9tICcuLi91dGlsL3ZpZXdfdXRpbHMnO1xuXG5pbXBvcnQge1xuICBhZGRUb1ZpZXdUcmVlLFxuICBjcmVhdGVEaXJlY3RpdmVzSW5zdGFuY2VzLFxuICBjcmVhdGVMQ29udGFpbmVyLFxuICBjcmVhdGVUVmlldyxcbiAgZ2V0T3JDcmVhdGVUTm9kZSxcbiAgcmVzb2x2ZURpcmVjdGl2ZXMsXG4gIHNhdmVSZXNvbHZlZExvY2Fsc0luRGF0YSxcbn0gZnJvbSAnLi9zaGFyZWQnO1xuXG5mdW5jdGlvbiB0ZW1wbGF0ZUZpcnN0Q3JlYXRlUGFzcyhcbiAgaW5kZXg6IG51bWJlcixcbiAgdFZpZXc6IFRWaWV3LFxuICBsVmlldzogTFZpZXcsXG4gIHRlbXBsYXRlRm46IENvbXBvbmVudFRlbXBsYXRlPGFueT4gfCBudWxsLFxuICBkZWNsczogbnVtYmVyLFxuICB2YXJzOiBudW1iZXIsXG4gIHRhZ05hbWU/OiBzdHJpbmcgfCBudWxsLFxuICBhdHRycz86IFRBdHRyaWJ1dGVzIHwgbnVsbCxcbiAgbG9jYWxSZWZzSW5kZXg/OiBudW1iZXIgfCBudWxsLFxuKTogVENvbnRhaW5lck5vZGUge1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0Rmlyc3RDcmVhdGVQYXNzKHRWaWV3KTtcbiAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5maXJzdENyZWF0ZVBhc3MrKztcbiAgY29uc3QgdFZpZXdDb25zdHMgPSB0Vmlldy5jb25zdHM7XG5cbiAgLy8gVE9ETyhwayk6IHJlZmFjdG9yIGdldE9yQ3JlYXRlVE5vZGUgdG8gaGF2ZSB0aGUgXCJjcmVhdGVcIiBvbmx5IHZlcnNpb25cbiAgY29uc3QgdE5vZGUgPSBnZXRPckNyZWF0ZVROb2RlKHRWaWV3LCBpbmRleCwgVE5vZGVUeXBlLkNvbnRhaW5lciwgdGFnTmFtZSB8fCBudWxsLCBhdHRycyB8fCBudWxsKTtcblxuICByZXNvbHZlRGlyZWN0aXZlcyh0VmlldywgbFZpZXcsIHROb2RlLCBnZXRDb25zdGFudDxzdHJpbmdbXT4odFZpZXdDb25zdHMsIGxvY2FsUmVmc0luZGV4KSk7XG4gIHJlZ2lzdGVyUG9zdE9yZGVySG9va3ModFZpZXcsIHROb2RlKTtcblxuICBjb25zdCBlbWJlZGRlZFRWaWV3ID0gKHROb2RlLnRWaWV3ID0gY3JlYXRlVFZpZXcoXG4gICAgVFZpZXdUeXBlLkVtYmVkZGVkLFxuICAgIHROb2RlLFxuICAgIHRlbXBsYXRlRm4sXG4gICAgZGVjbHMsXG4gICAgdmFycyxcbiAgICB0Vmlldy5kaXJlY3RpdmVSZWdpc3RyeSxcbiAgICB0Vmlldy5waXBlUmVnaXN0cnksXG4gICAgbnVsbCxcbiAgICB0Vmlldy5zY2hlbWFzLFxuICAgIHRWaWV3Q29uc3RzLFxuICAgIG51bGwgLyogc3NySWQgKi8sXG4gICkpO1xuXG4gIGlmICh0Vmlldy5xdWVyaWVzICE9PSBudWxsKSB7XG4gICAgdFZpZXcucXVlcmllcy50ZW1wbGF0ZSh0VmlldywgdE5vZGUpO1xuICAgIGVtYmVkZGVkVFZpZXcucXVlcmllcyA9IHRWaWV3LnF1ZXJpZXMuZW1iZWRkZWRUVmlldyh0Tm9kZSk7XG4gIH1cblxuICByZXR1cm4gdE5vZGU7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBMQ29udGFpbmVyIGZvciBhbiBlbWJlZGRlZCB2aWV3LlxuICpcbiAqIEBwYXJhbSBkZWNsYXJhdGlvbkxWaWV3IExWaWV3IGluIHdoaWNoIHRoZSB0ZW1wbGF0ZSB3YXMgZGVjbGFyZWQuXG4gKiBAcGFyYW0gZGVjbGFyYXRpb25UVmlldyBUVmlldyBpbiB3aGljaCB0aGUgdGVtcGxhdGUgd2EgZGVjbGFyZWQuXG4gKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBjb250YWluZXIgaW4gdGhlIGRhdGEgYXJyYXlcbiAqIEBwYXJhbSB0ZW1wbGF0ZUZuIElubGluZSB0ZW1wbGF0ZVxuICogQHBhcmFtIGRlY2xzIFRoZSBudW1iZXIgb2Ygbm9kZXMsIGxvY2FsIHJlZnMsIGFuZCBwaXBlcyBmb3IgdGhpcyB0ZW1wbGF0ZVxuICogQHBhcmFtIHZhcnMgVGhlIG51bWJlciBvZiBiaW5kaW5ncyBmb3IgdGhpcyB0ZW1wbGF0ZVxuICogQHBhcmFtIHRhZ05hbWUgVGhlIG5hbWUgb2YgdGhlIGNvbnRhaW5lciBlbGVtZW50LCBpZiBhcHBsaWNhYmxlXG4gKiBAcGFyYW0gYXR0cnNJbmRleCBJbmRleCBvZiB0ZW1wbGF0ZSBhdHRyaWJ1dGVzIGluIHRoZSBgY29uc3RzYCBhcnJheS5cbiAqIEBwYXJhbSBsb2NhbFJlZnMgSW5kZXggb2YgdGhlIGxvY2FsIHJlZmVyZW5jZXMgaW4gdGhlIGBjb25zdHNgIGFycmF5LlxuICogQHBhcmFtIGxvY2FsUmVmRXh0cmFjdG9yIEEgZnVuY3Rpb24gd2hpY2ggZXh0cmFjdHMgbG9jYWwtcmVmcyB2YWx1ZXMgZnJvbSB0aGUgdGVtcGxhdGUuXG4gKiAgICAgICAgRGVmYXVsdHMgdG8gdGhlIGN1cnJlbnQgZWxlbWVudCBhc3NvY2lhdGVkIHdpdGggdGhlIGxvY2FsLXJlZi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY2xhcmVUZW1wbGF0ZShcbiAgZGVjbGFyYXRpb25MVmlldzogTFZpZXcsXG4gIGRlY2xhcmF0aW9uVFZpZXc6IFRWaWV3LFxuICBpbmRleDogbnVtYmVyLFxuICB0ZW1wbGF0ZUZuOiBDb21wb25lbnRUZW1wbGF0ZTxhbnk+IHwgbnVsbCxcbiAgZGVjbHM6IG51bWJlcixcbiAgdmFyczogbnVtYmVyLFxuICB0YWdOYW1lPzogc3RyaW5nIHwgbnVsbCxcbiAgYXR0cnM/OiBUQXR0cmlidXRlcyB8IG51bGwsXG4gIGxvY2FsUmVmc0luZGV4PzogbnVtYmVyIHwgbnVsbCxcbiAgbG9jYWxSZWZFeHRyYWN0b3I/OiBMb2NhbFJlZkV4dHJhY3Rvcixcbik6IFROb2RlIHtcbiAgY29uc3QgYWRqdXN0ZWRJbmRleCA9IGluZGV4ICsgSEVBREVSX09GRlNFVDtcbiAgY29uc3QgdE5vZGUgPSBkZWNsYXJhdGlvblRWaWV3LmZpcnN0Q3JlYXRlUGFzc1xuICAgID8gdGVtcGxhdGVGaXJzdENyZWF0ZVBhc3MoXG4gICAgICAgIGFkanVzdGVkSW5kZXgsXG4gICAgICAgIGRlY2xhcmF0aW9uVFZpZXcsXG4gICAgICAgIGRlY2xhcmF0aW9uTFZpZXcsXG4gICAgICAgIHRlbXBsYXRlRm4sXG4gICAgICAgIGRlY2xzLFxuICAgICAgICB2YXJzLFxuICAgICAgICB0YWdOYW1lLFxuICAgICAgICBhdHRycyxcbiAgICAgICAgbG9jYWxSZWZzSW5kZXgsXG4gICAgICApXG4gICAgOiAoZGVjbGFyYXRpb25UVmlldy5kYXRhW2FkanVzdGVkSW5kZXhdIGFzIFRDb250YWluZXJOb2RlKTtcbiAgc2V0Q3VycmVudFROb2RlKHROb2RlLCBmYWxzZSk7XG5cbiAgY29uc3QgY29tbWVudCA9IF9sb2NhdGVPckNyZWF0ZUNvbnRhaW5lckFuY2hvcihcbiAgICBkZWNsYXJhdGlvblRWaWV3LFxuICAgIGRlY2xhcmF0aW9uTFZpZXcsXG4gICAgdE5vZGUsXG4gICAgaW5kZXgsXG4gICkgYXMgUkNvbW1lbnQ7XG5cbiAgaWYgKHdhc0xhc3ROb2RlQ3JlYXRlZCgpKSB7XG4gICAgYXBwZW5kQ2hpbGQoZGVjbGFyYXRpb25UVmlldywgZGVjbGFyYXRpb25MVmlldywgY29tbWVudCwgdE5vZGUpO1xuICB9XG4gIGF0dGFjaFBhdGNoRGF0YShjb21tZW50LCBkZWNsYXJhdGlvbkxWaWV3KTtcblxuICBjb25zdCBsQ29udGFpbmVyID0gY3JlYXRlTENvbnRhaW5lcihjb21tZW50LCBkZWNsYXJhdGlvbkxWaWV3LCBjb21tZW50LCB0Tm9kZSk7XG4gIGRlY2xhcmF0aW9uTFZpZXdbYWRqdXN0ZWRJbmRleF0gPSBsQ29udGFpbmVyO1xuICBhZGRUb1ZpZXdUcmVlKGRlY2xhcmF0aW9uTFZpZXcsIGxDb250YWluZXIpO1xuXG4gIC8vIElmIGh5ZHJhdGlvbiBpcyBlbmFibGVkLCBsb29rcyB1cCBkZWh5ZHJhdGVkIHZpZXdzIGluIHRoZSBET01cbiAgLy8gdXNpbmcgaHlkcmF0aW9uIGFubm90YXRpb24gaW5mbyBhbmQgc3RvcmVzIHRob3NlIHZpZXdzIG9uIExDb250YWluZXIuXG4gIC8vIEluIGNsaWVudC1vbmx5IG1vZGUsIHRoaXMgZnVuY3Rpb24gaXMgYSBub29wLlxuICBwb3B1bGF0ZURlaHlkcmF0ZWRWaWV3c0luTENvbnRhaW5lcihsQ29udGFpbmVyLCB0Tm9kZSwgZGVjbGFyYXRpb25MVmlldyk7XG5cbiAgaWYgKGlzRGlyZWN0aXZlSG9zdCh0Tm9kZSkpIHtcbiAgICBjcmVhdGVEaXJlY3RpdmVzSW5zdGFuY2VzKGRlY2xhcmF0aW9uVFZpZXcsIGRlY2xhcmF0aW9uTFZpZXcsIHROb2RlKTtcbiAgfVxuXG4gIGlmIChsb2NhbFJlZnNJbmRleCAhPSBudWxsKSB7XG4gICAgc2F2ZVJlc29sdmVkTG9jYWxzSW5EYXRhKGRlY2xhcmF0aW9uTFZpZXcsIHROb2RlLCBsb2NhbFJlZkV4dHJhY3Rvcik7XG4gIH1cblxuICByZXR1cm4gdE5vZGU7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBMQ29udGFpbmVyIGZvciBhbiBuZy10ZW1wbGF0ZSAoZHluYW1pY2FsbHktaW5zZXJ0ZWQgdmlldyksIGUuZy5cbiAqXG4gKiA8bmctdGVtcGxhdGUgI2Zvbz5cbiAqICAgIDxkaXY+PC9kaXY+XG4gKiA8L25nLXRlbXBsYXRlPlxuICpcbiAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIGNvbnRhaW5lciBpbiB0aGUgZGF0YSBhcnJheVxuICogQHBhcmFtIHRlbXBsYXRlRm4gSW5saW5lIHRlbXBsYXRlXG4gKiBAcGFyYW0gZGVjbHMgVGhlIG51bWJlciBvZiBub2RlcywgbG9jYWwgcmVmcywgYW5kIHBpcGVzIGZvciB0aGlzIHRlbXBsYXRlXG4gKiBAcGFyYW0gdmFycyBUaGUgbnVtYmVyIG9mIGJpbmRpbmdzIGZvciB0aGlzIHRlbXBsYXRlXG4gKiBAcGFyYW0gdGFnTmFtZSBUaGUgbmFtZSBvZiB0aGUgY29udGFpbmVyIGVsZW1lbnQsIGlmIGFwcGxpY2FibGVcbiAqIEBwYXJhbSBhdHRyc0luZGV4IEluZGV4IG9mIHRlbXBsYXRlIGF0dHJpYnV0ZXMgaW4gdGhlIGBjb25zdHNgIGFycmF5LlxuICogQHBhcmFtIGxvY2FsUmVmcyBJbmRleCBvZiB0aGUgbG9jYWwgcmVmZXJlbmNlcyBpbiB0aGUgYGNvbnN0c2AgYXJyYXkuXG4gKiBAcGFyYW0gbG9jYWxSZWZFeHRyYWN0b3IgQSBmdW5jdGlvbiB3aGljaCBleHRyYWN0cyBsb2NhbC1yZWZzIHZhbHVlcyBmcm9tIHRoZSB0ZW1wbGF0ZS5cbiAqICAgICAgICBEZWZhdWx0cyB0byB0aGUgY3VycmVudCBlbGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgbG9jYWwtcmVmLlxuICpcbiAqIEBjb2RlR2VuQXBpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiDJtcm1dGVtcGxhdGUoXG4gIGluZGV4OiBudW1iZXIsXG4gIHRlbXBsYXRlRm46IENvbXBvbmVudFRlbXBsYXRlPGFueT4gfCBudWxsLFxuICBkZWNsczogbnVtYmVyLFxuICB2YXJzOiBudW1iZXIsXG4gIHRhZ05hbWU/OiBzdHJpbmcgfCBudWxsLFxuICBhdHRyc0luZGV4PzogbnVtYmVyIHwgbnVsbCxcbiAgbG9jYWxSZWZzSW5kZXg/OiBudW1iZXIgfCBudWxsLFxuICBsb2NhbFJlZkV4dHJhY3Rvcj86IExvY2FsUmVmRXh0cmFjdG9yLFxuKTogdHlwZW9mIMm1ybV0ZW1wbGF0ZSB7XG4gIGNvbnN0IGxWaWV3ID0gZ2V0TFZpZXcoKTtcbiAgY29uc3QgdFZpZXcgPSBnZXRUVmlldygpO1xuICBjb25zdCBhdHRycyA9IGdldENvbnN0YW50PFRBdHRyaWJ1dGVzPih0Vmlldy5jb25zdHMsIGF0dHJzSW5kZXgpO1xuICBkZWNsYXJlVGVtcGxhdGUoXG4gICAgbFZpZXcsXG4gICAgdFZpZXcsXG4gICAgaW5kZXgsXG4gICAgdGVtcGxhdGVGbixcbiAgICBkZWNscyxcbiAgICB2YXJzLFxuICAgIHRhZ05hbWUsXG4gICAgYXR0cnMsXG4gICAgbG9jYWxSZWZzSW5kZXgsXG4gICAgbG9jYWxSZWZFeHRyYWN0b3IsXG4gICk7XG4gIHJldHVybiDJtcm1dGVtcGxhdGU7XG59XG5cbmxldCBfbG9jYXRlT3JDcmVhdGVDb250YWluZXJBbmNob3IgPSBjcmVhdGVDb250YWluZXJBbmNob3JJbXBsO1xuXG4vKipcbiAqIFJlZ3VsYXIgY3JlYXRpb24gbW9kZSBmb3IgTENvbnRhaW5lcnMgYW5kIHRoZWlyIGFuY2hvciAoY29tbWVudCkgbm9kZXMuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUNvbnRhaW5lckFuY2hvckltcGwoXG4gIHRWaWV3OiBUVmlldyxcbiAgbFZpZXc6IExWaWV3LFxuICB0Tm9kZTogVE5vZGUsXG4gIGluZGV4OiBudW1iZXIsXG4pOiBSQ29tbWVudCB7XG4gIGxhc3ROb2RlV2FzQ3JlYXRlZCh0cnVlKTtcbiAgcmV0dXJuIGxWaWV3W1JFTkRFUkVSXS5jcmVhdGVDb21tZW50KG5nRGV2TW9kZSA/ICdjb250YWluZXInIDogJycpO1xufVxuXG4vKipcbiAqIEVuYWJsZXMgaHlkcmF0aW9uIGNvZGUgcGF0aCAodG8gbG9va3VwIGV4aXN0aW5nIGVsZW1lbnRzIGluIERPTSlcbiAqIGluIGFkZGl0aW9uIHRvIHRoZSByZWd1bGFyIGNyZWF0aW9uIG1vZGUgZm9yIExDb250YWluZXJzIGFuZCB0aGVpclxuICogYW5jaG9yIChjb21tZW50KSBub2Rlcy5cbiAqL1xuZnVuY3Rpb24gbG9jYXRlT3JDcmVhdGVDb250YWluZXJBbmNob3JJbXBsKFxuICB0VmlldzogVFZpZXcsXG4gIGxWaWV3OiBMVmlldyxcbiAgdE5vZGU6IFROb2RlLFxuICBpbmRleDogbnVtYmVyLFxuKTogUkNvbW1lbnQge1xuICBjb25zdCBoeWRyYXRpb25JbmZvID0gbFZpZXdbSFlEUkFUSU9OXTtcbiAgY29uc3QgaXNOb2RlQ3JlYXRpb25Nb2RlID1cbiAgICAhaHlkcmF0aW9uSW5mbyB8fFxuICAgIGlzSW5Ta2lwSHlkcmF0aW9uQmxvY2soKSB8fFxuICAgIGlzRGV0YWNoZWRCeUkxOG4odE5vZGUpIHx8XG4gICAgaXNEaXNjb25uZWN0ZWROb2RlKGh5ZHJhdGlvbkluZm8sIGluZGV4KTtcbiAgbGFzdE5vZGVXYXNDcmVhdGVkKGlzTm9kZUNyZWF0aW9uTW9kZSk7XG5cbiAgLy8gUmVndWxhciBjcmVhdGlvbiBtb2RlLlxuICBpZiAoaXNOb2RlQ3JlYXRpb25Nb2RlKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUNvbnRhaW5lckFuY2hvckltcGwodFZpZXcsIGxWaWV3LCB0Tm9kZSwgaW5kZXgpO1xuICB9XG5cbiAgY29uc3Qgc3NySWQgPSBoeWRyYXRpb25JbmZvLmRhdGFbVEVNUExBVEVTXT8uW2luZGV4XSA/PyBudWxsO1xuXG4gIC8vIEFwcGx5IGBzc3JJZGAgdmFsdWUgdG8gdGhlIHVuZGVybHlpbmcgVFZpZXcgaWYgaXQgd2FzIG5vdCBwcmV2aW91c2x5IHNldC5cbiAgLy9cbiAgLy8gVGhlcmUgbWlnaHQgYmUgc2l0dWF0aW9ucyB3aGVuIHRoZSBzYW1lIGNvbXBvbmVudCBpcyBwcmVzZW50IGluIGEgdGVtcGxhdGVcbiAgLy8gbXVsdGlwbGUgdGltZXMgYW5kIHNvbWUgaW5zdGFuY2VzIGFyZSBvcHRlZC1vdXQgb2YgdXNpbmcgaHlkcmF0aW9uIHZpYVxuICAvLyBgbmdTa2lwSHlkcmF0aW9uYCBhdHRyaWJ1dGUuIEluIHRoaXMgc2NlbmFyaW8sIGF0IHRoZSB0aW1lIGEgVFZpZXcgaXMgY3JlYXRlZCxcbiAgLy8gdGhlIGBzc3JJZGAgbWlnaHQgYmUgYG51bGxgIChpZiB0aGUgZmlyc3QgY29tcG9uZW50IGlzIG9wdGVkLW91dCBvZiBoeWRyYXRpb24pLlxuICAvLyBUaGUgY29kZSBiZWxvdyBtYWtlcyBzdXJlIHRoYXQgdGhlIGBzc3JJZGAgaXMgYXBwbGllZCB0byB0aGUgVFZpZXcgaWYgaXQncyBzdGlsbFxuICAvLyBgbnVsbGAgYW5kIHZlcmlmaWVzIHdlIG5ldmVyIHRyeSB0byBvdmVycmlkZSBpdCB3aXRoIGEgZGlmZmVyZW50IHZhbHVlLlxuICBpZiAoc3NySWQgIT09IG51bGwgJiYgdE5vZGUudFZpZXcgIT09IG51bGwpIHtcbiAgICBpZiAodE5vZGUudFZpZXcuc3NySWQgPT09IG51bGwpIHtcbiAgICAgIHROb2RlLnRWaWV3LnNzcklkID0gc3NySWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5nRGV2TW9kZSAmJlxuICAgICAgICBhc3NlcnRFcXVhbCh0Tm9kZS50Vmlldy5zc3JJZCwgc3NySWQsICdVbmV4cGVjdGVkIHZhbHVlIG9mIHRoZSBgc3NySWRgIGZvciB0aGlzIFRWaWV3Jyk7XG4gICAgfVxuICB9XG5cbiAgLy8gSHlkcmF0aW9uIG1vZGUsIGxvb2tpbmcgdXAgZXhpc3RpbmcgZWxlbWVudHMgaW4gRE9NLlxuICBjb25zdCBjdXJyZW50Uk5vZGUgPSBsb2NhdGVOZXh0Uk5vZGUoaHlkcmF0aW9uSW5mbywgdFZpZXcsIGxWaWV3LCB0Tm9kZSkhO1xuICBuZ0Rldk1vZGUgJiYgdmFsaWRhdGVOb2RlRXhpc3RzKGN1cnJlbnRSTm9kZSwgbFZpZXcsIHROb2RlKTtcblxuICBzZXRTZWdtZW50SGVhZChoeWRyYXRpb25JbmZvLCBpbmRleCwgY3VycmVudFJOb2RlKTtcbiAgY29uc3Qgdmlld0NvbnRhaW5lclNpemUgPSBjYWxjU2VyaWFsaXplZENvbnRhaW5lclNpemUoaHlkcmF0aW9uSW5mbywgaW5kZXgpO1xuICBjb25zdCBjb21tZW50ID0gc2libGluZ0FmdGVyPFJDb21tZW50Pih2aWV3Q29udGFpbmVyU2l6ZSwgY3VycmVudFJOb2RlKSE7XG5cbiAgaWYgKG5nRGV2TW9kZSkge1xuICAgIHZhbGlkYXRlTWF0Y2hpbmdOb2RlKGNvbW1lbnQsIE5vZGUuQ09NTUVOVF9OT0RFLCBudWxsLCBsVmlldywgdE5vZGUpO1xuICAgIG1hcmtSTm9kZUFzQ2xhaW1lZEJ5SHlkcmF0aW9uKGNvbW1lbnQpO1xuICB9XG5cbiAgcmV0dXJuIGNvbW1lbnQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmFibGVMb2NhdGVPckNyZWF0ZUNvbnRhaW5lckFuY2hvckltcGwoKSB7XG4gIF9sb2NhdGVPckNyZWF0ZUNvbnRhaW5lckFuY2hvciA9IGxvY2F0ZU9yQ3JlYXRlQ29udGFpbmVyQW5jaG9ySW1wbDtcbn1cbiJdfQ==