/** * @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 { AUTO_STYLE, style } from '@angular/animations'; import { invalidDefinition, invalidKeyframes, invalidOffset, invalidParallelAnimation, invalidStagger, invalidState, invalidStyleValue, invalidTrigger, keyframeOffsetsOutOfOrder, keyframesMissingOffsets } from '../error_helpers'; import { getOrSetDefaultValue } from '../render/shared'; import { convertToMap, copyObj, extractStyleParams, iteratorToArray, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, normalizeAnimationEntry, resolveTiming, SUBSTITUTION_EXPR_START, validateStyleParams, visitDslNode } from '../util'; import { pushUnrecognizedPropertiesWarning } from '../warning_helpers'; import { parseTransitionExpr } from './animation_transition_expr'; const SELF_TOKEN = ':self'; const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g'); /* * [Validation] * The visitor code below will traverse the animation AST generated by the animation verb functions * (the output is a tree of objects) and attempt to perform a series of validations on the data. The * following corner-cases will be validated: * * 1. Overlap of animations * Given that a CSS property cannot be animated in more than one place at the same time, it's * important that this behavior is detected and validated. The way in which this occurs is that * each time a style property is examined, a string-map containing the property will be updated with * the start and end times for when the property is used within an animation step. * * If there are two or more parallel animations that are currently running (these are invoked by the * group()) on the same element then the validator will throw an error. Since the start/end timing * values are collected for each property then if the current animation step is animating the same * property and its timing values fall anywhere into the window of time that the property is * currently being animated within then this is what causes an error. * * 2. Timing values * The validator will validate to see if a timing value of `duration delay easing` or * `durationNumber` is valid or not. * * (note that upon validation the code below will replace the timing data with an object containing * {duration,delay,easing}. * * 3. Offset Validation * Each of the style() calls are allowed to have an offset value when placed inside of keyframes(). * Offsets within keyframes() are considered valid when: * * - No offsets are used at all * - Each style() entry contains an offset value * - Each offset is between 0 and 1 * - Each offset is greater to or equal than the previous one * * Otherwise an error will be thrown. */ export function buildAnimationAst(driver, metadata, errors, warnings) { return new AnimationAstBuilderVisitor(driver).build(metadata, errors, warnings); } const ROOT_SELECTOR = ''; export class AnimationAstBuilderVisitor { constructor(_driver) { this._driver = _driver; } build(metadata, errors, warnings) { const context = new AnimationAstBuilderContext(errors); this._resetContextStyleTimingState(context); const ast = visitDslNode(this, normalizeAnimationEntry(metadata), context); if (typeof ngDevMode === 'undefined' || ngDevMode) { if (context.unsupportedCSSPropertiesFound.size) { pushUnrecognizedPropertiesWarning(warnings, [...context.unsupportedCSSPropertiesFound.keys()]); } } return ast; } _resetContextStyleTimingState(context) { context.currentQuerySelector = ROOT_SELECTOR; context.collectedStyles = new Map(); context.collectedStyles.set(ROOT_SELECTOR, new Map()); context.currentTime = 0; } visitTrigger(metadata, context) { let queryCount = context.queryCount = 0; let depCount = context.depCount = 0; const states = []; const transitions = []; if (metadata.name.charAt(0) == '@') { context.errors.push(invalidTrigger()); } metadata.definitions.forEach(def => { this._resetContextStyleTimingState(context); if (def.type == 0 /* AnimationMetadataType.State */) { const stateDef = def; const name = stateDef.name; name.toString().split(/\s*,\s*/).forEach(n => { stateDef.name = n; states.push(this.visitState(stateDef, context)); }); stateDef.name = name; } else if (def.type == 1 /* AnimationMetadataType.Transition */) { const transition = this.visitTransition(def, context); queryCount += transition.queryCount; depCount += transition.depCount; transitions.push(transition); } else { context.errors.push(invalidDefinition()); } }); return { type: 7 /* AnimationMetadataType.Trigger */, name: metadata.name, states, transitions, queryCount, depCount, options: null }; } visitState(metadata, context) { const styleAst = this.visitStyle(metadata.styles, context); const astParams = (metadata.options && metadata.options.params) || null; if (styleAst.containsDynamicStyles) { const missingSubs = new Set(); const params = astParams || {}; styleAst.styles.forEach(style => { if (style instanceof Map) { style.forEach(value => { extractStyleParams(value).forEach(sub => { if (!params.hasOwnProperty(sub)) { missingSubs.add(sub); } }); }); } }); if (missingSubs.size) { const missingSubsArr = iteratorToArray(missingSubs.values()); context.errors.push(invalidState(metadata.name, missingSubsArr)); } } return { type: 0 /* AnimationMetadataType.State */, name: metadata.name, style: styleAst, options: astParams ? { params: astParams } : null }; } visitTransition(metadata, context) { context.queryCount = 0; context.depCount = 0; const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); const matchers = parseTransitionExpr(metadata.expr, context.errors); return { type: 1 /* AnimationMetadataType.Transition */, matchers, animation, queryCount: context.queryCount, depCount: context.depCount, options: normalizeAnimationOptions(metadata.options) }; } visitSequence(metadata, context) { return { type: 2 /* AnimationMetadataType.Sequence */, steps: metadata.steps.map(s => visitDslNode(this, s, context)), options: normalizeAnimationOptions(metadata.options) }; } visitGroup(metadata, context) { const currentTime = context.currentTime; let furthestTime = 0; const steps = metadata.steps.map(step => { context.currentTime = currentTime; const innerAst = visitDslNode(this, step, context); furthestTime = Math.max(furthestTime, context.currentTime); return innerAst; }); context.currentTime = furthestTime; return { type: 3 /* AnimationMetadataType.Group */, steps, options: normalizeAnimationOptions(metadata.options) }; } visitAnimate(metadata, context) { const timingAst = constructTimingAst(metadata.timings, context.errors); context.currentAnimateTimings = timingAst; let styleAst; let styleMetadata = metadata.styles ? metadata.styles : style({}); if (styleMetadata.type == 5 /* AnimationMetadataType.Keyframes */) { styleAst = this.visitKeyframes(styleMetadata, context); } else { let styleMetadata = metadata.styles; let isEmpty = false; if (!styleMetadata) { isEmpty = true; const newStyleData = {}; if (timingAst.easing) { newStyleData['easing'] = timingAst.easing; } styleMetadata = style(newStyleData); } context.currentTime += timingAst.duration + timingAst.delay; const _styleAst = this.visitStyle(styleMetadata, context); _styleAst.isEmptyStep = isEmpty; styleAst = _styleAst; } context.currentAnimateTimings = null; return { type: 4 /* AnimationMetadataType.Animate */, timings: timingAst, style: styleAst, options: null }; } visitStyle(metadata, context) { const ast = this._makeStyleAst(metadata, context); this._validateStyleAst(ast, context); return ast; } _makeStyleAst(metadata, context) { const styles = []; const metadataStyles = Array.isArray(metadata.styles) ? metadata.styles : [metadata.styles]; for (let styleTuple of metadataStyles) { if (typeof styleTuple === 'string') { if (styleTuple === AUTO_STYLE) { styles.push(styleTuple); } else { context.errors.push(invalidStyleValue(styleTuple)); } } else { styles.push(convertToMap(styleTuple)); } } let containsDynamicStyles = false; let collectedEasing = null; styles.forEach(styleData => { if (styleData instanceof Map) { if (styleData.has('easing')) { collectedEasing = styleData.get('easing'); styleData.delete('easing'); } if (!containsDynamicStyles) { for (let value of styleData.values()) { if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) { containsDynamicStyles = true; break; } } } } }); return { type: 6 /* AnimationMetadataType.Style */, styles, easing: collectedEasing, offset: metadata.offset, containsDynamicStyles, options: null }; } _validateStyleAst(ast, context) { const timings = context.currentAnimateTimings; let endTime = context.currentTime; let startTime = context.currentTime; if (timings && startTime > 0) { startTime -= timings.duration + timings.delay; } ast.styles.forEach(tuple => { if (typeof tuple === 'string') return; tuple.forEach((value, prop) => { if (typeof ngDevMode === 'undefined' || ngDevMode) { if (!this._driver.validateStyleProperty(prop)) { tuple.delete(prop); context.unsupportedCSSPropertiesFound.add(prop); return; } } // This is guaranteed to have a defined Map at this querySelector location making it // safe to add the assertion here. It is set as a default empty map in prior methods. const collectedStyles = context.collectedStyles.get(context.currentQuerySelector); const collectedEntry = collectedStyles.get(prop); let updateCollectedStyle = true; if (collectedEntry) { if (startTime != endTime && startTime >= collectedEntry.startTime && endTime <= collectedEntry.endTime) { context.errors.push(invalidParallelAnimation(prop, collectedEntry.startTime, collectedEntry.endTime, startTime, endTime)); updateCollectedStyle = false; } // we always choose the smaller start time value since we // want to have a record of the entire animation window where // the style property is being animated in between startTime = collectedEntry.startTime; } if (updateCollectedStyle) { collectedStyles.set(prop, { startTime, endTime }); } if (context.options) { validateStyleParams(value, context.options, context.errors); } }); }); } visitKeyframes(metadata, context) { const ast = { type: 5 /* AnimationMetadataType.Keyframes */, styles: [], options: null }; if (!context.currentAnimateTimings) { context.errors.push(invalidKeyframes()); return ast; } const MAX_KEYFRAME_OFFSET = 1; let totalKeyframesWithOffsets = 0; const offsets = []; let offsetsOutOfOrder = false; let keyframesOutOfRange = false; let previousOffset = 0; const keyframes = metadata.steps.map(styles => { const style = this._makeStyleAst(styles, context); let offsetVal = style.offset != null ? style.offset : consumeOffset(style.styles); let offset = 0; if (offsetVal != null) { totalKeyframesWithOffsets++; offset = style.offset = offsetVal; } keyframesOutOfRange = keyframesOutOfRange || offset < 0 || offset > 1; offsetsOutOfOrder = offsetsOutOfOrder || offset < previousOffset; previousOffset = offset; offsets.push(offset); return style; }); if (keyframesOutOfRange) { context.errors.push(invalidOffset()); } if (offsetsOutOfOrder) { context.errors.push(keyframeOffsetsOutOfOrder()); } const length = metadata.steps.length; let generatedOffset = 0; if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) { context.errors.push(keyframesMissingOffsets()); } else if (totalKeyframesWithOffsets == 0) { generatedOffset = MAX_KEYFRAME_OFFSET / (length - 1); } const limit = length - 1; const currentTime = context.currentTime; const currentAnimateTimings = context.currentAnimateTimings; const animateDuration = currentAnimateTimings.duration; keyframes.forEach((kf, i) => { const offset = generatedOffset > 0 ? (i == limit ? 1 : (generatedOffset * i)) : offsets[i]; const durationUpToThisFrame = offset * animateDuration; context.currentTime = currentTime + currentAnimateTimings.delay + durationUpToThisFrame; currentAnimateTimings.duration = durationUpToThisFrame; this._validateStyleAst(kf, context); kf.offset = offset; ast.styles.push(kf); }); return ast; } visitReference(metadata, context) { return { type: 8 /* AnimationMetadataType.Reference */, animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), options: normalizeAnimationOptions(metadata.options) }; } visitAnimateChild(metadata, context) { context.depCount++; return { type: 9 /* AnimationMetadataType.AnimateChild */, options: normalizeAnimationOptions(metadata.options) }; } visitAnimateRef(metadata, context) { return { type: 10 /* AnimationMetadataType.AnimateRef */, animation: this.visitReference(metadata.animation, context), options: normalizeAnimationOptions(metadata.options) }; } visitQuery(metadata, context) { const parentSelector = context.currentQuerySelector; const options = (metadata.options || {}); context.queryCount++; context.currentQuery = metadata; const [selector, includeSelf] = normalizeSelector(metadata.selector); context.currentQuerySelector = parentSelector.length ? (parentSelector + ' ' + selector) : selector; getOrSetDefaultValue(context.collectedStyles, context.currentQuerySelector, new Map()); const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); context.currentQuery = null; context.currentQuerySelector = parentSelector; return { type: 11 /* AnimationMetadataType.Query */, selector, limit: options.limit || 0, optional: !!options.optional, includeSelf, animation, originalSelector: metadata.selector, options: normalizeAnimationOptions(metadata.options) }; } visitStagger(metadata, context) { if (!context.currentQuery) { context.errors.push(invalidStagger()); } const timings = metadata.timings === 'full' ? { duration: 0, delay: 0, easing: 'full' } : resolveTiming(metadata.timings, context.errors, true); return { type: 12 /* AnimationMetadataType.Stagger */, animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), timings, options: null }; } } function normalizeSelector(selector) { const hasAmpersand = selector.split(/\s*,\s*/).find(token => token == SELF_TOKEN) ? true : false; if (hasAmpersand) { selector = selector.replace(SELF_TOKEN_REGEX, ''); } // Note: the :enter and :leave aren't normalized here since those // selectors are filled in at runtime during timeline building selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR) .replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.slice(1)) .replace(/:animating/g, NG_ANIMATING_SELECTOR); return [selector, hasAmpersand]; } function normalizeParams(obj) { return obj ? copyObj(obj) : null; } export class AnimationAstBuilderContext { constructor(errors) { this.errors = errors; this.queryCount = 0; this.depCount = 0; this.currentTransition = null; this.currentQuery = null; this.currentQuerySelector = null; this.currentAnimateTimings = null; this.currentTime = 0; this.collectedStyles = new Map(); this.options = null; this.unsupportedCSSPropertiesFound = new Set(); } } function consumeOffset(styles) { if (typeof styles == 'string') return null; let offset = null; if (Array.isArray(styles)) { styles.forEach(styleTuple => { if (styleTuple instanceof Map && styleTuple.has('offset')) { const obj = styleTuple; offset = parseFloat(obj.get('offset')); obj.delete('offset'); } }); } else if (styles instanceof Map && styles.has('offset')) { const obj = styles; offset = parseFloat(obj.get('offset')); obj.delete('offset'); } return offset; } function constructTimingAst(value, errors) { if (value.hasOwnProperty('duration')) { return value; } if (typeof value == 'number') { const duration = resolveTiming(value, errors).duration; return makeTimingAst(duration, 0, ''); } const strValue = value; const isDynamic = strValue.split(/\s+/).some(v => v.charAt(0) == '{' && v.charAt(1) == '{'); if (isDynamic) { const ast = makeTimingAst(0, 0, ''); ast.dynamic = true; ast.strValue = strValue; return ast; } const timings = resolveTiming(strValue, errors); return makeTimingAst(timings.duration, timings.delay, timings.easing); } function normalizeAnimationOptions(options) { if (options) { options = copyObj(options); if (options['params']) { options['params'] = normalizeParams(options['params']); } } else { options = {}; } return options; } function makeTimingAst(duration, delay, easing) { return { duration, delay, easing }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5pbWF0aW9uX2FzdF9idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvYW5pbWF0aW9ucy9icm93c2VyL3NyYy9kc2wvYW5pbWF0aW9uX2FzdF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFBc2MsVUFBVSxFQUFFLEtBQUssRUFBZ0IsTUFBTSxxQkFBcUIsQ0FBQztBQUUxZ0IsT0FBTyxFQUFDLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSx3QkFBd0IsRUFBbUIsY0FBYyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUseUJBQXlCLEVBQUUsdUJBQXVCLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUVwUCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUN0RCxPQUFPLEVBQUMsWUFBWSxFQUFFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUscUJBQXFCLEVBQUUsbUJBQW1CLEVBQUUsdUJBQXVCLEVBQUUsYUFBYSxFQUFFLHVCQUF1QixFQUFFLG1CQUFtQixFQUFFLFlBQVksRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUNuTyxPQUFPLEVBQUMsaUNBQWlDLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUlyRSxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSw2QkFBNkIsQ0FBQztBQUVoRSxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUM7QUFDM0IsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLE1BQU0sQ0FBQyxNQUFNLFVBQVUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRWxFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDN0IsTUFBdUIsRUFBRSxRQUErQyxFQUFFLE1BQWUsRUFDekYs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QVMsYUFBYSxDQUFDLFFBQWdCLEVBQUUsS0FBYSxFQUFFLE1BQW1CO0lBQ3pFLE9BQU8sRUFBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBQyxDQUFDO0FBQ25DLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cbmltcG9ydCB7QW5pbWF0ZVRpbWluZ3MsIEFuaW1hdGlvbkFuaW1hdGVDaGlsZE1ldGFkYXRhLCBBbmltYXRpb25BbmltYXRlTWV0YWRhdGEsIEFuaW1hdGlvbkFuaW1hdGVSZWZNZXRhZGF0YSwgQW5pbWF0aW9uR3JvdXBNZXRhZGF0YSwgQW5pbWF0aW9uS2V5ZnJhbWVzU2VxdWVuY2VNZXRhZGF0YSwgQW5pbWF0aW9uTWV0YWRhdGEsIEFuaW1hdGlvbk1ldGFkYXRhVHlwZSwgQW5pbWF0aW9uT3B0aW9ucywgQW5pbWF0aW9uUXVlcnlNZXRhZGF0YSwgQW5pbWF0aW9uUXVlcnlPcHRpb25zLCBBbmltYXRpb25SZWZlcmVuY2VNZXRhZGF0YSwgQW5pbWF0aW9uU2VxdWVuY2VNZXRhZGF0YSwgQW5pbWF0aW9uU3RhZ2dlck1ldGFkYXRhLCBBbmltYXRpb25TdGF0ZU1ldGFkYXRhLCBBbmltYXRpb25TdHlsZU1ldGFkYXRhLCBBbmltYXRpb25UcmFuc2l0aW9uTWV0YWRhdGEsIEFuaW1hdGlvblRyaWdnZXJNZXRhZGF0YSwgQVVUT19TVFlMRSwgc3R5bGUsIMm1U3R5bGVEYXRhTWFwfSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcblxuaW1wb3J0IHtpbnZhbGlkRGVmaW5pdGlvbiwgaW52YWxpZEtleWZyYW1lcywgaW52YWxpZE9mZnNldCwgaW52YWxpZFBhcmFsbGVsQW5pbWF0aW9uLCBpbnZhbGlkUHJvcGVydHksIGludmFsaWRTdGFnZ2VyLCBpbnZhbGlkU3RhdGUsIGludmFsaWRTdHlsZVZhbHVlLCBpbnZhbGlkVHJpZ2dlciwga2V5ZnJhbWVPZmZzZXRzT3V0T2ZPcmRlciwga2V5ZnJhbWVzTWlzc2luZ09mZnNldHN9IGZyb20gJy4uL2Vycm9yX2hlbHBlcnMnO1xuaW1wb3J0IHtBbmltYXRpb25Ecml2ZXJ9IGZyb20gJy4uL3JlbmRlci9hbmltYXRpb25fZHJpdmVyJztcbmltcG9ydCB7Z2V0T3JTZXREZWZhdWx0VmFsdWV9IGZyb20gJy4uL3JlbmRlci9zaGFyZWQnO1xuaW1wb3J0IHtjb252ZXJ0VG9NYXAsIGNvcHlPYmosIGV4dHJhY3RTdHlsZVBhcmFtcywgaXRlcmF0b3JUb0FycmF5LCBOR19BTklNQVRJTkdfU0VMRUNUT1IsIE5HX1RSSUdHRVJfU0VMRUNUT1IsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5LCByZXNvbHZlVGltaW5nLCBTVUJTVElUVVRJT05fRVhQUl9TVEFSVCwgdmFsaWRhdGVTdHlsZVBhcmFtcywgdmlzaXREc2xOb2RlfSBmcm9tICcuLi91dGlsJztcbmltcG9ydCB7cHVzaFVucmVjb2duaXplZFByb3BlcnRpZXNXYXJuaW5nfSBmcm9tICcuLi93YXJuaW5nX2hlbHBlcnMnO1xuXG5pbXBvcnQge0FuaW1hdGVBc3QsIEFuaW1hdGVDaGlsZEFzdCwgQW5pbWF0ZVJlZkFzdCwgQXN0LCBEeW5hbWljVGltaW5nQXN0LCBHcm91cEFzdCwgS2V5ZnJhbWVzQXN0LCBRdWVyeUFzdCwgUmVmZXJlbmNlQXN0LCBTZXF1ZW5jZUFzdCwgU3RhZ2dlckFzdCwgU3RhdGVBc3QsIFN0eWxlQXN0LCBUaW1pbmdBc3QsIFRyYW5zaXRpb25Bc3QsIFRyaWdnZXJBc3R9IGZyb20gJy4vYW5pbWF0aW9uX2FzdCc7XG5pbXBvcnQge0FuaW1hdGlvbkRzbFZpc2l0b3J9IGZyb20gJy4vYW5pbWF0aW9uX2RzbF92aXNpdG9yJztcbmltcG9ydCB7cGFyc2VUcmFuc2l0aW9uRXhwcn0gZnJvbSAnLi9hbmltYXRpb25fdHJhbnNpdGlvbl9leHByJztcblxuY29uc3QgU0VMRl9UT0tFTiA9ICc6c2VsZic7XG5jb25zdCBTRUxGX1RPS0VOX1JFR0VYID0gbmV3IFJlZ0V4cChgXFxzKiR7U0VMRl9UT0tFTn1cXHMqLD9gLCAnZycpO1xuXG4vKlxuICogW1ZhbGlkYXRpb25dXG4gKiBUaGUgdmlzaXRvciBjb2RlIGJlbG93IHdpbGwgdHJhdmVyc2UgdGhlIGFuaW1hdGlvbiBBU1QgZ2VuZXJhdGVkIGJ5IHRoZSBhbmltYXRpb24gdmVyYiBmdW5jdGlvbnNcbiAqICh0aGUgb3V0cHV0IGlzIGEgdHJlZSBvZiBvYmplY3RzKSBhbmQgYXR0ZW1wdCB0byBwZXJmb3JtIGEgc2VyaWVzIG9mIHZhbGlkYXRpb25zIG9uIHRoZSBkYXRhLiBUaGVcbiAqIGZvbGxvd2luZyBjb3JuZXItY2FzZXMgd2lsbCBiZSB2YWxpZGF0ZWQ6XG4gKlxuICogMS4gT3ZlcmxhcCBvZiBhbmltYXRpb25zXG4gKiBHaXZlbiB0aGF0IGEgQ1NTIHByb3BlcnR5IGNhbm5vdCBiZSBhbmltYXRlZCBpbiBtb3JlIHRoYW4gb25lIHBsYWNlIGF0IHRoZSBzYW1lIHRpbWUsIGl0J3NcbiAqIGltcG9ydGFudCB0aGF0IHRoaXMgYmVoYXZpb3IgaXMgZGV0ZWN0ZWQgYW5kIHZhbGlkYXRlZC4gVGhlIHdheSBpbiB3aGljaCB0aGlzIG9jY3VycyBpcyB0aGF0XG4gKiBlYWNoIHRpbWUgYSBzdHlsZSBwcm9wZXJ0eSBpcyBleGFtaW5lZCwgYSBzdHJpbmctbWFwIGNvbnRhaW5pbmcgdGhlIHByb3BlcnR5IHdpbGwgYmUgdXBkYXRlZCB3aXRoXG4gKiB0aGUgc3RhcnQgYW5kIGVuZCB0aW1lcyBmb3Igd2hlbiB0aGUgcHJvcGVydHkgaXMgdXNlZCB3aXRoaW4gYW4gYW5pbWF0aW9uIHN0ZXAuXG4gKlxuICogSWYgdGhlcmUgYXJlIHR3byBvciBtb3JlIHBhcmFsbGVsIGFuaW1hdGlvbnMgdGhhdCBhcmUgY3VycmVudGx5IHJ1bm5pbmcgKHRoZXNlIGFyZSBpbnZva2VkIGJ5IHRoZVxuICogZ3JvdXAoKSkgb24gdGhlIHNhbWUgZWxlbWVudCB0aGVuIHRoZSB2YWxpZGF0b3Igd2lsbCB0aHJvdyBhbiBlcnJvci4gU2luY2UgdGhlIHN0YXJ0L2VuZCB0aW1pbmdcbiAqIHZhbHVlcyBhcmUgY29sbGVjdGVkIGZvciBlYWNoIHByb3BlcnR5IHRoZW4gaWYgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIHN0ZXAgaXMgYW5pbWF0aW5nIHRoZSBzYW1lXG4gKiBwcm9wZXJ0eSBhbmQgaXRzIHRpbWluZyB2YWx1ZXMgZmFsbCBhbnl3aGVyZSBpbnRvIHRoZSB3aW5kb3cgb2YgdGltZSB0aGF0IHRoZSBwcm9wZXJ0eSBpc1xuICogY3VycmVudGx5IGJlaW5nIGFuaW1hdGVkIHdpdGhpbiB0aGVuIHRoaXMgaXMgd2hhdCBjYXVzZXMgYW4gZXJyb3IuXG4gKlxuICogMi4gVGltaW5nIHZhbHVlc1xuICogVGhlIHZhbGlkYXRvciB3aWxsIHZhbGlkYXRlIHRvIHNlZSBpZiBhIHRpbWluZyB2YWx1ZSBvZiBgZHVyYXRpb24gZGVsYXkgZWFzaW5nYCBvclxuICogYGR1cmF0aW9uTnVtYmVyYCBpcyB2YWxpZCBvciBub3QuXG4gKlxuICogKG5vdGUgdGhhdCB1cG9uIHZhbGlkYXRpb24gdGhlIGNvZGUgYmVsb3cgd2lsbCByZXBsYWNlIHRoZSB0aW1pbmcgZGF0YSB3aXRoIGFuIG9iamVjdCBjb250YWluaW5nXG4gKiB7ZHVyYXRpb24sZGVsYXksZWFzaW5nfS5cbiAqXG4gKiAzLiBPZmZzZXQgVmFsaWRhdGlvblxuICogRWFjaCBvZiB0aGUgc3R5bGUoKSBjYWxscyBhcmUgYWxsb3dlZCB0byBoYXZlIGFuIG9mZnNldCB2YWx1ZSB3aGVuIHBsYWNlZCBpbnNpZGUgb2Yga2V5ZnJhbWVzKCkuXG4gKiBPZmZzZXRzIHdpdGhpbiBrZXlmcmFtZXMoKSBhcmUgY29uc2lkZXJlZCB2YWxpZCB3aGVuOlxuICpcbiAqICAgLSBObyBvZmZzZXRzIGFyZSB1c2VkIGF0IGFsbFxuICogICAtIEVhY2ggc3R5bGUoKSBlbnRyeSBjb250YWlucyBhbiBvZmZzZXQgdmFsdWVcbiAqICAgLSBFYWNoIG9mZnNldCBpcyBiZXR3ZWVuIDAgYW5kIDFcbiAqICAgLSBFYWNoIG9mZnNldCBpcyBncmVhdGVyIHRvIG9yIGVxdWFsIHRoYW4gdGhlIHByZXZpb3VzIG9uZVxuICpcbiAqIE90aGVyd2lzZSBhbiBlcnJvciB3aWxsIGJlIHRocm93bi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQW5pbWF0aW9uQXN0KFxuICAgIGRyaXZlcjogQW5pbWF0aW9uRHJpdmVyLCBtZXRhZGF0YTogQW5pbWF0aW9uTWV0YWRhdGF8QW5pbWF0aW9uTWV0YWRhdGFbXSwgZXJyb3JzOiBFcnJvcltdLFxuICAgIHdhcm5pbmdzOiBzdHJpbmdbXSk6IEFzdDxBbmltYXRpb25NZXRhZGF0YVR5cGU+IHtcbiAgcmV0dXJuIG5ldyBBbmltYXRpb25Bc3RCdWlsZGVyVmlzaXRvcihkcml2ZXIpLmJ1aWxkKG1ldGFkYXRhLCBlcnJvcnMsIHdhcm5pbmdzKTtcbn1cblxuY29uc3QgUk9PVF9TRUxFQ1RPUiA9ICcnO1xuXG5leHBvcnQgY2xhc3MgQW5pbWF0aW9uQXN0QnVpbGRlclZpc2l0b3IgaW1wbGVtZW50cyBBbmltYXRpb25Ec2xWaXNpdG9yIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfZHJpdmVyOiBBbmltYXRpb25Ecml2ZXIpIHt9XG5cbiAgYnVpbGQobWV0YWRhdGE6IEFuaW1hdGlvbk1ldGFkYXRhfEFuaW1hdGlvbk1ldGFkYXRhW10sIGVycm9yczogRXJyb3JbXSwgd2FybmluZ3M6IHN0cmluZ1tdKTpcbiAgICAgIEFzdDxBbmltYXRpb25NZXRhZGF0YVR5cGU+IHtcbiAgICBjb25zdCBjb250ZXh0ID0gbmV3IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0KGVycm9ycyk7XG4gICAgdGhpcy5fcmVzZXRDb250ZXh0U3R5bGVUaW1pbmdTdGF0ZShjb250ZXh0KTtcbiAgICBjb25zdCBhc3QgPVxuICAgICAgICA8QXN0PEFuaW1hdGlvbk1ldGFkYXRhVHlwZT4+dmlzaXREc2xOb2RlKHRoaXMsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5KG1ldGFkYXRhKSwgY29udGV4dCk7XG5cbiAgICBpZiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSB7XG4gICAgICBpZiAoY29udGV4dC51bnN1cHBvcnRlZENTU1Byb3BlcnRpZXNGb3VuZC5zaXplKSB7XG4gICAgICAgIHB1c2hVbnJlY29nbml6ZWRQcm9wZXJ0aWVzV2FybmluZyhcbiAgICAgICAgICAgIHdhcm5pbmdzLFxuICAgICAgICAgICAgWy4uLmNvbnRleHQudW5zdXBwb3J0ZWRDU1NQcm9wZXJ0aWVzRm91bmQua2V5cygpXSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVzZXRDb250ZXh0U3R5bGVUaW1pbmdTdGF0ZShjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCkge1xuICAgIGNvbnRleHQuY3VycmVudFF1ZXJ5U2VsZWN0b3IgPSBST09UX1NFTEVDVE9SO1xuICAgIGNvbnRleHQuY29sbGVjdGVkU3R5bGVzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIFN0eWxlVGltZVR1cGxlPj4oKTtcbiAgICBjb250ZXh0LmNvbGxlY3RlZFN0eWxlcy5zZXQoUk9PVF9TRUxFQ1RPUiwgbmV3IE1hcCgpKTtcbiAgICBjb250ZXh0LmN1cnJlbnRUaW1lID0gMDtcbiAgfVxuXG4gIHZpc2l0VHJpZ2dlcihtZXRhZGF0YTogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6XG4gICAgICBUcmlnZ2VyQXN0IHtcbiAgICBsZXQgcXVlcnlDb3VudCA9IGNvbnRleHQucXVlcnlDb3VudCA9IDA7XG4gICAgbGV0IGRlcENvdW50ID0gY29udGV4dC5kZXBDb3VudCA9IDA7XG4gICAgY29uc3Qgc3RhdGVzOiBTdGF0ZUFzdFtdID0gW107XG4gICAgY29uc3QgdHJhbnNpdGlvbnM6IFRyYW5zaXRpb25Bc3RbXSA9IFtdO1xuICAgIGlmIChtZXRhZGF0YS5uYW1lLmNoYXJBdCgwKSA9PSAnQCcpIHtcbiAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goaW52YWxpZFRyaWdnZXIoKSk7XG4gICAgfVxuXG4gICAgbWV0YWRhdGEuZGVmaW5pdGlvbnMuZm9yRWFjaChkZWYgPT4ge1xuICAgICAgdGhpcy5fcmVzZXRDb250ZXh0U3R5bGVUaW1pbmdTdGF0ZShjb250ZXh0KTtcbiAgICAgIGlmIChkZWYudHlwZSA9PSBBbmltYXRpb25NZXRhZGF0YVR5cGUuU3RhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhdGVEZWYgPSBkZWYgYXMgQW5pbWF0aW9uU3RhdGVNZXRhZGF0YTtcbiAgICAgICAgY29uc3QgbmFtZSA9IHN0YXRlRGVmLm5hbWU7XG4gICAgICAgIG5hbWUudG9TdHJpbmcoKS5zcGxpdCgvXFxzKixcXHMqLykuZm9yRWFjaChuID0+IHtcbiAgICAgICAgICBzdGF0ZURlZi5uYW1lID0gbjtcbiAgICAgICAgICBzdGF0ZXMucHVzaCh0aGlzLnZpc2l0U3RhdGUoc3RhdGVEZWYsIGNvbnRleHQpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHN0YXRlRGVmLm5hbWUgPSBuYW1lO1xuICAgICAgfSBlbHNlIGlmIChkZWYudHlwZSA9PSBBbmltYXRpb25NZXRhZGF0YVR5cGUuVHJhbnNpdGlvbikge1xuICAgICAgICBjb25zdCB0cmFuc2l0aW9uID0gdGhpcy52aXNpdFRyYW5zaXRpb24oZGVmIGFzIEFuaW1hdGlvblRyYW5zaXRpb25NZXRhZGF0YSwgY29udGV4dCk7XG4gICAgICAgIHF1ZXJ5Q291bnQgKz0gdHJhbnNpdGlvbi5xdWVyeUNvdW50O1xuICAgICAgICBkZXBDb3VudCArPSB0cmFuc2l0aW9uLmRlcENvdW50O1xuICAgICAgICB0cmFuc2l0aW9ucy5wdXNoKHRyYW5zaXRpb24pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkRGVmaW5pdGlvbigpKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuVHJpZ2dlcixcbiAgICAgIG5hbWU6IG1ldGFkYXRhLm5hbWUsXG4gICAgICBzdGF0ZXMsXG4gICAgICB0cmFuc2l0aW9ucyxcbiAgICAgIHF1ZXJ5Q291bnQsXG4gICAgICBkZXBDb3VudCxcbiAgICAgIG9wdGlvbnM6IG51bGxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRTdGF0ZShtZXRhZGF0YTogQW5pbWF0aW9uU3RhdGVNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBTdGF0ZUFzdCB7XG4gICAgY29uc3Qgc3R5bGVBc3QgPSB0aGlzLnZpc2l0U3R5bGUobWV0YWRhdGEuc3R5bGVzLCBjb250ZXh0KTtcbiAgICBjb25zdCBhc3RQYXJhbXMgPSAobWV0YWRhdGEub3B0aW9ucyAmJiBtZXRhZGF0YS5vcHRpb25zLnBhcmFtcykgfHwgbnVsbDtcbiAgICBpZiAoc3R5bGVBc3QuY29udGFpbnNEeW5hbWljU3R5bGVzKSB7XG4gICAgICBjb25zdCBtaXNzaW5nU3VicyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgY29uc3QgcGFyYW1zID0gYXN0UGFyYW1zIHx8IHt9O1xuICAgICAgc3R5bGVBc3Quc3R5bGVzLmZvckVhY2goc3R5bGUgPT4ge1xuICAgICAgICBpZiAoc3R5bGUgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgICBzdHlsZS5mb3JFYWNoKHZhbHVlID0+IHtcbiAgICAgICAgICAgIGV4dHJhY3RTdHlsZVBhcmFtcyh2YWx1ZSkuZm9yRWFjaChzdWIgPT4ge1xuICAgICAgICAgICAgICBpZiAoIXBhcmFtcy5oYXNPd25Qcm9wZXJ0eShzdWIpKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1N1YnMuYWRkKHN1Yik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGlmIChtaXNzaW5nU3Vicy5zaXplKSB7XG4gICAgICAgIGNvbnN0IG1pc3NpbmdTdWJzQXJyID0gaXRlcmF0b3JUb0FycmF5KG1pc3NpbmdTdWJzLnZhbHVlcygpKTtcbiAgICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkU3RhdGUobWV0YWRhdGEubmFtZSwgbWlzc2luZ1N1YnNBcnIpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlN0YXRlLFxuICAgICAgbmFtZTogbWV0YWRhdGEubmFtZSxcbiAgICAgIHN0eWxlOiBzdHlsZUFzdCxcbiAgICAgIG9wdGlvbnM6IGFzdFBhcmFtcyA/IHtwYXJhbXM6IGFzdFBhcmFtc30gOiBudWxsXG4gICAgfTtcbiAgfVxuXG4gIHZpc2l0VHJhbnNpdGlvbihtZXRhZGF0YTogQW5pbWF0aW9uVHJhbnNpdGlvbk1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6XG4gICAgICBUcmFuc2l0aW9uQXN0IHtcbiAgICBjb250ZXh0LnF1ZXJ5Q291bnQgPSAwO1xuICAgIGNvbnRleHQuZGVwQ291bnQgPSAwO1xuICAgIGNvbnN0IGFuaW1hdGlvbiA9IHZpc2l0RHNsTm9kZSh0aGlzLCBub3JtYWxpemVBbmltYXRpb25FbnRyeShtZXRhZGF0YS5hbmltYXRpb24pLCBjb250ZXh0KTtcbiAgICBjb25zdCBtYXRjaGVycyA9IHBhcnNlVHJhbnNpdGlvbkV4cHIobWV0YWRhdGEuZXhwciwgY29udGV4dC5lcnJvcnMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5UcmFuc2l0aW9uLFxuICAgICAgbWF0Y2hlcnMsXG4gICAgICBhbmltYXRpb24sXG4gICAgICBxdWVyeUNvdW50OiBjb250ZXh0LnF1ZXJ5Q291bnQsXG4gICAgICBkZXBDb3VudDogY29udGV4dC5kZXBDb3VudCxcbiAgICAgIG9wdGlvbnM6IG5vcm1hbGl6ZUFuaW1hdGlvbk9wdGlvbnMobWV0YWRhdGEub3B0aW9ucylcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRTZXF1ZW5jZShtZXRhZGF0YTogQW5pbWF0aW9uU2VxdWVuY2VNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOlxuICAgICAgU2VxdWVuY2VBc3Qge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuU2VxdWVuY2UsXG4gICAgICBzdGVwczogbWV0YWRhdGEuc3RlcHMubWFwKHMgPT4gdmlzaXREc2xOb2RlKHRoaXMsIHMsIGNvbnRleHQpKSxcbiAgICAgIG9wdGlvbnM6IG5vcm1hbGl6ZUFuaW1hdGlvbk9wdGlvbnMobWV0YWRhdGEub3B0aW9ucylcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRHcm91cChtZXRhZGF0YTogQW5pbWF0aW9uR3JvdXBNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBHcm91cEFzdCB7XG4gICAgY29uc3QgY3VycmVudFRpbWUgPSBjb250ZXh0LmN1cnJlbnRUaW1lO1xuICAgIGxldCBmdXJ0aGVzdFRpbWUgPSAwO1xuICAgIGNvbnN0IHN0ZXBzID0gbWV0YWRhdGEuc3RlcHMubWFwKHN0ZXAgPT4ge1xuICAgICAgY29udGV4dC5jdXJyZW50VGltZSA9IGN1cnJlbnRUaW1lO1xuICAgICAgY29uc3QgaW5uZXJBc3QgPSB2aXNpdERzbE5vZGUodGhpcywgc3RlcCwgY29udGV4dCk7XG4gICAgICBmdXJ0aGVzdFRpbWUgPSBNYXRoLm1heChmdXJ0aGVzdFRpbWUsIGNvbnRleHQuY3VycmVudFRpbWUpO1xuICAgICAgcmV0dXJuIGlubmVyQXN0O1xuICAgIH0pO1xuXG4gICAgY29udGV4dC5jdXJyZW50VGltZSA9IGZ1cnRoZXN0VGltZTtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLkdyb3VwLFxuICAgICAgc3RlcHMsXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpXG4gICAgfTtcbiAgfVxuXG4gIHZpc2l0QW5pbWF0ZShtZXRhZGF0YTogQW5pbWF0aW9uQW5pbWF0ZU1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6XG4gICAgICBBbmltYXRlQXN0IHtcbiAgICBjb25zdCB0aW1pbmdBc3QgPSBjb25zdHJ1Y3RUaW1pbmdBc3QobWV0YWRhdGEudGltaW5ncywgY29udGV4dC5lcnJvcnMpO1xuICAgIGNvbnRleHQuY3VycmVudEFuaW1hdGVUaW1pbmdzID0gdGltaW5nQXN0O1xuICAgIGxldCBzdHlsZUFzdDogU3R5bGVBc3R8S2V5ZnJhbWVzQXN0O1xuICAgIGxldCBzdHlsZU1ldGFkYXRhOiBBbmltYXRpb25TdHlsZU1ldGFkYXRhfEFuaW1hdGlvbktleWZyYW1lc1NlcXVlbmNlTWV0YWRhdGEgPVxuICAgICAgICBtZXRhZGF0YS5zdHlsZXMgPyBtZXRhZGF0YS5zdHlsZXMgOiBzdHlsZSh7fSk7XG4gICAgaWYgKHN0eWxlTWV0YWRhdGEudHlwZSA9PSBBbmltYXRpb25NZXRhZGF0YVR5cGUuS2V5ZnJhbWVzKSB7XG4gICAgICBzdHlsZUFzdCA9IHRoaXMudmlzaXRLZXlmcmFtZXMoc3R5bGVNZXRhZGF0YSBhcyBBbmltYXRpb25LZXlmcmFtZXNTZXF1ZW5jZU1ldGFkYXRhLCBjb250ZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHN0eWxlTWV0YWRhdGEgPSBtZXRhZGF0YS5zdHlsZXMgYXMgQW5pbWF0aW9uU3R5bGVNZXRhZGF0YTtcbiAgICAgIGxldCBpc0VtcHR5ID0gZmFsc2U7XG4gICAgICBpZiAoIXN0eWxlTWV0YWRhdGEpIHtcbiAgICAgICAgaXNFbXB0eSA9IHRydWU7XG4gICAgICAgIGNvbnN0IG5ld1N0eWxlRGF0YToge1twcm9wOiBzdHJpbmddOiBzdHJpbmd8bnVtYmVyfSA9IHt9O1xuICAgICAgICBpZiAodGltaW5nQXN0LmVhc2luZykge1xuICAgICAgICAgIG5ld1N0eWxlRGF0YVsnZWFzaW5nJ10gPSB0aW1pbmdBc3QuZWFzaW5nO1xuICAgICAgICB9XG4gICAgICAgIHN0eWxlTWV0YWRhdGEgPSBzdHlsZShuZXdTdHlsZURhdGEpO1xuICAgICAgfVxuICAgICAgY29udGV4dC5jdXJyZW50VGltZSArPSB0aW1pbmdBc3QuZHVyYXRpb24gKyB0aW1pbmdBc3QuZGVsYXk7XG4gICAgICBjb25zdCBfc3R5bGVBc3QgPSB0aGlzLnZpc2l0U3R5bGUoc3R5bGVNZXRhZGF0YSwgY29udGV4dCk7XG4gICAgICBfc3R5bGVBc3QuaXNFbXB0eVN0ZXAgPSBpc0VtcHR5O1xuICAgICAgc3R5bGVBc3QgPSBfc3R5bGVBc3Q7XG4gICAgfVxuXG4gICAgY29udGV4dC5jdXJyZW50QW5pbWF0ZVRpbWluZ3MgPSBudWxsO1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuQW5pbWF0ZSxcbiAgICAgIHRpbWluZ3M6IHRpbWluZ0FzdCxcbiAgICAgIHN0eWxlOiBzdHlsZUFzdCxcbiAgICAgIG9wdGlvbnM6IG51bGxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRTdHlsZShtZXRhZGF0YTogQW5pbWF0aW9uU3R5bGVNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBTdHlsZUFzdCB7XG4gICAgY29uc3QgYXN0ID0gdGhpcy5fbWFrZVN0eWxlQXN0KG1ldGFkYXRhLCBjb250ZXh0KTtcbiAgICB0aGlzLl92YWxpZGF0ZVN0eWxlQXN0KGFzdCwgY29udGV4dCk7XG4gICAgcmV0dXJuIGFzdDtcbiAgfVxuXG4gIHByaXZhdGUgX21ha2VTdHlsZUFzdChtZXRhZGF0YTogQW5pbWF0aW9uU3R5bGVNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOlxuICAgICAgU3R5bGVBc3Qge1xuICAgIGNvbnN0IHN0eWxlczogQXJyYXk8KMm1U3R5bGVEYXRhTWFwIHwgc3RyaW5nKT4gPSBbXTtcbiAgICBjb25zdCBtZXRhZGF0YVN0eWxlcyA9IEFycmF5LmlzQXJyYXkobWV0YWRhdGEuc3R5bGVzKSA/IG1ldGFkYXRhLnN0eWxlcyA6IFttZXRhZGF0YS5zdHlsZXNdO1xuXG4gICAgZm9yIChsZXQgc3R5bGVUdXBsZSBvZiBtZXRhZGF0YVN0eWxlcykge1xuICAgICAgaWYgKHR5cGVvZiBzdHlsZVR1cGxlID09PSAnc3RyaW5nJykge1xuICAgICAgICBpZiAoc3R5bGVUdXBsZSA9PT0gQVVUT19TVFlMRSkge1xuICAgICAgICAgIHN0eWxlcy5wdXNoKHN0eWxlVHVwbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goaW52YWxpZFN0eWxlVmFsdWUoc3R5bGVUdXBsZSkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHlsZXMucHVzaChjb252ZXJ0VG9NYXAoc3R5bGVUdXBsZSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBjb250YWluc0R5bmFtaWNTdHlsZXMgPSBmYWxzZTtcbiAgICBsZXQgY29sbGVjdGVkRWFzaW5nOiBzdHJpbmd8bnVsbCA9IG51bGw7XG4gICAgc3R5bGVzLmZvckVhY2goc3R5bGVEYXRhID0+IHtcbiAgICAgIGlmIChzdHlsZURhdGEgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgaWYgKHN0eWxlRGF0YS5oYXMoJ2Vhc2luZycpKSB7XG4gICAgICAgICAgY29sbGVjdGVkRWFzaW5nID0gc3R5bGVEYXRhLmdldCgnZWFzaW5nJykgYXMgc3RyaW5nO1xuICAgICAgICAgIHN0eWxlRGF0YS5kZWxldGUoJ2Vhc2luZycpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY29udGFpbnNEeW5hbWljU3R5bGVzKSB7XG4gICAgICAgICAgZm9yIChsZXQgdmFsdWUgb2Ygc3R5bGVEYXRhLnZhbHVlcygpKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUhLnRvU3RyaW5nKCkuaW5kZXhPZihTVUJTVElUVVRJT05fRVhQUl9TVEFSVCkgPj0gMCkge1xuICAgICAgICAgICAgICBjb250YWluc0R5bmFtaWNTdHlsZXMgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuU3R5bGUsXG4gICAgICBzdHlsZXMsXG4gICAgICBlYXNpbmc6IGNvbGxlY3RlZEVhc2luZyxcbiAgICAgIG9mZnNldDogbWV0YWRhdGEub2Zmc2V0LFxuICAgICAgY29udGFpbnNEeW5hbWljU3R5bGVzLFxuICAgICAgb3B0aW9uczogbnVsbFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF92YWxpZGF0ZVN0eWxlQXN0KGFzdDogU3R5bGVBc3QsIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0KTogdm9pZCB7XG4gICAgY29uc3QgdGltaW5ncyA9IGNvbnRleHQuY3VycmVudEFuaW1hdGVUaW1pbmdzO1xuICAgIGxldCBlbmRUaW1lID0gY29udGV4dC5jdXJyZW50VGltZTtcbiAgICBsZXQgc3RhcnRUaW1lID0gY29udGV4dC5jdXJyZW50VGltZTtcbiAgICBpZiAodGltaW5ncyAmJiBzdGFydFRpbWUgPiAwKSB7XG4gICAgICBzdGFydFRpbWUgLT0gdGltaW5ncy5kdXJhdGlvbiArIHRpbWluZ3MuZGVsYXk7XG4gICAgfVxuXG4gICAgYXN0LnN0eWxlcy5mb3JFYWNoKHR1cGxlID0+IHtcbiAgICAgIGlmICh0eXBlb2YgdHVwbGUgPT09ICdzdHJpbmcnKSByZXR1cm47XG5cbiAgICAgIHR1cGxlLmZvckVhY2goKHZhbHVlLCBwcm9wKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgbmdEZXZNb2RlID09PSAndW5kZWZpbmVkJyB8fCBuZ0Rldk1vZGUpIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX2RyaXZlci52YWxpZGF0ZVN0eWxlUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgIHR1cGxlLmRlbGV0ZShwcm9wKTtcbiAgICAgICAgICAgIGNvbnRleHQudW5zdXBwb3J0ZWRDU1NQcm9wZXJ0aWVzRm91bmQuYWRkKHByb3ApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoaXMgaXMgZ3VhcmFudGVlZCB0byBoYXZlIGEgZGVmaW5lZCBNYXAgYXQgdGhpcyBxdWVyeVNlbGVjdG9yIGxvY2F0aW9uIG1ha2luZyBpdFxuICAgICAgICAvLyBzYWZlIHRvIGFkZCB0aGUgYXNzZXJ0aW9uIGhlcmUuIEl0IGlzIHNldCBhcyBhIGRlZmF1bHQgZW1wdHkgbWFwIGluIHByaW9yIG1ldGhvZHMuXG4gICAgICAgIGNvbnN0IGNvbGxlY3RlZFN0eWxlcyA9IGNvbnRleHQuY29sbGVjdGVkU3R5bGVzLmdldChjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yISkhO1xuICAgICAgICBjb25zdCBjb2xsZWN0ZWRFbnRyeSA9IGNvbGxlY3RlZFN0eWxlcy5nZXQocHJvcCk7XG4gICAgICAgIGxldCB1cGRhdGVDb2xsZWN0ZWRTdHlsZSA9IHRydWU7XG4gICAgICAgIGlmIChjb2xsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgIGlmIChzdGFydFRpbWUgIT0gZW5kVGltZSAmJiBzdGFydFRpbWUgPj0gY29sbGVjdGVkRW50cnkuc3RhcnRUaW1lICYmXG4gICAgICAgICAgICAgIGVuZFRpbWUgPD0gY29sbGVjdGVkRW50cnkuZW5kVGltZSkge1xuICAgICAgICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkUGFyYWxsZWxBbmltYXRpb24oXG4gICAgICAgICAgICAgICAgcHJvcCwgY29sbGVjdGVkRW50cnkuc3RhcnRUaW1lLCBjb2xsZWN0ZWRFbnRyeS5lbmRUaW1lLCBzdGFydFRpbWUsIGVuZFRpbWUpKTtcbiAgICAgICAgICAgIHVwZGF0ZUNvbGxlY3RlZFN0eWxlID0gZmFsc2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gd2UgYWx3YXlzIGNob29zZSB0aGUgc21hbGxlciBzdGFydCB0aW1lIHZhbHVlIHNpbmNlIHdlXG4gICAgICAgICAgLy8gd2FudCB0byBoYXZlIGEgcmVjb3JkIG9mIHRoZSBlbnRpcmUgYW5pbWF0aW9uIHdpbmRvdyB3aGVyZVxuICAgICAgICAgIC8vIHRoZSBzdHlsZSBwcm9wZXJ0eSBpcyBiZWluZyBhbmltYXRlZCBpbiBiZXR3ZWVuXG4gICAgICAgICAgc3RhcnRUaW1lID0gY29sbGVjdGVkRW50cnkuc3RhcnRUaW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVwZGF0ZUNvbGxlY3RlZFN0eWxlKSB7XG4gICAgICAgICAgY29sbGVjdGVkU3R5bGVzLnNldChwcm9wLCB7c3RhcnRUaW1lLCBlbmRUaW1lfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dC5vcHRpb25zKSB7XG4gICAgICAgICAgdmFsaWRhdGVTdHlsZVBhcmFtcyh2YWx1ZSwgY29udGV4dC5vcHRpb25zLCBjb250ZXh0LmVycm9ycyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgdmlzaXRLZXlmcmFtZXMobWV0YWRhdGE6IEFuaW1hdGlvbktleWZyYW1lc1NlcXVlbmNlTWV0YWRhdGEsIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0KTpcbiAgICAgIEtleWZyYW1lc0FzdCB7XG4gICAgY29uc3QgYXN0OiBLZXlmcmFtZXNBc3QgPSB7dHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLktleWZyYW1lcywgc3R5bGVzOiBbXSwgb3B0aW9uczogbnVsbH07XG4gICAgaWYgKCFjb250ZXh0LmN1cnJlbnRBbmltYXRlVGltaW5ncykge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkS2V5ZnJhbWVzKCkpO1xuICAgICAgcmV0dXJuIGFzdDtcbiAgICB9XG5cbiAgICBjb25zdCBNQVhfS0VZRlJBTUVfT0ZGU0VUID0gMTtcblxuICAgIGxldCB0b3RhbEtleWZyYW1lc1dpdGhPZmZzZXRzID0gMDtcbiAgICBjb25zdCBvZmZzZXRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGxldCBvZmZzZXRzT3V0T2ZPcmRlciA9IGZhbHNlO1xuICAgIGxldCBrZXlmcmFtZXNPdXRPZlJhbmdlID0gZmFsc2U7XG4gICAgbGV0IHByZXZpb3VzT2Zmc2V0OiBudW1iZXIgPSAwO1xuXG4gICAgY29uc3Qga2V5ZnJhbWVzOiBTdHlsZUFzdFtdID0gbWV0YWRhdGEuc3RlcHMubWFwKHN0eWxlcyA9PiB7XG4gICAgICBjb25zdCBzdHlsZSA9IHRoaXMuX21ha2VTdHlsZUFzdChzdHlsZXMsIGNvbnRleHQpO1xuICAgICAgbGV0IG9mZnNldFZhbDogbnVtYmVyfG51bGwgPVxuICAgICAgICAgIHN0eWxlLm9mZnNldCAhPSBudWxsID8gc3R5bGUub2Zmc2V0IDogY29uc3VtZU9mZnNldChzdHlsZS5zdHlsZXMpO1xuICAgICAgbGV0IG9mZnNldDogbnVtYmVyID0gMDtcbiAgICAgIGlmIChvZmZzZXRWYWwgIT0gbnVsbCkge1xuICAgICAgICB0b3RhbEtleWZyYW1lc1dpdGhPZmZzZXRzKys7XG4gICAgICAgIG9mZnNldCA9IHN0eWxlLm9mZnNldCA9IG9mZnNldFZhbDtcbiAgICAgIH1cbiAgICAgIGtleWZyYW1lc091dE9mUmFuZ2UgPSBrZXlmcmFtZXNPdXRPZlJhbmdlIHx8IG9mZnNldCA8IDAgfHwgb2Zmc2V0ID4gMTtcbiAgICAgIG9mZnNldHNPdXRPZk9yZGVyID0gb2Zmc2V0c091dE9mT3JkZXIgfHwgb2Zmc2V0IDwgcHJldmlvdXNPZmZzZXQ7XG4gICAgICBwcmV2aW91c09mZnNldCA9IG9mZnNldDtcbiAgICAgIG9mZnNldHMucHVzaChvZmZzZXQpO1xuICAgICAgcmV0dXJuIHN0eWxlO1xuICAgIH0pO1xuXG4gICAgaWYgKGtleWZyYW1lc091dE9mUmFuZ2UpIHtcbiAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goaW52YWxpZE9mZnNldCgpKTtcbiAgICB9XG5cbiAgICBpZiAob2Zmc2V0c091dE9mT3JkZXIpIHtcbiAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goa2V5ZnJhbWVPZmZzZXRzT3V0T2ZPcmRlcigpKTtcbiAgICB9XG5cbiAgICBjb25zdCBsZW5ndGggPSBtZXRhZGF0YS5zdGVwcy5sZW5ndGg7XG4gICAgbGV0IGdlbmVyYXRlZE9mZnNldCA9IDA7XG4gICAgaWYgKHRvdGFsS2V5ZnJhbWVzV2l0aE9mZnNldHMgPiAwICYmIHRvdGFsS2V5ZnJhbWVzV2l0aE9mZnNldHMgPCBsZW5ndGgpIHtcbiAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goa2V5ZnJhbWVzTWlzc2luZ09mZnNldHMoKSk7XG4gICAgfSBlbHNlIGlmICh0b3RhbEtleWZyYW1lc1dpdGhPZmZzZXRzID09IDApIHtcbiAgICAgIGdlbmVyYXRlZE9mZnNldCA9IE1BWF9LRVlGUkFNRV9PRkZTRVQgLyAobGVuZ3RoIC0gMSk7XG4gICAgfVxuXG4gICAgY29uc3QgbGltaXQgPSBsZW5ndGggLSAxO1xuICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gY29udGV4dC5jdXJyZW50VGltZTtcbiAgICBjb25zdCBjdXJyZW50QW5pbWF0ZVRpbWluZ3MgPSBjb250ZXh0LmN1cnJlbnRBbmltYXRlVGltaW5ncyE7XG4gICAgY29uc3QgYW5pbWF0ZUR1cmF0aW9uID0gY3VycmVudEFuaW1hdGVUaW1pbmdzLmR1cmF0aW9uO1xuICAgIGtleWZyYW1lcy5mb3JFYWNoKChrZiwgaSkgPT4ge1xuICAgICAgY29uc3Qgb2Zmc2V0ID0gZ2VuZXJhdGVkT2Zmc2V0ID4gMCA/IChpID09IGxpbWl0ID8gMSA6IChnZW5lcmF0ZWRPZmZzZXQgKiBpKSkgOiBvZmZzZXRzW2ldO1xuICAgICAgY29uc3QgZHVyYXRpb25VcFRvVGhpc0ZyYW1lID0gb2Zmc2V0ICogYW5pbWF0ZUR1cmF0aW9uO1xuICAgICAgY29udGV4dC5jdXJyZW50VGltZSA9IGN1cnJlbnRUaW1lICsgY3VycmVudEFuaW1hdGVUaW1pbmdzLmRlbGF5ICsgZHVyYXRpb25VcFRvVGhpc0ZyYW1lO1xuICAgICAgY3VycmVudEFuaW1hdGVUaW1pbmdzLmR1cmF0aW9uID0gZHVyYXRpb25VcFRvVGhpc0ZyYW1lO1xuICAgICAgdGhpcy5fdmFsaWRhdGVTdHlsZUFzdChrZiwgY29udGV4dCk7XG4gICAgICBrZi5vZmZzZXQgPSBvZmZzZXQ7XG5cbiAgICAgIGFzdC5zdHlsZXMucHVzaChrZik7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgdmlzaXRSZWZlcmVuY2UobWV0YWRhdGE6IEFuaW1hdGlvblJlZmVyZW5jZU1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6XG4gICAgICBSZWZlcmVuY2VBc3Qge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuUmVmZXJlbmNlLFxuICAgICAgYW5pbWF0aW9uOiB2aXNpdERzbE5vZGUodGhpcywgbm9ybWFsaXplQW5pbWF0aW9uRW50cnkobWV0YWRhdGEuYW5pbWF0aW9uKSwgY29udGV4dCksXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpXG4gICAgfTtcbiAgfVxuXG4gIHZpc2l0QW5pbWF0ZUNoaWxkKG1ldGFkYXRhOiBBbmltYXRpb25BbmltYXRlQ2hpbGRNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOlxuICAgICAgQW5pbWF0ZUNoaWxkQXN0IHtcbiAgICBjb250ZXh0LmRlcENvdW50Kys7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5BbmltYXRlQ2hpbGQsXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpXG4gICAgfTtcbiAgfVxuXG4gIHZpc2l0QW5pbWF0ZVJlZihtZXRhZGF0YTogQW5pbWF0aW9uQW5pbWF0ZVJlZk1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6XG4gICAgICBBbmltYXRlUmVmQXN0IHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLkFuaW1hdGVSZWYsXG4gICAgICBhbmltYXRpb246IHRoaXMudmlzaXRSZWZlcmVuY2UobWV0YWRhdGEuYW5pbWF0aW9uLCBjb250ZXh0KSxcbiAgICAgIG9wdGlvbnM6IG5vcm1hbGl6ZUFuaW1hdGlvbk9wdGlvbnMobWV0YWRhdGEub3B0aW9ucylcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRRdWVyeShtZXRhZGF0YTogQW5pbWF0aW9uUXVlcnlNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBRdWVyeUFzdCB7XG4gICAgY29uc3QgcGFyZW50U2VsZWN0b3IgPSBjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yITtcbiAgICBjb25zdCBvcHRpb25zID0gKG1ldGFkYXRhLm9wdGlvbnMgfHwge30pIGFzIEFuaW1hdGlvblF1ZXJ5T3B0aW9ucztcblxuICAgIGNvbnRleHQucXVlcnlDb3VudCsrO1xuICAgIGNvbnRleHQuY3VycmVudFF1ZXJ5ID0gbWV0YWRhdGE7XG4gICAgY29uc3QgW3NlbGVjdG9yLCBpbmNsdWRlU2VsZl0gPSBub3JtYWxpemVTZWxlY3RvcihtZXRhZGF0YS5zZWxlY3Rvcik7XG4gICAgY29udGV4dC5jdXJyZW50UXVlcnlTZWxlY3RvciA9XG4gICAgICAgIHBhcmVudFNlbGVjdG9yLmxlbmd0aCA/IChwYXJlbnRTZWxlY3RvciArICcgJyArIHNlbGVjdG9yKSA6IHNlbGVjdG9yO1xuICAgIGdldE9yU2V0RGVmYXVsdFZhbHVlKGNvbnRleHQuY29sbGVjdGVkU3R5bGVzLCBjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yLCBuZXcgTWFwKCkpO1xuXG4gICAgY29uc3QgYW5pbWF0aW9uID0gdmlzaXREc2xOb2RlKHRoaXMsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5KG1ldGFkYXRhLmFuaW1hdGlvbiksIGNvbnRleHQpO1xuICAgIGNvbnRleHQuY3VycmVudFF1ZXJ5ID0gbnVsbDtcbiAgICBjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yID0gcGFyZW50U2VsZWN0b3I7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlF1ZXJ5LFxuICAgICAgc2VsZWN0b3IsXG4gICAgICBsaW1pdDogb3B0aW9ucy5saW1pdCB8fCAwLFxuICAgICAgb3B0aW9uYWw6ICEhb3B0aW9ucy5vcHRpb25hbCxcbiAgICAgIGluY2x1ZGVTZWxmLFxuICAgICAgYW5pbWF0aW9uLFxuICAgICAgb3JpZ2luYWxTZWxlY3RvcjogbWV0YWRhdGEuc2VsZWN0b3IsXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpXG4gICAgfTtcbiAgfVxuXG4gIHZpc2l0U3RhZ2dlcihtZXRhZGF0YTogQW5pbWF0aW9uU3RhZ2dlck1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6XG4gICAgICBTdGFnZ2VyQXN0IHtcbiAgICBpZiAoIWNvbnRleHQuY3VycmVudFF1ZXJ5KSB7XG4gICAgICBjb250ZXh0LmVycm9ycy5wdXNoKGludmFsaWRTdGFnZ2VyKCkpO1xuICAgIH1cbiAgICBjb25zdCB0aW1pbmdzID0gbWV0YWRhdGEudGltaW5ncyA9PT0gJ2Z1bGwnID9cbiAgICAgICAge2R1cmF0aW9uOiAwLCBkZWxheTogMCwgZWFzaW5nOiAnZnVsbCd9IDpcbiAgICAgICAgcmVzb2x2ZVRpbWluZyhtZXRhZGF0YS50aW1pbmdzLCBjb250ZXh0LmVycm9ycywgdHJ1ZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlN0YWdnZXIsXG4gICAgICBhbmltYXRpb246IHZpc2l0RHNsTm9kZSh0aGlzLCBub3JtYWxpemVBbmltYXRpb25FbnRyeShtZXRhZGF0YS5hbmltYXRpb24pLCBjb250ZXh0KSxcbiAgICAgIHRpbWluZ3MsXG4gICAgICBvcHRpb25zOiBudWxsXG4gICAgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVTZWxlY3RvcihzZWxlY3Rvcjogc3RyaW5nKTogW3N0cmluZywgYm9vbGVhbl0ge1xuICBjb25zdCBoYXNBbXBlcnNhbmQgPSBzZWxlY3Rvci5zcGxpdCgvXFxzKixcXHMqLykuZmluZCh0b2tlbiA9PiB0b2tlbiA9PSBTRUxGX1RPS0VOKSA/IHRydWUgOiBmYWxzZTtcbiAgaWYgKGhhc0FtcGVyc2FuZCkge1xuICAgIHNlbGVjdG9yID0gc2VsZWN0b3IucmVwbGFjZShTRUxGX1RPS0VOX1JFR0VYLCAnJyk7XG4gIH1cblxuICAvLyBOb3RlOiB0aGUgOmVudGVyIGFuZCA6bGVhdmUgYXJlbid0IG5vcm1hbGl6ZWQgaGVyZSBzaW5jZSB0aG9zZVxuICAvLyBzZWxlY3RvcnMgYXJlIGZpbGxlZCBpbiBhdCBydW50aW1lIGR1cmluZyB0aW1lbGluZSBidWlsZGluZ1xuICBzZWxlY3RvciA9IHNlbGVjdG9yLnJlcGxhY2UoL0BcXCovZywgTkdfVFJJR0dFUl9TRUxFQ1RPUilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL0BcXHcrL2csIG1hdGNoID0+IE5HX1RSSUdHRVJfU0VMRUNUT1IgKyAnLScgKyBtYXRjaC5zbGljZSgxKSlcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLzphbmltYXRpbmcvZywgTkdfQU5JTUFUSU5HX1NFTEVDVE9SKTtcblxuICByZXR1cm4gW3NlbGVjdG9yLCBoYXNBbXBlcnNhbmRdO1xufVxuXG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVBhcmFtcyhvYmo6IHtba2V5OiBzdHJpbmddOiBhbnl9fGFueSk6IHtba2V5OiBzdHJpbmddOiBhbnl9fG51bGwge1xuICByZXR1cm4gb2JqID8gY29weU9iaihvYmopIDogbnVsbDtcbn1cblxuZXhwb3J0IHR5cGUgU3R5bGVUaW1lVHVwbGUgPSB7XG4gIHN0YXJ0VGltZTogbnVtYmVyOyBlbmRUaW1lOiBudW1iZXI7XG59O1xuXG5leHBvcnQgY2xhc3MgQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQge1xuICBwdWJsaWMgcXVlcnlDb3VudDogbnVtYmVyID0gMDtcbiAgcHVibGljIGRlcENvdW50OiBudW1iZXIgPSAwO1xuICBwdWJsaWMgY3VycmVudFRyYW5zaXRpb246IEFuaW1hdGlvblRyYW5zaXRpb25NZXRhZGF0YXxudWxsID0gbnVsbDtcbiAgcHVibGljIGN1cnJlbnRRdWVyeTogQW5pbWF0aW9uUXVlcnlNZXRhZGF0YXxudWxsID0gbnVsbDtcbiAgcHVibGljIGN1cnJlbnRRdWVyeVNlbGVjdG9yOiBzdHJpbmd8bnVsbCA9IG51bGw7XG4gIHB1YmxpYyBjdXJyZW50QW5pbWF0ZVRpbWluZ3M6IFRpbWluZ0FzdHxudWxsID0gbnVsbDtcbiAgcHVibGljIGN1cnJlbnRUaW1lOiBudW1iZXIgPSAwO1xuICBwdWJsaWMgY29sbGVjdGVkU3R5bGVzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIFN0eWxlVGltZVR1cGxlPj4oKTtcbiAgcHVibGljIG9wdGlvbnM6IEFuaW1hdGlvbk9wdGlvbnN8bnVsbCA9IG51bGw7XG4gIHB1YmxpYyB1bnN1cHBvcnRlZENTU1Byb3BlcnRpZXNGb3VuZDogU2V0PHN0cmluZz4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3RydWN0b3IocHVibGljIGVycm9yczogRXJyb3JbXSkge31cbn1cblxudHlwZSBPZmZzZXRTdHlsZXMgPSBzdHJpbmd8ybVTdHlsZURhdGFNYXA7XG5cbmZ1bmN0aW9uIGNvbnN1bWVPZmZzZXQoc3R5bGVzOiBPZmZzZXRTdHlsZXN8QXJyYXk8T2Zmc2V0U3R5bGVzPik6IG51bWJlcnxudWxsIHtcbiAgaWYgKHR5cGVvZiBzdHlsZXMgPT0gJ3N0cmluZycpIHJldHVybiBudWxsO1xuXG4gIGxldCBvZmZzZXQ6IG51bWJlcnxudWxsID0gbnVsbDtcblxuICBpZiAoQXJyYXkuaXNBcnJheShzdHlsZXMpKSB7XG4gICAgc3R5bGVzLmZvckVhY2goc3R5bGVUdXBsZSA9PiB7XG4gICAgICBpZiAoc3R5bGVUdXBsZSBpbnN0YW5jZW9mIE1hcCAmJiBzdHlsZVR1cGxlLmhhcygnb2Zmc2V0JykpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gc3R5bGVUdXBsZSBhcyDJtVN0eWxlRGF0YU1hcDtcbiAgICAgICAgb2Zmc2V0ID0gcGFyc2VGbG9hdChvYmouZ2V0KCdvZmZzZXQnKSBhcyBzdHJpbmcpO1xuICAgICAgICBvYmouZGVsZXRlKCdvZmZzZXQnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSBlbHNlIGlmIChzdHlsZXMgaW5zdGFuY2VvZiBNYXAgJiYgc3R5bGVzLmhhcygnb2Zmc2V0JykpIHtcbiAgICBjb25zdCBvYmogPSBzdHlsZXM7XG4gICAgb2Zmc2V0ID0gcGFyc2VGbG9hdChvYmouZ2V0KCdvZmZzZXQnKSBhcyBzdHJpbmcpO1xuICAgIG9iai5kZWxldGUoJ29mZnNldCcpO1xuICB9XG4gIHJldHVybiBvZmZzZXQ7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFRpbWluZ0FzdCh2YWx1ZTogc3RyaW5nfG51bWJlcnxBbmltYXRlVGltaW5ncywgZXJyb3JzOiBFcnJvcltdKSB7XG4gIGlmICh2YWx1ZS5oYXNPd25Qcm9wZXJ0eSgnZHVyYXRpb24nKSkge1xuICAgIHJldHVybiB2YWx1ZSBhcyBBbmltYXRlVGltaW5ncztcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicpIHtcbiAgICBjb25zdCBkdXJhdGlvbiA9IHJlc29sdmVUaW1pbmcodmFsdWUsIGVycm9ycykuZHVyYXRpb247XG4gICAgcmV0dXJuIG1ha2VUaW1pbmdBc3QoZHVyYXRpb24sIDAsICcnKTtcbiAgfVxuXG4gIGNvbnN0IHN0clZhbHVlID0gdmFsdWUgYXMgc3RyaW5nO1xuICBjb25zdCBpc0R5bmFtaWMgPSBzdHJWYWx1ZS5zcGxpdCgvXFxzKy8pLnNvbWUodiA9PiB2LmNoYXJBdCgwKSA9PSAneycgJiYgdi5jaGFyQXQoMSkgPT0gJ3snKTtcbiAgaWYgKGlzRHluYW1pYykge1xuICAgIGNvbnN0IGFzdCA9IG1ha2VUaW1pbmdBc3QoMCwgMCwgJycpIGFzIGFueTtcbiAgICBhc3QuZHluYW1pYyA9IHRydWU7XG4gICAgYXN0LnN0clZhbHVlID0gc3RyVmFsdWU7XG4gICAgcmV0dXJuIGFzdCBhcyBEeW5hbWljVGltaW5nQXN0O1xuICB9XG5cbiAgY29uc3QgdGltaW5ncyA9IHJlc29sdmVUaW1pbmcoc3RyVmFsdWUsIGVycm9ycyk7XG4gIHJldHVybiBtYWtlVGltaW5nQXN0KHRpbWluZ3MuZHVyYXRpb24sIHRpbWluZ3MuZGVsYXksIHRpbWluZ3MuZWFzaW5nKTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplQW5pbWF0aW9uT3B0aW9ucyhvcHRpb25zOiBBbmltYXRpb25PcHRpb25zfG51bGwpOiBBbmltYXRpb25PcHRpb25zIHtcbiAgaWYgKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gY29weU9iaihvcHRpb25zKTtcbiAgICBpZiAob3B0aW9uc1sncGFyYW1zJ10pIHtcbiAgICAgIG9wdGlvbnNbJ3BhcmFtcyddID0gbm9ybWFsaXplUGFyYW1zKG9wdGlvbnNbJ3BhcmFtcyddKSE7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIG9wdGlvbnMgPSB7fTtcbiAgfVxuICByZXR1cm4gb3B0aW9ucztcbn1cblxuZnVuY3Rpb24gbWFrZVRpbWluZ0FzdChkdXJhdGlvbjogbnVtYmVyLCBkZWxheTogbnVtYmVyLCBlYXNpbmc6IHN0cmluZ3xudWxsKTogVGltaW5nQXN0IHtcbiAgcmV0dXJuIHtkdXJhdGlvbiwgZGVsYXksIGVhc2luZ307XG59XG4iXX0=