ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
279 lines (270 loc) • 40.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.HandlebarsNodeVisitors = undefined;
var _builders = require("../builders");
var _builders2 = _interopRequireDefault(_builders);
var _utils = require("../utils");
var _parser = require("../parser");
var _syntaxError = require("../errors/syntax-error");
var _syntaxError2 = _interopRequireDefault(_syntaxError);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class HandlebarsNodeVisitors extends _parser.Parser {
Program(program) {
let body = [];
let node = _builders2.default.program(body, program.blockParams, program.loc);
let i,
l = program.body.length;
this.elementStack.push(node);
if (l === 0) {
return this.elementStack.pop();
}
for (i = 0; i < l; i++) {
this.acceptNode(program.body[i]);
}
// Ensure that that the element stack is balanced properly.
let poppedNode = this.elementStack.pop();
if (poppedNode !== node) {
let elementNode = poppedNode;
throw new _syntaxError2.default("Unclosed element `" + elementNode.tag + "` (on line " + elementNode.loc.start.line + ").", elementNode.loc);
}
return node;
}
BlockStatement(block) {
if (this.tokenizer['state'] === 'comment') {
this.appendToCommentData(this.sourceForNode(block));
return;
}
if (this.tokenizer['state'] !== 'comment' && this.tokenizer['state'] !== 'data' && this.tokenizer['state'] !== 'beforeData') {
throw new _syntaxError2.default("A block may only be used inside an HTML element or another block.", block.loc);
}
let { path, params, hash } = acceptCallNodes(this, block);
let program = this.Program(block.program);
let inverse = block.inverse ? this.Program(block.inverse) : null;
let node = _builders2.default.block(path, params, hash, program, inverse, block.loc);
let parentProgram = this.currentElement();
(0, _utils.appendChild)(parentProgram, node);
}
MustacheStatement(rawMustache) {
let { tokenizer } = this;
if (tokenizer['state'] === 'comment') {
this.appendToCommentData(this.sourceForNode(rawMustache));
return;
}
let mustache;
let { escaped, loc } = rawMustache;
if (rawMustache.path.type.match(/Literal$/)) {
mustache = {
type: 'MustacheStatement',
path: this.acceptNode(rawMustache.path),
params: [],
hash: _builders2.default.hash(),
escaped,
loc
};
} else {
let { path, params, hash } = acceptCallNodes(this, rawMustache);
mustache = _builders2.default.mustache(path, params, hash, !escaped, loc);
}
switch (tokenizer.state) {
// Tag helpers
case "tagName":
addElementModifier(this.currentStartTag, mustache);
tokenizer.state = "beforeAttributeName";
break;
case "beforeAttributeName":
addElementModifier(this.currentStartTag, mustache);
break;
case "attributeName":
case "afterAttributeName":
this.beginAttributeValue(false);
this.finishAttributeValue();
addElementModifier(this.currentStartTag, mustache);
tokenizer.state = "beforeAttributeName";
break;
case "afterAttributeValueQuoted":
addElementModifier(this.currentStartTag, mustache);
tokenizer.state = "beforeAttributeName";
break;
// Attribute values
case "beforeAttributeValue":
appendDynamicAttributeValuePart(this.currentAttribute, mustache);
tokenizer.state = 'attributeValueUnquoted';
break;
case "attributeValueDoubleQuoted":
case "attributeValueSingleQuoted":
case "attributeValueUnquoted":
appendDynamicAttributeValuePart(this.currentAttribute, mustache);
break;
// TODO: Only append child when the tokenizer state makes
// sense to do so, otherwise throw an error.
default:
(0, _utils.appendChild)(this.currentElement(), mustache);
}
return mustache;
}
ContentStatement(content) {
updateTokenizerLocation(this.tokenizer, content);
this.tokenizer.tokenizePart(content.value);
this.tokenizer.flushData();
}
CommentStatement(rawComment) {
let { tokenizer } = this;
if (tokenizer.state === 'comment') {
this.appendToCommentData(this.sourceForNode(rawComment));
return null;
}
let { value, loc } = rawComment;
let comment = _builders2.default.mustacheComment(value, loc);
switch (tokenizer.state) {
case "beforeAttributeName":
this.currentStartTag.comments.push(comment);
break;
case 'beforeData':
case 'data':
(0, _utils.appendChild)(this.currentElement(), comment);
break;
default:
throw new _syntaxError2.default(`Using a Handlebars comment when in the \`${tokenizer.state}\` state is not supported: "${comment.value}" on line ${loc.start.line}:${loc.start.column}`, rawComment.loc);
}
return comment;
}
PartialStatement(partial) {
let { loc } = partial;
throw new _syntaxError2.default(`Handlebars partials are not supported: "${this.sourceForNode(partial, partial.name)}" at L${loc.start.line}:C${loc.start.column}`, partial.loc);
}
PartialBlockStatement(partialBlock) {
let { loc } = partialBlock;
throw new _syntaxError2.default(`Handlebars partial blocks are not supported: "${this.sourceForNode(partialBlock, partialBlock.name)}" at L${loc.start.line}:C${loc.start.column}`, partialBlock.loc);
}
Decorator(decorator) {
let { loc } = decorator;
throw new _syntaxError2.default(`Handlebars decorators are not supported: "${this.sourceForNode(decorator, decorator.path)}" at L${loc.start.line}:C${loc.start.column}`, decorator.loc);
}
DecoratorBlock(decoratorBlock) {
let { loc } = decoratorBlock;
throw new _syntaxError2.default(`Handlebars decorator blocks are not supported: "${this.sourceForNode(decoratorBlock, decoratorBlock.path)}" at L${loc.start.line}:C${loc.start.column}`, decoratorBlock.loc);
}
SubExpression(sexpr) {
let { path, params, hash } = acceptCallNodes(this, sexpr);
return _builders2.default.sexpr(path, params, hash, sexpr.loc);
}
PathExpression(path) {
let { original, loc } = path;
let parts;
if (original.indexOf('/') !== -1) {
if (original.slice(0, 2) === './') {
throw new _syntaxError2.default(`Using "./" is not supported in Glimmer and unnecessary: "${path.original}" on line ${loc.start.line}.`, path.loc);
}
if (original.slice(0, 3) === '../') {
throw new _syntaxError2.default(`Changing context using "../" is not supported in Glimmer: "${path.original}" on line ${loc.start.line}.`, path.loc);
}
if (original.indexOf('.') !== -1) {
throw new _syntaxError2.default(`Mixing '.' and '/' in paths is not supported in Glimmer; use only '.' to separate property paths: "${path.original}" on line ${loc.start.line}.`, path.loc);
}
parts = [path.parts.join('/')];
} else {
parts = path.parts;
}
let thisHead = false;
// This is to fix a bug in the Handlebars AST where the path expressions in
// `{{this.foo}}` (and similarly `{{foo-bar this.foo named=this.foo}}` etc)
// are simply turned into `{{foo}}`. The fix is to push it back onto the
// parts array and let the runtime see the difference. However, we cannot
// simply use the string `this` as it means literally the property called
// "this" in the current context (it can be expressed in the syntax as
// `{{[this]}}`, where the square bracket are generally for this kind of
// escaping – such as `{{foo.["bar.baz"]}}` would mean lookup a property
// named literally "bar.baz" on `this.foo`). By convention, we use `null`
// for this purpose.
if (original.match(/^this(\..+)?$/)) {
thisHead = true;
}
return {
type: 'PathExpression',
original: path.original,
this: thisHead,
parts,
data: path.data,
loc: path.loc
};
}
Hash(hash) {
let pairs = [];
for (let i = 0; i < hash.pairs.length; i++) {
let pair = hash.pairs[i];
pairs.push(_builders2.default.pair(pair.key, this.acceptNode(pair.value), pair.loc));
}
return _builders2.default.hash(pairs, hash.loc);
}
StringLiteral(string) {
return _builders2.default.literal('StringLiteral', string.value, string.loc);
}
BooleanLiteral(boolean) {
return _builders2.default.literal('BooleanLiteral', boolean.value, boolean.loc);
}
NumberLiteral(number) {
return _builders2.default.literal('NumberLiteral', number.value, number.loc);
}
UndefinedLiteral(undef) {
return _builders2.default.literal('UndefinedLiteral', undefined, undef.loc);
}
NullLiteral(nul) {
return _builders2.default.literal('NullLiteral', null, nul.loc);
}
}
exports.HandlebarsNodeVisitors = HandlebarsNodeVisitors;
function calculateRightStrippedOffsets(original, value) {
if (value === '') {
// if it is empty, just return the count of newlines
// in original
return {
lines: original.split("\n").length - 1,
columns: 0
};
}
// otherwise, return the number of newlines prior to
// `value`
let difference = original.split(value)[0];
let lines = difference.split(/\n/);
let lineCount = lines.length - 1;
return {
lines: lineCount,
columns: lines[lineCount].length
};
}
function updateTokenizerLocation(tokenizer, content) {
let line = content.loc.start.line;
let column = content.loc.start.column;
let offsets = calculateRightStrippedOffsets(content.original, content.value);
line = line + offsets.lines;
if (offsets.lines) {
column = offsets.columns;
} else {
column = column + offsets.columns;
}
tokenizer.line = line;
tokenizer.column = column;
}
function acceptCallNodes(compiler, node) {
let path = compiler.PathExpression(node.path);
let params = node.params ? node.params.map(e => compiler.acceptNode(e)) : [];
let hash = node.hash ? compiler.Hash(node.hash) : _builders2.default.hash();
return { path, params, hash };
}
function addElementModifier(element, mustache) {
let { path, params, hash, loc } = mustache;
if ((0, _utils.isLiteral)(path)) {
let modifier = `{{${(0, _utils.printLiteral)(path)}}}`;
let tag = `<${element.name} ... ${modifier} ...`;
throw new _syntaxError2.default(`In ${tag}, ${modifier} is not a valid modifier: "${path.original}" on line ${loc && loc.start.line}.`, mustache.loc);
}
let modifier = _builders2.default.elementModifier(path, params, hash, loc);
element.modifiers.push(modifier);
}
function appendDynamicAttributeValuePart(attribute, part) {
attribute.isDynamic = true;
attribute.parts.push(part);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9wYXJzZXIvaGFuZGxlYmFycy1ub2RlLXZpc2l0b3JzLmpzIl0sIm5hbWVzIjpbIkhhbmRsZWJhcnNOb2RlVmlzaXRvcnMiLCJQcm9ncmFtIiwicHJvZ3JhbSIsImJvZHkiLCJub2RlIiwiYmxvY2tQYXJhbXMiLCJsb2MiLCJpIiwibCIsImxlbmd0aCIsImVsZW1lbnRTdGFjayIsInB1c2giLCJwb3AiLCJhY2NlcHROb2RlIiwicG9wcGVkTm9kZSIsImVsZW1lbnROb2RlIiwidGFnIiwic3RhcnQiLCJsaW5lIiwiQmxvY2tTdGF0ZW1lbnQiLCJibG9jayIsInRva2VuaXplciIsImFwcGVuZFRvQ29tbWVudERhdGEiLCJzb3VyY2VGb3JOb2RlIiwicGF0aCIsInBhcmFtcyIsImhhc2giLCJhY2NlcHRDYWxsTm9kZXMiLCJpbnZlcnNlIiwicGFyZW50UHJvZ3JhbSIsImN1cnJlbnRFbGVtZW50IiwiTXVzdGFjaGVTdGF0ZW1lbnQiLCJyYXdNdXN0YWNoZSIsIm11c3RhY2hlIiwiZXNjYXBlZCIsInR5cGUiLCJtYXRjaCIsInN0YXRlIiwiYWRkRWxlbWVudE1vZGlmaWVyIiwiY3VycmVudFN0YXJ0VGFnIiwiYmVnaW5BdHRyaWJ1dGVWYWx1ZSIsImZpbmlzaEF0dHJpYnV0ZVZhbHVlIiwiYXBwZW5kRHluYW1pY0F0dHJpYnV0ZVZhbHVlUGFydCIsImN1cnJlbnRBdHRyaWJ1dGUiLCJDb250ZW50U3RhdGVtZW50IiwiY29udGVudCIsInVwZGF0ZVRva2VuaXplckxvY2F0aW9uIiwidG9rZW5pemVQYXJ0IiwidmFsdWUiLCJmbHVzaERhdGEiLCJDb21tZW50U3RhdGVtZW50IiwicmF3Q29tbWVudCIsImNvbW1lbnQiLCJtdXN0YWNoZUNvbW1lbnQiLCJjb21tZW50cyIsImNvbHVtbiIsIlBhcnRpYWxTdGF0ZW1lbnQiLCJwYXJ0aWFsIiwibmFtZSIsIlBhcnRpYWxCbG9ja1N0YXRlbWVudCIsInBhcnRpYWxCbG9jayIsIkRlY29yYXRvciIsImRlY29yYXRvciIsIkRlY29yYXRvckJsb2NrIiwiZGVjb3JhdG9yQmxvY2siLCJTdWJFeHByZXNzaW9uIiwic2V4cHIiLCJQYXRoRXhwcmVzc2lvbiIsIm9yaWdpbmFsIiwicGFydHMiLCJpbmRleE9mIiwic2xpY2UiLCJqb2luIiwidGhpc0hlYWQiLCJ0aGlzIiwiZGF0YSIsIkhhc2giLCJwYWlycyIsInBhaXIiLCJrZXkiLCJTdHJpbmdMaXRlcmFsIiwic3RyaW5nIiwibGl0ZXJhbCIsIkJvb2xlYW5MaXRlcmFsIiwiYm9vbGVhbiIsIk51bWJlckxpdGVyYWwiLCJudW1iZXIiLCJVbmRlZmluZWRMaXRlcmFsIiwidW5kZWYiLCJ1bmRlZmluZWQiLCJOdWxsTGl0ZXJhbCIsIm51bCIsImNhbGN1bGF0ZVJpZ2h0U3RyaXBwZWRPZmZzZXRzIiwibGluZXMiLCJzcGxpdCIsImNvbHVtbnMiLCJkaWZmZXJlbmNlIiwibGluZUNvdW50Iiwib2Zmc2V0cyIsImNvbXBpbGVyIiwibWFwIiwiZSIsImVsZW1lbnQiLCJtb2RpZmllciIsImVsZW1lbnRNb2RpZmllciIsIm1vZGlmaWVycyIsImF0dHJpYnV0ZSIsInBhcnQiLCJpc0R5bmFtaWMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7OztBQUNBOztBQUNBOztBQUNBOzs7Ozs7QUFDTyxNQUFNQSxzQkFBTix3QkFBNEM7QUFDL0NDLFlBQVFDLE9BQVIsRUFBaUI7QUFDYixZQUFJQyxPQUFPLEVBQVg7QUFDQSxZQUFJQyxPQUFPLG1CQUFFRixPQUFGLENBQVVDLElBQVYsRUFBZ0JELFFBQVFHLFdBQXhCLEVBQXFDSCxRQUFRSSxHQUE3QyxDQUFYO0FBQ0EsWUFBSUMsQ0FBSjtBQUFBLFlBQ0lDLElBQUlOLFFBQVFDLElBQVIsQ0FBYU0sTUFEckI7QUFFQSxhQUFLQyxZQUFMLENBQWtCQyxJQUFsQixDQUF1QlAsSUFBdkI7QUFDQSxZQUFJSSxNQUFNLENBQVYsRUFBYTtBQUNULG1CQUFPLEtBQUtFLFlBQUwsQ0FBa0JFLEdBQWxCLEVBQVA7QUFDSDtBQUNELGFBQUtMLElB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QUFSLENBQWtCOUYsSUFBbEIsQ0FBdUI0RixRQUF2QjtBQUNIO0FBQ0QsU0FBUzdELCtCQUFULENBQXlDZ0UsU0FBekMsRUFBb0RDLElBQXBELEVBQTBEO0FBQ3RERCxjQUFVRSxTQUFWLEdBQXNCLElBQXRCO0FBQ0FGLGNBQVVyQyxLQUFWLENBQWdCMUQsSUFBaEIsQ0FBcUJnRyxJQUFyQjtBQUNIIiwiZmlsZSI6ImxpYi9wYXJzZXIvaGFuZGxlYmFycy1ub2RlLXZpc2l0b3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGIgZnJvbSBcIi4uL2J1aWxkZXJzXCI7XG5pbXBvcnQgeyBhcHBlbmRDaGlsZCwgaXNMaXRlcmFsLCBwcmludExpdGVyYWwgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCB7IFBhcnNlciB9IGZyb20gJy4uL3BhcnNlcic7XG5pbXBvcnQgU3ludGF4RXJyb3IgZnJvbSAnLi4vZXJyb3JzL3N5bnRheC1lcnJvcic7XG5leHBvcnQgY2xhc3MgSGFuZGxlYmFyc05vZGVWaXNpdG9ycyBleHRlbmRzIFBhcnNlciB7XG4gICAgUHJvZ3JhbShwcm9ncmFtKSB7XG4gICAgICAgIGxldCBib2R5ID0gW107XG4gICAgICAgIGxldCBub2RlID0gYi5wcm9ncmFtKGJvZHksIHByb2dyYW0uYmxvY2tQYXJhbXMsIHByb2dyYW0ubG9jKTtcbiAgICAgICAgbGV0IGksXG4gICAgICAgICAgICBsID0gcHJvZ3JhbS5ib2R5Lmxlbmd0aDtcbiAgICAgICAgdGhpcy5lbGVtZW50U3RhY2sucHVzaChub2RlKTtcbiAgICAgICAgaWYgKGwgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRTdGFjay5wb3AoKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmFjY2VwdE5vZGUocHJvZ3JhbS5ib2R5W2ldKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBFbnN1cmUgdGhhdCB0aGF0IHRoZSBlbGVtZW50IHN0YWNrIGlzIGJhbGFuY2VkIHByb3Blcmx5LlxuICAgICAgICBsZXQgcG9wcGVkTm9kZSA9IHRoaXMuZWxlbWVudFN0YWNrLnBvcCgpO1xuICAgICAgICBpZiAocG9wcGVkTm9kZSAhPT0gbm9kZSkge1xuICAgICAgICAgICAgbGV0IGVsZW1lbnROb2RlID0gcG9wcGVkTm9kZTtcbiAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihcIlVuY2xvc2VkIGVsZW1lbnQgYFwiICsgZWxlbWVudE5vZGUudGFnICsgXCJgIChvbiBsaW5lIFwiICsgZWxlbWVudE5vZGUubG9jLnN0YXJ0LmxpbmUgKyBcIikuXCIsIGVsZW1lbnROb2RlLmxvYyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfVxuICAgIEJsb2NrU3RhdGVtZW50KGJsb2NrKSB7XG4gICAgICAgIGlmICh0aGlzLnRva2VuaXplclsnc3RhdGUnXSA9PT0gJ2NvbW1lbnQnKSB7XG4gICAgICAgICAgICB0aGlzLmFwcGVuZFRvQ29tbWVudERhdGEodGhpcy5zb3VyY2VGb3JOb2RlKGJsb2NrKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudG9rZW5pemVyWydzdGF0ZSddICE9PSAnY29tbWVudCcgJiYgdGhpcy50b2tlbml6ZXJbJ3N0YXRlJ10gIT09ICdkYXRhJyAmJiB0aGlzLnRva2VuaXplclsnc3RhdGUnXSAhPT0gJ2JlZm9yZURhdGEnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoXCJBIGJsb2NrIG1heSBvbmx5IGJlIHVzZWQgaW5zaWRlIGFuIEhUTUwgZWxlbWVudCBvciBhbm90aGVyIGJsb2NrLlwiLCBibG9jay5sb2MpO1xuICAgICAgICB9XG4gICAgICAgIGxldCB7IHBhdGgsIHBhcmFtcywgaGFzaCB9ID0gYWNjZXB0Q2FsbE5vZGVzKHRoaXMsIGJsb2NrKTtcbiAgICAgICAgbGV0IHByb2dyYW0gPSB0aGlzLlByb2dyYW0oYmxvY2sucHJvZ3JhbSk7XG4gICAgICAgIGxldCBpbnZlcnNlID0gYmxvY2suaW52ZXJzZSA/IHRoaXMuUHJvZ3JhbShibG9jay5pbnZlcnNlKSA6IG51bGw7XG4gICAgICAgIGxldCBub2RlID0gYi5ibG9jayhwYXRoLCBwYXJhbXMsIGhhc2gsIHByb2dyYW0sIGludmVyc2UsIGJsb2NrLmxvYyk7XG4gICAgICAgIGxldCBwYXJlbnRQcm9ncmFtID0gdGhpcy5jdXJyZW50RWxlbWVudCgpO1xuICAgICAgICBhcHBlbmRDaGlsZChwYXJlbnRQcm9ncmFtLCBub2RlKTtcbiAgICB9XG4gICAgTXVzdGFjaGVTdGF0ZW1lbnQocmF3TXVzdGFjaGUpIHtcbiAgICAgICAgbGV0IHsgdG9rZW5pemVyIH0gPSB0aGlzO1xuICAgICAgICBpZiAodG9rZW5pemVyWydzdGF0ZSddID09PSAnY29tbWVudCcpIHtcbiAgICAgICAgICAgIHRoaXMuYXBwZW5kVG9Db21tZW50RGF0YSh0aGlzLnNvdXJjZUZvck5vZGUocmF3TXVzdGFjaGUpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbXVzdGFjaGU7XG4gICAgICAgIGxldCB7IGVzY2FwZWQsIGxvYyB9ID0gcmF3TXVzdGFjaGU7XG4gICAgICAgIGlmIChyYXdNdXN0YWNoZS5wYXRoLnR5cGUubWF0Y2goL0xpdGVyYWwkLykpIHtcbiAgICAgICAgICAgIG11c3RhY2hlID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdNdXN0YWNoZVN0YXRlbWVudCcsXG4gICAgICAgICAgICAgICAgcGF0aDogdGhpcy5hY2NlcHROb2RlKHJhd011c3RhY2hlLnBhdGgpLFxuICAgICAgICAgICAgICAgIHBhcmFtczogW10sXG4gICAgICAgICAgICAgICAgaGFzaDogYi5oYXNoKCksXG4gICAgICAgICAgICAgICAgZXNjYXBlZCxcbiAgICAgICAgICAgICAgICBsb2NcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsZXQgeyBwYXRoLCBwYXJhbXMsIGhhc2ggfSA9IGFjY2VwdENhbGxOb2Rlcyh0aGlzLCByYXdNdXN0YWNoZSk7XG4gICAgICAgICAgICBtdXN0YWNoZSA9IGIubXVzdGFjaGUocGF0aCwgcGFyYW1zLCBoYXNoLCAhZXNjYXBlZCwgbG9jKTtcbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKHRva2VuaXplci5zdGF0ZSkge1xuICAgICAgICAgICAgLy8gVGFnIGhlbHBlcnNcbiAgICAgICAgICAgIGNhc2UgXCJ0YWdOYW1lXCI6XG4gICAgICAgICAgICAgICAgYWRkRWxlbWVudE1vZGlmaWVyKHRoaXMuY3VycmVudFN0YXJ0VGFnLCBtdXN0YWNoZSk7XG4gICAgICAgICAgICAgICAgdG9rZW5pemVyLnN0YXRlID0gXCJiZWZvcmVBdHRyaWJ1dGVOYW1lXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiYmVmb3JlQXR0cmlidXRlTmFtZVwiOlxuICAgICAgICAgICAgICAgIGFkZEVsZW1lbnRNb2RpZmllcih0aGlzLmN1cnJlbnRTdGFydFRhZywgbXVzdGFjaGUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImF0dHJpYnV0ZU5hbWVcIjpcbiAgICAgICAgICAgIGNhc2UgXCJhZnRlckF0dHJpYnV0ZU5hbWVcIjpcbiAgICAgICAgICAgICAgICB0aGlzLmJlZ2luQXR0cmlidXRlVmFsdWUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoQXR0cmlidXRlVmFsdWUoKTtcbiAgICAgICAgICAgICAgICBhZGRFbGVtZW50TW9kaWZpZXIodGhpcy5jdXJyZW50U3RhcnRUYWcsIG11c3RhY2hlKTtcbiAgICAgICAgICAgICAgICB0b2tlbml6ZXIuc3RhdGUgPSBcImJlZm9yZUF0dHJpYnV0ZU5hbWVcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJhZnRlckF0dHJpYnV0ZVZhbHVlUXVvdGVkXCI6XG4gICAgICAgICAgICAgICAgYWRkRWxlbWVudE1vZGlmaWVyKHRoaXMuY3VycmVudFN0YXJ0VGFnLCBtdXN0YWNoZSk7XG4gICAgICAgICAgICAgICAgdG9rZW5pemVyLnN0YXRlID0gXCJiZWZvcmVBdHRyaWJ1dGVOYW1lXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyBBdHRyaWJ1dGUgdmFsdWVzXG4gICAgICAgICAgICBjYXNlIFwiYmVmb3JlQXR0cmlidXRlVmFsdWVcIjpcbiAgICAgICAgICAgICAgICBhcHBlbmREeW5hbWljQXR0cmlidXRlVmFsdWVQYXJ0KHRoaXMuY3VycmVudEF0dHJpYnV0ZSwgbXVzdGFjaGUpO1xuICAgICAgICAgICAgICAgIHRva2VuaXplci5zdGF0ZSA9ICdhdHRyaWJ1dGVWYWx1ZVVucXVvdGVkJztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJhdHRyaWJ1dGVWYWx1ZURvdWJsZVF1b3RlZFwiOlxuICAgICAgICAgICAgY2FzZSBcImF0dHJpYnV0ZVZhbHVlU2luZ2xlUXVvdGVkXCI6XG4gICAgICAgICAgICBjYXNlIFwiYXR0cmlidXRlVmFsdWVVbnF1b3RlZFwiOlxuICAgICAgICAgICAgICAgIGFwcGVuZER5bmFtaWNBdHRyaWJ1dGVWYWx1ZVBhcnQodGhpcy5jdXJyZW50QXR0cmlidXRlLCBtdXN0YWNoZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyBUT0RPOiBPbmx5IGFwcGVuZCBjaGlsZCB3aGVuIHRoZSB0b2tlbml6ZXIgc3RhdGUgbWFrZXNcbiAgICAgICAgICAgIC8vIHNlbnNlIHRvIGRvIHNvLCBvdGhlcndpc2UgdGhyb3cgYW4gZXJyb3IuXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGFwcGVuZENoaWxkKHRoaXMuY3VycmVudEVsZW1lbnQoKSwgbXVzdGFjaGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtdXN0YWNoZTtcbiAgICB9XG4gICAgQ29udGVudFN0YXRlbWVudChjb250ZW50KSB7XG4gICAgICAgIHVwZGF0ZVRva2VuaXplckxvY2F0aW9uKHRoaXMudG9rZW5pemVyLCBjb250ZW50KTtcbiAgICAgICAgdGhpcy50b2tlbml6ZXIudG9rZW5pemVQYXJ0KGNvbnRlbnQudmFsdWUpO1xuICAgICAgICB0aGlzLnRva2VuaXplci5mbHVzaERhdGEoKTtcbiAgICB9XG4gICAgQ29tbWVudFN0YXRlbWVudChyYXdDb21tZW50KSB7XG4gICAgICAgIGxldCB7IHRva2VuaXplciB9ID0gdGhpcztcbiAgICAgICAgaWYgKHRva2VuaXplci5zdGF0ZSA9PT0gJ2NvbW1lbnQnKSB7XG4gICAgICAgICAgICB0aGlzLmFwcGVuZFRvQ29tbWVudERhdGEodGhpcy5zb3VyY2VGb3JOb2RlKHJhd0NvbW1lbnQpKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGxldCB7IHZhbHVlLCBsb2MgfSA9IHJhd0NvbW1lbnQ7XG4gICAgICAgIGxldCBjb21tZW50ID0gYi5tdXN0YWNoZUNvbW1lbnQodmFsdWUsIGxvYyk7XG4gICAgICAgIHN3aXRjaCAodG9rZW5pemVyLnN0YXRlKSB7XG4gICAgICAgICAgICBjYXNlIFwiYmVmb3JlQXR0cmlidXRlTmFtZVwiOlxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFN0YXJ0VGFnLmNvbW1lbnRzLnB1c2goY29tbWVudCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdiZWZvcmVEYXRhJzpcbiAgICAgICAgICAgIGNhc2UgJ2RhdGEnOlxuICAgICAgICAgICAgICAgIGFwcGVuZENoaWxkKHRoaXMuY3VycmVudEVsZW1lbnQoKSwgY29tbWVudCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgVXNpbmcgYSBIYW5kbGViYXJzIGNvbW1lbnQgd2hlbiBpbiB0aGUgXFxgJHt0b2tlbml6ZXIuc3RhdGV9XFxgIHN0YXRlIGlzIG5vdCBzdXBwb3J0ZWQ6IFwiJHtjb21tZW50LnZhbHVlfVwiIG9uIGxpbmUgJHtsb2Muc3RhcnQubGluZX06JHtsb2Muc3RhcnQuY29sdW1ufWAsIHJhd0NvbW1lbnQubG9jKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tbWVudDtcbiAgICB9XG4gICAgUGFydGlhbFN0YXRlbWVudChwYXJ0aWFsKSB7XG4gICAgICAgIGxldCB7IGxvYyB9ID0gcGFydGlhbDtcbiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKGBIYW5kbGViYXJzIHBhcnRpYWxzIGFyZSBub3Qgc3VwcG9ydGVkOiBcIiR7dGhpcy5zb3VyY2VGb3JOb2RlKHBhcnRpYWwsIHBhcnRpYWwubmFtZSl9XCIgYXQgTCR7bG9jLnN0YXJ0LmxpbmV9OkMke2xvYy5zdGFydC5jb2x1bW59YCwgcGFydGlhbC5sb2MpO1xuICAgIH1cbiAgICBQYXJ0aWFsQmxvY2tTdGF0ZW1lbnQocGFydGlhbEJsb2NrKSB7XG4gICAgICAgIGxldCB7IGxvYyB9ID0gcGFydGlhbEJsb2NrO1xuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYEhhbmRsZWJhcnMgcGFydGlhbCBibG9ja3MgYXJlIG5vdCBzdXBwb3J0ZWQ6IFwiJHt0aGlzLnNvdXJjZUZvck5vZGUocGFydGlhbEJsb2NrLCBwYXJ0aWFsQmxvY2submFtZSl9XCIgYXQgTCR7bG9jLnN0YXJ0LmxpbmV9OkMke2xvYy5zdGFydC5jb2x1bW59YCwgcGFydGlhbEJsb2NrLmxvYyk7XG4gICAgfVxuICAgIERlY29yYXRvcihkZWNvcmF0b3IpIHtcbiAgICAgICAgbGV0IHsgbG9jIH0gPSBkZWNvcmF0b3I7XG4gICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcihgSGFuZGxlYmFycyBkZWNvcmF0b3JzIGFyZSBub3Qgc3VwcG9ydGVkOiBcIiR7dGhpcy5zb3VyY2VGb3JOb2RlKGRlY29yYXRvciwgZGVjb3JhdG9yLnBhdGgpfVwiIGF0IEwke2xvYy5zdGFydC5saW5lfTpDJHtsb2Muc3RhcnQuY29sdW1ufWAsIGRlY29yYXRvci5sb2MpO1xuICAgIH1cbiAgICBEZWNvcmF0b3JCbG9jayhkZWNvcmF0b3JCbG9jaykge1xuICAgICAgICBsZXQgeyBsb2MgfSA9IGRlY29yYXRvckJsb2NrO1xuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYEhhbmRsZWJhcnMgZGVjb3JhdG9yIGJsb2NrcyBhcmUgbm90IHN1cHBvcnRlZDogXCIke3RoaXMuc291cmNlRm9yTm9kZShkZWNvcmF0b3JCbG9jaywgZGVjb3JhdG9yQmxvY2sucGF0aCl9XCIgYXQgTCR7bG9jLnN0YXJ0LmxpbmV9OkMke2xvYy5zdGFydC5jb2x1bW59YCwgZGVjb3JhdG9yQmxvY2subG9jKTtcbiAgICB9XG4gICAgU3ViRXhwcmVzc2lvbihzZXhwcikge1xuICAgICAgICBsZXQgeyBwYXRoLCBwYXJhbXMsIGhhc2ggfSA9IGFjY2VwdENhbGxOb2Rlcyh0aGlzLCBzZXhwcik7XG4gICAgICAgIHJldHVybiBiLnNleHByKHBhdGgsIHBhcmFtcywgaGFzaCwgc2V4cHIubG9jKTtcbiAgICB9XG4gICAgUGF0aEV4cHJlc3Npb24ocGF0aCkge1xuICAgICAgICBsZXQgeyBvcmlnaW5hbCwgbG9jIH0gPSBwYXRoO1xuICAgICAgICBsZXQgcGFydHM7XG4gICAgICAgIGlmIChvcmlnaW5hbC5pbmRleE9mKCcvJykgIT09IC0xKSB7XG4gICAgICAgICAgICBpZiAob3JpZ2luYWwuc2xpY2UoMCwgMikgPT09ICcuLycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYFVzaW5nIFwiLi9cIiBpcyBub3Qgc3VwcG9ydGVkIGluIEdsaW1tZXIgYW5kIHVubmVjZXNzYXJ5OiBcIiR7cGF0aC5vcmlnaW5hbH1cIiBvbiBsaW5lICR7bG9jLnN0YXJ0LmxpbmV9LmAsIHBhdGgubG9jKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcmlnaW5hbC5zbGljZSgwLCAzKSA9PT0gJy4uLycpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYENoYW5naW5nIGNvbnRleHQgdXNpbmcgXCIuLi9cIiBpcyBub3Qgc3VwcG9ydGVkIGluIEdsaW1tZXI6IFwiJHtwYXRoLm9yaWdpbmFsfVwiIG9uIGxpbmUgJHtsb2Muc3RhcnQubGluZX0uYCwgcGF0aC5sb2MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9yaWdpbmFsLmluZGV4T2YoJy4nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYE1peGluZyAnLicgYW5kICcvJyBpbiBwYXRocyBpcyBub3Qgc3VwcG9ydGVkIGluIEdsaW1tZXI7IHVzZSBvbmx5ICcuJyB0byBzZXBhcmF0ZSBwcm9wZXJ0eSBwYXRoczogXCIke3BhdGgub3JpZ2luYWx9XCIgb24gbGluZSAke2xvYy5zdGFydC5saW5lfS5gLCBwYXRoLmxvYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJ0cyA9IFtwYXRoLnBhcnRzLmpvaW4oJy8nKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXJ0cyA9IHBhdGgucGFydHM7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHRoaXNIZWFkID0gZmFsc2U7XG4gICAgICAgIC8vIFRoaXMgaXMgdG8gZml4IGEgYnVnIGluIHRoZSBIYW5kbGViYXJzIEFTVCB3aGVyZSB0aGUgcGF0aCBleHByZXNzaW9ucyBpblxuICAgICAgICAvLyBge3t0aGlzLmZvb319YCAoYW5kIHNpbWlsYXJseSBge3tmb28tYmFyIHRoaXMuZm9vIG5hbWVkPXRoaXMuZm9vfX1gIGV0YylcbiAgICAgICAgLy8gYXJlIHNpbXBseSB0dXJuZWQgaW50byBge3tmb299fWAuIFRoZSBmaXggaXMgdG8gcHVzaCBpdCBiYWNrIG9udG8gdGhlXG4gICAgICAgIC8vIHBhcnRzIGFycmF5IGFuZCBsZXQgdGhlIHJ1bnRpbWUgc2VlIHRoZSBkaWZmZXJlbmNlLiBIb3dldmVyLCB3ZSBjYW5ub3RcbiAgICAgICAgLy8gc2ltcGx5IHVzZSB0aGUgc3RyaW5nIGB0aGlzYCBhcyBpdCBtZWFucyBsaXRlcmFsbHkgdGhlIHByb3BlcnR5IGNhbGxlZFxuICAgICAgICAvLyBcInRoaXNcIiBpbiB0aGUgY3VycmVudCBjb250ZXh0IChpdCBjYW4gYmUgZXhwcmVzc2VkIGluIHRoZSBzeW50YXggYXNcbiAgICAgICAgLy8gYHt7W3RoaXNdfX1gLCB3aGVyZSB0aGUgc3F1YXJlIGJyYWNrZXQgYXJlIGdlbmVyYWxseSBmb3IgdGhpcyBraW5kIG9mXG4gICAgICAgIC8vIGVzY2FwaW5nIOKAkyBzdWNoIGFzIGB7e2Zvby5bXCJiYXIuYmF6XCJdfX1gIHdvdWxkIG1lYW4gbG9va3VwIGEgcHJvcGVydHlcbiAgICAgICAgLy8gbmFtZWQgbGl0ZXJhbGx5IFwiYmFyLmJhelwiIG9uIGB0aGlzLmZvb2ApLiBCeSBjb252ZW50aW9uLCB3ZSB1c2UgYG51bGxgXG4gICAgICAgIC8vIGZvciB0aGlzIHB1cnBvc2UuXG4gICAgICAgIGlmIChvcmlnaW5hbC5tYXRjaCgvXnRoaXMoXFwuLispPyQvKSkge1xuICAgICAgICAgICAgdGhpc0hlYWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiAnUGF0aEV4cHJlc3Npb24nLFxuICAgICAgICAgICAgb3JpZ2luYWw6IHBhdGgub3JpZ2luYWwsXG4gICAgICAgICAgICB0aGlzOiB0aGlzSGVhZCxcbiAgICAgICAgICAgIHBhcnRzLFxuICAgICAgICAgICAgZGF0YTogcGF0aC5kYXRhLFxuICAgICAgICAgICAgbG9jOiBwYXRoLmxvY1xuICAgICAgICB9O1xuICAgIH1cbiAgICBIYXNoKGhhc2gpIHtcbiAgICAgICAgbGV0IHBhaXJzID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGFzaC5wYWlycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IHBhaXIgPSBoYXNoLnBhaXJzW2ldO1xuICAgICAgICAgICAgcGFpcnMucHVzaChiLnBhaXIocGFpci5rZXksIHRoaXMuYWNjZXB0Tm9kZShwYWlyLnZhbHVlKSwgcGFpci5sb2MpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYi5oYXNoKHBhaXJzLCBoYXNoLmxvYyk7XG4gICAgfVxuICAgIFN0cmluZ0xpdGVyYWwoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBiLmxpdGVyYWwoJ1N0cmluZ0xpdGVyYWwnLCBzdHJpbmcudmFsdWUsIHN0cmluZy5sb2MpO1xuICAgIH1cbiAgICBCb29sZWFuTGl0ZXJhbChib29sZWFuKSB7XG4gICAgICAgIHJldHVybiBiLmxpdGVyYWwoJ0Jvb2xlYW5MaXRlcmFsJywgYm9vbGVhbi52YWx1ZSwgYm9vbGVhbi5sb2MpO1xuICAgIH1cbiAgICBOdW1iZXJMaXRlcmFsKG51bWJlcikge1xuICAgICAgICByZXR1cm4gYi5saXRlcmFsKCdOdW1iZXJMaXRlcmFsJywgbnVtYmVyLnZhbHVlLCBudW1iZXIubG9jKTtcbiAgICB9XG4gICAgVW5kZWZpbmVkTGl0ZXJhbCh1bmRlZikge1xuICAgICAgICByZXR1cm4gYi5saXRlcmFsKCdVbmRlZmluZWRMaXRlcmFsJywgdW5kZWZpbmVkLCB1bmRlZi5sb2MpO1xuICAgIH1cbiAgICBOdWxsTGl0ZXJhbChudWwpIHtcbiAgICAgICAgcmV0dXJuIGIubGl0ZXJhbCgnTnVsbExpdGVyYWwnLCBudWxsLCBudWwubG9jKTtcbiAgICB9XG59XG5mdW5jdGlvbiBjYWxjdWxhdGVSaWdodFN0cmlwcGVkT2Zmc2V0cyhvcmlnaW5hbCwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT09ICcnKSB7XG4gICAgICAgIC8vIGlmIGl0IGlzIGVtcHR5LCBqdXN0IHJldHVybiB0aGUgY291bnQgb2YgbmV3bGluZXNcbiAgICAgICAgLy8gaW4gb3JpZ2luYWxcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxpbmVzOiBvcmlnaW5hbC5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxLFxuICAgICAgICAgICAgY29sdW1uczogMFxuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBvdGhlcndpc2UsIHJldHVybiB0aGUgbnVtYmVyIG9mIG5ld2xpbmVzIHByaW9yIHRvXG4gICAgLy8gYHZhbHVlYFxuICAgIGxldCBkaWZmZXJlbmNlID0gb3JpZ2luYWwuc3BsaXQodmFsdWUpWzBdO1xuICAgIGxldCBsaW5lcyA9IGRpZmZlcmVuY2Uuc3BsaXQoL1xcbi8pO1xuICAgIGxldCBsaW5lQ291bnQgPSBsaW5lcy5sZW5ndGggLSAxO1xuICAgIHJldHVybiB7XG4gICAgICAgIGxpbmVzOiBsaW5lQ291bnQsXG4gICAgICAgIGNvbHVtbnM6IGxpbmVzW2xpbmVDb3VudF0ubGVuZ3RoXG4gICAgfTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZVRva2VuaXplckxvY2F0aW9uKHRva2VuaXplciwgY29udGVudCkge1xuICAgIGxldCBsaW5lID0gY29udGVudC5sb2Muc3RhcnQubGluZTtcbiAgICBsZXQgY29sdW1uID0gY29udGVudC5sb2Muc3RhcnQuY29sdW1uO1xuICAgIGxldCBvZmZzZXRzID0gY2FsY3VsYXRlUmlnaHRTdHJpcHBlZE9mZnNldHMoY29udGVudC5vcmlnaW5hbCwgY29udGVudC52YWx1ZSk7XG4gICAgbGluZSA9IGxpbmUgKyBvZmZzZXRzLmxpbmVzO1xuICAgIGlmIChvZmZzZXRzLmxpbmVzKSB7XG4gICAgICAgIGNvbHVtbiA9IG9mZnNldHMuY29sdW1ucztcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb2x1bW4gPSBjb2x1bW4gKyBvZmZzZXRzLmNvbHVtbnM7XG4gICAgfVxuICAgIHRva2VuaXplci5saW5lID0gbGluZTtcbiAgICB0b2tlbml6ZXIuY29sdW1uID0gY29sdW1uO1xufVxuZnVuY3Rpb24gYWNjZXB0Q2FsbE5vZGVzKGNvbXBpbGVyLCBub2RlKSB7XG4gICAgbGV0IHBhdGggPSBjb21waWxlci5QYXRoRXhwcmVzc2lvbihub2RlLnBhdGgpO1xuICAgIGxldCBwYXJhbXMgPSBub2RlLnBhcmFtcyA/IG5vZGUucGFyYW1zLm1hcChlID0+IGNvbXBpbGVyLmFjY2VwdE5vZGUoZSkpIDogW107XG4gICAgbGV0IGhhc2ggPSBub2RlLmhhc2ggPyBjb21waWxlci5IYXNoKG5vZGUuaGFzaCkgOiBiLmhhc2goKTtcbiAgICByZXR1cm4geyBwYXRoLCBwYXJhbXMsIGhhc2ggfTtcbn1cbmZ1bmN0aW9uIGFkZEVsZW1lbnRNb2RpZmllcihlbGVtZW50LCBtdXN0YWNoZSkge1xuICAgIGxldCB7IHBhdGgsIHBhcmFtcywgaGFzaCwgbG9jIH0gPSBtdXN0YWNoZTtcbiAgICBpZiAoaXNMaXRlcmFsKHBhdGgpKSB7XG4gICAgICAgIGxldCBtb2RpZmllciA9IGB7eyR7cHJpbnRMaXRlcmFsKHBhdGgpfX19YDtcbiAgICAgICAgbGV0IHRhZyA9IGA8JHtlbGVtZW50Lm5hbWV9IC4uLiAke21vZGlmaWVyfSAuLi5gO1xuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYEluICR7dGFnfSwgJHttb2RpZmllcn0gaXMgbm90IGEgdmFsaWQgbW9kaWZpZXI6IFwiJHtwYXRoLm9yaWdpbmFsfVwiIG9uIGxpbmUgJHtsb2MgJiYgbG9jLnN0YXJ0LmxpbmV9LmAsIG11c3RhY2hlLmxvYyk7XG4gICAgfVxuICAgIGxldCBtb2RpZmllciA9IGIuZWxlbWVudE1vZGlmaWVyKHBhdGgsIHBhcmFtcywgaGFzaCwgbG9jKTtcbiAgICBlbGVtZW50Lm1vZGlmaWVycy5wdXNoKG1vZGlmaWVyKTtcbn1cbmZ1bmN0aW9uIGFwcGVuZER5bmFtaWNBdHRyaWJ1dGVWYWx1ZVBhcnQoYXR0cmlidXRlLCBwYXJ0KSB7XG4gICAgYXR0cmlidXRlLmlzRHluYW1pYyA9IHRydWU7XG4gICAgYXR0cmlidXRlLnBhcnRzLnB1c2gocGFydCk7XG59Il19