@glimmer/compiler
Version:
326 lines (321 loc) • 38.7 kB
JavaScript
'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