UNPKG

@glimmer/compiler

Version:
326 lines (321 loc) 38.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.BlockSymbolTable = exports.ProgramSymbolTable = exports.SymbolTable = undefined; var _util = require('@glimmer/util'); class SymbolTable { static top() { return new ProgramSymbolTable(); } child(locals) { let symbols = locals.map(name => this.allocate(name)); return new BlockSymbolTable(this, locals, symbols); } } exports.SymbolTable = SymbolTable; class ProgramSymbolTable extends SymbolTable { constructor() { super(...arguments); this.symbols = []; this.freeVariables = []; this.size = 1; this.named = (0, _util.dict)(); this.blocks = (0, _util.dict)(); } has(_name) { return false; } get(_name) { throw (0, _util.unreachable)(); } getLocalsMap() { return {}; } getEvalInfo() { return []; } allocateFree(name) { let index = this.freeVariables.indexOf(name); if (index !== -1) { return index; } index = this.freeVariables.length; this.freeVariables.push(name); return index; } allocateNamed(name) { let named = this.named[name]; if (!named) { named = this.named[name] = this.allocate(name); } return named; } allocateBlock(name) { if (name === 'inverse') { name = 'else'; } let block = this.blocks[name]; if (!block) { block = this.blocks[name] = this.allocate(`&${name}`); } return block; } allocate(identifier) { this.symbols.push(identifier); return this.size++; } } exports.ProgramSymbolTable = ProgramSymbolTable; class BlockSymbolTable extends SymbolTable { constructor(parent, symbols, slots) { super(); this.parent = parent; this.symbols = symbols; this.slots = slots; } has(name) { return this.symbols.indexOf(name) !== -1 || this.parent.has(name); } get(name) { let slot = this.symbols.indexOf(name); return slot === -1 ? this.parent.get(name) : this.slots[slot]; } getLocalsMap() { let dict = this.parent.getLocalsMap(); this.symbols.forEach(symbol => dict[symbol] = this.get(symbol)); return dict; } getEvalInfo() { let locals = this.getLocalsMap(); return Object.keys(locals).map(symbol => locals[symbol]); } allocateFree(name) { return this.parent.allocateFree(name); } allocateNamed(name) { return this.parent.allocateNamed(name); } allocateBlock(name) { return this.parent.allocateBlock(name); } allocate(identifier) { return this.parent.allocate(identifier); } } exports.BlockSymbolTable = BlockSymbolTable; /** * 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 */ class Frame { constructor() { 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; } } class TemplateVisitor { constructor() { this.frameStack = []; this.actions = []; this.programDepth = -1; } visit(node) { this[node.type](node); } // Traversal methods Block(program) { return this.anyBlock(program); } Template(program) { return this.anyBlock(program); } anyBlock(program) { this.programDepth++; let parentFrame = this.getCurrentFrame(); let programFrame = this.pushFrame(); if (!parentFrame) { program.symbols = SymbolTable.top(); } else { program.symbols = parentFrame.symbols.child(program.blockParams); } let startType, endType; 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 (let 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++; } this.actions.push(...programFrame.actions.reverse()); } ElementNode(element) { let parentFrame = this.currentFrame; let 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); let actionArgs = [element, parentFrame.childIndex, parentFrame.childCount]; elementFrame.actions.push(['closeElement', actionArgs]); for (let i = element.attributes.length - 1; i >= 0; i--) { this.visit(element.attributes[i]); } for (let i = element.children.length - 1; i >= 0; i--) { elementFrame.childIndex = i; this.visit(element.children[i]); } let open = ['openElement', [...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.push(...elementFrame.actions); } AttrNode(attr) { if (attr.value.type !== 'TextNode') { this.currentFrame.mustacheCount++; } } TextNode(text) { let frame = this.currentFrame; if (text.chars === '') { frame.blankChildTextNodes.push(domIndexOf(frame.children, text)); } frame.actions.push(['text', [text, frame.childIndex, frame.childCount]]); } BlockStatement(node) { let 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); } } PartialStatement(node) { let frame = this.currentFrame; frame.mustacheCount++; frame.actions.push(['mustache', [node, frame.childIndex, frame.childCount]]); } CommentStatement(text) { let frame = this.currentFrame; frame.actions.push(['comment', [text, frame.childIndex, frame.childCount]]); } MustacheCommentStatement() { // Intentional empty: Handlebars comments should not affect output. } MustacheStatement(mustache) { let frame = this.currentFrame; frame.mustacheCount++; frame.actions.push(['mustache', [mustache, frame.childIndex, frame.childCount]]); } // Frame helpers get currentFrame() { return this.getCurrentFrame(); } getCurrentFrame() { return this.frameStack[this.frameStack.length - 1]; } pushFrame() { let frame = new Frame(); this.frameStack.push(frame); return frame; } popFrame() { return this.frameStack.pop(); } } exports.default = TemplateVisitor; // Returns the index of `domNode` in the `nodes` array, skipping // over any nodes which do not represent DOM nodes. function domIndexOf(nodes, domNode) { let index = -1; for (let i = 0; i < nodes.length; i++) { let 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL2NvbXBpbGVyL2xpYi90ZW1wbGF0ZS12aXNpdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUlNLE1BQUEsV0FBQSxDQUEyQjtBQUMvQixXQUFBLEdBQUEsR0FBVTtBQUNSLGVBQU8sSUFBUCxrQkFBTyxFQUFQO0FBQ0Q7QUFhRCxVQUFBLE1BQUEsRUFBc0I7QUFDcEIsWUFBSSxVQUFVLE9BQUEsR0FBQSxDQUFXLFFBQVEsS0FBQSxRQUFBLENBQWpDLElBQWlDLENBQW5CLENBQWQ7QUFDQSxlQUFPLElBQUEsZ0JBQUEsQ0FBQSxJQUFBLEVBQUEsTUFBQSxFQUFQLE9BQU8sQ0FBUDtBQUNEO0FBbkI4QjtRQUEzQixXLEdBQUEsVztBQXNCQSxNQUFBLGtCQUFBLFNBQUEsV0FBQSxDQUE2QztBQUFuRCxrQkFBQTs7QUFDUyxhQUFBLE9BQUEsR0FBQSxFQUFBO0FBQ0EsYUFBQSxhQUFBLEdBQUEsRUFBQTtBQUVDLGFBQUEsSUFBQSxHQUFBLENBQUE7QUFDQSxhQUFBLEtBQUEsR0FBQSxpQkFBQTtBQUNBLGFBQUEsTUFBQSxHQUFBLGlCQUFBO0FBMERUO0FBeERDLFFBQUEsS0FBQSxFQUFpQjtBQUNmLGVBQUEsS0FBQTtBQUNEO0FBRUQsUUFBQSxLQUFBLEVBQWlCO0FBQ2YsY0FBQSx3QkFBQTtBQUNEO0FBRUQsbUJBQVk7QUFDVixlQUFBLEVBQUE7QUFDRDtBQUVELGtCQUFXO0FBQ1QsZUFBQSxFQUFBO0FBQ0Q7QUFFRCxpQkFBQSxJQUFBLEVBQXlCO0FBQ3ZCLFlBQUksUUFBUSxLQUFBLGFBQUEsQ0FBQSxPQUFBLENBQVosSUFBWSxDQUFaO0FBRUEsWUFBSSxVQUFVLENBQWQsQ0FBQSxFQUFrQjtBQUNoQixtQkFBQSxLQUFBO0FBQ0Q7QUFFRCxnQkFBUSxLQUFBLGFBQUEsQ0FBUixNQUFBO0FBQ0EsYUFBQSxhQUFBLENBQUEsSUFBQSxDQUFBLElBQUE7QUFDQSxlQUFBLEtBQUE7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LFFBQVEsS0FBWixZQUFBO0FBQ0EsY0FBQSxhQUFBO0FBQ0EsY0FBQSxPQUFBLENBQUEsSUFBQSxDQUFtQixDQUFBLFVBQUEsRUFBYSxDQUFBLFFBQUEsRUFBVyxNQUFYLFVBQUEsRUFBNkIsTUFBN0QsVUFBZ0MsQ0FBYixDQUFuQjtBQUNEO0FBRUQ7QUFFQSxRQUFBLFlBQUEsR0FBd0I7QUFDdEIsZUFBYyxLQUFkLGVBQWMsRUFBZDtBQUNEO0FBRU8sc0JBQWU7QUFDckIsZUFBTyxLQUFBLFVBQUEsQ0FBZ0IsS0FBQSxVQUFBLENBQUEsTUFBQSxHQUF2QixDQUFPLENBQVA7QUFDRDtBQUVPLGdCQUFTO0FBQ2YsWUFBSSxRQUFRLElBQVosS0FBWSxFQUFaO0FBQ0EsYUFBQSxVQUFBLENBQUEsSUFBQSxDQUFBLEtBQUE7QUFDQSxlQUFBLEtBQUE7QUFDRDtBQUVPLGVBQVE7QUFDZCxlQUFPLEtBQUEsVUFBQSxDQUFQLEdBQU8sRUFBUDtBQUNEO0FBbkxpQztrQkFBdEIsZSxFQXNMZDtBQUNBOztBQUNBLFNBQUEsVUFBQSxDQUFBLEtBQUEsRUFBQSxPQUFBLEVBQThFO0FBQzVFLFFBQUksUUFBUSxDQUFaLENBQUE7QUFFQSxTQUFLLElBQUksSUFBVCxDQUFBLEVBQWdCLElBQUksTUFBcEIsTUFBQSxFQUFBLEdBQUEsRUFBdUM7QUFDckMsWUFBSSxPQUFPLE1BQVgsQ0FBVyxDQUFYO0FBRUEsWUFBSSxLQUFBLElBQUEsS0FBQSxVQUFBLElBQTRCLEtBQUEsSUFBQSxLQUFoQyxhQUFBLEVBQTZEO0FBQzNEO0FBREYsU0FBQSxNQUVPO0FBQ0w7QUFDRDtBQUVELFlBQUksU0FBSixPQUFBLEVBQXNCO0FBQ3BCLG1CQUFBLEtBQUE7QUFDRDtBQUNGO0FBRUQsV0FBTyxDQUFQLENBQUE7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFTVCB9IGZyb20gJ0BnbGltbWVyL3N5bnRheCc7XG5pbXBvcnQgeyBPcHRpb24sIGRpY3QsIHVucmVhY2hhYmxlLCBleHBlY3QgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7IENvcmUsIERpY3QgfSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFN5bWJvbFRhYmxlIHtcbiAgc3RhdGljIHRvcCgpOiBQcm9ncmFtU3ltYm9sVGFibGUge1xuICAgIHJldHVybiBuZXcgUHJvZ3JhbVN5bWJvbFRhYmxlKCk7XG4gIH1cblxuICBhYnN0cmFjdCBoYXMobmFtZTogc3RyaW5nKTogYm9vbGVhbjtcbiAgYWJzdHJhY3QgZ2V0KG5hbWU6IHN0cmluZyk6IG51bWJlcjtcblxuICBhYnN0cmFjdCBnZXRMb2NhbHNNYXAoKTogRGljdDxudW1iZXI+O1xuICBhYnN0cmFjdCBnZXRFdmFsSW5mbygpOiBDb3JlLkV2YWxJbmZvO1xuXG4gIGFic3RyYWN0IGFsbG9jYXRlRnJlZShuYW1lOiBzdHJpbmcpOiBudW1iZXI7XG4gIGFic3RyYWN0IGFsbG9jYXRlTmFtZWQobmFtZTogc3RyaW5nKTogbnVtYmVyO1xuICBhYnN0cmFjdCBhbGxvY2F0ZUJsb2NrKG5hbWU6IHN0cmluZyk6IG51bWJlcjtcbiAgYWJzdHJhY3QgYWxsb2NhdGUoaWRlbnRpZmllcjogc3RyaW5nKTogbnVtYmVyO1xuXG4gIGNoaWxkKGxvY2Fsczogc3RyaW5nW10pOiBCbG9ja1N5bWJvbFRhYmxlIHtcbiAgICBsZXQgc3ltYm9scyA9IGxvY2Fscy5tYXAobmFtZSA9PiB0aGlzLmFsbG9jYXRlKG5hbWUpKTtcbiAgICByZXR1cm4gbmV3IEJsb2NrU3ltYm9sVGFibGUodGhpcywgbG9jYWxzLCBzeW1ib2xzKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUHJvZ3JhbVN5bWJvbFRhYmxlIGV4dGVuZHMgU3ltYm9sVGFibGUge1xuICBwdWJsaWMgc3ltYm9sczogc3RyaW5nW10gPSBbXTtcbiAgcHVibGljIGZyZWVWYXJpYWJsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgcHJpdmF0ZSBzaXplID0gMTtcbiAgcHJpdmF0ZSBuYW1lZCA9IGRpY3Q8bnVtYmVyPigpO1xuICBwcml2YXRlIGJsb2NrcyA9IGRpY3Q8bnVtYmVyPigpO1xuXG4gIGhhcyhfbmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZ2V0KF9uYW1lOiBzdHJpbmcpOiBuZXZlciB7XG4gICAgdGhyb3cgdW5yZWFjaGFibGUoKTtcbiAgfVxuXG4gIGdldExvY2Fsc01hcCgpOiBEaWN0PG51bWJlcj4ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGdldEV2YWxJbmZvKCk6IENvcmUuRXZhbEluZm8ge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGFsbG9jYXRlRnJlZShuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBpbmRleCA9IHRoaXMuZnJlZVZhcmlhYmxlcy5pbmRleE9mKG5hbWUpO1xuXG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cblxuICAgIGluZGV4ID0gdGhpcy5mcmVlVmFyaWFibGVzLmxlbmd0aDtcbiAgICB0aGlzLmZyZWVWYXJpYWJsZXMucHVzaChuYW1lKTtcbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICBhbGxvY2F0ZU5hbWVkKG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgbGV0IG5hbWVkID0gdGhpcy5uYW1lZFtuYW1lXTtcblxuICAgIGlmICghbmFtZWQpIHtcbiAgICAgIG5hbWVkID0gdGhpcy5uYW1lZFtuYW1lXSA9IHRoaXMuYWxsb2NhdGUobmFtZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5hbWVkO1xuICB9XG5cbiAgYWxsb2NhdGVCbG9jayhuYW1lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGlmIChuYW1lID09PSAnaW52ZXJzZScpIHtcbiAgICAgIG5hbWUgPSAnZWxzZSc7XG4gICAgfVxuXG4gICAgbGV0IGJsb2NrID0gdGhpcy5ibG9ja3NbbmFtZV07XG5cbiAgICBpZiAoIWJsb2NrKSB7XG4gICAgICBibG9jayA9IHRoaXMuYmxvY2tzW25hbWVdID0gdGhpcy5hbGxvY2F0ZShgJiR7bmFtZX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYmxvY2s7XG4gIH1cblxuICBhbGxvY2F0ZShpZGVudGlmaWVyOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHRoaXMuc3ltYm9scy5wdXNoKGlkZW50aWZpZXIpO1xuICAgIHJldHVybiB0aGlzLnNpemUrKztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQmxvY2tTeW1ib2xUYWJsZSBleHRlbmRzIFN5bWJvbFRhYmxlIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBwYXJlbnQ6IFN5bWJvbFRhYmxlLCBwdWJsaWMgc3ltYm9sczogc3RyaW5nW10sIHB1YmxpYyBzbG90czogbnVtYmVyW10pIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgaGFzKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN5bWJvbHMuaW5kZXhPZihuYW1lKSAhPT0gLTEgfHwgdGhpcy5wYXJlbnQuaGFzKG5hbWUpO1xuICB9XG5cbiAgZ2V0KG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgbGV0IHNsb3QgPSB0aGlzLnN5bWJvbHMuaW5kZXhPZihuYW1lKTtcbiAgICByZXR1cm4gc2xvdCA9PT0gLTEgPyB0aGlzLnBhcmVudC5nZXQobmFtZSkgOiB0aGlzLnNsb3RzW3Nsb3RdO1xuICB9XG5cbiAgZ2V0TG9jYWxzTWFwKCk6IERpY3Q8bnVtYmVyPiB7XG4gICAgbGV0IGRpY3QgPSB0aGlzLnBhcmVudC5nZXRMb2NhbHNNYXAoKTtcbiAgICB0aGlzLnN5bWJvbHMuZm9yRWFjaChzeW1ib2wgPT4gKGRpY3Rbc3ltYm9sXSA9IHRoaXMuZ2V0KHN5bWJvbCkpKTtcbiAgICByZXR1cm4gZGljdDtcbiAgfVxuXG4gIGdldEV2YWxJbmZvKCk6IENvcmUuRXZhbEluZm8ge1xuICAgIGxldCBsb2NhbHMgPSB0aGlzLmdldExvY2Fsc01hcCgpO1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhsb2NhbHMpLm1hcChzeW1ib2wgPT4gbG9jYWxzW3N5bWJvbF0pO1xuICB9XG5cbiAgYWxsb2NhdGVGcmVlKG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucGFyZW50LmFsbG9jYXRlRnJlZShuYW1lKTtcbiAgfVxuXG4gIGFsbG9jYXRlTmFtZWQobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnQuYWxsb2NhdGVOYW1lZChuYW1lKTtcbiAgfVxuXG4gIGFsbG9jYXRlQmxvY2sobmFtZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnQuYWxsb2NhdGVCbG9jayhuYW1lKTtcbiAgfVxuXG4gIGFsbG9jYXRlKGlkZW50aWZpZXI6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMucGFyZW50LmFsbG9jYXRlKGlkZW50aWZpZXIpO1xuICB9XG59XG5cbi8qKlxuICogVGFrZXMgaW4gYW4gQVNUIGFuZCBvdXRwdXRzIGEgbGlzdCBvZiBhY3Rpb25zIHRvIGJlIGNvbnN1bWVkXG4gKiBieSBhIGNvbXBpbGVyLiBGb3IgZXhhbXBsZSwgdGhlIHRlbXBsYXRlXG4gKlxuICogICAgIGZvb3t7YmFyfX08ZGl2PmJhejwvZGl2PlxuICpcbiAqIHByb2R1Y2VzIHRoZSBhY3Rpb25zXG4gKlxuICogICAgIFtbJ3N0YXJ0UHJvZ3JhbScsIFtwcm9ncmFtTm9kZSwgMF1dLFxuICogICAgICBbJ3RleHQnLCBbdGV4dE5vZGUsIDAsIDNdXSxcbiAqICAgICAgWydtdXN0YWNoZScsIFttdXN0YWNoZU5vZGUsIDEsIDNdXSxcbiAqICAgICAgWydvcGVuRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMiwgMywgMF1dLFxuICogICAgICBbJ3RleHQnLCBbdGV4dE5vZGUsIDAsIDFdXSxcbiAqICAgICAgWydjbG9zZUVsZW1lbnQnLCBbZWxlbWVudE5vZGUsIDIsIDNdLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXV1cbiAqXG4gKiBUaGlzIHZpc2l0b3Igd2Fsa3MgdGhlIEFTVCBkZXB0aCBmaXJzdCBhbmQgYmFja3dhcmRzLiBBc1xuICogYSByZXN1bHQgdGhlIGJvdHRvbS1tb3N0IGNoaWxkIHRlbXBsYXRlIHdpbGwgYXBwZWFyIGF0IHRoZVxuICogdG9wIG9mIHRoZSBhY3Rpb25zIGxpc3Qgd2hlcmVhcyB0aGUgcm9vdCB0ZW1wbGF0ZSB3aWxsIGFwcGVhclxuICogYXQgdGhlIGJvdHRvbSBvZiB0aGUgbGlzdC4gRm9yIGV4YW1wbGUsXG4gKlxuICogICAgIDxkaXY+e3sjaWZ9fWZvb3t7ZWxzZX19YmFyPGI+PC9iPnt7L2lmfX08L2Rpdj5cbiAqXG4gKiBwcm9kdWNlcyB0aGUgYWN0aW9uc1xuICpcbiAqICAgICBbWydzdGFydFByb2dyYW0nLCBbcHJvZ3JhbU5vZGUsIDBdXSxcbiAqICAgICAgWyd0ZXh0JywgW3RleHROb2RlLCAwLCAyLCAwXV0sXG4gKiAgICAgIFsnb3BlbkVsZW1lbnQnLCBbZWxlbWVudE5vZGUsIDEsIDIsIDBdXSxcbiAqICAgICAgWydjbG9zZUVsZW1lbnQnLCBbZWxlbWVudE5vZGUsIDEsIDJdXSxcbiAqICAgICAgWydlbmRQcm9ncmFtJywgW3Byb2dyYW1Ob2RlXV0sXG4gKiAgICAgIFsnc3RhcnRQcm9ncmFtJywgW3Byb2dyYW1Ob2RlLCAwXV0sXG4gKiAgICAgIFsndGV4dCcsIFt0ZXh0Tm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXSxcbiAqICAgICAgWydzdGFydFByb2dyYW0nLCBbcHJvZ3JhbU5vZGUsIDJdXSxcbiAqICAgICAgWydvcGVuRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMCwgMSwgMV1dLFxuICogICAgICBbJ2Jsb2NrJywgW2Jsb2NrTm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2Nsb3NlRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXV1cbiAqXG4gKiBUaGUgc3RhdGUgb2YgdGhlIHRyYXZlcnNhbCBpcyBtYWludGFpbmVkIGJ5IGEgc3RhY2sgb2YgZnJhbWVzLlxuICogV2hlbmV2ZXIgYSBub2RlIHdpdGggY2hpbGRyZW4gaXMgZW50ZXJlZCAoZWl0aGVyIGEgUHJvZ3JhbU5vZGVcbiAqIG9yIGFuIEVsZW1lbnROb2RlKSBhIGZyYW1lIGlzIHB1c2hlZCBvbnRvIHRoZSBzdGFjay4gVGhlIGZyYW1lXG4gKiBjb250YWlucyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3RhdGUgb2YgdGhlIHRyYXZlcnNhbCBvZiB0aGF0XG4gKiBub2RlLiBGb3IgZXhhbXBsZSxcbiAqXG4gKiAgIC0gaW5kZXggb2YgdGhlIGN1cnJlbnQgY2hpbGQgbm9kZSBiZWluZyB2aXNpdGVkXG4gKiAgIC0gdGhlIG51bWJlciBvZiBtdXN0YWNoZXMgY29udGFpbmVkIHdpdGhpbiBpdHMgY2hpbGQgbm9kZXNcbiAqICAgLSB0aGUgbGlzdCBvZiBhY3Rpb25zIGdlbmVyYXRlZCBieSBpdHMgY2hpbGQgbm9kZXNcbiAqL1xuXG5jbGFzcyBGcmFtZSB7XG4gIHB1YmxpYyBwYXJlbnROb2RlOiBPcHRpb248T2JqZWN0PiA9IG51bGw7XG4gIHB1YmxpYyBjaGlsZHJlbjogT3B0aW9uPEFTVC5Ob2RlW10+ID0gbnVsbDtcbiAgcHVibGljIGNoaWxkSW5kZXg6IE9wdGlvbjxudW1iZXI+ID0gbnVsbDtcbiAgcHVibGljIGNoaWxkQ291bnQ6IE9wdGlvbjxudW1iZXI+ID0gbnVsbDtcbiAgcHVibGljIGNoaWxkVGVtcGxhdGVDb3VudCA9IDA7XG4gIHB1YmxpYyBtdXN0YWNoZUNvdW50ID0gMDtcbiAgcHVibGljIGFjdGlvbnM6IEFjdGlvbltdID0gW107XG4gIHB1YmxpYyBibGFua0NoaWxkVGV4dE5vZGVzOiBPcHRpb248bnVtYmVyW10+ID0gbnVsbDtcbiAgcHVibGljIHN5bWJvbHM6IE9wdGlvbjxBU1QuU3ltYm9scz4gPSBudWxsO1xufVxuXG5leHBvcnQgbmFtZXNwYWNlIEFjdGlvbiB7XG4gIGV4cG9ydCB0eXBlIFN0YXJ0UHJvZ3JhbSA9IFsnc3RhcnRQcm9ncmFtJywgW0FTVC5UZW1wbGF0ZSwgbnVtYmVyLCBudW1iZXJbXV1dO1xuICBleHBvcnQgdHlwZSBFbmRQcm9ncmFtID0gWydlbmRQcm9ncmFtJywgW0FTVC5UZW1wbGF0ZSwgbnVtYmVyXV07XG4gIGV4cG9ydCB0eXBlIFN0YXJ0QmxvY2sgPSBbJ3N0YXJ0QmxvY2snLCBbQVNULkJsb2NrLCBudW1iZXIsIG51bWJlcltdXV07XG4gIGV4cG9ydCB0eXBlIEVuZEJsb2NrID0gWydlbmRCbG9jaycsIFtBU1QuQmxvY2ssIG51bWJlcl1dO1xuICBleHBvcnQgdHlwZSBCbG9jayA9IFsnYmxvY2snLCBbQVNULkJsb2NrU3RhdGVtZW50LCBudW1iZXIsIG51bWJlcl1dO1xuICBleHBvcnQgdHlwZSBNdXN0YWNoZSA9IFtcbiAgICAnbXVzdGFjaGUnLFxuICAgIFtBU1QuTXVzdGFjaGVTdGF0ZW1lbnQgfCBBU1QuUGFydGlhbFN0YXRlbWVudCwgbnVtYmVyLCBudW1iZXJdXG4gIF07XG4gIGV4cG9ydCB0eXBlIE9wZW5FbGVtZW50ID0gWydvcGVuRWxlbWVudCcsIFtBU1QuRWxlbWVudE5vZGUsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcltdXV07XG4gIGV4cG9ydCB0eXBlIENsb3NlRWxlbWVudCA9IFsnY2xvc2VFbGVtZW50JywgW0FTVC5FbGVtZW50Tm9kZSwgbnVtYmVyLCBudW1iZXJdXTtcbiAgZXhwb3J0IHR5cGUgVGV4dCA9IFsndGV4dCcsIFtBU1QuVGV4dE5vZGUsIG51bWJlciwgbnVtYmVyXV07XG4gIGV4cG9ydCB0eXBlIENvbW1lbnQgPSBbJ2NvbW1lbnQnLCBbQVNULkNvbW1lbnRTdGF0ZW1lbnQsIG51bWJlciwgbnVtYmVyXV07XG5cbiAgZXhwb3J0IHR5cGUgQWN0aW9uID1cbiAgICB8IFN0YXJ0UHJvZ3JhbVxuICAgIHwgRW5kUHJvZ3JhbVxuICAgIHwgU3RhcnRCbG9ja1xuICAgIHwgRW5kQmxvY2tcbiAgICB8IEJsb2NrXG4gICAgfCBNdXN0YWNoZVxuICAgIHwgT3BlbkVsZW1lbnRcbiAgICB8IENsb3NlRWxlbWVudFxuICAgIHwgVGV4dFxuICAgIHwgQ29tbWVudDtcbn1cblxuZXhwb3J0IHR5cGUgQWN0aW9uID0gQWN0aW9uLkFjdGlvbjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVtcGxhdGVWaXNpdG9yIHtcbiAgcHJpdmF0ZSBmcmFtZVN0YWNrOiBGcmFtZVtdID0gW107XG4gIHB1YmxpYyBhY3Rpb25zOiBBY3Rpb25bXSA9IFtdO1xuICBwcml2YXRlIHByb2dyYW1EZXB0aCA9IC0xO1xuXG4gIHZpc2l0PFMgZXh0ZW5kcyBBU1QuVG9wTGV2ZWxTdGF0ZW1lbnQ+KG5vZGU6IFMpIHtcbiAgICAodGhpc1tub2RlLnR5cGVdIGFzICh0aGlzOiB0aGlzLCBub2RlOiBTKSA9PiB2b2lkKShub2RlKTtcbiAgfVxuXG4gIC8vIFRyYXZlcnNhbCBtZXRob2RzXG5cbiAgQmxvY2socHJvZ3JhbTogQVNULkJsb2NrKSB7XG4gICAgcmV0dXJuIHRoaXMuYW55QmxvY2socHJvZ3JhbSk7XG4gIH1cblxuICBUZW1wbGF0ZShwcm9ncmFtOiBBU1QuVGVtcGxhdGUpIHtcbiAgICByZXR1cm4gdGhpcy5hbnlCbG9jayhwcm9ncmFtKTtcbiAgfVxuXG4gIGFueUJsb2NrKHByb2dyYW06IEFTVC5CbG9jayB8IEFTVC5UZW1wbGF0ZSkge1xuICAgIHRoaXMucHJvZ3JhbURlcHRoKys7XG5cbiAgICBsZXQgcGFyZW50RnJhbWUgPSB0aGlzLmdldEN1cnJlbnRGcmFtZSgpO1xuICAgIGxldCBwcm9ncmFtRnJhbWUgPSB0aGlzLnB1c2hGcmFtZSgpO1xuXG4gICAgaWYgKCFwYXJlbnRGcmFtZSkge1xuICAgICAgKHByb2dyYW0gYXMgQVNULlRlbXBsYXRlKS5zeW1ib2xzID0gU3ltYm9sVGFibGUudG9wKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIChwcm9ncmFtIGFzIEFTVC5CbG9jaykuc3ltYm9scyA9IHBhcmVudEZyYW1lLnN5bWJvbHMhLmNoaWxkKHByb2dyYW0uYmxvY2tQYXJhbXMpO1xuICAgIH1cblxuICAgIGxldCBzdGFydFR5cGU6IHN0cmluZywgZW5kVHlwZTogc3RyaW5nO1xuXG4gICAgaWYgKHRoaXMucHJvZ3JhbURlcHRoID09PSAwKSB7XG4gICAgICBzdGFydFR5cGUgPSAnc3RhcnRQcm9ncmFtJztcbiAgICAgIGVuZFR5cGUgPSAnZW5kUHJvZ3JhbSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXJ0VHlwZSA9ICdzdGFydEJsb2NrJztcbiAgICAgIGVuZFR5cGUgPSAnZW5kQmxvY2snO1xuICAgIH1cblxuICAgIHByb2dyYW1GcmFtZS5wYXJlbnROb2RlID0gcHJvZ3JhbTtcbiAgICBwcm9ncmFtRnJhbWUuY2hpbGRyZW4gPSBwcm9ncmFtLmJvZHk7XG4gICAgcHJvZ3JhbUZyYW1lLmNoaWxkQ291bnQgPSBwcm9ncmFtLmJvZHkubGVuZ3RoO1xuICAgIHByb2dyYW1GcmFtZS5ibGFua0NoaWxkVGV4dE5vZGVzID0gW107XG4gICAgcHJvZ3JhbUZyYW1lLmFjdGlvbnMucHVzaChbZW5kVHlwZSwgW3Byb2dyYW0sIHRoaXMucHJvZ3JhbURlcHRoXV0gYXMgQWN0aW9uKTtcbiAgICBwcm9ncmFtRnJhbWUuc3ltYm9scyA9IHByb2dyYW1bJ3N5bWJvbHMnXSE7XG5cbiAgICBmb3IgKGxldCBpID0gcHJvZ3JhbS5ib2R5Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBwcm9ncmFtRnJhbWUuY2hpbGRJbmRleCA9IGk7XG4gICAgICB0aGlzLnZpc2l0KHByb2dyYW0uYm9keVtpXSk7XG4gICAgfVxuXG4gICAgcHJvZ3JhbUZyYW1lLmFjdGlvbnMucHVzaChbXG4gICAgICBzdGFydFR5cGUsXG4gICAgICBbcHJvZ3JhbSwgcHJvZ3JhbUZyYW1lLmNoaWxkVGVtcGxhdGVDb3VudCwgcHJvZ3JhbUZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMucmV2ZXJzZSgpXSxcbiAgICBdIGFzIEFjdGlvbik7XG4gICAgdGhpcy5wb3BGcmFtZSgpO1xuXG4gICAgdGhpcy5wcm9ncmFtRGVwdGgtLTtcblxuICAgIC8vIFB1c2ggdGhlIGNvbXBsZXRlZCB0ZW1wbGF0ZSBpbnRvIHRoZSBnbG9iYWwgYWN0aW9ucyBsaXN0XG4gICAgaWYgKHBhcmVudEZyYW1lKSB7XG4gICAgICBwYXJlbnRGcmFtZS5jaGlsZFRlbXBsYXRlQ291bnQrKztcbiAgICB9XG4gICAgdGhpcy5hY3Rpb25zLnB1c2goLi4ucHJvZ3JhbUZyYW1lLmFjdGlvbnMucmV2ZXJzZSgpKTtcbiAgfVxuXG4gIEVsZW1lbnROb2RlKGVsZW1lbnQ6IEFTVC5FbGVtZW50Tm9kZSkge1xuICAgIGxldCBwYXJlbnRGcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuICAgIGxldCBlbGVtZW50RnJhbWUgPSB0aGlzLnB1c2hGcmFtZSgpO1xuXG4gICAgZWxlbWVudEZyYW1lLnBhcmVudE5vZGUgPSBlbGVtZW50O1xuICAgIGVsZW1lbnRGcmFtZS5jaGlsZHJlbiA9IGVsZW1lbnQuY2hpbGRyZW47XG4gICAgZWxlbWVudEZyYW1lLmNoaWxkQ291bnQgPSBlbGVtZW50LmNoaWxkcmVuLmxlbmd0aDtcbiAgICBlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCArPSBlbGVtZW50Lm1vZGlmaWVycy5sZW5ndGg7XG4gICAgZWxlbWVudEZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMgPSBbXTtcbiAgICBlbGVtZW50RnJhbWUuc3ltYm9scyA9IGVsZW1lbnQuc3ltYm9scyA9IHBhcmVudEZyYW1lLnN5bWJvbHMhLmNoaWxkKGVsZW1lbnQuYmxvY2tQYXJhbXMpO1xuXG4gICAgbGV0IGFjdGlvbkFyZ3M6IFtBU1QuRWxlbWVudE5vZGUsIG51bWJlciwgbnVtYmVyXSA9IFtcbiAgICAgIGVsZW1lbnQsXG4gICAgICBwYXJlbnRGcmFtZS5jaGlsZEluZGV4ISxcbiAgICAgIHBhcmVudEZyYW1lLmNoaWxkQ291bnQhLFxuICAgIF07XG5cbiAgICBlbGVtZW50RnJhbWUuYWN0aW9ucy5wdXNoKFsnY2xvc2VFbGVtZW50JywgYWN0aW9uQXJnc10pO1xuXG4gICAgZm9yIChsZXQgaSA9IGVsZW1lbnQuYXR0cmlidXRlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdGhpcy52aXNpdChlbGVtZW50LmF0dHJpYnV0ZXNbaV0pO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBlbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBlbGVtZW50RnJhbWUuY2hpbGRJbmRleCA9IGk7XG4gICAgICB0aGlzLnZpc2l0KGVsZW1lbnQuY2hpbGRyZW5baV0pO1xuICAgIH1cblxuICAgIGxldCBvcGVuID0gW1xuICAgICAgJ29wZW5FbGVtZW50JyxcbiAgICAgIFsuLi5hY3Rpb25BcmdzLCBlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCwgZWxlbWVudEZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMucmV2ZXJzZSgpXSxcbiAgICBdIGFzIEFjdGlvbi5PcGVuRWxlbWVudDtcbiAgICBlbGVtZW50RnJhbWUuYWN0aW9ucy5wdXNoKG9wZW4pO1xuXG4gICAgdGhpcy5wb3BGcmFtZSgpO1xuXG4gICAgLy8gUHJvcGFnYXRlIHRoZSBlbGVtZW50J3MgZnJhbWUgc3RhdGUgdG8gdGhlIHBhcmVudCBmcmFtZVxuICAgIGlmIChlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCA+IDApIHtcbiAgICAgIHBhcmVudEZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICB9XG4gICAgcGFyZW50RnJhbWUuY2hpbGRUZW1wbGF0ZUNvdW50ICs9IGVsZW1lbnRGcmFtZS5jaGlsZFRlbXBsYXRlQ291bnQ7XG4gICAgcGFyZW50RnJhbWUuYWN0aW9ucy5wdXNoKC4uLmVsZW1lbnRGcmFtZS5hY3Rpb25zKTtcbiAgfVxuXG4gIEF0dHJOb2RlKGF0dHI6IEFTVC5BdHRyTm9kZSkge1xuICAgIGlmIChhdHRyLnZhbHVlLnR5cGUgIT09ICdUZXh0Tm9kZScpIHtcbiAgICAgIHRoaXMuY3VycmVudEZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICB9XG4gIH1cblxuICBUZXh0Tm9kZSh0ZXh0OiBBU1QuVGV4dE5vZGUpIHtcbiAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICBpZiAodGV4dC5jaGFycyA9PT0gJycpIHtcbiAgICAgIGZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMhLnB1c2goZG9tSW5kZXhPZihmcmFtZS5jaGlsZHJlbiEsIHRleHQpKTtcbiAgICB9XG4gICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsndGV4dCcsIFt0ZXh0LCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0gYXMgQWN0aW9uKTtcbiAgfVxuXG4gIEJsb2NrU3RhdGVtZW50KG5vZGU6IEFTVC5CbG9ja1N0YXRlbWVudCkge1xuICAgIGxldCBmcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuXG4gICAgZnJhbWUubXVzdGFjaGVDb3VudCsrO1xuICAgIGZyYW1lLmFjdGlvbnMucHVzaChbJ2Jsb2NrJywgW25vZGUsIGZyYW1lLmNoaWxkSW5kZXgsIGZyYW1lLmNoaWxkQ291bnRdXSBhcyBBY3Rpb24pO1xuXG4gICAgaWYgKG5vZGUuaW52ZXJzZSkge1xuICAgICAgdGhpcy52aXNpdChub2RlLmludmVyc2UpO1xuICAgIH1cbiAgICBpZiAobm9kZS5wcm9ncmFtKSB7XG4gICAgICB0aGlzLnZpc2l0KG5vZGUucHJvZ3JhbSk7XG4gICAgfVxuICB9XG5cbiAgUGFydGlhbFN0YXRlbWVudChub2RlOiBBU1QuUGFydGlhbFN0YXRlbWVudCkge1xuICAgIGxldCBmcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuICAgIGZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICBmcmFtZS5hY3Rpb25zLnB1c2goWydtdXN0YWNoZScsIFtub2RlLCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0gYXMgQWN0aW9uKTtcbiAgfVxuXG4gIENvbW1lbnRTdGF0ZW1lbnQodGV4dDogQVNULkNvbW1lbnRTdGF0ZW1lbnQpIHtcbiAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICBmcmFtZS5hY3Rpb25zLnB1c2goWydjb21tZW50JywgW3RleHQsIGZyYW1lLmNoaWxkSW5kZXgsIGZyYW1lLmNoaWxkQ291bnRdXSBhcyBBY3Rpb24pO1xuICB9XG5cbiAgTXVzdGFjaGVDb21tZW50U3RhdGVtZW50KCkge1xuICAgIC8vIEludGVudGlvbmFsIGVtcHR5OiBIYW5kbGViYXJzIGNvbW1lbnRzIHNob3VsZCBub3QgYWZmZWN0IG91dHB1dC5cbiAgfVxuXG4gIE11c3RhY2hlU3RhdGVtZW50KG11c3RhY2hlOiBBU1QuTXVzdGFjaGVTdGF0ZW1lbnQpIHtcbiAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICBmcmFtZS5tdXN0YWNoZUNvdW50Kys7XG4gICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsnbXVzdGFjaGUnLCBbbXVzdGFjaGUsIGZyYW1lLmNoaWxkSW5kZXgsIGZyYW1lLmNoaWxkQ291bnRdXSBhcyBBY3Rpb24pO1xuICB9XG5cbiAgLy8gRnJhbWUgaGVscGVyc1xuXG4gIHByaXZhdGUgZ2V0IGN1cnJlbnRGcmFtZSgpOiBGcmFtZSB7XG4gICAgcmV0dXJuIGV4cGVjdCh0aGlzLmdldEN1cnJlbnRGcmFtZSgpLCAnRXhwZWN0ZWQgYSBjdXJyZW50IGZyYW1lJyk7XG4gIH1cblxuICBwcml2YXRlIGdldEN1cnJlbnRGcmFtZSgpOiBPcHRpb248RnJhbWU+IHtcbiAgICByZXR1cm4gdGhpcy5mcmFtZVN0YWNrW3RoaXMuZnJhbWVTdGFjay5sZW5ndGggLSAxXTtcbiAgfVxuXG4gIHByaXZhdGUgcHVzaEZyYW1lKCkge1xuICAgIGxldCBmcmFtZSA9IG5ldyBGcmFtZSgpO1xuICAgIHRoaXMuZnJhbWVTdGFjay5wdXNoKGZyYW1lKTtcbiAgICByZXR1cm4gZnJhbWU7XG4gIH1cblxuICBwcml2YXRlIHBvcEZyYW1lKCkge1xuICAgIHJldHVybiB0aGlzLmZyYW1lU3RhY2sucG9wKCk7XG4gIH1cbn1cblxuLy8gUmV0dXJucyB0aGUgaW5kZXggb2YgYGRvbU5vZGVgIGluIHRoZSBgbm9kZXNgIGFycmF5LCBza2lwcGluZ1xuLy8gb3ZlciBhbnkgbm9kZXMgd2hpY2ggZG8gbm90IHJlcHJlc2VudCBET00gbm9kZXMuXG5mdW5jdGlvbiBkb21JbmRleE9mKG5vZGVzOiBBU1QuTm9kZVtdLCBkb21Ob2RlOiBBU1QuVGV4dE5vZGUgfCBBU1QuRWxlbWVudE5vZGUpIHtcbiAgbGV0IGluZGV4ID0gLTE7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBub2RlID0gbm9kZXNbaV07XG5cbiAgICBpZiAobm9kZS50eXBlICE9PSAnVGV4dE5vZGUnICYmIG5vZGUudHlwZSAhPT0gJ0VsZW1lbnROb2RlJykge1xuICAgICAgY29udGludWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGluZGV4Kys7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUgPT09IGRvbU5vZGUpIHtcbiAgICAgIHJldHVybiBpbmRleDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gLTE7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9