package.esm2022.browser.src.dsl.animation_ast_builder.mjs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of animations Show documentation
Show all versions of animations Show documentation
Angular - animations integration with web-animations
/**
* @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.dev/license
*/
import { AnimationMetadataType, 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 { extractStyleParams, 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 == 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 == AnimationMetadataType.Transition) {
const transition = this.visitTransition(def, context);
queryCount += transition.queryCount;
depCount += transition.depCount;
transitions.push(transition);
}
else {
context.errors.push(invalidDefinition());
}
});
return {
type: 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) {
context.errors.push(invalidState(metadata.name, [...missingSubs.values()]));
}
}
return {
type: 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: AnimationMetadataType.Transition,
matchers,
animation,
queryCount: context.queryCount,
depCount: context.depCount,
options: normalizeAnimationOptions(metadata.options),
};
}
visitSequence(metadata, context) {
return {
type: 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: 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 == 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: 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(new Map(Object.entries(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: 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: 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: AnimationMetadataType.Reference,
animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context),
options: normalizeAnimationOptions(metadata.options),
};
}
visitAnimateChild(metadata, context) {
context.depCount++;
return {
type: AnimationMetadataType.AnimateChild,
options: normalizeAnimationOptions(metadata.options),
};
}
visitAnimateRef(metadata, context) {
return {
type: 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: 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: 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 ? { ...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 = { ...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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5pbWF0aW9uX2FzdF9idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvYW5pbWF0aW9ucy9icm93c2VyL3NyYy9kc2wvYW5pbWF0aW9uX2FzdF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFRTCxxQkFBcUIsRUFXckIsVUFBVSxFQUNWLEtBQUssR0FFTixNQUFNLHFCQUFxQixDQUFDO0FBRTdCLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFDYix3QkFBd0IsRUFFeEIsY0FBYyxFQUNkLFlBQVksRUFDWixpQkFBaUIsRUFDakIsY0FBYyxFQUNkLHlCQUF5QixFQUN6Qix1QkFBdUIsR0FDeEIsTUFBTSxrQkFBa0IsQ0FBQztBQUUxQixPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUN0RCxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLHFCQUFxQixFQUNyQixtQkFBbUIsRUFDbkIsdUJBQXVCLEVBQ3ZCLGFBQWEsRUFDYix1QkFBdUIsRUFDdkIsbUJBQW1CLEVBQ25CLFlBQVksR0FDYixNQUFNLFNBQVMsQ0FBQztBQUNqQixPQUFPLEVBQUMsaUNBQWlDLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQXFCckUsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sNkJBQTZCLENBQUM7QUFFaEUsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDO0FBQzNCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxNQUFNLENBQUMsS0FBSyxVQUFVLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztBQUVoRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQ0c7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQy9CLE1BQXVCLEVBQ3ZCLFFBQWlELEVBQ2pELE1BQWUsRUFDZixRQUFrQjtJ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QyxDQUFDO0FBQ25DLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5kZXYvbGljZW5zZVxuICovXG5pbXBvcnQge1xuICBBbmltYXRlVGltaW5ncyxcbiAgQW5pbWF0aW9uQW5pbWF0ZUNoaWxkTWV0YWRhdGEsXG4gIEFuaW1hdGlvbkFuaW1hdGVNZXRhZGF0YSxcbiAgQW5pbWF0aW9uQW5pbWF0ZVJlZk1ldGFkYXRhLFxuICBBbmltYXRpb25Hcm91cE1ldGFkYXRhLFxuICBBbmltYXRpb25LZXlmcmFtZXNTZXF1ZW5jZU1ldGFkYXRhLFxuICBBbmltYXRpb25NZXRhZGF0YSxcbiAgQW5pbWF0aW9uTWV0YWRhdGFUeXBlLFxuICBBbmltYXRpb25PcHRpb25zLFxuICBBbmltYXRpb25RdWVyeU1ldGFkYXRhLFxuICBBbmltYXRpb25RdWVyeU9wdGlvbnMsXG4gIEFuaW1hdGlvblJlZmVyZW5jZU1ldGFkYXRhLFxuICBBbmltYXRpb25TZXF1ZW5jZU1ldGFkYXRhLFxuICBBbmltYXRpb25TdGFnZ2VyTWV0YWRhdGEsXG4gIEFuaW1hdGlvblN0YXRlTWV0YWRhdGEsXG4gIEFuaW1hdGlvblN0eWxlTWV0YWRhdGEsXG4gIEFuaW1hdGlvblRyYW5zaXRpb25NZXRhZGF0YSxcbiAgQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhLFxuICBBVVRPX1NUWUxFLFxuICBzdHlsZSxcbiAgybVTdHlsZURhdGFNYXAsXG59IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuXG5pbXBvcnQge1xuICBpbnZhbGlkRGVmaW5pdGlvbixcbiAgaW52YWxpZEtleWZyYW1lcyxcbiAgaW52YWxpZE9mZnNldCxcbiAgaW52YWxpZFBhcmFsbGVsQW5pbWF0aW9uLFxuICBpbnZhbGlkUHJvcGVydHksXG4gIGludmFsaWRTdGFnZ2VyLFxuICBpbnZhbGlkU3RhdGUsXG4gIGludmFsaWRTdHlsZVZhbHVlLFxuICBpbnZhbGlkVHJpZ2dlcixcbiAga2V5ZnJhbWVPZmZzZXRzT3V0T2ZPcmRlcixcbiAga2V5ZnJhbWVzTWlzc2luZ09mZnNldHMsXG59IGZyb20gJy4uL2Vycm9yX2hlbHBlcnMnO1xuaW1wb3J0IHtBbmltYXRpb25Ecml2ZXJ9IGZyb20gJy4uL3JlbmRlci9hbmltYXRpb25fZHJpdmVyJztcbmltcG9ydCB7Z2V0T3JTZXREZWZhdWx0VmFsdWV9IGZyb20gJy4uL3JlbmRlci9zaGFyZWQnO1xuaW1wb3J0IHtcbiAgZXh0cmFjdFN0eWxlUGFyYW1zLFxuICBOR19BTklNQVRJTkdfU0VMRUNUT1IsXG4gIE5HX1RSSUdHRVJfU0VMRUNUT1IsXG4gIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5LFxuICByZXNvbHZlVGltaW5nLFxuICBTVUJTVElUVVRJT05fRVhQUl9TVEFSVCxcbiAgdmFsaWRhdGVTdHlsZVBhcmFtcyxcbiAgdmlzaXREc2xOb2RlLFxufSBmcm9tICcuLi91dGlsJztcbmltcG9ydCB7cHVzaFVucmVjb2duaXplZFByb3BlcnRpZXNXYXJuaW5nfSBmcm9tICcuLi93YXJuaW5nX2hlbHBlcnMnO1xuXG5pbXBvcnQge1xuICBBbmltYXRlQXN0LFxuICBBbmltYXRlQ2hpbGRBc3QsXG4gIEFuaW1hdGVSZWZBc3QsXG4gIEFzdCxcbiAgRHluYW1pY1RpbWluZ0FzdCxcbiAgR3JvdXBBc3QsXG4gIEtleWZyYW1lc0FzdCxcbiAgUXVlcnlBc3QsXG4gIFJlZmVyZW5jZUFzdCxcbiAgU2VxdWVuY2VBc3QsXG4gIFN0YWdnZXJBc3QsXG4gIFN0YXRlQXN0LFxuICBTdHlsZUFzdCxcbiAgVGltaW5nQXN0LFxuICBUcmFuc2l0aW9uQXN0LFxuICBUcmlnZ2VyQXN0LFxufSBmcm9tICcuL2FuaW1hdGlvbl9hc3QnO1xuaW1wb3J0IHtBbmltYXRpb25Ec2xWaXNpdG9yfSBmcm9tICcuL2FuaW1hdGlvbl9kc2xfdmlzaXRvcic7XG5pbXBvcnQge3BhcnNlVHJhbnNpdGlvbkV4cHJ9IGZyb20gJy4vYW5pbWF0aW9uX3RyYW5zaXRpb25fZXhwcic7XG5cbmNvbnN0IFNFTEZfVE9LRU4gPSAnOnNlbGYnO1xuY29uc3QgU0VMRl9UT0tFTl9SRUdFWCA9IG5ldyBSZWdFeHAoYHMqJHtTRUxGX1RPS0VOfXMqLD9gLCAnZycpO1xuXG4vKlxuICogW1ZhbGlkYXRpb25dXG4gKiBUaGUgdmlzaXRvciBjb2RlIGJlbG93IHdpbGwgdHJhdmVyc2UgdGhlIGFuaW1hdGlvbiBBU1QgZ2VuZXJhdGVkIGJ5IHRoZSBhbmltYXRpb24gdmVyYiBmdW5jdGlvbnNcbiAqICh0aGUgb3V0cHV0IGlzIGEgdHJlZSBvZiBvYmplY3RzKSBhbmQgYXR0ZW1wdCB0byBwZXJmb3JtIGEgc2VyaWVzIG9mIHZhbGlkYXRpb25zIG9uIHRoZSBkYXRhLiBUaGVcbiAqIGZvbGxvd2luZyBjb3JuZXItY2FzZXMgd2lsbCBiZSB2YWxpZGF0ZWQ6XG4gKlxuICogMS4gT3ZlcmxhcCBvZiBhbmltYXRpb25zXG4gKiBHaXZlbiB0aGF0IGEgQ1NTIHByb3BlcnR5IGNhbm5vdCBiZSBhbmltYXRlZCBpbiBtb3JlIHRoYW4gb25lIHBsYWNlIGF0IHRoZSBzYW1lIHRpbWUsIGl0J3NcbiAqIGltcG9ydGFudCB0aGF0IHRoaXMgYmVoYXZpb3IgaXMgZGV0ZWN0ZWQgYW5kIHZhbGlkYXRlZC4gVGhlIHdheSBpbiB3aGljaCB0aGlzIG9jY3VycyBpcyB0aGF0XG4gKiBlYWNoIHRpbWUgYSBzdHlsZSBwcm9wZXJ0eSBpcyBleGFtaW5lZCwgYSBzdHJpbmctbWFwIGNvbnRhaW5pbmcgdGhlIHByb3BlcnR5IHdpbGwgYmUgdXBkYXRlZCB3aXRoXG4gKiB0aGUgc3RhcnQgYW5kIGVuZCB0aW1lcyBmb3Igd2hlbiB0aGUgcHJvcGVydHkgaXMgdXNlZCB3aXRoaW4gYW4gYW5pbWF0aW9uIHN0ZXAuXG4gKlxuICogSWYgdGhlcmUgYXJlIHR3byBvciBtb3JlIHBhcmFsbGVsIGFuaW1hdGlvbnMgdGhhdCBhcmUgY3VycmVudGx5IHJ1bm5pbmcgKHRoZXNlIGFyZSBpbnZva2VkIGJ5IHRoZVxuICogZ3JvdXAoKSkgb24gdGhlIHNhbWUgZWxlbWVudCB0aGVuIHRoZSB2YWxpZGF0b3Igd2lsbCB0aHJvdyBhbiBlcnJvci4gU2luY2UgdGhlIHN0YXJ0L2VuZCB0aW1pbmdcbiAqIHZhbHVlcyBhcmUgY29sbGVjdGVkIGZvciBlYWNoIHByb3BlcnR5IHRoZW4gaWYgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIHN0ZXAgaXMgYW5pbWF0aW5nIHRoZSBzYW1lXG4gKiBwcm9wZXJ0eSBhbmQgaXRzIHRpbWluZyB2YWx1ZXMgZmFsbCBhbnl3aGVyZSBpbnRvIHRoZSB3aW5kb3cgb2YgdGltZSB0aGF0IHRoZSBwcm9wZXJ0eSBpc1xuICogY3VycmVudGx5IGJlaW5nIGFuaW1hdGVkIHdpdGhpbiB0aGVuIHRoaXMgaXMgd2hhdCBjYXVzZXMgYW4gZXJyb3IuXG4gKlxuICogMi4gVGltaW5nIHZhbHVlc1xuICogVGhlIHZhbGlkYXRvciB3aWxsIHZhbGlkYXRlIHRvIHNlZSBpZiBhIHRpbWluZyB2YWx1ZSBvZiBgZHVyYXRpb24gZGVsYXkgZWFzaW5nYCBvclxuICogYGR1cmF0aW9uTnVtYmVyYCBpcyB2YWxpZCBvciBub3QuXG4gKlxuICogKG5vdGUgdGhhdCB1cG9uIHZhbGlkYXRpb24gdGhlIGNvZGUgYmVsb3cgd2lsbCByZXBsYWNlIHRoZSB0aW1pbmcgZGF0YSB3aXRoIGFuIG9iamVjdCBjb250YWluaW5nXG4gKiB7ZHVyYXRpb24sZGVsYXksZWFzaW5nfS5cbiAqXG4gKiAzLiBPZmZzZXQgVmFsaWRhdGlvblxuICogRWFjaCBvZiB0aGUgc3R5bGUoKSBjYWxscyBhcmUgYWxsb3dlZCB0byBoYXZlIGFuIG9mZnNldCB2YWx1ZSB3aGVuIHBsYWNlZCBpbnNpZGUgb2Yga2V5ZnJhbWVzKCkuXG4gKiBPZmZzZXRzIHdpdGhpbiBrZXlmcmFtZXMoKSBhcmUgY29uc2lkZXJlZCB2YWxpZCB3aGVuOlxuICpcbiAqICAgLSBObyBvZmZzZXRzIGFyZSB1c2VkIGF0IGFsbFxuICogICAtIEVhY2ggc3R5bGUoKSBlbnRyeSBjb250YWlucyBhbiBvZmZzZXQgdmFsdWVcbiAqICAgLSBFYWNoIG9mZnNldCBpcyBiZXR3ZWVuIDAgYW5kIDFcbiAqICAgLSBFYWNoIG9mZnNldCBpcyBncmVhdGVyIHRvIG9yIGVxdWFsIHRoYW4gdGhlIHByZXZpb3VzIG9uZVxuICpcbiAqIE90aGVyd2lzZSBhbiBlcnJvciB3aWxsIGJlIHRocm93bi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQW5pbWF0aW9uQXN0KFxuICBkcml2ZXI6IEFuaW1hdGlvbkRyaXZlcixcbiAgbWV0YWRhdGE6IEFuaW1hdGlvbk1ldGFkYXRhIHwgQW5pbWF0aW9uTWV0YWRhdGFbXSxcbiAgZXJyb3JzOiBFcnJvcltdLFxuICB3YXJuaW5nczogc3RyaW5nW10sXG4pOiBBc3Q8QW5pbWF0aW9uTWV0YWRhdGFUeXBlPiB7XG4gIHJldHVybiBuZXcgQW5pbWF0aW9uQXN0QnVpbGRlclZpc2l0b3IoZHJpdmVyKS5idWlsZChtZXRhZGF0YSwgZXJyb3JzLCB3YXJuaW5ncyk7XG59XG5cbmNvbnN0IFJPT1RfU0VMRUNUT1IgPSAnJztcblxuZXhwb3J0IGNsYXNzIEFuaW1hdGlvbkFzdEJ1aWxkZXJWaXNpdG9yIGltcGxlbWVudHMgQW5pbWF0aW9uRHNsVmlzaXRvciB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2RyaXZlcjogQW5pbWF0aW9uRHJpdmVyKSB7fVxuXG4gIGJ1aWxkKFxuICAgIG1ldGFkYXRhOiBBbmltYXRpb25NZXRhZGF0YSB8IEFuaW1hdGlvbk1ldGFkYXRhW10sXG4gICAgZXJyb3JzOiBFcnJvcltdLFxuICAgIHdhcm5pbmdzOiBzdHJpbmdbXSxcbiAgKTogQXN0PEFuaW1hdGlvbk1ldGFkYXRhVHlwZT4ge1xuICAgIGNvbnN0IGNvbnRleHQgPSBuZXcgQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQoZXJyb3JzKTtcbiAgICB0aGlzLl9yZXNldENvbnRleHRTdHlsZVRpbWluZ1N0YXRlKGNvbnRleHQpO1xuICAgIGNvbnN0IGFzdCA9IDxBc3Q8QW5pbWF0aW9uTWV0YWRhdGFUeXBlPj4oXG4gICAgICB2aXNpdERzbE5vZGUodGhpcywgbm9ybWFsaXplQW5pbWF0aW9uRW50cnkobWV0YWRhdGEpLCBjb250ZXh0KVxuICAgICk7XG5cbiAgICBpZiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSB7XG4gICAgICBpZiAoY29udGV4dC51bnN1cHBvcnRlZENTU1Byb3BlcnRpZXNGb3VuZC5zaXplKSB7XG4gICAgICAgIHB1c2hVbnJlY29nbml6ZWRQcm9wZXJ0aWVzV2FybmluZyh3YXJuaW5ncywgW1xuICAgICAgICAgIC4uLmNvbnRleHQudW5zdXBwb3J0ZWRDU1NQcm9wZXJ0aWVzRm91bmQua2V5cygpLFxuICAgICAgICBdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVzZXRDb250ZXh0U3R5bGVUaW1pbmdTdGF0ZShjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCkge1xuICAgIGNvbnRleHQuY3VycmVudFF1ZXJ5U2VsZWN0b3IgPSBST09UX1NFTEVDVE9SO1xuICAgIGNvbnRleHQuY29sbGVjdGVkU3R5bGVzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIFN0eWxlVGltZVR1cGxlPj4oKTtcbiAgICBjb250ZXh0LmNvbGxlY3RlZFN0eWxlcy5zZXQoUk9PVF9TRUxFQ1RPUiwgbmV3IE1hcCgpKTtcbiAgICBjb250ZXh0LmN1cnJlbnRUaW1lID0gMDtcbiAgfVxuXG4gIHZpc2l0VHJpZ2dlcihcbiAgICBtZXRhZGF0YTogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhLFxuICAgIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0LFxuICApOiBUcmlnZ2VyQXN0IHtcbiAgICBsZXQgcXVlcnlDb3VudCA9IChjb250ZXh0LnF1ZXJ5Q291bnQgPSAwKTtcbiAgICBsZXQgZGVwQ291bnQgPSAoY29udGV4dC5kZXBDb3VudCA9IDApO1xuICAgIGNvbnN0IHN0YXRlczogU3RhdGVBc3RbXSA9IFtdO1xuICAgIGNvbnN0IHRyYW5zaXRpb25zOiBUcmFuc2l0aW9uQXN0W10gPSBbXTtcbiAgICBpZiAobWV0YWRhdGEubmFtZS5jaGFyQXQoMCkgPT0gJ0AnKSB7XG4gICAgICBjb250ZXh0LmVycm9ycy5wdXNoKGludmFsaWRUcmlnZ2VyKCkpO1xuICAgIH1cblxuICAgIG1ldGFkYXRhLmRlZmluaXRpb25zLmZvckVhY2goKGRlZikgPT4ge1xuICAgICAgdGhpcy5fcmVzZXRDb250ZXh0U3R5bGVUaW1pbmdTdGF0ZShjb250ZXh0KTtcbiAgICAgIGlmIChkZWYudHlwZSA9PSBBbmltYXRpb25NZXRhZGF0YVR5cGUuU3RhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhdGVEZWYgPSBkZWYgYXMgQW5pbWF0aW9uU3RhdGVNZXRhZGF0YTtcbiAgICAgICAgY29uc3QgbmFtZSA9IHN0YXRlRGVmLm5hbWU7XG4gICAgICAgIG5hbWVcbiAgICAgICAgICAudG9TdHJpbmcoKVxuICAgICAgICAgIC5zcGxpdCgvXFxzKixcXHMqLylcbiAgICAgICAgICAuZm9yRWFjaCgobikgPT4ge1xuICAgICAgICAgICAgc3RhdGVEZWYubmFtZSA9IG47XG4gICAgICAgICAgICBzdGF0ZXMucHVzaCh0aGlzLnZpc2l0U3RhdGUoc3RhdGVEZWYsIGNvbnRleHQpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgc3RhdGVEZWYubmFtZSA9IG5hbWU7XG4gICAgICB9IGVsc2UgaWYgKGRlZi50eXBlID09IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5UcmFuc2l0aW9uKSB7XG4gICAgICAgIGNvbnN0IHRyYW5zaXRpb24gPSB0aGlzLnZpc2l0VHJhbnNpdGlvbihkZWYgYXMgQW5pbWF0aW9uVHJhbnNpdGlvbk1ldGFkYXRhLCBjb250ZXh0KTtcbiAgICAgICAgcXVlcnlDb3VudCArPSB0cmFuc2l0aW9uLnF1ZXJ5Q291bnQ7XG4gICAgICAgIGRlcENvdW50ICs9IHRyYW5zaXRpb24uZGVwQ291bnQ7XG4gICAgICAgIHRyYW5zaXRpb25zLnB1c2godHJhbnNpdGlvbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZXh0LmVycm9ycy5wdXNoKGludmFsaWREZWZpbml0aW9uKCkpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5UcmlnZ2VyLFxuICAgICAgbmFtZTogbWV0YWRhdGEubmFtZSxcbiAgICAgIHN0YXRlcyxcbiAgICAgIHRyYW5zaXRpb25zLFxuICAgICAgcXVlcnlDb3VudCxcbiAgICAgIGRlcENvdW50LFxuICAgICAgb3B0aW9uczogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRTdGF0ZShtZXRhZGF0YTogQW5pbWF0aW9uU3RhdGVNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBTdGF0ZUFzdCB7XG4gICAgY29uc3Qgc3R5bGVBc3QgPSB0aGlzLnZpc2l0U3R5bGUobWV0YWRhdGEuc3R5bGVzLCBjb250ZXh0KTtcbiAgICBjb25zdCBhc3RQYXJhbXMgPSAobWV0YWRhdGEub3B0aW9ucyAmJiBtZXRhZGF0YS5vcHRpb25zLnBhcmFtcykgfHwgbnVsbDtcbiAgICBpZiAoc3R5bGVBc3QuY29udGFpbnNEeW5hbWljU3R5bGVzKSB7XG4gICAgICBjb25zdCBtaXNzaW5nU3VicyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgY29uc3QgcGFyYW1zID0gYXN0UGFyYW1zIHx8IHt9O1xuICAgICAgc3R5bGVBc3Quc3R5bGVzLmZvckVhY2goKHN0eWxlKSA9PiB7XG4gICAgICAgIGlmIChzdHlsZSBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICAgIHN0eWxlLmZvckVhY2goKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBleHRyYWN0U3R5bGVQYXJhbXModmFsdWUpLmZvckVhY2goKHN1YikgPT4ge1xuICAgICAgICAgICAgICBpZiAoIXBhcmFtcy5oYXNPd25Qcm9wZXJ0eShzdWIpKSB7XG4gICAgICAgICAgICAgICAgbWlzc2luZ1N1YnMuYWRkKHN1Yik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGlmIChtaXNzaW5nU3Vicy5zaXplKSB7XG4gICAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goaW52YWxpZFN0YXRlKG1ldGFkYXRhLm5hbWUsIFsuLi5taXNzaW5nU3Vicy52YWx1ZXMoKV0pKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlN0YXRlLFxuICAgICAgbmFtZTogbWV0YWRhdGEubmFtZSxcbiAgICAgIHN0eWxlOiBzdHlsZUFzdCxcbiAgICAgIG9wdGlvbnM6IGFzdFBhcmFtcyA/IHtwYXJhbXM6IGFzdFBhcmFtc30gOiBudWxsLFxuICAgIH07XG4gIH1cblxuICB2aXNpdFRyYW5zaXRpb24oXG4gICAgbWV0YWRhdGE6IEFuaW1hdGlvblRyYW5zaXRpb25NZXRhZGF0YSxcbiAgICBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCxcbiAgKTogVHJhbnNpdGlvbkFzdCB7XG4gICAgY29udGV4dC5xdWVyeUNvdW50ID0gMDtcbiAgICBjb250ZXh0LmRlcENvdW50ID0gMDtcbiAgICBjb25zdCBhbmltYXRpb24gPSB2aXNpdERzbE5vZGUodGhpcywgbm9ybWFsaXplQW5pbWF0aW9uRW50cnkobWV0YWRhdGEuYW5pbWF0aW9uKSwgY29udGV4dCk7XG4gICAgY29uc3QgbWF0Y2hlcnMgPSBwYXJzZVRyYW5zaXRpb25FeHByKG1ldGFkYXRhLmV4cHIsIGNvbnRleHQuZXJyb3JzKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuVHJhbnNpdGlvbixcbiAgICAgIG1hdGNoZXJzLFxuICAgICAgYW5pbWF0aW9uLFxuICAgICAgcXVlcnlDb3VudDogY29udGV4dC5xdWVyeUNvdW50LFxuICAgICAgZGVwQ291bnQ6IGNvbnRleHQuZGVwQ291bnQsXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpLFxuICAgIH07XG4gIH1cblxuICB2aXNpdFNlcXVlbmNlKFxuICAgIG1ldGFkYXRhOiBBbmltYXRpb25TZXF1ZW5jZU1ldGFkYXRhLFxuICAgIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0LFxuICApOiBTZXF1ZW5jZUFzdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5TZXF1ZW5jZSxcbiAgICAgIHN0ZXBzOiBtZXRhZGF0YS5zdGVwcy5tYXAoKHMpID0+IHZpc2l0RHNsTm9kZSh0aGlzLCBzLCBjb250ZXh0KSksXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpLFxuICAgIH07XG4gIH1cblxuICB2aXNpdEdyb3VwKG1ldGFkYXRhOiBBbmltYXRpb25Hcm91cE1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6IEdyb3VwQXN0IHtcbiAgICBjb25zdCBjdXJyZW50VGltZSA9IGNvbnRleHQuY3VycmVudFRpbWU7XG4gICAgbGV0IGZ1cnRoZXN0VGltZSA9IDA7XG4gICAgY29uc3Qgc3RlcHMgPSBtZXRhZGF0YS5zdGVwcy5tYXAoKHN0ZXApID0+IHtcbiAgICAgIGNvbnRleHQuY3VycmVudFRpbWUgPSBjdXJyZW50VGltZTtcbiAgICAgIGNvbnN0IGlubmVyQXN0ID0gdmlzaXREc2xOb2RlKHRoaXMsIHN0ZXAsIGNvbnRleHQpO1xuICAgICAgZnVydGhlc3RUaW1lID0gTWF0aC5tYXgoZnVydGhlc3RUaW1lLCBjb250ZXh0LmN1cnJlbnRUaW1lKTtcbiAgICAgIHJldHVybiBpbm5lckFzdDtcbiAgICB9KTtcblxuICAgIGNvbnRleHQuY3VycmVudFRpbWUgPSBmdXJ0aGVzdFRpbWU7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5Hcm91cCxcbiAgICAgIHN0ZXBzLFxuICAgICAgb3B0aW9uczogbm9ybWFsaXplQW5pbWF0aW9uT3B0aW9ucyhtZXRhZGF0YS5vcHRpb25zKSxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRBbmltYXRlKFxuICAgIG1ldGFkYXRhOiBBbmltYXRpb25BbmltYXRlTWV0YWRhdGEsXG4gICAgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQsXG4gICk6IEFuaW1hdGVBc3Qge1xuICAgIGNvbnN0IHRpbWluZ0FzdCA9IGNvbnN0cnVjdFRpbWluZ0FzdChtZXRhZGF0YS50aW1pbmdzLCBjb250ZXh0LmVycm9ycyk7XG4gICAgY29udGV4dC5jdXJyZW50QW5pbWF0ZVRpbWluZ3MgPSB0aW1pbmdBc3Q7XG4gICAgbGV0IHN0eWxlQXN0OiBTdHlsZUFzdCB8IEtleWZyYW1lc0FzdDtcbiAgICBsZXQgc3R5bGVNZXRhZGF0YTogQW5pbWF0aW9uU3R5bGVNZXRhZGF0YSB8IEFuaW1hdGlvbktleWZyYW1lc1NlcXVlbmNlTWV0YWRhdGEgPSBtZXRhZGF0YS5zdHlsZXNcbiAgICAgID8gbWV0YWRhdGEuc3R5bGVzXG4gICAgICA6IHN0eWxlKHt9KTtcbiAgICBpZiAoc3R5bGVNZXRhZGF0YS50eXBlID09IEFuaW1hdGlvbk1ldGFkYXRhVHlwZS5LZXlmcmFtZXMpIHtcbiAgICAgIHN0eWxlQXN0ID0gdGhpcy52aXNpdEtleWZyYW1lcyhzdHlsZU1ldGFkYXRhIGFzIEFuaW1hdGlvbktleWZyYW1lc1NlcXVlbmNlTWV0YWRhdGEsIGNvbnRleHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgc3R5bGVNZXRhZGF0YSA9IG1ldGFkYXRhLnN0eWxlcyBhcyBBbmltYXRpb25TdHlsZU1ldGFkYXRhO1xuICAgICAgbGV0IGlzRW1wdHkgPSBmYWxzZTtcbiAgICAgIGlmICghc3R5bGVNZXRhZGF0YSkge1xuICAgICAgICBpc0VtcHR5ID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgbmV3U3R5bGVEYXRhOiB7W3Byb3A6IHN0cmluZ106IHN0cmluZyB8IG51bWJlcn0gPSB7fTtcbiAgICAgICAgaWYgKHRpbWluZ0FzdC5lYXNpbmcpIHtcbiAgICAgICAgICBuZXdTdHlsZURhdGFbJ2Vhc2luZyddID0gdGltaW5nQXN0LmVhc2luZztcbiAgICAgICAgfVxuICAgICAgICBzdHlsZU1ldGFkYXRhID0gc3R5bGUobmV3U3R5bGVEYXRhKTtcbiAgICAgIH1cbiAgICAgIGNvbnRleHQuY3VycmVudFRpbWUgKz0gdGltaW5nQXN0LmR1cmF0aW9uICsgdGltaW5nQXN0LmRlbGF5O1xuICAgICAgY29uc3QgX3N0eWxlQXN0ID0gdGhpcy52aXNpdFN0eWxlKHN0eWxlTWV0YWRhdGEsIGNvbnRleHQpO1xuICAgICAgX3N0eWxlQXN0LmlzRW1wdHlTdGVwID0gaXNFbXB0eTtcbiAgICAgIHN0eWxlQXN0ID0gX3N0eWxlQXN0O1xuICAgIH1cblxuICAgIGNvbnRleHQuY3VycmVudEFuaW1hdGVUaW1pbmdzID0gbnVsbDtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLkFuaW1hdGUsXG4gICAgICB0aW1pbmdzOiB0aW1pbmdBc3QsXG4gICAgICBzdHlsZTogc3R5bGVBc3QsXG4gICAgICBvcHRpb25zOiBudWxsLFxuICAgIH07XG4gIH1cblxuICB2aXNpdFN0eWxlKG1ldGFkYXRhOiBBbmltYXRpb25TdHlsZU1ldGFkYXRhLCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6IFN0eWxlQXN0IHtcbiAgICBjb25zdCBhc3QgPSB0aGlzLl9tYWtlU3R5bGVBc3QobWV0YWRhdGEsIGNvbnRleHQpO1xuICAgIHRoaXMuX3ZhbGlkYXRlU3R5bGVBc3QoYXN0LCBjb250ZXh0KTtcbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgcHJpdmF0ZSBfbWFrZVN0eWxlQXN0KFxuICAgIG1ldGFkYXRhOiBBbmltYXRpb25TdHlsZU1ldGFkYXRhLFxuICAgIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0LFxuICApOiBTdHlsZUFzdCB7XG4gICAgY29uc3Qgc3R5bGVzOiBBcnJheTzJtVN0eWxlRGF0YU1hcCB8IHN0cmluZz4gPSBbXTtcbiAgICBjb25zdCBtZXRhZGF0YVN0eWxlcyA9IEFycmF5LmlzQXJyYXkobWV0YWRhdGEuc3R5bGVzKSA/IG1ldGFkYXRhLnN0eWxlcyA6IFttZXRhZGF0YS5zdHlsZXNdO1xuXG4gICAgZm9yIChsZXQgc3R5bGVUdXBsZSBvZiBtZXRhZGF0YVN0eWxlcykge1xuICAgICAgaWYgKHR5cGVvZiBzdHlsZVR1cGxlID09PSAnc3RyaW5nJykge1xuICAgICAgICBpZiAoc3R5bGVUdXBsZSA9PT0gQVVUT19TVFlMRSkge1xuICAgICAgICAgIHN0eWxlcy5wdXNoKHN0eWxlVHVwbGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goaW52YWxpZFN0eWxlVmFsdWUoc3R5bGVUdXBsZSkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHlsZXMucHVzaChuZXcgTWFwKE9iamVjdC5lbnRyaWVzKHN0eWxlVHVwbGUpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGNvbnRhaW5zRHluYW1pY1N0eWxlcyA9IGZhbHNlO1xuICAgIGxldCBjb2xsZWN0ZWRFYXNpbmc6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAgIHN0eWxlcy5mb3JFYWNoKChzdHlsZURhdGEpID0+IHtcbiAgICAgIGlmIChzdHlsZURhdGEgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgaWYgKHN0eWxlRGF0YS5oYXMoJ2Vhc2luZycpKSB7XG4gICAgICAgICAgY29sbGVjdGVkRWFzaW5nID0gc3R5bGVEYXRhLmdldCgnZWFzaW5nJykgYXMgc3RyaW5nO1xuICAgICAgICAgIHN0eWxlRGF0YS5kZWxldGUoJ2Vhc2luZycpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY29udGFpbnNEeW5hbWljU3R5bGVzKSB7XG4gICAgICAgICAgZm9yIChsZXQgdmFsdWUgb2Ygc3R5bGVEYXRhLnZhbHVlcygpKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUhLnRvU3RyaW5nKCkuaW5kZXhPZihTVUJTVElUVVRJT05fRVhQUl9TVEFSVCkgPj0gMCkge1xuICAgICAgICAgICAgICBjb250YWluc0R5bmFtaWNTdHlsZXMgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuU3R5bGUsXG4gICAgICBzdHlsZXMsXG4gICAgICBlYXNpbmc6IGNvbGxlY3RlZEVhc2luZyxcbiAgICAgIG9mZnNldDogbWV0YWRhdGEub2Zmc2V0LFxuICAgICAgY29udGFpbnNEeW5hbWljU3R5bGVzLFxuICAgICAgb3B0aW9uczogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBfdmFsaWRhdGVTdHlsZUFzdChhc3Q6IFN0eWxlQXN0LCBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCk6IHZvaWQge1xuICAgIGNvbnN0IHRpbWluZ3MgPSBjb250ZXh0LmN1cnJlbnRBbmltYXRlVGltaW5ncztcbiAgICBsZXQgZW5kVGltZSA9IGNvbnRleHQuY3VycmVudFRpbWU7XG4gICAgbGV0IHN0YXJ0VGltZSA9IGNvbnRleHQuY3VycmVudFRpbWU7XG4gICAgaWYgKHRpbWluZ3MgJiYgc3RhcnRUaW1lID4gMCkge1xuICAgICAgc3RhcnRUaW1lIC09IHRpbWluZ3MuZHVyYXRpb24gKyB0aW1pbmdzLmRlbGF5O1xuICAgIH1cblxuICAgIGFzdC5zdHlsZXMuZm9yRWFjaCgodHVwbGUpID0+IHtcbiAgICAgIGlmICh0eXBlb2YgdHVwbGUgPT09ICdzdHJpbmcnKSByZXR1cm47XG5cbiAgICAgIHR1cGxlLmZvckVhY2goKHZhbHVlLCBwcm9wKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgbmdEZXZNb2RlID09PSAndW5kZWZpbmVkJyB8fCBuZ0Rldk1vZGUpIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX2RyaXZlci52YWxpZGF0ZVN0eWxlUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgIHR1cGxlLmRlbGV0ZShwcm9wKTtcbiAgICAgICAgICAgIGNvbnRleHQudW5zdXBwb3J0ZWRDU1NQcm9wZXJ0aWVzRm91bmQuYWRkKHByb3ApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoaXMgaXMgZ3VhcmFudGVlZCB0byBoYXZlIGEgZGVmaW5lZCBNYXAgYXQgdGhpcyBxdWVyeVNlbGVjdG9yIGxvY2F0aW9uIG1ha2luZyBpdFxuICAgICAgICAvLyBzYWZlIHRvIGFkZCB0aGUgYXNzZXJ0aW9uIGhlcmUuIEl0IGlzIHNldCBhcyBhIGRlZmF1bHQgZW1wdHkgbWFwIGluIHByaW9yIG1ldGhvZHMuXG4gICAgICAgIGNvbnN0IGNvbGxlY3RlZFN0eWxlcyA9IGNvbnRleHQuY29sbGVjdGVkU3R5bGVzLmdldChjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yISkhO1xuICAgICAgICBjb25zdCBjb2xsZWN0ZWRFbnRyeSA9IGNvbGxlY3RlZFN0eWxlcy5nZXQocHJvcCk7XG4gICAgICAgIGxldCB1cGRhdGVDb2xsZWN0ZWRTdHlsZSA9IHRydWU7XG4gICAgICAgIGlmIChjb2xsZWN0ZWRFbnRyeSkge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHN0YXJ0VGltZSAhPSBlbmRUaW1lICYmXG4gICAgICAgICAgICBzdGFydFRpbWUgPj0gY29sbGVjdGVkRW50cnkuc3RhcnRUaW1lICYmXG4gICAgICAgICAgICBlbmRUaW1lIDw9IGNvbGxlY3RlZEVudHJ5LmVuZFRpbWVcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goXG4gICAgICAgICAgICAgIGludmFsaWRQYXJhbGxlbEFuaW1hdGlvbihcbiAgICAgICAgICAgICAgICBwcm9wLFxuICAgICAgICAgICAgICAgIGNvbGxlY3RlZEVudHJ5LnN0YXJ0VGltZSxcbiAgICAgICAgICAgICAgICBjb2xsZWN0ZWRFbnRyeS5lbmRUaW1lLFxuICAgICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgICAgICBlbmRUaW1lLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHVwZGF0ZUNvbGxlY3RlZFN0eWxlID0gZmFsc2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gd2UgYWx3YXlzIGNob29zZSB0aGUgc21hbGxlciBzdGFydCB0aW1lIHZhbHVlIHNpbmNlIHdlXG4gICAgICAgICAgLy8gd2FudCB0byBoYXZlIGEgcmVjb3JkIG9mIHRoZSBlbnRpcmUgYW5pbWF0aW9uIHdpbmRvdyB3aGVyZVxuICAgICAgICAgIC8vIHRoZSBzdHlsZSBwcm9wZXJ0eSBpcyBiZWluZyBhbmltYXRlZCBpbiBiZXR3ZWVuXG4gICAgICAgICAgc3RhcnRUaW1lID0gY29sbGVjdGVkRW50cnkuc3RhcnRUaW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVwZGF0ZUNvbGxlY3RlZFN0eWxlKSB7XG4gICAgICAgICAgY29sbGVjdGVkU3R5bGVzLnNldChwcm9wLCB7c3RhcnRUaW1lLCBlbmRUaW1lfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dC5vcHRpb25zKSB7XG4gICAgICAgICAgdmFsaWRhdGVTdHlsZVBhcmFtcyh2YWx1ZSwgY29udGV4dC5vcHRpb25zLCBjb250ZXh0LmVycm9ycyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgdmlzaXRLZXlmcmFtZXMoXG4gICAgbWV0YWRhdGE6IEFuaW1hdGlvbktleWZyYW1lc1NlcXVlbmNlTWV0YWRhdGEsXG4gICAgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQsXG4gICk6IEtleWZyYW1lc0FzdCB7XG4gICAgY29uc3QgYXN0OiBLZXlmcmFtZXNBc3QgPSB7dHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLktleWZyYW1lcywgc3R5bGVzOiBbXSwgb3B0aW9uczogbnVsbH07XG4gICAgaWYgKCFjb250ZXh0LmN1cnJlbnRBbmltYXRlVGltaW5ncykge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkS2V5ZnJhbWVzKCkpO1xuICAgICAgcmV0dXJuIGFzdDtcbiAgICB9XG5cbiAgICBjb25zdCBNQVhfS0VZRlJBTUVfT0ZGU0VUID0gMTtcblxuICAgIGxldCB0b3RhbEtleWZyYW1lc1dpdGhPZmZzZXRzID0gMDtcbiAgICBjb25zdCBvZmZzZXRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGxldCBvZmZzZXRzT3V0T2ZPcmRlciA9IGZhbHNlO1xuICAgIGxldCBrZXlmcmFtZXNPdXRPZlJhbmdlID0gZmFsc2U7XG4gICAgbGV0IHByZXZpb3VzT2Zmc2V0OiBudW1iZXIgPSAwO1xuXG4gICAgY29uc3Qga2V5ZnJhbWVzOiBTdHlsZUFzdFtdID0gbWV0YWRhdGEuc3RlcHMubWFwKChzdHlsZXMpID0+IHtcbiAgICAgIGNvbnN0IHN0eWxlID0gdGhpcy5fbWFrZVN0eWxlQXN0KHN0eWxlcywgY29udGV4dCk7XG4gICAgICBsZXQgb2Zmc2V0VmFsOiBudW1iZXIgfCBudWxsID1cbiAgICAgICAgc3R5bGUub2Zmc2V0ICE9IG51bGwgPyBzdHlsZS5vZmZzZXQgOiBjb25zdW1lT2Zmc2V0KHN0eWxlLnN0eWxlcyk7XG4gICAgICBsZXQgb2Zmc2V0OiBudW1iZXIgPSAwO1xuICAgICAgaWYgKG9mZnNldFZhbCAhPSBudWxsKSB7XG4gICAgICAgIHRvdGFsS2V5ZnJhbWVzV2l0aE9mZnNldHMrKztcbiAgICAgICAgb2Zmc2V0ID0gc3R5bGUub2Zmc2V0ID0gb2Zmc2V0VmFsO1xuICAgICAgfVxuICAgICAga2V5ZnJhbWVzT3V0T2ZSYW5nZSA9IGtleWZyYW1lc091dE9mUmFuZ2UgfHwgb2Zmc2V0IDwgMCB8fCBvZmZzZXQgPiAxO1xuICAgICAgb2Zmc2V0c091dE9mT3JkZXIgPSBvZmZzZXRzT3V0T2ZPcmRlciB8fCBvZmZzZXQgPCBwcmV2aW91c09mZnNldDtcbiAgICAgIHByZXZpb3VzT2Zmc2V0ID0gb2Zmc2V0O1xuICAgICAgb2Zmc2V0cy5wdXNoKG9mZnNldCk7XG4gICAgICByZXR1cm4gc3R5bGU7XG4gICAgfSk7XG5cbiAgICBpZiAoa2V5ZnJhbWVzT3V0T2ZSYW5nZSkge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkT2Zmc2V0KCkpO1xuICAgIH1cblxuICAgIGlmIChvZmZzZXRzT3V0T2ZPcmRlcikge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChrZXlmcmFtZU9mZnNldHNPdXRPZk9yZGVyKCkpO1xuICAgIH1cblxuICAgIGNvbnN0IGxlbmd0aCA9IG1ldGFkYXRhLnN0ZXBzLmxlbmd0aDtcbiAgICBsZXQgZ2VuZXJhdGVkT2Zmc2V0ID0gMDtcbiAgICBpZiAodG90YWxLZXlmcmFtZXNXaXRoT2Zmc2V0cyA+IDAgJiYgdG90YWxLZXlmcmFtZXNXaXRoT2Zmc2V0cyA8IGxlbmd0aCkge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChrZXlmcmFtZXNNaXNzaW5nT2Zmc2V0cygpKTtcbiAgICB9IGVsc2UgaWYgKHRvdGFsS2V5ZnJhbWVzV2l0aE9mZnNldHMgPT0gMCkge1xuICAgICAgZ2VuZXJhdGVkT2Zmc2V0ID0gTUFYX0tFWUZSQU1FX09GRlNFVCAvIChsZW5ndGggLSAxKTtcbiAgICB9XG5cbiAgICBjb25zdCBsaW1pdCA9IGxlbmd0aCAtIDE7XG4gICAgY29uc3QgY3VycmVudFRpbWUgPSBjb250ZXh0LmN1cnJlbnRUaW1lO1xuICAgIGNvbnN0IGN1cnJlbnRBbmltYXRlVGltaW5ncyA9IGNvbnRleHQuY3VycmVudEFuaW1hdGVUaW1pbmdzITtcbiAgICBjb25zdCBhbmltYXRlRHVyYXRpb24gPSBjdXJyZW50QW5pbWF0ZVRpbWluZ3MuZHVyYXRpb247XG4gICAga2V5ZnJhbWVzLmZvckVhY2goKGtmLCBpKSA9PiB7XG4gICAgICBjb25zdCBvZmZzZXQgPSBnZW5lcmF0ZWRPZmZzZXQgPiAwID8gKGkgPT0gbGltaXQgPyAxIDogZ2VuZXJhdGVkT2Zmc2V0ICogaSkgOiBvZmZzZXRzW2ldO1xuICAgICAgY29uc3QgZHVyYXRpb25VcFRvVGhpc0ZyYW1lID0gb2Zmc2V0ICogYW5pbWF0ZUR1cmF0aW9uO1xuICAgICAgY29udGV4dC5jdXJyZW50VGltZSA9IGN1cnJlbnRUaW1lICsgY3VycmVudEFuaW1hdGVUaW1pbmdzLmRlbGF5ICsgZHVyYXRpb25VcFRvVGhpc0ZyYW1lO1xuICAgICAgY3VycmVudEFuaW1hdGVUaW1pbmdzLmR1cmF0aW9uID0gZHVyYXRpb25VcFRvVGhpc0ZyYW1lO1xuICAgICAgdGhpcy5fdmFsaWRhdGVTdHlsZUFzdChrZiwgY29udGV4dCk7XG4gICAgICBrZi5vZmZzZXQgPSBvZmZzZXQ7XG5cbiAgICAgIGFzdC5zdHlsZXMucHVzaChrZik7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgdmlzaXRSZWZlcmVuY2UoXG4gICAgbWV0YWRhdGE6IEFuaW1hdGlvblJlZmVyZW5jZU1ldGFkYXRhLFxuICAgIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0LFxuICApOiBSZWZlcmVuY2VBc3Qge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuUmVmZXJlbmNlLFxuICAgICAgYW5pbWF0aW9uOiB2aXNpdERzbE5vZGUodGhpcywgbm9ybWFsaXplQW5pbWF0aW9uRW50cnkobWV0YWRhdGEuYW5pbWF0aW9uKSwgY29udGV4dCksXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpLFxuICAgIH07XG4gIH1cblxuICB2aXNpdEFuaW1hdGVDaGlsZChcbiAgICBtZXRhZGF0YTogQW5pbWF0aW9uQW5pbWF0ZUNoaWxkTWV0YWRhdGEsXG4gICAgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQsXG4gICk6IEFuaW1hdGVDaGlsZEFzdCB7XG4gICAgY29udGV4dC5kZXBDb3VudCsrO1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuQW5pbWF0ZUNoaWxkLFxuICAgICAgb3B0aW9uczogbm9ybWFsaXplQW5pbWF0aW9uT3B0aW9ucyhtZXRhZGF0YS5vcHRpb25zKSxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRBbmltYXRlUmVmKFxuICAgIG1ldGFkYXRhOiBBbmltYXRpb25BbmltYXRlUmVmTWV0YWRhdGEsXG4gICAgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQsXG4gICk6IEFuaW1hdGVSZWZBc3Qge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuQW5pbWF0ZVJlZixcbiAgICAgIGFuaW1hdGlvbjogdGhpcy52aXNpdFJlZmVyZW5jZShtZXRhZGF0YS5hbmltYXRpb24sIGNvbnRleHQpLFxuICAgICAgb3B0aW9uczogbm9ybWFsaXplQW5pbWF0aW9uT3B0aW9ucyhtZXRhZGF0YS5vcHRpb25zKSxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRRdWVyeShtZXRhZGF0YTogQW5pbWF0aW9uUXVlcnlNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBRdWVyeUFzdCB7XG4gICAgY29uc3QgcGFyZW50U2VsZWN0b3IgPSBjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yITtcbiAgICBjb25zdCBvcHRpb25zID0gKG1ldGFkYXRhLm9wdGlvbnMgfHwge30pIGFzIEFuaW1hdGlvblF1ZXJ5T3B0aW9ucztcblxuICAgIGNvbnRleHQucXVlcnlDb3VudCsrO1xuICAgIGNvbnRleHQuY3VycmVudFF1ZXJ5ID0gbWV0YWRhdGE7XG4gICAgY29uc3QgW3NlbGVjdG9yLCBpbmNsdWRlU2VsZl0gPSBub3JtYWxpemVTZWxlY3RvcihtZXRhZGF0YS5zZWxlY3Rvcik7XG4gICAgY29udGV4dC5jdXJyZW50UXVlcnlTZWxlY3RvciA9IHBhcmVudFNlbGVjdG9yLmxlbmd0aFxuICAgICAgPyBwYXJlbnRTZWxlY3RvciArICcgJyArIHNlbGVjdG9yXG4gICAgICA6IHNlbGVjdG9yO1xuICAgIGdldE9yU2V0RGVmYXVsdFZhbHVlKGNvbnRleHQuY29sbGVjdGVkU3R5bGVzLCBjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yLCBuZXcgTWFwKCkpO1xuXG4gICAgY29uc3QgYW5pbWF0aW9uID0gdmlzaXREc2xOb2RlKHRoaXMsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5KG1ldGFkYXRhLmFuaW1hdGlvbiksIGNvbnRleHQpO1xuICAgIGNvbnRleHQuY3VycmVudFF1ZXJ5ID0gbnVsbDtcbiAgICBjb250ZXh0LmN1cnJlbnRRdWVyeVNlbGVjdG9yID0gcGFyZW50U2VsZWN0b3I7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlF1ZXJ5LFxuICAgICAgc2VsZWN0b3IsXG4gICAgICBsaW1pdDogb3B0aW9ucy5saW1pdCB8fCAwLFxuICAgICAgb3B0aW9uYWw6ICEhb3B0aW9ucy5vcHRpb25hbCxcbiAgICAgIGluY2x1ZGVTZWxmLFxuICAgICAgYW5pbWF0aW9uLFxuICAgICAgb3JpZ2luYWxTZWxlY3RvcjogbWV0YWRhdGEuc2VsZWN0b3IsXG4gICAgICBvcHRpb25zOiBub3JtYWxpemVBbmltYXRpb25PcHRpb25zKG1ldGFkYXRhLm9wdGlvbnMpLFxuICAgIH07XG4gIH1cblxuICB2aXNpdFN0YWdnZXIoXG4gICAgbWV0YWRhdGE6IEFuaW1hdGlvblN0YWdnZXJNZXRhZGF0YSxcbiAgICBjb250ZXh0OiBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dCxcbiAgKTogU3RhZ2dlckFzdCB7XG4gICAgaWYgKCFjb250ZXh0LmN1cnJlbnRRdWVyeSkge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChpbnZhbGlkU3RhZ2dlcigpKTtcbiAgICB9XG4gICAgY29uc3QgdGltaW5ncyA9XG4gICAgICBtZXRhZGF0YS50aW1pbmdzID09PSAnZnVsbCdcbiAgICAgICAgPyB7ZHVyYXRpb246IDAsIGRlbGF5OiAwLCBlYXNpbmc6ICdmdWxsJ31cbiAgICAgICAgOiByZXNvbHZlVGltaW5nKG1ldGFkYXRhLnRpbWluZ3MsIGNvbnRleHQuZXJyb3JzLCB0cnVlKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuU3RhZ2dlcixcbiAgICAgIGFuaW1hdGlvbjogdmlzaXREc2xOb2RlKHRoaXMsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5KG1ldGFkYXRhLmFuaW1hdGlvbiksIGNvbnRleHQpLFxuICAgICAgdGltaW5ncyxcbiAgICAgIG9wdGlvbnM6IG51bGwsXG4gICAgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVTZWxlY3RvcihzZWxlY3Rvcjogc3RyaW5nKTogW3N0cmluZywgYm9vbGVhbl0ge1xuICBjb25zdCBoYXNBbXBlcnNhbmQgPSBzZWxlY3Rvci5zcGxpdCgvXFxzKixcXHMqLykuZmluZCgodG9rZW4pID0+IHRva2VuID09IFNFTEZfVE9LRU4pXG4gICAgPyB0cnVlXG4gICAgOiBmYWxzZTtcbiAgaWYgKGhhc0FtcGVyc2FuZCkge1xuICAgIHNlbGVjdG9yID0gc2VsZWN0b3IucmVwbGFjZShTRUxGX1RPS0VOX1JFR0VYLCAnJyk7XG4gIH1cblxuICAvLyBOb3RlOiB0aGUgOmVudGVyIGFuZCA6bGVhdmUgYXJlbid0IG5vcm1hbGl6ZWQgaGVyZSBzaW5jZSB0aG9zZVxuICAvLyBzZWxlY3RvcnMgYXJlIGZpbGxlZCBpbiBhdCBydW50aW1lIGR1cmluZyB0aW1lbGluZSBidWlsZGluZ1xuICBzZWxlY3RvciA9IHNlbGVjdG9yXG4gICAgLnJlcGxhY2UoL0BcXCovZywgTkdfVFJJR0dFUl9TRUxFQ1RPUilcbiAgICAucmVwbGFjZSgvQFxcdysvZywgKG1hdGNoKSA9PiBOR19UUklHR0VSX1NFTEVDVE9SICsgJy0nICsgbWF0Y2guc2xpY2UoMSkpXG4gICAgLnJlcGxhY2UoLzphbmltYXRpbmcvZywgTkdfQU5JTUFUSU5HX1NFTEVDVE9SKTtcblxuICByZXR1cm4gW3NlbGVjdG9yLCBoYXNBbXBlcnNhbmRdO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemVQYXJhbXMob2JqOiB7W2tleTogc3RyaW5nXTogYW55fSB8IGFueSk6IHtba2V5OiBzdHJpbmddOiBhbnl9IHwgbnVsbCB7XG4gIHJldHVybiBvYmogPyB7Li4ub2JqfSA6IG51bGw7XG59XG5cbmV4cG9ydCB0eXBlIFN0eWxlVGltZVR1cGxlID0ge1xuICBzdGFydFRpbWU6IG51bWJlcjtcbiAgZW5kVGltZTogbnVtYmVyO1xufTtcblxuZXhwb3J0IGNsYXNzIEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0IHtcbiAgcHVibGljIHF1ZXJ5Q291bnQ6IG51bWJlciA9IDA7XG4gIHB1YmxpYyBkZXBDb3VudDogbnVtYmVyID0gMDtcbiAgcHVibGljIGN1cnJlbnRUcmFuc2l0aW9uOiBBbmltYXRpb25UcmFuc2l0aW9uTWV0YWRhdGEgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGN1cnJlbnRRdWVyeTogQW5pbWF0aW9uUXVlcnlNZXRhZGF0YSB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgY3VycmVudFF1ZXJ5U2VsZWN0b3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgY3VycmVudEFuaW1hdGVUaW1pbmdzOiBUaW1pbmdBc3QgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGN1cnJlbnRUaW1lOiBudW1iZXIgPSAwO1xuICBwdWJsaWMgY29sbGVjdGVkU3R5bGVzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIFN0eWxlVGltZVR1cGxlPj4oKTtcbiAgcHVibGljIG9wdGlvbnM6IEFuaW1hdGlvbk9wdGlvbnMgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIHVuc3VwcG9ydGVkQ1NTUHJvcGVydGllc0ZvdW5kOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgZXJyb3JzOiBFcnJvcltdKSB7fVxufVxuXG50eXBlIE9mZnNldFN0eWxlcyA9IHN0cmluZyB8IMm1U3R5bGVEYXRhTWFwO1xuXG5mdW5jdGlvbiBjb25zdW1lT2Zmc2V0KHN0eWxlczogT2Zmc2V0U3R5bGVzIHwgQXJyYXk8T2Zmc2V0U3R5bGVzPik6IG51bWJlciB8IG51bGwge1xuICBpZiAodHlwZW9mIHN0eWxlcyA9PSAnc3RyaW5nJykgcmV0dXJuIG51bGw7XG5cbiAgbGV0IG9mZnNldDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkoc3R5bGVzKSkge1xuICAgIHN0eWxlcy5mb3JFYWNoKChzdHlsZVR1cGxlKSA9PiB7XG4gICAgICBpZiAoc3R5bGVUdXBsZSBpbnN0YW5jZW9mIE1hcCAmJiBzdHlsZVR1cGxlLmhhcygnb2Zmc2V0JykpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gc3R5bGVUdXBsZSBhcyDJtVN0eWxlRGF0YU1hcDtcbiAgICAgICAgb2Zmc2V0ID0gcGFyc2VGbG9hdChvYmouZ2V0KCdvZmZzZXQnKSBhcyBzdHJpbmcpO1xuICAgICAgICBvYmouZGVsZXRlKCdvZmZzZXQnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSBlbHNlIGlmIChzdHlsZXMgaW5zdGFuY2VvZiBNYXAgJiYgc3R5bGVzLmhhcygnb2Zmc2V0JykpIHtcbiAgICBjb25zdCBvYmogPSBzdHlsZXM7XG4gICAgb2Zmc2V0ID0gcGFyc2VGbG9hdChvYmouZ2V0KCdvZmZzZXQnKSBhcyBzdHJpbmcpO1xuICAgIG9iai5kZWxldGUoJ29mZnNldCcpO1xuICB9XG4gIHJldHVybiBvZmZzZXQ7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFRpbWluZ0FzdCh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgQW5pbWF0ZVRpbWluZ3MsIGVycm9yczogRXJyb3JbXSkge1xuICBpZiAodmFsdWUuaGFzT3duUHJvcGVydHkoJ2R1cmF0aW9uJykpIHtcbiAgICByZXR1cm4gdmFsdWUgYXMgQW5pbWF0ZVRpbWluZ3M7XG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgY29uc3QgZHVyYXRpb24gPSByZXNvbHZlVGltaW5nKHZhbHVlLCBlcnJvcnMpLmR1cmF0aW9uO1xuICAgIHJldHVybiBtYWtlVGltaW5nQXN0KGR1cmF0aW9uLCAwLCAnJyk7XG4gIH1cblxuICBjb25zdCBzdHJWYWx1ZSA9IHZhbHVlIGFzIHN0cmluZztcbiAgY29uc3QgaXNEeW5hbWljID0gc3RyVmFsdWUuc3BsaXQoL1xccysvKS5zb21lKCh2KSA9PiB2LmNoYXJBdCgwKSA9PSAneycgJiYgdi5jaGFyQXQoMSkgPT0gJ3snKTtcbiAgaWYgKGlzRHluYW1pYykge1xuICAgIGNvbnN0IGFzdCA9IG1ha2VUaW1pbmdBc3QoMCwgMCwgJycpIGFzIGFueTtcbiAgICBhc3QuZHluYW1pYyA9IHRydWU7XG4gICAgYXN0LnN0clZhbHVlID0gc3RyVmFsdWU7XG4gICAgcmV0dXJuIGFzdCBhcyBEeW5hbWljVGltaW5nQXN0O1xuICB9XG5cbiAgY29uc3QgdGltaW5ncyA9IHJlc29sdmVUaW1pbmcoc3RyVmFsdWUsIGVycm9ycyk7XG4gIHJldHVybiBtYWtlVGltaW5nQXN0KHRpbWluZ3MuZHVyYXRpb24sIHRpbWluZ3MuZGVsYXksIHRpbWluZ3MuZWFzaW5nKTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplQW5pbWF0aW9uT3B0aW9ucyhvcHRpb25zOiBBbmltYXRpb25PcHRpb25zIHwgbnVsbCk6IEFuaW1hdGlvbk9wdGlvbnMge1xuICBpZiAob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB7Li4ub3B0aW9uc307XG4gICAgaWYgKG9wdGlvbnNbJ3BhcmFtcyddKSB7XG4gICAgICBvcHRpb25zWydwYXJhbXMnXSA9IG5vcm1hbGl6ZVBhcmFtcyhvcHRpb25zWydwYXJhbXMnXSkhO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBvcHRpb25zID0ge307XG4gIH1cbiAgcmV0dXJuIG9wdGlvbnM7XG59XG5cbmZ1bmN0aW9uIG1ha2VUaW1pbmdBc3QoZHVyYXRpb246IG51bWJlciwgZGVsYXk6IG51bWJlciwgZWFzaW5nOiBzdHJpbmcgfCBudWxsKTogVGltaW5nQXN0IHtcbiAgcmV0dXJuIHtkdXJhdGlvbiwgZGVsYXksIGVhc2luZ307XG59XG4iXX0=