@glimmer/compiler
Version:
259 lines (219 loc) • 27.8 kB
JavaScript
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
import { generateSyntaxError, isKeyword, KEYWORDS_TYPES } from '@glimmer/syntax';
import { exhausted } from '@glimmer/util';
import { Err } from '../../../shared/result';
var KeywordImpl = /*#__PURE__*/function () {
function KeywordImpl(keyword, type, delegate) {
this.keyword = keyword;
this.delegate = delegate;
var nodes = new Set();
for (var _iterator = _createForOfIteratorHelperLoose(KEYWORD_NODES[type]), _step; !(_step = _iterator()).done;) {
var nodeType = _step.value;
nodes.add(nodeType);
}
this.types = nodes;
}
var _proto = KeywordImpl.prototype;
_proto.match = function match(node) {
if (!this.types.has(node.type)) {
return false;
}
var path = getCalleeExpression(node);
if (path !== null && path.type === 'Path' && path.ref.type === 'Free') {
if (path.tail.length > 0) {
if (path.ref.resolution.serialize() === 'Loose') {
// cannot be a keyword reference, keywords do not allow paths (must be
// relying on implicit this fallback)
return false;
}
}
return path.ref.name === this.keyword;
} else {
return false;
}
};
_proto.translate = function translate(node, state) {
var _this = this;
if (this.match(node)) {
var path = getCalleeExpression(node);
if (path !== null && path.type === 'Path' && path.tail.length > 0) {
return Err(generateSyntaxError("The `" + this.keyword + "` keyword was used incorrectly. It was used as `" + path.loc.asString() + "`, but it cannot be used with additional path segments. \n\nError caused by", node.loc));
}
var param = this.delegate.assert(node, state);
return param.andThen(function (param) {
return _this.delegate.translate({
node: node,
state: state
}, param);
});
} else {
return null;
}
};
return KeywordImpl;
}();
export var KEYWORD_NODES = {
Call: ['Call'],
Block: ['InvokeBlock'],
Append: ['AppendContent'],
Modifier: ['ElementModifier']
};
export function keyword(keyword, type, delegate) {
return new KeywordImpl(keyword, type, delegate);
}
function getCalleeExpression(node) {
switch (node.type) {
// This covers the inside of attributes and expressions, as well as the callee
// of call nodes
case 'Path':
return node;
case 'AppendContent':
return getCalleeExpression(node.value);
case 'Call':
case 'InvokeBlock':
case 'ElementModifier':
return node.callee;
default:
return null;
}
}
export var Keywords = /*#__PURE__*/function () {
function Keywords(type) {
this._keywords = [];
this._type = type;
}
var _proto2 = Keywords.prototype;
_proto2.kw = function kw(name, delegate) {
this._keywords.push(keyword(name, this._type, delegate));
return this;
};
_proto2.translate = function translate(node, state) {
for (var _iterator2 = _createForOfIteratorHelperLoose(this._keywords), _step2; !(_step2 = _iterator2()).done;) {
var _keyword = _step2.value;
var result = _keyword.translate(node, state);
if (result !== null) {
return result;
}
}
var path = getCalleeExpression(node);
if (path && path.type === 'Path' && path.ref.type === 'Free' && isKeyword(path.ref.name)) {
var name = path.ref.name;
var usedType = this._type;
var validTypes = KEYWORDS_TYPES[name];
if (validTypes.indexOf(usedType) === -1) {
return Err(generateSyntaxError("The `" + name + "` keyword was used incorrectly. It was used as " + typesToReadableName[usedType] + ", but its valid usages are:\n\n" + generateTypesMessage(name, validTypes) + "\n\nError caused by", node.loc));
}
}
return null;
};
return Keywords;
}();
var typesToReadableName = {
Append: 'an append statement',
Block: 'a block statement',
Call: 'a call expression',
Modifier: 'a modifier'
};
function generateTypesMessage(name, types) {
return types.map(function (type) {
switch (type) {
case 'Append':
return "- As an append statement, as in: {{" + name + "}}";
case 'Block':
return "- As a block statement, as in: {{#" + name + "}}{{/" + name + "}}";
case 'Call':
return "- As an expression, as in: (" + name + ")";
case 'Modifier':
return "- As a modifier, as in: <div {{" + name + "}}></div>";
default:
return exhausted(type);
}
}).join('\n\n');
}
/**
* This function builds keyword definitions for a particular type of AST node (`KeywordType`).
*
* You can build keyword definitions for:
*
* - `Expr`: A `SubExpression` or `PathExpression`
* - `Block`: A `BlockStatement`
* - A `BlockStatement` is a keyword candidate if its head is a
* `PathExpression`
* - `Append`: An `AppendStatement`
*
* A node is a keyword candidate if:
*
* - A `PathExpression` is a keyword candidate if it has no tail, and its
* head expression is a `LocalVarHead` or `FreeVarHead` whose name is
* the keyword's name.
* - A `SubExpression`, `AppendStatement`, or `BlockStatement` is a keyword
* candidate if its head is a keyword candidate.
*
* The keyword infrastructure guarantees that:
*
* - If a node is not a keyword candidate, it is never passed to any keyword's
* `assert` method.
* - If a node is not the `KeywordType` for a particular keyword, it will not
* be passed to the keyword's `assert` method.
*
* `Expr` keywords are used in expression positions and should return HIR
* expressions. `Block` and `Append` keywords are used in statement
* positions and should return HIR statements.
*
* A keyword definition has two parts:
*
* - `match`, which determines whether an AST node matches the keyword, and can
* optionally return some information extracted from the AST node.
* - `translate`, which takes a matching AST node as well as the extracted
* information and returns an appropriate HIR instruction.
*
* # Example
*
* This keyword:
*
* - turns `(hello)` into `"hello"`
* - as long as `hello` is not in scope
* - makes it an error to pass any arguments (such as `(hello world)`)
*
* ```ts
* keywords('SubExpr').kw('hello', {
* assert(node: ExprKeywordNode): Result<void> | false {
* // we don't want to transform `hello` as a `PathExpression`
* if (node.type !== 'SubExpression') {
* return false;
* }
*
* // node.head would be `LocalVarHead` if `hello` was in scope
* if (node.head.type !== 'FreeVarHead') {
* return false;
* }
*
* if (node.params.length || node.hash) {
* return Err(generateSyntaxError(`(hello) does not take any arguments`), node.loc);
* } else {
* return Ok();
* }
* },
*
* translate(node: ASTv2.SubExpression): hir.Expression {
* return ASTv2.builders.literal("hello", node.loc)
* }
* })
* ```
*
* The keyword infrastructure checks to make sure that the node is the right
* type before calling `assert`, so you only need to consider `SubExpression`
* and `PathExpression` here. It also checks to make sure that the node passed
* to `assert` has the keyword name in the right place.
*
* Note the important difference between returning `false` from `assert`,
* which just means that the node didn't match, and returning `Err`, which
* means that the node matched, but there was a keyword-specific syntax
* error.
*/
export function keywords(type) {
return new Keywords(type);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL2NvbXBpbGVyL2xpYi9wYXNzZXMvMS1ub3JtYWxpemF0aW9uL2tleXdvcmRzL2ltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsU0FBQSxtQkFBQSxFQUFBLFNBQUEsRUFBQSxjQUFBLFFBQUEsaUJBQUE7QUFPQSxTQUFBLFNBQUEsUUFBQSxlQUFBO0FBRUEsU0FBQSxHQUFBLFFBQUEsd0JBQUE7O0lBZ0JBLFc7QUFRRSx1QkFBQSxPQUFBLEVBQUEsSUFBQSxFQUFBLFFBQUEsRUFHa0U7QUFGdEQsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUVGLFNBQUEsUUFBQSxHQUFBLFFBQUE7QUFFUixRQUFJLEtBQUssR0FBRyxJQUFaLEdBQVksRUFBWjs7QUFDQSx5REFBcUIsYUFBYSxDQUFsQyxJQUFrQyxDQUFsQyx3Q0FBMEM7QUFBQSxVQUExQyxRQUEwQztBQUN4QyxNQUFBLEtBQUssQ0FBTCxHQUFBLENBQUEsUUFBQTtBQUNEOztBQUVELFNBQUEsS0FBQSxHQUFBLEtBQUE7QUFDRDs7OztTQUVTLEssR0FBQSxlQUFLLElBQUwsRUFBZ0M7QUFDeEMsUUFBSSxDQUFDLEtBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBZSxJQUFJLENBQXhCLElBQUssQ0FBTCxFQUFnQztBQUM5QixhQUFBLEtBQUE7QUFDRDs7QUFFRCxRQUFJLElBQUksR0FBRyxtQkFBbUIsQ0FBOUIsSUFBOEIsQ0FBOUI7O0FBRUEsUUFBSSxJQUFJLEtBQUosSUFBQSxJQUFpQixJQUFJLENBQUosSUFBQSxLQUFqQixNQUFBLElBQXlDLElBQUksQ0FBSixHQUFBLENBQUEsSUFBQSxLQUE3QyxNQUFBLEVBQXVFO0FBQ3JFLFVBQUksSUFBSSxDQUFKLElBQUEsQ0FBQSxNQUFBLEdBQUosQ0FBQSxFQUEwQjtBQUN4QixZQUFJLElBQUksQ0FBSixHQUFBLENBQUEsVUFBQSxDQUFBLFNBQUEsT0FBSixPQUFBLEVBQWlEO0FBQy9DO0FBQ0E7QUFDQSxpQkFBQSxLQUFBO0FBQ0Q7QUFDRjs7QUFFRCxhQUFPLElBQUksQ0FBSixHQUFBLENBQUEsSUFBQSxLQUFrQixLQUF6QixPQUFBO0FBVEYsS0FBQSxNQVVPO0FBQ0wsYUFBQSxLQUFBO0FBQ0Q7QUFDRixHOztTQUVELFMsR0FBQSxtQkFBUyxJQUFULEVBQVMsS0FBVCxFQUE0RDtBQUFBOztBQUMxRCxRQUFJLEtBQUEsS0FBQSxDQUFKLElBQUksQ0FBSixFQUFzQjtBQUNwQixVQUFJLElBQUksR0FBRyxtQkFBbUIsQ0FBOUIsSUFBOEIsQ0FBOUI7O0FBRUEsVUFBSSxJQUFJLEtBQUosSUFBQSxJQUFpQixJQUFJLENBQUosSUFBQSxLQUFqQixNQUFBLElBQXlDLElBQUksQ0FBSixJQUFBLENBQUEsTUFBQSxHQUE3QyxDQUFBLEVBQW1FO0FBQ2pFLGVBQU8sR0FBRyxDQUNSLG1CQUFtQixXQUVmLEtBQUssT0FGVSx3REFHb0MsSUFBSSxDQUFKLEdBQUEsQ0FIcEMsUUFHb0MsRUFIcEMsa0ZBSWpCLElBQUksQ0FMUixHQUNxQixDQURYLENBQVY7QUFRRDs7QUFFRCxVQUFJLEtBQUssR0FBRyxLQUFBLFFBQUEsQ0FBQSxNQUFBLENBQUEsSUFBQSxFQUFaLEtBQVksQ0FBWjtBQUNBLGFBQU8sS0FBSyxDQUFMLE9BQUEsQ0FBZSxVQUFBLEtBQUQ7QUFBQSxlQUFXLEtBQUEsQ0FBQSxRQUFBLENBQUEsU0FBQSxDQUF3QjtBQUFFLFVBQUEsSUFBRixFQUFFLElBQUY7QUFBUSxVQUFBLEtBQUEsRUFBQTtBQUFSLFNBQXhCLEVBQWhDLEtBQWdDLENBQVg7QUFBQSxPQUFkLENBQVA7QUFmRixLQUFBLE1BZ0JPO0FBQ0wsYUFBQSxJQUFBO0FBQ0Q7QUFDRixHOzs7OztBQVNILE9BQU8sSUFBTSxhQUFhLEdBQUc7QUFDM0IsRUFBQSxJQUFJLEVBQUUsQ0FEcUIsTUFDckIsQ0FEcUI7QUFFM0IsRUFBQSxLQUFLLEVBQUUsQ0FGb0IsYUFFcEIsQ0FGb0I7QUFHM0IsRUFBQSxNQUFNLEVBQUUsQ0FIbUIsZUFHbkIsQ0FIbUI7QUFJM0IsRUFBQSxRQUFRLEVBQUUsQ0FBQSxpQkFBQTtBQUppQixDQUF0QjtBQXFDUCxPQUFNLFNBQUEsT0FBQSxDQUFBLE9BQUEsRUFBQSxJQUFBLEVBQUEsUUFBQSxFQUlpQztBQUNyQyxTQUFPLElBQUEsV0FBQSxDQUFBLE9BQUEsRUFBQSxJQUFBLEVBQVAsUUFBTyxDQUFQO0FBQ0Q7O0FBU0QsU0FBQSxtQkFBQSxDQUFBLElBQUEsRUFDMEM7QUFFeEMsVUFBUSxJQUFJLENBQVosSUFBQTtBQUNFO0FBQ0E7QUFDQSxTQUFBLE1BQUE7QUFDRSxhQUFBLElBQUE7O0FBQ0YsU0FBQSxlQUFBO0FBQ0UsYUFBTyxtQkFBbUIsQ0FBQyxJQUFJLENBQS9CLEtBQTBCLENBQTFCOztBQUNGLFNBQUEsTUFBQTtBQUNBLFNBQUEsYUFBQTtBQUNBLFNBQUEsaUJBQUE7QUFDRSxhQUFPLElBQUksQ0FBWCxNQUFBOztBQUNGO0FBQ0UsYUFBQSxJQUFBO0FBWko7QUFjRDs7QUFFRCxXQUFNLFFBQU47QUFLRSxvQkFBQSxJQUFBLEVBQW1CO0FBSG5CLFNBQUEsU0FBQSxHQUFBLEVBQUE7QUFJRSxTQUFBLEtBQUEsR0FBQSxJQUFBO0FBQ0Q7O0FBUEg7O0FBQUEsVUFTRSxFQVRGLEdBU0UsWUFBRSxJQUFGLEVBQUUsUUFBRixFQUU0RDtBQUUxRCxTQUFBLFNBQUEsQ0FBQSxJQUFBLENBQW9CLE9BQU8sQ0FBQSxJQUFBLEVBQU8sS0FBUCxLQUFBLEVBQTNCLFFBQTJCLENBQTNCOztBQUVBLFdBQUEsSUFBQTtBQUNELEdBaEJIOztBQUFBLFVBa0JFLFNBbEJGLEdBa0JFLG1CQUFTLElBQVQsRUFBUyxLQUFULEVBRTJCO0FBRXpCLDBEQUFvQixLQUFwQixTQUFBLDJDQUFvQztBQUFBLFVBQXBDLFFBQW9DOztBQUNsQyxVQUFJLE1BQU0sR0FBRyxRQUFPLENBQVAsU0FBQSxDQUFBLElBQUEsRUFBYixLQUFhLENBQWI7O0FBQ0EsVUFBSSxNQUFNLEtBQVYsSUFBQSxFQUFxQjtBQUNuQixlQUFBLE1BQUE7QUFDRDtBQUNGOztBQUVELFFBQUksSUFBSSxHQUFHLG1CQUFtQixDQUE5QixJQUE4QixDQUE5Qjs7QUFFQSxRQUFJLElBQUksSUFBSSxJQUFJLENBQUosSUFBQSxLQUFSLE1BQUEsSUFBZ0MsSUFBSSxDQUFKLEdBQUEsQ0FBQSxJQUFBLEtBQWhDLE1BQUEsSUFBNEQsU0FBUyxDQUFDLElBQUksQ0FBSixHQUFBLENBQTFFLElBQXlFLENBQXpFLEVBQTBGO0FBQUEsVUFDbEYsSUFEa0YsR0FDekUsSUFBSSxDQUFuQixHQUR3RixDQUNsRixJQURrRjtBQUd4RixVQUFJLFFBQVEsR0FBRyxLQUFmLEtBQUE7QUFDQSxVQUFJLFVBQVUsR0FBRyxjQUFjLENBQS9CLElBQStCLENBQS9COztBQUVBLFVBQUksVUFBVSxDQUFWLE9BQUEsQ0FBQSxRQUFBLE1BQWlDLENBQXJDLENBQUEsRUFBeUM7QUFDdkMsZUFBTyxHQUFHLENBQ1IsbUJBQW1CLFdBQ1IsSUFEUSx1REFFZixtQkFBbUIsQ0FBQSxRQUFBLENBRkosdUNBR2lCLG9CQUFvQixDQUFBLElBQUEsRUFIckMsVUFHcUMsQ0FIckMsMEJBT2pCLElBQUksQ0FSUixHQUNxQixDQURYLENBQVY7QUFXRDtBQUNGOztBQUVELFdBQUEsSUFBQTtBQUNELEdBckRIOztBQUFBO0FBQUE7QUF3REEsSUFBTSxtQkFBbUIsR0FBRztBQUMxQixFQUFBLE1BQU0sRUFEb0IscUJBQUE7QUFFMUIsRUFBQSxLQUFLLEVBRnFCLG1CQUFBO0FBRzFCLEVBQUEsSUFBSSxFQUhzQixtQkFBQTtBQUkxQixFQUFBLFFBQVEsRUFBRTtBQUpnQixDQUE1Qjs7QUFPQSxTQUFBLG9CQUFBLENBQUEsSUFBQSxFQUFBLEtBQUEsRUFBZ0U7QUFDOUQsU0FBTyxLQUFLLENBQUwsR0FBQSxDQUNDLFVBQUEsSUFBRCxFQUFTO0FBQ1osWUFBQSxJQUFBO0FBQ0UsV0FBQSxRQUFBO0FBQ0UsdURBQUEsSUFBQTs7QUFDRixXQUFBLE9BQUE7QUFDRSxzREFBNEMsSUFBNUMsYUFBQSxJQUFBOztBQUNGLFdBQUEsTUFBQTtBQUNFLGdEQUFBLElBQUE7O0FBQ0YsV0FBQSxVQUFBO0FBQ0UsbURBQUEsSUFBQTs7QUFDRjtBQUNFLGVBQU8sU0FBUyxDQUFoQixJQUFnQixDQUFoQjtBQVZKO0FBRkcsR0FBQSxFQUFBLElBQUEsQ0FBUCxNQUFPLENBQVA7QUFnQkQ7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFpRkEsT0FBTSxTQUFBLFFBQUEsQ0FBQSxJQUFBLEVBQWlEO0FBQ3JELFNBQU8sSUFBQSxRQUFBLENBQVAsSUFBTyxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBU1R2MixcbiAgZ2VuZXJhdGVTeW50YXhFcnJvcixcbiAgaXNLZXl3b3JkLFxuICBLRVlXT1JEU19UWVBFUyxcbiAgS2V5d29yZFR5cGUsXG59IGZyb20gJ0BnbGltbWVyL3N5bnRheCc7XG5pbXBvcnQgeyBleGhhdXN0ZWQgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcblxuaW1wb3J0IHsgRXJyLCBSZXN1bHQgfSBmcm9tICcuLi8uLi8uLi9zaGFyZWQvcmVzdWx0JztcbmltcG9ydCB7IE5vcm1hbGl6YXRpb25TdGF0ZSB9IGZyb20gJy4uL2NvbnRleHQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmREZWxlZ2F0ZTxNYXRjaCBleHRlbmRzIEtleXdvcmRNYXRjaCwgViwgT3V0PiB7XG4gIGFzc2VydChvcHRpb25zOiBNYXRjaCwgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSk6IFJlc3VsdDxWPjtcbiAgdHJhbnNsYXRlKG9wdGlvbnM6IHsgbm9kZTogTWF0Y2g7IHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGUgfSwgcGFyYW06IFYpOiBSZXN1bHQ8T3V0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBLZXl3b3JkPEsgZXh0ZW5kcyBLZXl3b3JkVHlwZSA9IEtleXdvcmRUeXBlLCBPdXQgPSB1bmtub3duPiB7XG4gIHRyYW5zbGF0ZShub2RlOiBLZXl3b3JkQ2FuZGlkYXRlc1tLXSwgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSk6IFJlc3VsdDxPdXQ+IHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCbG9ja0tleXdvcmQ8T3V0ID0gdW5rbm93bj4ge1xuICB0cmFuc2xhdGUobm9kZTogQVNUdjIuSW52b2tlQmxvY2ssIHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGUpOiBSZXN1bHQ8T3V0PiB8IG51bGw7XG59XG5cbmNsYXNzIEtleXdvcmRJbXBsPFxuICBLIGV4dGVuZHMgS2V5d29yZFR5cGUsXG4gIFMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFBhcmFtID0gdW5rbm93bixcbiAgT3V0ID0gdW5rbm93blxuPiB7XG4gIHByb3RlY3RlZCB0eXBlczogU2V0PEtleXdvcmRDYW5kaWRhdGVzW0tdWyd0eXBlJ10+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBrZXl3b3JkOiBTLFxuICAgIHR5cGU6IEtleXdvcmRUeXBlLFxuICAgIHByaXZhdGUgZGVsZWdhdGU6IEtleXdvcmREZWxlZ2F0ZTxLZXl3b3JkTWF0Y2hlc1tLXSwgUGFyYW0sIE91dD5cbiAgKSB7XG4gICAgbGV0IG5vZGVzID0gbmV3IFNldDxLZXl3b3JkTm9kZVsndHlwZSddPigpO1xuICAgIGZvciAobGV0IG5vZGVUeXBlIG9mIEtFWVdPUkRfTk9ERVNbdHlwZV0pIHtcbiAgICAgIG5vZGVzLmFkZChub2RlVHlwZSk7XG4gICAgfVxuXG4gICAgdGhpcy50eXBlcyA9IG5vZGVzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1hdGNoKG5vZGU6IEtleXdvcmRDYW5kaWRhdGVzW0tdKTogbm9kZSBpcyBLZXl3b3JkTWF0Y2hlc1tLXSB7XG4gICAgaWYgKCF0aGlzLnR5cGVzLmhhcyhub2RlLnR5cGUpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbGV0IHBhdGggPSBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUpO1xuXG4gICAgaWYgKHBhdGggIT09IG51bGwgJiYgcGF0aC50eXBlID09PSAnUGF0aCcgJiYgcGF0aC5yZWYudHlwZSA9PT0gJ0ZyZWUnKSB7XG4gICAgICBpZiAocGF0aC50YWlsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKHBhdGgucmVmLnJlc29sdXRpb24uc2VyaWFsaXplKCkgPT09ICdMb29zZScpIHtcbiAgICAgICAgICAvLyBjYW5ub3QgYmUgYSBrZXl3b3JkIHJlZmVyZW5jZSwga2V5d29yZHMgZG8gbm90IGFsbG93IHBhdGhzIChtdXN0IGJlXG4gICAgICAgICAgLy8gcmVseWluZyBvbiBpbXBsaWNpdCB0aGlzIGZhbGxiYWNrKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGF0aC5yZWYubmFtZSA9PT0gdGhpcy5rZXl3b3JkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgdHJhbnNsYXRlKG5vZGU6IEtleXdvcmRNYXRjaGVzW0tdLCBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlKTogUmVzdWx0PE91dD4gfCBudWxsIHtcbiAgICBpZiAodGhpcy5tYXRjaChub2RlKSkge1xuICAgICAgbGV0IHBhdGggPSBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUpO1xuXG4gICAgICBpZiAocGF0aCAhPT0gbnVsbCAmJiBwYXRoLnR5cGUgPT09ICdQYXRoJyAmJiBwYXRoLnRhaWwubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gRXJyKFxuICAgICAgICAgIGdlbmVyYXRlU3ludGF4RXJyb3IoXG4gICAgICAgICAgICBgVGhlIFxcYCR7XG4gICAgICAgICAgICAgIHRoaXMua2V5d29yZFxuICAgICAgICAgICAgfVxcYCBrZXl3b3JkIHdhcyB1c2VkIGluY29ycmVjdGx5LiBJdCB3YXMgdXNlZCBhcyBcXGAke3BhdGgubG9jLmFzU3RyaW5nKCl9XFxgLCBidXQgaXQgY2Fubm90IGJlIHVzZWQgd2l0aCBhZGRpdGlvbmFsIHBhdGggc2VnbWVudHMuIFxcblxcbkVycm9yIGNhdXNlZCBieWAsXG4gICAgICAgICAgICBub2RlLmxvY1xuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHBhcmFtID0gdGhpcy5kZWxlZ2F0ZS5hc3NlcnQobm9kZSwgc3RhdGUpO1xuICAgICAgcmV0dXJuIHBhcmFtLmFuZFRoZW4oKHBhcmFtKSA9PiB0aGlzLmRlbGVnYXRlLnRyYW5zbGF0ZSh7IG5vZGUsIHN0YXRlIH0sIHBhcmFtKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgdHlwZSBQb3NzaWJsZU5vZGUgPVxuICB8IEFTVHYyLlBhdGhFeHByZXNzaW9uXG4gIHwgQVNUdjIuQXBwZW5kQ29udGVudFxuICB8IEFTVHYyLkNhbGxFeHByZXNzaW9uXG4gIHwgQVNUdjIuSW52b2tlQmxvY2s7XG5cbmV4cG9ydCBjb25zdCBLRVlXT1JEX05PREVTID0ge1xuICBDYWxsOiBbJ0NhbGwnXSxcbiAgQmxvY2s6IFsnSW52b2tlQmxvY2snXSxcbiAgQXBwZW5kOiBbJ0FwcGVuZENvbnRlbnQnXSxcbiAgTW9kaWZpZXI6IFsnRWxlbWVudE1vZGlmaWVyJ10sXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmRDYW5kaWRhdGVzIHtcbiAgQ2FsbDogQVNUdjIuRXhwcmVzc2lvbk5vZGU7XG4gIEJsb2NrOiBBU1R2Mi5JbnZva2VCbG9jaztcbiAgQXBwZW5kOiBBU1R2Mi5BcHBlbmRDb250ZW50O1xuICBNb2RpZmllcjogQVNUdjIuRWxlbWVudE1vZGlmaWVyO1xufVxuXG5leHBvcnQgdHlwZSBLZXl3b3JkQ2FuZGlkYXRlID0gS2V5d29yZENhbmRpZGF0ZXNba2V5b2YgS2V5d29yZENhbmRpZGF0ZXNdO1xuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmRNYXRjaGVzIHtcbiAgQ2FsbDogQVNUdjIuQ2FsbEV4cHJlc3Npb247XG4gIEJsb2NrOiBBU1R2Mi5JbnZva2VCbG9jaztcbiAgQXBwZW5kOiBBU1R2Mi5BcHBlbmRDb250ZW50O1xuICBNb2RpZmllcjogQVNUdjIuRWxlbWVudE1vZGlmaWVyO1xufVxuXG5leHBvcnQgdHlwZSBLZXl3b3JkTWF0Y2ggPSBLZXl3b3JkTWF0Y2hlc1trZXlvZiBLZXl3b3JkTWF0Y2hlc107XG5cbi8qKlxuICogQSBcImdlbmVyaWNcIiBrZXl3b3JkIGlzIHNvbWV0aGluZyBsaWtlIGBoYXMtYmxvY2tgLCB3aGljaCBtYWtlcyBzZW5zZSBpbiB0aGUgY29udGV4dFxuICogb2Ygc3ViLWV4cHJlc3Npb24gb3IgYXBwZW5kXG4gKi9cbmV4cG9ydCB0eXBlIEdlbmVyaWNLZXl3b3JkTm9kZSA9IEFTVHYyLkFwcGVuZENvbnRlbnQgfCBBU1R2Mi5DYWxsRXhwcmVzc2lvbjtcblxuZXhwb3J0IHR5cGUgS2V5d29yZE5vZGUgPVxuICB8IEdlbmVyaWNLZXl3b3JkTm9kZVxuICB8IEFTVHYyLkNhbGxFeHByZXNzaW9uXG4gIHwgQVNUdjIuSW52b2tlQmxvY2tcbiAgfCBBU1R2Mi5FbGVtZW50TW9kaWZpZXI7XG5cbmV4cG9ydCBmdW5jdGlvbiBrZXl3b3JkPFxuICBLIGV4dGVuZHMgS2V5d29yZFR5cGUsXG4gIEQgZXh0ZW5kcyBLZXl3b3JkRGVsZWdhdGU8S2V5d29yZE1hdGNoZXNbS10sIHVua25vd24sIE91dD4sXG4gIE91dCA9IHVua25vd25cbj4oa2V5d29yZDogc3RyaW5nLCB0eXBlOiBLLCBkZWxlZ2F0ZTogRCk6IEtleXdvcmQ8SywgT3V0PiB7XG4gIHJldHVybiBuZXcgS2V5d29yZEltcGwoa2V5d29yZCwgdHlwZSwgZGVsZWdhdGUgYXMgS2V5d29yZERlbGVnYXRlPEtleXdvcmRNYXRjaCwgdW5rbm93biwgT3V0Pik7XG59XG5cbmV4cG9ydCB0eXBlIFBvc3NpYmxlS2V5d29yZCA9IEtleXdvcmROb2RlO1xudHlwZSBPdXRGb3I8SyBleHRlbmRzIEtleXdvcmQgfCBCbG9ja0tleXdvcmQ+ID0gSyBleHRlbmRzIEJsb2NrS2V5d29yZDxpbmZlciBPdXQ+XG4gID8gT3V0XG4gIDogSyBleHRlbmRzIEtleXdvcmQ8S2V5d29yZFR5cGUsIGluZmVyIE91dD5cbiAgPyBPdXRcbiAgOiBuZXZlcjtcblxuZnVuY3Rpb24gZ2V0Q2FsbGVlRXhwcmVzc2lvbihcbiAgbm9kZTogS2V5d29yZE5vZGUgfCBBU1R2Mi5FeHByZXNzaW9uTm9kZVxuKTogQVNUdjIuRXhwcmVzc2lvbk5vZGUgfCBudWxsIHtcbiAgc3dpdGNoIChub2RlLnR5cGUpIHtcbiAgICAvLyBUaGlzIGNvdmVycyB0aGUgaW5zaWRlIG9mIGF0dHJpYnV0ZXMgYW5kIGV4cHJlc3Npb25zLCBhcyB3ZWxsIGFzIHRoZSBjYWxsZWVcbiAgICAvLyBvZiBjYWxsIG5vZGVzXG4gICAgY2FzZSAnUGF0aCc6XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICBjYXNlICdBcHBlbmRDb250ZW50JzpcbiAgICAgIHJldHVybiBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUudmFsdWUpO1xuICAgIGNhc2UgJ0NhbGwnOlxuICAgIGNhc2UgJ0ludm9rZUJsb2NrJzpcbiAgICBjYXNlICdFbGVtZW50TW9kaWZpZXInOlxuICAgICAgcmV0dXJuIG5vZGUuY2FsbGVlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgS2V5d29yZHM8SyBleHRlbmRzIEtleXdvcmRUeXBlLCBLZXl3b3JkTGlzdCBleHRlbmRzIEtleXdvcmQ8Sz4gPSBuZXZlcj5cbiAgaW1wbGVtZW50cyBLZXl3b3JkPEssIE91dEZvcjxLZXl3b3JkTGlzdD4+IHtcbiAgX2tleXdvcmRzOiBLZXl3b3JkW10gPSBbXTtcbiAgX3R5cGU6IEs7XG5cbiAgY29uc3RydWN0b3IodHlwZTogSykge1xuICAgIHRoaXMuX3R5cGUgPSB0eXBlO1xuICB9XG5cbiAga3c8UyBleHRlbmRzIHN0cmluZyA9IHN0cmluZywgT3V0ID0gdW5rbm93bj4oXG4gICAgbmFtZTogUyxcbiAgICBkZWxlZ2F0ZTogS2V5d29yZERlbGVnYXRlPEtleXdvcmRNYXRjaGVzW0tdLCB1bmtub3duLCBPdXQ+XG4gICk6IEtleXdvcmRzPEssIEtleXdvcmRMaXN0IHwgS2V5d29yZDxLLCBPdXQ+PiB7XG4gICAgdGhpcy5fa2V5d29yZHMucHVzaChrZXl3b3JkKG5hbWUsIHRoaXMuX3R5cGUsIGRlbGVnYXRlKSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHRyYW5zbGF0ZShcbiAgICBub2RlOiBLZXl3b3JkQ2FuZGlkYXRlc1tLXSxcbiAgICBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlXG4gICk6IFJlc3VsdDxPdXRGb3I8S2V5d29yZExpc3Q+PiB8IG51bGwge1xuICAgIGZvciAobGV0IGtleXdvcmQgb2YgdGhpcy5fa2V5d29yZHMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBrZXl3b3JkLnRyYW5zbGF0ZShub2RlLCBzdGF0ZSkgYXMgUmVzdWx0PE91dEZvcjxLZXl3b3JkTGlzdD4+O1xuICAgICAgaWYgKHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBwYXRoID0gZ2V0Q2FsbGVlRXhwcmVzc2lvbihub2RlKTtcblxuICAgIGlmIChwYXRoICYmIHBhdGgudHlwZSA9PT0gJ1BhdGgnICYmIHBhdGgucmVmLnR5cGUgPT09ICdGcmVlJyAmJiBpc0tleXdvcmQocGF0aC5yZWYubmFtZSkpIHtcbiAgICAgIGxldCB7IG5hbWUgfSA9IHBhdGgucmVmO1xuXG4gICAgICBsZXQgdXNlZFR5cGUgPSB0aGlzLl90eXBlO1xuICAgICAgbGV0IHZhbGlkVHlwZXMgPSBLRVlXT1JEU19UWVBFU1tuYW1lXTtcblxuICAgICAgaWYgKHZhbGlkVHlwZXMuaW5kZXhPZih1c2VkVHlwZSkgPT09IC0xKSB7XG4gICAgICAgIHJldHVybiBFcnIoXG4gICAgICAgICAgZ2VuZXJhdGVTeW50YXhFcnJvcihcbiAgICAgICAgICAgIGBUaGUgXFxgJHtuYW1lfVxcYCBrZXl3b3JkIHdhcyB1c2VkIGluY29ycmVjdGx5LiBJdCB3YXMgdXNlZCBhcyAke1xuICAgICAgICAgICAgICB0eXBlc1RvUmVhZGFibGVOYW1lW3VzZWRUeXBlXVxuICAgICAgICAgICAgfSwgYnV0IGl0cyB2YWxpZCB1c2FnZXMgYXJlOlxcblxcbiR7Z2VuZXJhdGVUeXBlc01lc3NhZ2UoXG4gICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgIHZhbGlkVHlwZXNcbiAgICAgICAgICAgICl9XFxuXFxuRXJyb3IgY2F1c2VkIGJ5YCxcbiAgICAgICAgICAgIG5vZGUubG9jXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmNvbnN0IHR5cGVzVG9SZWFkYWJsZU5hbWUgPSB7XG4gIEFwcGVuZDogJ2FuIGFwcGVuZCBzdGF0ZW1lbnQnLFxuICBCbG9jazogJ2EgYmxvY2sgc3RhdGVtZW50JyxcbiAgQ2FsbDogJ2EgY2FsbCBleHByZXNzaW9uJyxcbiAgTW9kaWZpZXI6ICdhIG1vZGlmaWVyJyxcbn07XG5cbmZ1bmN0aW9uIGdlbmVyYXRlVHlwZXNNZXNzYWdlKG5hbWU6IHN0cmluZywgdHlwZXM6IEtleXdvcmRUeXBlW10pOiBzdHJpbmcge1xuICByZXR1cm4gdHlwZXNcbiAgICAubWFwKCh0eXBlKSA9PiB7XG4gICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnQXBwZW5kJzpcbiAgICAgICAgICByZXR1cm4gYC0gQXMgYW4gYXBwZW5kIHN0YXRlbWVudCwgYXMgaW46IHt7JHtuYW1lfX19YDtcbiAgICAgICAgY2FzZSAnQmxvY2snOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhIGJsb2NrIHN0YXRlbWVudCwgYXMgaW46IHt7IyR7bmFtZX19fXt7LyR7bmFtZX19fWA7XG4gICAgICAgIGNhc2UgJ0NhbGwnOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhbiBleHByZXNzaW9uLCBhcyBpbjogKCR7bmFtZX0pYDtcbiAgICAgICAgY2FzZSAnTW9kaWZpZXInOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhIG1vZGlmaWVyLCBhcyBpbjogPGRpdiB7eyR7bmFtZX19fT48L2Rpdj5gO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBleGhhdXN0ZWQodHlwZSk7XG4gICAgICB9XG4gICAgfSlcbiAgICAuam9pbignXFxuXFxuJyk7XG59XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBidWlsZHMga2V5d29yZCBkZWZpbml0aW9ucyBmb3IgYSBwYXJ0aWN1bGFyIHR5cGUgb2YgQVNUIG5vZGUgKGBLZXl3b3JkVHlwZWApLlxuICpcbiAqIFlvdSBjYW4gYnVpbGQga2V5d29yZCBkZWZpbml0aW9ucyBmb3I6XG4gKlxuICogLSBgRXhwcmA6IEEgYFN1YkV4cHJlc3Npb25gIG9yIGBQYXRoRXhwcmVzc2lvbmBcbiAqIC0gYEJsb2NrYDogQSBgQmxvY2tTdGF0ZW1lbnRgXG4gKiAgIC0gQSBgQmxvY2tTdGF0ZW1lbnRgIGlzIGEga2V5d29yZCBjYW5kaWRhdGUgaWYgaXRzIGhlYWQgaXMgYVxuICogICAgIGBQYXRoRXhwcmVzc2lvbmBcbiAqIC0gYEFwcGVuZGA6IEFuIGBBcHBlbmRTdGF0ZW1lbnRgXG4gKlxuICogQSBub2RlIGlzIGEga2V5d29yZCBjYW5kaWRhdGUgaWY6XG4gKlxuICogLSBBIGBQYXRoRXhwcmVzc2lvbmAgaXMgYSBrZXl3b3JkIGNhbmRpZGF0ZSBpZiBpdCBoYXMgbm8gdGFpbCwgYW5kIGl0c1xuICogICBoZWFkIGV4cHJlc3Npb24gaXMgYSBgTG9jYWxWYXJIZWFkYCBvciBgRnJlZVZhckhlYWRgIHdob3NlIG5hbWUgaXNcbiAqICAgdGhlIGtleXdvcmQncyBuYW1lLlxuICogLSBBIGBTdWJFeHByZXNzaW9uYCwgYEFwcGVuZFN0YXRlbWVudGAsIG9yIGBCbG9ja1N0YXRlbWVudGAgaXMgYSBrZXl3b3JkXG4gKiAgIGNhbmRpZGF0ZSBpZiBpdHMgaGVhZCBpcyBhIGtleXdvcmQgY2FuZGlkYXRlLlxuICpcbiAqIFRoZSBrZXl3b3JkIGluZnJhc3RydWN0dXJlIGd1YXJhbnRlZXMgdGhhdDpcbiAqXG4gKiAtIElmIGEgbm9kZSBpcyBub3QgYSBrZXl3b3JkIGNhbmRpZGF0ZSwgaXQgaXMgbmV2ZXIgcGFzc2VkIHRvIGFueSBrZXl3b3JkJ3NcbiAqICAgYGFzc2VydGAgbWV0aG9kLlxuICogLSBJZiBhIG5vZGUgaXMgbm90IHRoZSBgS2V5d29yZFR5cGVgIGZvciBhIHBhcnRpY3VsYXIga2V5d29yZCwgaXQgd2lsbCBub3RcbiAqICAgYmUgcGFzc2VkIHRvIHRoZSBrZXl3b3JkJ3MgYGFzc2VydGAgbWV0aG9kLlxuICpcbiAqIGBFeHByYCBrZXl3b3JkcyBhcmUgdXNlZCBpbiBleHByZXNzaW9uIHBvc2l0aW9ucyBhbmQgc2hvdWxkIHJldHVybiBISVJcbiAqIGV4cHJlc3Npb25zLiBgQmxvY2tgIGFuZCBgQXBwZW5kYCBrZXl3b3JkcyBhcmUgdXNlZCBpbiBzdGF0ZW1lbnRcbiAqIHBvc2l0aW9ucyBhbmQgc2hvdWxkIHJldHVybiBISVIgc3RhdGVtZW50cy5cbiAqXG4gKiBBIGtleXdvcmQgZGVmaW5pdGlvbiBoYXMgdHdvIHBhcnRzOlxuICpcbiAqIC0gYG1hdGNoYCwgd2hpY2ggZGV0ZXJtaW5lcyB3aGV0aGVyIGFuIEFTVCBub2RlIG1hdGNoZXMgdGhlIGtleXdvcmQsIGFuZCBjYW5cbiAqICAgb3B0aW9uYWxseSByZXR1cm4gc29tZSBpbmZvcm1hdGlvbiBleHRyYWN0ZWQgZnJvbSB0aGUgQVNUIG5vZGUuXG4gKiAtIGB0cmFuc2xhdGVgLCB3aGljaCB0YWtlcyBhIG1hdGNoaW5nIEFTVCBub2RlIGFzIHdlbGwgYXMgdGhlIGV4dHJhY3RlZFxuICogICBpbmZvcm1hdGlvbiBhbmQgcmV0dXJucyBhbiBhcHByb3ByaWF0ZSBISVIgaW5zdHJ1Y3Rpb24uXG4gKlxuICogIyBFeGFtcGxlXG4gKlxuICogVGhpcyBrZXl3b3JkOlxuICpcbiAqIC0gdHVybnMgYChoZWxsbylgIGludG8gYFwiaGVsbG9cImBcbiAqICAgLSBhcyBsb25nIGFzIGBoZWxsb2AgaXMgbm90IGluIHNjb3BlXG4gKiAtIG1ha2VzIGl0IGFuIGVycm9yIHRvIHBhc3MgYW55IGFyZ3VtZW50cyAoc3VjaCBhcyBgKGhlbGxvIHdvcmxkKWApXG4gKlxuICogYGBgdHNcbiAqIGtleXdvcmRzKCdTdWJFeHByJykua3coJ2hlbGxvJywge1xuICogICBhc3NlcnQobm9kZTogRXhwcktleXdvcmROb2RlKTogUmVzdWx0PHZvaWQ+IHwgZmFsc2Uge1xuICogICAgIC8vIHdlIGRvbid0IHdhbnQgdG8gdHJhbnNmb3JtIGBoZWxsb2AgYXMgYSBgUGF0aEV4cHJlc3Npb25gXG4gKiAgICAgaWYgKG5vZGUudHlwZSAhPT0gJ1N1YkV4cHJlc3Npb24nKSB7XG4gKiAgICAgICByZXR1cm4gZmFsc2U7XG4gKiAgICAgfVxuICpcbiAqICAgICAvLyBub2RlLmhlYWQgd291bGQgYmUgYExvY2FsVmFySGVhZGAgaWYgYGhlbGxvYCB3YXMgaW4gc2NvcGVcbiAqICAgICBpZiAobm9kZS5oZWFkLnR5cGUgIT09ICdGcmVlVmFySGVhZCcpIHtcbiAqICAgICAgIHJldHVybiBmYWxzZTtcbiAqICAgICB9XG4gKlxuICogICAgIGlmIChub2RlLnBhcmFtcy5sZW5ndGggfHwgbm9kZS5oYXNoKSB7XG4gKiAgICAgICByZXR1cm4gRXJyKGdlbmVyYXRlU3ludGF4RXJyb3IoYChoZWxsbykgZG9lcyBub3QgdGFrZSBhbnkgYXJndW1lbnRzYCksIG5vZGUubG9jKTtcbiAqICAgICB9IGVsc2Uge1xuICogICAgICAgcmV0dXJuIE9rKCk7XG4gKiAgICAgfVxuICogICB9LFxuICpcbiAqICAgdHJhbnNsYXRlKG5vZGU6IEFTVHYyLlN1YkV4cHJlc3Npb24pOiBoaXIuRXhwcmVzc2lvbiB7XG4gKiAgICAgcmV0dXJuIEFTVHYyLmJ1aWxkZXJzLmxpdGVyYWwoXCJoZWxsb1wiLCBub2RlLmxvYylcbiAqICAgfVxuICogfSlcbiAqIGBgYFxuICpcbiAqIFRoZSBrZXl3b3JkIGluZnJhc3RydWN0dXJlIGNoZWNrcyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgbm9kZSBpcyB0aGUgcmlnaHRcbiAqIHR5cGUgYmVmb3JlIGNhbGxpbmcgYGFzc2VydGAsIHNvIHlvdSBvbmx5IG5lZWQgdG8gY29uc2lkZXIgYFN1YkV4cHJlc3Npb25gXG4gKiBhbmQgYFBhdGhFeHByZXNzaW9uYCBoZXJlLiBJdCBhbHNvIGNoZWNrcyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgbm9kZSBwYXNzZWRcbiAqIHRvIGBhc3NlcnRgIGhhcyB0aGUga2V5d29yZCBuYW1lIGluIHRoZSByaWdodCBwbGFjZS5cbiAqXG4gKiBOb3RlIHRoZSBpbXBvcnRhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHJldHVybmluZyBgZmFsc2VgIGZyb20gYGFzc2VydGAsXG4gKiB3aGljaCBqdXN0IG1lYW5zIHRoYXQgdGhlIG5vZGUgZGlkbid0IG1hdGNoLCBhbmQgcmV0dXJuaW5nIGBFcnJgLCB3aGljaFxuICogbWVhbnMgdGhhdCB0aGUgbm9kZSBtYXRjaGVkLCBidXQgdGhlcmUgd2FzIGEga2V5d29yZC1zcGVjaWZpYyBzeW50YXhcbiAqIGVycm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24ga2V5d29yZHM8SyBleHRlbmRzIEtleXdvcmRUeXBlPih0eXBlOiBLKTogS2V5d29yZHM8Sz4ge1xuICByZXR1cm4gbmV3IEtleXdvcmRzKHR5cGUpO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==