ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
311 lines (299 loc) • 36.8 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.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 [];
}
allocateNamed(name) {
let named = this.named[name];
if (!named) {
named = this.named[name] = this.allocate(`@${name}`);
}
return named;
}
allocateBlock(name) {
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]);
}
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
Program(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 (0, _util.expect)(this.getCurrentFrame(), "Expected a current frame");
}
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90ZW1wbGF0ZS12aXNpdG9yLmpzIl0sIm5hbWVzIjpbIlN5bWJvbFRhYmxlIiwidG9wIiwiUHJvZ3JhbVN5bWJvbFRhYmxlIiwiY2hpbGQiLCJsb2NhbHMiLCJzeW1ib2xzIiwibWFwIiwibmFtZSIsImFsbG9jYXRlIiwiQmxvY2tTeW1ib2xUYWJsZSIsImNvbnN0cnVjdG9yIiwiYXJndW1lbnRzIiwic2l6ZSIsIm5hbWVkIiwiYmxvY2tzIiwiaGFzIiwiX25hbWUiLCJnZXQiLCJnZXRMb2NhbHNNYXAiLCJnZXRFdmFsSW5mbyIsImFsbG9jYXRlTmFtZWQiLCJhbGxvY2F0ZUJsb2NrIiwiYmxvY2siLCJpZGVudGlmaWVyIiwicHVzaCIsInBhcmVudCIsInNsb3RzIiwiaW5kZXhPZiIsInNsb3QiLCJkaWN0IiwiZm9yRWFjaCIsInN5bWJvbCIsIk9iamVjdCIsImtleXMiLCJGcmFtZSIsInBhcmVudE5vZGUiLCJjaGlsZHJlbiIsImNoaWxkSW5kZXgiLCJjaGlsZENvdW50IiwiY2hpbGRUZW1wbGF0ZUNvdW50IiwibXVzdGFjaGVDb3VudCIsImFjdGlvbnMiLCJibGFua0NoaWxkVGV4dE5vZGVzIiwiVGVtcGxhdGVWaXNpdG9yIiwiZnJhbWVTdGFjayIsInByb2dyYW1EZXB0aCIsInZpc2l0Iiwibm9kZSIsInR5cGUiLCJQcm9ncmFtIiwicHJvZ3JhbSIsInBhcmVudEZyYW1lIiwiZ2V0Q3VycmVudEZyYW1lIiwicHJvZ3JhbUZyYW1lIiwicHVzaEZyYW1lIiwiYmxvY2tQYXJhbXMiLCJzdGFydFR5cGUiLCJlbmRUeXBlIiwiYm9keSIsImxlbmd0aCIsImkiLCJyZXZlcnNlIiwicG9wRnJhbWUiLCJFbGVtZW50Tm9kZSIsImVsZW1lbnQiLCJjdXJyZW50RnJhbWUiLCJlbGVtZW50RnJhbWUiLCJtb2RpZmllcnMiLCJhY3Rpb25BcmdzIiwiYXR0cmlidXRlcyIsIm9wZW4iLCJBdHRyTm9kZSIsImF0dHIiLCJ2YWx1ZSIsIlRleHROb2RlIiwidGV4dCIsImZyYW1lIiwiY2hhcnMiLCJkb21JbmRleE9mIiwiQmxvY2tTdGF0ZW1lbnQiLCJpbnZlcnNlIiwiUGFydGlhbFN0YXRlbWVudCIsIkNvbW1lbnRTdGF0ZW1lbnQiLCJNdXN0YWNoZUNvbW1lbnRTdGF0ZW1lbnQiLCJNdXN0YWNoZVN0YXRlbWVudCIsIm11c3RhY2hlIiwicG9wIiwibm9kZXMiLCJkb21Ob2RlIiwiaW5kZXgiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDTyxNQUFNQSxXQUFOLENBQWtCO0FBQ3JCLFdBQU9DLEdBQVAsR0FBYTtBQUNULGVBQU8sSUFBSUMsa0JBQUosRUFBUDtBQUNIO0FBQ0RDLFVBQU1DLE1BQU4sRUFBYztBQUNWLFlBQUlDLFVBQVVELE9BQU9FLEdBQVAsQ0FBV0MsUUFBUSxLQUFLQyxRQUFMLENBQWNELElBQWQsQ0FBbkIsQ0FBZDtBQUNBLGVBQU8sSUFBSUUsZ0JBQUosQ0FBcUIsSUFBckIsRUFBMkJMLE1BQTNCLEVBQW1DQyxPQUFuQyxDQUFQO0FBQ0g7QUFQb0I7UUFBWkwsVyxHQUFBQSxXO0FBU04sTUFBTUUsa0JBQU4sU0FBaUNGLFdBQWpDLENBQTZDO0FBQ2hEVSxrQkFBYztBQUNWLGNBQU0sR0FBR0MsU0FBVDtBQUNBLGFBQUtOLE9BQUwsR0FBZSxFQUFmO0FBQ0EsYUFBS08sSUFBTCxHQUFZLENBQVo7QUFDQSxhQUFLQyxLQUFMLEdBQWEsaUJBQWI7QUFDQSxhQUFLQyxNQUFMLEdBQWMsaUJBQWQ7QUFDSDtBQUNEQyxRQUFJQyxLQUFKLEVBQVc7QUFDUCxlQUFPLEtBQVA7QUFDSDtBQUNEQyxRQUFJRCxLQUFKLEVBQVc7QUFDUCxjQUFNLHdCQUFOO0FBQ0g7QUFDREUsbUJBQWU7QUFDWCxlQUFPLEVBQVA7QUFDSDtBQUNEQyxrQkFBYztBQUNWLGVBQU8sRUFBUDtBQUNIO0FBQ0RDLGtCQUFjYixJQUFkLEVBQW9CO0FBQ2hCLFlBQUlNLFFBQVEsS0FBS0EsS0FBTCxDQUFXTixJQUFYLENBQVo7QUFDQSxZQUFJLENBQUNNLEtBQUwsRUFBWTtBQUNS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QixNQUFNNUIsTUFBMUIsRUFBa0NDLEdBQWxDLEVBQXVDO0FBQ25DLFlBQUliLE9BQU93QyxNQUFNM0IsQ0FBTixDQUFYO0FBQ0EsWUFBSWIsS0FBS0MsSUFBTCxLQUFjLFVBQWQsSUFBNEJELEtBQUtDLElBQUwsS0FBYyxhQUE5QyxFQUE2RDtBQUN6RDtBQUNILFNBRkQsTUFFTztBQUNIeUM7QUFDSDtBQUNELFlBQUkxQyxTQUFTeUMsT0FBYixFQUFzQjtBQUNsQixtQkFBT0MsS0FBUDtBQUNIO0FBQ0o7QUFDRCxXQUFPLENBQUMsQ0FBUjtBQUNIIiwiZmlsZSI6ImxpYi90ZW1wbGF0ZS12aXNpdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZGljdCwgdW5yZWFjaGFibGUsIGV4cGVjdCB9IGZyb20gJ0BnbGltbWVyL3V0aWwnO1xuZXhwb3J0IGNsYXNzIFN5bWJvbFRhYmxlIHtcbiAgICBzdGF0aWMgdG9wKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb2dyYW1TeW1ib2xUYWJsZSgpO1xuICAgIH1cbiAgICBjaGlsZChsb2NhbHMpIHtcbiAgICAgICAgbGV0IHN5bWJvbHMgPSBsb2NhbHMubWFwKG5hbWUgPT4gdGhpcy5hbGxvY2F0ZShuYW1lKSk7XG4gICAgICAgIHJldHVybiBuZXcgQmxvY2tTeW1ib2xUYWJsZSh0aGlzLCBsb2NhbHMsIHN5bWJvbHMpO1xuICAgIH1cbn1cbmV4cG9ydCBjbGFzcyBQcm9ncmFtU3ltYm9sVGFibGUgZXh0ZW5kcyBTeW1ib2xUYWJsZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuc3ltYm9scyA9IFtdO1xuICAgICAgICB0aGlzLnNpemUgPSAxO1xuICAgICAgICB0aGlzLm5hbWVkID0gZGljdCgpO1xuICAgICAgICB0aGlzLmJsb2NrcyA9IGRpY3QoKTtcbiAgICB9XG4gICAgaGFzKF9uYW1lKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZ2V0KF9uYW1lKSB7XG4gICAgICAgIHRocm93IHVucmVhY2hhYmxlKCk7XG4gICAgfVxuICAgIGdldExvY2Fsc01hcCgpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBnZXRFdmFsSW5mbygpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBhbGxvY2F0ZU5hbWVkKG5hbWUpIHtcbiAgICAgICAgbGV0IG5hbWVkID0gdGhpcy5uYW1lZFtuYW1lXTtcbiAgICAgICAgaWYgKCFuYW1lZCkge1xuICAgICAgICAgICAgbmFtZWQgPSB0aGlzLm5hbWVkW25hbWVdID0gdGhpcy5hbGxvY2F0ZShgQCR7bmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmFtZWQ7XG4gICAgfVxuICAgIGFsbG9jYXRlQmxvY2sobmFtZSkge1xuICAgICAgICBsZXQgYmxvY2sgPSB0aGlzLmJsb2Nrc1tuYW1lXTtcbiAgICAgICAgaWYgKCFibG9jaykge1xuICAgICAgICAgICAgYmxvY2sgPSB0aGlzLmJsb2Nrc1tuYW1lXSA9IHRoaXMuYWxsb2NhdGUoYCYke25hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJsb2NrO1xuICAgIH1cbiAgICBhbGxvY2F0ZShpZGVudGlmaWVyKSB7XG4gICAgICAgIHRoaXMuc3ltYm9scy5wdXNoKGlkZW50aWZpZXIpO1xuICAgICAgICByZXR1cm4gdGhpcy5zaXplKys7XG4gICAgfVxufVxuZXhwb3J0IGNsYXNzIEJsb2NrU3ltYm9sVGFibGUgZXh0ZW5kcyBTeW1ib2xUYWJsZSB7XG4gICAgY29uc3RydWN0b3IocGFyZW50LCBzeW1ib2xzLCBzbG90cykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnBhcmVudCA9IHBhcmVudDtcbiAgICAgICAgdGhpcy5zeW1ib2xzID0gc3ltYm9scztcbiAgICAgICAgdGhpcy5zbG90cyA9IHNsb3RzO1xuICAgIH1cbiAgICBoYXMobmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW1ib2xzLmluZGV4T2YobmFtZSkgIT09IC0xIHx8IHRoaXMucGFyZW50LmhhcyhuYW1lKTtcbiAgICB9XG4gICAgZ2V0KG5hbWUpIHtcbiAgICAgICAgbGV0IHNsb3QgPSB0aGlzLnN5bWJvbHMuaW5kZXhPZihuYW1lKTtcbiAgICAgICAgcmV0dXJuIHNsb3QgPT09IC0xID8gdGhpcy5wYXJlbnQuZ2V0KG5hbWUpIDogdGhpcy5zbG90c1tzbG90XTtcbiAgICB9XG4gICAgZ2V0TG9jYWxzTWFwKCkge1xuICAgICAgICBsZXQgZGljdCA9IHRoaXMucGFyZW50LmdldExvY2Fsc01hcCgpO1xuICAgICAgICB0aGlzLnN5bWJvbHMuZm9yRWFjaChzeW1ib2wgPT4gZGljdFtzeW1ib2xdID0gdGhpcy5nZXQoc3ltYm9sKSk7XG4gICAgICAgIHJldHVybiBkaWN0O1xuICAgIH1cbiAgICBnZXRFdmFsSW5mbygpIHtcbiAgICAgICAgbGV0IGxvY2FscyA9IHRoaXMuZ2V0TG9jYWxzTWFwKCk7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhsb2NhbHMpLm1hcChzeW1ib2wgPT4gbG9jYWxzW3N5bWJvbF0pO1xuICAgIH1cbiAgICBhbGxvY2F0ZU5hbWVkKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50LmFsbG9jYXRlTmFtZWQobmFtZSk7XG4gICAgfVxuICAgIGFsbG9jYXRlQmxvY2sobmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnQuYWxsb2NhdGVCbG9jayhuYW1lKTtcbiAgICB9XG4gICAgYWxsb2NhdGUoaWRlbnRpZmllcikge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnQuYWxsb2NhdGUoaWRlbnRpZmllcik7XG4gICAgfVxufVxuLyoqXG4gKiBUYWtlcyBpbiBhbiBBU1QgYW5kIG91dHB1dHMgYSBsaXN0IG9mIGFjdGlvbnMgdG8gYmUgY29uc3VtZWRcbiAqIGJ5IGEgY29tcGlsZXIuIEZvciBleGFtcGxlLCB0aGUgdGVtcGxhdGVcbiAqXG4gKiAgICAgZm9ve3tiYXJ9fTxkaXY+YmF6PC9kaXY+XG4gKlxuICogcHJvZHVjZXMgdGhlIGFjdGlvbnNcbiAqXG4gKiAgICAgW1snc3RhcnRQcm9ncmFtJywgW3Byb2dyYW1Ob2RlLCAwXV0sXG4gKiAgICAgIFsndGV4dCcsIFt0ZXh0Tm9kZSwgMCwgM11dLFxuICogICAgICBbJ211c3RhY2hlJywgW211c3RhY2hlTm9kZSwgMSwgM11dLFxuICogICAgICBbJ29wZW5FbGVtZW50JywgW2VsZW1lbnROb2RlLCAyLCAzLCAwXV0sXG4gKiAgICAgIFsndGV4dCcsIFt0ZXh0Tm9kZSwgMCwgMV1dLFxuICogICAgICBbJ2Nsb3NlRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMiwgM10sXG4gKiAgICAgIFsnZW5kUHJvZ3JhbScsIFtwcm9ncmFtTm9kZV1dXVxuICpcbiAqIFRoaXMgdmlzaXRvciB3YWxrcyB0aGUgQVNUIGRlcHRoIGZpcnN0IGFuZCBiYWNrd2FyZHMuIEFzXG4gKiBhIHJlc3VsdCB0aGUgYm90dG9tLW1vc3QgY2hpbGQgdGVtcGxhdGUgd2lsbCBhcHBlYXIgYXQgdGhlXG4gKiB0b3Agb2YgdGhlIGFjdGlvbnMgbGlzdCB3aGVyZWFzIHRoZSByb290IHRlbXBsYXRlIHdpbGwgYXBwZWFyXG4gKiBhdCB0aGUgYm90dG9tIG9mIHRoZSBsaXN0LiBGb3IgZXhhbXBsZSxcbiAqXG4gKiAgICAgPGRpdj57eyNpZn19Zm9ve3tlbHNlfX1iYXI8Yj48L2I+e3svaWZ9fTwvZGl2PlxuICpcbiAqIHByb2R1Y2VzIHRoZSBhY3Rpb25zXG4gKlxuICogICAgIFtbJ3N0YXJ0UHJvZ3JhbScsIFtwcm9ncmFtTm9kZSwgMF1dLFxuICogICAgICBbJ3RleHQnLCBbdGV4dE5vZGUsIDAsIDIsIDBdXSxcbiAqICAgICAgWydvcGVuRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMSwgMiwgMF1dLFxuICogICAgICBbJ2Nsb3NlRWxlbWVudCcsIFtlbGVtZW50Tm9kZSwgMSwgMl1dLFxuICogICAgICBbJ2VuZFByb2dyYW0nLCBbcHJvZ3JhbU5vZGVdXSxcbiAqICAgICAgWydzdGFydFByb2dyYW0nLCBbcHJvZ3JhbU5vZGUsIDBdXSxcbiAqICAgICAgWyd0ZXh0JywgW3RleHROb2RlLCAwLCAxXV0sXG4gKiAgICAgIFsnZW5kUHJvZ3JhbScsIFtwcm9ncmFtTm9kZV1dLFxuICogICAgICBbJ3N0YXJ0UHJvZ3JhbScsIFtwcm9ncmFtTm9kZSwgMl1dLFxuICogICAgICBbJ29wZW5FbGVtZW50JywgW2VsZW1lbnROb2RlLCAwLCAxLCAxXV0sXG4gKiAgICAgIFsnYmxvY2snLCBbYmxvY2tOb2RlLCAwLCAxXV0sXG4gKiAgICAgIFsnY2xvc2VFbGVtZW50JywgW2VsZW1lbnROb2RlLCAwLCAxXV0sXG4gKiAgICAgIFsnZW5kUHJvZ3JhbScsIFtwcm9ncmFtTm9kZV1dXVxuICpcbiAqIFRoZSBzdGF0ZSBvZiB0aGUgdHJhdmVyc2FsIGlzIG1haW50YWluZWQgYnkgYSBzdGFjayBvZiBmcmFtZXMuXG4gKiBXaGVuZXZlciBhIG5vZGUgd2l0aCBjaGlsZHJlbiBpcyBlbnRlcmVkIChlaXRoZXIgYSBQcm9ncmFtTm9kZVxuICogb3IgYW4gRWxlbWVudE5vZGUpIGEgZnJhbWUgaXMgcHVzaGVkIG9udG8gdGhlIHN0YWNrLiBUaGUgZnJhbWVcbiAqIGNvbnRhaW5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzdGF0ZSBvZiB0aGUgdHJhdmVyc2FsIG9mIHRoYXRcbiAqIG5vZGUuIEZvciBleGFtcGxlLFxuICpcbiAqICAgLSBpbmRleCBvZiB0aGUgY3VycmVudCBjaGlsZCBub2RlIGJlaW5nIHZpc2l0ZWRcbiAqICAgLSB0aGUgbnVtYmVyIG9mIG11c3RhY2hlcyBjb250YWluZWQgd2l0aGluIGl0cyBjaGlsZCBub2Rlc1xuICogICAtIHRoZSBsaXN0IG9mIGFjdGlvbnMgZ2VuZXJhdGVkIGJ5IGl0cyBjaGlsZCBub2Rlc1xuICovXG5jbGFzcyBGcmFtZSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMucGFyZW50Tm9kZSA9IG51bGw7XG4gICAgICAgIHRoaXMuY2hpbGRyZW4gPSBudWxsO1xuICAgICAgICB0aGlzLmNoaWxkSW5kZXggPSBudWxsO1xuICAgICAgICB0aGlzLmNoaWxkQ291bnQgPSBudWxsO1xuICAgICAgICB0aGlzLmNoaWxkVGVtcGxhdGVDb3VudCA9IDA7XG4gICAgICAgIHRoaXMubXVzdGFjaGVDb3VudCA9IDA7XG4gICAgICAgIHRoaXMuYWN0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmJsYW5rQ2hpbGRUZXh0Tm9kZXMgPSBudWxsO1xuICAgICAgICB0aGlzLnN5bWJvbHMgPSBudWxsO1xuICAgIH1cbn1cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRlbXBsYXRlVmlzaXRvciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZnJhbWVTdGFjayA9IFtdO1xuICAgICAgICB0aGlzLmFjdGlvbnMgPSBbXTtcbiAgICAgICAgdGhpcy5wcm9ncmFtRGVwdGggPSAtMTtcbiAgICB9XG4gICAgdmlzaXQobm9kZSkge1xuICAgICAgICB0aGlzW25vZGUudHlwZV0obm9kZSk7XG4gICAgfVxuICAgIC8vIFRyYXZlcnNhbCBtZXRob2RzXG4gICAgUHJvZ3JhbShwcm9ncmFtKSB7XG4gICAgICAgIHRoaXMucHJvZ3JhbURlcHRoKys7XG4gICAgICAgIGxldCBwYXJlbnRGcmFtZSA9IHRoaXMuZ2V0Q3VycmVudEZyYW1lKCk7XG4gICAgICAgIGxldCBwcm9ncmFtRnJhbWUgPSB0aGlzLnB1c2hGcmFtZSgpO1xuICAgICAgICBpZiAoIXBhcmVudEZyYW1lKSB7XG4gICAgICAgICAgICBwcm9ncmFtWydzeW1ib2xzJ10gPSBTeW1ib2xUYWJsZS50b3AoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb2dyYW1bJ3N5bWJvbHMnXSA9IHBhcmVudEZyYW1lLnN5bWJvbHMuY2hpbGQocHJvZ3JhbS5ibG9ja1BhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHN0YXJ0VHlwZSwgZW5kVHlwZTtcbiAgICAgICAgaWYgKHRoaXMucHJvZ3JhbURlcHRoID09PSAwKSB7XG4gICAgICAgICAgICBzdGFydFR5cGUgPSAnc3RhcnRQcm9ncmFtJztcbiAgICAgICAgICAgIGVuZFR5cGUgPSAnZW5kUHJvZ3JhbSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGFydFR5cGUgPSAnc3RhcnRCbG9jayc7XG4gICAgICAgICAgICBlbmRUeXBlID0gJ2VuZEJsb2NrJztcbiAgICAgICAgfVxuICAgICAgICBwcm9ncmFtRnJhbWUucGFyZW50Tm9kZSA9IHByb2dyYW07XG4gICAgICAgIHByb2dyYW1GcmFtZS5jaGlsZHJlbiA9IHByb2dyYW0uYm9keTtcbiAgICAgICAgcHJvZ3JhbUZyYW1lLmNoaWxkQ291bnQgPSBwcm9ncmFtLmJvZHkubGVuZ3RoO1xuICAgICAgICBwcm9ncmFtRnJhbWUuYmxhbmtDaGlsZFRleHROb2RlcyA9IFtdO1xuICAgICAgICBwcm9ncmFtRnJhbWUuYWN0aW9ucy5wdXNoKFtlbmRUeXBlLCBbcHJvZ3JhbSwgdGhpcy5wcm9ncmFtRGVwdGhdXSk7XG4gICAgICAgIHByb2dyYW1GcmFtZS5zeW1ib2xzID0gcHJvZ3JhbVsnc3ltYm9scyddO1xuICAgICAgICBmb3IgKGxldCBpID0gcHJvZ3JhbS5ib2R5Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBwcm9ncmFtRnJhbWUuY2hpbGRJbmRleCA9IGk7XG4gICAgICAgICAgICB0aGlzLnZpc2l0KHByb2dyYW0uYm9keVtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcHJvZ3JhbUZyYW1lLmFjdGlvbnMucHVzaChbc3RhcnRUeXBlLCBbcHJvZ3JhbSwgcHJvZ3JhbUZyYW1lLmNoaWxkVGVtcGxhdGVDb3VudCwgcHJvZ3JhbUZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMucmV2ZXJzZSgpXV0pO1xuICAgICAgICB0aGlzLnBvcEZyYW1lKCk7XG4gICAgICAgIHRoaXMucHJvZ3JhbURlcHRoLS07XG4gICAgICAgIC8vIFB1c2ggdGhlIGNvbXBsZXRlZCB0ZW1wbGF0ZSBpbnRvIHRoZSBnbG9iYWwgYWN0aW9ucyBsaXN0XG4gICAgICAgIGlmIChwYXJlbnRGcmFtZSkge1xuICAgICAgICAgICAgcGFyZW50RnJhbWUuY2hpbGRUZW1wbGF0ZUNvdW50Kys7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hY3Rpb25zLnB1c2goLi4ucHJvZ3JhbUZyYW1lLmFjdGlvbnMucmV2ZXJzZSgpKTtcbiAgICB9XG4gICAgRWxlbWVudE5vZGUoZWxlbWVudCkge1xuICAgICAgICBsZXQgcGFyZW50RnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICAgICAgbGV0IGVsZW1lbnRGcmFtZSA9IHRoaXMucHVzaEZyYW1lKCk7XG4gICAgICAgIGVsZW1lbnRGcmFtZS5wYXJlbnROb2RlID0gZWxlbWVudDtcbiAgICAgICAgZWxlbWVudEZyYW1lLmNoaWxkcmVuID0gZWxlbWVudC5jaGlsZHJlbjtcbiAgICAgICAgZWxlbWVudEZyYW1lLmNoaWxkQ291bnQgPSBlbGVtZW50LmNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgZWxlbWVudEZyYW1lLm11c3RhY2hlQ291bnQgKz0gZWxlbWVudC5tb2RpZmllcnMubGVuZ3RoO1xuICAgICAgICBlbGVtZW50RnJhbWUuYmxhbmtDaGlsZFRleHROb2RlcyA9IFtdO1xuICAgICAgICBlbGVtZW50RnJhbWUuc3ltYm9scyA9IGVsZW1lbnRbJ3N5bWJvbHMnXSA9IHBhcmVudEZyYW1lLnN5bWJvbHMuY2hpbGQoZWxlbWVudC5ibG9ja1BhcmFtcyk7XG4gICAgICAgIGxldCBhY3Rpb25BcmdzID0gW2VsZW1lbnQsIHBhcmVudEZyYW1lLmNoaWxkSW5kZXgsIHBhcmVudEZyYW1lLmNoaWxkQ291bnRdO1xuICAgICAgICBlbGVtZW50RnJhbWUuYWN0aW9ucy5wdXNoKFsnY2xvc2VFbGVtZW50JywgYWN0aW9uQXJnc10pO1xuICAgICAgICBmb3IgKGxldCBpID0gZWxlbWVudC5hdHRyaWJ1dGVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICB0aGlzLnZpc2l0KGVsZW1lbnQuYXR0cmlidXRlc1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaSA9IGVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGVsZW1lbnRGcmFtZS5jaGlsZEluZGV4ID0gaTtcbiAgICAgICAgICAgIHRoaXMudmlzaXQoZWxlbWVudC5jaGlsZHJlbltpXSk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IG9wZW4gPSBbJ29wZW5FbGVtZW50JywgWy4uLmFjdGlvbkFyZ3MsIGVsZW1lbnRGcmFtZS5tdXN0YWNoZUNvdW50LCBlbGVtZW50RnJhbWUuYmxhbmtDaGlsZFRleHROb2Rlcy5yZXZlcnNlKCldXTtcbiAgICAgICAgZWxlbWVudEZyYW1lLmFjdGlvbnMucHVzaChvcGVuKTtcbiAgICAgICAgdGhpcy5wb3BGcmFtZSgpO1xuICAgICAgICAvLyBQcm9wYWdhdGUgdGhlIGVsZW1lbnQncyBmcmFtZSBzdGF0ZSB0byB0aGUgcGFyZW50IGZyYW1lXG4gICAgICAgIGlmIChlbGVtZW50RnJhbWUubXVzdGFjaGVDb3VudCA+IDApIHtcbiAgICAgICAgICAgIHBhcmVudEZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRGcmFtZS5jaGlsZFRlbXBsYXRlQ291bnQgKz0gZWxlbWVudEZyYW1lLmNoaWxkVGVtcGxhdGVDb3VudDtcbiAgICAgICAgcGFyZW50RnJhbWUuYWN0aW9ucy5wdXNoKC4uLmVsZW1lbnRGcmFtZS5hY3Rpb25zKTtcbiAgICB9XG4gICAgQXR0ck5vZGUoYXR0cikge1xuICAgICAgICBpZiAoYXR0ci52YWx1ZS50eXBlICE9PSAnVGV4dE5vZGUnKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRGcmFtZS5tdXN0YWNoZUNvdW50Kys7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBUZXh0Tm9kZSh0ZXh0KSB7XG4gICAgICAgIGxldCBmcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuICAgICAgICBpZiAodGV4dC5jaGFycyA9PT0gJycpIHtcbiAgICAgICAgICAgIGZyYW1lLmJsYW5rQ2hpbGRUZXh0Tm9kZXMucHVzaChkb21JbmRleE9mKGZyYW1lLmNoaWxkcmVuLCB0ZXh0KSk7XG4gICAgICAgIH1cbiAgICAgICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsndGV4dCcsIFt0ZXh0LCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0pO1xuICAgIH1cblxuICAgIEJsb2NrU3RhdGVtZW50KG5vZGUpIHtcbiAgICAgICAgbGV0IGZyYW1lID0gdGhpcy5jdXJyZW50RnJhbWU7XG4gICAgICAgIGZyYW1lLm11c3RhY2hlQ291bnQrKztcbiAgICAgICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsnYmxvY2snLCBbbm9kZSwgZnJhbWUuY2hpbGRJbmRleCwgZnJhbWUuY2hpbGRDb3VudF1dKTtcbiAgICAgICAgaWYgKG5vZGUuaW52ZXJzZSkge1xuICAgICAgICAgICAgdGhpcy52aXNpdChub2RlLmludmVyc2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlLnByb2dyYW0pIHtcbiAgICAgICAgICAgIHRoaXMudmlzaXQobm9kZS5wcm9ncmFtKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIFBhcnRpYWxTdGF0ZW1lbnQobm9kZSkge1xuICAgICAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICAgICAgZnJhbWUubXVzdGFjaGVDb3VudCsrO1xuICAgICAgICBmcmFtZS5hY3Rpb25zLnB1c2goWydtdXN0YWNoZScsIFtub2RlLCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0pO1xuICAgIH1cblxuICAgIENvbW1lbnRTdGF0ZW1lbnQodGV4dCkge1xuICAgICAgICBsZXQgZnJhbWUgPSB0aGlzLmN1cnJlbnRGcmFtZTtcbiAgICAgICAgZnJhbWUuYWN0aW9ucy5wdXNoKFsnY29tbWVudCcsIFt0ZXh0LCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0pO1xuICAgIH1cblxuICAgIE11c3RhY2hlQ29tbWVudFN0YXRlbWVudCgpIHtcbiAgICAgICAgLy8gSW50ZW50aW9uYWwgZW1wdHk6IEhhbmRsZWJhcnMgY29tbWVudHMgc2hvdWxkIG5vdCBhZmZlY3Qgb3V0cHV0LlxuICAgIH1cblxuICAgIE11c3RhY2hlU3RhdGVtZW50KG11c3RhY2hlKSB7XG4gICAgICAgIGxldCBmcmFtZSA9IHRoaXMuY3VycmVudEZyYW1lO1xuICAgICAgICBmcmFtZS5tdXN0YWNoZUNvdW50Kys7XG4gICAgICAgIGZyYW1lLmFjdGlvbnMucHVzaChbJ211c3RhY2hlJywgW211c3RhY2hlLCBmcmFtZS5jaGlsZEluZGV4LCBmcmFtZS5jaGlsZENvdW50XV0pO1xuICAgIH1cblxuICAgIC8vIEZyYW1lIGhlbHBlcnNcbiAgICBnZXQgY3VycmVudEZyYW1lKCkge1xuICAgICAgICByZXR1cm4gZXhwZWN0KHRoaXMuZ2V0Q3VycmVudEZyYW1lKCksIFwiRXhwZWN0ZWQgYSBjdXJyZW50IGZyYW1lXCIpO1xuICAgIH1cbiAgICBnZXRDdXJyZW50RnJhbWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZyYW1lU3RhY2tbdGhpcy5mcmFtZVN0YWNrLmxlbmd0aCAtIDFdO1xuICAgIH1cbiAgICBwdXNoRnJhbWUoKSB7XG4gICAgICAgIGxldCBmcmFtZSA9IG5ldyBGcmFtZSgpO1xuICAgICAgICB0aGlzLmZyYW1lU3RhY2sucHVzaChmcmFtZSk7XG4gICAgICAgIHJldHVybiBmcmFtZTtcbiAgICB9XG4gICAgcG9wRnJhbWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZyYW1lU3RhY2sucG9wKCk7XG4gICAgfVxufVxuLy8gUmV0dXJucyB0aGUgaW5kZXggb2YgYGRvbU5vZGVgIGluIHRoZSBgbm9kZXNgIGFycmF5LCBza2lwcGluZ1xuLy8gb3ZlciBhbnkgbm9kZXMgd2hpY2ggZG8gbm90IHJlcHJlc2VudCBET00gbm9kZXMuXG5mdW5jdGlvbiBkb21JbmRleE9mKG5vZGVzLCBkb21Ob2RlKSB7XG4gICAgbGV0IGluZGV4ID0gLTE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAobm9kZS50eXBlICE9PSAnVGV4dE5vZGUnICYmIG5vZGUudHlwZSAhPT0gJ0VsZW1lbnROb2RlJykge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub2RlID09PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xufSJdfQ==