UNPKG

@glimmer/compiler

Version:
242 lines (209 loc) 26 kB
import { generateSyntaxError, isKeyword, KEYWORDS_TYPES } from '@glimmer/syntax'; import { exhausted } from '@glimmer/util'; import { Err } from '../../../shared/result'; class KeywordImpl { constructor(keyword, type, delegate) { this.keyword = keyword; this.delegate = delegate; let nodes = new Set(); for (let nodeType of KEYWORD_NODES[type]) { nodes.add(nodeType); } this.types = nodes; } match(node) { if (!this.types.has(node.type)) { return false; } let 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; } } translate(node, state) { if (this.match(node)) { let 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)); } let param = this.delegate.assert(node, state); return param.andThen(param => this.delegate.translate({ node, state }, param)); } else { return null; } } } export const 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 class Keywords { constructor(type) { this._keywords = []; this._type = type; } kw(name, delegate) { this._keywords.push(keyword(name, this._type, delegate)); return this; } translate(node, state) { for (let keyword of this._keywords) { let result = keyword.translate(node, state); if (result !== null) { return result; } } let path = getCalleeExpression(node); if (path && path.type === 'Path' && path.ref.type === 'Free' && isKeyword(path.ref.name)) { let { name } = path.ref; let usedType = this._type; let 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; } } const typesToReadableName = { Append: 'an append statement', Block: 'a block statement', Call: 'a call expression', Modifier: 'a modifier' }; function generateTypesMessage(name, types) { return types.map(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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL2NvbXBpbGVyL2xpYi9wYXNzZXMvMS1ub3JtYWxpemF0aW9uL2tleXdvcmRzL2ltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsU0FFRSxtQkFGRixFQUdFLFNBSEYsRUFJRSxjQUpGLFFBTU8saUJBTlA7QUFPQSxTQUFTLFNBQVQsUUFBMEIsZUFBMUI7QUFFQSxTQUFTLEdBQVQsUUFBNEIsd0JBQTVCOztBQWdCQSxNQUFNLFdBQU4sQ0FBaUI7QUFRZixFQUFBLFdBQUEsQ0FDWSxPQURaLEVBRUUsSUFGRixFQUdVLFFBSFYsRUFHa0U7QUFGdEQsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUVGLFNBQUEsUUFBQSxHQUFBLFFBQUE7QUFFUixRQUFJLEtBQUssR0FBRyxJQUFJLEdBQUosRUFBWjs7QUFDQSxTQUFLLElBQUksUUFBVCxJQUFxQixhQUFhLENBQUMsSUFBRCxDQUFsQyxFQUEwQztBQUN4QyxNQUFBLEtBQUssQ0FBQyxHQUFOLENBQVUsUUFBVjtBQUNEOztBQUVELFNBQUssS0FBTCxHQUFhLEtBQWI7QUFDRDs7QUFFUyxFQUFBLEtBQUssQ0FBQyxJQUFELEVBQTJCO0FBQ3hDLFFBQUksQ0FBQyxLQUFLLEtBQUwsQ0FBVyxHQUFYLENBQWUsSUFBSSxDQUFDLElBQXBCLENBQUwsRUFBZ0M7QUFDOUIsYUFBTyxLQUFQO0FBQ0Q7O0FBRUQsUUFBSSxJQUFJLEdBQUcsbUJBQW1CLENBQUMsSUFBRCxDQUE5Qjs7QUFFQSxRQUFJLElBQUksS0FBSyxJQUFULElBQWlCLElBQUksQ0FBQyxJQUFMLEtBQWMsTUFBL0IsSUFBeUMsSUFBSSxDQUFDLEdBQUwsQ0FBUyxJQUFULEtBQWtCLE1BQS9ELEVBQXVFO0FBQ3JFLFVBQUksSUFBSSxDQUFDLElBQUwsQ0FBVSxNQUFWLEdBQW1CLENBQXZCLEVBQTBCO0FBQ3hCLFlBQUksSUFBSSxDQUFDLEdBQUwsQ0FBUyxVQUFULENBQW9CLFNB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NUQ7O0FBQ0YsV0FBSyxNQUFMO0FBQ0UsZUFBTywrQkFBK0IsSUFBSSxHQUExQzs7QUFDRixXQUFLLFVBQUw7QUFDRSxlQUFPLGtDQUFrQyxJQUFJLFdBQTdDOztBQUNGO0FBQ0UsZUFBTyxTQUFTLENBQUMsSUFBRCxDQUFoQjtBQVZKO0FBWUQsR0FkSSxFQWVKLElBZkksQ0FlQyxNQWZELENBQVA7QUFnQkQ7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFpRkEsT0FBTSxTQUFVLFFBQVYsQ0FBMEMsSUFBMUMsRUFBaUQ7QUFDckQsU0FBTyxJQUFJLFFBQUosQ0FBYSxJQUFiLENBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFTVHYyLFxuICBnZW5lcmF0ZVN5bnRheEVycm9yLFxuICBpc0tleXdvcmQsXG4gIEtFWVdPUkRTX1RZUEVTLFxuICBLZXl3b3JkVHlwZSxcbn0gZnJvbSAnQGdsaW1tZXIvc3ludGF4JztcbmltcG9ydCB7IGV4aGF1c3RlZCB9IGZyb20gJ0BnbGltbWVyL3V0aWwnO1xuXG5pbXBvcnQgeyBFcnIsIFJlc3VsdCB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC9yZXN1bHQnO1xuaW1wb3J0IHsgTm9ybWFsaXphdGlvblN0YXRlIH0gZnJvbSAnLi4vY29udGV4dCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgS2V5d29yZERlbGVnYXRlPE1hdGNoIGV4dGVuZHMgS2V5d29yZE1hdGNoLCBWLCBPdXQ+IHtcbiAgYXNzZXJ0KG9wdGlvbnM6IE1hdGNoLCBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlKTogUmVzdWx0PFY+O1xuICB0cmFuc2xhdGUob3B0aW9uczogeyBub2RlOiBNYXRjaDsgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSB9LCBwYXJhbTogVik6IFJlc3VsdDxPdXQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmQ8SyBleHRlbmRzIEtleXdvcmRUeXBlID0gS2V5d29yZFR5cGUsIE91dCA9IHVua25vd24+IHtcbiAgdHJhbnNsYXRlKG5vZGU6IEtleXdvcmRDYW5kaWRhdGVzW0tdLCBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlKTogUmVzdWx0PE91dD4gfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJsb2NrS2V5d29yZDxPdXQgPSB1bmtub3duPiB7XG4gIHRyYW5zbGF0ZShub2RlOiBBU1R2Mi5JbnZva2VCbG9jaywgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSk6IFJlc3VsdDxPdXQ+IHwgbnVsbDtcbn1cblxuY2xhc3MgS2V5d29yZEltcGw8XG4gIEsgZXh0ZW5kcyBLZXl3b3JkVHlwZSxcbiAgUyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgUGFyYW0gPSB1bmtub3duLFxuICBPdXQgPSB1bmtub3duXG4+IHtcbiAgcHJvdGVjdGVkIHR5cGVzOiBTZXQ8S2V5d29yZENhbmRpZGF0ZXNbS11bJ3R5cGUnXT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIGtleXdvcmQ6IFMsXG4gICAgdHlwZTogS2V5d29yZFR5cGUsXG4gICAgcHJpdmF0ZSBkZWxlZ2F0ZTogS2V5d29yZERlbGVnYXRlPEtleXdvcmRNYXRjaGVzW0tdLCBQYXJhbSwgT3V0PlxuICApIHtcbiAgICBsZXQgbm9kZXMgPSBuZXcgU2V0PEtleXdvcmROb2RlWyd0eXBlJ10+KCk7XG4gICAgZm9yIChsZXQgbm9kZVR5cGUgb2YgS0VZV09SRF9OT0RFU1t0eXBlXSkge1xuICAgICAgbm9kZXMuYWRkKG5vZGVUeXBlKTtcbiAgICB9XG5cbiAgICB0aGlzLnR5cGVzID0gbm9kZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWF0Y2gobm9kZTogS2V5d29yZENhbmRpZGF0ZXNbS10pOiBub2RlIGlzIEtleXdvcmRNYXRjaGVzW0tdIHtcbiAgICBpZiAoIXRoaXMudHlwZXMuaGFzKG5vZGUudHlwZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBsZXQgcGF0aCA9IGdldENhbGxlZUV4cHJlc3Npb24obm9kZSk7XG5cbiAgICBpZiAocGF0aCAhPT0gbnVsbCAmJiBwYXRoLnR5cGUgPT09ICdQYXRoJyAmJiBwYXRoLnJlZi50eXBlID09PSAnRnJlZScpIHtcbiAgICAgIGlmIChwYXRoLnRhaWwubGVuZ3RoID4gMCkge1xuICAgICAgICBpZiAocGF0aC5yZWYucmVzb2x1dGlvbi5zZXJpYWxpemUoKSA9PT0gJ0xvb3NlJykge1xuICAgICAgICAgIC8vIGNhbm5vdCBiZSBhIGtleXdvcmQgcmVmZXJlbmNlLCBrZXl3b3JkcyBkbyBub3QgYWxsb3cgcGF0aHMgKG11c3QgYmVcbiAgICAgICAgICAvLyByZWx5aW5nIG9uIGltcGxpY2l0IHRoaXMgZmFsbGJhY2spXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwYXRoLnJlZi5uYW1lID09PSB0aGlzLmtleXdvcmQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICB0cmFuc2xhdGUobm9kZTogS2V5d29yZE1hdGNoZXNbS10sIHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGUpOiBSZXN1bHQ8T3V0PiB8IG51bGwge1xuICAgIGlmICh0aGlzLm1hdGNoKG5vZGUpKSB7XG4gICAgICBsZXQgcGF0aCA9IGdldENhbGxlZUV4cHJlc3Npb24obm9kZSk7XG5cbiAgICAgIGlmIChwYXRoICE9PSBudWxsICYmIHBhdGgudHlwZSA9PT0gJ1BhdGgnICYmIHBhdGgudGFpbC5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiBFcnIoXG4gICAgICAgICAgZ2VuZXJhdGVTeW50YXhFcnJvcihcbiAgICAgICAgICAgIGBUaGUgXFxgJHtcbiAgICAgICAgICAgICAgdGhpcy5rZXl3b3JkXG4gICAgICAgICAgICB9XFxgIGtleXdvcmQgd2FzIHVzZWQgaW5jb3JyZWN0bHkuIEl0IHdhcyB1c2VkIGFzIFxcYCR7cGF0aC5sb2MuYXNTdHJpbmcoKX1cXGAsIGJ1dCBpdCBjYW5ub3QgYmUgdXNlZCB3aXRoIGFkZGl0aW9uYWwgcGF0aCBzZWdtZW50cy4gXFxuXFxuRXJyb3IgY2F1c2VkIGJ5YCxcbiAgICAgICAgICAgIG5vZGUubG9jXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBsZXQgcGFyYW0gPSB0aGlzLmRlbGVnYXRlLmFzc2VydChub2RlLCBzdGF0ZSk7XG4gICAgICByZXR1cm4gcGFyYW0uYW5kVGhlbigocGFyYW0pID0+IHRoaXMuZGVsZWdhdGUudHJhbnNsYXRlKHsgbm9kZSwgc3RhdGUgfSwgcGFyYW0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCB0eXBlIFBvc3NpYmxlTm9kZSA9XG4gIHwgQVNUdjIuUGF0aEV4cHJlc3Npb25cbiAgfCBBU1R2Mi5BcHBlbmRDb250ZW50XG4gIHwgQVNUdjIuQ2FsbEV4cHJlc3Npb25cbiAgfCBBU1R2Mi5JbnZva2VCbG9jaztcblxuZXhwb3J0IGNvbnN0IEtFWVdPUkRfTk9ERVMgPSB7XG4gIENhbGw6IFsnQ2FsbCddLFxuICBCbG9jazogWydJbnZva2VCbG9jayddLFxuICBBcHBlbmQ6IFsnQXBwZW5kQ29udGVudCddLFxuICBNb2RpZmllcjogWydFbGVtZW50TW9kaWZpZXInXSxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBpbnRlcmZhY2UgS2V5d29yZENhbmRpZGF0ZXMge1xuICBDYWxsOiBBU1R2Mi5FeHByZXNzaW9uTm9kZTtcbiAgQmxvY2s6IEFTVHYyLkludm9rZUJsb2NrO1xuICBBcHBlbmQ6IEFTVHYyLkFwcGVuZENvbnRlbnQ7XG4gIE1vZGlmaWVyOiBBU1R2Mi5FbGVtZW50TW9kaWZpZXI7XG59XG5cbmV4cG9ydCB0eXBlIEtleXdvcmRDYW5kaWRhdGUgPSBLZXl3b3JkQ2FuZGlkYXRlc1trZXlvZiBLZXl3b3JkQ2FuZGlkYXRlc107XG5cbmV4cG9ydCBpbnRlcmZhY2UgS2V5d29yZE1hdGNoZXMge1xuICBDYWxsOiBBU1R2Mi5DYWxsRXhwcmVzc2lvbjtcbiAgQmxvY2s6IEFTVHYyLkludm9rZUJsb2NrO1xuICBBcHBlbmQ6IEFTVHYyLkFwcGVuZENvbnRlbnQ7XG4gIE1vZGlmaWVyOiBBU1R2Mi5FbGVtZW50TW9kaWZpZXI7XG59XG5cbmV4cG9ydCB0eXBlIEtleXdvcmRNYXRjaCA9IEtleXdvcmRNYXRjaGVzW2tleW9mIEtleXdvcmRNYXRjaGVzXTtcblxuLyoqXG4gKiBBIFwiZ2VuZXJpY1wiIGtleXdvcmQgaXMgc29tZXRoaW5nIGxpa2UgYGhhcy1ibG9ja2AsIHdoaWNoIG1ha2VzIHNlbnNlIGluIHRoZSBjb250ZXh0XG4gKiBvZiBzdWItZXhwcmVzc2lvbiBvciBhcHBlbmRcbiAqL1xuZXhwb3J0IHR5cGUgR2VuZXJpY0tleXdvcmROb2RlID0gQVNUdjIuQXBwZW5kQ29udGVudCB8IEFTVHYyLkNhbGxFeHByZXNzaW9uO1xuXG5leHBvcnQgdHlwZSBLZXl3b3JkTm9kZSA9XG4gIHwgR2VuZXJpY0tleXdvcmROb2RlXG4gIHwgQVNUdjIuQ2FsbEV4cHJlc3Npb25cbiAgfCBBU1R2Mi5JbnZva2VCbG9ja1xuICB8IEFTVHYyLkVsZW1lbnRNb2RpZmllcjtcblxuZXhwb3J0IGZ1bmN0aW9uIGtleXdvcmQ8XG4gIEsgZXh0ZW5kcyBLZXl3b3JkVHlwZSxcbiAgRCBleHRlbmRzIEtleXdvcmREZWxlZ2F0ZTxLZXl3b3JkTWF0Y2hlc1tLXSwgdW5rbm93biwgT3V0PixcbiAgT3V0ID0gdW5rbm93blxuPihrZXl3b3JkOiBzdHJpbmcsIHR5cGU6IEssIGRlbGVnYXRlOiBEKTogS2V5d29yZDxLLCBPdXQ+IHtcbiAgcmV0dXJuIG5ldyBLZXl3b3JkSW1wbChrZXl3b3JkLCB0eXBlLCBkZWxlZ2F0ZSBhcyBLZXl3b3JkRGVsZWdhdGU8S2V5d29yZE1hdGNoLCB1bmtub3duLCBPdXQ+KTtcbn1cblxuZXhwb3J0IHR5cGUgUG9zc2libGVLZXl3b3JkID0gS2V5d29yZE5vZGU7XG50eXBlIE91dEZvcjxLIGV4dGVuZHMgS2V5d29yZCB8IEJsb2NrS2V5d29yZD4gPSBLIGV4dGVuZHMgQmxvY2tLZXl3b3JkPGluZmVyIE91dD5cbiAgPyBPdXRcbiAgOiBLIGV4dGVuZHMgS2V5d29yZDxLZXl3b3JkVHlwZSwgaW5mZXIgT3V0PlxuICA/IE91dFxuICA6IG5ldmVyO1xuXG5mdW5jdGlvbiBnZXRDYWxsZWVFeHByZXNzaW9uKFxuICBub2RlOiBLZXl3b3JkTm9kZSB8IEFTVHYyLkV4cHJlc3Npb25Ob2RlXG4pOiBBU1R2Mi5FeHByZXNzaW9uTm9kZSB8IG51bGwge1xuICBzd2l0Y2ggKG5vZGUudHlwZSkge1xuICAgIC8vIFRoaXMgY292ZXJzIHRoZSBpbnNpZGUgb2YgYXR0cmlidXRlcyBhbmQgZXhwcmVzc2lvbnMsIGFzIHdlbGwgYXMgdGhlIGNhbGxlZVxuICAgIC8vIG9mIGNhbGwgbm9kZXNcbiAgICBjYXNlICdQYXRoJzpcbiAgICAgIHJldHVybiBub2RlO1xuICAgIGNhc2UgJ0FwcGVuZENvbnRlbnQnOlxuICAgICAgcmV0dXJuIGdldENhbGxlZUV4cHJlc3Npb24obm9kZS52YWx1ZSk7XG4gICAgY2FzZSAnQ2FsbCc6XG4gICAgY2FzZSAnSW52b2tlQmxvY2snOlxuICAgIGNhc2UgJ0VsZW1lbnRNb2RpZmllcic6XG4gICAgICByZXR1cm4gbm9kZS5jYWxsZWU7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBLZXl3b3JkczxLIGV4dGVuZHMgS2V5d29yZFR5cGUsIEtleXdvcmRMaXN0IGV4dGVuZHMgS2V5d29yZDxLPiA9IG5ldmVyPlxuICBpbXBsZW1lbnRzIEtleXdvcmQ8SywgT3V0Rm9yPEtleXdvcmRMaXN0Pj4ge1xuICBfa2V5d29yZHM6IEtleXdvcmRbXSA9IFtdO1xuICBfdHlwZTogSztcblxuICBjb25zdHJ1Y3Rvcih0eXBlOiBLKSB7XG4gICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gIH1cblxuICBrdzxTIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLCBPdXQgPSB1bmtub3duPihcbiAgICBuYW1lOiBTLFxuICAgIGRlbGVnYXRlOiBLZXl3b3JkRGVsZWdhdGU8S2V5d29yZE1hdGNoZXNbS10sIHVua25vd24sIE91dD5cbiAgKTogS2V5d29yZHM8SywgS2V5d29yZExpc3QgfCBLZXl3b3JkPEssIE91dD4+IHtcbiAgICB0aGlzLl9rZXl3b3Jkcy5wdXNoKGtleXdvcmQobmFtZSwgdGhpcy5fdHlwZSwgZGVsZWdhdGUpKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdHJhbnNsYXRlKFxuICAgIG5vZGU6IEtleXdvcmRDYW5kaWRhdGVzW0tdLFxuICAgIHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGVcbiAgKTogUmVzdWx0PE91dEZvcjxLZXl3b3JkTGlzdD4+IHwgbnVsbCB7XG4gICAgZm9yIChsZXQga2V5d29yZCBvZiB0aGlzLl9rZXl3b3Jkcykge1xuICAgICAgbGV0IHJlc3VsdCA9IGtleXdvcmQudHJhbnNsYXRlKG5vZGUsIHN0YXRlKSBhcyBSZXN1bHQ8T3V0Rm9yPEtleXdvcmRMaXN0Pj47XG4gICAgICBpZiAocmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHBhdGggPSBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUpO1xuXG4gICAgaWYgKHBhdGggJiYgcGF0aC50eXBlID09PSAnUGF0aCcgJiYgcGF0aC5yZWYudHlwZSA9PT0gJ0ZyZWUnICYmIGlzS2V5d29yZChwYXRoLnJlZi5uYW1lKSkge1xuICAgICAgbGV0IHsgbmFtZSB9ID0gcGF0aC5yZWY7XG5cbiAgICAgIGxldCB1c2VkVHlwZSA9IHRoaXMuX3R5cGU7XG4gICAgICBsZXQgdmFsaWRUeXBlcyA9IEtFWVdPUkRTX1RZUEVTW25hbWVdO1xuXG4gICAgICBpZiAodmFsaWRUeXBlcy5pbmRleE9mKHVzZWRUeXBlKSA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIEVycihcbiAgICAgICAgICBnZW5lcmF0ZVN5bnRheEVycm9yKFxuICAgICAgICAgICAgYFRoZSBcXGAke25hbWV9XFxgIGtleXdvcmQgd2FzIHVzZWQgaW5jb3JyZWN0bHkuIEl0IHdhcyB1c2VkIGFzICR7XG4gICAgICAgICAgICAgIHR5cGVzVG9SZWFkYWJsZU5hbWVbdXNlZFR5cGVdXG4gICAgICAgICAgICB9LCBidXQgaXRzIHZhbGlkIHVzYWdlcyBhcmU6XFxuXFxuJHtnZW5lcmF0ZVR5cGVzTWVzc2FnZShcbiAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgdmFsaWRUeXBlc1xuICAgICAgICAgICAgKX1cXG5cXG5FcnJvciBjYXVzZWQgYnlgLFxuICAgICAgICAgICAgbm9kZS5sb2NcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuY29uc3QgdHlwZXNUb1JlYWRhYmxlTmFtZSA9IHtcbiAgQXBwZW5kOiAnYW4gYXBwZW5kIHN0YXRlbWVudCcsXG4gIEJsb2NrOiAnYSBibG9jayBzdGF0ZW1lbnQnLFxuICBDYWxsOiAnYSBjYWxsIGV4cHJlc3Npb24nLFxuICBNb2RpZmllcjogJ2EgbW9kaWZpZXInLFxufTtcblxuZnVuY3Rpb24gZ2VuZXJhdGVUeXBlc01lc3NhZ2UobmFtZTogc3RyaW5nLCB0eXBlczogS2V5d29yZFR5cGVbXSk6IHN0cmluZyB7XG4gIHJldHVybiB0eXBlc1xuICAgIC5tYXAoKHR5cGUpID0+IHtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdBcHBlbmQnOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhbiBhcHBlbmQgc3RhdGVtZW50LCBhcyBpbjoge3ske25hbWV9fX1gO1xuICAgICAgICBjYXNlICdCbG9jayc6XG4gICAgICAgICAgcmV0dXJuIGAtIEFzIGEgYmxvY2sgc3RhdGVtZW50LCBhcyBpbjoge3sjJHtuYW1lfX19e3svJHtuYW1lfX19YDtcbiAgICAgICAgY2FzZSAnQ2FsbCc6XG4gICAgICAgICAgcmV0dXJuIGAtIEFzIGFuIGV4cHJlc3Npb24sIGFzIGluOiAoJHtuYW1lfSlgO1xuICAgICAgICBjYXNlICdNb2RpZmllcic6XG4gICAgICAgICAgcmV0dXJuIGAtIEFzIGEgbW9kaWZpZXIsIGFzIGluOiA8ZGl2IHt7JHtuYW1lfX19PjwvZGl2PmA7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIGV4aGF1c3RlZCh0eXBlKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5qb2luKCdcXG5cXG4nKTtcbn1cblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGJ1aWxkcyBrZXl3b3JkIGRlZmluaXRpb25zIGZvciBhIHBhcnRpY3VsYXIgdHlwZSBvZiBBU1Qgbm9kZSAoYEtleXdvcmRUeXBlYCkuXG4gKlxuICogWW91IGNhbiBidWlsZCBrZXl3b3JkIGRlZmluaXRpb25zIGZvcjpcbiAqXG4gKiAtIGBFeHByYDogQSBgU3ViRXhwcmVzc2lvbmAgb3IgYFBhdGhFeHByZXNzaW9uYFxuICogLSBgQmxvY2tgOiBBIGBCbG9ja1N0YXRlbWVudGBcbiAqICAgLSBBIGBCbG9ja1N0YXRlbWVudGAgaXMgYSBrZXl3b3JkIGNhbmRpZGF0ZSBpZiBpdHMgaGVhZCBpcyBhXG4gKiAgICAgYFBhdGhFeHByZXNzaW9uYFxuICogLSBgQXBwZW5kYDogQW4gYEFwcGVuZFN0YXRlbWVudGBcbiAqXG4gKiBBIG5vZGUgaXMgYSBrZXl3b3JkIGNhbmRpZGF0ZSBpZjpcbiAqXG4gKiAtIEEgYFBhdGhFeHByZXNzaW9uYCBpcyBhIGtleXdvcmQgY2FuZGlkYXRlIGlmIGl0IGhhcyBubyB0YWlsLCBhbmQgaXRzXG4gKiAgIGhlYWQgZXhwcmVzc2lvbiBpcyBhIGBMb2NhbFZhckhlYWRgIG9yIGBGcmVlVmFySGVhZGAgd2hvc2UgbmFtZSBpc1xuICogICB0aGUga2V5d29yZCdzIG5hbWUuXG4gKiAtIEEgYFN1YkV4cHJlc3Npb25gLCBgQXBwZW5kU3RhdGVtZW50YCwgb3IgYEJsb2NrU3RhdGVtZW50YCBpcyBhIGtleXdvcmRcbiAqICAgY2FuZGlkYXRlIGlmIGl0cyBoZWFkIGlzIGEga2V5d29yZCBjYW5kaWRhdGUuXG4gKlxuICogVGhlIGtleXdvcmQgaW5mcmFzdHJ1Y3R1cmUgZ3VhcmFudGVlcyB0aGF0OlxuICpcbiAqIC0gSWYgYSBub2RlIGlzIG5vdCBhIGtleXdvcmQgY2FuZGlkYXRlLCBpdCBpcyBuZXZlciBwYXNzZWQgdG8gYW55IGtleXdvcmQnc1xuICogICBgYXNzZXJ0YCBtZXRob2QuXG4gKiAtIElmIGEgbm9kZSBpcyBub3QgdGhlIGBLZXl3b3JkVHlwZWAgZm9yIGEgcGFydGljdWxhciBrZXl3b3JkLCBpdCB3aWxsIG5vdFxuICogICBiZSBwYXNzZWQgdG8gdGhlIGtleXdvcmQncyBgYXNzZXJ0YCBtZXRob2QuXG4gKlxuICogYEV4cHJgIGtleXdvcmRzIGFyZSB1c2VkIGluIGV4cHJlc3Npb24gcG9zaXRpb25zIGFuZCBzaG91bGQgcmV0dXJuIEhJUlxuICogZXhwcmVzc2lvbnMuIGBCbG9ja2AgYW5kIGBBcHBlbmRgIGtleXdvcmRzIGFyZSB1c2VkIGluIHN0YXRlbWVudFxuICogcG9zaXRpb25zIGFuZCBzaG91bGQgcmV0dXJuIEhJUiBzdGF0ZW1lbnRzLlxuICpcbiAqIEEga2V5d29yZCBkZWZpbml0aW9uIGhhcyB0d28gcGFydHM6XG4gKlxuICogLSBgbWF0Y2hgLCB3aGljaCBkZXRlcm1pbmVzIHdoZXRoZXIgYW4gQVNUIG5vZGUgbWF0Y2hlcyB0aGUga2V5d29yZCwgYW5kIGNhblxuICogICBvcHRpb25hbGx5IHJldHVybiBzb21lIGluZm9ybWF0aW9uIGV4dHJhY3RlZCBmcm9tIHRoZSBBU1Qgbm9kZS5cbiAqIC0gYHRyYW5zbGF0ZWAsIHdoaWNoIHRha2VzIGEgbWF0Y2hpbmcgQVNUIG5vZGUgYXMgd2VsbCBhcyB0aGUgZXh0cmFjdGVkXG4gKiAgIGluZm9ybWF0aW9uIGFuZCByZXR1cm5zIGFuIGFwcHJvcHJpYXRlIEhJUiBpbnN0cnVjdGlvbi5cbiAqXG4gKiAjIEV4YW1wbGVcbiAqXG4gKiBUaGlzIGtleXdvcmQ6XG4gKlxuICogLSB0dXJucyBgKGhlbGxvKWAgaW50byBgXCJoZWxsb1wiYFxuICogICAtIGFzIGxvbmcgYXMgYGhlbGxvYCBpcyBub3QgaW4gc2NvcGVcbiAqIC0gbWFrZXMgaXQgYW4gZXJyb3IgdG8gcGFzcyBhbnkgYXJndW1lbnRzIChzdWNoIGFzIGAoaGVsbG8gd29ybGQpYClcbiAqXG4gKiBgYGB0c1xuICoga2V5d29yZHMoJ1N1YkV4cHInKS5rdygnaGVsbG8nLCB7XG4gKiAgIGFzc2VydChub2RlOiBFeHByS2V5d29yZE5vZGUpOiBSZXN1bHQ8dm9pZD4gfCBmYWxzZSB7XG4gKiAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byB0cmFuc2Zvcm0gYGhlbGxvYCBhcyBhIGBQYXRoRXhwcmVzc2lvbmBcbiAqICAgICBpZiAobm9kZS50eXBlICE9PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAqICAgICAgIHJldHVybiBmYWxzZTtcbiAqICAgICB9XG4gKlxuICogICAgIC8vIG5vZGUuaGVhZCB3b3VsZCBiZSBgTG9jYWxWYXJIZWFkYCBpZiBgaGVsbG9gIHdhcyBpbiBzY29wZVxuICogICAgIGlmIChub2RlLmhlYWQudHlwZSAhPT0gJ0ZyZWVWYXJIZWFkJykge1xuICogICAgICAgcmV0dXJuIGZhbHNlO1xuICogICAgIH1cbiAqXG4gKiAgICAgaWYgKG5vZGUucGFyYW1zLmxlbmd0aCB8fCBub2RlLmhhc2gpIHtcbiAqICAgICAgIHJldHVybiBFcnIoZ2VuZXJhdGVTeW50YXhFcnJvcihgKGhlbGxvKSBkb2VzIG5vdCB0YWtlIGFueSBhcmd1bWVudHNgKSwgbm9kZS5sb2MpO1xuICogICAgIH0gZWxzZSB7XG4gKiAgICAgICByZXR1cm4gT2soKTtcbiAqICAgICB9XG4gKiAgIH0sXG4gKlxuICogICB0cmFuc2xhdGUobm9kZTogQVNUdjIuU3ViRXhwcmVzc2lvbik6IGhpci5FeHByZXNzaW9uIHtcbiAqICAgICByZXR1cm4gQVNUdjIuYnVpbGRlcnMubGl0ZXJhbChcImhlbGxvXCIsIG5vZGUubG9jKVxuICogICB9XG4gKiB9KVxuICogYGBgXG4gKlxuICogVGhlIGtleXdvcmQgaW5mcmFzdHJ1Y3R1cmUgY2hlY2tzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBub2RlIGlzIHRoZSByaWdodFxuICogdHlwZSBiZWZvcmUgY2FsbGluZyBgYXNzZXJ0YCwgc28geW91IG9ubHkgbmVlZCB0byBjb25zaWRlciBgU3ViRXhwcmVzc2lvbmBcbiAqIGFuZCBgUGF0aEV4cHJlc3Npb25gIGhlcmUuIEl0IGFsc28gY2hlY2tzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBub2RlIHBhc3NlZFxuICogdG8gYGFzc2VydGAgaGFzIHRoZSBrZXl3b3JkIG5hbWUgaW4gdGhlIHJpZ2h0IHBsYWNlLlxuICpcbiAqIE5vdGUgdGhlIGltcG9ydGFudCBkaWZmZXJlbmNlIGJldHdlZW4gcmV0dXJuaW5nIGBmYWxzZWAgZnJvbSBgYXNzZXJ0YCxcbiAqIHdoaWNoIGp1c3QgbWVhbnMgdGhhdCB0aGUgbm9kZSBkaWRuJ3QgbWF0Y2gsIGFuZCByZXR1cm5pbmcgYEVycmAsIHdoaWNoXG4gKiBtZWFucyB0aGF0IHRoZSBub2RlIG1hdGNoZWQsIGJ1dCB0aGVyZSB3YXMgYSBrZXl3b3JkLXNwZWNpZmljIHN5bnRheFxuICogZXJyb3IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBrZXl3b3JkczxLIGV4dGVuZHMgS2V5d29yZFR5cGU+KHR5cGU6IEspOiBLZXl3b3JkczxLPiB7XG4gIHJldHVybiBuZXcgS2V5d29yZHModHlwZSk7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9