@glimmer/compiler
Version:
428 lines (365 loc) • 41.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.BlockSymbolTable = exports.ProgramSymbolTable = exports.SymbolTable = undefined;
var _util = require("@glimmer/util");
var _createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
}
}return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
};
}();
function _defaults(obj, defaults) {
var keys = Object.getOwnPropertyNames(defaults);for (var i = 0; i < keys.length; i++) {
var key = keys[i];var value = Object.getOwnPropertyDescriptor(defaults, key);if (value && value.configurable && obj[key] === undefined) {
Object.defineProperty(obj, key, value);
}
}return obj;
}
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}return call && (typeof call === "object" || typeof call === "function") ? call : self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var SymbolTable = exports.SymbolTable = function () {
function SymbolTable() {
_classCallCheck(this, SymbolTable);
}
SymbolTable.top = function top() {
return new ProgramSymbolTable();
};
SymbolTable.prototype.child = function child(locals) {
var _this = this;
var symbols = locals.map(function (name) {
return _this.allocate(name);
});
return new BlockSymbolTable(this, locals, symbols);
};
return SymbolTable;
}();
var ProgramSymbolTable = exports.ProgramSymbolTable = function (_SymbolTable) {
_inherits(ProgramSymbolTable, _SymbolTable);
function ProgramSymbolTable() {
_classCallCheck(this, ProgramSymbolTable);
var _this2 = _possibleConstructorReturn(this, _SymbolTable.apply(this, arguments));
_this2.symbols = [];
_this2.size = 1;
_this2.named = (0, _util.dict)();
_this2.blocks = (0, _util.dict)();
return _this2;
}
ProgramSymbolTable.prototype.has = function has(_name) {
return false;
};
ProgramSymbolTable.prototype.get = function get(_name) {
throw (0, _util.unreachable)();
};
ProgramSymbolTable.prototype.getLocalsMap = function getLocalsMap() {
return {};
};
ProgramSymbolTable.prototype.getEvalInfo = function getEvalInfo() {
return [];
};
ProgramSymbolTable.prototype.allocateNamed = function allocateNamed(name) {
var named = this.named[name];
if (!named) {
named = this.named[name] = this.allocate(name);
}
return named;
};
ProgramSymbolTable.prototype.allocateBlock = function allocateBlock(name) {
if (name === 'inverse') {
name = 'else';
}
var block = this.blocks[name];
if (!block) {
block = this.blocks[name] = this.allocate('&' + name);
}
return block;
};
ProgramSymbolTable.prototype.allocate = function allocate(identifier) {
this.symbols.push(identifier);
return this.size++;
};
return ProgramSymbolTable;
}(SymbolTable);
var BlockSymbolTable = exports.BlockSymbolTable = function (_SymbolTable2) {
_inherits(BlockSymbolTable, _SymbolTable2);
function BlockSymbolTable(parent, symbols, slots) {
_classCallCheck(this, BlockSymbolTable);
var _this3 = _possibleConstructorReturn(this, _SymbolTable2.call(this));
_this3.parent = parent;
_this3.symbols = symbols;
_this3.slots = slots;
return _this3;
}
BlockSymbolTable.prototype.has = function has(name) {
return this.symbols.indexOf(name) !== -1 || this.parent.has(name);
};
BlockSymbolTable.prototype.get = function get(name) {
var slot = this.symbols.indexOf(name);
return slot === -1 ? this.parent.get(name) : this.slots[slot];
};
BlockSymbolTable.prototype.getLocalsMap = function getLocalsMap() {
var _this4 = this;
var dict = this.parent.getLocalsMap();
this.symbols.forEach(function (symbol) {
return dict[symbol] = _this4.get(symbol);
});
return dict;
};
BlockSymbolTable.prototype.getEvalInfo = function getEvalInfo() {
var locals = this.getLocalsMap();
return Object.keys(locals).map(function (symbol) {
return locals[symbol];
});
};
BlockSymbolTable.prototype.allocateNamed = function allocateNamed(name) {
return this.parent.allocateNamed(name);
};
BlockSymbolTable.prototype.allocateBlock = function allocateBlock(name) {
return this.parent.allocateBlock(name);
};
BlockSymbolTable.prototype.allocate = function allocate(identifier) {
return this.parent.allocate(identifier);
};
return BlockSymbolTable;
}(SymbolTable);
/**
* Takes in an AST and outputs a list of actions to be consumed
* by a compiler. For example, the template
*
* foo{{bar}}<div>baz</div>
*
* produces the actions
*
* [['startProgram', [programNode, 0]],
* ['text', [textNode, 0, 3]],
* ['mustache', [mustacheNode, 1, 3]],
* ['openElement', [elementNode, 2, 3, 0]],
* ['text', [textNode, 0, 1]],
* ['closeElement', [elementNode, 2, 3],
* ['endProgram', [programNode]]]
*
* This visitor walks the AST depth first and backwards. As
* a result the bottom-most child template will appear at the
* top of the actions list whereas the root template will appear
* at the bottom of the list. For example,
*
* <div>{{#if}}foo{{else}}bar<b></b>{{/if}}</div>
*
* produces the actions
*
* [['startProgram', [programNode, 0]],
* ['text', [textNode, 0, 2, 0]],
* ['openElement', [elementNode, 1, 2, 0]],
* ['closeElement', [elementNode, 1, 2]],
* ['endProgram', [programNode]],
* ['startProgram', [programNode, 0]],
* ['text', [textNode, 0, 1]],
* ['endProgram', [programNode]],
* ['startProgram', [programNode, 2]],
* ['openElement', [elementNode, 0, 1, 1]],
* ['block', [blockNode, 0, 1]],
* ['closeElement', [elementNode, 0, 1]],
* ['endProgram', [programNode]]]
*
* The state of the traversal is maintained by a stack of frames.
* Whenever a node with children is entered (either a ProgramNode
* or an ElementNode) a frame is pushed onto the stack. The frame
* contains information about the state of the traversal of that
* node. For example,
*
* - index of the current child node being visited
* - the number of mustaches contained within its child nodes
* - the list of actions generated by its child nodes
*/
var Frame = function Frame() {
_classCallCheck(this, Frame);
this.parentNode = null;
this.children = null;
this.childIndex = null;
this.childCount = null;
this.childTemplateCount = 0;
this.mustacheCount = 0;
this.actions = [];
this.blankChildTextNodes = null;
this.symbols = null;
};
var TemplateVisitor = function () {
function TemplateVisitor() {
_classCallCheck(this, TemplateVisitor);
this.frameStack = [];
this.actions = [];
this.programDepth = -1;
}
TemplateVisitor.prototype.visit = function visit(node) {
this[node.type](node);
};
// Traversal methods
TemplateVisitor.prototype.Block = function Block(program) {
return this.anyBlock(program);
};
TemplateVisitor.prototype.Template = function Template(program) {
return this.anyBlock(program);
};
TemplateVisitor.prototype.anyBlock = function anyBlock(program) {
var _actions;
this.programDepth++;
var parentFrame = this.getCurrentFrame();
var programFrame = this.pushFrame();
if (!parentFrame) {
program.symbols = SymbolTable.top();
} else {
program.symbols = parentFrame.symbols.child(program.blockParams);
}
var startType = void 0,
endType = void 0;
if (this.programDepth === 0) {
startType = 'startProgram';
endType = 'endProgram';
} else {
startType = 'startBlock';
endType = 'endBlock';
}
programFrame.parentNode = program;
programFrame.children = program.body;
programFrame.childCount = program.body.length;
programFrame.blankChildTextNodes = [];
programFrame.actions.push([endType, [program, this.programDepth]]);
programFrame.symbols = program['symbols'];
for (var i = program.body.length - 1; i >= 0; i--) {
programFrame.childIndex = i;
this.visit(program.body[i]);
}
programFrame.actions.push([startType, [program, programFrame.childTemplateCount, programFrame.blankChildTextNodes.reverse()]]);
this.popFrame();
this.programDepth--;
// Push the completed template into the global actions list
if (parentFrame) {
parentFrame.childTemplateCount++;
}
(_actions = this.actions).push.apply(_actions, programFrame.actions.reverse());
};
TemplateVisitor.prototype.ElementNode = function ElementNode(element) {
var _parentFrame$actions;
var parentFrame = this.currentFrame;
var elementFrame = this.pushFrame();
elementFrame.parentNode = element;
elementFrame.children = element.children;
elementFrame.childCount = element.children.length;
elementFrame.mustacheCount += element.modifiers.length;
elementFrame.blankChildTextNodes = [];
elementFrame.symbols = element.symbols = parentFrame.symbols.child(element.blockParams);
var actionArgs = [element, parentFrame.childIndex, parentFrame.childCount];
elementFrame.actions.push(['closeElement', actionArgs]);
for (var i = element.attributes.length - 1; i >= 0; i--) {
this.visit(element.attributes[i]);
}
for (var _i = element.children.length - 1; _i >= 0; _i--) {
elementFrame.childIndex = _i;
this.visit(element.children[_i]);
}
var open = ['openElement', [].concat(actionArgs, [elementFrame.mustacheCount, elementFrame.blankChildTextNodes.reverse()])];
elementFrame.actions.push(open);
this.popFrame();
// Propagate the element's frame state to the parent frame
if (elementFrame.mustacheCount > 0) {
parentFrame.mustacheCount++;
}
parentFrame.childTemplateCount += elementFrame.childTemplateCount;
(_parentFrame$actions = parentFrame.actions).push.apply(_parentFrame$actions, elementFrame.actions);
};
TemplateVisitor.prototype.AttrNode = function AttrNode(attr) {
if (attr.value.type !== 'TextNode') {
this.currentFrame.mustacheCount++;
}
};
TemplateVisitor.prototype.TextNode = function TextNode(text) {
var frame = this.currentFrame;
if (text.chars === '') {
frame.blankChildTextNodes.push(domIndexOf(frame.children, text));
}
frame.actions.push(['text', [text, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.BlockStatement = function BlockStatement(node) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['block', [node, frame.childIndex, frame.childCount]]);
if (node.inverse) {
this.visit(node.inverse);
}
if (node.program) {
this.visit(node.program);
}
};
TemplateVisitor.prototype.PartialStatement = function PartialStatement(node) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['mustache', [node, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.CommentStatement = function CommentStatement(text) {
var frame = this.currentFrame;
frame.actions.push(['comment', [text, frame.childIndex, frame.childCount]]);
};
TemplateVisitor.prototype.MustacheCommentStatement = function MustacheCommentStatement() {
// Intentional empty: Handlebars comments should not affect output.
};
TemplateVisitor.prototype.MustacheStatement = function MustacheStatement(mustache) {
var frame = this.currentFrame;
frame.mustacheCount++;
frame.actions.push(['mustache', [mustache, frame.childIndex, frame.childCount]]);
};
// Frame helpers
TemplateVisitor.prototype.getCurrentFrame = function getCurrentFrame() {
return this.frameStack[this.frameStack.length - 1];
};
TemplateVisitor.prototype.pushFrame = function pushFrame() {
var frame = new Frame();
this.frameStack.push(frame);
return frame;
};
TemplateVisitor.prototype.popFrame = function popFrame() {
return this.frameStack.pop();
};
_createClass(TemplateVisitor, [{
key: 'currentFrame',
get: function get() {
return this.getCurrentFrame();
}
}]);
return TemplateVisitor;
}();
// Returns the index of `domNode` in the `nodes` array, skipping
// over any nodes which do not represent DOM nodes.
exports.default = TemplateVisitor;
function domIndexOf(nodes, domNode) {
var index = -1;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
if (node.type !== 'TextNode' && node.type !== 'ElementNode') {
continue;
} else {
index++;
}
if (node === domNode) {
return index;
}
}
return -1;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL2NvbXBpbGVyL2xpYi90ZW1wbGF0ZS12aXNpdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFHQSxJQUFBLG9DQUFBLFlBQUE7QUFBQSxhQUFBLFdBQUEsR0FBQTtBQUFBLHdCQUFBLElBQUEsRUFBQSxXQUFBO0FBQUE7O0FBQUEsZ0JBQUEsR0FBQSxHQUFBLFNBQUEsR0FBQSxHQUNZO0FBQ1IsZUFBTyxJQUFQLGtCQUFPLEVBQVA7QUFGSixLQUFBOztBQUFBLGdCQUFBLFNBQUEsQ0FBQSxLQUFBLEdBQUEsU0FBQSxLQUFBLENBQUEsTUFBQSxFQWV3QjtBQUFBLFlBQUEsUUFBQSxJQUFBOztBQUNwQixZQUFJLFVBQVUsT0FBQSxHQUFBLENBQVcsVUFBQSxJQUFBLEVBQUE7QUFBQSxtQkFBUSxNQUFBLFFBQUEsQ0FBakMsSUFBaUMsQ0FBUjtBQUF6QixTQUFjLENBQWQ7QUFDQSxlQUFPLElBQUEsZ0JBQUEsQ0FBQSxJQUFBLEVBQUEsTUFBQSxFQUFQLE9BQU8sQ0FBUDtBQWpCSixLQUFBOztBQUFBLFdBQUEsV0FBQTtBQUFBLENBQUEsRUFBQTtBQXFCQSxJQUFBLGtEQUFBLFVBQUEsWUFBQSxFQUFBO0FBQUEsY0FBQSxrQkFBQSxFQUFBLFlBQUE7O0FBQUEsYUFBQSxrQkFBQSxHQUFBO0FBQUEsd0JBQUEsSUFBQSxFQUFBLGtCQUFBOztBQUFBLFlBQUEsU0FBQSwyQkFBQSxJQUFBLEUseUJBQUEsUyxDQUFBLENBQUE7O0FBQ1MsZUFBQSxPQUFBLEdBQUEsRUFBQTtBQUVDLGVBQUEsSUFBQSxHQUFBLENBQUE7QUFDQSxlQUFBLEtBQUEsR0FBQSxpQkFBQTtBQUNBLGVBQUEsTUFBQSxHQUFBLGlCQUFBO0FBTFYsZUFBQSxNQUFBO0FBbURDOztBQW5ERCx1QkFBQSxTQUFBLENBQUEsR0FBQSxHQUFBLFNBQUEs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ZW50IjpbImltcG9ydCB7IEFTVCB9IGZyb20gJ0BnbGltbWVyL3N5bnRheCc7XG5pbXBvcnQgeyBPcHRpb24sIGRpY3QsIHVucmVhY2hhYmxlLCBleHBlY3QgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7IENvcmUsIERpY3QgfSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFN5bWJvbFRhYmxlIHtcbiAgc3RhdGljIHRvcCgpOiBQcm9ncmFtU3ltYm9sVGFibGUge1xuICAgIHJldHVybiBuZXcgUHJvZ3JhbVN5bWJvbFRhYmxlKCk7XG4gIH1cblxuICBhYnN0cmFjdCBoYXMobmFtZTogc3RyaW5nKTogYm9vbGVhbjtcbiAgYWJzdHJhY3QgZ2V0KG5hbWU6IHN0cmluZyk6IG51bWJlcjtcblxuICBhYnN0cmFjdCBnZXRMb2NhbHNNYXAoKTogRGljdDxudW1iZXI+O1xuICBhYnN0cmFjdCBnZXRFdmFsSW5mbygpOiBDb3JlLkV2YWxJbmZvO1xuXG4gIGFic3RyYWN0IGFsbG9jYXRlTmFtZWQobmFtZTogc3RyaW5nKTogbnVtYmVyO1xuICBhYnN0cmFjdCBhbGxvY2F0ZUJsb2NrKG5hbWU6IHN0cmluZyk6IG51bWJlcjtcbiAgYWJzdHJhY3QgYWxsb2NhdGUoaWRlbnRpZmllcjogc3RyaW5nKTogbnVtYmVyO1xuXG4gIGNoaWxkKGxvY2Fsczogc3RyaW5nW10pOiBCbG9ja1N5bWJvbFRhYmxlIHtcbiAgICBsZXQgc3ltYm9scyA9IGxvY2Fscy5tYXAobmFtZSA9PiB0aGlzLmFsbG9jYXRlKG5hbWUpKTtcbiAgICByZXR1cm4gbmV3IEJsb2NrU3ltYm9sVGFibGUodGhpcywgbG9jYWxzLCBzeW1ib2xzKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUHJvZ3JhbVN5bWJvbFRhYmxlIGV4dGVuZHMgU3ltYm9sVGFibGUge1xuICBwdWJsaWMgc3ltYm9sczogc3RyaW5nW10gPSBbXTtcblxuICBwcml2YXRlIHNpemUgPSAxO1xuICBwcml2YXRlIG5hbWVkID0gZGljdDxudW1iZXI+KCk7XG4gIHByaXZhdGUgYmxvY2tzID0gZGljdDxudW1iZXI+KCk7XG5cbiAgaGFzKF9uYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBnZXQoX25hbWU6IHN0cmluZyk6IG5ldmVyIHtcbiAgICB0aHJvdyB1bnJlYWNoYWJsZSgpO1xuICB9XG5cbiAgZ2V0TG9jYWxzTWFwKCk6IERpY3Q8bnVtYmVyPiB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgZ2V0RXZhbEluZm8oKTogQ29yZS5FdmFsSW5mbyB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgYWxsb2NhdGVOYW1lZChuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBuYW1lZCA9IHRoaXMubmFtZWRbbmFtZV07XG5cbiAgICBpZiAoIW5hbWVkKSB7XG4gICAgICBuYW1lZCA9IHRoaXMubmFtZWRbbmFtZV0gPSB0aGlzLmFsbG9jYXRlKG5hbWUpO1xuICAgIH1cblxuICAgIHJldHVybiBuYW1lZDtcbiAgfVxuXG4gIGFsbG9jYXRlQmxvY2sobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBpZiAobmFtZSA9PT0gJ2ludmVyc2UnKSB7XG4gICAgICBuYW1lID0gJ2Vsc2UnO1xuICAgIH1cblxuICAgIGxldCBibG9jayA9IHRoaXMuYmxvY2tzW25hbWVdO1xuXG4gICAgaWYgKCFibG9jaykge1xuICAgICAgYmxvY2sgPSB0aGlzLmJsb2Nrc1tuYW1lXSA9IHRoaXMuYWxsb2NhdGUoYCYke25hbWV9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJsb2NrO1xuICB9XG5cbiAgYWxsb2NhdGUoaWRlbnRpZmllcjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICB0aGlzLnN5bWJvbHMucHVzaChpZGVudGlmaWVyKTtcbiAgICByZXR1cm4gdGhpcy5zaXplKys7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJsb2NrU3ltYm9sVGFibGUgZXh0ZW5kcyBTeW1ib2xUYWJsZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcGFyZW50OiBTeW1ib2xUYWJsZSwgcHVibGljIHN5bWJvbHM6IHN0cmluZ1tdLCBwdWJsaWMgc2xvdHM6IG51bWJlcltdKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIGhhcyhuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zeW1ib2xzLmluZGV4T2YobmFtZSkgIT09IC0xIHx8IHRoaXMucGFyZW50LmhhcyhuYW1lKTtcbiAgfVxuXG4gIGdldChuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBzbG90ID0gdGhpcy5zeW1ib2xzLmluZGV4T2YobmFtZSk7XG4gICAgcmV0dXJuIHNsb3QgPT09IC0xID8gdGhpcy5wYXJlbnQuZ2V0KG5hbWUpIDogdGhpcy5zbG90c1tzbG90XTtcbiAgfVxuXG4gIGdldExvY2Fsc01hcCgpOiBEaWN0PG51bWJlcj4ge1xuICAgIGxldCBkaWN0ID0gdGhpcy5wYXJlbnQuZ2V0TG9jYWxzTWFwKCk7XG4gICAgdGhpcy5zeW1ib2xzLmZvckVhY2goc3ltYm9sID0+IChkaWN0W3N5bWJvbF0gPSB0aGlzLmdldChzeW1ib2wpKSk7XG4gICAgcmV0dXJuIGRpY3Q7XG4gIH1cblxuICBnZXRFdmFsSW5mbygpOiBDb3JlLkV2YWxJbmZvIHtcbiAgICBsZXQgbG9jYWxzID0gdGhpcy5nZXRMb2NhbHNNYXAoKTtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMobG9jYWxzKS5tYXAoc3ltYm9sID0+IGxvY2Fsc1tzeW1ib2xdKTtcbiAgfVxuXG4gIGFsbG9jYXRlTmFtZWQobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnQuYWxsb2NhdGVOYW1lZChuYW1lKTtcbiAgfVxuXG4gIGFsbG9jYXRlQmxvY2sobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnQuYWxsb2NhdGVCbG9jayhuYW1lKTtcbiAgfVxuXG4gIGFsbG9jYXRlKGlkZW50aWZpZXI6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucGFyZW50LmFsbG9jYXRlKGlkZW50aWZpZXIpO1xuICB9XG59XG5cbi8qKlxuICogVGFrZXMgaW4gYW4gQVNUIGFuZCBvdXRwdXRzIGEgbGlzdCBvZiBhY3Rpb25zIHRvIGJlIGNvbnN1bWVkXG4gKiBieSBhIGNvbXBpbGVyLiBGb3IgZXhhbXBsZSwgdGhlIHRlbXBsYXRlXG4gKlxuICogICAgIGZvb3t7YmFyfX08ZGl2PmJhejwvZGl2PlxuICpcbiAqIHByb2R1Y2VzIHRoZSBhY3Rpb25zXG4gKlxuICogICAgIFtbJ3N0YXJ0UHJvZ3JhbScsIFtwcm9ncmFtTm9kZSwgMF1dLFxuICogICAgICBbJ3RleHQnLCBbdGV4dE5vZGUsIDAsIDNdXSxcbiAqICAgICAgWydtdXN0YWNoZScsIFttdXN0YWNoZU5vZGUsIDEsIDNdXSxcbiAqICAgICAgWydvcGVuRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMiwgMywgMF1dLFxuICogICAgICBbJ3RleHQnLCBbdGV4dE5vZGUsIDAsIDFdXSxcbiAqICAgICAgWydjbG9zZUVsZW1lbnQnLCBbZWxlbWVudE5vZGUsIDIsIDNdLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXV1cbiAqXG4gKiBUaGlzIHZpc2l0b3Igd2Fsa3MgdGhlIEFTVCBkZXB0aCBmaXJzdCBhbmQgYmFja3dhcmRzLiBBc1xuICogYSByZXN1bHQgdGhlIGJvdHRvbS1tb3N0IGNoaWxkIHRlbXBsYXRlIHdpbGwgYXBwZWFyIGF0IHRoZVxuICogdG9wIG9mIHRoZSBhY3Rpb25zIGxpc3Qgd2hlcmVhcyB0aGUgcm9vdCB0ZW1wbGF0ZSB3aWxsIGFwcGVhclxuICogYXQgdGhlIGJvdHRvbSBvZiB0aGUgbGlzdC4gRm9yIGV4YW1wbGUsXG4gKlxuICogICAgIDxkaXY+e3sjaWZ9fWZvb3t7ZWxzZX19YmFyPGI+PC9iPnt7L2lmfX08L2Rpdj5cbiAqXG4gKiBwcm9kdWNlcyB0aGUgYWN0aW9uc1xuICpcbiAqICAgICBbWydzdGFydFByb2dyYW0nLCBbcHJvZ3JhbU5vZGUsIDBdXSxcbiAqICAgICAgWyd0ZXh0JywgW3RleHROb2RlLCAwLCAyLCAwXV0sXG4gKiAgICAgIFsnb3BlbkVsZW1lbnQnLCBbZWxlbWVudE5vZGUsIDEsIDIsIDBdXSxcbiAqICAgICAgWydjbG9zZUVsZW1lbnQnLCBbZWxlbWVudE5vZGUsIDEsIDJdXSxcbiAqICAgICAgWydlbmRQcm9ncmFtJywgW3Byb2dyYW1Ob2RlXV0sXG4gKiAgICAgIFsnc3RhcnRQcm9ncmFtJywgW3Byb2dyYW1Ob2RlLCAwXV0sXG4gKiAgICAgIFsndGV4dCcsIFt0ZXh0Tm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXSxcbiAqICAgICAgWydzdGFydFByb2dyYW0nLCBbcHJvZ3JhbU5vZGUsIDJdXSxcbiAqICAgICAgWydvcGVuRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMCwgMSwgMV1dLFxuICogICAgICBbJ2Jsb2NrJywgW2Jsb2NrTm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2Nsb3NlRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXV1cbiAqXG4gKiBUaGUgc3RhdGUgb2YgdGhlIHRyYXZlcnNhbCBpcyBtYWludGFpbmVkIGJ5IGEgc3RhY2sgb2YgZnJhbWVzLlxuICogV2hlbmV2ZXIgYSBub2RlIHdpdGggY2hpbGRyZW4gaXMgZW50ZXJlZCAoZWl0aGVyIGEgUHJvZ3JhbU5vZGVcbiAqIG9yIGFuIEVsZW1lbnROb2RlKSBhIGZyYW1lIGlzIHB1c2hlZCBvbnRvIHRoZSBzdGFjay4gVGhlIGZyYW1lXG4gKiBjb250YWlucyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3RhdGUgb2YgdGhlIHRyYXZlcnNhbCBvZiB0aGF0XG4gKiBub2RlLiBGb3IgZXhhbXBsZSxcbiAqXG4gKiAgIC0gaW5kZXggb2YgdGhlIGN1cnJlbnQgY2hpbGQgbm9kZSBiZWluZyB2aXNpdGVkXG4gKiAgIC0gdGhlIG51bWJlciBvZiBtdXN0YWNoZXMgY29udGFpbmVkIHdpdGhpbiBpdHMgY2hpbGQgbm9kZXNcbiAqICAgLSB0aGUgbGlzdCBvZiBhY3Rpb25zIGdlbmVyYXRlZCBieSBpdHMgY2hpbGQgbm9kZXNcbiAqL1xuXG5jbGFzcyBGcmFtZSB7XG4gIHB1YmxpYyBwYXJlbnROb2RlOiBPcHRpb248T2JqZWN0PiA9IG51bGw7XG4gIHB1YmxpYyBjaGlsZHJlbjogT3B0aW9uPEFTVC5Ob2RlW10+ID0gbnVsbDtcbiAgcHVibGljIGNoaWxkSW5kZXg6IE9wdGlvbjxudW1iZXI+ID0gbnVsbDtcbiAgcHVibGljIGNoaWxkQ291bnQ6IE9wdGlvbjxudW1iZXI+ID0gbnVsbDtcbiAgcHVibGljIGNoaWxkVGVtcGxhdGVDb3VudCA9IDA7XG4gIHB1YmxpYyBtdXN0YWNoZUNvdW50ID0gMDtcbiAgcHVibGljIGFjdGlvbnM6IEFjdGlvbltdID0gW107XG4gIHB1YmxpYyBibGFua0NoaWxkVGV4dE5vZGVzOiBPcHRpb248bnVtYmVyW10+ID0gbnVsbDtcbiAgcHVibGljIHN5bWJvbHM6IE9wdGlvbjxBU1QuU3ltYm9scz4gPSBudWxsO1xufVxuXG5leHBvcnQgbmFtZXNwYWNlIEFjdGlvbiB7XG4gIGV4cG9ydCB0eXBlIFN0YXJ0UHJvZ3JhbSA9IFsnc3RhcnRQcm9ncmFtJywgW0FTVC5UZW1wbGF0ZSwgbnVtYmVyLCBudW1iZXJbXV1dO1xuICBleHBvcnQgdHlwZSBFbmRQcm9ncmFtID0gWydlbmRQcm9ncmFtJywgW0FTVC5UZW1wbGF0ZSwgbnVtYmVyXV07XG4gIGV4cG9ydCB0eXBlIFN0YXJ0QmxvY2sgPSBbJ3N0YXJ0QmxvY2snLCBbQVNULkJsb2NrLCBudW1iZXIsIG51bWJlcltdXV07XG4gIGV4cG9ydCB0eXBlIEVuZEJsb2NrID0gWydlbmRCbG9jaycsIFtBU1QuQmxvY2ssIG51bWJlcl1dO1xuICBleHBvcnQgdHlwZSBCbG9jayA9IFsnYmxvY2snLCBbQVNULkJsb2NrU3RhdGVtZW50LCBudW1iZXIsIG51bWJlcl1dO1xuICBleHBvcnQgdHlwZSBNdXN0YWNoZSA9IFtcbiAgICAnbXVzdGFjaGUnLFxuICAgIFtBU1QuTXVzdGFjaGVTdGF0ZW1lbnQgfCBBU1QuUGFydGlhbFN0YXRlbWVudCwgbnVtYmVyLCBudW1iZXJdXG4gIF07XG4gIGV4cG9ydCB0eXBlIE9wZW5FbGVtZW50ID0gWydvcGVuRWxlbWVudCcsIFtBU1QuRWxlbWVudE5vZGUsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcltdXV07XG4gIGV4cG9ydCB0eXBlIENsb3NlRWxlbWVudCA9IFsnY2xvc2VFbGVtZW50JywgW0FTVC5FbGVtZW50Tm9kZSwgbnVtYmVyLCBudW1iZXJdXTtcbiAgZXhwb3J0IHR5cGUgVGV4dCA9IFsndGV4dCcsIFtBU1QuVGV4dE5vZGUsIG51bWJlciwgbnVtYmVyXV07XG4gIGV4cG9ydCB0eXBlIENvbW1lbnQgPSBbJ2NvbW1lbnQnLCBbQVNULkNvbW1lbnRTdGF0ZW1lbnQsIG51bWJlciwgbnVtYmVyXV07XG5cbiAgZXhwb3J0IHR5cGUgQWN0aW9uID1cbiAgICB8IFN0YXJ0UHJvZ3JhbVxuICAgIHwgRW5kUHJvZ3JhbVxuICAgIHwgU3RhcnRCbG9ja1xuICAgIHwgRW5kQmxvY2tcbiAgICB8IEJsb2NrXG4gICAgfCBNdXN0YWNoZVxuICAgIHwgT3BlbkVsZW1lbnRcbiAgICB8IENsb3NlRWxlbWVudFxuICAgIHwgVGV4dFxuICAgIHwgQ29tbWVudDtcbn1cblxuZXhwb3J0IHR5cGUgQWN0aW9uID0gQWN0aW9uLkFjdGlvbjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVtcGxhdGVWaXNpdG9yIHtcbiAgcHJpdmF0ZSBmcmFtZVN0YWNrOiBGcmFtZVtdID0gW107XG4gIHB1YmxpYyBhY3Rpb25zOiBBY3Rpb25bXSA9IFtdO1xuICBwcml2YXRlIHByb2dyYW1EZXB0aCA9IC0xO1xuXG4gIHZpc2l0PFMgZXh0ZW5kcyBBU1QuVG9wTGV2ZWxTdGF0ZW1lbnQ+KG5vZGU6IFMpIHtcbiAgICAodGhpc1tub2RlLnR5cGVdIGFzICh0aGlzOiB0aGlzLCBub2RlOiBTKSA9PiB2b2lkKShub2RlKTtcbiAgfVxuXG4gIC8vIFRyYXZlcnNhbCBtZXRob2RzXG5cbiAgQmxvY2socHJvZ3JhbTogQVNULkJsb2NrKSB7XG4gICAgcmV0dXJuIHRoaXMuYW55QmxvY2socHJvZ3JhbSk7XG4gIH1cblxuICBUZW1wbGF0ZShwcm9ncmFtOiBBU1QuVGVtcGxhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5hbnlCbG9jayhwcm9ncmFtKTtcbiAgfVxuXG4gIGFueUJsb2NrKHByb2dyYW06IEFTVC5CbG9jayB8IEFTVC5UZW1wbGF0ZSkge1xuICAgIHRoaXMucHJvZ3JhbURlcHRoKys7XG5cbiAgICBsZXQgcGFyZW50RnJhbWUgPSB0aGlzLmdldEN1cnJlbnRGcmFtZSgpO1xuICAgIGxldCBwcm9ncmFtRnJhbWUgPSB0aGlzLnB1c2hGcmFtZSgpO1xuXG4gICAgaWYgKCFwYXJlbnRGcmFtZSkge1xuICAgICAgKHByb2dyYW0gYXMgQVNULlRlbXBsYXRlKS5zeW1ib2xzID0gU3ltYm9sVGFibGUudG9wKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIChwcm9ncmFtIGFzIEFTVC5CbG9jaykuc3ltYm9scyA9IHBhcmVudEZyYW1lLnN5bWJvbHMhLmNoaWxkKHByb2dyYW0uYmxvY2tQYXJhbXMpO1xuICAgIH1cblxuICAgIGxldCBzdGFydFR5cGU6IHN0cmluZywgZW5kVHlwZTogc3RyaW5nO1xuXG4gICAgaWYgKHRoaXMucHJvZ3JhbURlcHRoID09PSAwKSB7XG4gICAgICBzdGFydFR5cGUgPSAnc3RhcnRQcm9ncmFtJztcbiAgICAgIGVuZFR5cGUgPSAnZW5kUHJvZ3JhbSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXJ0VHlwZSA9ICdzdGFydEJsb2NrJztcbiAgICAgIGVuZFR5cGUgPSAnZW5kQmxvY2snO1xuICAgIH1cblxuICAgIHByb2dyYW1GcmFtZS5wYXJlbnROb2RlID0gcHJvZ3JhbTtcbiAgICBwcm9ncmFtRnJhbWUuY2hpbGRyZW4gPSBwcm9ncmFtLmJvZHk7XG4gICAgcHJvZ3JhbUZyYW1lLmNoaWxkQ291bnQgPSBwcm9ncmFtLmJvZHkubGVuZ3RoO1xuICAgIHByb2dyYW1GcmFtZS5ibGFua0NoaWxkVGV4dE5vZGVzID0gW107XG4gICAgcHJvZ3JhbUZyYW1lLmFjdGlvbnMucHVzaChbZW5kVHlwZSwgW3Byb2dyYW0sIHRoaXMucHJvZ3JhbURlcHRoXV0gYXMgQWN0aW9uKTtcbiAgICBwcm9ncmFtRnJhbWUuc3ltYm9scyA9IHByb2dyYW1bJ3N5bWJvbHMnXSE7XG5cbiAgICBmb3IgKGxldCBpID0gcHJvZ3JhbS5ib2R5Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBwcm9ncmFtRnJhbWUuY2hpbGRJbmRleCA9IGk7XG4gICAgICB0aGlzLnZpc2l0KHByb2dyYW0uYm9keVtpXSk7XG4gICAgfVxuXG4gICAgcHJvZ3JhbUZyYW1lLmFjdGlvbnMucHVzaChbXG4gICAgICBzdGFydFR5cGUsXG4gICAgICBbcHJvZ3JhbSwgcHJvZ3JhbUZyYW1lLmNoaWxkVGVtcGxhdGVDb3VudCwgcHJvZ3JhbUZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMucmV2ZXJzZSgpXSxcbiAgICBdIGFzIEFjdGlvbik7XG4gICAgdGhpcy5wb3BGcmFtZSgpO1xuXG4gICAgdGhpcy5wcm9ncmFtRGVwdGgtLTtcblxuICAgIC8vIFB1c2ggdGhlIGNvbXBsZXRlZCB0ZW1wbGF0ZSBpbnRvIHRoZSBnbG9iYWwgYWN0aW9ucyBsaXN0XG4gICAgaWYgKHBhcmVudEZyYW1lKSB7XG4gICAgICBwYXJlbnRGcmFtZS5jaGlsZFRlbXBsYXRlQ291bnQrKztcbiAgICB9XG4gICAgdGhpcy5hY3Rpb25zLnB1c2goLi4ucHJvZ3JhbUZyYW1lLmFjdGlvbnMucmV2ZXJzZSgpKTtcbiAgfVxuXG4gIEVsZW1lbnROb2RlKGVsZW1lbnQ6IEFTVC5FbGVtZW50Tm9kZSkge1xuICAgIGxldCBwYXJlbnRGcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuICAgIGxldCBlbGVtZW50RnJhbWUgPSB0aGlzLnB1c2hGcmFtZSgpO1xuXG4gICAgZWxlbWVudEZyYW1lLnBhcmVudE5vZGUgPSBlbGVtZW50O1xuICAgIGVsZW1lbnRGcmFtZS5jaGlsZHJlbiA9IGVsZW1lbnQuY2hpbGRyZW47XG4gICAgZWxlbWVudEZyYW1lLmNoaWxkQ291bnQgPSBlbGVtZW50LmNoaWxkcmVuLmxlbmd0aDtcbiAgICBlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCArPSBlbGVtZW50Lm1vZGlmaWVycy5sZW5ndGg7XG4gICAgZWxlbWVudEZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMgPSBbXTtcbiAgICBlbGVtZW50RnJhbWUuc3ltYm9scyA9IGVsZW1lbnQuc3ltYm9scyA9IHBhcmVudEZyYW1lLnN5bWJvbHMhLmNoaWxkKGVsZW1lbnQuYmxvY2tQYXJhbXMpO1xuXG4gICAgbGV0IGFjdGlvbkFyZ3M6IFtBU1QuRWxlbWVudE5vZGUsIG51bWJlciwgbnVtYmVyXSA9IFtcbiAgICAgIGVsZW1lbnQsXG4gICAgICBwYXJlbnRGcmFtZS5jaGlsZEluZGV4ISxcbiAgICAgIHBhcmVudEZyYW1lLmNoaWxkQ291bnQhLFxuICAgIF07XG5cbiAgICBlbGVtZW50RnJhbWUuYWN0aW9ucy5wdXNoKFsnY2xvc2VFbGVtZW50JywgYWN0aW9uQXJnc10pO1xuXG4gICAgZm9yIChsZXQgaSA9IGVsZW1lbnQuYXR0cmlidXRlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdGhpcy52aXNpdChlbGVtZW50LmF0dHJpYnV0ZXNbaV0pO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBlbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBlbGVtZW50RnJhbWUuY2hpbGRJbmRleCA9IGk7XG4gICAgICB0aGlzLnZpc2l0KGVsZW1lbnQuY2hpbGRyZW5baV0pO1xuICAgIH1cblxuICAgIGxldCBvcGVuID0gW1xuICAgICAgJ29wZW5FbGVtZW50JyxcbiAgICAgIFsuLi5hY3Rpb25BcmdzLCBlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCwgZWxlbWVudEZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMucmV2ZXJzZSgpXSxcbiAgICBdIGFzIEFjdGlvbi5PcGVuRWxlbWVudDtcbiAgICBlbGVtZW50RnJhbWUuYWN0aW9ucy5wdXNoKG9wZW4pO1xuXG4gICAgdGhpcy5wb3BGcmFtZSgpO1xuXG4gICAgLy8gUHJvcGFnYXRlIHRoZSBlbGVtZW50J3MgZnJhbWUgc3RhdGUgdG8gdGhlIHBhcmVudCBmcmFtZVxuICAgIGlmIChlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCA+IDApIHtcbiAgICAgIHBhcmVudEZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICB9XG4gICAgcGFyZW50RnJhbWUuY2hpbGRUZW1wbGF0ZUNvdW50ICs9IGVsZW1lbnRGcmFtZS5jaGlsZFRlbXBsYXRlQ291bnQ7XG4gICAgcGFyZW50RnJhbWUuYWN0aW9ucy5wdXNoKC4uLmVsZW1lbnRGcmFtZS5hY3Rpb25zKTtcbiAgfVxuXG4gIEF0dHJOb2RlKGF0dHI6IEFTVC5BdHRyTm9kZSkge1xuICAgIGlmIChhdHRyLnZhbHVlLnR5cGUgIT09ICdUZXh0Tm9kZScpIHtcbiAgICAgIHRoaXMuY3VycmVudEZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICB9XG4gIH1cblxuICBUZXh0Tm9kZSh0ZXh0OiBBU1QuVGV4dE5vZGUpIHtcbiAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICBpZiAodGV4dC5jaGFycyA9PT0gJycpIHtcbiAgICAgIGZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMhLnB1c2goZG9tSW5kZXhPZihmcmFtZS5jaGlsZHJlbiEsIHRleHQpKTtcbiAgICB9XG4gICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsndGV4dCcsIFt0ZXh0LCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0gYXMgQWN0aW9uKTtcbiAgfVxuXG4gIEJsb2NrU3RhdGVtZW50KG5vZGU6IEFTVC5CbG9ja1N0YXRlbWVudCkge1xuICAgIGxldCBmcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuXG4gICAgZnJhbWUubXVzdGFjaGVDb3VudCsrO1xuICAgIGZyYW1lLmFjdGlvbnMucHVzaChbJ2Jsb2NrJywgW25vZGUsIGZyYW1lLmNoaWxkSW5kZXgsIGZyYW1lLmNoaWxkQ291bnRdXSBhcyBBY3Rpb24pO1xuXG4gICAgaWYgKG5vZGUuaW52ZXJzZSkge1xuICAgICAgdGhpcy52aXNpdChub2RlLmludmVyc2UpO1xuICAgIH1cbiAgICBpZiAobm9kZS5wcm9ncmFtKSB7XG4gICAgICB0aGlzLnZpc2l0KG5vZGUucHJvZ3JhbSk7XG4gICAgfVxuICB9XG5cbiAgUGFydGlhbFN0YXRlbWVudChub2RlOiBBU1QuUGFydGlhbFN0YXRlbWVudCkge1xuICAgIGxldCBmcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuICAgIGZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICBmcmFtZS5hY3Rpb25zLnB1c2goWydtdXN0YWNoZScsIFtub2RlLCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0gYXMgQWN0aW9uKTtcbiAgfVxuXG4gIENvbW1lbnRTdGF0ZW1lbnQodGV4dDogQVNULkNvbW1lbnRTdGF0ZW1lbnQpIHtcbiAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICBmcmFtZS5hY3Rpb25zLnB1c2goWydjb21tZW50JywgW3RleHQsIGZyYW1lLmNoaWxkSW5kZXgsIGZyYW1lLmNoaWxkQ291bnRdXSBhcyBBY3Rpb24pO1xuICB9XG5cbiAgTXVzdGFjaGVDb21tZW50U3RhdGVtZW50KCkge1xuICAgIC8vIEludGVudGlvbmFsIGVtcHR5OiBIYW5kbGViYXJzIGNvbW1lbnRzIHNob3VsZCBub3QgYWZmZWN0IG91dHB1dC5cbiAgfVxuXG4gIE11c3RhY2hlU3RhdGVtZW50KG11c3RhY2hlOiBBU1QuTXVzdGFjaGVTdGF0ZW1lbnQpIHtcbiAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICBmcmFtZS5tdXN0YWNoZUNvdW50Kys7XG4gICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsnbXVzdGFjaGUnLCBbbXVzdGFjaGUsIGZyYW1lLmNoaWxkSW5kZXgsIGZyYW1lLmNoaWxkQ291bnRdXSBhcyBBY3Rpb24pO1xuICB9XG5cbiAgLy8gRnJhbWUgaGVscGVyc1xuXG4gIHByaXZhdGUgZ2V0IGN1cnJlbnRGcmFtZSgpOiBGcmFtZSB7XG4gICAgcmV0dXJuIGV4cGVjdCh0aGlzLmdldEN1cnJlbnRGcmFtZSgpLCAnRXhwZWN0ZWQgYSBjdXJyZW50IGZyYW1lJyk7XG4gIH1cblxuICBwcml2YXRlIGdldEN1cnJlbnRGcmFtZSgpOiBPcHRpb248RnJhbWU+IHtcbiAgICByZXR1cm4gdGhpcy5mcmFtZVN0YWNrW3RoaXMuZnJhbWVTdGFjay5sZW5ndGggLSAxXTtcbiAgfVxuXG4gIHByaXZhdGUgcHVzaEZyYW1lKCkge1xuICAgIGxldCBmcmFtZSA9IG5ldyBGcmFtZSgpO1xuICAgIHRoaXMuZnJhbWVTdGFjay5wdXNoKGZyYW1lKTtcbiAgICByZXR1cm4gZnJhbWU7XG4gIH1cblxuICBwcml2YXRlIHBvcEZyYW1lKCkge1xuICAgIHJldHVybiB0aGlzLmZyYW1lU3RhY2sucG9wKCk7XG4gIH1cbn1cblxuLy8gUmV0dXJucyB0aGUgaW5kZXggb2YgYGRvbU5vZGVgIGluIHRoZSBgbm9kZXNgIGFycmF5LCBza2lwcGluZ1xuLy8gb3ZlciBhbnkgbm9kZXMgd2hpY2ggZG8gbm90IHJlcHJlc2VudCBET00gbm9kZXMuXG5mdW5jdGlvbiBkb21JbmRleE9mKG5vZGVzOiBBU1QuTm9kZVtdLCBkb21Ob2RlOiBBU1QuVGV4dE5vZGUgfCBBU1QuRWxlbWVudE5vZGUpIHtcbiAgbGV0IGluZGV4ID0gLTE7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBub2RlID0gbm9kZXNbaV07XG5cbiAgICBpZiAobm9kZS50eXBlICE9PSAnVGV4dE5vZGUnICYmIG5vZGUudHlwZSAhPT0gJ0VsZW1lbnROb2RlJykge1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGluZGV4Kys7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUgPT09IGRvbU5vZGUpIHtcbiAgICAgIHJldHVybiBpbmRleDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gLTE7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9