UNPKG

@angular/animations

Version:

Angular - animations integration with web-animations

502 lines • 71.6 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { AUTO_STYLE, style } from '@angular/animations'; import { getOrSetAsInMap } from '../render/shared'; import { copyObj, extractStyleParams, iteratorToArray, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, normalizeAnimationEntry, resolveTiming, SUBSTITUTION_EXPR_START, validateStyleParams, visitDslNode } from '../util'; 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) { return new AnimationAstBuilderVisitor(driver).build(metadata, errors); } const ROOT_SELECTOR = ''; export class AnimationAstBuilderVisitor { constructor(_driver) { this._driver = _driver; } build(metadata, errors) { const context = new AnimationAstBuilderContext(errors); this._resetContextStyleTimingState(context); return visitDslNode(this, normalizeAnimationEntry(metadata), context); } _resetContextStyleTimingState(context) { context.currentQuerySelector = ROOT_SELECTOR; context.collectedStyles = {}; context.collectedStyles[ROOT_SELECTOR] = {}; 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('animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\'@foo\', [...]))'); } metadata.definitions.forEach(def => { this._resetContextStyleTimingState(context); if (def.type == 0 /* 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 /* Transition */) { const transition = this.visitTransition(def, context); queryCount += transition.queryCount; depCount += transition.depCount; transitions.push(transition); } else { context.errors.push('only state() and transition() definitions can sit inside of a trigger()'); } }); return { type: 7 /* 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(value => { if (isObject(value)) { const stylesObj = value; Object.keys(stylesObj).forEach(prop => { extractStyleParams(stylesObj[prop]).forEach(sub => { if (!params.hasOwnProperty(sub)) { missingSubs.add(sub); } }); }); } }); if (missingSubs.size) { const missingSubsArr = iteratorToArray(missingSubs.values()); context.errors.push(`state("${metadata .name}", ...) must define default values for all the following style substitutions: ${missingSubsArr.join(', ')}`); } } return { type: 0 /* 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 /* Transition */, matchers, animation, queryCount: context.queryCount, depCount: context.depCount, options: normalizeAnimationOptions(metadata.options) }; } visitSequence(metadata, context) { return { type: 2 /* 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 /* 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 /* 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 /* 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 = []; if (Array.isArray(metadata.styles)) { metadata.styles.forEach(styleTuple => { if (typeof styleTuple == 'string') { if (styleTuple == AUTO_STYLE) { styles.push(styleTuple); } else { context.errors.push(`The provided style string value ${styleTuple} is not allowed.`); } } else { styles.push(styleTuple); } }); } else { styles.push(metadata.styles); } let containsDynamicStyles = false; let collectedEasing = null; styles.forEach(styleData => { if (isObject(styleData)) { const styleMap = styleData; const easing = styleMap['easing']; if (easing) { collectedEasing = easing; delete styleMap['easing']; } if (!containsDynamicStyles) { for (let prop in styleMap) { const value = styleMap[prop]; if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) { containsDynamicStyles = true; break; } } } } }); return { type: 6 /* 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; Object.keys(tuple).forEach(prop => { if (!this._driver.validateStyleProperty(prop)) { context.errors.push(`The provided animation property "${prop}" is not a supported CSS property for animations`); return; } const collectedStyles = context.collectedStyles[context.currentQuerySelector]; const collectedEntry = collectedStyles[prop]; let updateCollectedStyle = true; if (collectedEntry) { if (startTime != endTime && startTime >= collectedEntry.startTime && endTime <= collectedEntry.endTime) { context.errors.push(`The CSS property "${prop}" that exists between the times of "${collectedEntry.startTime}ms" and "${collectedEntry .endTime}ms" is also being animated in a parallel animation between the times of "${startTime}ms" and "${endTime}ms"`); 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[prop] = { startTime, endTime }; } if (context.options) { validateStyleParams(tuple[prop], context.options, context.errors); } }); }); } visitKeyframes(metadata, context) { const ast = { type: 5 /* Keyframes */, styles: [], options: null }; if (!context.currentAnimateTimings) { context.errors.push(`keyframes() must be placed inside of a call to animate()`); 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(`Please ensure that all keyframe offsets are between 0 and 1`); } if (offsetsOutOfOrder) { context.errors.push(`Please ensure that all keyframe offsets are in order`); } const length = metadata.steps.length; let generatedOffset = 0; if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) { context.errors.push(`Not all style() steps within the declared keyframes() contain offsets`); } 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 /* Reference */, animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), options: normalizeAnimationOptions(metadata.options) }; } visitAnimateChild(metadata, context) { context.depCount++; return { type: 9 /* AnimateChild */, options: normalizeAnimationOptions(metadata.options) }; } visitAnimateRef(metadata, context) { return { type: 10 /* 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; getOrSetAsInMap(context.collectedStyles, context.currentQuerySelector, {}); const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); context.currentQuery = null; context.currentQuerySelector = parentSelector; return { type: 11 /* 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(`stagger() can only be used inside of query()`); } const timings = metadata.timings === 'full' ? { duration: 0, delay: 0, easing: 'full' } : resolveTiming(metadata.timings, context.errors, true); return { type: 12 /* 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, ''); } // the :enter and :leave selectors are filled in at runtime during timeline building selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR) .replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.substr(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 = {}; this.options = null; } } function consumeOffset(styles) { if (typeof styles == 'string') return null; let offset = null; if (Array.isArray(styles)) { styles.forEach(styleTuple => { if (isObject(styleTuple) && styleTuple.hasOwnProperty('offset')) { const obj = styleTuple; offset = parseFloat(obj['offset']); delete obj['offset']; } }); } else if (isObject(styles) && styles.hasOwnProperty('offset')) { const obj = styles; offset = parseFloat(obj['offset']); delete obj['offset']; } return offset; } function isObject(value) { return !Array.isArray(value) && typeof value == 'object'; } function constructTimingAst(value, errors) { let timings = null; if (value.hasOwnProperty('duration')) { timings = value; } else 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; } timings = 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5pbWF0aW9uX2FzdF9idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvYW5pbWF0aW9ucy9icm93c2VyL3NyYy9kc2wvYW5pbWF0aW9uX2FzdF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFBc2MsVUFBVSxFQUFFLEtBQUssRUFBYSxNQUFNLHFCQUFxQixDQUFDO0FBR3ZnQixPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDakQsT0FBTyxFQUFDLE9BQU8sRUFBa0Isa0JBQWtCLEVBQUUsZUFBZSxFQUFrQixxQkFBcUIsRUFBRSxtQkFBbUIsRUFBRSx1QkFBdUIsRUFBRSxhQUFhLEVBQUUsdUJBQXVCLEVBQUUsbUJBQW1CLEVBQUUsWUFBWSxFQUFDLE1BQU0sU0FBUyxDQUFDO0FBSXJQLE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLDZCQUE2QixDQUFDO0FBRWhFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQztBQUMzQixNQUFNLGdCQUFnQixHQUFHLElBQUksTUFBTSxDQUFDLE1BQU0sVUFBVSxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFFbEU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUNHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUM3QixNQUF1QixFQUFFLFFBQStDLEVBQ3hFLE1BQWE7SUFDZixPQUFPLElBQUksMEJBQTBCLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBRXpCLE1BQU0sT0FBTywwQkFBMEI7SUFDckMsWUFBb0IsT0FBd0I7UUFBeEIsWUFBTyxHQUFQLE9BQU8sQ0FBaUI7SUFBRyxDQUFDO0lBRWhELEtBQUss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QUFHLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN4QixPQUFPLEdBQXVCLENBQUM7S0FDaEM7SUFFRCxPQUFPLEdBQUcsT0FBTyxJQUFJLGFBQWEsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDckQsT0FBTyxhQUFhLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQsU0FBUyx5QkFBeUIsQ0FBQyxPQUE4QjtJQUMvRCxJQUFJLE9BQU8sRUFBRTtRQUNYLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0IsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDckIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUUsQ0FBQztTQUN6RDtLQUNGO1NBQU07UUFDTCxPQUFPLEdBQUcsRUFBRSxDQUFDO0tBQ2Q7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsUUFBZ0IsRUFBRSxLQUFhLEVBQUUsTUFBbUI7SUFDekUsT0FBTyxFQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFDLENBQUM7QUFDbkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuaW1wb3J0IHtBbmltYXRlVGltaW5ncywgQW5pbWF0aW9uQW5pbWF0ZUNoaWxkTWV0YWRhdGEsIEFuaW1hdGlvbkFuaW1hdGVNZXRhZGF0YSwgQW5pbWF0aW9uQW5pbWF0ZVJlZk1ldGFkYXRhLCBBbmltYXRpb25Hcm91cE1ldGFkYXRhLCBBbmltYXRpb25LZXlmcmFtZXNTZXF1ZW5jZU1ldGFkYXRhLCBBbmltYXRpb25NZXRhZGF0YSwgQW5pbWF0aW9uTWV0YWRhdGFUeXBlLCBBbmltYXRpb25PcHRpb25zLCBBbmltYXRpb25RdWVyeU1ldGFkYXRhLCBBbmltYXRpb25RdWVyeU9wdGlvbnMsIEFuaW1hdGlvblJlZmVyZW5jZU1ldGFkYXRhLCBBbmltYXRpb25TZXF1ZW5jZU1ldGFkYXRhLCBBbmltYXRpb25TdGFnZ2VyTWV0YWRhdGEsIEFuaW1hdGlvblN0YXRlTWV0YWRhdGEsIEFuaW1hdGlvblN0eWxlTWV0YWRhdGEsIEFuaW1hdGlvblRyYW5zaXRpb25NZXRhZGF0YSwgQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhLCBBVVRPX1NUWUxFLCBzdHlsZSwgybVTdHlsZURhdGF9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuXG5pbXBvcnQge0FuaW1hdGlvbkRyaXZlcn0gZnJvbSAnLi4vcmVuZGVyL2FuaW1hdGlvbl9kcml2ZXInO1xuaW1wb3J0IHtnZXRPclNldEFzSW5NYXB9IGZyb20gJy4uL3JlbmRlci9zaGFyZWQnO1xuaW1wb3J0IHtjb3B5T2JqLCBFTlRFUl9TRUxFQ1RPUiwgZXh0cmFjdFN0eWxlUGFyYW1zLCBpdGVyYXRvclRvQXJyYXksIExFQVZFX1NFTEVDVE9SLCBOR19BTklNQVRJTkdfU0VMRUNUT1IsIE5HX1RSSUdHRVJfU0VMRUNUT1IsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5LCByZXNvbHZlVGltaW5nLCBTVUJTVElUVVRJT05fRVhQUl9TVEFSVCwgdmFsaWRhdGVTdHlsZVBhcmFtcywgdmlzaXREc2xOb2RlfSBmcm9tICcuLi91dGlsJztcblxuaW1wb3J0IHtBbmltYXRlQXN0LCBBbmltYXRlQ2hpbGRBc3QsIEFuaW1hdGVSZWZBc3QsIEFzdCwgRHluYW1pY1RpbWluZ0FzdCwgR3JvdXBBc3QsIEtleWZyYW1lc0FzdCwgUXVlcnlBc3QsIFJlZmVyZW5jZUFzdCwgU2VxdWVuY2VBc3QsIFN0YWdnZXJBc3QsIFN0YXRlQXN0LCBTdHlsZUFzdCwgVGltaW5nQXN0LCBUcmFuc2l0aW9uQXN0LCBUcmlnZ2VyQXN0fSBmcm9tICcuL2FuaW1hdGlvbl9hc3QnO1xuaW1wb3J0IHtBbmltYXRpb25Ec2xWaXNpdG9yfSBmcm9tICcuL2FuaW1hdGlvbl9kc2xfdmlzaXRvcic7XG5pbXBvcnQge3BhcnNlVHJhbnNpdGlvbkV4cHJ9IGZyb20gJy4vYW5pbWF0aW9uX3RyYW5zaXRpb25fZXhwcic7XG5cbmNvbnN0IFNFTEZfVE9LRU4gPSAnOnNlbGYnO1xuY29uc3QgU0VMRl9UT0tFTl9SRUdFWCA9IG5ldyBSZWdFeHAoYFxccyoke1NFTEZfVE9LRU59XFxzKiw/YCwgJ2cnKTtcblxuLypcbiAqIFtWYWxpZGF0aW9uXVxuICogVGhlIHZpc2l0b3IgY29kZSBiZWxvdyB3aWxsIHRyYXZlcnNlIHRoZSBhbmltYXRpb24gQVNUIGdlbmVyYXRlZCBieSB0aGUgYW5pbWF0aW9uIHZlcmIgZnVuY3Rpb25zXG4gKiAodGhlIG91dHB1dCBpcyBhIHRyZWUgb2Ygb2JqZWN0cykgYW5kIGF0dGVtcHQgdG8gcGVyZm9ybSBhIHNlcmllcyBvZiB2YWxpZGF0aW9ucyBvbiB0aGUgZGF0YS4gVGhlXG4gKiBmb2xsb3dpbmcgY29ybmVyLWNhc2VzIHdpbGwgYmUgdmFsaWRhdGVkOlxuICpcbiAqIDEuIE92ZXJsYXAgb2YgYW5pbWF0aW9uc1xuICogR2l2ZW4gdGhhdCBhIENTUyBwcm9wZXJ0eSBjYW5ub3QgYmUgYW5pbWF0ZWQgaW4gbW9yZSB0aGFuIG9uZSBwbGFjZSBhdCB0aGUgc2FtZSB0aW1lLCBpdCdzXG4gKiBpbXBvcnRhbnQgdGhhdCB0aGlzIGJlaGF2aW9yIGlzIGRldGVjdGVkIGFuZCB2YWxpZGF0ZWQuIFRoZSB3YXkgaW4gd2hpY2ggdGhpcyBvY2N1cnMgaXMgdGhhdFxuICogZWFjaCB0aW1lIGEgc3R5bGUgcHJvcGVydHkgaXMgZXhhbWluZWQsIGEgc3RyaW5nLW1hcCBjb250YWluaW5nIHRoZSBwcm9wZXJ0eSB3aWxsIGJlIHVwZGF0ZWQgd2l0aFxuICogdGhlIHN0YXJ0IGFuZCBlbmQgdGltZXMgZm9yIHdoZW4gdGhlIHByb3BlcnR5IGlzIHVzZWQgd2l0aGluIGFuIGFuaW1hdGlvbiBzdGVwLlxuICpcbiAqIElmIHRoZXJlIGFyZSB0d28gb3IgbW9yZSBwYXJhbGxlbCBhbmltYXRpb25zIHRoYXQgYXJlIGN1cnJlbnRseSBydW5uaW5nICh0aGVzZSBhcmUgaW52b2tlZCBieSB0aGVcbiAqIGdyb3VwKCkpIG9uIHRoZSBzYW1lIGVsZW1lbnQgdGhlbiB0aGUgdmFsaWRhdG9yIHdpbGwgdGhyb3cgYW4gZXJyb3IuIFNpbmNlIHRoZSBzdGFydC9lbmQgdGltaW5nXG4gKiB2YWx1ZXMgYXJlIGNvbGxlY3RlZCBmb3IgZWFjaCBwcm9wZXJ0eSB0aGVuIGlmIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBzdGVwIGlzIGFuaW1hdGluZyB0aGUgc2FtZVxuICogcHJvcGVydHkgYW5kIGl0cyB0aW1pbmcgdmFsdWVzIGZhbGwgYW55d2hlcmUgaW50byB0aGUgd2luZG93IG9mIHRpbWUgdGhhdCB0aGUgcHJvcGVydHkgaXNcbiAqIGN1cnJlbnRseSBiZWluZyBhbmltYXRlZCB3aXRoaW4gdGhlbiB0aGlzIGlzIHdoYXQgY2F1c2VzIGFuIGVycm9yLlxuICpcbiAqIDIuIFRpbWluZyB2YWx1ZXNcbiAqIFRoZSB2YWxpZGF0b3Igd2lsbCB2YWxpZGF0ZSB0byBzZWUgaWYgYSB0aW1pbmcgdmFsdWUgb2YgYGR1cmF0aW9uIGRlbGF5IGVhc2luZ2Agb3JcbiAqIGBkdXJhdGlvbk51bWJlcmAgaXMgdmFsaWQgb3Igbm90LlxuICpcbiAqIChub3RlIHRoYXQgdXBvbiB2YWxpZGF0aW9uIHRoZSBjb2RlIGJlbG93IHdpbGwgcmVwbGFjZSB0aGUgdGltaW5nIGRhdGEgd2l0aCBhbiBvYmplY3QgY29udGFpbmluZ1xuICoge2R1cmF0aW9uLGRlbGF5LGVhc2luZ30uXG4gKlxuICogMy4gT2Zmc2V0IFZhbGlkYXRpb25cbiAqIEVhY2ggb2YgdGhlIHN0eWxlKCkgY2FsbHMgYXJlIGFsbG93ZWQgdG8gaGF2ZSBhbiBvZmZzZXQgdmFsdWUgd2hlbiBwbGFjZWQgaW5zaWRlIG9mIGtleWZyYW1lcygpLlxuICogT2Zmc2V0cyB3aXRoaW4ga2V5ZnJhbWVzKCkgYXJlIGNvbnNpZGVyZWQgdmFsaWQgd2hlbjpcbiAqXG4gKiAgIC0gTm8gb2Zmc2V0cyBhcmUgdXNlZCBhdCBhbGxcbiAqICAgLSBFYWNoIHN0eWxlKCkgZW50cnkgY29udGFpbnMgYW4gb2Zmc2V0IHZhbHVlXG4gKiAgIC0gRWFjaCBvZmZzZXQgaXMgYmV0d2VlbiAwIGFuZCAxXG4gKiAgIC0gRWFjaCBvZmZzZXQgaXMgZ3JlYXRlciB0byBvciBlcXVhbCB0aGFuIHRoZSBwcmV2aW91cyBvbmVcbiAqXG4gKiBPdGhlcndpc2UgYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEFuaW1hdGlvbkFzdChcbiAgICBkcml2ZXI6IEFuaW1hdGlvbkRyaXZlciwgbWV0YWRhdGE6IEFuaW1hdGlvbk1ldGFkYXRhfEFuaW1hdGlvbk1ldGFkYXRhW10sXG4gICAgZXJyb3JzOiBhbnlbXSk6IEFzdDxBbmltYXRpb25NZXRhZGF0YVR5cGU+IHtcbiAgcmV0dXJuIG5ldyBBbmltYXRpb25Bc3RCdWlsZGVyVmlzaXRvcihkcml2ZXIpLmJ1aWxkKG1ldGFkYXRhLCBlcnJvcnMpO1xufVxuXG5jb25zdCBST09UX1NFTEVDVE9SID0gJyc7XG5cbmV4cG9ydCBjbGFzcyBBbmltYXRpb25Bc3RCdWlsZGVyVmlzaXRvciBpbXBsZW1lbnRzIEFuaW1hdGlvbkRzbFZpc2l0b3Ige1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9kcml2ZXI6IEFuaW1hdGlvbkRyaXZlcikge31cblxuICBidWlsZChtZXRhZGF0YTogQW5pbWF0aW9uTWV0YWRhdGF8QW5pbWF0aW9uTWV0YWRhdGFbXSwgZXJyb3JzOiBhbnlbXSk6XG4gICAgICBBc3Q8QW5pbWF0aW9uTWV0YWRhdGFUeXBlPiB7XG4gICAgY29uc3QgY29udGV4dCA9IG5ldyBBbmltYXRpb25Bc3RCdWlsZGVyQ29udGV4dChlcnJvcnMpO1xuICAgIHRoaXMuX3Jlc2V0Q29udGV4dFN0eWxlVGltaW5nU3RhdGUoY29udGV4dCk7XG4gICAgcmV0dXJuIDxBc3Q8QW5pbWF0aW9uTWV0YWRhdGFUeXBlPj52aXNpdERzbE5vZGUoXG4gICAgICAgIHRoaXMsIG5vcm1hbGl6ZUFuaW1hdGlvbkVudHJ5KG1ldGFkYXRhKSwgY29udGV4dCk7XG4gIH1cblxuICBwcml2YXRlIF9yZXNldENvbnRleHRTdHlsZVRpbWluZ1N0YXRlKGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0KSB7XG4gICAgY29udGV4dC5jdXJyZW50UXVlcnlTZWxlY3RvciA9IFJPT1RfU0VMRUNUT1I7XG4gICAgY29udGV4dC5jb2xsZWN0ZWRTdHlsZXMgPSB7fTtcbiAgICBjb250ZXh0LmNvbGxlY3RlZFN0eWxlc1tST09UX1NFTEVDVE9SXSA9IHt9O1xuICAgIGNvbnRleHQuY3VycmVudFRpbWUgPSAwO1xuICB9XG5cbiAgdmlzaXRUcmlnZ2VyKG1ldGFkYXRhOiBBbmltYXRpb25UcmlnZ2VyTWV0YWRhdGEsIGNvbnRleHQ6IEFuaW1hdGlvbkFzdEJ1aWxkZXJDb250ZXh0KTpcbiAgICAgIFRyaWdnZXJBc3Qge1xuICAgIGxldCBxdWVyeUNvdW50ID0gY29udGV4dC5xdWVyeUNvdW50ID0gMDtcbiAgICBsZXQgZGVwQ291bnQgPSBjb250ZXh0LmRlcENvdW50ID0gMDtcbiAgICBjb25zdCBzdGF0ZXM6IFN0YXRlQXN0W10gPSBbXTtcbiAgICBjb25zdCB0cmFuc2l0aW9uczogVHJhbnNpdGlvbkFzdFtdID0gW107XG4gICAgaWYgKG1ldGFkYXRhLm5hbWUuY2hhckF0KDApID09ICdAJykge1xuICAgICAgY29udGV4dC5lcnJvcnMucHVzaChcbiAgICAgICAgICAnYW5pbWF0aW9uIHRyaWdnZXJzIGNhbm5vdCBiZSBwcmVmaXhlZCB3aXRoIGFuIGBAYCBzaWduIChlLmcuIHRyaWdnZXIoXFwnQGZvb1xcJywgWy4uLl0pKScpO1xuICAgIH1cblxuICAgIG1ldGFkYXRhLmRlZmluaXRpb25zLmZvckVhY2goZGVmID0+IHtcbiAgICAgIHRoaXMuX3Jlc2V0Q29udGV4dFN0eWxlVGltaW5nU3RhdGUoY29udGV4dCk7XG4gICAgICBpZiAoZGVmLnR5cGUgPT0gQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlN0YXRlKSB7XG4gICAgICAgIGNvbnN0IHN0YXRlRGVmID0gZGVmIGFzIEFuaW1hdGlvblN0YXRlTWV0YWRhdGE7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBzdGF0ZURlZi5uYW1lO1xuICAgICAgICBuYW1lLnRvU3RyaW5nKCkuc3BsaXQoL1xccyosXFxzKi8pLmZvckVhY2gobiA9PiB7XG4gICAgICAgICAgc3RhdGVEZWYubmFtZSA9IG47XG4gICAgICAgICAgc3RhdGVzLnB1c2godGhpcy52aXNpdFN0YXRlKHN0YXRlRGVmLCBjb250ZXh0KSk7XG4gICAgICAgIH0pO1xuICAgICAgICBzdGF0ZURlZi5uYW1lID0gbmFtZTtcbiAgICAgIH0gZWxzZSBpZiAoZGVmLnR5cGUgPT0gQW5pbWF0aW9uTWV0YWRhdGFUeXBlLlRyYW5zaXRpb24pIHtcbiAgICAgICAgY29uc3QgdHJhbnNpdGlvbiA9IHRoaXMudmlzaXRUcmFuc2l0aW9uKGRlZiBhcyBBbmltYXRpb25UcmFuc2l0aW9uTWV0YWRhdGEsIGNvbnRleHQpO1xuICAgICAgICBxdWVyeUNvdW50ICs9IHRyYW5zaXRpb24ucXVlcnlDb3VudDtcbiAgICAgICAgZGVwQ291bnQgKz0gdHJhbnNpdGlvbi5kZXBDb3VudDtcbiAgICAgICAgdHJhbnNpdGlvbnMucHVzaCh0cmFuc2l0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRleHQuZXJyb3JzLnB1c2goXG4gICAgICAgICAgICAnb25seSBzdGF0ZSgpIGFuZCB0cmFuc2l0aW9uKCkgZGVmaW5pdGlvbnMgY2FuIHNpdCBpbnNpZGUgb2YgYSB0cmlnZ2VyKCknKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiBBbmltYXRpb25NZXRhZGF0YVR5cGUuVHJpZ2dlcixcbiAgICAgIG5hbWU6IG1ldGFkYXRhLm5hbWUsXG4gICAgICBzdGF0ZXMsXG4gICAgICB0cmFuc2l0aW9ucyxcbiAgICAgIHF1ZXJ5Q291bnQsXG4gICAgICBkZXBDb3VudCxcbiAgICAgIG9wdGlvbnM6IG51bGxcbiAgICB9O1xuICB9XG5cbiAgdmlzaXRTdGF0ZShtZXRhZGF0YTogQW5pbWF0aW9uU3RhdGVNZXRhZGF0YSwgY29udGV4dDogQW5pbWF0aW9uQXN0QnVpbGRlckNvbnRleHQpOiBTdGF0ZUFzdCB7XG4gICAgY29uc3Qgc3R5bGVBc3QgPSB0aGlzLnZpc2l0U3R5bGUobWV0YWRhdGEuc3R5bGVzLCBjb250ZXh0KTtcbiAgICBjb25zdCBhc3RQYXJhbXMgPSAobWV0YWRhdGEub3B0aW9ucyAmJiBtZXRhZGF0YS5vcHRpb25zLnBhcmFtcykgfHwgbnVsbDtcbiAgICBpZiAoc3R5bGVBc3QuY29ud