constructs
Version:
A programming model for software-defined state
532 lines • 56.9 kB
JavaScript
"use strict";
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RootConstruct = exports.ConstructOrder = exports.Construct = exports.Node = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const dependency_1 = require("./dependency");
const stack_trace_1 = require("./private/stack-trace");
const uniqueid_1 = require("./private/uniqueid");
const CONSTRUCT_SYM = Symbol.for('constructs.Construct');
/**
* Represents the construct node in the scope tree.
*/
class Node {
/**
* Returns the node associated with a construct.
* @param construct the construct
*
* @deprecated use `construct.node` instead
*/
static of(construct) {
return construct.node;
}
constructor(host, scope, id) {
this.host = host;
this._locked = false; // if this is "true", addChild will fail
id = id ?? ''; // if undefined, convert to empty string
this.id = sanitizeId(id);
this.scope = scope;
if (scope && !this.id) {
throw new Error('Only root constructs may have an empty ID');
}
// add to parent scope
scope?.node.addChild(host, this.id);
}
/**
* The full, absolute path of this construct in the tree.
*
* Components are separated by '/'.
*/
get path() {
const components = [];
for (const scope of this.scopes) {
if (scope.node.id) {
components.push(scope.node.id);
}
}
return components.join(Node.PATH_SEP);
}
/**
* Returns an opaque tree-unique address for this construct.
*
* Addresses are 42 characters hexadecimal strings. They begin with "c8"
* followed by 40 lowercase hexadecimal characters (0-9a-f).
*
* Addresses are calculated using a SHA-1 of the components of the construct
* path.
*
* To enable refactoring of construct trees, constructs with the ID `Default`
* will be excluded from the calculation. In those cases constructs in the
* same tree may have the same address.
*
* @example c83a2846e506bcc5f10682b564084bca2d275709ee
*/
get addr() {
if (!this._addr) {
this._addr = (0, uniqueid_1.addressOf)(this.scopes.map(c => c.node.id));
}
return this._addr;
}
/**
* Return a direct child by id, or undefined
*
* @param id Identifier of direct child
* @returns the child if found, or undefined
*/
tryFindChild(id) {
return this._children?.[sanitizeId(id)];
}
/**
* Return a direct child by id
*
* Throws an error if the child is not found.
*
* @param id Identifier of direct child
* @returns Child with the given id.
*/
findChild(id) {
const ret = this.tryFindChild(id);
if (!ret) {
throw new Error(`No child with id: '${id}'`);
}
return ret;
}
/**
* Returns the child construct that has the id `Default` or `Resource`.
* This is usually the construct that provides the bulk of the underlying functionality.
* Useful for modifications of the underlying construct that are not available at the higher levels.
*
* @throws if there is more than one child
* @returns a construct or undefined if there is no default child
*/
get defaultChild() {
if (this._defaultChild !== undefined) {
return this._defaultChild;
}
const resourceChild = this.tryFindChild('Resource');
const defaultChild = this.tryFindChild('Default');
if (resourceChild && defaultChild) {
throw new Error(`Cannot determine default child for ${this.path}. There is both a child with id "Resource" and id "Default"`);
}
return defaultChild || resourceChild;
}
/**
* Override the defaultChild property.
*
* This should only be used in the cases where the correct
* default child is not named 'Resource' or 'Default' as it
* should be.
*
* If you set this to undefined, the default behavior of finding
* the child named 'Resource' or 'Default' will be used.
*/
set defaultChild(value) {
this._defaultChild = value;
}
/**
* All direct children of this construct.
*/
get children() {
return Object.values(this._children ?? {});
}
/**
* Return this construct and all of its children in the given order
*/
findAll(order = ConstructOrder.PREORDER) {
const ret = new Array();
visit(this.host);
return ret;
function visit(c) {
if (order === ConstructOrder.PREORDER) {
ret.push(c);
}
for (const child of c.node.children) {
visit(child);
}
if (order === ConstructOrder.POSTORDER) {
ret.push(c);
}
}
}
/**
* This can be used to set contextual values.
* Context must be set before any children are added, since children may consult context info during construction.
* If the key already exists, it will be overridden.
* @param key The context key
* @param value The context value
*/
setContext(key, value) {
if (this.children.length > 0) {
const names = this.children.map(c => c.node.id);
throw new Error('Cannot set context after children have been added: ' + names.join(','));
}
if (!this._context) {
this._context = {};
}
this._context[key] = value;
}
/**
* Retrieves a value from tree context if present. Otherwise, would throw an error.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param key The context key
* @returns The context value or throws error if there is no context value for this key
*/
getContext(key) {
const value = this._context?.[key];
if (value !== undefined) {
return value;
}
if (value === undefined && !this.scope?.node) {
throw new Error(`No context value present for ${key} key`);
}
return this.scope && this.scope.node.getContext(key);
}
/**
* Retrieves the all context of a node from tree context.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param defaults Any keys to override the retrieved context
* @returns The context object or an empty object if there is discovered context
*/
getAllContext(defaults) {
return this.scopes.reverse()
.reduce((a, s) => ({ ...(s.node._context), ...a }), { ...defaults });
}
/**
* Retrieves a value from tree context.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param key The context key
* @returns The context value or `undefined` if there is no context value for this key.
*/
tryGetContext(key) {
const value = this._context?.[key];
if (value !== undefined) {
return value;
}
return this.scope && this.scope.node.tryGetContext(key);
}
/**
* An immutable array of metadata objects associated with this construct.
* This can be used, for example, to implement support for deprecation notices, source mapping, etc.
*/
get metadata() {
return [...this._metadata ?? []];
}
/**
* Adds a metadata entry to this construct.
* Entries are arbitrary values and will also include a stack trace to allow tracing back to
* the code location for when the entry was added. It can be used, for example, to include source
* mapping in CloudFormation templates to improve diagnostics.
* Note that construct metadata is not the same as CloudFormation resource metadata and is never written to the CloudFormation template.
* The metadata entries are written to the Cloud Assembly Manifest if the `treeMetadata` property is specified in the props of the App that contains this Construct.
*
* @param type a string denoting the type of metadata
* @param data the value of the metadata (can be a Token). If null/undefined, metadata will not be added.
* @param options options
*/
addMetadata(type, data, options = {}) {
if (data == null) {
return;
}
const node = this;
function getTrace() {
if (options.stackTraceOverride && options.stackTraceOverride.length > 0) {
return options.stackTraceOverride;
}
const shouldTrace = options.stackTrace ?? false;
return shouldTrace ? (0, stack_trace_1.captureStackTrace)(options.traceFromFunction ?? node.addMetadata) : undefined;
}
if (!this._metadata) {
this._metadata = [];
}
this._metadata.push({ type, data, trace: getTrace() });
}
/**
* All parent scopes of this construct.
*
* @returns a list of parent scopes. The last element in the list will always
* be the current construct and the first element will be the root of the
* tree.
*/
get scopes() {
const ret = new Array();
let curr = this.host;
while (curr) {
ret.unshift(curr);
curr = curr.node.scope;
}
return ret;
}
/**
* Returns the root of the construct tree.
* @returns The root of the construct tree.
*/
get root() {
return this.scopes[0];
}
/**
* Returns true if this construct or the scopes in which it is defined are
* locked.
*/
get locked() {
if (this._locked) {
return true;
}
if (this.scope && this.scope.node.locked) {
return true;
}
return false;
}
/**
* Add an ordering dependency on another construct.
*
* An `IDependable`
*/
addDependency(...deps) {
if (!this._dependencies) {
this._dependencies = new Set();
}
for (const d of deps) {
this._dependencies.add(d);
}
}
/**
* Return all dependencies registered on this node (non-recursive).
*/
get dependencies() {
const result = new Array();
if (this._dependencies) {
for (const dep of this._dependencies) {
for (const root of dependency_1.Dependable.of(dep).dependencyRoots) {
result.push(root);
}
}
}
return result;
}
/**
* Remove the child with the given name, if present.
*
* @returns Whether a child with the given name was deleted.
*/
tryRemoveChild(childName) {
if (!this._children || !(childName in this._children)) {
return false;
}
delete this._children[childName];
return true;
}
/**
* Adds a validation to this construct.
*
* When `node.validate()` is called, the `validate()` method will be called on
* all validations and all errors will be returned.
*
* @param validation The validation object
*/
addValidation(validation) {
if (!this._validations) {
this._validations = [];
}
this._validations.push(validation);
}
/**
* Validates this construct.
*
* Invokes the `validate()` method on all validations added through
* `addValidation()`.
*
* @returns an array of validation error messages associated with this
* construct.
*/
validate() {
return (this._validations ?? []).flatMap(v => v.validate());
}
/**
* Locks this construct from allowing more children to be added. After this
* call, no more children can be added to this construct or to any children.
*/
lock() {
this._locked = true;
}
/**
* Applies one or more mixins to this construct.
*
* Mixins are applied in order. The list of constructs is captured at the
* start of the call, so constructs added by a mixin will not be visited.
* Use multiple `with()` calls if subsequent mixins should apply to added
* constructs.
*
* @param mixins The mixins to apply
* @returns This construct for chaining
*/
with(...mixins) {
const allConstructs = this.findAll();
for (const mixin of mixins) {
for (const construct of allConstructs) {
if (mixin.supports(construct)) {
mixin.applyTo(construct);
}
}
}
return this.host;
}
;
/**
* Adds a child construct to this node.
*
* @param child The child construct
* @param childName The type name of the child construct.
* @returns The resolved path part name of the child
*/
addChild(child, childName) {
if (this.locked) {
// special error if root is locked
if (!this.path) {
throw new Error('Cannot add children during synthesis');
}
throw new Error(`Cannot add children to "${this.path}" during synthesis`);
}
if (!this._children) {
this._children = {};
}
if (this._children[childName]) {
const name = this.id ?? '';
const typeName = this.host.constructor.name;
throw new Error(`There is already a Construct with name '${childName}' in ${typeName}${name.length > 0 ? ' [' + name + ']' : ''}`);
}
this._children[childName] = child;
}
}
exports.Node = Node;
_a = JSII_RTTI_SYMBOL_1;
Node[_a] = { fqn: "constructs.Node", version: "10.6.0" };
/**
* Separator used to delimit construct path components.
*/
Node.PATH_SEP = '/';
/**
* Represents the building block of the construct graph.
*
* All constructs besides the root construct must be created within the scope of
* another construct.
*/
class Construct {
/**
* Checks if `x` is a construct.
*
* Use this method instead of `instanceof` to properly detect `Construct`
* instances, even when the construct library is symlinked.
*
* Explanation: in JavaScript, multiple copies of the `constructs` library on
* disk are seen as independent, completely different libraries. As a
* consequence, the class `Construct` in each copy of the `constructs` library
* is seen as a different class, and an instance of one class will not test as
* `instanceof` the other class. `npm install` will not create installations
* like this, but users may manually symlink construct libraries together or
* use a monorepo tool: in those cases, multiple copies of the `constructs`
* library can be accidentally installed, and `instanceof` will behave
* unpredictably. It is safest to avoid using `instanceof`, and using
* this type-testing method instead.
*
* @returns true if `x` is an object created from a class which extends `Construct`.
* @param x Any object
*/
static isConstruct(x) {
return x && typeof x === 'object' && x[CONSTRUCT_SYM];
}
/**
* Creates a new construct node.
*
* @param scope The scope in which to define this construct
* @param id The scoped construct ID. Must be unique amongst siblings. If
* the ID includes a path separator (`/`), then it will be replaced by double
* dash `--`.
*/
constructor(scope, id) {
this.node = new Node(this, scope, id);
// implement IDependable privately
dependency_1.Dependable.implement(this, {
dependencyRoots: [this],
});
}
/**
* Applies one or more mixins to this construct.
*
* Mixins are applied in order. The list of constructs is captured at the
* start of the call, so constructs added by a mixin will not be visited.
* Use multiple `with()` calls if subsequent mixins should apply to added
* constructs.
*
* @param mixins The mixins to apply
* @returns This construct for chaining
*/
with(...mixins) {
return this.node.with(...mixins);
}
;
/**
* Returns a string representation of this construct.
*/
toString() {
return this.node.path || '<root>';
}
}
exports.Construct = Construct;
_b = JSII_RTTI_SYMBOL_1;
Construct[_b] = { fqn: "constructs.Construct", version: "10.6.0" };
/**
* In what order to return constructs
*/
var ConstructOrder;
(function (ConstructOrder) {
/**
* Depth-first, pre-order
*/
ConstructOrder[ConstructOrder["PREORDER"] = 0] = "PREORDER";
/**
* Depth-first, post-order (leaf nodes first)
*/
ConstructOrder[ConstructOrder["POSTORDER"] = 1] = "POSTORDER";
})(ConstructOrder || (exports.ConstructOrder = ConstructOrder = {}));
const PATH_SEP_REGEX = new RegExp(`${Node.PATH_SEP}`, 'g');
/**
* Return a sanitized version of an arbitrary string, so it can be used as an ID
*/
function sanitizeId(id) {
// Escape path seps as double dashes
return id.replace(PATH_SEP_REGEX, '--');
}
// Mark all instances of 'Construct'
Object.defineProperty(Construct.prototype, CONSTRUCT_SYM, {
value: true,
enumerable: false,
writable: false,
});
/**
* Creates a new root construct node.
*
* The root construct represents the top of the construct tree and is not contained within a parent scope itself.
* For root constructs, the id is optional.
*/
class RootConstruct extends Construct {
/**
* Creates a new root construct node.
*
* @param id The scoped construct ID. Must be unique amongst siblings. If
* the ID includes a path separator (`/`), then it will be replaced by double
* dash `--`.
*/
constructor(id) {
super(undefined, id ?? '');
}
}
exports.RootConstruct = RootConstruct;
_c = JSII_RTTI_SYMBOL_1;
RootConstruct[_c] = { fqn: "constructs.RootConstruct", version: "10.6.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RydWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbnN0cnVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUNBLDZDQUEwQztBQUcxQyx1REFBMEQ7QUFDMUQsaURBQStDO0FBRS9DLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQztBQXVCekQ7O0dBRUc7QUFDSCxNQUFhLElBQUk7SUFNZjs7Ozs7T0FLRztJQUNJLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBcUI7UUFDcEMsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDO0lBQ3hCLENBQUM7SUF5QkQsWUFBb0MsSUFBZSxFQUFFLEtBQWlCLEVBQUUsRUFBVTtRQUE5QyxTQUFJLEdBQUosSUFBSSxDQUFXO1FBVDNDLFlBQU8sR0FBRyxLQUFLLENBQUMsQ0FBQyx3Q0FBd0M7UUFVL0QsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyx3Q0FBd0M7UUFFdkQsSUFBSSxDQUFDLEVBQUUsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFFbkIsSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQVcsSUFBSTtRQUNiLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUN0QixLQUFLLE1BQU0sS0FBSyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMs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OztBQVZILHNDQVdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBJRGVwZW5kYWJsZSB9IGZyb20gJy4vZGVwZW5kZW5jeSc7XG5pbXBvcnQgeyBEZXBlbmRhYmxlIH0gZnJvbSAnLi9kZXBlbmRlbmN5JztcbmltcG9ydCB0eXBlIHsgTWV0YWRhdGFFbnRyeSB9IGZyb20gJy4vbWV0YWRhdGEnO1xuaW1wb3J0IHR5cGUgeyBJTWl4aW4gfSBmcm9tICcuL21peGluJztcbmltcG9ydCB7IGNhcHR1cmVTdGFja1RyYWNlIH0gZnJvbSAnLi9wcml2YXRlL3N0YWNrLXRyYWNlJztcbmltcG9ydCB7IGFkZHJlc3NPZiB9IGZyb20gJy4vcHJpdmF0ZS91bmlxdWVpZCc7XG5cbmNvbnN0IENPTlNUUlVDVF9TWU0gPSBTeW1ib2wuZm9yKCdjb25zdHJ1Y3RzLkNvbnN0cnVjdCcpO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBjb25zdHJ1Y3QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSUNvbnN0cnVjdCBleHRlbmRzIElEZXBlbmRhYmxlIHtcbiAgLyoqXG4gICAqIFRoZSB0cmVlIG5vZGUuXG4gICAqL1xuICByZWFkb25seSBub2RlOiBOb2RlO1xuXG4gIC8qKlxuICAgKiBBcHBsaWVzIG9uZSBvciBtb3JlIG1peGlucyB0byB0aGlzIGNvbnN0cnVjdC5cbiAgICpcbiAgICogTWl4aW5zIGFyZSBhcHBsaWVkIGluIG9yZGVyLiBUaGUgbGlzdCBvZiBjb25zdHJ1Y3RzIGlzIGNhcHR1cmVkIGF0IHRoZVxuICAgKiBzdGFydCBvZiB0aGUgY2FsbCwgc28gY29uc3RydWN0cyBhZGRlZCBieSBhIG1peGluIHdpbGwgbm90IGJlIHZpc2l0ZWQuXG4gICAqXG4gICAqIEBwYXJhbSBtaXhpbnMgVGhlIG1peGlucyB0byBhcHBseVxuICAgKiBAcmV0dXJucyBUaGlzIGNvbnN0cnVjdCBmb3IgY2hhaW5pbmdcbiAgICovXG4gIHdpdGgoLi4ubWl4aW5zOiBJTWl4aW5bXSk6IElDb25zdHJ1Y3Q7XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgY29uc3RydWN0IG5vZGUgaW4gdGhlIHNjb3BlIHRyZWUuXG4gKi9cbmV4cG9ydCBjbGFzcyBOb2RlIHtcbiAgLyoqXG4gICAqIFNlcGFyYXRvciB1c2VkIHRvIGRlbGltaXQgY29uc3RydWN0IHBhdGggY29tcG9uZW50cy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUEFUSF9TRVAgPSAnLyc7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG5vZGUgYXNzb2NpYXRlZCB3aXRoIGEgY29uc3RydWN0LlxuICAgKiBAcGFyYW0gY29uc3RydWN0IHRoZSBjb25zdHJ1Y3RcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBjb25zdHJ1Y3Qubm9kZWAgaW5zdGVhZFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBvZihjb25zdHJ1Y3Q6IElDb25zdHJ1Y3QpOiBOb2RlIHtcbiAgICByZXR1cm4gY29uc3RydWN0Lm5vZGU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2NvcGUgaW4gd2hpY2ggdGhpcyBjb25zdHJ1Y3QgaXMgZGVmaW5lZC5cbiAgICpcbiAgICogVGhlIHZhbHVlIGlzIGB1bmRlZmluZWRgIGF0IHRoZSByb290IG9mIHRoZSBjb25zdHJ1Y3Qgc2NvcGUgdHJlZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzY29wZT86IElDb25zdHJ1Y3Q7XG5cbiAgLyoqXG4gICAqIFRoZSBpZCBvZiB0aGlzIGNvbnN0cnVjdCB3aXRoaW4gdGhlIGN1cnJlbnQgc2NvcGUuXG4gICAqXG4gICAqIFRoaXMgaXMgYSBzY29wZS11bmlxdWUgaWQuIFRvIG9idGFpbiBhbiBhcHAtdW5pcXVlIGlkIGZvciB0aGlzIGNvbnN0cnVjdCwgdXNlIGBhZGRyYC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBpZDogc3RyaW5nO1xuXG4gIHByaXZhdGUgX2xvY2tlZCA9IGZhbHNlOyAvLyBpZiB0aGlzIGlzIFwidHJ1ZVwiLCBhZGRDaGlsZCB3aWxsIGZhaWxcbiAgcHJpdmF0ZSBfY2hpbGRyZW46IHsgW2lkOiBzdHJpbmddOiBJQ29uc3RydWN0IH0gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX2NvbnRleHQ6IHsgW2tleTogc3RyaW5nXTogYW55IH0gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX21ldGFkYXRhOiBBcnJheTxNZXRhZGF0YUVudHJ5PiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfZGVwZW5kZW5jaWVzOiBTZXQ8SURlcGVuZGFibGU+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9kZWZhdWx0Q2hpbGQ6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX3ZhbGlkYXRpb25zOiBBcnJheTxJVmFsaWRhdGlvbj4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX2FkZHI/OiBzdHJpbmc7IC8vIGNhY2hlXG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgaG9zdDogQ29uc3RydWN0LCBzY29wZTogSUNvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIGlkID0gaWQgPz8gJyc7IC8vIGlmIHVuZGVmaW5lZCwgY29udmVydCB0byBlbXB0eSBzdHJpbmdcblxuICAgIHRoaXMuaWQgPSBzYW5pdGl6ZUlkKGlkKTtcbiAgICB0aGlzLnNjb3BlID0gc2NvcGU7XG5cbiAgICBpZiAoc2NvcGUgJiYgIXRoaXMuaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSByb290IGNvbnN0cnVjdHMgbWF5IGhhdmUgYW4gZW1wdHkgSUQnKTtcbiAgICB9XG5cbiAgICAvLyBhZGQgdG8gcGFyZW50IHNjb3BlXG4gICAgc2NvcGU/Lm5vZGUuYWRkQ2hpbGQoaG9zdCwgdGhpcy5pZCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGZ1bGwsIGFic29sdXRlIHBhdGggb2YgdGhpcyBjb25zdHJ1Y3QgaW4gdGhlIHRyZWUuXG4gICAqXG4gICAqIENvbXBvbmVudHMgYXJlIHNlcGFyYXRlZCBieSAnLycuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHBhdGgoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb21wb25lbnRzID0gW107XG4gICAgZm9yIChjb25zdCBzY29wZSBvZiB0aGlzLnNjb3Blcykge1xuICAgICAgaWYgKHNjb3BlLm5vZGUuaWQpIHtcbiAgICAgICAgY29tcG9uZW50cy5wdXNoKHNjb3BlLm5vZGUuaWQpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY29tcG9uZW50cy5qb2luKE5vZGUuUEFUSF9TRVApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gb3BhcXVlIHRyZWUtdW5pcXVlIGFkZHJlc3MgZm9yIHRoaXMgY29uc3RydWN0LlxuICAgKlxuICAgKiBBZGRyZXNzZXMgYXJlIDQyIGNoYXJhY3RlcnMgaGV4YWRlY2ltYWwgc3RyaW5ncy4gVGhleSBiZWdpbiB3aXRoIFwiYzhcIlxuICAgKiBmb2xsb3dlZCBieSA0MCBsb3dlcmNhc2UgaGV4YWRlY2ltYWwgY2hhcmFjdGVycyAoMC05YS1mKS5cbiAgICpcbiAgICogQWRkcmVzc2VzIGFyZSBjYWxjdWxhdGVkIHVzaW5nIGEgU0hBLTEgb2YgdGhlIGNvbXBvbmVudHMgb2YgdGhlIGNvbnN0cnVjdFxuICAgKiBwYXRoLlxuICAgKlxuICAgKiBUbyBlbmFibGUgcmVmYWN0b3Jpbmcgb2YgY29uc3RydWN0IHRyZWVzLCBjb25zdHJ1Y3RzIHdpdGggdGhlIElEIGBEZWZhdWx0YFxuICAgKiB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gdGhlIGNhbGN1bGF0aW9uLiBJbiB0aG9zZSBjYXNlcyBjb25zdHJ1Y3RzIGluIHRoZVxuICAgKiBzYW1lIHRyZWUgbWF5IGhhdmUgdGhlIHNhbWUgYWRkcmVzcy5cbiAgICpcbiAgICogQGV4YW1wbGUgYzgzYTI4NDZlNTA2YmNjNWYxMDY4MmI1NjQwODRiY2EyZDI3NTcwOWVlXG4gICAqL1xuICBwdWJsaWMgZ2V0IGFkZHIoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuX2FkZHIpIHtcbiAgICAgIHRoaXMuX2FkZHIgPSBhZGRyZXNzT2YodGhpcy5zY29wZXMubWFwKGMgPT4gYy5ub2RlLmlkKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2FkZHI7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgZGlyZWN0IGNoaWxkIGJ5IGlkLCBvciB1bmRlZmluZWRcbiAgICpcbiAgICogQHBhcmFtIGlkIElkZW50aWZpZXIgb2YgZGlyZWN0IGNoaWxkXG4gICAqIEByZXR1cm5zIHRoZSBjaGlsZCBpZiBmb3VuZCwgb3IgdW5kZWZpbmVkXG4gICAqL1xuICBwdWJsaWMgdHJ5RmluZENoaWxkKGlkOiBzdHJpbmcpOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW4/LltzYW5pdGl6ZUlkKGlkKV07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgZGlyZWN0IGNoaWxkIGJ5IGlkXG4gICAqXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiB0aGUgY2hpbGQgaXMgbm90IGZvdW5kLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgSWRlbnRpZmllciBvZiBkaXJlY3QgY2hpbGRcbiAgICogQHJldHVybnMgQ2hpbGQgd2l0aCB0aGUgZ2l2ZW4gaWQuXG4gICAqL1xuICBwdWJsaWMgZmluZENoaWxkKGlkOiBzdHJpbmcpOiBJQ29uc3RydWN0IHtcbiAgICBjb25zdCByZXQgPSB0aGlzLnRyeUZpbmRDaGlsZChpZCk7XG4gICAgaWYgKCFyZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gY2hpbGQgd2l0aCBpZDogJyR7aWR9J2ApO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNoaWxkIGNvbnN0cnVjdCB0aGF0IGhhcyB0aGUgaWQgYERlZmF1bHRgIG9yIGBSZXNvdXJjZWAuXG4gICAqIFRoaXMgaXMgdXN1YWxseSB0aGUgY29uc3RydWN0IHRoYXQgcHJvdmlkZXMgdGhlIGJ1bGsgb2YgdGhlIHVuZGVybHlpbmcgZnVuY3Rpb25hbGl0eS5cbiAgICogVXNlZnVsIGZvciBtb2RpZmljYXRpb25zIG9mIHRoZSB1bmRlcmx5aW5nIGNvbnN0cnVjdCB0aGF0IGFyZSBub3QgYXZhaWxhYmxlIGF0IHRoZSBoaWdoZXIgbGV2ZWxzLlxuICAgKlxuICAgKiBAdGhyb3dzIGlmIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgY2hpbGRcbiAgICogQHJldHVybnMgYSBjb25zdHJ1Y3Qgb3IgdW5kZWZpbmVkIGlmIHRoZXJlIGlzIG5vIGRlZmF1bHQgY2hpbGRcbiAgICovXG4gIHB1YmxpYyBnZXQgZGVmYXVsdENoaWxkKCk6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQge1xuICAgIGlmICh0aGlzLl9kZWZhdWx0Q2hpbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2RlZmF1bHRDaGlsZDtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZUNoaWxkID0gdGhpcy50cnlGaW5kQ2hpbGQoJ1Jlc291cmNlJyk7XG4gICAgY29uc3QgZGVmYXVsdENoaWxkID0gdGhpcy50cnlGaW5kQ2hpbGQoJ0RlZmF1bHQnKTtcbiAgICBpZiAocmVzb3VyY2VDaGlsZCAmJiBkZWZhdWx0Q2hpbGQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGRldGVybWluZSBkZWZhdWx0IGNoaWxkIGZvciAke3RoaXMucGF0aH0uIFRoZXJlIGlzIGJvdGggYSBjaGlsZCB3aXRoIGlkIFwiUmVzb3VyY2VcIiBhbmQgaWQgXCJEZWZhdWx0XCJgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVmYXVsdENoaWxkIHx8IHJlc291cmNlQ2hpbGQ7XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgdGhlIGRlZmF1bHRDaGlsZCBwcm9wZXJ0eS5cbiAgICpcbiAgICogVGhpcyBzaG91bGQgb25seSBiZSB1c2VkIGluIHRoZSBjYXNlcyB3aGVyZSB0aGUgY29ycmVjdFxuICAgKiBkZWZhdWx0IGNoaWxkIGlzIG5vdCBuYW1lZCAnUmVzb3VyY2UnIG9yICdEZWZhdWx0JyBhcyBpdFxuICAgKiBzaG91bGQgYmUuXG4gICAqXG4gICAqIElmIHlvdSBzZXQgdGhpcyB0byB1bmRlZmluZWQsIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIGZpbmRpbmdcbiAgICogdGhlIGNoaWxkIG5hbWVkICdSZXNvdXJjZScgb3IgJ0RlZmF1bHQnIHdpbGwgYmUgdXNlZC5cbiAgICovXG4gIHB1YmxpYyBzZXQgZGVmYXVsdENoaWxkKHZhbHVlOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fZGVmYXVsdENoaWxkID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQWxsIGRpcmVjdCBjaGlsZHJlbiBvZiB0aGlzIGNvbnN0cnVjdC5cbiAgICovXG4gIHB1YmxpYyBnZXQgY2hpbGRyZW4oKSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5fY2hpbGRyZW4gPz8ge30pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGlzIGNvbnN0cnVjdCBhbmQgYWxsIG9mIGl0cyBjaGlsZHJlbiBpbiB0aGUgZ2l2ZW4gb3JkZXJcbiAgICovXG4gIHB1YmxpYyBmaW5kQWxsKG9yZGVyOiBDb25zdHJ1Y3RPcmRlciA9IENvbnN0cnVjdE9yZGVyLlBSRU9SREVSKTogSUNvbnN0cnVjdFtdIHtcbiAgICBjb25zdCByZXQgPSBuZXcgQXJyYXk8SUNvbnN0cnVjdD4oKTtcbiAgICB2aXNpdCh0aGlzLmhvc3QpO1xuICAgIHJldHVybiByZXQ7XG5cbiAgICBmdW5jdGlvbiB2aXNpdChjOiBJQ29uc3RydWN0KSB7XG4gICAgICBpZiAob3JkZXIgPT09IENvbnN0cnVjdE9yZGVyLlBSRU9SREVSKSB7XG4gICAgICAgIHJldC5wdXNoKGMpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGMubm9kZS5jaGlsZHJlbikge1xuICAgICAgICB2aXNpdChjaGlsZCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcmRlciA9PT0gQ29uc3RydWN0T3JkZXIuUE9TVE9SREVSKSB7XG4gICAgICAgIHJldC5wdXNoKGMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGNhbiBiZSB1c2VkIHRvIHNldCBjb250ZXh0dWFsIHZhbHVlcy5cbiAgICogQ29udGV4dCBtdXN0IGJlIHNldCBiZWZvcmUgYW55IGNoaWxkcmVuIGFyZSBhZGRlZCwgc2luY2UgY2hpbGRyZW4gbWF5IGNvbnN1bHQgY29udGV4dCBpbmZvIGR1cmluZyBjb25zdHJ1Y3Rpb24uXG4gICAqIElmIHRoZSBrZXkgYWxyZWFkeSBleGlzdHMsIGl0IHdpbGwgYmUgb3ZlcnJpZGRlbi5cbiAgICogQHBhcmFtIGtleSBUaGUgY29udGV4dCBrZXlcbiAgICogQHBhcmFtIHZhbHVlIFRoZSBjb250ZXh0IHZhbHVlXG4gICAqL1xuICBwdWJsaWMgc2V0Q29udGV4dChrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5hbWVzID0gdGhpcy5jaGlsZHJlbi5tYXAoYyA9PiBjLm5vZGUuaWQpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3Qgc2V0IGNvbnRleHQgYWZ0ZXIgY2hpbGRyZW4gaGF2ZSBiZWVuIGFkZGVkOiAnICsgbmFtZXMuam9pbignLCcpKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLl9jb250ZXh0KSB7XG4gICAgICB0aGlzLl9jb250ZXh0ID0ge307XG4gICAgfVxuICAgIHRoaXMuX2NvbnRleHRba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyBhIHZhbHVlIGZyb20gdHJlZSBjb250ZXh0IGlmIHByZXNlbnQuIE90aGVyd2lzZSwgd291bGQgdGhyb3cgYW4gZXJyb3IuXG4gICAqXG4gICAqIENvbnRleHQgaXMgdXN1YWxseSBpbml0aWFsaXplZCBhdCB0aGUgcm9vdCwgYnV0IGNhbiBiZSBvdmVycmlkZGVuIGF0IGFueSBwb2ludCBpbiB0aGUgdHJlZS5cbiAgICpcbiAgICogQHBhcmFtIGtleSBUaGUgY29udGV4dCBrZXlcbiAgICogQHJldHVybnMgVGhlIGNvbnRleHQgdmFsdWUgb3IgdGhyb3dzIGVycm9yIGlmIHRoZXJlIGlzIG5vIGNvbnRleHQgdmFsdWUgZm9yIHRoaXMga2V5XG4gICAqL1xuICBwdWJsaWMgZ2V0Q29udGV4dChrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLl9jb250ZXh0Py5ba2V5XTtcblxuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7IHJldHVybiB2YWx1ZTsgfVxuXG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgJiYgIXRoaXMuc2NvcGU/Lm5vZGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gY29udGV4dCB2YWx1ZSBwcmVzZW50IGZvciAke2tleX0ga2V5YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc2NvcGUgJiYgdGhpcy5zY29wZS5ub2RlLmdldENvbnRleHQoa2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIGFsbCBjb250ZXh0IG9mIGEgbm9kZSBmcm9tIHRyZWUgY29udGV4dC5cbiAgICpcbiAgICogQ29udGV4dCBpcyB1c3VhbGx5IGluaXRpYWxpemVkIGF0IHRoZSByb290LCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYXQgYW55IHBvaW50IGluIHRoZSB0cmVlLlxuICAgKlxuICAgKiBAcGFyYW0gZGVmYXVsdHMgQW55IGtleXMgdG8gb3ZlcnJpZGUgdGhlIHJldHJpZXZlZCBjb250ZXh0XG4gICAqIEByZXR1cm5zIFRoZSBjb250ZXh0IG9iamVjdCBvciBhbiBlbXB0eSBvYmplY3QgaWYgdGhlcmUgaXMgZGlzY292ZXJlZCBjb250ZXh0XG4gICAqL1xuICBwdWJsaWMgZ2V0QWxsQ29udGV4dChkZWZhdWx0cz86IG9iamVjdCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuc2NvcGVzLnJldmVyc2UoKVxuICAgICAgLnJlZHVjZSgoYSwgcykgPT4gKHsgLi4uKHMubm9kZS5fY29udGV4dCksIC4uLmEgfSksIHsgLi4uZGVmYXVsdHMgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGEgdmFsdWUgZnJvbSB0cmVlIGNvbnRleHQuXG4gICAqXG4gICAqIENvbnRleHQgaXMgdXN1YWxseSBpbml0aWFsaXplZCBhdCB0aGUgcm9vdCwgYnV0IGNhbiBiZSBvdmVycmlkZGVuIGF0IGFueSBwb2ludCBpbiB0aGUgdHJlZS5cbiAgICpcbiAgICogQHBhcmFtIGtleSBUaGUgY29udGV4dCBrZXlcbiAgICogQHJldHVybnMgVGhlIGNvbnRleHQgdmFsdWUgb3IgYHVuZGVmaW5lZGAgaWYgdGhlcmUgaXMgbm8gY29udGV4dCB2YWx1ZSBmb3IgdGhpcyBrZXkuXG4gICAqL1xuICBwdWJsaWMgdHJ5R2V0Q29udGV4dChrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLl9jb250ZXh0Py5ba2V5XTtcbiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdmFsdWU7IH1cblxuICAgIHJldHVybiB0aGlzLnNjb3BlICYmIHRoaXMuc2NvcGUubm9kZS50cnlHZXRDb250ZXh0KGtleSk7XG4gIH1cblxuICAvKipcbiAgICogQW4gaW1tdXRhYmxlIGFycmF5IG9mIG1ldGFkYXRhIG9iamVjdHMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgY29uc3RydWN0LlxuICAgKiBUaGlzIGNhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgdG8gaW1wbGVtZW50IHN1cHBvcnQgZm9yIGRlcHJlY2F0aW9uIG5vdGljZXMsIHNvdXJjZSBtYXBwaW5nLCBldGMuXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1ldGFkYXRhKCkge1xuICAgIHJldHVybiBbLi4udGhpcy5fbWV0YWRhdGEgPz8gW11dO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBtZXRhZGF0YSBlbnRyeSB0byB0aGlzIGNvbnN0cnVjdC5cbiAgICogRW50cmllcyBhcmUgYXJiaXRyYXJ5IHZhbHVlcyBhbmQgd2lsbCBhbHNvIGluY2x1ZGUgYSBzdGFjayB0cmFjZSB0byBhbGxvdyB0cmFjaW5nIGJhY2sgdG9cbiAgICogdGhlIGNvZGUgbG9jYXRpb24gZm9yIHdoZW4gdGhlIGVudHJ5IHdhcyBhZGRlZC4gSXQgY2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCB0byBpbmNsdWRlIHNvdXJjZVxuICAgKiBtYXBwaW5nIGluIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlcyB0byBpbXByb3ZlIGRpYWdub3N0aWNzLlxuICAgKiBOb3RlIHRoYXQgY29uc3RydWN0IG1ldGFkYXRhIGlzIG5vdCB0aGUgc2FtZSBhcyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSBtZXRhZGF0YSBhbmQgaXMgbmV2ZXIgd3JpdHRlbiB0byB0aGUgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUuXG4gICAqIFRoZSBtZXRhZGF0YSBlbnRyaWVzIGFyZSB3cml0dGVuIHRvIHRoZSBDbG91ZCBBc3NlbWJseSBNYW5pZmVzdCBpZiB0aGUgYHRyZWVNZXRhZGF0YWAgcHJvcGVydHkgaXMgc3BlY2lmaWVkIGluIHRoZSBwcm9wcyBvZiB0aGUgQXBwIHRoYXQgY29udGFpbnMgdGhpcyBDb25zdHJ1Y3QuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIGEgc3RyaW5nIGRlbm90aW5nIHRoZSB0eXBlIG9mIG1ldGFkYXRhXG4gICAqIEBwYXJhbSBkYXRhIHRoZSB2YWx1ZSBvZiB0aGUgbWV0YWRhdGEgKGNhbiBiZSBhIFRva2VuKS4gSWYgbnVsbC91bmRlZmluZWQsIG1ldGFkYXRhIHdpbGwgbm90IGJlIGFkZGVkLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgYWRkTWV0YWRhdGEodHlwZTogc3RyaW5nLCBkYXRhOiBhbnksIG9wdGlvbnM6IE1ldGFkYXRhT3B0aW9ucyA9IHsgfSk6IHZvaWQge1xuICAgIGlmIChkYXRhID09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBub2RlID0gdGhpcztcbiAgICBmdW5jdGlvbiBnZXRUcmFjZSgpIHtcbiAgICAgIGlmIChvcHRpb25zLnN0YWNrVHJhY2VPdmVycmlkZSAmJiBvcHRpb25zLnN0YWNrVHJhY2VPdmVycmlkZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLnN0YWNrVHJhY2VPdmVycmlkZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHNob3VsZFRyYWNlID0gb3B0aW9ucy5zdGFja1RyYWNlID8/IGZhbHNlO1xuICAgICAgcmV0dXJuIHNob3VsZFRyYWNlID8gY2FwdHVyZVN0YWNrVHJhY2Uob3B0aW9ucy50cmFjZUZyb21GdW5jdGlvbiA/PyBub2RlLmFkZE1ldGFkYXRhKSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX21ldGFkYXRhKSB7XG4gICAgICB0aGlzLl9tZXRhZGF0YSA9IFtdO1xuICAgIH1cbiAgICB0aGlzLl9tZXRhZGF0YS5wdXNoKHsgdHlwZSwgZGF0YSwgdHJhY2U6IGdldFRyYWNlKCkgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWxsIHBhcmVudCBzY29wZXMgb2YgdGhpcyBjb25zdHJ1Y3QuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgbGlzdCBvZiBwYXJlbnQgc2NvcGVzLiBUaGUgbGFzdCBlbGVtZW50IGluIHRoZSBsaXN0IHdpbGwgYWx3YXlzXG4gICAqIGJlIHRoZSBjdXJyZW50IGNvbnN0cnVjdCBhbmQgdGhlIGZpcnN0IGVsZW1lbnQgd2lsbCBiZSB0aGUgcm9vdCBvZiB0aGVcbiAgICogdHJlZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgc2NvcGVzKCk6IElDb25zdHJ1Y3RbXSB7XG4gICAgY29uc3QgcmV0ID0gbmV3IEFycmF5PElDb25zdHJ1Y3Q+KCk7XG5cbiAgICBsZXQgY3VycjogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZCA9IHRoaXMuaG9zdDtcbiAgICB3aGlsZSAoY3Vycikge1xuICAgICAgcmV0LnVuc2hpZnQoY3Vycik7XG4gICAgICBjdXJyID0gY3Vyci5ub2RlLnNjb3BlO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgcm9vdCBvZiB0aGUgY29uc3RydWN0IHRyZWUuXG4gICAqIEByZXR1cm5zIFRoZSByb290IG9mIHRoZSBjb25zdHJ1Y3QgdHJlZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgcm9vdCgpIHtcbiAgICByZXR1cm4gdGhpcy5zY29wZXNbMF07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoaXMgY29uc3RydWN0IG9yIHRoZSBzY29wZXMgaW4gd2hpY2ggaXQgaXMgZGVmaW5lZCBhcmVcbiAgICogbG9ja2VkLlxuICAgKi9cbiAgcHVibGljIGdldCBsb2NrZWQoKSB7XG4gICAgaWYgKHRoaXMuX2xvY2tlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2NvcGUgJiYgdGhpcy5zY29wZS5ub2RlLmxvY2tlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBvcmRlcmluZyBkZXBlbmRlbmN5IG9uIGFub3RoZXIgY29uc3RydWN0LlxuICAgKlxuICAgKiBBbiBgSURlcGVuZGFibGVgXG4gICAqL1xuICBwdWJsaWMgYWRkRGVwZW5kZW5jeSguLi5kZXBzOiBJRGVwZW5kYWJsZVtdKSB7XG4gICAgaWYgKCF0aGlzLl9kZXBlbmRlbmNpZXMpIHtcbiAgICAgIHRoaXMuX2RlcGVuZGVuY2llcyA9IG5ldyBTZXQoKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkIG9mIGRlcHMpIHtcbiAgICAgIHRoaXMuX2RlcGVuZGVuY2llcy5hZGQoZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbGwgZGVwZW5kZW5jaWVzIHJlZ2lzdGVyZWQgb24gdGhpcyBub2RlIChub24tcmVjdXJzaXZlKS5cbiAgICovXG4gIHB1YmxpYyBnZXQgZGVwZW5kZW5jaWVzKCk6IElDb25zdHJ1Y3RbXSB7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5PElDb25zdHJ1Y3Q+KCk7XG4gICAgaWYgKHRoaXMuX2RlcGVuZGVuY2llcykge1xuICAgICAgZm9yIChjb25zdCBkZXAgb2YgdGhpcy5fZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgIGZvciAoY29uc3Qgcm9vdCBvZiBEZXBlbmRhYmxlLm9mKGRlcCkuZGVwZW5kZW5jeVJvb3RzKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2gocm9vdCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGNoaWxkIHdpdGggdGhlIGdpdmVuIG5hbWUsIGlmIHByZXNlbnQuXG4gICAqXG4gICAqIEByZXR1cm5zIFdoZXRoZXIgYSBjaGlsZCB3aXRoIHRoZSBnaXZlbiBuYW1lIHdhcyBkZWxldGVkLlxuICAgKi9cbiAgcHVibGljIHRyeVJlbW92ZUNoaWxkKGNoaWxkTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLl9jaGlsZHJlbiB8fCAhKGNoaWxkTmFtZSBpbiB0aGlzLl9jaGlsZHJlbikpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgZGVsZXRlIHRoaXMuX2NoaWxkcmVuW2NoaWxkTmFtZV07XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHZhbGlkYXRpb24gdG8gdGhpcyBjb25zdHJ1Y3QuXG4gICAqXG4gICAqIFdoZW4gYG5vZGUudmFsaWRhdGUoKWAgaXMgY2FsbGVkLCB0aGUgYHZhbGlkYXRlKClgIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCBvblxuICAgKiBhbGwgdmFsaWRhdGlvbnMgYW5kIGFsbCBlcnJvcnMgd2lsbCBiZSByZXR1cm5lZC5cbiAgICpcbiAgICogQHBhcmFtIHZhbGlkYXRpb24gVGhlIHZhbGlkYXRpb24gb2JqZWN0XG4gICAqL1xuICBwdWJsaWMgYWRkVmFsaWRhdGlvbih2YWxpZGF0aW9uOiBJVmFsaWRhdGlvbikge1xuICAgIGlmICghdGhpcy5fdmFsaWRhdGlvbnMpIHtcbiAgICAgIHRoaXMuX3ZhbGlkYXRpb25zID0gW107XG4gICAgfVxuICAgIHRoaXMuX3ZhbGlkYXRpb25zLnB1c2godmFsaWRhdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoaXMgY29uc3RydWN0LlxuICAgKlxuICAgKiBJbnZva2VzIHRoZSBgdmFsaWRhdGUoKWAgbWV0aG9kIG9uIGFsbCB2YWxpZGF0aW9ucyBhZGRlZCB0aHJvdWdoXG4gICAqIGBhZGRWYWxpZGF0aW9uKClgLlxuICAgKlxuICAgKiBAcmV0dXJucyBhbiBhcnJheSBvZiB2YWxpZGF0aW9uIGVycm9yIG1lc3NhZ2VzIGFzc29jaWF0ZWQgd2l0aCB0aGlzXG4gICAqIGNvbnN0cnVjdC5cbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZSgpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuICh0aGlzLl92YWxpZGF0aW9ucyA/PyBbXSkuZmxhdE1hcCh2ID0+IHYudmFsaWRhdGUoKSk7XG4gIH1cblxuICAvKipcbiAgICogTG9ja3MgdGhpcyBjb25zdHJ1Y3QgZnJvbSBhbGxvd2luZyBtb3JlIGNoaWxkcmVuIHRvIGJlIGFkZGVkLiBBZnRlciB0aGlzXG4gICAqIGNhbGwsIG5vIG1vcmUgY2hpbGRyZW4gY2FuIGJlIGFkZGVkIHRvIHRoaXMgY29uc3RydWN0IG9yIHRvIGFueSBjaGlsZHJlbi5cbiAgICovXG4gIHB1YmxpYyBsb2NrKCkge1xuICAgIHRoaXMuX2xvY2tlZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBvbmUgb3IgbW9yZSBtaXhpbnMgdG8gdGhpcyBjb25zdHJ1Y3QuXG4gICAqXG4gICAqIE1peGlucyBhcmUgYXBwbGllZCBpbiBvcmRlci4gVGhlIGxpc3Qgb2YgY29uc3RydWN0cyBpcyBjYXB0dXJlZCBhdCB0aGVcbiAgICogc3RhcnQgb2YgdGhlIGNhbGwsIHNvIGNvbnN0cnVjdHMgYWRkZWQgYnkgYSBtaXhpbiB3aWxsIG5vdCBiZSB2aXNpdGVkLlxuICAgKiBVc2UgbXVsdGlwbGUgYHdpdGgoKWAgY2FsbHMgaWYgc3Vic2VxdWVudCBtaXhpbnMgc2hvdWxkIGFwcGx5IHRvIGFkZGVkXG4gICAqIGNvbnN0cnVjdHMuXG4gICAqXG4gICAqIEBwYXJhbSBtaXhpbnMgVGhlIG1peGlucyB0byBhcHBseVxuICAgKiBAcmV0dXJucyBUaGlzIGNvbnN0cnVjdCBmb3IgY2hhaW5pbmdcbiAgICovXG4gIHB1YmxpYyB3aXRoKC4uLm1peGluczogSU1peGluW10pOiBJQ29uc3RydWN0IHtcbiAgICBjb25zdCBhbGxDb25zdHJ1Y3RzID0gdGhpcy5maW5kQWxsKCk7XG4gICAgZm9yIChjb25zdCBtaXhpbiBvZiBtaXhpbnMpIHtcbiAgICAgIGZvciAoY29uc3QgY29uc3RydWN0IG9mIGFsbENvbnN0cnVjdHMpIHtcbiAgICAgICAgaWYgKG1peGluLnN1cHBvcnRzKGNvbnN0cnVjdCkpIHtcbiAgICAgICAgICBtaXhpbi5hcHBseVRvKGNvbnN0cnVjdCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaG9zdDtcbiAgfTtcblxuICAvKipcbiAgICogQWRkcyBhIGNoaWxkIGNvbnN0cnVjdCB0byB0aGlzIG5vZGUuXG4gICAqXG4gICAqIEBwYXJhbSBjaGlsZCBUaGUgY2hpbGQgY29uc3RydWN0XG4gICAqIEBwYXJhbSBjaGlsZE5hbWUgVGhlIHR5cGUgbmFtZSBvZiB0aGUgY2hpbGQgY29uc3RydWN0LlxuICAgKiBAcmV0dXJucyBUaGUgcmVzb2x2ZWQgcGF0aCBwYXJ0IG5hbWUgb2YgdGhlIGNoaWxkXG4gICAqL1xuICBwcml2YXRlIGFkZENoaWxkKGNoaWxkOiBDb25zdHJ1Y3QsIGNoaWxkTmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMubG9ja2VkKSB7XG5cbiAgICAgIC8vIHNwZWNpYWwgZXJyb3IgaWYgcm9vdCBpcyBsb2NrZWRcbiAgICAgIGlmICghdGhpcy5wYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBjaGlsZHJlbiBkdXJpbmcgc3ludGhlc2lzJyk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGFkZCBjaGlsZHJlbiB0byBcIiR7dGhpcy5wYXRofVwiIGR1cmluZyBzeW50aGVzaXNgKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX2NoaWxkcmVuKSB7XG4gICAgICB0aGlzLl9jaGlsZHJlbiA9IHt9O1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9jaGlsZHJlbltjaGlsZE5hbWVdKSB7XG4gICAgICBjb25zdCBuYW1lID0gdGhpcy5pZCA/PyAnJztcbiAgICAgIGNvbnN0IHR5cGVOY