UNPKG

@glimmer/compiler

Version:
428 lines (365 loc) 41.6 kB
"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