UNPKG

@angular/compiler

Version:

Angular - the compiler library

541 lines • 72.1 kB
(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define("@angular/compiler/src/render3/view/styling_builder", ["require", "exports", "tslib", "@angular/compiler/src/expression_parser/ast", "@angular/compiler/src/output/output_ast", "@angular/compiler/src/template_parser/template_parser", "@angular/compiler/src/render3/r3_identifiers", "@angular/compiler/src/render3/view/style_parser", "@angular/compiler/src/render3/view/util"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseProperty = exports.StylingBuilder = exports.MIN_STYLING_BINDING_SLOTS_REQUIRED = void 0; var tslib_1 = require("tslib"); var ast_1 = require("@angular/compiler/src/expression_parser/ast"); var o = require("@angular/compiler/src/output/output_ast"); var template_parser_1 = require("@angular/compiler/src/template_parser/template_parser"); var r3_identifiers_1 = require("@angular/compiler/src/render3/r3_identifiers"); var style_parser_1 = require("@angular/compiler/src/render3/view/style_parser"); var util_1 = require("@angular/compiler/src/render3/view/util"); var IMPORTANT_FLAG = '!important'; /** * Minimum amount of binding slots required in the runtime for style/class bindings. * * Styling in Angular uses up two slots in the runtime LView/TData data structures to * record binding data, property information and metadata. * * When a binding is registered it will place the following information in the `LView`: * * slot 1) binding value * slot 2) cached value (all other values collected before it in string form) * * When a binding is registered it will place the following information in the `TData`: * * slot 1) prop name * slot 2) binding index that points to the previous style/class binding (and some extra config * values) * * Let's imagine we have a binding that looks like so: * * ``` * <div [style.width]="x" [style.height]="y"> * ``` * * Our `LView` and `TData` data-structures look like so: * * ```typescript * LView = [ * // ... * x, // value of x * "width: x", * * y, // value of y * "width: x; height: y", * // ... * ]; * * TData = [ * // ... * "width", // binding slot 20 * 0, * * "height", * 20, * // ... * ]; * ``` * * */ exports.MIN_STYLING_BINDING_SLOTS_REQUIRED = 2; /** * Produces creation/update instructions for all styling bindings (class and style) * * It also produces the creation instruction to register all initial styling values * (which are all the static class="..." and style="..." attribute values that exist * on an element within a template). * * The builder class below handles producing instructions for the following cases: * * - Static style/class attributes (style="..." and class="...") * - Dynamic style/class map bindings ([style]="map" and [class]="map|string") * - Dynamic style/class property bindings ([style.prop]="exp" and [class.name]="exp") * * Due to the complex relationship of all of these cases, the instructions generated * for these attributes/properties/bindings must be done so in the correct order. The * order which these must be generated is as follows: * * if (createMode) { * styling(...) * } * if (updateMode) { * styleMap(...) * classMap(...) * styleProp(...) * classProp(...) * } * * The creation/update methods within the builder class produce these instructions. */ var StylingBuilder = /** @class */ (function () { function StylingBuilder(_directiveExpr) { this._directiveExpr = _directiveExpr; /** Whether or not there are any static styling values present */ this._hasInitialValues = false; /** * Whether or not there are any styling bindings present * (i.e. `[style]`, `[class]`, `[style.prop]` or `[class.name]`) */ this.hasBindings = false; this.hasBindingsWithPipes = false; /** the input for [class] (if it exists) */ this._classMapInput = null; /** the input for [style] (if it exists) */ this._styleMapInput = null; /** an array of each [style.prop] input */ this._singleStyleInputs = null; /** an array of each [class.name] input */ this._singleClassInputs = null; this._lastStylingInput = null; this._firstStylingInput = null; // maps are used instead of hash maps because a Map will // retain the ordering of the keys /** * Represents the location of each style binding in the template * (e.g. `<div [style.width]="w" [style.height]="h">` implies * that `width=0` and `height=1`) */ this._stylesIndex = new Map(); /** * Represents the location of each class binding in the template * (e.g. `<div [class.big]="b" [class.hidden]="h">` implies * that `big=0` and `hidden=1`) */ this._classesIndex = new Map(); this._initialStyleValues = []; this._initialClassValues = []; } /** * Registers a given input to the styling builder to be later used when producing AOT code. * * The code below will only accept the input if it is somehow tied to styling (whether it be * style/class bindings or static style/class attributes). */ StylingBuilder.prototype.registerBoundInput = function (input) { // [attr.style] or [attr.class] are skipped in the code below, // they should not be treated as styling-based bindings since // they are intended to be written directly to the attr and // will therefore skip all style/class resolution that is present // with style="", [style]="" and [style.prop]="", class="", // [class.prop]="". [class]="" assignments var binding = null; var name = input.name; switch (input.type) { case 0 /* Property */: binding = this.registerInputBasedOnName(name, input.value, input.sourceSpan); break; case 3 /* Style */: binding = this.registerStyleInput(name, false, input.value, input.sourceSpan, input.unit); break; case 2 /* Class */: binding = this.registerClassInput(name, false, input.value, input.sourceSpan); break; } return binding ? true : false; }; StylingBuilder.prototype.registerInputBasedOnName = function (name, expression, sourceSpan) { var binding = null; var prefix = name.substring(0, 6); var isStyle = name === 'style' || prefix === 'style.' || prefix === 'style!'; var isClass = !isStyle && (name === 'class' || prefix === 'class.' || prefix === 'class!'); if (isStyle || isClass) { var isMapBased = name.charAt(5) !== '.'; // style.prop or class.prop makes this a no var property = name.substr(isMapBased ? 5 : 6); // the dot explains why there's a +1 if (isStyle) { binding = this.registerStyleInput(property, isMapBased, expression, sourceSpan); } else { binding = this.registerClassInput(property, isMapBased, expression, sourceSpan); } } return binding; }; StylingBuilder.prototype.registerStyleInput = function (name, isMapBased, value, sourceSpan, suffix) { if (template_parser_1.isEmptyExpression(value)) { return null; } name = normalizePropName(name); var _a = parseProperty(name), property = _a.property, hasOverrideFlag = _a.hasOverrideFlag, bindingSuffix = _a.suffix; suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix; var entry = { name: property, suffix: suffix, value: value, sourceSpan: sourceSpan, hasOverrideFlag: hasOverrideFlag }; if (isMapBased) { this._styleMapInput = entry; } else { (this._singleStyleInputs = this._singleStyleInputs || []).push(entry); registerIntoMap(this._stylesIndex, property); } this._lastStylingInput = entry; this._firstStylingInput = this._firstStylingInput || entry; this._checkForPipes(value); this.hasBindings = true; return entry; }; StylingBuilder.prototype.registerClassInput = function (name, isMapBased, value, sourceSpan) { if (template_parser_1.isEmptyExpression(value)) { return null; } var _a = parseProperty(name), property = _a.property, hasOverrideFlag = _a.hasOverrideFlag; var entry = { name: property, value: value, sourceSpan: sourceSpan, hasOverrideFlag: hasOverrideFlag, suffix: null }; if (isMapBased) { if (this._classMapInput) { throw new Error('[class] and [className] bindings cannot be used on the same element simultaneously'); } this._classMapInput = entry; } else { (this._singleClassInputs = this._singleClassInputs || []).push(entry); registerIntoMap(this._classesIndex, property); } this._lastStylingInput = entry; this._firstStylingInput = this._firstStylingInput || entry; this._checkForPipes(value); this.hasBindings = true; return entry; }; StylingBuilder.prototype._checkForPipes = function (value) { if ((value instanceof ast_1.ASTWithSource) && (value.ast instanceof ast_1.BindingPipe)) { this.hasBindingsWithPipes = true; } }; /** * Registers the element's static style string value to the builder. * * @param value the style string (e.g. `width:100px; height:200px;`) */ StylingBuilder.prototype.registerStyleAttr = function (value) { this._initialStyleValues = style_parser_1.parse(value); this._hasInitialValues = true; }; /** * Registers the element's static class string value to the builder. * * @param value the className string (e.g. `disabled gold zoom`) */ StylingBuilder.prototype.registerClassAttr = function (value) { this._initialClassValues = value.trim().split(/\s+/g); this._hasInitialValues = true; }; /** * Appends all styling-related expressions to the provided attrs array. * * @param attrs an existing array where each of the styling expressions * will be inserted into. */ StylingBuilder.prototype.populateInitialStylingAttrs = function (attrs) { // [CLASS_MARKER, 'foo', 'bar', 'baz' ...] if (this._initialClassValues.length) { attrs.push(o.literal(1 /* Classes */)); for (var i = 0; i < this._initialClassValues.length; i++) { attrs.push(o.literal(this._initialClassValues[i])); } } // [STYLE_MARKER, 'width', '200px', 'height', '100px', ...] if (this._initialStyleValues.length) { attrs.push(o.literal(2 /* Styles */)); for (var i = 0; i < this._initialStyleValues.length; i += 2) { attrs.push(o.literal(this._initialStyleValues[i]), o.literal(this._initialStyleValues[i + 1])); } } }; /** * Builds an instruction with all the expressions and parameters for `elementHostAttrs`. * * The instruction generation code below is used for producing the AOT statement code which is * responsible for registering initial styles (within a directive hostBindings' creation block), * as well as any of the provided attribute values, to the directive host element. */ StylingBuilder.prototype.assignHostAttrs = function (attrs, definitionMap) { if (this._directiveExpr && (attrs.length || this._hasInitialValues)) { this.populateInitialStylingAttrs(attrs); definitionMap.set('hostAttrs', o.literalArr(attrs)); } }; /** * Builds an instruction with all the expressions and parameters for `classMap`. * * The instruction data will contain all expressions for `classMap` to function * which includes the `[class]` expression params. */ StylingBuilder.prototype.buildClassMapInstruction = function (valueConverter) { if (this._classMapInput) { return this._buildMapBasedInstruction(valueConverter, true, this._classMapInput); } return null; }; /** * Builds an instruction with all the expressions and parameters for `styleMap`. * * The instruction data will contain all expressions for `styleMap` to function * which includes the `[style]` expression params. */ StylingBuilder.prototype.buildStyleMapInstruction = function (valueConverter) { if (this._styleMapInput) { return this._buildMapBasedInstruction(valueConverter, false, this._styleMapInput); } return null; }; StylingBuilder.prototype._buildMapBasedInstruction = function (valueConverter, isClassBased, stylingInput) { // each styling binding value is stored in the LView // map-based bindings allocate two slots: one for the // previous binding value and another for the previous // className or style attribute value. var totalBindingSlotsRequired = exports.MIN_STYLING_BINDING_SLOTS_REQUIRED; // these values must be outside of the update block so that they can // be evaluated (the AST visit call) during creation time so that any // pipes can be picked up in time before the template is built var mapValue = stylingInput.value.visit(valueConverter); var reference; if (mapValue instanceof ast_1.Interpolation) { totalBindingSlotsRequired += mapValue.expressions.length; reference = isClassBased ? getClassMapInterpolationExpression(mapValue) : getStyleMapInterpolationExpression(mapValue); } else { reference = isClassBased ? r3_identifiers_1.Identifiers.classMap : r3_identifiers_1.Identifiers.styleMap; } return { reference: reference, calls: [{ supportsInterpolation: true, sourceSpan: stylingInput.sourceSpan, allocateBindingSlots: totalBindingSlotsRequired, params: function (convertFn) { var convertResult = convertFn(mapValue); var params = Array.isArray(convertResult) ? convertResult : [convertResult]; return params; } }] }; }; StylingBuilder.prototype._buildSingleInputs = function (reference, inputs, valueConverter, getInterpolationExpressionFn, isClassBased) { var instructions = []; inputs.forEach(function (input) { var previousInstruction = instructions[instructions.length - 1]; var value = input.value.visit(valueConverter); var referenceForCall = reference; // each styling binding value is stored in the LView // but there are two values stored for each binding: // 1) the value itself // 2) an intermediate value (concatenation of style up to this point). // We need to store the intermediate value so that we don't allocate // the strings on each CD. var totalBindingSlotsRequired = exports.MIN_STYLING_BINDING_SLOTS_REQUIRED; if (value instanceof ast_1.Interpolation) { totalBindingSlotsRequired += value.expressions.length; if (getInterpolationExpressionFn) { referenceForCall = getInterpolationExpressionFn(value); } } var call = { sourceSpan: input.sourceSpan, allocateBindingSlots: totalBindingSlotsRequired, supportsInterpolation: !!getInterpolationExpressionFn, params: function (convertFn) { // params => stylingProp(propName, value, suffix) var params = []; params.push(o.literal(input.name)); var convertResult = convertFn(value); if (Array.isArray(convertResult)) { params.push.apply(params, tslib_1.__spread(convertResult)); } else { params.push(convertResult); } // [style.prop] bindings may use suffix values (e.g. px, em, etc...), therefore, // if that is detected then we need to pass that in as an optional param. if (!isClassBased && input.suffix !== null) { params.push(o.literal(input.suffix)); } return params; } }; // If we ended up generating a call to the same instruction as the previous styling property // we can chain the calls together safely to save some bytes, otherwise we have to generate // a separate instruction call. This is primarily a concern with interpolation instructions // where we may start off with one `reference`, but end up using another based on the // number of interpolations. if (previousInstruction && previousInstruction.reference === referenceForCall) { previousInstruction.calls.push(call); } else { instructions.push({ reference: referenceForCall, calls: [call] }); } }); return instructions; }; StylingBuilder.prototype._buildClassInputs = function (valueConverter) { if (this._singleClassInputs) { return this._buildSingleInputs(r3_identifiers_1.Identifiers.classProp, this._singleClassInputs, valueConverter, null, true); } return []; }; StylingBuilder.prototype._buildStyleInputs = function (valueConverter) { if (this._singleStyleInputs) { return this._buildSingleInputs(r3_identifiers_1.Identifiers.styleProp, this._singleStyleInputs, valueConverter, getStylePropInterpolationExpression, false); } return []; }; /** * Constructs all instructions which contain the expressions that will be placed * into the update block of a template function or a directive hostBindings function. */ StylingBuilder.prototype.buildUpdateLevelInstructions = function (valueConverter) { var instructions = []; if (this.hasBindings) { var styleMapInstruction = this.buildStyleMapInstruction(valueConverter); if (styleMapInstruction) { instructions.push(styleMapInstruction); } var classMapInstruction = this.buildClassMapInstruction(valueConverter); if (classMapInstruction) { instructions.push(classMapInstruction); } instructions.push.apply(instructions, tslib_1.__spread(this._buildStyleInputs(valueConverter))); instructions.push.apply(instructions, tslib_1.__spread(this._buildClassInputs(valueConverter))); } return instructions; }; return StylingBuilder; }()); exports.StylingBuilder = StylingBuilder; function registerIntoMap(map, key) { if (!map.has(key)) { map.set(key, map.size); } } function parseProperty(name) { var hasOverrideFlag = false; var overrideIndex = name.indexOf(IMPORTANT_FLAG); if (overrideIndex !== -1) { name = overrideIndex > 0 ? name.substring(0, overrideIndex) : ''; hasOverrideFlag = true; } var suffix = null; var property = name; var unitIndex = name.lastIndexOf('.'); if (unitIndex > 0) { suffix = name.substr(unitIndex + 1); property = name.substring(0, unitIndex); } return { property: property, suffix: suffix, hasOverrideFlag: hasOverrideFlag }; } exports.parseProperty = parseProperty; /** * Gets the instruction to generate for an interpolated class map. * @param interpolation An Interpolation AST */ function getClassMapInterpolationExpression(interpolation) { switch (util_1.getInterpolationArgsLength(interpolation)) { case 1: return r3_identifiers_1.Identifiers.classMap; case 3: return r3_identifiers_1.Identifiers.classMapInterpolate1; case 5: return r3_identifiers_1.Identifiers.classMapInterpolate2; case 7: return r3_identifiers_1.Identifiers.classMapInterpolate3; case 9: return r3_identifiers_1.Identifiers.classMapInterpolate4; case 11: return r3_identifiers_1.Identifiers.classMapInterpolate5; case 13: return r3_identifiers_1.Identifiers.classMapInterpolate6; case 15: return r3_identifiers_1.Identifiers.classMapInterpolate7; case 17: return r3_identifiers_1.Identifiers.classMapInterpolate8; default: return r3_identifiers_1.Identifiers.classMapInterpolateV; } } /** * Gets the instruction to generate for an interpolated style map. * @param interpolation An Interpolation AST */ function getStyleMapInterpolationExpression(interpolation) { switch (util_1.getInterpolationArgsLength(interpolation)) { case 1: return r3_identifiers_1.Identifiers.styleMap; case 3: return r3_identifiers_1.Identifiers.styleMapInterpolate1; case 5: return r3_identifiers_1.Identifiers.styleMapInterpolate2; case 7: return r3_identifiers_1.Identifiers.styleMapInterpolate3; case 9: return r3_identifiers_1.Identifiers.styleMapInterpolate4; case 11: return r3_identifiers_1.Identifiers.styleMapInterpolate5; case 13: return r3_identifiers_1.Identifiers.styleMapInterpolate6; case 15: return r3_identifiers_1.Identifiers.styleMapInterpolate7; case 17: return r3_identifiers_1.Identifiers.styleMapInterpolate8; default: return r3_identifiers_1.Identifiers.styleMapInterpolateV; } } /** * Gets the instruction to generate for an interpolated style prop. * @param interpolation An Interpolation AST */ function getStylePropInterpolationExpression(interpolation) { switch (util_1.getInterpolationArgsLength(interpolation)) { case 1: return r3_identifiers_1.Identifiers.styleProp; case 3: return r3_identifiers_1.Identifiers.stylePropInterpolate1; case 5: return r3_identifiers_1.Identifiers.stylePropInterpolate2; case 7: return r3_identifiers_1.Identifiers.stylePropInterpolate3; case 9: return r3_identifiers_1.Identifiers.stylePropInterpolate4; case 11: return r3_identifiers_1.Identifiers.stylePropInterpolate5; case 13: return r3_identifiers_1.Identifiers.stylePropInterpolate6; case 15: return r3_identifiers_1.Identifiers.stylePropInterpolate7; case 17: return r3_identifiers_1.Identifiers.stylePropInterpolate8; default: return r3_identifiers_1.Identifiers.stylePropInterpolateV; } } function normalizePropName(prop) { return style_parser_1.hyphenate(prop); } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3R5bGluZ19idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlcjMvdmlldy9zdHlsaW5nX2J1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztJQVFBLG1FQUF3RztJQUN4RywyREFBNkM7SUFFN0MseUZBQXdFO0lBRXhFLCtFQUFvRDtJQUVwRCxnRkFBOEQ7SUFFOUQsZ0VBQWlFO0lBRWpFLElBQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztJQUVwQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7U0ErQ0s7SUFDUSxRQUFBLGtDQUFrQyxHQUFHLENBQUMsQ0FBQztJQTZCcEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0E0Qkc7SUFDSDtRQXdDRSx3QkFBb0IsY0FBaUM7WUFBakMsbUJBQWMsR0FBZCxjQUFjLENBQW1CO1lBdkNyRCxpRUFBaUU7WUFDekQsc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1lBQ2xDOzs7ZUFHRztZQUNJLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1lBQ3BCLHlCQUFvQixHQUFHLEtBQUssQ0FBQztZQUVwQywyQ0FBMkM7WUFDbkMsbUJBQWMsR0FBMkIsSUFBSSxDQUFDO1lBQ3RELDJDQUEyQztZQUNuQyxtQkFBYyxHQUEyQixJQUFJLENBQUM7WUFDdEQsMENBQTBDO1lBQ2xDLHVCQUFrQixHQUE2QixJQUFJLENBQUM7WUFDNUQsMENBQTBDO1lBQ2xDLHVCQUFrQixHQUE2QixJQUFJLENBQUM7WUFDcEQsc0JBQWlCLEdBQTJCLElBQUksQ0FBQztZQUNqRCx1QkFBa0IsR0FBMkIsSUFBSSxDQUFDO1lBRTFELHdEQUF3RDtZQUN4RCxrQ0FBa0M7WUFFbEM7Ozs7ZUFJRztZQUNLLGlCQUFZLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7WUFFakQ7Ozs7ZUFJRztZ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QUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTLG1DQUFtQyxDQUFDLGFBQTRCO1FBQ3ZFLFFBQVEsaUNBQTBCLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDakQsS0FBSyxDQUFDO2dCQUNKLE9BQU8sNEJBQUUsQ0FBQyxTQUFTLENBQUM7WUFDdEIsS0FBSyxDQUFDO2dCQUNKLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNsQyxLQUFLLENBQUM7Z0JBQ0osT0FBTyw0QkFBRSxDQUFDLHFCQUFxQixDQUFDO1lBQ2xDLEtBQUssQ0FBQztnQkFDSixPQUFPLDRCQUFFLENBQUMscUJBQXFCLENBQUM7WUFDbEMsS0FBSyxDQUFDO2dCQUNKLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNsQyxLQUFLLEVBQUU7Z0JBQ0wsT0FBTyw0QkFBRSxDQUFDLHFCQUFxQixDQUFDO1lBQ2xDLEtBQUssRUFBRTtnQkFDTCxPQUFPLDRCQUFFLENBQUMscUJBQXFCLENBQUM7WUFDbEMsS0FBSyxFQUFFO2dCQUNMLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNsQyxLQUFLLEVBQUU7Z0JBQ0wsT0FBTyw0QkFBRSxDQUFDLHFCQUFxQixDQUFDO1lBQ2xDO2dCQUNFLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztTQUNuQztJQUNILENBQUM7SUFFRCxTQUFTLGlCQUFpQixDQUFDLElBQVk7UUFDckMsT0FBTyx3QkFBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cbmltcG9ydCB7QXR0cmlidXRlTWFya2VyfSBmcm9tICcuLi8uLi9jb3JlJztcbmltcG9ydCB7QVNULCBBU1RXaXRoU291cmNlLCBCaW5kaW5nUGlwZSwgQmluZGluZ1R5cGUsIEludGVycG9sYXRpb259IGZyb20gJy4uLy4uL2V4cHJlc3Npb25fcGFyc2VyL2FzdCc7XG5pbXBvcnQgKiBhcyBvIGZyb20gJy4uLy4uL291dHB1dC9vdXRwdXRfYXN0JztcbmltcG9ydCB7UGFyc2VTb3VyY2VTcGFufSBmcm9tICcuLi8uLi9wYXJzZV91dGlsJztcbmltcG9ydCB7aXNFbXB0eUV4cHJlc3Npb259IGZyb20gJy4uLy4uL3RlbXBsYXRlX3BhcnNlci90ZW1wbGF0ZV9wYXJzZXInO1xuaW1wb3J0ICogYXMgdCBmcm9tICcuLi9yM19hc3QnO1xuaW1wb3J0IHtJZGVudGlmaWVycyBhcyBSM30gZnJvbSAnLi4vcjNfaWRlbnRpZmllcnMnO1xuXG5pbXBvcnQge2h5cGhlbmF0ZSwgcGFyc2UgYXMgcGFyc2VTdHlsZX0gZnJvbSAnLi9zdHlsZV9wYXJzZXInO1xuaW1wb3J0IHtWYWx1ZUNvbnZlcnRlcn0gZnJvbSAnLi90ZW1wbGF0ZSc7XG5pbXBvcnQge0RlZmluaXRpb25NYXAsIGdldEludGVycG9sYXRpb25BcmdzTGVuZ3RofSBmcm9tICcuL3V0aWwnO1xuXG5jb25zdCBJTVBPUlRBTlRfRkxBRyA9ICchaW1wb3J0YW50JztcblxuLyoqXG4gKiBNaW5pbXVtIGFtb3VudCBvZiBiaW5kaW5nIHNsb3RzIHJlcXVpcmVkIGluIHRoZSBydW50aW1lIGZvciBzdHlsZS9jbGFzcyBiaW5kaW5ncy5cbiAqXG4gKiBTdHlsaW5nIGluIEFuZ3VsYXIgdXNlcyB1cCB0d28gc2xvdHMgaW4gdGhlIHJ1bnRpbWUgTFZpZXcvVERhdGEgZGF0YSBzdHJ1Y3R1cmVzIHRvXG4gKiByZWNvcmQgYmluZGluZyBkYXRhLCBwcm9wZXJ0eSBpbmZvcm1hdGlvbiBhbmQgbWV0YWRhdGEuXG4gKlxuICogV2hlbiBhIGJpbmRpbmcgaXMgcmVnaXN0ZXJlZCBpdCB3aWxsIHBsYWNlIHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb24gaW4gdGhlIGBMVmlld2A6XG4gKlxuICogc2xvdCAxKSBiaW5kaW5nIHZhbHVlXG4gKiBzbG90IDIpIGNhY2hlZCB2YWx1ZSAoYWxsIG90aGVyIHZhbHVlcyBjb2xsZWN0ZWQgYmVmb3JlIGl0IGluIHN0cmluZyBmb3JtKVxuICpcbiAqIFdoZW4gYSBiaW5kaW5nIGlzIHJlZ2lzdGVyZWQgaXQgd2lsbCBwbGFjZSB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uIGluIHRoZSBgVERhdGFgOlxuICpcbiAqIHNsb3QgMSkgcHJvcCBuYW1lXG4gKiBzbG90IDIpIGJpbmRpbmcgaW5kZXggdGhhdCBwb2ludHMgdG8gdGhlIHByZXZpb3VzIHN0eWxlL2NsYXNzIGJpbmRpbmcgKGFuZCBzb21lIGV4dHJhIGNvbmZpZ1xuICogdmFsdWVzKVxuICpcbiAqIExldCdzIGltYWdpbmUgd2UgaGF2ZSBhIGJpbmRpbmcgdGhhdCBsb29rcyBsaWtlIHNvOlxuICpcbiAqIGBgYFxuICogPGRpdiBbc3R5bGUud2lkdGhdPVwieFwiIFtzdHlsZS5oZWlnaHRdPVwieVwiPlxuICogYGBgXG4gKlxuICogT3VyIGBMVmlld2AgYW5kIGBURGF0YWAgZGF0YS1zdHJ1Y3R1cmVzIGxvb2sgbGlrZSBzbzpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBMVmlldyA9IFtcbiAqICAgLy8gLi4uXG4gKiAgIHgsIC8vIHZhbHVlIG9mIHhcbiAqICAgXCJ3aWR0aDogeFwiLFxuICpcbiAqICAgeSwgLy8gdmFsdWUgb2YgeVxuICogICBcIndpZHRoOiB4OyBoZWlnaHQ6IHlcIixcbiAqICAgLy8gLi4uXG4gKiBdO1xuICpcbiAqIFREYXRhID0gW1xuICogICAvLyAuLi5cbiAqICAgXCJ3aWR0aFwiLCAvLyBiaW5kaW5nIHNsb3QgMjBcbiAqICAgMCxcbiAqXG4gKiAgIFwiaGVpZ2h0XCIsXG4gKiAgIDIwLFxuICogICAvLyAuLi5cbiAqIF07XG4gKiBgYGBcbiAqXG4gKiAqL1xuZXhwb3J0IGNvbnN0IE1JTl9TVFlMSU5HX0JJTkRJTkdfU0xPVFNfUkVRVUlSRUQgPSAyO1xuXG4vKipcbiAqIEEgc3R5bGluZyBleHByZXNzaW9uIHN1bW1hcnkgdGhhdCBpcyB0byBiZSBwcm9jZXNzZWQgYnkgdGhlIGNvbXBpbGVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3R5bGluZ0luc3RydWN0aW9uIHtcbiAgcmVmZXJlbmNlOiBvLkV4dGVybmFsUmVmZXJlbmNlO1xuICAvKiogQ2FsbHMgdG8gaW5kaXZpZHVhbCBzdHlsaW5nIGluc3RydWN0aW9ucy4gVXNlZCB3aGVuIGNoYWluaW5nIGNhbGxzIHRvIHRoZSBzYW1lIGluc3RydWN0aW9uLiAqL1xuICBjYWxsczogU3R5bGluZ0luc3RydWN0aW9uQ2FsbFtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0eWxpbmdJbnN0cnVjdGlvbkNhbGwge1xuICBzb3VyY2VTcGFuOiBQYXJzZVNvdXJjZVNwYW58bnVsbDtcbiAgc3VwcG9ydHNJbnRlcnBvbGF0aW9uOiBib29sZWFuO1xuICBhbGxvY2F0ZUJpbmRpbmdTbG90czogbnVtYmVyO1xuICBwYXJhbXM6ICgoY29udmVydEZuOiAodmFsdWU6IGFueSkgPT4gby5FeHByZXNzaW9uIHwgby5FeHByZXNzaW9uW10pID0+IG8uRXhwcmVzc2lvbltdKTtcbn1cblxuLyoqXG4gKiBBbiBpbnRlcm5hbCByZWNvcmQgb2YgdGhlIGlucHV0IGRhdGEgZm9yIGEgc3R5bGluZyBiaW5kaW5nXG4gKi9cbmludGVyZmFjZSBCb3VuZFN0eWxpbmdFbnRyeSB7XG4gIGhhc092ZXJyaWRlRmxhZzogYm9vbGVhbjtcbiAgbmFtZTogc3RyaW5nfG51bGw7XG4gIHN1ZmZpeDogc3RyaW5nfG51bGw7XG4gIHNvdXJjZVNwYW46IFBhcnNlU291cmNlU3BhbjtcbiAgdmFsdWU6IEFTVDtcbn1cblxuLyoqXG4gKiBQcm9kdWNlcyBjcmVhdGlvbi91cGRhdGUgaW5zdHJ1Y3Rpb25zIGZvciBhbGwgc3R5bGluZyBiaW5kaW5ncyAoY2xhc3MgYW5kIHN0eWxlKVxuICpcbiAqIEl0IGFsc28gcHJvZHVjZXMgdGhlIGNyZWF0aW9uIGluc3RydWN0aW9uIHRvIHJlZ2lzdGVyIGFsbCBpbml0aWFsIHN0eWxpbmcgdmFsdWVzXG4gKiAod2hpY2ggYXJlIGFsbCB0aGUgc3RhdGljIGNsYXNzPVwiLi4uXCIgYW5kIHN0eWxlPVwiLi4uXCIgYXR0cmlidXRlIHZhbHVlcyB0aGF0IGV4aXN0XG4gKiBvbiBhbiBlbGVtZW50IHdpdGhpbiBhIHRlbXBsYXRlKS5cbiAqXG4gKiBUaGUgYnVpbGRlciBjbGFzcyBiZWxvdyBoYW5kbGVzIHByb2R1Y2luZyBpbnN0cnVjdGlvbnMgZm9yIHRoZSBmb2xsb3dpbmcgY2FzZXM6XG4gKlxuICogLSBTdGF0aWMgc3R5bGUvY2xhc3MgYXR0cmlidXRlcyAoc3R5bGU9XCIuLi5cIiBhbmQgY2xhc3M9XCIuLi5cIilcbiAqIC0gRHluYW1pYyBzdHlsZS9jbGFzcyBtYXAgYmluZGluZ3MgKFtzdHlsZV09XCJtYXBcIiBhbmQgW2NsYXNzXT1cIm1hcHxzdHJpbmdcIilcbiAqIC0gRHluYW1pYyBzdHlsZS9jbGFzcyBwcm9wZXJ0eSBiaW5kaW5ncyAoW3N0eWxlLnByb3BdPVwiZXhwXCIgYW5kIFtjbGFzcy5uYW1lXT1cImV4cFwiKVxuICpcbiAqIER1ZSB0byB0aGUgY29tcGxleCByZWxhdGlvbnNoaXAgb2YgYWxsIG9mIHRoZXNlIGNhc2VzLCB0aGUgaW5zdHJ1Y3Rpb25zIGdlbmVyYXRlZFxuICogZm9yIHRoZXNlIGF0dHJpYnV0ZXMvcHJvcGVydGllcy9iaW5kaW5ncyBtdXN0IGJlIGRvbmUgc28gaW4gdGhlIGNvcnJlY3Qgb3JkZXIuIFRoZVxuICogb3JkZXIgd2hpY2ggdGhlc2UgbXVzdCBiZSBnZW5lcmF0ZWQgaXMgYXMgZm9sbG93czpcbiAqXG4gKiBpZiAoY3JlYXRlTW9kZSkge1xuICogICBzdHlsaW5nKC4uLilcbiAqIH1cbiAqIGlmICh1cGRhdGVNb2RlKSB7XG4gKiAgIHN0eWxlTWFwKC4uLilcbiAqICAgY2xhc3NNYXAoLi4uKVxuICogICBzdHlsZVByb3AoLi4uKVxuICogICBjbGFzc1Byb3AoLi4uKVxuICogfVxuICpcbiAqIFRoZSBjcmVhdGlvbi91cGRhdGUgbWV0aG9kcyB3aXRoaW4gdGhlIGJ1aWxkZXIgY2xhc3MgcHJvZHVjZSB0aGVzZSBpbnN0cnVjdGlvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHlsaW5nQnVpbGRlciB7XG4gIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGVyZSBhcmUgYW55IHN0YXRpYyBzdHlsaW5nIHZhbHVlcyBwcmVzZW50ICovXG4gIHByaXZhdGUgX2hhc0luaXRpYWxWYWx1ZXMgPSBmYWxzZTtcbiAgLyoqXG4gICAqICBXaGV0aGVyIG9yIG5vdCB0aGVyZSBhcmUgYW55IHN0eWxpbmcgYmluZGluZ3MgcHJlc2VudFxuICAgKiAgKGkuZS4gYFtzdHlsZV1gLCBgW2NsYXNzXWAsIGBbc3R5bGUucHJvcF1gIG9yIGBbY2xhc3MubmFtZV1gKVxuICAgKi9cbiAgcHVibGljIGhhc0JpbmRpbmdzID0gZmFsc2U7XG4gIHB1YmxpYyBoYXNCaW5kaW5nc1dpdGhQaXBlcyA9IGZhbHNlO1xuXG4gIC8qKiB0aGUgaW5wdXQgZm9yIFtjbGFzc10gKGlmIGl0IGV4aXN0cykgKi9cbiAgcHJpdmF0ZSBfY2xhc3NNYXBJbnB1dDogQm91bmRTdHlsaW5nRW50cnl8bnVsbCA9IG51bGw7XG4gIC8qKiB0aGUgaW5wdXQgZm9yIFtzdHlsZV0gKGlmIGl0IGV4aXN0cykgKi9cbiAgcHJpdmF0ZSBfc3R5bGVNYXBJbnB1dDogQm91bmRTdHlsaW5nRW50cnl8bnVsbCA9IG51bGw7XG4gIC8qKiBhbiBhcnJheSBvZiBlYWNoIFtzdHlsZS5wcm9wXSBpbnB1dCAqL1xuICBwcml2YXRlIF9zaW5nbGVTdHlsZUlucHV0czogQm91bmRTdHlsaW5nRW50cnlbXXxudWxsID0gbnVsbDtcbiAgLyoqIGFuIGFycmF5IG9mIGVhY2ggW2NsYXNzLm5hbWVdIGlucHV0ICovXG4gIHByaXZhdGUgX3NpbmdsZUNsYXNzSW5wdXRzOiBCb3VuZFN0eWxpbmdFbnRyeVtdfG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9sYXN0U3R5bGluZ0lucHV0OiBCb3VuZFN0eWxpbmdFbnRyeXxudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfZmlyc3RTdHlsaW5nSW5wdXQ6IEJvdW5kU3R5bGluZ0VudHJ5fG51bGwgPSBudWxsO1xuXG4gIC8vIG1hcHMgYXJlIHVzZWQgaW5zdGVhZCBvZiBoYXNoIG1hcHMgYmVjYXVzZSBhIE1hcCB3aWxsXG4gIC8vIHJldGFpbiB0aGUgb3JkZXJpbmcgb2YgdGhlIGtleXNcblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgbG9jYXRpb24gb2YgZWFjaCBzdHlsZSBiaW5kaW5nIGluIHRoZSB0ZW1wbGF0ZVxuICAgKiAoZS5nLiBgPGRpdiBbc3R5bGUud2lkdGhdPVwid1wiIFtzdHlsZS5oZWlnaHRdPVwiaFwiPmAgaW1wbGllc1xuICAgKiB0aGF0IGB3aWR0aD0wYCBhbmQgYGhlaWdodD0xYClcbiAgICovXG4gIHByaXZhdGUgX3N0eWxlc0luZGV4ID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICAvKipcbiAgICogUmVwcmVzZW50cyB0aGUgbG9jYXRpb24gb2YgZWFjaCBjbGFzcyBiaW5kaW5nIGluIHRoZSB0ZW1wbGF0ZVxuICAgKiAoZS5nLiBgPGRpdiBbY2xhc3MuYmlnXT1cImJcIiBbY2xhc3MuaGlkZGVuXT1cImhcIj5gIGltcGxpZXNcbiAgICogdGhhdCBgYmlnPTBgIGFuZCBgaGlkZGVuPTFgKVxuICAgKi9cbiAgcHJpdmF0ZSBfY2xhc3Nlc0luZGV4ID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgcHJpdmF0ZSBfaW5pdGlhbFN0eWxlVmFsdWVzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIF9pbml0aWFsQ2xhc3NWYWx1ZXM6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfZGlyZWN0aXZlRXhwcjogby5FeHByZXNzaW9ufG51bGwpIHt9XG5cbiAgLyoqXG4gICAqIFJlZ2