/** * @license * Copyright Google Inc. 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 { __extends } from "tslib"; import { AST, ImplicitReceiver, RecursiveAstVisitor } from '../../expression_parser/ast'; import { Template } from '../r3_ast'; import { createCssSelector } from './template'; import { getAttrsForDirectiveMatching } from './util'; /** * Processes `Target`s with a given set of directives and performs a binding operation, which * returns an object similar to TypeScript's `ts.TypeChecker` that contains knowledge about the * target. */ var R3TargetBinder = /** @class */ (function () { function R3TargetBinder(directiveMatcher) { this.directiveMatcher = directiveMatcher; } /** * Perform a binding operation on the given `Target` and return a `BoundTarget` which contains * metadata about the types referenced in the template. */ R3TargetBinder.prototype.bind = function (target) { if (!target.template) { // TODO(alxhub): handle targets which contain things like HostBindings, etc. throw new Error('Binding without a template not yet supported'); } // First, parse the template into a `Scope` structure. This operation captures the syntactic // scopes in the template and makes them available for later use. var scope = Scope.apply(target.template); // Next, perform directive matching on the template using the `DirectiveBinder`. This returns: // - directives: Map of nodes (elements & ng-templates) to the directives on them. // - bindings: Map of inputs, outputs, and attributes to the directive/element that claims // them. TODO(alxhub): handle multiple directives claiming an input/output/etc. // - references: Map of #references to their targets. var _a = DirectiveBinder.apply(target.template, this.directiveMatcher), directives = _a.directives, bindings = _a.bindings, references = _a.references; // Finally, run the TemplateBinder to bind references, variables, and other entities within the // template. This extracts all the metadata that doesn't depend on directive matching. var _b = TemplateBinder.apply(target.template, scope), expressions = _b.expressions, symbols = _b.symbols, nestingLevel = _b.nestingLevel, usedPipes = _b.usedPipes; return new R3BoundTarget(target, directives, bindings, references, expressions, symbols, nestingLevel, usedPipes); }; return R3TargetBinder; }()); export { R3TargetBinder }; /** * Represents a binding scope within a template. * * Any variables, references, or other named entities declared within the template will * be captured and available by name in `namedEntities`. Additionally, child templates will * be analyzed and have their child `Scope`s available in `childScopes`. */ var Scope = /** @class */ (function () { function Scope(parentScope) { this.parentScope = parentScope; /** * Named members of the `Scope`, such as `Reference`s or `Variable`s. */ this.namedEntities = new Map(); /** * Child `Scope`s for immediately nested `Template`s. */ this.childScopes = new Map(); } /** * Process a template (either as a `Template` sub-template with variables, or a plain array of * template `Node`s) and construct its `Scope`. */ Scope.apply = function (template) { var scope = new Scope(); scope.ingest(template); return scope; }; /** * Internal method to process the template and populate the `Scope`. */ Scope.prototype.ingest = function (template) { var _this = this; if (template instanceof Template) { // Variables on an <ng-template> are defined in the inner scope. template.variables.forEach(function (node) { return _this.visitVariable(node); }); // Process the nodes of the template. template.children.forEach(function (node) { return node.visit(_this); }); } else { // No overarching `Template` instance, so process the nodes directly. template.forEach(function (node) { return node.visit(_this); }); } }; Scope.prototype.visitElement = function (element) { var _this = this; // `Element`s in the template may have `Reference`s which are captured in the scope. element.references.forEach(function (node) { return _this.visitReference(node); }); // Recurse into the `Element`'s children. element.children.forEach(function (node) { return node.visit(_this); }); }; Scope.prototype.visitTemplate = function (template) { var _this = this; // References on a <ng-template> are defined in the outer scope, so capture them before // processing the template's child scope. template.references.forEach(function (node) { return _this.visitReference(node); }); // Next, create an inner scope and process the template within it. var scope = new Scope(this); scope.ingest(template); this.childScopes.set(template, scope); }; Scope.prototype.visitVariable = function (variable) { // Declare the variable if it's not already. this.maybeDeclare(variable); }; Scope.prototype.visitReference = function (reference) { // Declare the variable if it's not already. this.maybeDeclare(reference); }; // Unused visitors. Scope.prototype.visitContent = function (content) { }; Scope.prototype.visitBoundAttribute = function (attr) { }; Scope.prototype.visitBoundEvent = function (event) { }; Scope.prototype.visitBoundText = function (text) { }; Scope.prototype.visitText = function (text) { }; Scope.prototype.visitTextAttribute = function (attr) { }; Scope.prototype.visitIcu = function (icu) { }; Scope.prototype.maybeDeclare = function (thing) { // Declare something with a name, as long as that name isn't taken. if (!this.namedEntities.has(thing.name)) { this.namedEntities.set(thing.name, thing); } }; /** * Look up a variable within this `Scope`. * * This can recurse into a parent `Scope` if it's available. */ Scope.prototype.lookup = function (name) { if (this.namedEntities.has(name)) { // Found in the local scope. return this.namedEntities.get(name); } else if (this.parentScope !== undefined) { // Not in the local scope, but there's a parent scope so check there. return this.parentScope.lookup(name); } else { // At the top level and it wasn't found. return null; } }; /** * Get the child scope for a `Template`. * * This should always be defined. */ Scope.prototype.getChildScope = function (template) { var res = this.childScopes.get(template); if (res === undefined) { throw new Error("Assertion error: child scope for " + template + " not found"); } return res; }; return Scope; }()); /** * Processes a template and matches directives on nodes (elements and templates). * * Usually used via the static `apply()` method. */ var DirectiveBinder = /** @class */ (function () { function DirectiveBinder(matcher, directives, bindings, references) { this.matcher = matcher; this.directives = directives; this.bindings = bindings; this.references = references; } /** * Process a template (list of `Node`s) and perform directive matching against each node. * * @param template the list of template `Node`s to match (recursively). * @param selectorMatcher a `SelectorMatcher` containing the directives that are in scope for * this template. * @returns three maps which contain information about directives in the template: the * `directives` map which lists directives matched on each node, the `bindings` map which * indicates which directives claimed which bindings (inputs, outputs, etc), and the `references` * map which resolves #references (`Reference`s) within the template to the named directive or * template node. */ DirectiveBinder.apply = function (template, selectorMatcher) { var directives = new Map(); var bindings = new Map(); var references = new Map(); var matcher = new DirectiveBinder(selectorMatcher, directives, bindings, references); matcher.ingest(template); return { directives: directives, bindings: bindings, references: references }; }; DirectiveBinder.prototype.ingest = function (template) { var _this = this; template.forEach(function (node) { return node.visit(_this); }); }; DirectiveBinder.prototype.visitElement = function (element) { this.visitElementOrTemplate(element.name, element); }; DirectiveBinder.prototype.visitTemplate = function (template) { this.visitElementOrTemplate('ng-template', template); }; DirectiveBinder.prototype.visitElementOrTemplate = function (elementName, node) { var _this = this; // First, determine the HTML shape of the node for the purpose of directive matching. // Do this by building up a `CssSelector` for the node. var cssSelector = createCssSelector(elementName, getAttrsForDirectiveMatching(node)); // Next, use the `SelectorMatcher` to get the list of directives on the node. var directives = []; this.matcher.match(cssSelector, function (_, directive) { return directives.push(directive); }); if (directives.length > 0) { this.directives.set(node, directives); } // Resolve any references that are created on this node. node.references.forEach(function (ref) { var dirTarget = null; // If the reference expression is empty, then it matches the "primary" directive on the node // (if there is one). Otherwise it matches the host node itself (either an element or // <ng-template> node). if (ref.value.trim() === '') { // This could be a reference to a component if there is one. dirTarget = directives.find(function (dir) { return dir.isComponent; }) || null; } else { // This should be a reference to a directive exported via exportAs. dirTarget = directives.find(function (dir) { return dir.exportAs !== null && dir.exportAs.some(function (value) { return value === ref.value; }); }) || null; // Check if a matching directive was found. if (dirTarget === null) { // No matching directive was found - this reference points to an unknown target. Leave it // unmapped. return; } } if (dirTarget !== null) { // This reference points to a directive. _this.references.set(ref, { directive: dirTarget, node: node }); } else { // This reference points to the node itself. _this.references.set(ref, node); } }); var setAttributeBinding = function (attribute, ioType) { var dir = directives.find(function (dir) { return dir[ioType].hasOwnProperty(attribute.name); }); var binding = dir !== undefined ? dir : node; _this.bindings.set(attribute, binding); }; // Node inputs (bound attributes) and text attributes can be bound to an // input on a directive. node.inputs.forEach(function (input) { return setAttributeBinding(input, 'inputs'); }); node.attributes.forEach(function (attr) { return setAttributeBinding(attr, 'inputs'); }); if (node instanceof Template) { node.templateAttrs.forEach(function (attr) { return setAttributeBinding(attr, 'inputs'); }); } // Node outputs (bound events) can be bound to an output on a directive. node.outputs.forEach(function (output) { return setAttributeBinding(output, 'outputs'); }); // Recurse into the node's children. node.children.forEach(function (child) { return child.visit(_this); }); }; // Unused visitors. DirectiveBinder.prototype.visitContent = function (content) { }; DirectiveBinder.prototype.visitVariable = function (variable) { }; DirectiveBinder.prototype.visitReference = function (reference) { }; DirectiveBinder.prototype.visitTextAttribute = function (attribute) { }; DirectiveBinder.prototype.visitBoundAttribute = function (attribute) { }; DirectiveBinder.prototype.visitBoundEvent = function (attribute) { }; DirectiveBinder.prototype.visitBoundAttributeOrEvent = function (node) { }; DirectiveBinder.prototype.visitText = function (text) { }; DirectiveBinder.prototype.visitBoundText = function (text) { }; DirectiveBinder.prototype.visitIcu = function (icu) { }; return DirectiveBinder; }()); /** * Processes a template and extract metadata about expressions and symbols within. * * This is a companion to the `DirectiveBinder` that doesn't require knowledge of directives matched * within the template in order to operate. * * Expressions are visited by the superclass `RecursiveAstVisitor`, with custom logic provided * by overridden methods from that visitor. */ var TemplateBinder = /** @class */ (function (_super) { __extends(TemplateBinder, _super); function TemplateBinder(bindings, symbols, usedPipes, nestingLevel, scope, template, level) { var _this = _super.call(this) || this; _this.bindings = bindings; _this.symbols = symbols; _this.usedPipes = usedPipes; _this.nestingLevel = nestingLevel; _this.scope = scope; _this.template = template; _this.level = level; _this.pipesUsed = []; // Save a bit of processing time by constructing this closure in advance. _this.visitNode = function (node) { return node.visit(_this); }; return _this; } // This method is defined to reconcile the type of TemplateBinder since both // RecursiveAstVisitor and Visitor define the visit() method in their // interfaces. TemplateBinder.prototype.visit = function (node, context) { if (node instanceof AST) { node.visit(this, context); } else { node.visit(this); } }; /** * Process a template and extract metadata about expressions and symbols within. * * @param template the nodes of the template to process * @param scope the `Scope` of the template being processed. * @returns three maps which contain metadata about the template: `expressions` which interprets * special `AST` nodes in expressions as pointing to references or variables declared within the * template, `symbols` which maps those variables and references to the nested `Template` which * declares them, if any, and `nestingLevel` which associates each `Template` with a integer * nesting level (how many levels deep within the template structure the `Template` is), starting * at 1. */ TemplateBinder.apply = function (template, scope) { var expressions = new Map(); var symbols = new Map(); var nestingLevel = new Map(); var usedPipes = new Set(); // The top-level template has nesting level 0. var binder = new TemplateBinder(expressions, symbols, usedPipes, nestingLevel, scope, template instanceof Template ? template : null, 0); binder.ingest(template); return { expressions: expressions, symbols: symbols, nestingLevel: nestingLevel, usedPipes: usedPipes }; }; TemplateBinder.prototype.ingest = function (template) { if (template instanceof Template) { // For <ng-template>s, process only variables and child nodes. Inputs, outputs, templateAttrs, // and references were all processed in the scope of the containing template. template.variables.forEach(this.visitNode); template.children.forEach(this.visitNode); // Set the nesting level. this.nestingLevel.set(template, this.level); } else { // Visit each node from the top-level template. template.forEach(this.visitNode); } }; TemplateBinder.prototype.visitElement = function (element) { // Visit the inputs, outputs, and children of the element. element.inputs.forEach(this.visitNode); element.outputs.forEach(this.visitNode); element.children.forEach(this.visitNode); }; TemplateBinder.prototype.visitTemplate = function (template) { // First, visit inputs, outputs and template attributes of the template node. template.inputs.forEach(this.visitNode); template.outputs.forEach(this.visitNode); template.templateAttrs.forEach(this.visitNode); // References are also evaluated in the outer context. template.references.forEach(this.visitNode); // Next, recurse into the template using its scope, and bumping the nesting level up by one. var childScope = this.scope.getChildScope(template); var binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.nestingLevel, childScope, template, this.level + 1); binder.ingest(template); }; TemplateBinder.prototype.visitVariable = function (variable) { // Register the `Variable` as a symbol in the current `Template`. if (this.template !== null) { this.symbols.set(variable, this.template); } }; TemplateBinder.prototype.visitReference = function (reference) { // Register the `Reference` as a symbol in the current `Template`. if (this.template !== null) { this.symbols.set(reference, this.template); } }; // Unused template visitors TemplateBinder.prototype.visitText = function (text) { }; TemplateBinder.prototype.visitContent = function (content) { }; TemplateBinder.prototype.visitTextAttribute = function (attribute) { }; TemplateBinder.prototype.visitIcu = function (icu) { }; // The remaining visitors are concerned with processing AST expressions within template bindings TemplateBinder.prototype.visitBoundAttribute = function (attribute) { attribute.value.visit(this); }; TemplateBinder.prototype.visitBoundEvent = function (event) { event.handler.visit(this); }; TemplateBinder.prototype.visitBoundText = function (text) { text.value.visit(this); }; TemplateBinder.prototype.visitPipe = function (ast, context) { this.usedPipes.add(ast.name); return _super.prototype.visitPipe.call(this, ast, context); }; // These five types of AST expressions can refer to expression roots, which could be variables // or references in the current scope. TemplateBinder.prototype.visitPropertyRead = function (ast, context) { this.maybeMap(context, ast, ast.name); return _super.prototype.visitPropertyRead.call(this, ast, context); }; TemplateBinder.prototype.visitSafePropertyRead = function (ast, context) { this.maybeMap(context, ast, ast.name); return _super.prototype.visitSafePropertyRead.call(this, ast, context); }; TemplateBinder.prototype.visitPropertyWrite = function (ast, context) { this.maybeMap(context, ast, ast.name); return _super.prototype.visitPropertyWrite.call(this, ast, context); }; TemplateBinder.prototype.visitMethodCall = function (ast, context) { this.maybeMap(context, ast, ast.name); return _super.prototype.visitMethodCall.call(this, ast, context); }; TemplateBinder.prototype.visitSafeMethodCall = function (ast, context) { this.maybeMap(context, ast, ast.name); return _super.prototype.visitSafeMethodCall.call(this, ast, context); }; TemplateBinder.prototype.maybeMap = function (scope, ast, name) { // If the receiver of the expression isn't the `ImplicitReceiver`, this isn't the root of an // `AST` expression that maps to a `Variable` or `Reference`. if (!(ast.receiver instanceof ImplicitReceiver)) { return; } // Check whether the name exists in the current scope. If so, map it. Otherwise, the name is // probably a property on the top-level component context. var target = this.scope.lookup(name); if (target !== null) { this.bindings.set(ast, target); } }; return TemplateBinder; }(RecursiveAstVisitor)); /** * Metadata container for a `Target` that allows queries for specific bits of metadata. * * See `BoundTarget` for documentation on the individual methods. */ var R3BoundTarget = /** @class */ (function () { function R3BoundTarget(target, directives, bindings, references, exprTargets, symbols, nestingLevel, usedPipes) { this.target = target; this.directives = directives; this.bindings = bindings; this.references = references; this.exprTargets = exprTargets; this.symbols = symbols; this.nestingLevel = nestingLevel; this.usedPipes = usedPipes; } R3BoundTarget.prototype.getDirectivesOfNode = function (node) { return this.directives.get(node) || null; }; R3BoundTarget.prototype.getReferenceTarget = function (ref) { return this.references.get(ref) || null; }; R3BoundTarget.prototype.getConsumerOfBinding = function (binding) { return this.bindings.get(binding) || null; }; R3BoundTarget.prototype.getExpressionTarget = function (expr) { return this.exprTargets.get(expr) || null; }; R3BoundTarget.prototype.getTemplateOfSymbol = function (symbol) { return this.symbols.get(symbol) || null; }; R3BoundTarget.prototype.getNestingLevel = function (template) { return this.nestingLevel.get(template) || 0; }; R3BoundTarget.prototype.getUsedDirectives = function () { var set = new Set(); this.directives.forEach(function (dirs) { return dirs.forEach(function (dir) { return set.add(dir); }); }); return Array.from(set.values()); }; R3BoundTarget.prototype.getUsedPipes = function () { return Array.from(this.usedPipes); }; return R3BoundTarget; }()); export { R3BoundTarget }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidDJfYmluZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlcjMvdmlldy90Ml9iaW5kZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HOztBQUVILE9BQU8sRUFBQyxHQUFHLEVBQWUsZ0JBQWdCLEVBQTJDLG1CQUFtQixFQUFtQyxNQUFNLDZCQUE2QixDQUFDO0FBRS9LLE9BQU8sRUFBZ0YsUUFBUSxFQUF5QyxNQUFNLFdBQVcsQ0FBQztBQUcxSixPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDN0MsT0FBTyxFQUFDLDRCQUE0QixFQUFDLE1BQU0sUUFBUSxDQUFDO0FBR3BEOzs7O0dBSUc7QUFDSDtJQUNFLHdCQUFvQixnQkFBNkM7UUFBN0MscUJBQWdCLEdBQWhCLGdCQUFnQixDQUE2QjtJQUFHLENBQUM7SUFFckU7OztPQUdHO0lBQ0gsNkJBQUksR0FBSixVQUFLLE1BQWM7UUFDakIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7WUFDcEIsNEVBQTRFO1lBQzVFLE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztTQUNqRTtRQUVELDRGQUE0RjtRQUM1RixpRUFBaUU7UUFDakUsSUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFM0MsOEZBQThGO1FBQzlGLG9GQUFvRjtRQUNwRiw0RkFBNEY7UUFDNUYsbUZBQW1GO1FBQ25GLHVEQUF1RDtRQUNqRCxJQUFBLGtFQUMyRCxFQUQxRCwwQkFBVSxFQUFFLHNCQUFRLEVBQUUsMEJBQ29DLENBQUM7UUFDbEUsK0ZBQStGO1FBQy9GLHNGQUFzRjtRQUNoRixJQUFBLGlEQUMwQyxFQUR6Qyw0QkFBVyxFQUFFLG9CQUFPLEVBQUUsOEJBQVksRUFBRSx3QkFD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c2VcbiAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtBU1QsIEJpbmRpbmdQaXBlLCBJbXBsaWNpdFJlY2VpdmVyLCBNZXRob2RDYWxsLCBQcm9wZXJ0eVJlYWQsIFByb3BlcnR5V3JpdGUsIFJlY3Vyc2l2ZUFzdFZpc2l0b3IsIFNhZmVNZXRob2RDYWxsLCBTYWZlUHJvcGVydHlSZWFkfSBmcm9tICcuLi8uLi9leHByZXNzaW9uX3BhcnNlci9hc3QnO1xuaW1wb3J0IHtDc3NTZWxlY3RvciwgU2VsZWN0b3JNYXRjaGVyfSBmcm9tICcuLi8uLi9zZWxlY3Rvcic7XG5pbXBvcnQge0JvdW5kQXR0cmlidXRlLCBCb3VuZEV2ZW50LCBCb3VuZFRleHQsIENvbnRlbnQsIEVsZW1lbnQsIEljdSwgTm9kZSwgUmVmZXJlbmNlLCBUZW1wbGF0ZSwgVGV4dCwgVGV4dEF0dHJpYnV0ZSwgVmFyaWFibGUsIFZpc2l0b3J9IGZyb20gJy4uL3IzX2FzdCc7XG5cbmltcG9ydCB7Qm91bmRUYXJnZXQsIERpcmVjdGl2ZU1ldGEsIFRhcmdldCwgVGFyZ2V0QmluZGVyfSBmcm9tICcuL3QyX2FwaSc7XG5pbXBvcnQge2NyZWF0ZUNzc1NlbGVjdG9yfSBmcm9tICcuL3RlbXBsYXRlJztcbmltcG9ydCB7Z2V0QXR0cnNGb3JEaXJlY3RpdmVNYXRjaGluZ30gZnJvbSAnLi91dGlsJztcblxuXG4vKipcbiAqIFByb2Nlc3NlcyBgVGFyZ2V0YHMgd2l0aCBhIGdpdmVuIHNldCBvZiBkaXJlY3RpdmVzIGFuZCBwZXJmb3JtcyBhIGJpbmRpbmcgb3BlcmF0aW9uLCB3aGljaFxuICogcmV0dXJucyBhbiBvYmplY3Qgc2ltaWxhciB0byBUeXBlU2NyaXB0J3MgYHRzLlR5cGVDaGVja2VyYCB0aGF0IGNvbnRhaW5zIGtub3dsZWRnZSBhYm91dCB0aGVcbiAqIHRhcmdldC5cbiAqL1xuZXhwb3J0IGNsYXNzIFIzVGFyZ2V0QmluZGVyPERpcmVjdGl2ZVQgZXh0ZW5kcyBEaXJlY3RpdmVNZXRhPiBpbXBsZW1lbnRzIFRhcmdldEJpbmRlcjxEaXJlY3RpdmVUPiB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZGlyZWN0aXZlTWF0Y2hlcjogU2VsZWN0b3JNYXRjaGVyPERpcmVjdGl2ZVQ+KSB7fVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgYmluZGluZyBvcGVyYXRpb24gb24gdGhlIGdpdmVuIGBUYXJnZXRgIGFuZCByZXR1cm4gYSBgQm91bmRUYXJnZXRgIHdoaWNoIGNvbnRhaW5zXG4gICAqIG1ldGFkYXRhIGFib3V0IHRoZSB0eXBlcyByZWZlcmVuY2VkIGluIHRoZSB0ZW1wbGF0ZS5cbiAgICovXG4gIGJpbmQodGFyZ2V0OiBUYXJnZXQpOiBCb3VuZFRhcmdldDxEaXJlY3RpdmVUPiB7XG4gICAgaWYgKCF0YXJnZXQudGVtcGxhdGUpIHtcbiAgICAgIC8vIFRPRE8oYWx4aHViKTogaGFuZGxlIHRhcmdldHMgd2hpY2ggY29udGFpbiB0aGluZ3MgbGlrZSBIb3N0QmluZGluZ3MsIGV0Yy5cbiAgICAgIHRocm93IG5ldyBFcnJvcignQmluZGluZyB3aXRob3V0IGEgdGVtcGxhdGUgbm90IHlldCBzdXBwb3J0ZWQnKTtcbiAgICB9XG5cbiAgICAvLyBGaXJzdCwgcGFyc2UgdGhlIHRlbXBsYXRlIGludG8gYSBgU2NvcGVgIHN0cnVjdHVyZS4gVGhpcyBvcGVyYXRpb24gY2FwdHVyZXMgdGhlIHN5bnRhY3RpY1xuICAgIC8vIHNjb3BlcyBpbiB0aGUgdGVtcGxhdGUgYW5kIG1ha2VzIHRoZW0gYXZhaWxhYmxlIGZvciBsYXRlciB1c2UuXG4gICAgY29uc3Qgc2NvcGUgPSBTY29wZS5hcHBseSh0YXJnZXQudGVtcGxhdGUpO1xuXG4gICAgLy8gTmV4dCwgcGVyZm9ybSBkaXJlY3RpdmUgbWF0Y2hpbmcgb24gdGhlIHRlbXBsYXRlIHVzaW5nIHRoZSBgRGlyZWN0aXZlQmluZGVyYC4gVGhpcyByZXR1cm5zOlxuICAgIC8vICAgLSBkaXJlY3RpdmVzOiBNYXAgb2Ygbm9kZXMgKGVsZW1lbnRzICYgbmctdGVtcGxhdGVzKSB0byB0aGUgZGlyZWN0aXZlcyBvbiB0aGVtLlxuICAgIC8vICAgLSBiaW5kaW5nczogTWFwIG9mIGlucHV0cywgb3V0cHV0cywgYW5kIGF0dHJpYnV0ZXMgdG8gdGhlIGRpcmVjdGl2ZS9lbGVtZW50IHRoYXQgY2xhaW1zXG4gICAgLy8gICAgIHRoZW0uIFRPRE8oYWx4aHViKTogaGFuZGxlIG11bHRpcGxlIGRpcmVjdGl2ZXMgY2xhaW1pbmcgYW4gaW5wdXQvb3V0cHV0L2V0Yy5cbiAgICAvLyAgIC0gcmVmZXJlbmNlczogTWFwIG9mICNyZWZlcmVuY2VzIHRvIHRoZWlyIHRhcmdldHMuXG4gICAgY29uc3Qge2RpcmVjdGl2ZXMsIGJpbmRpbmdzLCByZWZlcmVuY2VzfSA9XG4gICAgICAgIERpcmVjdGl2ZUJpbmRlci5hcHBseSh0YXJnZXQudGVtcGxhdGUsIHRoaXMuZGlyZWN0aXZlTWF0Y2hlcik7XG4gICAgLy8gRmluYWxseSwgcnVuIHRoZSBUZW1wbGF0ZUJpbmRlciB0byBiaW5kIHJlZmVyZW5jZXMsIHZhcmlhYmxlcywgYW5kIG90aGVyIGVudGl0aWVzIHdpdGhpbiB0aGVcbiAgICAvLyB0ZW1wbGF0ZS4gVGhpcyBleHRyYWN0cyBhbGwgdGhlIG1ldGFkYXRhIHRoYXQgZG9lc24ndCBkZXBlbmQgb24gZGlyZWN0aXZlIG1hdGNoaW5nLlxuICAgIGNvbnN0IHtleHByZXNzaW9ucywgc3ltYm9scywgbmVzdGluZ0xldmVsLCB1c2VkUGlwZXN9ID1cbiAgICAgICAgVGVtcGxhdGVCaW5kZXIuYXBwbHkodGFyZ2V0LnRlbXBsYXRlLCBzY29wZSk7XG4gICAgcmV0dXJuIG5ldyBSM0JvdW5kVGFyZ2V0KFxuICAgICAgICB0YXJnZXQsIGRpcmVjdGl2ZXMsIGJpbmRpbmdzLCByZWZlcmVuY2VzLCBleHByZXNzaW9ucywgc3ltYm9scywgbmVzdGluZ0xldmVsLCB1c2VkUGlwZXMpO1xuICB9XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGJpbmRpbmcgc2NvcGUgd2l0aGluIGEgdGVtcGxhdGUuXG4gKlxuICogQW55IHZhcmlhYmxlcywgcmVmZXJlbmNlcywgb3Igb3RoZXIgbmFtZWQgZW50aXRpZXMgZGVjbGFyZWQgd2l0aGluIHRoZSB0ZW1wbGF0ZSB3aWxsXG4gKiBiZSBjYXB0dXJlZCBhbmQgYXZhaWxhYmxlIGJ5IG5hbWUgaW4gYG5hbWVkRW50aXRpZXNgLiBBZGRpdGlvbmFsbHksIGNoaWxkIHRlbXBsYXRlcyB3aWxsXG4gKiBiZSBhbmFseXplZCBhbmQgaGF2ZSB0aGVpciBjaGlsZCBgU2NvcGVgcyBhdmFpbGFibGUgaW4gYGNoaWxkU2NvcGVzYC5cbiAqL1xuY2xhc3MgU2NvcGUgaW1wbGVtZW50cyBWaXNpdG9yIHtcbiAgLyoqXG4gICAqIE5hbWVkIG1lbWJlcnMgb2YgdGhlIGBTY29wZWAsIHN1Y2ggYXMgYFJlZmVyZW5jZWBzIG9yIGBWYXJpYWJsZWBzLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZWRFbnRpdGllcyA9IG5ldyBNYXA8c3RyaW5nLCBSZWZlcmVuY2V8VmFyaWFibGU+KCk7XG5cbiAgLyoqXG4gICAqIENoaWxkIGBTY29wZWBzIGZvciBpbW1lZGlhdGVseSBuZXN0ZWQgYFRlbXBsYXRlYHMuXG4gICAqL1xuICByZWFkb25seSBjaGlsZFNjb3BlcyA9IG5ldyBNYXA8VGVtcGxhdGUsIFNjb3BlPigpO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocmVhZG9ubHkgcGFyZW50U2NvcGU/OiBTY29wZSkge31cblxuICAvKipcbiAgICogUHJvY2VzcyBhIHRlbXBsYXRlIChlaXRoZXIgYXMgYSBgVGVtcGxhdGVgIHN1Yi10ZW1wbGF0ZSB3aXRoIHZhcmlhYmxlcywgb3IgYSBwbGFpbiBhcnJheSBvZlxuICAgKiB0ZW1wbGF0ZSBgTm9kZWBzKSBhbmQgY29uc3RydWN0IGl0cyBgU2NvcGVgLlxuICAgKi9cbiAgc3RhdGljIGFwcGx5KHRlbXBsYXRlOiBUZW1wbGF0ZXxOb2RlW10pOiBTY29wZSB7XG4gICAgY29uc3Qgc2NvcGUgPSBuZXcgU2NvcGUoKTtcbiAgICBzY29wZS5pbmdlc3QodGVtcGxhdGUpO1xuICAgIHJldHVybiBzY29wZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnRlcm5hbCBtZXRob2QgdG8gcHJvY2VzcyB0aGUgdGVtcGxhdGUgYW5kIHBvcHVsYXRlIHRoZSBgU2NvcGVgLlxuICAgKi9cbiAgcHJpdmF0ZSBpbmdlc3QodGVtcGxhdGU6IFRlbXBsYXRlfE5vZGVbXSk6IHZvaWQge1xuICAgIGlmICh0ZW1wbGF0ZSBpbnN0YW5jZW9mIFRlbXBsYXRlKSB7XG4gICAgICAvLyBWYXJpYWJsZXMgb24gYW4gPG5nLXRlbXBsYXRlPiBhcmUgZGVmaW5lZCBpbiB0aGUgaW5uZXIgc2NvcGUuXG4gICAgICB0ZW1wbGF0ZS52YXJpYWJsZXMuZm9yRWFjaChub2RlID0+IHRoaXMudmlzaXRWYXJpYWJsZShub2RlKSk7XG5cbiAgICAgIC8vIFByb2Nlc3MgdGhlIG5vZGVzIG9mIHRoZSB0ZW1wbGF0ZS5cbiAgICAgIHRlbXBsYXRlLmNoaWxkcmVuLmZvckVhY2gobm9kZSA9PiBub2RlLnZpc2l0KHRoaXMpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gTm8gb3ZlcmFyY2hpbmcgYFRlbXBsYXRlYCBpbnN0YW5jZSwgc28gcHJvY2VzcyB0aGUgbm9kZXMgZGlyZWN0bHkuXG4gICAgICB0ZW1wbGF0ZS5mb3JFYWNoKG5vZGUgPT4gbm9kZS52aXNpdCh0aGlzKSk7XG4gICAgfVxuICB9XG5cbiAgdmlzaXRFbGVtZW50KGVsZW1lbnQ6IEVsZW1lbnQpIHtcbiAgICAvLyBgRWxlbWVudGBzIGluIHRoZSB0ZW1wbGF0ZSBtYXkgaGF2ZSBgUmVmZXJlbmNlYHMgd2hpY2ggYXJlIGNhcHR1cmVkIGluIHRoZSBzY29wZS5cbiAgICBlbGVtZW50LnJlZmVyZW5jZXMuZm9yRWFjaChub2RlID0+IHRoaXMudmlzaXRSZWZlcmVuY2Uobm9kZSkpO1xuXG4gICAgLy8gUmVjdXJzZSBpbnRvIHRoZSBgRWxlbWVudGAncyBjaGlsZHJlbi5cbiAgICBlbGVtZW50LmNoaWxkcmVuLmZvckVhY2gobm9kZSA9PiBub2RlLnZpc2l0KHRoaXMpKTtcbiAgfVxuXG4gIHZpc2l0VGVtcGxhdGUodGVtcGxhdGU6IFRlbXBsYXRlKSB7XG4gICAgLy8gUmVmZXJlbmNlcyBvbiBhIDxuZy10ZW1wbGF0ZT4gYXJlIGRlZmluZWQgaW4gdGhlIG91dGVyIHNjb3BlLCBzbyBjYXB0dXJlIHRoZW0gYmVmb3JlXG4gICAgLy8gcHJvY2Vzc2luZyB0aGUgdGVtcGxhdGUncyBjaGlsZCBzY29wZS5cbiAgICB0ZW1wbGF0ZS5yZWZlcmVuY2VzLmZvckVhY2gobm9kZSA9PiB0aGlzLnZpc2l0UmVmZXJlbmNlKG5vZGUpKTtcblxuICAgIC8vIE5leHQsIGNyZWF0ZSBhbiBpbm5lciBzY29wZSBhbmQgcHJvY2VzcyB0aGUgdGVtcGxhdGUgd2l0aGluIGl0LlxuICAgIGNvbnN0IHNjb3BlID0gbmV3IFNjb3BlKHRoaXMpO1xuICAgIHNjb3BlLmluZ2VzdCh0ZW1wbGF0ZSk7XG4gICAgdGhpcy5jaGlsZFNjb3Blcy5zZXQodGVtcGxhdGUsIHNjb3BlKTtcbiAgfVxuXG4gIHZpc2l0VmFyaWFibGUodmFyaWFibGU6IFZhcmlhYmxlKSB7XG4gICAgLy8gRGVjbGFyZSB0aGUgdmFyaWFibGUgaWYgaXQncyBub3QgYWxyZWFkeS5cbiAgICB0aGlzLm1heWJlRGVjbGFyZSh2YXJpYWJsZSk7XG4gIH1cblxuICB2aXNpdFJlZmVyZW5jZShyZWZlcmVuY2U6IFJlZmVyZW5jZSkge1xuICAgIC8vIERlY2xhcmUgdGhlIHZhcmlhYmxlIGlmIGl0J3Mgbm90IGFscmVhZHkuXG4gICAgdGhpcy5tYXliZURlY2xhcmUocmVmZXJlbmNlKTtcbiAgfVxuXG4gIC8vIFVudXNlZCB2aXNpdG9ycy5cbiAgdmlzaXRDb250ZW50KGNvbnRlbnQ6IENvbnRlbnQpIHt9XG4gIHZpc2l0Qm91bmRBdHRyaWJ1dGUoYXR0cjogQm91bmRBdHRyaWJ1dGUpIHt9XG4gIHZpc2l0Qm91bmRFdmVudChldmVudDogQm91bmRFdmVudCkge31cbiAgdmlzaXRCb3VuZFRleHQodGV4dDogQm91bmRUZXh0KSB7fVxuICB2aXNpdFRleHQodGV4dDogVGV4dCkge31cbiAgdmlzaXRUZXh0QXR0cmlidXRlKGF0dHI6IFRleHRBdHRyaWJ1dGUpIHt9XG4gIHZpc2l0SWN1KGljdTogSWN1KSB7fVxuXG4gIHByaXZhdGUgbWF5YmVEZWNsYXJlKHRoaW5nOiBSZWZlcmVuY2V8VmFyaWFibGUpIHtcbiAgICAvLyBEZWNsYXJlIHNvbWV0aGluZyB3aXRoIGEgbmFtZSwgYXMgbG9uZyBhcyB0aGF0IG5hbWUgaXNuJ3QgdGFrZW4uXG4gICAgaWYgKCF0aGlzLm5hbWVkRW50aXRpZXMuaGFzKHRoaW5nLm5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVkRW50aXRpZXMuc2V0KHRoaW5nLm5hbWUsIHRoaW5nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTG9vayB1cCBhIHZhcmlhYmxlIHdpdGhpbiB0aGlzIGBTY29wZWAuXG4gICAqXG4gICAqIFRoaXMgY2FuIHJlY3Vyc2UgaW50byBhIHBhcmVudCBgU2NvcGVgIGlmIGl0J3MgYXZhaWxhYmxlLlxuICAgKi9cbiAgbG9va3VwKG5hbWU6IHN0cmluZyk6IFJlZmVyZW5jZXxWYXJpYWJsZXxudWxsIHtcbiAgICBpZiAodGhpcy5uYW1lZEVudGl0aWVzLmhhcyhuYW1lKSkge1xuICAgICAgLy8gRm91bmQgaW4gdGhlIGxvY2FsIHNjb3BlLlxuICAgICAgcmV0dXJuIHRoaXMubmFtZWRFbnRpdGllcy5nZXQobmFtZSkgITtcbiAgICB9IGVsc2UgaWYgKHRoaXMucGFyZW50U2NvcGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gTm90IGluIHRoZSBsb2NhbCBzY29wZSwgYnV0IHRoZXJlJ3MgYSBwYXJlbnQgc2NvcGUgc28gY2hlY2sgdGhlcmUuXG4gICAgICByZXR1cm4gdGhpcy5wYXJlbnRTY29wZS5sb29rdXAobmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IHRoZSB0b3AgbGV2ZWwgYW5kIGl0IHdhc24ndCBmb3VuZC5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGNoaWxkIHNjb3BlIGZvciBhIGBUZW1wbGF0ZWAuXG4gICAqXG4gICAqIFRoaXMgc2hvdWxkIGFsd2F5cyBiZSBkZWZpbmVkLlxuICAgKi9cbiAgZ2V0Q2hpbGRTY29wZSh0ZW1wbGF0ZTogVGVtcGxhdGUpOiBTY29wZSB7XG4gICAgY29uc3QgcmVzID0gdGhpcy5jaGlsZFNjb3Blcy5nZXQodGVtcGxhdGUpO1xuICAgIGlmIChyZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBc3NlcnRpb24gZXJyb3I6IGNoaWxkIHNjb3BlIGZvciAke3RlbXBsYXRlfSBub3QgZm91bmRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfVxufVxuXG4vKipcbiAqIFByb2Nlc3NlcyBhIHRlbXBsYXRlIGFuZCBtYXRjaGVzIGRpcmVjdGl2ZXMgb24gbm9kZXMgKGVsZW1lbnRzIGFuZCB0ZW1wbGF0ZXMpLlxuICpcbiAqIFVzdWFsbHkgdXNlZCB2aWEgdGhlIHN0YXRpYyBgYXBwbHkoKWAgbWV0aG9kLlxuICovXG5jbGFzcyBEaXJlY3RpdmVCaW5kZXI8RGlyZWN0aXZlVCBleHRlbmRzIERpcmVjdGl2ZU1ldGE+IGltcGxlbWVudHMgVmlzaXRvciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSBtYXRjaGVyOiBTZWxlY3Rvck1hdGNoZXI8RGlyZWN0aXZlVD4sXG4gICAgICBwcml2YXRlIGRpcmVjdGl2ZXM6IE1hcDxFbGVtZW50fFRlbXBsYXRlLCBEaXJlY3RpdmVUW10+LFxuICAgICAgcHJpdmF0ZSBiaW5kaW5nczogTWFwPEJvdW5kQXR0cmlidXRlfEJvdW5kRXZlbnR8VGV4dEF0dHJpYnV0ZSwgRGlyZWN0aXZlVHxFbGVtZW50fFRlbXBsYXRlPixcbiAgICAgIHByaXZhdGUgcmVmZXJlbmNlczpcbiAgICAgICAgICBNYXA8UmVmZXJlbmNlLCB7ZGlyZWN0aXZlOiBEaXJlY3RpdmVULCBub2RlOiBFbGVtZW50fFRlbXBsYXRlfXxFbGVtZW50fFRlbXBsYXRlPikge31cblxuICAvKipcbiAgICogUHJvY2VzcyBhIHRlbXBsYXRlIChsaXN0IG9mIGBOb2RlYHMpIGFuZCBwZXJmb3JtIGRpcmVjdGl2ZSBtYXRjaGluZyBhZ2FpbnN0IGVhY2ggbm9kZS5cbiAgICpcbiAgICogQHBhcmFtIHRlbXBsYXRlIHRoZSBsaXN0IG9mIHRlbXBsYXRlIGBOb2RlYHMgdG8gbWF0Y2ggKHJlY3Vyc2l2ZWx5KS5cbiAgICogQHBhcmFtIHNlbGVjdG9yTWF0Y2hlciBhIGBTZWxlY3Rvck1hdGNoZXJgIGNvbnRhaW5pbmcgdGhlIGRpcmVjdGl2ZXMgdGhhdCBhcmUgaW4gc2NvcGUgZm9yXG4gICAqIHRoaXMgdGVtcGxhdGUuXG4gICAqIEByZXR1cm5zIHRocmVlIG1hcHMgd2hpY2ggY29udGFpbiBpbmZvcm1hdGlvbiBhYm91dCBkaXJlY3RpdmVzIGluIHRoZSB0ZW1wbGF0ZTogdGhlXG4gICAqIGBkaXJlY3RpdmVzYCBtYXAgd2hpY2ggbGlzdHMgZGlyZWN0aXZlcyBtYXRjaGVkIG9uIGVhY2ggbm9kZSwgdGhlIGBiaW5kaW5nc2AgbWFwIHdoaWNoXG4gICAqIGluZGljYXRlcyB3aGljaCBkaXJlY3RpdmVzIGNsYWltZWQgd2hpY2ggYmluZGluZ3MgKGlucHV0cywgb3V0cHV0cywgZXRjKSwgYW5kIHRoZSBgcmVmZXJlbmNlc2BcbiAgICogbWFwIHdoaWNoIHJlc29sdmVzICNyZWZlcmVuY2VzIChgUmVmZXJlbmNlYHMpIHdpdGhpbiB0aGUgdGVtcGxhdGUgdG8gdGhlIG5hbWVkIGRpcmVjdGl2ZSBvclxuICAgKiB0ZW1wbGF0ZSBub2RlLlxuICAgKi9cbiAgc3RhdGljIGFwcGx5PERpcmVjdGl2ZVQgZXh0ZW5kcyBEaXJlY3RpdmVNZXRhPihcbiAgICAgIHRlbXBsYXRlOiBOb2RlW10sIHNlbGVjdG9yTWF0Y2hlcjogU2VsZWN0b3JNYXRjaGVyPERpcmVjdGl2ZVQ+KToge1xuICAgIGRpcmVjdGl2ZXM6IE1hcDxFbGVtZW50fFRlbXBsYXRlLCBEaXJlY3RpdmVUW10+LFxuICAgIGJpbmRpbmdzOiBNYXA8Qm91bmRBdHRyaWJ1dGV8Qm91bmRFdmVudHxUZXh0QXR0cmlidXRlLCBEaXJlY3RpdmVUfEVsZW1lbnR8VGVtcGxhdGU+LFxuICAgIHJlZmVyZW5jZXM6IE1hcDxSZWZlcmVuY2UsIHtkaXJlY3RpdmU6IERpcmVjdGl2ZVQsIG5vZGU6IEVsZW1lbnR8VGVtcGxhdGV9fEVsZW1lbnR8VGVtcGxhdGU+LFxuICB9IHtcbiAgICBjb25zdCBkaXJlY3RpdmVzID0gbmV3IE1hcDxFbGVtZW50fFRlbXBsYXRlLCBEaXJlY3RpdmVUW10+KCk7XG4gICAgY29uc3QgYmluZGluZ3MgPVxuICAgICAgICBuZXcgTWFwPEJvdW5kQXR0cmlidXRlfEJvdW5kRXZlbnR8VGV4dEF0dHJpYnV0ZSwgRGlyZWN0aXZlVHxFbGVtZW50fFRlbXBsYXRlPigpO1xuICAgIGNvbnN0IHJlZmVyZW5jZXMgPVxuICAgICAgICBuZXcgTWFwPFJlZmVyZW5jZSwge2RpcmVjdGl2ZTogRGlyZWN0aXZlVCwgbm9kZTogRWxlbWVudCB8IFRlbXBsYXRlfXxFbGVtZW50fFRlbXBsYXRlPigpO1xuICAgIGNvbnN0IG1hdGNoZXIgPSBuZXcgRGlyZWN0aXZlQmluZGVyKHNlbGVjdG9yTWF0Y2hlciwgZGlyZWN0aXZlcywgYmluZGluZ3MsIHJlZmVyZW5jZXMpO1xuICAgIG1hdGNoZXIuaW5nZXN0KHRlbXBsYXRlKTtcbiAgICByZXR1cm4ge2RpcmVjdGl2ZXMsIGJpbmRpbmdzLCByZWZlcmVuY2VzfTtcbiAgfVxuXG4gIHByaXZhdGUgaW5nZXN0KHRlbXBsYXRlOiBOb2RlW10pOiB2b2lkIHsgdGVtcGxhdGUuZm9yRWFjaChub2RlID0+IG5vZGUudmlzaXQodGhpcykpOyB9XG5cbiAgdmlzaXRFbGVtZW50KGVsZW1lbnQ6IEVsZW1lbnQpOiB2b2lkIHsgdGhpcy52aXNpdEVsZW1lbnRPclRlbXBsYXRlKGVsZW1lbnQubmFtZSwgZWxlbWVudCk7IH1cblxuICB2aXNpdFRlbXBsYXRlKHRlbXBsYXRlOiBUZW1wbGF0ZSk6IHZvaWQgeyB0aGlzLnZpc2l0RWxlbWVudE9yVGVtcGxhdGUoJ25nLXRlbXBsYXRlJywgdGVtcGxhdGUpOyB9XG5cbiAgdmlzaXRFbGVtZW50T3JUZW1wbGF0ZShlbGVtZW50TmFtZTogc3RyaW5nLCBub2RlOiBFbGVtZW50fFRlbXBsYXRlKTogdm9pZCB7XG4gICAgLy8gRmlyc3QsIGRldGVybWluZSB0aGUgSFRNTCBzaGFwZSBvZiB0aGUgbm9kZSBmb3IgdGhlIHB1cnBvc2Ugb2YgZGlyZWN0aXZlIG1hdGNoaW5nLlxuICAgIC8vIERvIHRoaXMgYnkgYnVpbGRpbmcgdXAgYSBgQ3NzU2VsZWN0b3JgIGZvciB0aGUgbm9kZS5cbiAgICBjb25zdCBjc3NTZWxlY3RvciA9IGNyZWF0ZUNzc1NlbGVjdG9yKGVsZW1lbnROYW1lLCBnZXRBdHRyc0ZvckRpcmVjdGl2ZU1hdGNoaW5nKG5vZGUpKTtcblxuICAgIC8vIE5leHQsIHVzZSB0aGUgYFNlbGVjdG9yTWF0Y2hlcmAgdG8gZ2V0IHRoZSBsaXN0IG9mIGRpcmVjdGl2ZXMgb24gdGhlIG5vZGUuXG4gICAgY29uc3QgZGlyZWN0aXZlczogRGlyZWN0aXZlVFtdID0gW107XG4gICAgdGhpcy5tYXRjaGVyLm1hdGNoKGNzc1NlbGVjdG9yLCAoXywgZGlyZWN0aXZlKSA9PiBkaXJlY3RpdmVzLnB1c2goZGlyZWN0aXZlKSk7XG4gICAgaWYgKGRpcmVjdGl2ZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5kaXJlY3RpdmVzLnNldChub2RlLCBkaXJlY3RpdmVzKTtcbiAgICB9XG5cbiAgICAvLyBSZXNvbHZlIGFueSByZWZlcmVuY2VzIHRoYXQgYXJlIGNyZWF0ZWQgb24gdGhpcyBub2RlLlxuICAgIG5vZGUucmVmZXJlbmNlcy5mb3JFYWNoKHJlZiA9PiB7XG4gICAgICBsZXQgZGlyVGFyZ2V0OiBEaXJlY3RpdmVUfG51bGwgPSBudWxsO1xuXG4gICAgICAvLyBJZiB0aGUgcmVmZXJlbmNlIGV4cHJlc3Npb24gaXMgZW1wdHksIHRoZW4gaXQgbWF0Y2hlcyB0aGUgXCJwcmltYXJ5XCIgZGlyZWN0aXZlIG9uIHRoZSBub2RlXG4gICAgICAvLyAoaWYgdGhlcmUgaXMgb25lKS4gT3RoZXJ3aXNlIGl0IG1hdGNoZXMgdGhlIGhvc3Qgbm9kZSBpdHNlbGYgKGVpdGhlciBhbiBlbGVtZW50IG9yXG4gICAgICAvLyA8bmctdGVtcGxhdGU+IG5vZGUpLlxuICAgICAgaWYgKHJlZi52YWx1ZS50cmltKCkgPT09ICcnKSB7XG4gICAgICAgIC8vIFRoaXMgY291bGQgYmUgYSByZWZlcmVuY2UgdG8gYSBjb21wb25lbnQgaWYgdGhlcmUgaXMgb25lLlxuICAgICAgICBkaXJUYXJnZXQgPSBkaXJlY3RpdmVzLmZpbmQoZGlyID0+IGRpci5pc0NvbXBvbmVudCkgfHwgbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRoaXMgc2hvdWxkIGJlIGEgcmVmZXJlbmNlIHRvIGEgZGlyZWN0aXZlIGV4cG9ydGVkIHZpYSBleHBvcnRBcy5cbiAgICAgICAgZGlyVGFyZ2V0ID1cbiAgICAgICAgICAgIGRpcmVjdGl2ZXMuZmluZChcbiAgICAgICAgICAgICAgICBkaXIgPT4gZGlyLmV4cG9ydEFzICE9PSBudWxsICYmIGRpci5leHBvcnRBcy5zb21lKHZhbHVlID0+IHZhbHVlID09PSByZWYudmFsdWUpKSB8fFxuICAgICAgICAgICAgbnVsbDtcbiAgICAgICAgLy8gQ2hlY2sgaWYgYSBtYXRjaGluZyBkaXJlY3RpdmUgd2FzIGZvdW5kLlxuICAgICAgICBpZiAoZGlyVGFyZ2V0ID09PSBudWxsKSB7XG4gICAgICAgICAgLy8gTm8gbWF0Y2hpbmcgZGlyZWN0aXZlIHdhcyBmb3VuZCAtIHRoaXMgcmVmZXJlbmNlIHBvaW50cyB0byBhbiB1bmtub3duIHRhcmdldC4gTGVhdmUgaXRcbiAgICAgICAgICAvLyB1bm1hcHBlZC5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGRpclRhcmdldCAhPT0gbnVsbCkge1xuICAgICAgICAvLyBUaGlzIHJlZmVyZW5jZSBwb2ludHMgdG8gYSBkaXJlY3RpdmUuXG4gICAgICAgIHRoaXMucmVmZXJlbmNlcy5zZXQocmVmLCB7ZGlyZWN0aXZlOiBkaXJUYXJnZXQsIG5vZGV9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRoaXMgcmVmZXJlbmNlIHBvaW50cyB0byB0aGUgbm9kZSBpdHNlbGYuXG4gICAgICAgIHRoaXMucmVmZXJlbmNlcy5zZXQocmVmLCBub2RlKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEFzc29jaWF0ZSBhdHRyaWJ1dGVzL2JpbmRpbmdzIG9uIHRoZSBub2RlIHdpdGggZGlyZWN0aXZlcyBvciB3aXRoIHRoZSBub2RlIGl0c2VsZi5cbiAgICB0eXBlIEJvdW5kTm9kZSA9IEJvdW5kQXR0cmlidXRlIHwgQm91bmRFdmVudCB8IFRleHRBdHRyaWJ1dGU7XG4gICAgY29uc3Qgc2V0QXR0cmlidXRlQmluZGluZyA9XG4gICAgICAgIChhdHRyaWJ1dGU6IEJvdW5kTm9kZSwgaW9UeXBlOiBrZXlvZiBQaWNrPERpcmVjdGl2ZU1ldGEsICdpbnB1dHMnfCdvdXRwdXRzJz4pID0+IHtcbiAgICAgICAgICBjb25zdCBkaXIgPSBkaXJlY3RpdmVzLmZpbmQoZGlyID0+IGRpcltpb1R5cGVdLmhhc093blByb3BlcnR5KGF0dHJpYnV0ZS5uYW1lKSk7XG4gICAgICAgICAgY29uc3QgYmluZGluZyA9IGRpciAhPT0gdW5kZWZpbmVkID8gZGlyIDogbm9kZTtcbiAgICAgICAgICB0aGlzLmJpbmRpbmdzLnNldChhdHRyaWJ1dGUsIGJpbmRpbmcpO1xuICAgICAgICB9O1xuXG4gICAgLy8gTm9kZSBpbnB1dHMgKGJvdW5kIGF0dHJpYnV0ZXMpIGFuZCB0ZXh0IGF0dHJpYnV0ZXMgY2FuIGJlIGJvdW5kIHRvIGFuXG4gICAgLy8gaW5wdXQgb24gYSBkaXJlY3RpdmUuXG4gICAgbm9kZS5pbnB1dHMuZm9yRWFjaChpbnB1dCA9PiBzZXRBdHRyaWJ1dGVCaW5kaW5nKGlucHV0LCAnaW5wdXRzJykpO1xuICAgIG5vZGUuYXR0cmlidXRlcy5mb3JFYWNoKGF0dHIgPT4gc2V0QXR0cmlidXRlQmluZGluZyhhdHRyLCAnaW5wdXRzJykpO1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgVGVtcGxhdGUpIHtcbiAgICAgIG5vZGUudGVtcGxhdGVBdHRycy5mb3JFYWNoKGF0dHIgPT4gc2V0QXR0cmlidXRlQmluZGluZyhhdHRyLCAnaW5wdXRzJykpO1xuICAgIH1cbiAgICAvLyBOb2RlIG91dHB1dHMgKGJvdW5kIGV2ZW50cykgY2FuIGJlIGJvdW5kIHRvIGFuIG91dHB1dCBvbiBhIGRpcmVjdGl2ZS5cbiAgICBub2RlLm91dHB1dHMuZm9yRWFjaChvdXRwdXQgPT4gc2V0QXR0cmlidXRlQmluZGluZyhvdXRwdXQsICdvdXRwdXRzJykpO1xuXG4gICAgLy8gUmVjdXJzZSBpbnRvIHRoZSBub2RlJ3MgY2hpbGRyZW4uXG4gICAgbm9kZS5jaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IGNoaWxkLnZpc2l0KHRoaXMpKTtcbiAgfVxuXG4gIC8vIFVudXNlZCB2aXNpdG9ycy5cbiAgdmlzaXRDb250ZW50KGNvbnRlbnQ6IENvbnRlbnQpOiB2b2lkIHt9XG4gIHZpc2l0VmFyaWFibGUodmFyaWFibGU6IFZhcmlhYmxlKTogdm9pZCB7fVxuICB2aXNpdFJlZmVyZW5jZShyZWZlcmVuY2U6IFJlZmVyZW5jZSk6IHZvaWQge31cbiAgdmlzaXRUZXh0QXR0cmlidXRlKGF0dHJpYnV0ZTogVGV4dEF0dHJpYnV0ZSk6IHZvaWQge31cbiAgdmlzaXRCb3VuZEF0dHJpYnV0ZShhdHRyaWJ1dGU6IEJvdW5kQXR0cmlidXRlKTogdm9pZCB7fVxuICB2aXNpdEJvdW5kRXZlbnQoYXR0cmlidXRlOiBCb3VuZEV2ZW50KTogdm9pZCB7fVxuICB2aXNpdEJvdW5kQXR0cmlidXRlT3JFdmVudChub2RlOiBCb3VuZEF0dHJpYnV0ZXxCb3VuZEV2ZW50KSB7fVxuICB2aXNpdFRleHQodGV4dDogVGV4dCk6IHZvaWQge31cbiAgdmlzaXRCb3VuZFRleHQodGV4dDogQm91bmRUZXh0KTogdm9pZCB7fVxuICB2aXNpdEljdShpY3U6IEljdSk6IHZvaWQge31cbn1cblxuLyoqXG4gKiBQcm9jZXNzZXMgYSB0ZW1wbGF0ZSBhbmQgZXh0cmFjdCBtZXRhZGF0YSBhYm91dCBleHByZXNzaW9ucyBhbmQgc3ltYm9scyB3aXRoaW4uXG4gKlxuICogVGhpcyBpcyBhIGNvbXBhbmlvbiB0byB0aGUgYERpcmVjdGl2ZUJpbmRlcmAgdGhhdCBkb2Vzbid0IHJlcXVpcmUga25vd2xlZGdlIG9mIGRpcmVjdGl2ZXMgbWF0Y2hlZFxuICogd2l0aGluIHRoZSB0ZW1wbGF0ZSBpbiBvcmRlciB0byBvcGVyYXRlLlxuICpcbiAqIEV4cHJlc3Npb25zIGFyZSB2aXNpdGVkIGJ5IHRoZSBzdXBlcmNsYXNzIGBSZWN1cnNpdmVBc3RWaXNpdG9yYCwgd2l0aCBjdXN0b20gbG9naWMgcHJvdmlkZWRcbiAqIGJ5IG92ZXJyaWRkZW4gbWV0aG9kcyBmcm9tIHRoYXQgdmlzaXRvci5cbiAqL1xuY2xhc3MgVGVtcGxhdGVCaW5kZXIgZXh0ZW5kcyBSZWN1cnNpdmVBc3RWaXNpdG9yIGltcGxlbWVudHMgVmlzaXRvciB7XG4gIHByaXZhdGUgdmlzaXROb2RlOiAobm9kZTogTm9kZSkgPT4gdm9pZDtcblxuICBwcml2YXRlIHBpcGVzVXNlZDogc3RyaW5nW10gPSBbXTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSBiaW5kaW5nczogTWFwPEFTVCwgUmVmZXJlbmNlfFZhcmlhYmxlPixcbiAgICAgIHByaXZhdGUgc3ltYm9sczogTWFwPFJlZmVyZW5jZXxWYXJpYWJsZSwgVGVtcGxhdGU+LCBwcml2YXRlIHVzZWRQaXBlczogU2V0PHN0cmluZz4sXG4gICAgICBwcml2YXRlIG5lc3RpbmdMZXZlbDogTWFwPFRlbXBsYXRlLCBudW1iZXI+LCBwcml2YXRlIHNjb3BlOiBTY29wZSxcbiAgICAgIHByaXZhdGUgdGVtcGxhdGU6IFRlbXBsYXRlfG51bGwsIHByaXZhdGUgbGV2ZWw6IG51bWJlcikge1xuICAgIHN1cGVyKCk7XG5cbiAgICAvLyBTYXZlIGEgYml0IG9mIHByb2Nlc3NpbmcgdGltZSBieSBjb25zdHJ1Y3RpbmcgdGhpcyBjbG9zdXJlIGluIGFkdmFuY2UuXG4gICAgdGhpcy52aXNpdE5vZGUgPSAobm9kZTogTm9kZSkgPT4gbm9kZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIC8vIFRoaXMgbWV0aG9kIGlzIGRlZmluZWQgdG8gcmVjb25jaWxlIHRoZSB0eXBlIG9mIFRlbXBsYXRlQmluZGVyIHNpbmNlIGJvdGhcbiAgLy8gUmVjdXJzaXZlQXN0VmlzaXRvciBhbmQgVmlzaXRvciBkZWZpbmUgdGhlIHZpc2l0KCkgbWV0aG9kIGluIHRoZWlyXG4gIC8vIGludGVyZmFjZXMuXG4gIHZpc2l0KG5vZGU6IEFTVHxOb2RlLCBjb250ZXh0PzogYW55KSB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBBU1QpIHtcbiAgICAgIG5vZGUudmlzaXQodGhpcywgY29udGV4dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5vZGUudmlzaXQodGhpcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByb2Nlc3MgYSB0ZW1wbGF0ZSBhbmQgZXh0cmFjdCBtZXRhZGF0YSBhYm91dCBleHByZXNzaW9ucyBhbmQgc3ltYm9scyB3aXRoaW4uXG4gICAqXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZSB0aGUgbm9kZXMgb2YgdGhlIHRlbXBsYXRlIHRvIHByb2Nlc3NcbiAgICogQHBhcmFtIHNjb3BlIHRoZSBgU2NvcGVgIG9mIHRoZSB0ZW1wbGF0ZSBiZWluZyBwcm9jZXNzZWQuXG4gICAqIEByZXR1cm5zIHRocmVlIG1hcHMgd2hpY2ggY29udGFpbiBtZXRhZGF0YSBhYm91dCB0aGUgdGVtcGxhdGU6IGBleHByZXNzaW9uc2Agd2hpY2ggaW50ZXJwcmV0c1xuICAgKiBzcGVjaWFsIGBBU1RgIG5vZGVzIGluIGV4cHJlc3Npb25zIGFzIHBvaW50aW5nIHRvIHJlZmVyZW5jZXMgb3IgdmFyaWFibGVzIGRlY2xhcmVkIHdpdGhpbiB0aGVcbiAgICogdGVtcGxhdGUsIGBzeW1ib2xzYCB3aGljaCBtYXBzIHRob3NlIHZhcmlhYmxlcyBhbmQgcmVmZXJlbmNlcyB0byB0aGUgbmVzdGVkIGBUZW1wbGF0ZWAgd2hpY2hcbiAgICogZGVjbGFyZXMgdGhlbSwgaWYgYW55LCBhbmQgYG5lc3RpbmdMZXZlbGAgd2hpY2ggYXNzb2NpYXRlcyBlYWNoIGBUZW1wbGF0ZWAgd2l0aCBhIGludGVnZXJcbiAgICogbmVzdGluZyBsZXZlbCAoaG93IG1hbnkgbGV2ZWxzIGRlZXAgd2l0aGluIHRoZSB0ZW1wbGF0ZSBzdHJ1Y3R1cmUgdGhlIGBUZW1wbGF0ZWAgaXMpLCBzdGFydGluZ1xuICAgKiBhdCAxLlxuICAgKi9cbiAgc3RhdGljIGFwcGx5KHRlbXBsYXRlOiBOb2RlW10sIHNjb3BlOiBTY29wZSk6IHtcbiAgICBleHByZXNzaW9uczogTWFwPEFTVCwgUmVmZXJlbmNlfFZhcmlhYmxlPixcbiAgICBzeW1ib2xzOiBNYXA8VmFyaWFibGV8UmVmZXJlbmNlLCBUZW1wbGF0ZT4sXG4gICAgbmVzdGluZ0xldmVsOiBNYXA8VGVtcGxhdGUsIG51bWJlcj4sXG4gICAgdXNlZFBpcGVzOiBTZXQ8c3RyaW5nPixcbiAgfSB7XG4gICAgY29uc3QgZXhwcmVzc2lvbnMgPSBuZXcgTWFwPEFTVCwgUmVmZXJlbmNlfFZhcmlhYmxlPigpO1xuICAgIGNvbnN0IHN5bWJvbHMgPSBuZXcgTWFwPFZhcmlhYmxlfFJlZmVyZW5jZSwgVGVtcGxhdGU+KCk7XG4gICAgY29uc3QgbmVzdGluZ0xldmVsID0gbmV3IE1hcDxUZW1wbGF0ZSwgbnVtYmVyPigpO1xuICAgIGNvbnN0IHVzZWRQaXBlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIC8vIFRoZSB0b3AtbGV2ZWwgdGVtcGxhdGUgaGFzIG5lc3RpbmcgbGV2ZWwgMC5cbiAgICBjb25zdCBiaW5kZXIgPSBuZXcgVGVtcGxhdGVCaW5kZXIoXG4gICAgICAgIGV4cHJlc3Npb25zLCBzeW1ib2xzLCB1c2VkUGlwZXMsIG5lc3RpbmdMZXZlbCwgc2NvcGUsXG4gICAgICAgIHRlbXBsYXRlIGluc3RhbmNlb2YgVGVtcGxhdGUgPyB0ZW1wbGF0ZSA6IG51bGwsIDApO1xuICAgIGJpbmRlci5pbmdlc3QodGVtcGxhdGUpO1xuICAgIHJldHVybiB7ZXhwcmVzc2lvbnMsIHN5bWJvbHMsIG5lc3RpbmdMZXZlbCwgdXNlZFBpcGVzfTtcbiAgfVxuXG4gIHByaXZhdGUgaW5nZXN0KHRlbXBsYXRlOiBUZW1wbGF0ZXxOb2RlW10pOiB2b2lkIHtcbiAgICBpZiAodGVtcGxhdGUgaW5zdGFuY2VvZiBUZW1wbGF0ZSkge1xuICAgICAgLy8gRm9yIDxuZy10ZW1wbGF0ZT5zLCBwcm9jZXNzIG9ubHkgdmFyaWFibGVzIGFuZCBjaGlsZCBub2Rlcy4gSW5wdXRzLCBvdXRwdXRzLCB0ZW1wbGF0ZUF0dHJzLFxuICAgICAgLy8gYW5kIHJlZmVyZW5jZXMgd2VyZSBhbGwgcHJvY2Vzc2VkIGluIHRoZSBzY29wZSBvZiB0aGUgY29udGFpbmluZyB0ZW1wbGF0ZS5cbiAgICAgIHRlbXBsYXRlLnZhcmlhYmxlcy5mb3JFYWNoKHRoaXMudmlzaXROb2RlKTtcbiAgICAgIHRlbXBsYXRlLmNoaWxkcmVuLmZvckVhY2godGhpcy52aXNpdE5vZGUpO1xuXG4gICAgICAvLyBTZXQgdGhlIG5lc3RpbmcgbGV2ZWwuXG4gICAgICB0aGlzLm5lc3RpbmdMZXZlbC5zZXQodGVtcGxhdGUsIHRoaXMubGV2ZWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBWaXNpdCBlYWNoIG5vZGUgZnJvbSB0aGUgdG9wLWxldmVsIHRlbXBsYXRlLlxuICAgICAgdGVtcGxhdGUuZm9yRWFjaCh0aGlzLnZpc2l0Tm9kZSk7XG4gICAgfVxuICB9XG5cbiAgdmlzaXRFbGVtZW50KGVsZW1lbnQ6IEVsZW1lbnQpIHtcbiAgICAvLyBWaXNpdCB0aGUgaW5wdXRzLCBvdXRwdXRzLCBhbmQgY2hpbGRyZW4gb2YgdGhlIGVsZW1lbnQuXG4gICAgZWxlbWVudC5pbnB1dHMuZm9yRWFjaCh0aGlzLnZpc2l0Tm9kZSk7XG4gICAgZWxlbWVudC5vdXRwdXRzLmZvckVhY2godGhpcy52aXNpdE5vZGUpO1xuICAgIGVsZW1lbnQuY2hpbGRyZW4uZm9yRWFjaCh0aGlzLnZpc2l0Tm9kZSk7XG4gIH1cblxuICB2aXNpdFRlbXBsYXRlKHRlbXBsYXRlOiBUZW1wbGF0ZSkge1xuICAgIC8vIEZpcnN0LCB2aXNpdCBpbnB1dHMsIG91dHB1dHMgYW5kIHRlbXBsYXRlIGF0dHJpYnV0ZXMgb2YgdGhlIHRlbXBsYXRlIG5vZGUuXG4gICAgdGVtcGxhdGUuaW5wdXRzLmZvckVhY2godGhpcy52aXNpdE5vZGUpO1xuICAgIHRlbXBsYXRlLm91dHB1dHMuZm9yRWFjaCh0aGlzLnZpc2l0Tm9kZSk7XG4gICAgdGVtcGxhdGUudGVtcGxhdGVBdHRycy5mb3JFYWNoKHRoaXMudmlzaXROb2RlKTtcblxuICAgIC8vIFJlZmVyZW5jZXMgYXJlIGFsc28gZXZhbHVhdGVkIGluIHRoZSBvdXRlciBjb250ZXh0LlxuICAgIHRlbXBsYXRlLnJlZmVyZW5jZXMuZm9yRWFjaCh0aGlzLnZpc2l0Tm9kZSk7XG5cbiAgICAvLyBOZXh0LCByZWN1cnNlIGludG8gdGhlIHRlbXBsYXRlIHVzaW5nIGl0cyBzY29wZSwgYW5kIGJ1bXBpbmcgdGhlIG5lc3RpbmcgbGV2ZWwgdXAgYnkgb25lLlxuICAgIGNvbnN0IGNoaWxkU2NvcGUgPSB0aGlzLnNjb3BlLmdldENoaWxkU2NvcGUodGVtcGxhdGUpO1xuICAgIGNvbnN0IGJpbmRlciA9IG5ldyBUZW1wbGF0ZUJpbmRlcihcbiAgICAgICAgdGhpcy5iaW5kaW5ncywgdGhpcy5zeW1ib2xzLCB0aGlzLnVzZWRQaXBlcywgdGhpcy5uZXN0aW5nTGV2ZWwsIGNoaWxkU2NvcGUsIHRlbXBsYXRlLFxuICAgICAgICB0aGlzLmxldmVsICsgMSk7XG4gICAgYmluZGVyLmluZ2VzdCh0ZW1wbGF0ZSk7XG4gIH1cblxuICB2aXNpdFZhcmlhYmxlKHZhcmlhYmxlOiBWYXJpYWJsZSkge1xuICAgIC8vIFJlZ2lzdGVyIHRoZSBgVmFyaWFibGVgIGFzIGEgc3ltYm9sIGluIHRoZSBjdXJyZW50IGBUZW1wbGF0ZWAuXG4gICAgaWYgKHRoaXMudGVtcGxhdGUgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuc3ltYm9scy5zZXQodmFyaWFibGUsIHRoaXMudGVtcGxhdGUpO1xuICAgIH1cbiAgfVxuXG4gIHZpc2l0UmVmZXJlbmNlKHJlZmVyZW5jZTogUmVmZXJlbmNlKSB7XG4gICAgLy8gUmVnaXN0ZXIgdGhlIGBSZWZlcmVuY2VgIGFzIGEgc3ltYm9sIGluIHRoZSBjdXJyZW50IGBUZW1wbGF0ZWAuXG4gICAgaWYgKHRoaXMudGVtcGxhdGUgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuc3ltYm9scy5zZXQocmVmZXJlbmNlLCB0aGlzLnRlbXBsYXRlKTtcbiAgICB9XG4gIH1cblxuICAvLyBVbnVzZWQgdGVtcGxhdGUgdmlzaXRvcnNcblxuICB2aXNpdFRleHQodGV4dDogVGV4dCkge31cbiAgdmlzaXRDb250ZW50KGNvbnRlbnQ6IENvbnRlbnQpIHt9XG4gIHZpc2l0VGV4dEF0dHJpYnV0ZShhdHRyaWJ1dGU6IFRleHRBdHRyaWJ1dGUpIHt9XG4gIHZpc2l0SWN1KGljdTogSWN1KTogdm9pZCB7fVxuXG4gIC8vIFRoZSByZW1haW5pbmcgdmlzaXRvcnMgYXJlIGNvbmNlcm5lZCB3aXRoIHByb2Nlc3NpbmcgQVNUIGV4cHJlc3Npb25zIHdpdGhpbiB0ZW1wbGF0ZSBiaW5kaW5nc1xuXG4gIHZpc2l0Qm91bmRBdHRyaWJ1dGUoYXR0cmlidXRlOiBCb3VuZEF0dHJpYnV0ZSkgeyBhdHRyaWJ1dGUudmFsdWUudmlzaXQodGhpcyk7IH1cblxuICB2aXNpdEJvdW5kRXZlbnQoZXZlbnQ6IEJvdW5kRXZlbnQpIHsgZXZlbnQuaGFuZGxlci52aXNpdCh0aGlzKTsgfVxuXG4gIHZpc2l0Qm91bmRUZXh0KHRleHQ6IEJvdW5kVGV4dCkgeyB0ZXh0LnZhbHVlLnZpc2l0KHRoaXMpOyB9XG4gIHZpc2l0UGlwZShhc3Q6IEJpbmRpbmdQaXBlLCBjb250ZXh0OiBhbnkpOiBhbnkge1xuICAgIHRoaXMudXNlZFBpcGVzLmFkZChhc3QubmFtZSk7XG4gICAgcmV0dXJuIHN1cGVyLnZpc2l0UGlwZShhc3QsIGNvbnRleHQpO1xuICB9XG5cbiAgLy8gVGhlc2UgZml2ZSB0eXBlcyBvZiBBU1QgZXhwcmVzc2lvbnMgY2FuIHJlZmVyIHRvIGV4cHJlc3Npb24gcm9vdHMsIHdoaWNoIGNvdWxkIGJlIHZhcmlhYmxlc1xuICAvLyBvciByZWZlcmVuY2VzIGluIHRoZSBjdXJyZW50IHNjb3BlLlxuXG4gIHZpc2l0UHJvcGVydHlSZWFkKGFzdDogUHJvcGVydHlSZWFkLCBjb250ZXh0OiBhbnkpOiBhbnkge1xuICAgIHRoaXMubWF5YmVNYXAoY29udGV4dCwgYXN0LCBhc3QubmFtZSk7XG4gICAgcmV0dXJuIHN1cGVyLnZpc2l0UHJvcGVydHlSZWFkKGFzdCwgY29udGV4dCk7XG4gIH1cblxuICB2aXNpdFNhZmVQcm9wZXJ0eVJlYWQoYXN0OiBTYWZlUHJvcGVydHlSZWFkLCBjb250ZXh0OiBhbnkpOiBhbnkge1xuICAgIHRoaXMubWF5YmVNYXAoY29udGV4dCwgYXN0LCBhc3QubmFtZSk7XG4gICAgcmV0dXJuIHN1cGVyLnZpc2l0U2FmZVByb3BlcnR5UmVhZChhc3QsIGNvbnRleHQpO1xuICB9XG5cbiAgdmlzaXRQcm9wZXJ0eVdyaXRlKGFzdDogUHJvcGVydHlXcml0ZSwgY29udGV4dDogYW55KTogYW55IHtcbiAgICB0aGlzLm1heWJlTWFwKGNvbnRleHQsIGFzdCwgYXN0Lm5hbWUpO1xuICAgIHJldHVybiBzdXBlci52aXNpdFByb3BlcnR5V3JpdGUoYXN0LCBjb250ZXh0KTtcbiAgfVxuXG4gIHZpc2l0TWV0aG9kQ2FsbChhc3Q6IE1ldGhvZENhbGwsIGNvbnRleHQ6IGFueSk6IGFueSB7XG4gICAgdGhpcy5tYXliZU1hcChjb250ZXh0LCBhc3QsIGFzdC5uYW1lKTtcbiAgICByZXR1cm4gc3VwZXIudmlzaXRNZXRob2RDYWxsKGFzdCwgY29udGV4dCk7XG4gIH1cblxuICB2aXNpdFNhZmVNZXRob2RDYWxsKGFzdDogU2FmZU1ldGhvZENhbGwsIGNvbnRleHQ6IGFueSk6IGFueSB7XG4gICAgdGhpcy5tYXliZU1hcChjb250ZXh0LCBhc3QsIGFzdC5uYW1lKTtcbiAgICByZXR1cm4gc3VwZXIudmlzaXRTYWZlTWV0aG9kQ2FsbChhc3QsIGNvbnRleHQpO1xuICB9XG5cbiAgcHJpdmF0ZSBtYXliZU1hcChcbiAgICAgIHNjb3BlOiBTY29wZSwgYXN0OiBQcm9wZXJ0eVJlYWR8U2FmZVByb3BlcnR5UmVhZHxQcm9wZXJ0eVdyaXRlfE1ldGhvZENhbGx8U2FmZU1ldGhvZENhbGwsXG4gICAgICBuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBJZiB0aGUgcmVjZWl2ZXIgb2YgdGhlIGV4cHJlc3Npb24gaXNuJ3QgdGhlIGBJbXBsaWNpdFJlY2VpdmVyYCwgdGhpcyBpc24ndCB0aGUgcm9vdCBvZiBhblxuICAgIC8vIGBBU1RgIGV4cHJlc3Npb24gdGhhdCBtYXBzIHRvIGEgYFZhcmlhYmxlYCBvciBgUmVmZXJlbmNlYC5cbiAgICBpZiAoIShhc3QucmVjZWl2ZXIgaW5zdGFuY2VvZiBJbXBsaWNpdFJlY2VpdmVyKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHdoZXRoZXIgdGhlIG5hbWUgZXhpc3RzIGluIHRoZSBjdXJyZW50IHNjb3BlLiBJZiBzbywgbWFwIGl0LiBPdGhlcndpc2UsIHRoZSBuYW1lIGlzXG4gICAgLy8gcHJvYmFibHkgYSBwcm9wZXJ0eSBvbiB0aGUgdG9wLWxldmVsIGNvbXBvbmVudCBjb250ZXh0LlxuICAgIGxldCB0YXJnZXQgPSB0aGlzLnNjb3BlLmxvb2t1cChuYW1lKTtcbiAgICBpZiAodGFyZ2V0ICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmJpbmRpbmdzLnNldChhc3QsIHRhcmdldCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogTWV0YWRhdGEgY29udGFpbmVyIGZvciBhIGBUYXJnZXRgIHRoYXQgYWxsb3dzIHF1ZXJpZXMgZm9yIHNwZWNpZmljIGJpdHMgb2YgbWV0YWRhdGEuXG4gKlxuICogU2VlIGBCb3VuZFRhcmdldGAgZm9yIGRvY3VtZW50YXRpb24gb24gdGhlIGluZGl2aWR1YWwgbWV0aG9kcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFIzQm91bmRUYXJnZXQ8RGlyZWN0aXZlVCBleHRlbmRzIERpcmVjdGl2ZU1ldGE+IGltcGxlbWVudHMgQm91bmRUYXJnZXQ8RGlyZWN0aXZlVD4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIHJlYWRvbmx5IHRhcmdldDogVGFyZ2V0LCBwcml2YXRlIGRpcmVjdGl2ZXM6IE1hcDxFbGVtZW50fFRlbXBsYXRlLCBEaXJlY3RpdmVUW10+LFxuICAgICAgcHJpdmF0ZSBiaW5kaW5nczogTWFwPEJvdW5kQXR0cmlidXRlfEJvdW5kRXZlbnR8VGV4dEF0dHJpYnV0ZSwgRGlyZWN0aXZlVHxFbGVtZW50fFRlbXBsYXRlPixcbiAgICAgIHByaXZhdGUgcmVmZXJlbmNlczpcbiAgICAgICAgICBNYXA8Qm91bmRBdHRyaWJ1dGV8Qm91bmRFdmVudHxSZWZlcmVuY2V8VGV4dEF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAge2RpcmVjdGl2ZTogRGlyZWN0aXZlVCwgbm9kZTogRWxlbWVudHxUZW1wbGF0ZX18RWxlbWVudHxUZW1wbGF0ZT4sXG4gICAgICBwcml2YXRlIGV4cHJUYXJnZXRzOiBNYXA8QVNULCBSZWZlcmVuY2V8VmFyaWFibGU+LFxuICAgICAgcHJpdmF0ZSBzeW1ib2xzOiBNYXA8UmVmZXJlbmNlfFZhcmlhYmxlLCBUZW1wbGF0ZT4sXG4gICAgICBwcml2YXRlIG5lc3RpbmdMZXZlbDogTWFwPFRlbXBsYXRlLCBudW1iZXI+LCBwcml2YXRlIHVzZWRQaXBlczogU2V0PHN0cmluZz4pIHt9XG5cbiAgZ2V0RGlyZWN0aXZlc09mTm9kZShub2RlOiBFbGVtZW50fFRlbXBsYXRlKTogRGlyZWN0aXZlVFtdfG51bGwge1xuICAgIHJldHVybiB0aGlzLmRpcmVjdGl2ZXMuZ2V0KG5vZGUpIHx8IG51bGw7XG4gIH1cblxuICBnZXRSZWZlcmVuY2VUYXJnZXQocmVmOiBSZWZlcmVuY2UpOiB7ZGlyZWN0aXZlOiBEaXJlY3RpdmVULCBub2RlOiBFbGVtZW50fFRlbXBsYXRlfXxFbGVtZW50XG4gICAgICB8VGVtcGxhdGV8bnVsbCB7XG4gICAgcmV0dXJuIHRoaXMucmVmZXJlbmNlcy5nZXQocmVmKSB8fCBudWxsO1xuICB9XG5cbiAgZ2V0Q29uc3VtZXJPZkJpbmRpbmcoYmluZGluZzogQm91bmRBdHRyaWJ1dGV8Qm91bmRFdmVudHxUZXh0QXR0cmlidXRlKTogRGlyZWN0aXZlVHxFbGVtZW50XG4gICAgICB8VGVtcGxhdGV8bnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYmluZGluZ3MuZ2V0KGJpbmRpbmcpIHx8IG51bGw7XG4gIH1cblxuICBnZXRFeHByZXNzaW9uVGFyZ2V0KGV4cHI6IEFTVCk6IFJlZmVyZW5jZXxWYXJpYWJsZXxudWxsIHtcbiAgICByZXR1cm4gdGhpcy5leHByVGFyZ2V0cy5nZXQoZXhwcikgfHwgbnVsbDtcbiAgfVxuXG4gIGdldFRlbXBsYXRlT2ZTeW1ib2woc3ltYm9sOiBSZWZlcmVuY2V8VmFyaWFibGUpOiBUZW1wbGF0ZXxudWxsIHtcbiAgICByZXR1cm4gdGhpcy5zeW1ib2xzLmdldChzeW1ib2wpIHx8IG51bGw7XG4gIH1cblxuICBnZXROZXN0aW5nTGV2ZWwodGVtcGxhdGU6IFRlbXBsYXRlKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMubmVzdGluZ0xldmVsLmdldCh0ZW1wbGF0ZSkgfHwgMDsgfVxuXG4gIGdldFVzZWREaXJlY3RpdmVzKCk6IERpcmVjdGl2ZVRbXSB7XG4gICAgY29uc3Qgc2V0ID0gbmV3IFNldDxEaXJlY3RpdmVUPigpO1xuICAgIHRoaXMuZGlyZWN0aXZlcy5mb3JFYWNoKGRpcnMgPT4gZGlycy5mb3JFYWNoKGRpciA9PiBzZXQuYWRkKGRpcikpKTtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShzZXQudmFsdWVzKCkpO1xuICB9XG5cbiAgZ2V0VXNlZFBpcGVzKCk6IHN0cmluZ1tdIHsgcmV0dXJuIEFycmF5LmZyb20odGhpcy51c2VkUGlwZXMpOyB9XG59XG4iXX0=