UNPKG

@glimmer/compiler

Version:
259 lines (219 loc) 27.8 kB
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL2NvbXBpbGVyL2xpYi9wYXNzZXMvMS1ub3JtYWxpemF0aW9uL2tleXdvcmRzL2ltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsU0FBQSxtQkFBQSxFQUFBLFNBQUEsRUFBQSxjQUFBLFFBQUEsaUJBQUE7QUFPQSxTQUFBLFNBQUEsUUFBQSxlQUFBO0FBRUEsU0FBQSxHQUFBLFFBQUEsd0JBQUE7O0lBZ0JBLFc7QUFRRSx1QkFBQSxPQUFBLEVBQUEsSUFBQSxFQUFBLFFBQUEsRUFHa0U7QUFGdEQsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUVGLFNBQUEsUUFBQSxHQUFBLFFBQUE7QUFFUixRQUFJLEtBQUssR0FBRyxJQUFaLEdBQVksRUFBWjs7QUFDQSx5REFBcUIsYUFBYSxDQUFsQyxJQUFrQyxDQUFsQyx3Q0FBMEM7QUFBQSxVQUExQyxRQUEwQztBQUN4QyxNQUFBLEtBQUssQ0FBTCxHQUFBLENBQUEsUUFBQTtBQUNEOztBQUVELFNBQUEsS0FBQSxHQUFBLEtBQUE7QUFDRDs7OztTQUVTLEssR0FBQSxlQUFLLElBQUwsRUFBZ0M7QUFDeEMsUUFBSSxDQUFDLEtBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBZSxJQUFJLENBQXhCLElBQUssQ0FBTCxFQUFnQztBQUM5QixhQUFBLEtBQUE7QUFDRDs7QUFFRCxRQUFJLElBQUksR0FBRyxtQkFBbUIsQ0FBOUIsSUFBOEIsQ0FBOUI7O0FBRUEsUUFBSSxJQUFJLEtBQUosSUFBQSxJQUFpQixJQUFJLENBQUosSUFBQSxLQUFqQixNQUFBLElBQXlDLElBQUksQ0FBSixHQUFBLENBQUEsSUFBQSxLQUE3QyxNQUFBLEVBQXVFO0FBQ3JFLFVBQUksSUFBSSxDQUFKLElBQUEsQ0FBQSxNQUFBLEdBQUosQ0FBQSxFQUEwQjtBQUN4QixZQUFJLElBQUksQ0FBSixHQUFBLENBQUEsVUFBQSxDQUFBLFNBQUEsT0FBSixPQUFBLEVBQWlE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QUNGLFdBQUEsTUFBQTtBQUNFLGdEQUFBLElBQUE7O0FBQ0YsV0FBQSxVQUFBO0FBQ0UsbURBQUEsSUFBQTs7QUFDRjtBQUNFLGVBQU8sU0FBUyxDQUFoQixJQUFnQixDQUFoQjtBQVZKO0FBRkcsR0FBQSxFQUFBLElBQUEsQ0FBUCxNQUFPLENBQVA7QUFnQkQ7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFpRkEsT0FBTSxTQUFBLFFBQUEsQ0FBQSxJQUFBLEVBQWlEO0FBQ3JELFNBQU8sSUFBQSxRQUFBLENBQVAsSUFBTyxDQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBU1R2MixcbiAgZ2VuZXJhdGVTeW50YXhFcnJvcixcbiAgaXNLZXl3b3JkLFxuICBLRVlXT1JEU19UWVBFUyxcbiAgS2V5d29yZFR5cGUsXG59IGZyb20gJ0BnbGltbWVyL3N5bnRheCc7XG5pbXBvcnQgeyBleGhhdXN0ZWQgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcblxuaW1wb3J0IHsgRXJyLCBSZXN1bHQgfSBmcm9tICcuLi8uLi8uLi9zaGFyZWQvcmVzdWx0JztcbmltcG9ydCB7IE5vcm1hbGl6YXRpb25TdGF0ZSB9IGZyb20gJy4uL2NvbnRleHQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmREZWxlZ2F0ZTxNYXRjaCBleHRlbmRzIEtleXdvcmRNYXRjaCwgViwgT3V0PiB7XG4gIGFzc2VydChvcHRpb25zOiBNYXRjaCwgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSk6IFJlc3VsdDxWPjtcbiAgdHJhbnNsYXRlKG9wdGlvbnM6IHsgbm9kZTogTWF0Y2g7IHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGUgfSwgcGFyYW06IFYpOiBSZXN1bHQ8T3V0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBLZXl3b3JkPEsgZXh0ZW5kcyBLZXl3b3JkVHlwZSA9IEtleXdvcmRUeXBlLCBPdXQgPSB1bmtub3duPiB7XG4gIHRyYW5zbGF0ZShub2RlOiBLZXl3b3JkQ2FuZGlkYXRlc1tLXSwgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSk6IFJlc3VsdDxPdXQ+IHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCbG9ja0tleXdvcmQ8T3V0ID0gdW5rbm93bj4ge1xuICB0cmFuc2xhdGUobm9kZTogQVNUdjIuSW52b2tlQmxvY2ssIHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGUpOiBSZXN1bHQ8T3V0PiB8IG51bGw7XG59XG5cbmNsYXNzIEtleXdvcmRJbXBsPFxuICBLIGV4dGVuZHMgS2V5d29yZFR5cGUsXG4gIFMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFBhcmFtID0gdW5rbm93bixcbiAgT3V0ID0gdW5rbm93blxuPiB7XG4gIHByb3RlY3RlZCB0eXBlczogU2V0PEtleXdvcmRDYW5kaWRhdGVzW0tdWyd0eXBlJ10+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBrZXl3b3JkOiBTLFxuICAgIHR5cGU6IEtleXdvcmRUeXBlLFxuICAgIHByaXZhdGUgZGVsZWdhdGU6IEtleXdvcmREZWxlZ2F0ZTxLZXl3b3JkTWF0Y2hlc1tLXSwgUGFyYW0sIE91dD5cbiAgKSB7XG4gICAgbGV0IG5vZGVzID0gbmV3IFNldDxLZXl3b3JkTm9kZVsndHlwZSddPigpO1xuICAgIGZvciAobGV0IG5vZGVUeXBlIG9mIEtFWVdPUkRfTk9ERVNbdHlwZV0pIHtcbiAgICAgIG5vZGVzLmFkZChub2RlVHlwZSk7XG4gICAgfVxuXG4gICAgdGhpcy50eXBlcyA9IG5vZGVzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1hdGNoKG5vZGU6IEtleXdvcmRDYW5kaWRhdGVzW0tdKTogbm9kZSBpcyBLZXl3b3JkTWF0Y2hlc1tLXSB7XG4gICAgaWYgKCF0aGlzLnR5cGVzLmhhcyhub2RlLnR5cGUpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbGV0IHBhdGggPSBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUpO1xuXG4gICAgaWYgKHBhdGggIT09IG51bGwgJiYgcGF0aC50eXBlID09PSAnUGF0aCcgJiYgcGF0aC5yZWYudHlwZSA9PT0gJ0ZyZWUnKSB7XG4gICAgICBpZiAocGF0aC50YWlsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKHBhdGgucmVmLnJlc29sdXRpb24uc2VyaWFsaXplKCkgPT09ICdMb29zZScpIHtcbiAgICAgICAgICAvLyBjYW5ub3QgYmUgYSBrZXl3b3JkIHJlZmVyZW5jZSwga2V5d29yZHMgZG8gbm90IGFsbG93IHBhdGhzIChtdXN0IGJlXG4gICAgICAgICAgLy8gcmVseWluZyBvbiBpbXBsaWNpdCB0aGlzIGZhbGxiYWNrKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGF0aC5yZWYubmFtZSA9PT0gdGhpcy5rZXl3b3JkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgdHJhbnNsYXRlKG5vZGU6IEtleXdvcmRNYXRjaGVzW0tdLCBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlKTogUmVzdWx0PE91dD4gfCBudWxsIHtcbiAgICBpZiAodGhpcy5tYXRjaChub2RlKSkge1xuICAgICAgbGV0IHBhdGggPSBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUpO1xuXG4gICAgICBpZiAocGF0aCAhPT0gbnVsbCAmJiBwYXRoLnR5cGUgPT09ICdQYXRoJyAmJiBwYXRoLnRhaWwubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gRXJyKFxuICAgICAgICAgIGdlbmVyYXRlU3ludGF4RXJyb3IoXG4gICAgICAgICAgICBgVGhlIFxcYCR7XG4gICAgICAgICAgICAgIHRoaXMua2V5d29yZFxuICAgICAgICAgICAgfVxcYCBrZXl3b3JkIHdhcyB1c2VkIGluY29ycmVjdGx5LiBJdCB3YXMgdXNlZCBhcyBcXGAke3BhdGgubG9jLmFzU3RyaW5nKCl9XFxgLCBidXQgaXQgY2Fubm90IGJlIHVzZWQgd2l0aCBhZGRpdGlvbmFsIHBhdGggc2VnbWVudHMuIFxcblxcbkVycm9yIGNhdXNlZCBieWAsXG4gICAgICAgICAgICBub2RlLmxvY1xuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgbGV0IHBhcmFtID0gdGhpcy5kZWxlZ2F0ZS5hc3NlcnQobm9kZSwgc3RhdGUpO1xuICAgICAgcmV0dXJuIHBhcmFtLmFuZFRoZW4oKHBhcmFtKSA9PiB0aGlzLmRlbGVnYXRlLnRyYW5zbGF0ZSh7IG5vZGUsIHN0YXRlIH0sIHBhcmFtKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgdHlwZSBQb3NzaWJsZU5vZGUgPVxuICB8IEFTVHYyLlBhdGhFeHByZXNzaW9uXG4gIHwgQVNUdjIuQXBwZW5kQ29udGVudFxuICB8IEFTVHYyLkNhbGxFeHByZXNzaW9uXG4gIHwgQVNUdjIuSW52b2tlQmxvY2s7XG5cbmV4cG9ydCBjb25zdCBLRVlXT1JEX05PREVTID0ge1xuICBDYWxsOiBbJ0NhbGwnXSxcbiAgQmxvY2s6IFsnSW52b2tlQmxvY2snXSxcbiAgQXBwZW5kOiBbJ0FwcGVuZENvbnRlbnQnXSxcbiAgTW9kaWZpZXI6IFsnRWxlbWVudE1vZGlmaWVyJ10sXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmRDYW5kaWRhdGVzIHtcbiAgQ2FsbDogQVNUdjIuRXhwcmVzc2lvbk5vZGU7XG4gIEJsb2NrOiBBU1R2Mi5JbnZva2VCbG9jaztcbiAgQXBwZW5kOiBBU1R2Mi5BcHBlbmRDb250ZW50O1xuICBNb2RpZmllcjogQVNUdjIuRWxlbWVudE1vZGlmaWVyO1xufVxuXG5leHBvcnQgdHlwZSBLZXl3b3JkQ2FuZGlkYXRlID0gS2V5d29yZENhbmRpZGF0ZXNba2V5b2YgS2V5d29yZENhbmRpZGF0ZXNdO1xuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmRNYXRjaGVzIHtcbiAgQ2FsbDogQVNUdjIuQ2FsbEV4cHJlc3Npb247XG4gIEJsb2NrOiBBU1R2Mi5JbnZva2VCbG9jaztcbiAgQXBwZW5kOiBBU1R2Mi5BcHBlbmRDb250ZW50O1xuICBNb2RpZmllcjogQVNUdjIuRWxlbWVudE1vZGlmaWVyO1xufVxuXG5leHBvcnQgdHlwZSBLZXl3b3JkTWF0Y2ggPSBLZXl3b3JkTWF0Y2hlc1trZXlvZiBLZXl3b3JkTWF0Y2hlc107XG5cbi8qKlxuICogQSBcImdlbmVyaWNcIiBrZXl3b3JkIGlzIHNvbWV0aGluZyBsaWtlIGBoYXMtYmxvY2tgLCB3aGljaCBtYWtlcyBzZW5zZSBpbiB0aGUgY29udGV4dFxuICogb2Ygc3ViLWV4cHJlc3Npb24gb3IgYXBwZW5kXG4gKi9cbmV4cG9ydCB0eXBlIEdlbmVyaWNLZXl3b3JkTm9kZSA9IEFTVHYyLkFwcGVuZENvbnRlbnQgfCBBU1R2Mi5DYWxsRXhwcmVzc2lvbjtcblxuZXhwb3J0IHR5cGUgS2V5d29yZE5vZGUgPVxuICB8IEdlbmVyaWNLZXl3b3JkTm9kZVxuICB8IEFTVHYyLkNhbGxFeHByZXNzaW9uXG4gIHwgQVNUdjIuSW52b2tlQmxvY2tcbiAgfCBBU1R2Mi5FbGVtZW50TW9kaWZpZXI7XG5cbmV4cG9ydCBmdW5jdGlvbiBrZXl3b3JkPFxuICBLIGV4dGVuZHMgS2V5d29yZFR5cGUsXG4gIEQgZXh0ZW5kcyBLZXl3b3JkRGVsZWdhdGU8S2V5d29yZE1hdGNoZXNbS10sIHVua25vd24sIE91dD4sXG4gIE91dCA9IHVua25vd25cbj4oa2V5d29yZDogc3RyaW5nLCB0eXBlOiBLLCBkZWxlZ2F0ZTogRCk6IEtleXdvcmQ8SywgT3V0PiB7XG4gIHJldHVybiBuZXcgS2V5d29yZEltcGwoa2V5d29yZCwgdHlwZSwgZGVsZWdhdGUgYXMgS2V5d29yZERlbGVnYXRlPEtleXdvcmRNYXRjaCwgdW5rbm93biwgT3V0Pik7XG59XG5cbmV4cG9ydCB0eXBlIFBvc3NpYmxlS2V5d29yZCA9IEtleXdvcmROb2RlO1xudHlwZSBPdXRGb3I8SyBleHRlbmRzIEtleXdvcmQgfCBCbG9ja0tleXdvcmQ+ID0gSyBleHRlbmRzIEJsb2NrS2V5d29yZDxpbmZlciBPdXQ+XG4gID8gT3V0XG4gIDogSyBleHRlbmRzIEtleXdvcmQ8S2V5d29yZFR5cGUsIGluZmVyIE91dD5cbiAgPyBPdXRcbiAgOiBuZXZlcjtcblxuZnVuY3Rpb24gZ2V0Q2FsbGVlRXhwcmVzc2lvbihcbiAgbm9kZTogS2V5d29yZE5vZGUgfCBBU1R2Mi5FeHByZXNzaW9uTm9kZVxuKTogQVNUdjIuRXhwcmVzc2lvbk5vZGUgfCBudWxsIHtcbiAgc3dpdGNoIChub2RlLnR5cGUpIHtcbiAgICAvLyBUaGlzIGNvdmVycyB0aGUgaW5zaWRlIG9mIGF0dHJpYnV0ZXMgYW5kIGV4cHJlc3Npb25zLCBhcyB3ZWxsIGFzIHRoZSBjYWxsZWVcbiAgICAvLyBvZiBjYWxsIG5vZGVzXG4gICAgY2FzZSAnUGF0aCc6XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICBjYXNlICdBcHBlbmRDb250ZW50JzpcbiAgICAgIHJldHVybiBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUudmFsdWUpO1xuICAgIGNhc2UgJ0NhbGwnOlxuICAgIGNhc2UgJ0ludm9rZUJsb2NrJzpcbiAgICBjYXNlICdFbGVtZW50TW9kaWZpZXInOlxuICAgICAgcmV0dXJuIG5vZGUuY2FsbGVlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgS2V5d29yZHM8SyBleHRlbmRzIEtleXdvcmRUeXBlLCBLZXl3b3JkTGlzdCBleHRlbmRzIEtleXdvcmQ8Sz4gPSBuZXZlcj5cbiAgaW1wbGVtZW50cyBLZXl3b3JkPEssIE91dEZvcjxLZXl3b3JkTGlzdD4+IHtcbiAgX2tleXdvcmRzOiBLZXl3b3JkW10gPSBbXTtcbiAgX3R5cGU6IEs7XG5cbiAgY29uc3RydWN0b3IodHlwZTogSykge1xuICAgIHRoaXMuX3R5cGUgPSB0eXBlO1xuICB9XG5cbiAga3c8UyBleHRlbmRzIHN0cmluZyA9IHN0cmluZywgT3V0ID0gdW5rbm93bj4oXG4gICAgbmFtZTogUyxcbiAgICBkZWxlZ2F0ZTogS2V5d29yZERlbGVnYXRlPEtleXdvcmRNYXRjaGVzW0tdLCB1bmtub3duLCBPdXQ+XG4gICk6IEtleXdvcmRzPEssIEtleXdvcmRMaXN0IHwgS2V5d29yZDxLLCBPdXQ+PiB7XG4gICAgdGhpcy5fa2V5d29yZHMucHVzaChrZXl3b3JkKG5hbWUsIHRoaXMuX3R5cGUsIGRlbGVnYXRlKSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHRyYW5zbGF0ZShcbiAgICBub2RlOiBLZXl3b3JkQ2FuZGlkYXRlc1tLXSxcbiAgICBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlXG4gICk6IFJlc3VsdDxPdXRGb3I8S2V5d29yZExpc3Q+PiB8IG51bGwge1xuICAgIGZvciAobGV0IGtleXdvcmQgb2YgdGhpcy5fa2V5d29yZHMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBrZXl3b3JkLnRyYW5zbGF0ZShub2RlLCBzdGF0ZSkgYXMgUmVzdWx0PE91dEZvcjxLZXl3b3JkTGlzdD4+O1xuICAgICAgaWYgKHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBwYXRoID0gZ2V0Q2FsbGVlRXhwcmVzc2lvbihub2RlKTtcblxuICAgIGlmIChwYXRoICYmIHBhdGgudHlwZSA9PT0gJ1BhdGgnICYmIHBhdGgucmVmLnR5cGUgPT09ICdGcmVlJyAmJiBpc0tleXdvcmQocGF0aC5yZWYubmFtZSkpIHtcbiAgICAgIGxldCB7IG5hbWUgfSA9IHBhdGgucmVmO1xuXG4gICAgICBsZXQgdXNlZFR5cGUgPSB0aGlzLl90eXBlO1xuICAgICAgbGV0IHZhbGlkVHlwZXMgPSBLRVlXT1JEU19UWVBFU1tuYW1lXTtcblxuICAgICAgaWYgKHZhbGlkVHlwZXMuaW5kZXhPZih1c2VkVHlwZSkgPT09IC0xKSB7XG4gICAgICAgIHJldHVybiBFcnIoXG4gICAgICAgICAgZ2VuZXJhdGVTeW50YXhFcnJvcihcbiAgICAgICAgICAgIGBUaGUgXFxgJHtuYW1lfVxcYCBrZXl3b3JkIHdhcyB1c2VkIGluY29ycmVjdGx5LiBJdCB3YXMgdXNlZCBhcyAke1xuICAgICAgICAgICAgICB0eXBlc1RvUmVhZGFibGVOYW1lW3VzZWRUeXBlXVxuICAgICAgICAgICAgfSwgYnV0IGl0cyB2YWxpZCB1c2FnZXMgYXJlOlxcblxcbiR7Z2VuZXJhdGVUeXBlc01lc3NhZ2UoXG4gICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgIHZhbGlkVHlwZXNcbiAgICAgICAgICAgICl9XFxuXFxuRXJyb3IgY2F1c2VkIGJ5YCxcbiAgICAgICAgICAgIG5vZGUubG9jXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmNvbnN0IHR5cGVzVG9SZWFkYWJsZU5hbWUgPSB7XG4gIEFwcGVuZDogJ2FuIGFwcGVuZCBzdGF0ZW1lbnQnLFxuICBCbG9jazogJ2EgYmxvY2sgc3RhdGVtZW50JyxcbiAgQ2FsbDogJ2EgY2FsbCBleHByZXNzaW9uJyxcbiAgTW9kaWZpZXI6ICdhIG1vZGlmaWVyJyxcbn07XG5cbmZ1bmN0aW9uIGdlbmVyYXRlVHlwZXNNZXNzYWdlKG5hbWU6IHN0cmluZywgdHlwZXM6IEtleXdvcmRUeXBlW10pOiBzdHJpbmcge1xuICByZXR1cm4gdHlwZXNcbiAgICAubWFwKCh0eXBlKSA9PiB7XG4gICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnQXBwZW5kJzpcbiAgICAgICAgICByZXR1cm4gYC0gQXMgYW4gYXBwZW5kIHN0YXRlbWVudCwgYXMgaW46IHt7JHtuYW1lfX19YDtcbiAgICAgICAgY2FzZSAnQmxvY2snOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhIGJsb2NrIHN0YXRlbWVudCwgYXMgaW46IHt7IyR7bmFtZX19fXt7LyR7bmFtZX19fWA7XG4gICAgICAgIGNhc2UgJ0NhbGwnOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhbiBleHByZXNzaW9uLCBhcyBpbjogKCR7bmFtZX0pYDtcbiAgICAgICAgY2FzZSAnTW9kaWZpZXInOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhIG1vZGlmaWVyLCBhcyBpbjogPGRpdiB7eyR7bmFtZX19fT48L2Rpdj5gO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBleGhhdXN0ZWQodHlwZSk7XG4gICAgICB9XG4gICAgfSlcbiAgICAuam9pbignXFxuXFxuJyk7XG59XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBidWlsZHMga2V5d29yZCBkZWZpbml0aW9ucyBmb3IgYSBwYXJ0aWN1bGFyIHR5cGUgb2YgQVNUIG5vZGUgKGBLZXl3b3JkVHlwZWApLlxuICpcbiAqIFlvdSBjYW4gYnVpbGQga2V5d29yZCBkZWZpbml0aW9ucyBmb3I6XG4gKlxuICogLSBgRXhwcmA6IEEgYFN1YkV4cHJlc3Npb25gIG9yIGBQYXRoRXhwcmVzc2lvbmBcbiAqIC0gYEJsb2NrYDogQSBgQmxvY2tTdGF0ZW1lbnRgXG4gKiAgIC0gQSBgQmxvY2tTdGF0ZW1lbnRgIGlzIGEga2V5d29yZCBjYW5kaWRhdGUgaWYgaXRzIGhlYWQgaXMgYVxuICogICAgIGBQYXRoRXhwcmVzc2lvbmBcbiAqIC0gYEFwcGVuZGA6IEFuIGBBcHBlbmRTdGF0ZW1lbnRgXG4gKlxuICogQSBub2RlIGlzIGEga2V5d29yZCBjYW5kaWRhdGUgaWY6XG4gKlxuICogLSBBIGBQYXRoRXhwcmVzc2lvbmAgaXMgYSBrZXl3b3JkIGNhbmRpZGF0ZSBpZiBpdCBoYXMgbm8gdGFpbCwgYW5kIGl0c1xuICogICBoZWFkIGV4cHJlc3Npb24gaXMgYSBgTG9jYWxWYXJIZWFkYCBvciBgRnJlZVZhckhlYWRgIHdob3NlIG5hbWUgaXNcbiAqICAgdGhlIGtleXdvcmQncyBuYW1lLlxuICogLSBBIGBTdWJFeHByZXNzaW9uYCwgYEFwcGVuZFN0YXRlbWVudGAsIG9yIGBCbG9ja1N0YXRlbWVudGAgaXMgYSBrZXl3b3JkXG4gKiAgIGNhbmRpZGF0ZSBpZiBpdHMgaGVhZCBpcyBhIGtleXdvcmQgY2FuZGlkYXRlLlxuICpcbiAqIFRoZSBrZXl3b3JkIGluZnJhc3RydWN0dXJlIGd1YXJhbnRlZXMgdGhhdDpcbiAqXG4gKiAtIElmIGEgbm9kZSBpcyBub3QgYSBrZXl3b3JkIGNhbmRpZGF0ZSwgaXQgaXMgbmV2ZXIgcGFzc2VkIHRvIGFueSBrZXl3b3JkJ3NcbiAqICAgYGFzc2VydGAgbWV0aG9kLlxuICogLSBJZiBhIG5vZGUgaXMgbm90IHRoZSBgS2V5d29yZFR5cGVgIGZvciBhIHBhcnRpY3VsYXIga2V5d29yZCwgaXQgd2lsbCBub3RcbiAqICAgYmUgcGFzc2VkIHRvIHRoZSBrZXl3b3JkJ3MgYGFzc2VydGAgbWV0aG9kLlxuICpcbiAqIGBFeHByYCBrZXl3b3JkcyBhcmUgdXNlZCBpbiBleHByZXNzaW9uIHBvc2l0aW9ucyBhbmQgc2hvdWxkIHJldHVybiBISVJcbiAqIGV4cHJlc3Npb25zLiBgQmxvY2tgIGFuZCBgQXBwZW5kYCBrZXl3b3JkcyBhcmUgdXNlZCBpbiBzdGF0ZW1lbnRcbiAqIHBvc2l0aW9ucyBhbmQgc2hvdWxkIHJldHVybiBISVIgc3RhdGVtZW50cy5cbiAqXG4gKiBBIGtleXdvcmQgZGVmaW5pdGlvbiBoYXMgdHdvIHBhcnRzOlxuICpcbiAqIC0gYG1hdGNoYCwgd2hpY2ggZGV0ZXJtaW5lcyB3aGV0aGVyIGFuIEFTVCBub2RlIG1hdGNoZXMgdGhlIGtleXdvcmQsIGFuZCBjYW5cbiAqICAgb3B0aW9uYWxseSByZXR1cm4gc29tZSBpbmZvcm1hdGlvbiBleHRyYWN0ZWQgZnJvbSB0aGUgQVNUIG5vZGUuXG4gKiAtIGB0cmFuc2xhdGVgLCB3aGljaCB0YWtlcyBhIG1hdGNoaW5nIEFTVCBub2RlIGFzIHdlbGwgYXMgdGhlIGV4dHJhY3RlZFxuICogICBpbmZvcm1hdGlvbiBhbmQgcmV0dXJucyBhbiBhcHByb3ByaWF0ZSBISVIgaW5zdHJ1Y3Rpb24uXG4gKlxuICogIyBFeGFtcGxlXG4gKlxuICogVGhpcyBrZXl3b3JkOlxuICpcbiAqIC0gdHVybnMgYChoZWxsbylgIGludG8gYFwiaGVsbG9cImBcbiAqICAgLSBhcyBsb25nIGFzIGBoZWxsb2AgaXMgbm90IGluIHNjb3BlXG4gKiAtIG1ha2VzIGl0IGFuIGVycm9yIHRvIHBhc3MgYW55IGFyZ3VtZW50cyAoc3VjaCBhcyBgKGhlbGxvIHdvcmxkKWApXG4gKlxuICogYGBgdHNcbiAqIGtleXdvcmRzKCdTdWJFeHByJykua3coJ2hlbGxvJywge1xuICogICBhc3NlcnQobm9kZTogRXhwcktleXdvcmROb2RlKTogUmVzdWx0PHZvaWQ+IHwgZmFsc2Uge1xuICogICAgIC8vIHdlIGRvbid0IHdhbnQgdG8gdHJhbnNmb3JtIGBoZWxsb2AgYXMgYSBgUGF0aEV4cHJlc3Npb25gXG4gKiAgICAgaWYgKG5vZGUudHlwZSAhPT0gJ1N1YkV4cHJlc3Npb24nKSB7XG4gKiAgICAgICByZXR1cm4gZmFsc2U7XG4gKiAgICAgfVxuICpcbiAqICAgICAvLyBub2RlLmhlYWQgd291bGQgYmUgYExvY2FsVmFySGVhZGAgaWYgYGhlbGxvYCB3YXMgaW4gc2NvcGVcbiAqICAgICBpZiAobm9kZS5oZWFkLnR5cGUgIT09ICdGcmVlVmFySGVhZCcpIHtcbiAqICAgICAgIHJldHVybiBmYWxzZTtcbiAqICAgICB9XG4gKlxuICogICAgIGlmIChub2RlLnBhcmFtcy5sZW5ndGggfHwgbm9kZS5oYXNoKSB7XG4gKiAgICAgICByZXR1cm4gRXJyKGdlbmVyYXRlU3ludGF4RXJyb3IoYChoZWxsbykgZG9lcyBub3QgdGFrZSBhbnkgYXJndW1lbnRzYCksIG5vZGUubG9jKTtcbiAqICAgICB9IGVsc2Uge1xuICogICAgICAgcmV0dXJuIE9rKCk7XG4gKiAgICAgfVxuICogICB9LFxuICpcbiAqICAgdHJhbnNsYXRlKG5vZGU6IEFTVHYyLlN1YkV4cHJlc3Npb24pOiBoaXIuRXhwcmVzc2lvbiB7XG4gKiAgICAgcmV0dXJuIEFTVHYyLmJ1aWxkZXJzLmxpdGVyYWwoXCJoZWxsb1wiLCBub2RlLmxvYylcbiAqICAgfVxuICogfSlcbiAqIGBgYFxuICpcbiAqIFRoZSBrZXl3b3JkIGluZnJhc3RydWN0dXJlIGNoZWNrcyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgbm9kZSBpcyB0aGUgcmlnaHRcbiAqIHR5cGUgYmVmb3JlIGNhbGxpbmcgYGFzc2VydGAsIHNvIHlvdSBvbmx5IG5lZWQgdG8gY29uc2lkZXIgYFN1YkV4cHJlc3Npb25gXG4gKiBhbmQgYFBhdGhFeHByZXNzaW9uYCBoZXJlLiBJdCBhbHNvIGNoZWNrcyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgbm9kZSBwYXNzZWRcbiAqIHRvIGBhc3NlcnRgIGhhcyB0aGUga2V5d29yZCBuYW1lIGluIHRoZSByaWdodCBwbGFjZS5cbiAqXG4gKiBOb3RlIHRoZSBpbXBvcnRhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHJldHVybmluZyBgZmFsc2VgIGZyb20gYGFzc2VydGAsXG4gKiB3aGljaCBqdXN0IG1lYW5zIHRoYXQgdGhlIG5vZGUgZGlkbid0IG1hdGNoLCBhbmQgcmV0dXJuaW5nIGBFcnJgLCB3aGljaFxuICogbWVhbnMgdGhhdCB0aGUgbm9kZSBtYXRjaGVkLCBidXQgdGhlcmUgd2FzIGEga2V5d29yZC1zcGVjaWZpYyBzeW50YXhcbiAqIGVycm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24ga2V5d29yZHM8SyBleHRlbmRzIEtleXdvcmRUeXBlPih0eXBlOiBLKTogS2V5d29yZHM8Sz4ge1xuICByZXR1cm4gbmV3IEtleXdvcmRzKHR5cGUpO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==