UNPKG

@angular/core

Version:

Angular - the core framework

277 lines • 36.8 kB
import { BINDING_INDEX, HEADER_OFFSET, HOST, RENDERER } from '../interfaces/view'; import { getActiveDirectiveId, getActiveDirectiveSuperClassDepth, getActiveDirectiveSuperClassHeight, getLView, getSelectedIndex } from '../state'; import { NO_CHANGE } from '../tokens'; import { renderStringify } from '../util/misc_utils'; import { getTNode, isStylingContext as isOldStylingContext } from '../util/view_utils'; import { applyClasses, applyStyles, registerBinding, updateClassBinding, updateStyleBinding } from './bindings'; import { activeStylingMapFeature, normalizeIntoStylingMap } from './map_based_bindings'; import { setCurrentStyleSanitizer } from './state'; import { attachStylingDebugObject } from './styling_debug'; import { allocTStylingContext, getCurrentOrLViewSanitizer, hasValueChanged, updateContextDirectiveIndex } from './util'; /** * -------- * * This file contains the core logic for how styling instructions are processed in Angular. * * To learn more about the algorithm see `TStylingContext`. * * -------- */ /** * Temporary function to bridge styling functionality between this new * refactor (which is here inside of `styling_next/`) and the old * implementation (which lives inside of `styling/`). * * This function is executed during the creation block of an element. * Because the existing styling implementation issues a call to the * `styling()` instruction, this instruction will also get run. The * central idea here is that the directive index values are bound * into the context. The directive index is temporary and is only * required until the `select(n)` instruction is fully functional. */ export function stylingInit() { var lView = getLView(); var index = getSelectedIndex(); var tNode = getTNode(index, lView); updateLastDirectiveIndex(tNode, getActiveDirectiveStylingIndex()); } /** * Sets the current style sanitizer function which will then be used * within all follow-up prop and map-based style binding instructions * for the given element. * * Note that once styling has been applied to the element (i.e. once * `select(n)` is executed or the hostBindings/template function exits) * then the active `sanitizerFn` will be set to `null`. This means that * once styling is applied to another element then a another call to * `styleSanitizer` will need to be made. * * @param sanitizerFn The sanitization function that will be used to * process style prop/value entries. * * @codeGenApi */ export function styleSanitizer(sanitizer) { setCurrentStyleSanitizer(sanitizer); } /** * Mirror implementation of the `styleProp()` instruction (found in `instructions/styling.ts`). */ export function styleProp(prop, value, suffix) { _stylingProp(prop, resolveStylePropValue(value, suffix), false); } /** * Mirror implementation of the `classProp()` instruction (found in `instructions/styling.ts`). */ export function classProp(className, value) { _stylingProp(className, value, true); } /** * Shared function used to update a prop-based styling binding for an element. */ function _stylingProp(prop, value, isClassBased) { var index = getSelectedIndex(); var lView = getLView(); var bindingIndex = lView[BINDING_INDEX]++; var tNode = getTNode(index, lView); var defer = getActiveDirectiveSuperClassHeight() > 0; if (isClassBased) { updateClassBinding(getClassesContext(tNode), lView, prop, bindingIndex, value, defer, false); } else { var sanitizer = getCurrentOrLViewSanitizer(lView); updateStyleBinding(getStylesContext(tNode), lView, prop, bindingIndex, value, sanitizer, defer, false); } } /** * Mirror implementation of the `styleMap()` instruction (found in `instructions/styling.ts`). */ export function styleMap(styles) { _stylingMap(styles, false); } /** * Mirror implementation of the `classMap()` instruction (found in `instructions/styling.ts`). */ export function classMap(classes) { _stylingMap(classes, true); } /** * Shared function used to update a map-based styling binding for an element. * * When this function is called it will activate support for `[style]` and * `[class]` bindings in Angular. */ function _stylingMap(value, isClassBased) { activeStylingMapFeature(); var index = getSelectedIndex(); var lView = getLView(); var bindingIndex = lView[BINDING_INDEX]++; if (value !== NO_CHANGE) { var tNode = getTNode(index, lView); var defer = getActiveDirectiveSuperClassHeight() > 0; var oldValue = lView[bindingIndex]; var valueHasChanged = hasValueChanged(oldValue, value); var lStylingMap = normalizeIntoStylingMap(oldValue, value); if (isClassBased) { updateClassBinding(getClassesContext(tNode), lView, null, bindingIndex, lStylingMap, defer, valueHasChanged); } else { var sanitizer = getCurrentOrLViewSanitizer(lView); updateStyleBinding(getStylesContext(tNode), lView, null, bindingIndex, lStylingMap, sanitizer, defer, valueHasChanged); } } } /** * Temporary function to bridge styling functionality between this new * refactor (which is here inside of `styling_next/`) and the old * implementation (which lives inside of `styling/`). * * The new styling refactor ensures that styling flushing is called * automatically when a template function exits or a follow-up element * is visited (i.e. when `select(n)` is called). Because the `select(n)` * instruction is not fully implemented yet (it doesn't actually execute * host binding instruction code at the right time), this means that a * styling apply function is still needed. * * This function is a mirror implementation of the `stylingApply()` * instruction (found in `instructions/styling.ts`). */ export function stylingApply() { var index = getSelectedIndex(); var lView = getLView(); var tNode = getTNode(index, lView); var renderer = getRenderer(tNode, lView); var native = getNativeFromLView(index, lView); var directiveIndex = getActiveDirectiveStylingIndex(); applyClasses(renderer, lView, getClassesContext(tNode), native, directiveIndex); var sanitizer = getCurrentOrLViewSanitizer(lView); applyStyles(renderer, lView, getStylesContext(tNode), native, directiveIndex, sanitizer); setCurrentStyleSanitizer(null); } /** * Temporary function to bridge styling functionality between this new * refactor (which is here inside of `styling_next/`) and the old * implementation (which lives inside of `styling/`). * * The purpose of this function is to traverse through the LView data * for a specific element index and return the native node. Because the * current implementation relies on there being a styling context array, * the code below will need to loop through these array values until it * gets a native element node. * * Note that this code is temporary and will disappear once the new * styling refactor lands in its entirety. */ function getNativeFromLView(index, viewData) { var storageIndex = index + HEADER_OFFSET; var slotValue = viewData[storageIndex]; var wrapper = viewData; while (Array.isArray(slotValue)) { wrapper = slotValue; slotValue = slotValue[HOST]; } if (isOldStylingContext(wrapper)) { return wrapper[0 /* ElementPosition */]; } else { return slotValue; } } function getRenderer(tNode, lView) { return tNode.type === 3 /* Element */ ? lView[RENDERER] : null; } /** * Searches and assigns provided all static style/class entries (found in the `attrs` value) * and registers them in their respective styling contexts. */ export function registerInitialStylingIntoContext(tNode, attrs, startIndex) { var classesContext; var stylesContext; var mode = -1; for (var i = startIndex; i < attrs.length; i++) { var attr = attrs[i]; if (typeof attr == 'number') { mode = attr; } else if (mode == 1 /* Classes */) { classesContext = classesContext || getClassesContext(tNode); registerBinding(classesContext, -1, attr, true, false); } else if (mode == 2 /* Styles */) { stylesContext = stylesContext || getStylesContext(tNode); registerBinding(stylesContext, -1, attr, attrs[++i], false); } } } /** * Mirror implementation of the same function found in `instructions/styling.ts`. */ export function getActiveDirectiveStylingIndex() { // whenever a directive's hostBindings function is called a uniqueId value // is assigned. Normally this is enough to help distinguish one directive // from another for the styling context, but there are situations where a // sub-class directive could inherit and assign styling in concert with a // parent directive. To help the styling code distinguish between a parent // sub-classed directive the inheritance depth is taken into account as well. return getActiveDirectiveId() + getActiveDirectiveSuperClassDepth(); } /** * Temporary function that will update the max directive index value in * both the classes and styles contexts present on the provided `tNode`. * * This code is only used because the `select(n)` code functionality is not * yet 100% functional. The `select(n)` instruction cannot yet evaluate host * bindings function code in sync with the associated template function code. * For this reason the styling algorithm needs to track the last directive index * value so that it knows exactly when to render styling to the element since * `stylingApply()` is called multiple times per CD (`stylingApply` will be * removed once `select(n)` is fixed). */ function updateLastDirectiveIndex(tNode, directiveIndex) { updateContextDirectiveIndex(getClassesContext(tNode), directiveIndex); updateContextDirectiveIndex(getStylesContext(tNode), directiveIndex); } function getStylesContext(tNode) { return getContext(tNode, false); } function getClassesContext(tNode) { return getContext(tNode, true); } /** * Returns/instantiates a styling context from/to a `tNode` instance. */ function getContext(tNode, isClassBased) { var context = isClassBased ? tNode.newClasses : tNode.newStyles; if (!context) { context = allocTStylingContext(); if (ngDevMode) { attachStylingDebugObject(context); } if (isClassBased) { tNode.newClasses = context; } else { tNode.newStyles = context; } } return context; } function resolveStylePropValue(value, suffix) { var resolvedValue = null; if (value !== null) { if (suffix) { // when a suffix is applied then it will bypass // sanitization entirely (b/c a new string is created) resolvedValue = renderStringify(value) + suffix; } else { // sanitization happens by dealing with a String value // this means that the string value will be passed through // into the style rendering later (which is where the value // will be sanitized before it is applied) resolvedValue = value; } } return resolvedValue; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdHJ1Y3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zcmMvcmVuZGVyMy9zdHlsaW5nX25leHQvaW5zdHJ1Y3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWFBLE9BQU8sRUFBQyxhQUFhLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBUyxRQUFRLEVBQVksTUFBTSxvQkFBb0IsQ0FBQztBQUNsRyxPQUFPLEVBQUMsb0JBQW9CLEVBQUUsaUNBQWlDLEVBQUUsa0NBQWtDLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQ2pKLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQ25ELE9BQU8sRUFBQyxRQUFRLEVBQUUsZ0JBQWdCLElBQUksbUJBQW1CLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRixPQUFPLEVBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFFOUcsT0FBTyxFQUFDLHVCQUF1QixFQUFFLHVCQUF1QixFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDdEYsT0FBTyxFQUEyQix3QkFBd0IsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUMzRSxPQUFPLEVBQUMsd0JBQXdCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RCxPQUFPLEVBQUMsb0JBQW9CLEVBQUUsMEJBQTBCLEVBQUUsZUFBZSxFQUFFLDJCQUEyQixFQUFDLE1BQU0sUUFBUSxDQUFDO0FBSXRIOzs7Ozs7OztHQVFHO0FBRUg7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLFVBQVUsV0FBVztJQUN6QixJQUFNLEtBQUssR0FBRyxRQUFRLEVBQUUsQ0FBQztJQUN6QixJ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Q0FBQyxDQUFDO0FBQ2pDLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsVUFBVSxDQUFDLEtBQVksRUFBRSxZQUFxQjtJQUNyRCxJQUFJLE9BQU8sR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7SUFDaEUsSUFBSSxDQUFDLE9BQU8sRUFBRTtRQUNaLE9BQU8sR0FBRyxvQkFBb0IsRUFBRSxDQUFDO1FBQ2pDLElBQUksU0FBUyxFQUFFO1lBQ2Isd0JBQXdCLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDbkM7UUFDRCxJQUFJLFlBQVksRUFBRTtZQUNoQixLQUFLLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQztTQUM1QjthQUFNO1lBQ0wsS0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUM7U0FDM0I7S0FDRjtJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxTQUFTLHFCQUFxQixDQUMxQixLQUFzQyxFQUFFLE1BQWlDO0lBQzNFLElBQUksYUFBYSxHQUFnQixJQUFJLENBQUM7SUFDdEMsSUFBSSxLQUFLLEtBQUssSUFBSSxFQUFFO1FBQ2xCLElBQUksTUFBTSxFQUFFO1lBQ1YsK0NBQStDO1lBQy9DLHNEQUFzRDtZQUN0RCxhQUFhLEdBQUcsZUFBZSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sQ0FBQztTQUNqRDthQUFNO1lBQ0wsc0RBQXNEO1lBQ3RELDBEQUEwRDtZQUMxRCwyREFBMkQ7WUFDM0QsMENBQTBDO1lBQzFDLGFBQWEsR0FBRyxLQUFzQixDQUFDO1NBQ3hDO0tBQ0Y7SUFDRCxPQUFPLGFBQWEsQ0FBQztBQUN2QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4qIEBsaWNlbnNlXG4qIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuKlxuKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4qL1xuaW1wb3J0IHtTYW5pdGl6ZXJ9IGZyb20gJy4uLy4uL3Nhbml0aXphdGlvbi9zZWN1cml0eSc7XG5pbXBvcnQge1N0eWxlU2FuaXRpemVGbn0gZnJvbSAnLi4vLi4vc2FuaXRpemF0aW9uL3N0eWxlX3Nhbml0aXplcic7XG5pbXBvcnQge0xDb250YWluZXJ9IGZyb20gJy4uL2ludGVyZmFjZXMvY29udGFpbmVyJztcbmltcG9ydCB7QXR0cmlidXRlTWFya2VyLCBUQXR0cmlidXRlcywgVE5vZGUsIFROb2RlVHlwZX0gZnJvbSAnLi4vaW50ZXJmYWNlcy9ub2RlJztcbmltcG9ydCB7UkVsZW1lbnR9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVuZGVyZXInO1xuaW1wb3J0IHtTdHlsaW5nQ29udGV4dCBhcyBPbGRTdHlsaW5nQ29udGV4dCwgU3R5bGluZ0luZGV4IGFzIE9sZFN0eWxpbmdJbmRleH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9zdHlsaW5nJztcbmltcG9ydCB7QklORElOR19JTkRFWCwgSEVBREVSX09GRlNFVCwgSE9TVCwgTFZpZXcsIFJFTkRFUkVSLCBTQU5JVElaRVJ9IGZyb20gJy4uL2ludGVyZmFjZXMvdmlldyc7XG5pbXBvcnQge2dldEFjdGl2ZURpcmVjdGl2ZUlkLCBnZXRBY3RpdmVEaXJlY3RpdmVTdXBlckNsYXNzRGVwdGgsIGdldEFjdGl2ZURpcmVjdGl2ZVN1cGVyQ2xhc3NIZWlnaHQsIGdldExWaWV3LCBnZXRTZWxlY3RlZEluZGV4fSBmcm9tICcuLi9zdGF0ZSc7XG5pbXBvcnQge05PX0NIQU5HRX0gZnJvbSAnLi4vdG9rZW5zJztcbmltcG9ydCB7cmVuZGVyU3RyaW5naWZ5fSBmcm9tICcuLi91dGlsL21pc2NfdXRpbHMnO1xuaW1wb3J0IHtnZXRUTm9kZSwgaXNTdHlsaW5nQ29udGV4dCBhcyBpc09sZFN0eWxpbmdDb250ZXh0fSBmcm9tICcuLi91dGlsL3ZpZXdfdXRpbHMnO1xuXG5pbXBvcnQge2FwcGx5Q2xhc3NlcywgYXBwbHlTdHlsZXMsIHJlZ2lzdGVyQmluZGluZywgdXBkYXRlQ2xhc3NCaW5kaW5nLCB1cGRhdGVTdHlsZUJpbmRpbmd9IGZyb20gJy4vYmluZGluZ3MnO1xuaW1wb3J0IHtUU3R5bGluZ0NvbnRleHR9IGZyb20gJy4vaW50ZXJmYWNlcyc7XG5pbXBvcnQge2FjdGl2ZVN0eWxpbmdNYXBGZWF0dXJlLCBub3JtYWxpemVJbnRvU3R5bGluZ01hcH0gZnJvbSAnLi9tYXBfYmFzZWRfYmluZGluZ3MnO1xuaW1wb3J0IHtnZXRDdXJyZW50U3R5bGVTYW5pdGl6ZXIsIHNldEN1cnJlbnRTdHlsZVNhbml0aXplcn0gZnJvbSAnLi9zdGF0ZSc7XG5pbXBvcnQge2F0dGFjaFN0eWxpbmdEZWJ1Z09iamVjdH0gZnJvbSAnLi9zdHlsaW5nX2RlYnVnJztcbmltcG9ydCB7YWxsb2NUU3R5bGluZ0NvbnRleHQsIGdldEN1cnJlbnRPckxWaWV3U2FuaXRpemVyLCBoYXNWYWx1ZUNoYW5nZWQsIHVwZGF0ZUNvbnRleHREaXJlY3RpdmVJbmRleH0gZnJvbSAnLi91dGlsJztcblxuXG5cbi8qKlxuICogLS0tLS0tLS1cbiAqXG4gKiBUaGlzIGZpbGUgY29udGFpbnMgdGhlIGNvcmUgbG9naWMgZm9yIGhvdyBzdHlsaW5nIGluc3RydWN0aW9ucyBhcmUgcHJvY2Vzc2VkIGluIEFuZ3VsYXIuXG4gKlxuICogVG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgYWxnb3JpdGhtIHNlZSBgVFN0eWxpbmdDb250ZXh0YC5cbiAqXG4gKiAtLS0tLS0tLVxuICovXG5cbi8qKlxuICogVGVtcG9yYXJ5IGZ1bmN0aW9uIHRvIGJyaWRnZSBzdHlsaW5nIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB0aGlzIG5ld1xuICogcmVmYWN0b3IgKHdoaWNoIGlzIGhlcmUgaW5zaWRlIG9mIGBzdHlsaW5nX25leHQvYCkgYW5kIHRoZSBvbGRcbiAqIGltcGxlbWVudGF0aW9uICh3aGljaCBsaXZlcyBpbnNpZGUgb2YgYHN0eWxpbmcvYCkuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBleGVjdXRlZCBkdXJpbmcgdGhlIGNyZWF0aW9uIGJsb2NrIG9mIGFuIGVsZW1lbnQuXG4gKiBCZWNhdXNlIHRoZSBleGlzdGluZyBzdHlsaW5nIGltcGxlbWVudGF0aW9uIGlzc3VlcyBhIGNhbGwgdG8gdGhlXG4gKiBgc3R5bGluZygpYCBpbnN0cnVjdGlvbiwgdGhpcyBpbnN0cnVjdGlvbiB3aWxsIGFsc28gZ2V0IHJ1bi4gVGhlXG4gKiBjZW50cmFsIGlkZWEgaGVyZSBpcyB0aGF0IHRoZSBkaXJlY3RpdmUgaW5kZXggdmFsdWVzIGFyZSBib3VuZFxuICogaW50byB0aGUgY29udGV4dC4gVGhlIGRpcmVjdGl2ZSBpbmRleCBpcyB0ZW1wb3JhcnkgYW5kIGlzIG9ubHlcbiAqIHJlcXVpcmVkIHVudGlsIHRoZSBgc2VsZWN0KG4pYCBpbnN0cnVjdGlvbiBpcyBmdWxseSBmdW5jdGlvbmFsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3R5bGluZ0luaXQoKSB7XG4gIGNvbnN0IGxWaWV3ID0gZ2V0TFZpZXcoKTtcbiAgY29uc3QgaW5kZXggPSBnZXRTZWxlY3RlZEluZGV4KCk7XG4gIGNvbnN0IHROb2RlID0gZ2V0VE5vZGUoaW5kZXgsIGxWaWV3KTtcbiAgdXBkYXRlTGFzdERpcmVjdGl2ZUluZGV4KHROb2RlLCBnZXRBY3RpdmVEaXJlY3RpdmVTdHlsaW5nSW5kZXgoKSk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgY3VycmVudCBzdHlsZSBzYW5pdGl6ZXIgZnVuY3Rpb24gd2hpY2ggd2lsbCB0aGVuIGJlIHVzZWRcbiAqIHdpdGhpbiBhbGwgZm9sbG93LXVwIHByb3AgYW5kIG1hcC1iYXNlZCBzdHlsZSBiaW5kaW5nIGluc3RydWN0aW9uc1xuICogZm9yIHRoZSBnaXZlbiBlbGVtZW50LlxuICpcbiAqIE5vdGUgdGhhdCBvbmNlIHN0eWxpbmcgaGFzIGJlZW4gYXBwbGllZCB0byB0aGUgZWxlbWVudCAoaS5lLiBvbmNlXG4gKiBgc2VsZWN0KG4pYCBpcyBleGVjdXRlZCBvciB0aGUgaG9zdEJpbmRpbmdzL3RlbXBsYXRlIGZ1bmN0aW9uIGV4aXRzKVxuICogdGhlbiB0aGUgYWN0aXZlIGBzYW5pdGl6ZXJGbmAgd2lsbCBiZSBzZXQgdG8gYG51bGxgLiBUaGlzIG1lYW5zIHRoYXRcbiAqIG9uY2Ugc3R5bGluZyBpcyBhcHBsaWVkIHRvIGFub3RoZXIgZWxlbWVudCB0aGVuIGEgYW5vdGhlciBjYWxsIHRvXG4gKiBgc3R5bGVTYW5pdGl6ZXJgIHdpbGwgbmVlZCB0byBiZSBtYWRlLlxuICpcbiAqIEBwYXJhbSBzYW5pdGl6ZXJGbiBUaGUgc2FuaXRpemF0aW9uIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSB1c2VkIHRvXG4gKiAgICAgICBwcm9jZXNzIHN0eWxlIHByb3AvdmFsdWUgZW50cmllcy5cbiAqXG4gKiBAY29kZUdlbkFwaVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3R5bGVTYW5pdGl6ZXIoc2FuaXRpemVyOiBTYW5pdGl6ZXIgfCBTdHlsZVNhbml0aXplRm4gfCBudWxsKTogdm9pZCB7XG4gIHNldEN1cnJlbnRTdHlsZVNhbml0aXplcihzYW5pdGl6ZXIpO1xufVxuXG4vKipcbiAqIE1pcnJvciBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgYHN0eWxlUHJvcCgpYCBpbnN0cnVjdGlvbiAoZm91bmQgaW4gYGluc3RydWN0aW9ucy9zdHlsaW5nLnRzYCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHlsZVByb3AoXG4gICAgcHJvcDogc3RyaW5nLCB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgU3RyaW5nIHwgbnVsbCwgc3VmZml4Pzogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICBfc3R5bGluZ1Byb3AocHJvcCwgcmVzb2x2ZVN0eWxlUHJvcFZhbHVlKHZhbHVlLCBzdWZmaXgpLCBmYWxzZSk7XG59XG5cbi8qKlxuICogTWlycm9yIGltcGxlbWVudGF0aW9uIG9mIHRoZSBgY2xhc3NQcm9wKClgIGluc3RydWN0aW9uIChmb3VuZCBpbiBgaW5zdHJ1Y3Rpb25zL3N0eWxpbmcudHNgKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYXNzUHJvcChjbGFzc05hbWU6IHN0cmluZywgdmFsdWU6IGJvb2xlYW4gfCBudWxsKTogdm9pZCB7XG4gIF9zdHlsaW5nUHJvcChjbGFzc05hbWUsIHZhbHVlLCB0cnVlKTtcbn1cblxuLyoqXG4gKiBTaGFyZWQgZnVuY3Rpb24gdXNlZCB0byB1cGRhdGUgYSBwcm9wLWJhc2VkIHN0eWxpbmcgYmluZGluZyBmb3IgYW4gZWxlbWVudC5cbiAqL1xuZnVuY3Rpb24gX3N0eWxpbmdQcm9wKFxuICAgIHByb3A6IHN0cmluZywgdmFsdWU6IGJvb2xlYW4gfCBudW1iZXIgfCBTdHJpbmcgfCBzdHJpbmcgfCBudWxsLCBpc0NsYXNzQmFzZWQ6IGJvb2xlYW4pIHtcbiAgY29uc3QgaW5kZXggPSBnZXRTZWxlY3RlZEluZGV4KCk7XG4gIGNvbnN0IGxWaWV3ID0gZ2V0TFZpZXcoKTtcbiAgY29uc3QgYmluZGluZ0luZGV4ID0gbFZpZXdbQklORElOR19JTkRFWF0rKztcbiAgY29uc3QgdE5vZGUgPSBnZXRUTm9kZShpbmRleCwgbFZpZXcpO1xuICBjb25zdCBkZWZlciA9IGdldEFjdGl2ZURpcmVjdGl2ZVN1cGVyQ2xhc3NIZWlnaHQoKSA+IDA7XG4gIGlmIChpc0NsYXNzQmFzZWQpIHtcbiAgICB1cGRhdGVDbGFzc0JpbmRpbmcoXG4gICAgICAgIGdldENsYXNzZXNDb250ZXh0KHROb2RlKSwgbFZpZXcsIHByb3AsIGJpbmRpbmdJbmRleCwgdmFsdWUgYXMgc3RyaW5nIHwgYm9vbGVhbiB8IG51bGwsXG4gICAgICAgIGRlZmVyLCBmYWxzZSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgc2FuaXRpemVyID0gZ2V0Q3VycmVudE9yTFZpZXdTYW5pdGl6ZXIobFZpZXcpO1xuICAgIHVwZGF0ZVN0eWxlQmluZGluZyhcbiAgICAgICAgZ2V0U3R5bGVzQ29udGV4dCh0Tm9kZSksIGxWaWV3LCBwcm9wLCBiaW5kaW5nSW5kZXgsIHZhbHVlIGFzIHN0cmluZyB8IG51bGwsIHNhbml0aXplcixcbiAgICAgICAgZGVmZXIsIGZhbHNlKTtcbiAgfVxufVxuXG4vKipcbiAqIE1pcnJvciBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgYHN0eWxlTWFwKClgIGluc3RydWN0aW9uIChmb3VuZCBpbiBgaW5zdHJ1Y3Rpb25zL3N0eWxpbmcudHNgKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0eWxlTWFwKHN0eWxlczoge1tzdHlsZU5hbWU6IHN0cmluZ106IGFueX0gfCBOT19DSEFOR0UgfCBudWxsKTogdm9pZCB7XG4gIF9zdHlsaW5nTWFwKHN0eWxlcywgZmFsc2UpO1xufVxuXG4vKipcbiAqIE1pcnJvciBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgYGNsYXNzTWFwKClgIGluc3RydWN0aW9uIChmb3VuZCBpbiBgaW5zdHJ1Y3Rpb25zL3N0eWxpbmcudHNgKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYXNzTWFwKGNsYXNzZXM6IHtbY2xhc3NOYW1lOiBzdHJpbmddOiBhbnl9IHwgTk9fQ0hBTkdFIHwgc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICBfc3R5bGluZ01hcChjbGFzc2VzLCB0cnVlKTtcbn1cblxuLyoqXG4gKiBTaGFyZWQgZnVuY3Rpb24gdXNlZCB0byB1cGRhdGUgYSBtYXAtYmFzZWQgc3R5bGluZyBiaW5kaW5nIGZvciBhbiBlbGVtZW50LlxuICpcbiAqIFdoZW4gdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgaXQgd2lsbCBhY3RpdmF0ZSBzdXBwb3J0IGZvciBgW3N0eWxlXWAgYW5kXG4gKiBgW2NsYXNzXWAgYmluZGluZ3MgaW4gQW5ndWxhci5cbiAqL1xuZnVuY3Rpb24gX3N0eWxpbmdNYXAodmFsdWU6IHtba2V5OiBzdHJpbmddOiBhbnl9IHwgc3RyaW5nIHwgbnVsbCwgaXNDbGFzc0Jhc2VkOiBib29sZWFuKSB7XG4gIGFjdGl2ZVN0eWxpbmdNYXBGZWF0dXJlKCk7XG4gIGNvbnN0IGluZGV4ID0gZ2V0U2VsZWN0ZWRJbmRleCgpO1xuICBjb25zdCBsVmlldyA9IGdldExWaWV3KCk7XG4gIGNvbnN0IGJpbmRpbmdJbmRleCA9IGxWaWV3W0JJTkRJTkdfSU5ERVhdKys7XG5cbiAgaWYgKHZhbHVlICE9PSBOT19DSEFOR0UpIHtcbiAgICBjb25zdCB0Tm9kZSA9IGdldFROb2RlKGluZGV4LCBsVmlldyk7XG4gICAgY29uc3QgZGVmZXIgPSBnZXRBY3RpdmVEaXJlY3RpdmVTdXBlckNsYXNzSGVpZ2h0KCkgPiAwO1xuICAgIGNvbnN0IG9sZFZhbHVlID0gbFZpZXdbYmluZGluZ0luZGV4XTtcbiAgICBjb25zdCB2YWx1ZUhhc0NoYW5nZWQgPSBoYXNWYWx1ZUNoYW5nZWQob2xkVmFsdWUsIHZhbHVlKTtcbiAgICBjb25zdCBsU3R5bGluZ01hcCA9IG5vcm1hbGl6ZUludG9TdHlsaW5nTWFwKG9sZFZhbHVlLCB2YWx1ZSk7XG4gICAgaWYgKGlzQ2xhc3NCYXNlZCkge1xuICAgICAgdXBkYXRlQ2xhc3NCaW5kaW5nKFxuICAgICAgICAgIGdldENsYXNzZXNDb250ZXh0KHROb2RlKSwgbFZpZXcsIG51bGwsIGJpbmRpbmdJbmRleCwgbFN0eWxpbmdNYXAsIGRlZmVyLCB2YWx1ZUhhc0NoYW5nZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzYW5pdGl6ZXIgPSBnZXRDdXJyZW50T3JMVmlld1Nhbml0aXplcihsVmlldyk7XG4gICAgICB1cGRhdGVTdHlsZUJpbmRpbmcoXG4gICAgICAgICAgZ2V0U3R5bGVzQ29udGV4dCh0Tm9kZSksIGxWaWV3LCBudWxsLCBiaW5kaW5nSW5kZXgsIGxTdHlsaW5nTWFwLCBzYW5pdGl6ZXIsIGRlZmVyLFxuICAgICAgICAgIHZhbHVlSGFzQ2hhbmdlZCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVGVtcG9yYXJ5IGZ1bmN0aW9uIHRvIGJyaWRnZSBzdHlsaW5nIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB0aGlzIG5ld1xuICogcmVmYWN0b3IgKHdoaWNoIGlzIGhlcmUgaW5zaWRlIG9mIGBzdHlsaW5nX25leHQvYCkgYW5kIHRoZSBvbGRcbiAqIGltcGxlbWVudGF0aW9uICh3aGljaCBsaXZlcyBpbnNpZGUgb2YgYHN0eWxpbmcvYCkuXG4gKlxuICogVGhlIG5ldyBzdHlsaW5nIHJlZmFjdG9yIGVuc3VyZXMgdGhhdCBzdHlsaW5nIGZsdXNoaW5nIGlzIGNhbGxlZFxuICogYXV0b21hdGljYWxseSB3aGVuIGEgdGVtcGxhdGUgZnVuY3Rpb24gZXhpdHMgb3IgYSBmb2xsb3ctdXAgZWxlbWVudFxuICogaXMgdmlzaXRlZCAoaS5lLiB3aGVuIGBzZWxlY3QobilgIGlzIGNhbGxlZCkuIEJlY2F1c2UgdGhlIGBzZWxlY3QobilgXG4gKiBpbnN0cnVjdGlvbiBpcyBub3QgZnVsbHkgaW1wbGVtZW50ZWQgeWV0IChpdCBkb2Vzbid0IGFjdHVhbGx5IGV4ZWN1dGVcbiAqIGhvc3QgYmluZGluZyBpbnN0cnVjdGlvbiBjb2RlIGF0IHRoZSByaWdodCB0aW1lKSwgdGhpcyBtZWFucyB0aGF0IGFcbiAqIHN0eWxpbmcgYXBwbHkgZnVuY3Rpb24gaXMgc3RpbGwgbmVlZGVkLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgYSBtaXJyb3IgaW1wbGVtZW50YXRpb24gb2YgdGhlIGBzdHlsaW5nQXBwbHkoKWBcbiAqIGluc3RydWN0aW9uIChmb3VuZCBpbiBgaW5zdHJ1Y3Rpb25zL3N0eWxpbmcudHNgKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0eWxpbmdBcHBseSgpIHtcbiAgY29uc3QgaW5kZXggPSBnZXRTZWxlY3RlZEluZGV4KCk7XG4gIGNvbnN0IGxWaWV3ID0gZ2V0TFZpZXcoKTtcbiAgY29uc3QgdE5vZGUgPSBnZXRUTm9kZShpbmRleCwgbFZpZXcpO1xuICBjb25zdCByZW5kZXJlciA9IGdldFJlbmRlcmVyKHROb2RlLCBsVmlldyk7XG4gIGNvbnN0IG5hdGl2ZSA9IGdldE5hdGl2ZUZyb21MVmlldyhpbmRleCwgbFZpZXcpO1xuICBjb25zdCBkaXJlY3RpdmVJbmRleCA9IGdldEFjdGl2ZURpcmVjdGl2ZVN0eWxpbmdJbmRleCgpO1xuICBhcHBseUNsYXNzZXMocmVuZGVyZXIsIGxWaWV3LCBnZXRDbGFzc2VzQ29udGV4dCh0Tm9kZSksIG5hdGl2ZSwgZGlyZWN0aXZlSW5kZXgpO1xuXG4gIGNvbnN0IHNhbml0aXplciA9IGdldEN1cnJlbnRPckxWaWV3U2FuaXRpemVyKGxWaWV3KTtcbiAgYXBwbHlTdHlsZXMocmVuZGVyZXIsIGxWaWV3LCBnZXRTdHlsZXNDb250ZXh0KHROb2RlKSwgbmF0aXZlLCBkaXJlY3RpdmVJbmRleCwgc2FuaXRpemVyKTtcblxuICBzZXRDdXJyZW50U3R5bGVTYW5pdGl6ZXIobnVsbCk7XG59XG5cbi8qKlxuICogVGVtcG9yYXJ5IGZ1bmN0aW9uIHRvIGJyaWRnZSBzdHlsaW5nIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB0aGlzIG5ld1xuICogcmVmYWN0b3IgKHdoaWNoIGlzIGhlcmUgaW5zaWRlIG9mIGBzdHlsaW5nX25leHQvYCkgYW5kIHRoZSBvbGRcbiAqIGltcGxlbWVudGF0aW9uICh3aGljaCBsaXZlcyBpbnNpZGUgb2YgYHN0eWxpbmcvYCkuXG4gKlxuICogVGhlIHB1cnBvc2Ugb2YgdGhpcyBmdW5jdGlvbiBpcyB0byB0cmF2ZXJzZSB0aHJvdWdoIHRoZSBMVmlldyBkYXRhXG4gKiBmb3IgYSBzcGVjaWZpYyBlbGVtZW50IGluZGV4IGFuZCByZXR1cm4gdGhlIG5hdGl2ZSBub2RlLiBCZWNhdXNlIHRoZVxuICogY3VycmVudCBpbXBsZW1lbnRhdGlvbiByZWxpZXMgb24gdGhlcmUgYmVpbmcgYSBzdHlsaW5nIGNvbnRleHQgYXJyYXksXG4gKiB0aGUgY29kZSBiZWxvdyB3aWxsIG5lZWQgdG8gbG9vcCB0aHJvdWdoIHRoZXNlIGFycmF5IHZhbHVlcyB1bnRpbCBpdFxuICogZ2V0cyBhIG5hdGl2ZSBlbGVtZW50IG5vZGUuXG4gKlxuICogTm90ZSB0aGF0IHRoaXMgY29kZSBpcyB0ZW1wb3JhcnkgYW5kIHdpbGwgZGlzYXBwZWFyIG9uY2UgdGhlIG5ld1xuICogc3R5bGluZyByZWZhY3RvciBsYW5kcyBpbiBpdHMgZW50aXJldHkuXG4gKi9cbmZ1bmN0aW9uIGdldE5hdGl2ZUZyb21MVmlldyhpbmRleDogbnVtYmVyLCB2aWV3RGF0YTogTFZpZXcpOiBSRWxlbWVudCB7XG4gIGxldCBzdG9yYWdlSW5kZXggPSBpbmRleCArIEhFQURFUl9PRkZTRVQ7XG4gIGxldCBzbG90VmFsdWU6IExDb250YWluZXJ8TFZpZXd8T2xkU3R5bGluZ0NvbnRleHR8UkVsZW1lbnQgPSB2aWV3RGF0YVtzdG9yYWdlSW5kZXhdO1xuICBsZXQgd3JhcHBlcjogTENvbnRhaW5lcnxMVmlld3xPbGRTdHlsaW5nQ29udGV4dCA9IHZpZXdEYXRhO1xuICB3aGlsZSAoQXJyYXkuaXNBcnJheShzbG90VmFsdWUpKSB7XG4gICAgd3JhcHBlciA9IHNsb3RWYWx1ZTtcbiAgICBzbG90VmFsdWUgPSBzbG90VmFsdWVbSE9TVF0gYXMgTFZpZXcgfCBPbGRTdHlsaW5nQ29udGV4dCB8IFJFbGVtZW50O1xuICB9XG4gIGlmIChpc09sZFN0eWxpbmdDb250ZXh0KHdyYXBwZXIpKSB7XG4gICAgcmV0dXJuIHdyYXBwZXJbT2xkU3R5bGluZ0luZGV4LkVsZW1lbnRQb3NpdGlvbl0gYXMgUkVsZW1lbnQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHNsb3RWYWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRSZW5kZXJlcih0Tm9kZTogVE5vZGUsIGxWaWV3OiBMVmlldykge1xuICByZXR1cm4gdE5vZGUudHlwZSA9PT0gVE5vZGVUeXBlLkVsZW1lbnQgPyBsVmlld1tSRU5ERVJFUl0gOiBudWxsO1xufVxuXG4vKipcbiAqIFNlYXJjaGVzIGFuZCBhc3NpZ25zIHByb3ZpZGVkIGFsbCBzdGF0aWMgc3R5bGUvY2xhc3MgZW50cmllcyAoZm91bmQgaW4gdGhlIGBhdHRyc2AgdmFsdWUpXG4gKiBhbmQgcmVnaXN0ZXJzIHRoZW0gaW4gdGhlaXIgcmVzcGVjdGl2ZSBzdHlsaW5nIGNvbnRleHRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJJbml0aWFsU3R5bGluZ0ludG9Db250ZXh0KFxuICAgIHROb2RlOiBUTm9kZSwgYXR0cnM6IFRBdHRyaWJ1dGVzLCBzdGFydEluZGV4OiBudW1iZXIpIHtcbiAgbGV0IGNsYXNzZXNDb250ZXh0ICE6IFRTdHlsaW5nQ29udGV4dDtcbiAgbGV0IHN0eWxlc0NvbnRleHQgITogVFN0eWxpbmdDb250ZXh0O1xuICBsZXQgbW9kZSA9IC0xO1xuICBmb3IgKGxldCBpID0gc3RhcnRJbmRleDsgaSA8IGF0dHJzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgYXR0ciA9IGF0dHJzW2ldO1xuICAgIGlmICh0eXBlb2YgYXR0ciA9PSAnbnVtYmVyJykge1xuICAgICAgbW9kZSA9IGF0dHI7XG4gICAgfSBlbHNlIGlmIChtb2RlID09IEF0dHJpYnV0ZU1hcmtlci5DbGFzc2VzKSB7XG4gICAgICBjbGFzc2VzQ29udGV4dCA9IGNsYXNzZXNDb250ZXh0IHx8IGdldENsYXNzZXNDb250ZXh0KHROb2RlKTtcbiAgICAgIHJlZ2lzdGVyQmluZGluZyhjbGFzc2VzQ29udGV4dCwgLTEsIGF0dHIgYXMgc3RyaW5nLCB0cnVlLCBmYWxzZSk7XG4gICAgfSBlbHNlIGlmIChtb2RlID09IEF0dHJpYnV0ZU1hcmtlci5TdHlsZXMpIHtcbiAgICAgIHN0eWxlc0NvbnRleHQgPSBzdHlsZXNDb250ZXh0IHx8IGdldFN0eWxlc0NvbnRleHQodE5vZGUpO1xuICAgICAgcmVnaXN0ZXJCaW5kaW5nKHN0eWxlc0NvbnRleHQsIC0xLCBhdHRyIGFzIHN0cmluZywgYXR0cnNbKytpXSBhcyBzdHJpbmcsIGZhbHNlKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBNaXJyb3IgaW1wbGVtZW50YXRpb24gb2YgdGhlIHNhbWUgZnVuY3Rpb24gZm91bmQgaW4gYGluc3RydWN0aW9ucy9zdHlsaW5nLnRzYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFjdGl2ZURpcmVjdGl2ZVN0eWxpbmdJbmRleCgpOiBudW1iZXIge1xuICAvLyB3aGVuZXZlciBhIGRpcmVjdGl2ZSdzIGhvc3RCaW5kaW5ncyBmdW5jdGlvbiBpcyBjYWxsZWQgYSB1bmlxdWVJZCB2YWx1ZVxuICAvLyBpcyBhc3NpZ25lZC4gTm9ybWFsbHkgdGhpcyBpcyBlbm91Z2ggdG8gaGVscCBkaXN0aW5ndWlzaCBvbmUgZGlyZWN0aXZlXG4gIC8vIGZyb20gYW5vdGhlciBmb3IgdGhlIHN0eWxpbmcgY29udGV4dCwgYnV0IHRoZXJlIGFyZSBzaXR1YXRpb25zIHdoZXJlIGFcbiAgLy8gc3ViLWNsYXNzIGRpcmVjdGl2ZSBjb3VsZCBpbmhlcml0IGFuZCBhc3NpZ24gc3R5bGluZyBpbiBjb25jZXJ0IHdpdGggYVxuICAvLyBwYXJlbnQgZGlyZWN0aXZlLiBUbyBoZWxwIHRoZSBzdHlsaW5nIGNvZGUgZGlzdGluZ3Vpc2ggYmV0d2VlbiBhIHBhcmVudFxuICAvLyBzdWItY2xhc3NlZCBkaXJlY3RpdmUgdGhlIGluaGVyaXRhbmNlIGRlcHRoIGlzIHRha2VuIGludG8gYWNjb3VudCBhcyB3ZWxsLlxuICByZXR1cm4gZ2V0QWN0aXZlRGlyZWN0aXZlSWQoKSArIGdldEFjdGl2ZURpcmVjdGl2ZVN1cGVyQ2xhc3NEZXB0aCgpO1xufVxuXG4vKipcbiAqIFRlbXBvcmFyeSBmdW5jdGlvbiB0aGF0IHdpbGwgdXBkYXRlIHRoZSBtYXggZGlyZWN0aXZlIGluZGV4IHZhbHVlIGluXG4gKiBib3RoIHRoZSBjbGFzc2VzIGFuZCBzdHlsZXMgY29udGV4dHMgcHJlc2VudCBvbiB0aGUgcHJvdmlkZWQgYHROb2RlYC5cbiAqXG4gKiBUaGlzIGNvZGUgaXMgb25seSB1c2VkIGJlY2F1c2UgdGhlIGBzZWxlY3QobilgIGNvZGUgZnVuY3Rpb25hbGl0eSBpcyBub3RcbiAqIHlldCAxMDAlIGZ1bmN0aW9uYWwuIFRoZSBgc2VsZWN0KG4pYCBpbnN0cnVjdGlvbiBjYW5ub3QgeWV0IGV2YWx1YXRlIGhvc3RcbiAqIGJpbmRpbmdzIGZ1bmN0aW9uIGNvZGUgaW4gc3luYyB3aXRoIHRoZSBhc3NvY2lhdGVkIHRlbXBsYXRlIGZ1bmN0aW9uIGNvZGUuXG4gKiBGb3IgdGhpcyByZWFzb24gdGhlIHN0eWxpbmcgYWxnb3JpdGhtIG5lZWRzIHRvIHRyYWNrIHRoZSBsYXN0IGRpcmVjdGl2ZSBpbmRleFxuICogdmFsdWUgc28gdGhhdCBpdCBrbm93cyBleGFjdGx5IHdoZW4gdG8gcmVuZGVyIHN0eWxpbmcgdG8gdGhlIGVsZW1lbnQgc2luY2VcbiAqIGBzdHlsaW5nQXBwbHkoKWAgaXMgY2FsbGVkIG11bHRpcGxlIHRpbWVzIHBlciBDRCAoYHN0eWxpbmdBcHBseWAgd2lsbCBiZVxuICogcmVtb3ZlZCBvbmNlIGBzZWxlY3QobilgIGlzIGZpeGVkKS5cbiAqL1xuZnVuY3Rpb24gdXBkYXRlTGFzdERpcmVjdGl2ZUluZGV4KHROb2RlOiBUTm9kZSwgZGlyZWN0aXZlSW5kZXg6IG51bWJlcikge1xuICB1cGRhdGVDb250ZXh0RGlyZWN0aXZlSW5kZXgoZ2V0Q2xhc3Nlc0NvbnRleHQodE5vZGUpLCBkaXJlY3RpdmVJbmRleCk7XG4gIHVwZGF0ZUNvbnRleHREaXJlY3RpdmVJbmRleChnZXRTdHlsZXNDb250ZXh0KHROb2RlKSwgZGlyZWN0aXZlSW5kZXgpO1xufVxuXG5mdW5jdGlvbiBnZXRTdHlsZXNDb250ZXh0KHROb2RlOiBUTm9kZSk6IFRTdHlsaW5nQ29udGV4dCB7XG4gIHJldHVybiBnZXRDb250ZXh0KHROb2RlLCBmYWxzZSk7XG59XG5cbmZ1bmN0aW9uIGdldENsYXNzZXNDb250ZXh0KHROb2RlOiBUTm9kZSk6IFRTdHlsaW5nQ29udGV4dCB7XG4gIHJldHVybiBnZXRDb250ZXh0KHROb2RlLCB0cnVlKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zL2luc3RhbnRpYXRlcyBhIHN0eWxpbmcgY29udGV4dCBmcm9tL3RvIGEgYHROb2RlYCBpbnN0YW5jZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Q29udGV4dCh0Tm9kZTogVE5vZGUsIGlzQ2xhc3NCYXNlZDogYm9vbGVhbikge1xuICBsZXQgY29udGV4dCA9IGlzQ2xhc3NCYXNlZCA/IHROb2RlLm5ld0NsYXNzZXMgOiB0Tm9kZS5uZXdTdHlsZXM7XG4gIGlmICghY29udGV4dCkge1xuICAgIGNvbnRleHQgPSBhbGxvY1RTdHlsaW5nQ29udGV4dCgpO1xuICAgIGlmIChuZ0Rldk1vZGUpIHtcbiAgICAgIGF0dGFjaFN0eWxpbmdEZWJ1Z09iamVjdChjb250ZXh0KTtcbiAgICB9XG4gICAgaWYgKGlzQ2xhc3NCYXNlZCkge1xuICAgICAgdE5vZGUubmV3Q2xhc3NlcyA9IGNvbnRleHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHROb2RlLm5ld1N0eWxlcyA9IGNvbnRleHQ7XG4gICAgfVxuICB9XG4gIHJldHVybiBjb250ZXh0O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3R5bGVQcm9wVmFsdWUoXG4gICAgdmFsdWU6IHN0cmluZyB8IG51bWJlciB8IFN0cmluZyB8IG51bGwsIHN1ZmZpeDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCkge1xuICBsZXQgcmVzb2x2ZWRWYWx1ZTogc3RyaW5nfG51bGwgPSBudWxsO1xuICBpZiAodmFsdWUgIT09IG51bGwpIHtcbiAgICBpZiAoc3VmZml4KSB7XG4gICAgICAvLyB3aGVuIGEgc3VmZml4IGlzIGFwcGxpZWQgdGhlbiBpdCB3aWxsIGJ5cGFzc1xuICAgICAgLy8gc2FuaXRpemF0aW9uIGVudGlyZWx5IChiL2MgYSBuZXcgc3RyaW5nIGlzIGNyZWF0ZWQpXG4gICAgICByZXNvbHZlZFZhbHVlID0gcmVuZGVyU3RyaW5naWZ5KHZhbHVlKSArIHN1ZmZpeDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gc2FuaXRpemF0aW9uIGhhcHBlbnMgYnkgZGVhbGluZyB3aXRoIGEgU3RyaW5nIHZhbHVlXG4gICAgICAvLyB0aGlzIG1lYW5zIHRoYXQgdGhlIHN0cmluZyB2YWx1ZSB3aWxsIGJlIHBhc3NlZCB0aHJvdWdoXG4gICAgICAvLyBpbnRvIHRoZSBzdHlsZSByZW5kZXJpbmcgbGF0ZXIgKHdoaWNoIGlzIHdoZXJlIHRoZSB2YWx1ZVxuICAgICAgLy8gd2lsbCBiZSBzYW5pdGl6ZWQgYmVmb3JlIGl0IGlzIGFwcGxpZWQpXG4gICAgICByZXNvbHZlZFZhbHVlID0gdmFsdWUgYXMgYW55IGFzIHN0cmluZztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc29sdmVkVmFsdWU7XG59XG4iXX0=