@glimmer/compiler
Version:
312 lines (261 loc) • 28.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keyword = keyword;
exports.keywords = keywords;
exports.Keywords = exports.KEYWORD_NODES = void 0;
var _syntax = require("@glimmer/syntax");
var _util = require("@glimmer/util");
var _result = require("../../../shared/result");
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;
}
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 (0, _result.Err)((0, _syntax.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;
}();
var KEYWORD_NODES = {
Call: ['Call'],
Block: ['InvokeBlock'],
Append: ['AppendContent'],
Modifier: ['ElementModifier']
};
exports.KEYWORD_NODES = KEYWORD_NODES;
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;
}
}
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' && (0, _syntax.isKeyword)(path.ref.name)) {
var name = path.ref.name;
var usedType = this._type;
var validTypes = _syntax.KEYWORDS_TYPES[name];
if (validTypes.indexOf(usedType) === -1) {
return (0, _result.Err)((0, _syntax.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;
}();
exports.Keywords = 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 (0, _util.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.
*/
function keywords(type) {
return new Keywords(type);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL2NvbXBpbGVyL2xpYi9wYXNzZXMvMS1ub3JtYWxpemF0aW9uL2tleXdvcmRzL2ltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7O0FBT0E7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7SUFnQkEsVztBQVFFLFdBQUEsV0FBQSxDQUFBLE9BQUEsRUFBQSxJQUFBLEVBQUEsUUFBQSxFQUdrRTtBQUZ0RCxTQUFBLE9BQUEsR0FBQSxPQUFBO0FBRUYsU0FBQSxRQUFBLEdBQUEsUUFBQTtBQUVSLFFBQUksS0FBSyxHQUFHLElBQVosR0FBWSxFQUFaOztBQUNBLFNBQUEsSUFBQSxTQUFBLEdBQUEsK0JBQUEsQ0FBcUIsYUFBYSxDQUFsQyxJQUFrQyxDQUFsQyxDQUFBLEVBQUEsS0FBQSxFQUFBLENBQUEsQ0FBQSxLQUFBLEdBQUEsU0FBQSxFQUFBLEVBQUEsSUFBQSxHQUEwQztBQUFBLFVBQTFDLFFBQTBDLEdBQUEsS0FBQSxDQUFBLEtBQUE7QUFDeEMsTUFBQSxLQUFLLENBQUwsR0FBQSxDQUFBLFFBQUE7QUFDRDs7QUFFRCxTQUFBLEtBQUEsR0FBQSxLQUFBO0FBQ0Q7Ozs7U0FFUyxLLEdBQUEsU0FBQSxLQUFBLENBQUEsSUFBQSxFQUFnQztBQUN4QyxRQUFJLENBQUMsS0FBQSxLQUFBLENBQUEsR0FBQSxDQUFlLElBQUksQ0FBeEIsSUFBSyxDQUFMLEVBQWdDO0FBQzlCLGFBQUEsS0FBQTtBQUNEOztBQUVELFFBQUksSUFBSSxHQUFHLG1CQUFtQixDQUE5QixJQUE4QixDQUE5Qjs7QUFFQSxRQUFJLElBQUksS0FBSixJQUFBLElBQWlCLElBQUksQ0FBSixJQUFBLEtBQWpCLE1BQUEsSUFBeUMsSUFBSSxDQUFKLEdBQUEsQ0FBQSxJQUFBLEtBQTdDLE1BQUEsRUFBdUU7QUFDckUsVUFBSSxJQUFJLENBQUosSUFB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QUEsU0FBQSxRQUFBO0FBQUEsQ0FBQSxFQUFBOzs7QUF3REEsSUFBTSxtQkFBbUIsR0FBRztBQUMxQixFQUFBLE1BQU0sRUFEb0IscUJBQUE7QUFFMUIsRUFBQSxLQUFLLEVBRnFCLG1CQUFBO0FBRzFCLEVBQUEsSUFBSSxFQUhzQixtQkFBQTtBQUkxQixFQUFBLFFBQVEsRUFBRTtBQUpnQixDQUE1Qjs7QUFPQSxTQUFBLG9CQUFBLENBQUEsSUFBQSxFQUFBLEtBQUEsRUFBZ0U7QUFDOUQsU0FBTyxLQUFLLENBQUwsR0FBQSxDQUNDLFVBQUQsSUFBQyxFQUFRO0FBQ1osWUFBQSxJQUFBO0FBQ0UsV0FBQSxRQUFBO0FBQ0UsZUFBQSx3Q0FBQSxJQUFBLEdBQUEsSUFBQTs7QUFDRixXQUFBLE9BQUE7QUFDRSxlQUFBLHVDQUFBLElBQUEsR0FBQSxPQUFBLEdBQUEsSUFBQSxHQUFBLElBQUE7O0FBQ0YsV0FBQSxNQUFBO0FBQ0UsZUFBQSxpQ0FBQSxJQUFBLEdBQUEsR0FBQTs7QUFDRixXQUFBLFVBQUE7QUFDRSxlQUFBLG9DQUFBLElBQUEsR0FBQSxXQUFBOztBQUNGO0FBQ0UsZUFBTyxxQkFBUCxJQUFPLENBQVA7QUFWSjtBQUZHLEdBQUEsRUFBQSxJQUFBLENBQVAsTUFBTyxDQUFQO0FBZ0JEO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBaUZNLFNBQUEsUUFBQSxDQUFBLElBQUEsRUFBaUQ7QUFDckQsU0FBTyxJQUFBLFFBQUEsQ0FBUCxJQUFPLENBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFTVHYyLFxuICBnZW5lcmF0ZVN5bnRheEVycm9yLFxuICBpc0tleXdvcmQsXG4gIEtFWVdPUkRTX1RZUEVTLFxuICBLZXl3b3JkVHlwZSxcbn0gZnJvbSAnQGdsaW1tZXIvc3ludGF4JztcbmltcG9ydCB7IGV4aGF1c3RlZCB9IGZyb20gJ0BnbGltbWVyL3V0aWwnO1xuXG5pbXBvcnQgeyBFcnIsIFJlc3VsdCB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC9yZXN1bHQnO1xuaW1wb3J0IHsgTm9ybWFsaXphdGlvblN0YXRlIH0gZnJvbSAnLi4vY29udGV4dCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgS2V5d29yZERlbGVnYXRlPE1hdGNoIGV4dGVuZHMgS2V5d29yZE1hdGNoLCBWLCBPdXQ+IHtcbiAgYXNzZXJ0KG9wdGlvbnM6IE1hdGNoLCBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlKTogUmVzdWx0PFY+O1xuICB0cmFuc2xhdGUob3B0aW9uczogeyBub2RlOiBNYXRjaDsgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSB9LCBwYXJhbTogVik6IFJlc3VsdDxPdXQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEtleXdvcmQ8SyBleHRlbmRzIEtleXdvcmRUeXBlID0gS2V5d29yZFR5cGUsIE91dCA9IHVua25vd24+IHtcbiAgdHJhbnNsYXRlKG5vZGU6IEtleXdvcmRDYW5kaWRhdGVzW0tdLCBzdGF0ZTogTm9ybWFsaXphdGlvblN0YXRlKTogUmVzdWx0PE91dD4gfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJsb2NrS2V5d29yZDxPdXQgPSB1bmtub3duPiB7XG4gIHRyYW5zbGF0ZShub2RlOiBBU1R2Mi5JbnZva2VCbG9jaywgc3RhdGU6IE5vcm1hbGl6YXRpb25TdGF0ZSk6IFJlc3VsdDxPdXQ+IHwgbnVsbDtcbn1cblxuY2xhc3MgS2V5d29yZEltcGw8XG4gIEsgZXh0ZW5kcyBLZXl3b3JkVHlwZSxcbiAgUyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgUGFyYW0gPSB1bmtub3duLFxuICBPdXQgPSB1bmtub3duXG4+IHtcbiAgcHJvdGVjdGVkIHR5cGVzOiBTZXQ8S2V5d29yZENhbmRpZGF0ZXNbS11bJ3R5cGUnXT47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIGtleXdvcmQ6IFMsXG4gICAgdHlwZTogS2V5d29yZFR5cGUsXG4gICAgcHJpdmF0ZSBkZWxlZ2F0ZTogS2V5d29yZERlbGVnYXRlPEtleXdvcmRNYXRjaGVzW0tdLCBQYXJhbSwgT3V0PlxuICApIHtcbiAgICBsZXQgbm9kZXMgPSBuZXcgU2V0PEtleXdvcmROb2RlWyd0eXBlJ10+KCk7XG4gICAgZm9yIChsZXQgbm9kZVR5cGUgb2YgS0VZV09SRF9OT0RFU1t0eXBlXSkge1xuICAgICAgbm9kZXMuYWRkKG5vZGVUeXBlKTtcbiAgICB9XG5cbiAgICB0aGlzLnR5cGVzID0gbm9kZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWF0Y2gobm9kZTogS2V5d29yZENhbmRpZGF0ZXNbS10pOiBub2RlIGlzIEtleXdvcmRNYXRjaGVzW0tdIHtcbiAgICBpZiAoIXRoaXMudHlwZXMuaGFzKG5vZGUudHlwZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBsZXQgcGF0aCA9IGdldENhbGxlZUV4cHJlc3Npb24obm9kZSk7XG5cbiAgICBpZiAocGF0aCAhPT0gbnVsbCAmJiBwYXRoLnR5cGUgPT09ICdQYXRoJyAmJiBwYXRoLnJlZi50eXBlID09PSAnRnJlZScpIHtcbiAgICAgIGlmIChwYXRoLnRhaWwubGVuZ3RoID4gMCkge1xuICAgICAgICBpZiAocGF0aC5yZWYucmVzb2x1dGlvbi5zZXJpYWxpemUoKSA9PT0gJ0xvb3NlJykge1xuICAgICAgICAgIC8vIGNhbm5vdCBiZSBhIGtleXdvcmQgcmVmZXJlbmNlLCBrZXl3b3JkcyBkbyBub3QgYWxsb3cgcGF0aHMgKG11c3QgYmVcbiAgICAgICAgICAvLyByZWx5aW5nIG9uIGltcGxpY2l0IHRoaXMgZmFsbGJhY2spXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwYXRoLnJlZi5uYW1lID09PSB0aGlzLmtleXdvcmQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICB0cmFuc2xhdGUobm9kZTogS2V5d29yZE1hdGNoZXNbS10sIHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGUpOiBSZXN1bHQ8T3V0PiB8IG51bGwge1xuICAgIGlmICh0aGlzLm1hdGNoKG5vZGUpKSB7XG4gICAgICBsZXQgcGF0aCA9IGdldENhbGxlZUV4cHJlc3Npb24obm9kZSk7XG5cbiAgICAgIGlmIChwYXRoICE9PSBudWxsICYmIHBhdGgudHlwZSA9PT0gJ1BhdGgnICYmIHBhdGgudGFpbC5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiBFcnIoXG4gICAgICAgICAgZ2VuZXJhdGVTeW50YXhFcnJvcihcbiAgICAgICAgICAgIGBUaGUgXFxgJHtcbiAgICAgICAgICAgICAgdGhpcy5rZXl3b3JkXG4gICAgICAgICAgICB9XFxgIGtleXdvcmQgd2FzIHVzZWQgaW5jb3JyZWN0bHkuIEl0IHdhcyB1c2VkIGFzIFxcYCR7cGF0aC5sb2MuYXNTdHJpbmcoKX1cXGAsIGJ1dCBpdCBjYW5ub3QgYmUgdXNlZCB3aXRoIGFkZGl0aW9uYWwgcGF0aCBzZWdtZW50cy4gXFxuXFxuRXJyb3IgY2F1c2VkIGJ5YCxcbiAgICAgICAgICAgIG5vZGUubG9jXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBsZXQgcGFyYW0gPSB0aGlzLmRlbGVnYXRlLmFzc2VydChub2RlLCBzdGF0ZSk7XG4gICAgICByZXR1cm4gcGFyYW0uYW5kVGhlbigocGFyYW0pID0+IHRoaXMuZGVsZWdhdGUudHJhbnNsYXRlKHsgbm9kZSwgc3RhdGUgfSwgcGFyYW0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCB0eXBlIFBvc3NpYmxlTm9kZSA9XG4gIHwgQVNUdjIuUGF0aEV4cHJlc3Npb25cbiAgfCBBU1R2Mi5BcHBlbmRDb250ZW50XG4gIHwgQVNUdjIuQ2FsbEV4cHJlc3Npb25cbiAgfCBBU1R2Mi5JbnZva2VCbG9jaztcblxuZXhwb3J0IGNvbnN0IEtFWVdPUkRfTk9ERVMgPSB7XG4gIENhbGw6IFsnQ2FsbCddLFxuICBCbG9jazogWydJbnZva2VCbG9jayddLFxuICBBcHBlbmQ6IFsnQXBwZW5kQ29udGVudCddLFxuICBNb2RpZmllcjogWydFbGVtZW50TW9kaWZpZXInXSxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBpbnRlcmZhY2UgS2V5d29yZENhbmRpZGF0ZXMge1xuICBDYWxsOiBBU1R2Mi5FeHByZXNzaW9uTm9kZTtcbiAgQmxvY2s6IEFTVHYyLkludm9rZUJsb2NrO1xuICBBcHBlbmQ6IEFTVHYyLkFwcGVuZENvbnRlbnQ7XG4gIE1vZGlmaWVyOiBBU1R2Mi5FbGVtZW50TW9kaWZpZXI7XG59XG5cbmV4cG9ydCB0eXBlIEtleXdvcmRDYW5kaWRhdGUgPSBLZXl3b3JkQ2FuZGlkYXRlc1trZXlvZiBLZXl3b3JkQ2FuZGlkYXRlc107XG5cbmV4cG9ydCBpbnRlcmZhY2UgS2V5d29yZE1hdGNoZXMge1xuICBDYWxsOiBBU1R2Mi5DYWxsRXhwcmVzc2lvbjtcbiAgQmxvY2s6IEFTVHYyLkludm9rZUJsb2NrO1xuICBBcHBlbmQ6IEFTVHYyLkFwcGVuZENvbnRlbnQ7XG4gIE1vZGlmaWVyOiBBU1R2Mi5FbGVtZW50TW9kaWZpZXI7XG59XG5cbmV4cG9ydCB0eXBlIEtleXdvcmRNYXRjaCA9IEtleXdvcmRNYXRjaGVzW2tleW9mIEtleXdvcmRNYXRjaGVzXTtcblxuLyoqXG4gKiBBIFwiZ2VuZXJpY1wiIGtleXdvcmQgaXMgc29tZXRoaW5nIGxpa2UgYGhhcy1ibG9ja2AsIHdoaWNoIG1ha2VzIHNlbnNlIGluIHRoZSBjb250ZXh0XG4gKiBvZiBzdWItZXhwcmVzc2lvbiBvciBhcHBlbmRcbiAqL1xuZXhwb3J0IHR5cGUgR2VuZXJpY0tleXdvcmROb2RlID0gQVNUdjIuQXBwZW5kQ29udGVudCB8IEFTVHYyLkNhbGxFeHByZXNzaW9uO1xuXG5leHBvcnQgdHlwZSBLZXl3b3JkTm9kZSA9XG4gIHwgR2VuZXJpY0tleXdvcmROb2RlXG4gIHwgQVNUdjIuQ2FsbEV4cHJlc3Npb25cbiAgfCBBU1R2Mi5JbnZva2VCbG9ja1xuICB8IEFTVHYyLkVsZW1lbnRNb2RpZmllcjtcblxuZXhwb3J0IGZ1bmN0aW9uIGtleXdvcmQ8XG4gIEsgZXh0ZW5kcyBLZXl3b3JkVHlwZSxcbiAgRCBleHRlbmRzIEtleXdvcmREZWxlZ2F0ZTxLZXl3b3JkTWF0Y2hlc1tLXSwgdW5rbm93biwgT3V0PixcbiAgT3V0ID0gdW5rbm93blxuPihrZXl3b3JkOiBzdHJpbmcsIHR5cGU6IEssIGRlbGVnYXRlOiBEKTogS2V5d29yZDxLLCBPdXQ+IHtcbiAgcmV0dXJuIG5ldyBLZXl3b3JkSW1wbChrZXl3b3JkLCB0eXBlLCBkZWxlZ2F0ZSBhcyBLZXl3b3JkRGVsZWdhdGU8S2V5d29yZE1hdGNoLCB1bmtub3duLCBPdXQ+KTtcbn1cblxuZXhwb3J0IHR5cGUgUG9zc2libGVLZXl3b3JkID0gS2V5d29yZE5vZGU7XG50eXBlIE91dEZvcjxLIGV4dGVuZHMgS2V5d29yZCB8IEJsb2NrS2V5d29yZD4gPSBLIGV4dGVuZHMgQmxvY2tLZXl3b3JkPGluZmVyIE91dD5cbiAgPyBPdXRcbiAgOiBLIGV4dGVuZHMgS2V5d29yZDxLZXl3b3JkVHlwZSwgaW5mZXIgT3V0PlxuICA/IE91dFxuICA6IG5ldmVyO1xuXG5mdW5jdGlvbiBnZXRDYWxsZWVFeHByZXNzaW9uKFxuICBub2RlOiBLZXl3b3JkTm9kZSB8IEFTVHYyLkV4cHJlc3Npb25Ob2RlXG4pOiBBU1R2Mi5FeHByZXNzaW9uTm9kZSB8IG51bGwge1xuICBzd2l0Y2ggKG5vZGUudHlwZSkge1xuICAgIC8vIFRoaXMgY292ZXJzIHRoZSBpbnNpZGUgb2YgYXR0cmlidXRlcyBhbmQgZXhwcmVzc2lvbnMsIGFzIHdlbGwgYXMgdGhlIGNhbGxlZVxuICAgIC8vIG9mIGNhbGwgbm9kZXNcbiAgICBjYXNlICdQYXRoJzpcbiAgICAgIHJldHVybiBub2RlO1xuICAgIGNhc2UgJ0FwcGVuZENvbnRlbnQnOlxuICAgICAgcmV0dXJuIGdldENhbGxlZUV4cHJlc3Npb24obm9kZS52YWx1ZSk7XG4gICAgY2FzZSAnQ2FsbCc6XG4gICAgY2FzZSAnSW52b2tlQmxvY2snOlxuICAgIGNhc2UgJ0VsZW1lbnRNb2RpZmllcic6XG4gICAgICByZXR1cm4gbm9kZS5jYWxsZWU7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBLZXl3b3JkczxLIGV4dGVuZHMgS2V5d29yZFR5cGUsIEtleXdvcmRMaXN0IGV4dGVuZHMgS2V5d29yZDxLPiA9IG5ldmVyPlxuICBpbXBsZW1lbnRzIEtleXdvcmQ8SywgT3V0Rm9yPEtleXdvcmRMaXN0Pj4ge1xuICBfa2V5d29yZHM6IEtleXdvcmRbXSA9IFtdO1xuICBfdHlwZTogSztcblxuICBjb25zdHJ1Y3Rvcih0eXBlOiBLKSB7XG4gICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gIH1cblxuICBrdzxTIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLCBPdXQgPSB1bmtub3duPihcbiAgICBuYW1lOiBTLFxuICAgIGRlbGVnYXRlOiBLZXl3b3JkRGVsZWdhdGU8S2V5d29yZE1hdGNoZXNbS10sIHVua25vd24sIE91dD5cbiAgKTogS2V5d29yZHM8SywgS2V5d29yZExpc3QgfCBLZXl3b3JkPEssIE91dD4+IHtcbiAgICB0aGlzLl9rZXl3b3Jkcy5wdXNoKGtleXdvcmQobmFtZSwgdGhpcy5fdHlwZSwgZGVsZWdhdGUpKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgdHJhbnNsYXRlKFxuICAgIG5vZGU6IEtleXdvcmRDYW5kaWRhdGVzW0tdLFxuICAgIHN0YXRlOiBOb3JtYWxpemF0aW9uU3RhdGVcbiAgKTogUmVzdWx0PE91dEZvcjxLZXl3b3JkTGlzdD4+IHwgbnVsbCB7XG4gICAgZm9yIChsZXQga2V5d29yZCBvZiB0aGlzLl9rZXl3b3Jkcykge1xuICAgICAgbGV0IHJlc3VsdCA9IGtleXdvcmQudHJhbnNsYXRlKG5vZGUsIHN0YXRlKSBhcyBSZXN1bHQ8T3V0Rm9yPEtleXdvcmRMaXN0Pj47XG4gICAgICBpZiAocmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHBhdGggPSBnZXRDYWxsZWVFeHByZXNzaW9uKG5vZGUpO1xuXG4gICAgaWYgKHBhdGggJiYgcGF0aC50eXBlID09PSAnUGF0aCcgJiYgcGF0aC5yZWYudHlwZSA9PT0gJ0ZyZWUnICYmIGlzS2V5d29yZChwYXRoLnJlZi5uYW1lKSkge1xuICAgICAgbGV0IHsgbmFtZSB9ID0gcGF0aC5yZWY7XG5cbiAgICAgIGxldCB1c2VkVHlwZSA9IHRoaXMuX3R5cGU7XG4gICAgICBsZXQgdmFsaWRUeXBlcyA9IEtFWVdPUkRTX1RZUEVTW25hbWVdO1xuXG4gICAgICBpZiAodmFsaWRUeXBlcy5pbmRleE9mKHVzZWRUeXBlKSA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIEVycihcbiAgICAgICAgICBnZW5lcmF0ZVN5bnRheEVycm9yKFxuICAgICAgICAgICAgYFRoZSBcXGAke25hbWV9XFxgIGtleXdvcmQgd2FzIHVzZWQgaW5jb3JyZWN0bHkuIEl0IHdhcyB1c2VkIGFzICR7XG4gICAgICAgICAgICAgIHR5cGVzVG9SZWFkYWJsZU5hbWVbdXNlZFR5cGVdXG4gICAgICAgICAgICB9LCBidXQgaXRzIHZhbGlkIHVzYWdlcyBhcmU6XFxuXFxuJHtnZW5lcmF0ZVR5cGVzTWVzc2FnZShcbiAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgdmFsaWRUeXBlc1xuICAgICAgICAgICAgKX1cXG5cXG5FcnJvciBjYXVzZWQgYnlgLFxuICAgICAgICAgICAgbm9kZS5sb2NcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuY29uc3QgdHlwZXNUb1JlYWRhYmxlTmFtZSA9IHtcbiAgQXBwZW5kOiAnYW4gYXBwZW5kIHN0YXRlbWVudCcsXG4gIEJsb2NrOiAnYSBibG9jayBzdGF0ZW1lbnQnLFxuICBDYWxsOiAnYSBjYWxsIGV4cHJlc3Npb24nLFxuICBNb2RpZmllcjogJ2EgbW9kaWZpZXInLFxufTtcblxuZnVuY3Rpb24gZ2VuZXJhdGVUeXBlc01lc3NhZ2UobmFtZTogc3RyaW5nLCB0eXBlczogS2V5d29yZFR5cGVbXSk6IHN0cmluZyB7XG4gIHJldHVybiB0eXBlc1xuICAgIC5tYXAoKHR5cGUpID0+IHtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdBcHBlbmQnOlxuICAgICAgICAgIHJldHVybiBgLSBBcyBhbiBhcHBlbmQgc3RhdGVtZW50LCBhcyBpbjoge3ske25hbWV9fX1gO1xuICAgICAgICBjYXNlICdCbG9jayc6XG4gICAgICAgICAgcmV0dXJuIGAtIEFzIGEgYmxvY2sgc3RhdGVtZW50LCBhcyBpbjoge3sjJHtuYW1lfX19e3svJHtuYW1lfX19YDtcbiAgICAgICAgY2FzZSAnQ2FsbCc6XG4gICAgICAgICAgcmV0dXJuIGAtIEFzIGFuIGV4cHJlc3Npb24sIGFzIGluOiAoJHtuYW1lfSlgO1xuICAgICAgICBjYXNlICdNb2RpZmllcic6XG4gICAgICAgICAgcmV0dXJuIGAtIEFzIGEgbW9kaWZpZXIsIGFzIGluOiA8ZGl2IHt7JHtuYW1lfX19PjwvZGl2PmA7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIGV4aGF1c3RlZCh0eXBlKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5qb2luKCdcXG5cXG4nKTtcbn1cblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGJ1aWxkcyBrZXl3b3JkIGRlZmluaXRpb25zIGZvciBhIHBhcnRpY3VsYXIgdHlwZSBvZiBBU1Qgbm9kZSAoYEtleXdvcmRUeXBlYCkuXG4gKlxuICogWW91IGNhbiBidWlsZCBrZXl3b3JkIGRlZmluaXRpb25zIGZvcjpcbiAqXG4gKiAtIGBFeHByYDogQSBgU3ViRXhwcmVzc2lvbmAgb3IgYFBhdGhFeHByZXNzaW9uYFxuICogLSBgQmxvY2tgOiBBIGBCbG9ja1N0YXRlbWVudGBcbiAqICAgLSBBIGBCbG9ja1N0YXRlbWVudGAgaXMgYSBrZXl3b3JkIGNhbmRpZGF0ZSBpZiBpdHMgaGVhZCBpcyBhXG4gKiAgICAgYFBhdGhFeHByZXNzaW9uYFxuICogLSBgQXBwZW5kYDogQW4gYEFwcGVuZFN0YXRlbWVudGBcbiAqXG4gKiBBIG5vZGUgaXMgYSBrZXl3b3JkIGNhbmRpZGF0ZSBpZjpcbiAqXG4gKiAtIEEgYFBhdGhFeHByZXNzaW9uYCBpcyBhIGtleXdvcmQgY2FuZGlkYXRlIGlmIGl0IGhhcyBubyB0YWlsLCBhbmQgaXRzXG4gKiAgIGhlYWQgZXhwcmVzc2lvbiBpcyBhIGBMb2NhbFZhckhlYWRgIG9yIGBGcmVlVmFySGVhZGAgd2hvc2UgbmFtZSBpc1xuICogICB0aGUga2V5d29yZCdzIG5hbWUuXG4gKiAtIEEgYFN1YkV4cHJlc3Npb25gLCBgQXBwZW5kU3RhdGVtZW50YCwgb3IgYEJsb2NrU3RhdGVtZW50YCBpcyBhIGtleXdvcmRcbiAqICAgY2FuZGlkYXRlIGlmIGl0cyBoZWFkIGlzIGEga2V5d29yZCBjYW5kaWRhdGUuXG4gKlxuICogVGhlIGtleXdvcmQgaW5mcmFzdHJ1Y3R1cmUgZ3VhcmFudGVlcyB0aGF0OlxuICpcbiAqIC0gSWYgYSBub2RlIGlzIG5vdCBhIGtleXdvcmQgY2FuZGlkYXRlLCBpdCBpcyBuZXZlciBwYXNzZWQgdG8gYW55IGtleXdvcmQnc1xuICogICBgYXNzZXJ0YCBtZXRob2QuXG4gKiAtIElmIGEgbm9kZSBpcyBub3QgdGhlIGBLZXl3b3JkVHlwZWAgZm9yIGEgcGFydGljdWxhciBrZXl3b3JkLCBpdCB3aWxsIG5vdFxuICogICBiZSBwYXNzZWQgdG8gdGhlIGtleXdvcmQncyBgYXNzZXJ0YCBtZXRob2QuXG4gKlxuICogYEV4cHJgIGtleXdvcmRzIGFyZSB1c2VkIGluIGV4cHJlc3Npb24gcG9zaXRpb25zIGFuZCBzaG91bGQgcmV0dXJuIEhJUlxuICogZXhwcmVzc2lvbnMuIGBCbG9ja2AgYW5kIGBBcHBlbmRgIGtleXdvcmRzIGFyZSB1c2VkIGluIHN0YXRlbWVudFxuICogcG9zaXRpb25zIGFuZCBzaG91bGQgcmV0dXJuIEhJUiBzdGF0ZW1lbnRzLlxuICpcbiAqIEEga2V5d29yZCBkZWZpbml0aW9uIGhhcyB0d28gcGFydHM6XG4gKlxuICogLSBgbWF0Y2hgLCB3aGljaCBkZXRlcm1pbmVzIHdoZXRoZXIgYW4gQVNUIG5vZGUgbWF0Y2hlcyB0aGUga2V5d29yZCwgYW5kIGNhblxuICogICBvcHRpb25hbGx5IHJldHVybiBzb21lIGluZm9ybWF0aW9uIGV4dHJhY3RlZCBmcm9tIHRoZSBBU1Qgbm9kZS5cbiAqIC0gYHRyYW5zbGF0ZWAsIHdoaWNoIHRha2VzIGEgbWF0Y2hpbmcgQVNUIG5vZGUgYXMgd2VsbCBhcyB0aGUgZXh0cmFjdGVkXG4gKiAgIGluZm9ybWF0aW9uIGFuZCByZXR1cm5zIGFuIGFwcHJvcHJpYXRlIEhJUiBpbnN0cnVjdGlvbi5cbiAqXG4gKiAjIEV4YW1wbGVcbiAqXG4gKiBUaGlzIGtleXdvcmQ6XG4gKlxuICogLSB0dXJucyBgKGhlbGxvKWAgaW50byBgXCJoZWxsb1wiYFxuICogICAtIGFzIGxvbmcgYXMgYGhlbGxvYCBpcyBub3QgaW4gc2NvcGVcbiAqIC0gbWFrZXMgaXQgYW4gZXJyb3IgdG8gcGFzcyBhbnkgYXJndW1lbnRzIChzdWNoIGFzIGAoaGVsbG8gd29ybGQpYClcbiAqXG4gKiBgYGB0c1xuICoga2V5d29yZHMoJ1N1YkV4cHInKS5rdygnaGVsbG8nLCB7XG4gKiAgIGFzc2VydChub2RlOiBFeHByS2V5d29yZE5vZGUpOiBSZXN1bHQ8dm9pZD4gfCBmYWxzZSB7XG4gKiAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byB0cmFuc2Zvcm0gYGhlbGxvYCBhcyBhIGBQYXRoRXhwcmVzc2lvbmBcbiAqICAgICBpZiAobm9kZS50eXBlICE9PSAnU3ViRXhwcmVzc2lvbicpIHtcbiAqICAgICAgIHJldHVybiBmYWxzZTtcbiAqICAgICB9XG4gKlxuICogICAgIC8vIG5vZGUuaGVhZCB3b3VsZCBiZSBgTG9jYWxWYXJIZWFkYCBpZiBgaGVsbG9gIHdhcyBpbiBzY29wZVxuICogICAgIGlmIChub2RlLmhlYWQudHlwZSAhPT0gJ0ZyZWVWYXJIZWFkJykge1xuICogICAgICAgcmV0dXJuIGZhbHNlO1xuICogICAgIH1cbiAqXG4gKiAgICAgaWYgKG5vZGUucGFyYW1zLmxlbmd0aCB8fCBub2RlLmhhc2gpIHtcbiAqICAgICAgIHJldHVybiBFcnIoZ2VuZXJhdGVTeW50YXhFcnJvcihgKGhlbGxvKSBkb2VzIG5vdCB0YWtlIGFueSBhcmd1bWVudHNgKSwgbm9kZS5sb2MpO1xuICogICAgIH0gZWxzZSB7XG4gKiAgICAgICByZXR1cm4gT2soKTtcbiAqICAgICB9XG4gKiAgIH0sXG4gKlxuICogICB0cmFuc2xhdGUobm9kZTogQVNUdjIuU3ViRXhwcmVzc2lvbik6IGhpci5FeHByZXNzaW9uIHtcbiAqICAgICByZXR1cm4gQVNUdjIuYnVpbGRlcnMubGl0ZXJhbChcImhlbGxvXCIsIG5vZGUubG9jKVxuICogICB9XG4gKiB9KVxuICogYGBgXG4gKlxuICogVGhlIGtleXdvcmQgaW5mcmFzdHJ1Y3R1cmUgY2hlY2tzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBub2RlIGlzIHRoZSByaWdodFxuICogdHlwZSBiZWZvcmUgY2FsbGluZyBgYXNzZXJ0YCwgc28geW91IG9ubHkgbmVlZCB0byBjb25zaWRlciBgU3ViRXhwcmVzc2lvbmBcbiAqIGFuZCBgUGF0aEV4cHJlc3Npb25gIGhlcmUuIEl0IGFsc28gY2hlY2tzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBub2RlIHBhc3NlZFxuICogdG8gYGFzc2VydGAgaGFzIHRoZSBrZXl3b3JkIG5hbWUgaW4gdGhlIHJpZ2h0IHBsYWNlLlxuICpcbiAqIE5vdGUgdGhlIGltcG9ydGFudCBkaWZmZXJlbmNlIGJldHdlZW4gcmV0dXJuaW5nIGBmYWxzZWAgZnJvbSBgYXNzZXJ0YCxcbiAqIHdoaWNoIGp1c3QgbWVhbnMgdGhhdCB0aGUgbm9kZSBkaWRuJ3QgbWF0Y2gsIGFuZCByZXR1cm5pbmcgYEVycmAsIHdoaWNoXG4gKiBtZWFucyB0aGF0IHRoZSBub2RlIG1hdGNoZWQsIGJ1dCB0aGVyZSB3YXMgYSBrZXl3b3JkLXNwZWNpZmljIHN5bnRheFxuICogZXJyb3IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBrZXl3b3JkczxLIGV4dGVuZHMgS2V5d29yZFR5cGU+KHR5cGU6IEspOiBLZXl3b3JkczxLPiB7XG4gIHJldHVybiBuZXcgS2V5d29yZHModHlwZSk7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9