@angular/compiler
Version:
Angular - the compiler library
546 lines • 72.6 kB
JavaScript
(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;
}
// CSS custom properties are case-sensitive so we shouldn't normalize them.
// See: https://www.w3.org/TR/css-variables-1/#defining-variables
if (!isCssCustomProperty(name)) {
name = style_parser_1.hyphenate(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) {
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.__spreadArray([], tslib_1.__read(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.__spreadArray([], tslib_1.__read(this._buildStyleInputs(valueConverter))));
instructions.push.apply(instructions, tslib_1.__spreadArray([], tslib_1.__read(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;
}
}
/**
* Checks whether property name is a custom CSS property.
* See: https://www.w3.org/TR/css-variables-1
*/
function isCssCustomProperty(name) {
return name.startsWith('--');
}
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3R5bGluZ19idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlcjMvdmlldy9zdHlsaW5nX2J1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztJQVFBLG1FQUF3RztJQUN4RywyREFBNkM7SUFFN0MseUZBQXdFO0lBRXhFLCtFQUFvRDtJQUVwRCxnRkFBOEQ7SUFFOUQsZ0VBQWlFO0lBRWpFLElBQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztJQUVwQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7U0ErQ0s7SUFDUSxRQUFBLGtDQUFrQyxHQUFHLENBQUMsQ0FBQztJQTZCcEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0E0Qkc7SUFDSDtRQXdDRSx3QkFBb0IsY0FBaUM7WUFBakMsbUJBQWMsR0FBZCxjQUFjLENBQW1CO1lBdkNyRCxpRUFBaUU7WUFDekQsc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1lBQ2xDOzs7ZUFHRztZQUNJLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1lBQ3BCLHlCQUFvQixHQUFHLEtBQUssQ0FBQztZQUVwQywyQ0FBMkM7WUFDbkMsbUJBQWMsR0FBMkIsSUFBSSxDQUFDO1lBQ3RELDJDQUEyQztZQUNuQyxtQkFBYyxHQUEyQixJQUFJLENBQUM7WUFDdEQsMENBQTBDO1lBQ2xDLHVCQUFrQixHQUE2QixJQUFJLENBQUM7WUFDNUQsMENBQTBDO1lBQ2xDLHVCQUFrQixHQUE2QixJQUFJLENBQUM7WUFDcEQsc0JBQWlCLEdBQTJCLElBQUksQ0FBQztZQUNqRCx1QkFBa0IsR0FBMkIsSUFBSSxDQUFDO1lBRTFELHdEQUF3RDtZQUN4RCxrQ0FBa0M7WUFFbEM7Ozs7ZUFJRztZQUNLLGlCQUFZLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7WUFFakQ7Ozs7ZUFJRztZ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OztPQUdHO0lBQ0gsU0FBUyxtQ0FBbUMsQ0FBQyxhQUE0QjtRQUN2RSxRQUFRLGlDQUEwQixDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQ2pELEtBQUssQ0FBQztnQkFDSixPQUFPLDRCQUFFLENBQUMsU0FBUyxDQUFDO1lBQ3RCLEtBQUssQ0FBQztnQkFDSixPQUFPLDRCQUFFLENBQUMscUJBQXFCLENBQUM7WUFDbEMsS0FBSyxDQUFDO2dCQUNKLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNsQyxLQUFLLENBQUM7Z0JBQ0osT0FBTyw0QkFBRSxDQUFDLHFCQUFxQixDQUFDO1lBQ2xDLEtBQUssQ0FBQztnQkFDSixPQUFPLDRCQUFFLENBQUMscUJBQXFCLENBQUM7WUFDbEMsS0FBSyxFQUFFO2dCQUNMLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNsQyxLQUFLLEVBQUU7Z0JBQ0wsT0FBTyw0QkFBRSxDQUFDLHFCQUFxQixDQUFDO1lBQ2xDLEtBQUssRUFBRTtnQkFDTCxPQUFPLDRCQUFFLENBQUMscUJBQXFCLENBQUM7WUFDbEMsS0FBSyxFQUFFO2dCQUNMLE9BQU8sNEJBQUUsQ0FBQyxxQkFBcUIsQ0FBQztZQUNsQztnQkFDRSxPQUFPLDRCQUFFLENBQUMscUJBQXFCLENBQUM7U0FDbkM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxJQUFZO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5pbXBvcnQge0F0dHJpYnV0ZU1hcmtlcn0gZnJvbSAnLi4vLi4vY29yZSc7XG5pbXBvcnQge0FTVCwgQVNUV2l0aFNvdXJjZSwgQmluZGluZ1BpcGUsIEJpbmRpbmdUeXBlLCBJbnRlcnBvbGF0aW9ufSBmcm9tICcuLi8uLi9leHByZXNzaW9uX3BhcnNlci9hc3QnO1xuaW1wb3J0ICogYXMgbyBmcm9tICcuLi8uLi9vdXRwdXQvb3V0cHV0X2FzdCc7XG5pbXBvcnQge1BhcnNlU291cmNlU3Bhbn0gZnJvbSAnLi4vLi4vcGFyc2VfdXRpbCc7XG5pbXBvcnQge2lzRW1wdHlFeHByZXNzaW9ufSBmcm9tICcuLi8uLi90ZW1wbGF0ZV9wYXJzZXIvdGVtcGxhdGVfcGFyc2VyJztcbmltcG9ydCAqIGFzIHQgZnJvbSAnLi4vcjNfYXN0JztcbmltcG9ydCB7SWRlbnRpZmllcnMgYXMgUjN9IGZyb20gJy4uL3IzX2lkZW50aWZpZXJzJztcblxuaW1wb3J0IHtoeXBoZW5hdGUsIHBhcnNlIGFzIHBhcnNlU3R5bGV9IGZyb20gJy4vc3R5bGVfcGFyc2VyJztcbmltcG9ydCB7VmFsdWVDb252ZXJ0ZXJ9IGZyb20gJy4vdGVtcGxhdGUnO1xuaW1wb3J0IHtEZWZpbml0aW9uTWFwLCBnZXRJbnRlcnBvbGF0aW9uQXJnc0xlbmd0aH0gZnJvbSAnLi91dGlsJztcblxuY29uc3QgSU1QT1JUQU5UX0ZMQUcgPSAnIWltcG9ydGFudCc7XG5cbi8qKlxuICogTWluaW11bSBhbW91bnQgb2YgYmluZGluZyBzbG90cyByZXF1aXJlZCBpbiB0aGUgcnVudGltZSBmb3Igc3R5bGUvY2xhc3MgYmluZGluZ3MuXG4gKlxuICogU3R5bGluZyBpbiBBbmd1bGFyIHVzZXMgdXAgdHdvIHNsb3RzIGluIHRoZSBydW50aW1lIExWaWV3L1REYXRhIGRhdGEgc3RydWN0dXJlcyB0b1xuICogcmVjb3JkIGJpbmRpbmcgZGF0YSwgcHJvcGVydHkgaW5mb3JtYXRpb24gYW5kIG1ldGFkYXRhLlxuICpcbiAqIFdoZW4gYSBiaW5kaW5nIGlzIHJlZ2lzdGVyZWQgaXQgd2lsbCBwbGFjZSB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uIGluIHRoZSBgTFZpZXdgOlxuICpcbiAqIHNsb3QgMSkgYmluZGluZyB2YWx1ZVxuICogc2xvdCAyKSBjYWNoZWQgdmFsdWUgKGFsbCBvdGhlciB2YWx1ZXMgY29sbGVjdGVkIGJlZm9yZSBpdCBpbiBzdHJpbmcgZm9ybSlcbiAqXG4gKiBXaGVuIGEgYmluZGluZyBpcyByZWdpc3RlcmVkIGl0IHdpbGwgcGxhY2UgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbiBpbiB0aGUgYFREYXRhYDpcbiAqXG4gKiBzbG90IDEpIHByb3AgbmFtZVxuICogc2xvdCAyKSBiaW5kaW5nIGluZGV4IHRoYXQgcG9pbnRzIHRvIHRoZSBwcmV2aW91cyBzdHlsZS9jbGFzcyBiaW5kaW5nIChhbmQgc29tZSBleHRyYSBjb25maWdcbiAqIHZhbHVlcylcbiAqXG4gKiBMZXQncyBpbWFnaW5lIHdlIGhhdmUgYSBiaW5kaW5nIHRoYXQgbG9va3MgbGlrZSBzbzpcbiAqXG4gKiBgYGBcbiAqIDxkaXYgW3N0eWxlLndpZHRoXT1cInhcIiBbc3R5bGUuaGVpZ2h0XT1cInlcIj5cbiAqIGBgYFxuICpcbiAqIE91ciBgTFZpZXdgIGFuZCBgVERhdGFgIGRhdGEtc3RydWN0dXJlcyBsb29rIGxpa2Ugc286XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogTFZpZXcgPSBbXG4gKiAgIC8vIC4uLlxuICogICB4LCAvLyB2YWx1ZSBvZiB4XG4gKiAgIFwid2lkdGg6IHhcIixcbiAqXG4gKiAgIHksIC8vIHZhbHVlIG9mIHlcbiAqICAgXCJ3aWR0aDogeDsgaGVpZ2h0OiB5XCIsXG4gKiAgIC8vIC4uLlxuICogXTtcbiAqXG4gKiBURGF0YSA9IFtcbiAqICAgLy8gLi4uXG4gKiAgIFwid2lkdGhcIiwgLy8gYmluZGluZyBzbG90IDIwXG4gKiAgIDAsXG4gKlxuICogICBcImhlaWdodFwiLFxuICogICAyMCxcbiAqICAgLy8gLi4uXG4gKiBdO1xuICogYGBgXG4gKlxuICogKi9cbmV4cG9ydCBjb25zdCBNSU5fU1RZTElOR19CSU5ESU5HX1NMT1RTX1JFUVVJUkVEID0gMjtcblxuLyoqXG4gKiBBIHN0eWxpbmcgZXhwcmVzc2lvbiBzdW1tYXJ5IHRoYXQgaXMgdG8gYmUgcHJvY2Vzc2VkIGJ5IHRoZSBjb21waWxlclxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0eWxpbmdJbnN0cnVjdGlvbiB7XG4gIHJlZmVyZW5jZTogby5FeHRlcm5hbFJlZmVyZW5jZTtcbiAgLyoqIENhbGxzIHRvIGluZGl2aWR1YWwgc3R5bGluZyBpbnN0cnVjdGlvbnMuIFVzZWQgd2hlbiBjaGFpbmluZyBjYWxscyB0byB0aGUgc2FtZSBpbnN0cnVjdGlvbi4gKi9cbiAgY2FsbHM6IFN0eWxpbmdJbnN0cnVjdGlvbkNhbGxbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdHlsaW5nSW5zdHJ1Y3Rpb25DYWxsIHtcbiAgc291cmNlU3BhbjogUGFyc2VTb3VyY2VTcGFufG51bGw7XG4gIHN1cHBvcnRzSW50ZXJwb2xhdGlvbjogYm9vbGVhbjtcbiAgYWxsb2NhdGVCaW5kaW5nU2xvdHM6IG51bWJlcjtcbiAgcGFyYW1zOiAoKGNvbnZlcnRGbjogKHZhbHVlOiBhbnkpID0+IG8uRXhwcmVzc2lvbiB8IG8uRXhwcmVzc2lvbltdKSA9PiBvLkV4cHJlc3Npb25bXSk7XG59XG5cbi8qKlxuICogQW4gaW50ZXJuYWwgcmVjb3JkIG9mIHRoZSBpbnB1dCBkYXRhIGZvciBhIHN0eWxpbmcgYmluZGluZ1xuICovXG5pbnRlcmZhY2UgQm91bmRTdHlsaW5nRW50cnkge1xuICBoYXNPdmVycmlkZUZsYWc6IGJvb2xlYW47XG4gIG5hbWU6IHN0cmluZ3xudWxsO1xuICBzdWZmaXg6IHN0cmluZ3xudWxsO1xuICBzb3VyY2VTcGFuOiBQYXJzZVNvdXJjZVNwYW47XG4gIHZhbHVlOiBBU1Q7XG59XG5cbi8qKlxuICogUHJvZHVjZXMgY3JlYXRpb24vdXBkYXRlIGluc3RydWN0aW9ucyBmb3IgYWxsIHN0eWxpbmcgYmluZGluZ3MgKGNsYXNzIGFuZCBzdHlsZSlcbiAqXG4gKiBJdCBhbHNvIHByb2R1Y2VzIHRoZSBjcmVhdGlvbiBpbnN0cnVjdGlvbiB0byByZWdpc3RlciBhbGwgaW5pdGlhbCBzdHlsaW5nIHZhbHVlc1xuICogKHdoaWNoIGFyZSBhbGwgdGhlIHN0YXRpYyBjbGFzcz1cIi4uLlwiIGFuZCBzdHlsZT1cIi4uLlwiIGF0dHJpYnV0ZSB2YWx1ZXMgdGhhdCBleGlzdFxuICogb24gYW4gZWxlbWVudCB3aXRoaW4gYSB0ZW1wbGF0ZSkuXG4gKlxuICogVGhlIGJ1aWxkZXIgY2xhc3MgYmVsb3cgaGFuZGxlcyBwcm9kdWNpbmcgaW5zdHJ1Y3Rpb25zIGZvciB0aGUgZm9sbG93aW5nIGNhc2VzOlxuICpcbiAqIC0gU3RhdGljIHN0eWxlL2NsYXNzIGF0dHJpYnV0ZXMgKHN0eWxlPVwiLi4uXCIgYW5kIGNsYXNzPVwiLi4uXCIpXG4gKiAtIER5bmFtaWMgc3R5bGUvY2xhc3MgbWFwIGJpbmRpbmdzIChbc3R5bGVdPVwibWFwXCIgYW5kIFtjbGFzc109XCJtYXB8c3RyaW5nXCIpXG4gKiAtIER5bmFtaWMgc3R5bGUvY2xhc3MgcHJvcGVydHkgYmluZGluZ3MgKFtzdHlsZS5wcm9wXT1cImV4cFwiIGFuZCBbY2xhc3MubmFtZV09XCJleHBcIilcbiAqXG4gKiBEdWUgdG8gdGhlIGNvbXBsZXggcmVsYXRpb25zaGlwIG9mIGFsbCBvZiB0aGVzZSBjYXNlcywgdGhlIGluc3RydWN0aW9ucyBnZW5lcmF0ZWRcbiAqIGZvciB0aGVzZSBhdHRyaWJ1dGVzL3Byb3BlcnRpZXMvYmluZGluZ3MgbXVzdCBiZSBkb25lIHNvIGluIHRoZSBjb3JyZWN0IG9yZGVyLiBUaGVcbiAqIG9yZGVyIHdoaWNoIHRoZXNlIG11c3QgYmUgZ2VuZXJhdGVkIGlzIGFzIGZvbGxvd3M6XG4gKlxuICogaWYgKGNyZWF0ZU1vZGUpIHtcbiAqICAgc3R5bGluZyguLi4pXG4gKiB9XG4gKiBpZiAodXBkYXRlTW9kZSkge1xuICogICBzdHlsZU1hcCguLi4pXG4gKiAgIGNsYXNzTWFwKC4uLilcbiAqICAgc3R5bGVQcm9wKC4uLilcbiAqICAgY2xhc3NQcm9wKC4uLilcbiAqIH1cbiAqXG4gKiBUaGUgY3JlYXRpb24vdXBkYXRlIG1ldGhvZHMgd2l0aGluIHRoZSBidWlsZGVyIGNsYXNzIHByb2R1Y2UgdGhlc2UgaW5zdHJ1Y3Rpb25zLlxuICovXG5leHBvcnQgY2xhc3MgU3R5bGluZ0J1aWxkZXIge1xuICAvKiogV2hldGhlciBvciBub3QgdGhlcmUgYXJlIGFueSBzdGF0aWMgc3R5bGluZyB2YWx1ZXMgcHJlc2VudCAqL1xuICBwcml2YXRlIF9oYXNJbml0aWFsVmFsdWVzID0gZmFsc2U7XG4gIC8qKlxuICAgKiAgV2hldGhlciBvciBub3QgdGhlcmUgYXJlIGFueSBzdHlsaW5nIGJpbmRpbmdzIHByZXNlbnRcbiAgICogIChpLmUuIGBbc3R5bGVdYCwgYFtjbGFzc11gLCBgW3N0eWxlLnByb3BdYCBvciBgW2NsYXNzLm5hbWVdYClcbiAgICovXG4gIHB1YmxpYyBoYXNCaW5kaW5ncyA9IGZhbHNlO1xuICBwdWJsaWMgaGFzQmluZGluZ3NXaXRoUGlwZXMgPSBmYWxzZTtcblxuICAvKiogdGhlIGlucHV0IGZvciBbY2xhc3NdIChpZiBpdCBleGlzdHMpICovXG4gIHByaXZhdGUgX2NsYXNzTWFwSW5wdXQ6IEJvdW5kU3R5bGluZ0VudHJ5fG51bGwgPSBudWxsO1xuICAvKiogdGhlIGlucHV0IGZvciBbc3R5bGVdIChpZiBpdCBleGlzdHMpICovXG4gIHByaXZhdGUgX3N0eWxlTWFwSW5wdXQ6IEJvdW5kU3R5bGluZ0VudHJ5fG51bGwgPSBudWxsO1xuICAvKiogYW4gYXJyYXkgb2YgZWFjaCBbc3R5bGUucHJvcF0gaW5wdXQgKi9cbiAgcHJpdmF0ZSBfc2luZ2xlU3R5bGVJbnB1dHM6IEJvdW5kU3R5bGluZ0VudHJ5W118bnVsbCA9IG51bGw7XG4gIC8qKiBhbiBhcnJheSBvZiBlYWNoIFtjbGFzcy5uYW1lXSBpbnB1dCAqL1xuICBwcml2YXRlIF9zaW5nbGVDbGFzc0lucHV0czogQm91bmRTdHlsaW5nRW50cnlbXXxudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfbGFzdFN0eWxpbmdJbnB1dDogQm91bmRTdHlsaW5nRW50cnl8bnVsbCA9IG51bGw7XG4gIHByaXZhdGUgX2ZpcnN0U3R5bGluZ0lucHV0OiBCb3VuZFN0eWxpbmdFbnRyeXxudWxsID0gbnVsbDtcblxuICAvLyBtYXBzIGFyZSB1c2VkIGluc3RlYWQgb2YgaGFzaCBtYXBzIGJlY2F1c2UgYSBNYXAgd2lsbFxuICAvLyByZXRhaW4gdGhlIG9yZGVyaW5nIG9mIHRoZSBrZXlzXG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIGxvY2F0aW9uIG9mIGVhY2ggc3R5bGUgYmluZGluZyBpbiB0aGUgdGVtcGxhdGVcbiAgICogKGUuZy4gYDxkaXYgW3N0eWxlLndpZHRoXT1cIndcIiBbc3R5bGUuaGVpZ2h0XT1cImhcIj5gIGltcGxpZXNcbiAgICogdGhhdCBgd2lkdGg9MGAgYW5kIGBoZWlnaHQ9MWApXG4gICAqL1xuICBwcml2YXRlIF9zdHlsZXNJbmRleCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIGxvY2F0aW9uIG9mIGVhY2ggY2xhc3MgYmluZGluZyBpbiB0aGUgdGVtcGxhdGVcbiAgICogKGUuZy4gYDxkaXYgW2NsYXNzLmJpZ109XCJiXCIgW2NsYXNzLmhpZGRlbl09XCJoXCI+YCBpbXBsaWVzXG4gICAqIHRoYXQgYGJpZz0wYCBhbmQgYGhpZGRlbj0xYClcbiAgICovXG4gIHByaXZhdGUgX2NsYXNzZXNJbmRleCA9IG5ld