@light0x00/parser-generator
Version:
A Parser Generator
540 lines (406 loc) • 41 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ProdsInjector = exports.ParsingTable = exports.Accept = exports.Reduce = exports.Goto = exports.Shift = exports.Operation = exports.AugmentedGrammar = exports.StateSet = exports.State = exports.ItemSet = exports.Item = void 0;
var _Definition = require("../Definition");
var _shim = require("@light0x00/shim");
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/* 项是所属项集中的一个成员,一个「项」由「产生式」和一个「点」组成,例如 A->a·B */
class Item {
/*
由于lookaheadSet可能重复,所以使用Set来存储
为什么lookaheadSet可能重复?
S->A
A->BC
B->b | 𝝴
C->b | 𝝴
S->·A , {$}
A->·BC , {b,b,$} //重复
*/
constructor(production, dot = 0, lookaheadSet = new Set()) {
_defineProperty(this, "prod", void 0);
_defineProperty(this, "_dot", 0);
_defineProperty(this, "lookaheadSet", void 0);
_defineProperty(this, "hashCodeCache", void 0);
this.prod = production;
/* 对于空推导(形如A->𝝴). 直接将 dot 置于末尾(A->𝝴·) */
this._dot = production.isEpsilon() ? production.length : dot;
this.lookaheadSet = lookaheadSet;
}
get dotPos() {
return this._dot;
}
hasNext() {
return this._dot < this.prod.length;
}
nextSymbol() {
if (!this.hasNext()) throw new Error(`${this} has no next item!`);
return this.prod[this._dot];
}
nextItem() {
if (!this.hasNext()) throw new Error(`${this} has no next item!`);
/*
😇New features to support LR
为什么当前项展望集应该被后继项继承?
考虑如下文法:
S->As
A->a
I0
S->·As ,$
A->·a ,s
I1
A->a· ,s
如上所示,I0输入a得到I1
其中「A->a· ,s」继承了「 A->·a ,s」的展望符
*/
return new Item(this.prod, this._dot + 1, this.lookaheadSet);
}
toString() {
let str = "";
let symbols = this.prod;
for (let i = 0; i < symbols.length; i++) {
if (this._dot == i) str += "·";
str += symbols[i];
}
if (this._dot == symbols.length) str += "·";
str += ",";
str += "{" + Array.from(this.lookaheadSet).join(",") + "}";
return `${this.prod.name}->${str}`;
}
equals(other) {
/*
两个项是否相等,
1. 所含产生式一样
2. 「dot」所在位置一样
😇New features to support LR
3. 展望集(lookaheadSet)一样
*/
if (other.prod.id != this.prod.id) return false;
if (other._dot != this._dot) return false;
if (other.lookaheadSet.size != this.lookaheadSet.size) return false; //n2复杂度 暂时不管
for (let t of this.lookaheadSet) {
// let find = false
// for (let o of other.lookaheadSet) {
// if (o == t) {
// find = true
// break
// }
// }
// if (!find)
// return false
if (!other.lookaheadSet.has(t)) {
return false;
}
}
return true;
}
/* 😇New features to support LALR */
isSameCoreWith(other) {
if (other.prod.id != this.prod.id) return false;
if (other._dot != this._dot) return false;
return true;
}
hashCode() {
if (this.hashCodeCache == null) {
// this.hashCodeCache = this.prod.id + '' + this._dot + hash.keys(this.lookaheadSet)
this.hashCodeCache = this.prod.id + "-" + this._dot;
}
return this.hashCodeCache;
} // reducible() {
// return this.dot == this.prod.length
// }
}
exports.Item = Item;
class ItemSet extends Array {
//用于记录已经添加的项的Hash 防止逻辑上的重复
constructor(...items) {
super(...items);
_defineProperty(this, "added", new Map());
_defineProperty(this, "items", new Array());
for (let item of items) this.added.set(item.hashCode(), item);
}
contains(item) {
return this.added.has(item.hashCode());
}
pushOrMerge(item) {
let existing = this.added.get(item.hashCode());
if (existing === undefined) {
this.push(item);
} else {
//已经存在 则合并LR展望符集
(0, _shim.addAll_Set)(existing.lookaheadSet, item.lookaheadSet);
}
} //最好的办法是 将数组作为内部对象 而不是继承
push(item) {
this.added.set(item.hashCode(), item);
return super.push(item);
}
toString() {
let str = "";
for (let item of this) {
str += item.toString() + "\n";
}
return str.replace(/\n$/, "");
}
equals(other) {
/* 两个项集A、B是否相等,取决于
1. 它们所包含的项个数相等
2. A、B中的每一个项在对方集合中都存在相等的项
*/
if (other.length != this.length) return false; //又写出一个n2复杂度23333 !!更好的办法是用Set来存放
for (let o1 of this) {
let hasMatched = false;
for (let o2 of other) {
if (o1.equals(o2)) {
hasMatched = true;
break;
}
}
if (!hasMatched) return false;
}
return true;
}
/*
返回当前状态的后继符号集
例: 对于下状态(项集),其后继符号为: {E,T,F,(,id}
I0
S->·E
E->·E+T
E->·T
T->·T*F
T->·F
F->·(E)
F->·id
*/
getNextSymbols() {
let nextSymbols = new Set();
for (let item of this) {
if (item.hasNext()) {
nextSymbols.add(item.nextSymbol());
}
}
return nextSymbols;
}
}
/* 状态基本等同于项集 唯一的区别是状态需要id 而项集不需要 */
exports.ItemSet = ItemSet;
class State extends ItemSet {
/* 描述当前状态在接受某个符号后去往的后继状态 */
constructor(id, items) {
super(...items);
_defineProperty(this, "id", void 0);
_defineProperty(this, "mapping", new Map());
this.id = id;
}
toString() {
return `<${this.id}>\n${super.toString()}`;
}
/**
* 添加后继状态
* 添加当前状态输入「指定符号」后去往的「后继状态」
*
* 原则上一个状态对于同一符号只能有一个后继状态,如果重复将抛出异常
* @param symbol 输入符号
* @param nextState 后继状态
*/
addNextState(symbol, nextState) {
(0, _shim.assert)(this.mapping.get(symbol) == null, `A state can only have one next state to the same symbol`);
this.mapping.set(symbol, nextState);
}
getNextState(symbol) {
return this.mapping.get(symbol);
}
}
exports.State = State;
class StateSet extends Array {
constructor(...args) {
super(...args);
_defineProperty(this, "mapping", new Map());
}
/* 判断状态集中是否已经存在 相同性质(参见ItemSet的equals方法) 的状态(项集) */
getExisting(state) {
for (let existing of this) {
if (existing.equals(state)) {
return existing;
}
}
return null;
}
satrtState() {
(0, _shim.assert)(this[0] != null);
return this[0];
}
}
/*
LR\SLR 在构造状态时有所不同 因此将不同部分独立处理
*/
exports.StateSet = StateSet;
/**
*
* 将二维数组形式的产生式集(Symbol[][]) 转为带有编号的Production集合,并赋予指定的非终结符
*
* 一个非终结符的产生式集可视为一个Symbol二维数组,
* 为了便于实现LR分析表,需要将这个二维数组转为Production集合,
* 且为每个Production赋予一个编号.
*/
class AugmentedGrammar extends _Definition.ActionGrammar {
constructor(rawGrammar, traits) {
super(rawGrammar, traits);
}
afterConstruct() {
(0, _shim.assert)(this.startNT().length == 1 && this.startNT()[0].length == 1, "The start symbol of an augmented grammar has one and only one production, and the production contains only one symbol!");
}
/* 开始符号的产生式 原则上只能有一个 */
get prodOfStartNT() {
return this.startNT()[0];
}
}
/* 表示LR语法分析表格的操作 */
exports.AugmentedGrammar = AugmentedGrammar;
class Operation {
isReduce() {
return false;
}
isShift() {
return false;
}
isGoto() {
return false;
}
isAccept() {
return false;
}
}
exports.Operation = Operation;
class Shift extends Operation {
constructor(nextState, prec = -1, assoc = false) {
super();
_defineProperty(this, "nextState", void 0);
_defineProperty(this, "prec", void 0);
_defineProperty(this, "assoc", void 0);
this.nextState = nextState;
this.prec = prec;
this.assoc = assoc;
}
setIfLarger(prec, assoc) {
if (prec > this.prec) {
this.prec = prec;
this.assoc = assoc;
}
}
toString() {
return `shift ${this.nextState.id}`;
}
equals(obj) {
return obj instanceof Shift && obj.nextState == this.nextState;
}
isShift() {
return true;
}
}
exports.Shift = Shift;
class Goto extends Operation {
constructor(nextState) {
super();
_defineProperty(this, "nextState", void 0);
this.nextState = nextState;
}
toString() {
return `goto ${this.nextState.id}`;
}
equals(obj) {
return obj instanceof Goto && obj.nextState == this.nextState;
}
isGoto() {
return true;
}
}
exports.Goto = Goto;
class Reduce extends Operation {
/* 用于归约的产生式 */
constructor(prod, prec = -1, leftAssoc = false) {
super();
_defineProperty(this, "prod", void 0);
_defineProperty(this, "prec", void 0);
_defineProperty(this, "leftAssoc", void 0);
this.prod = prod;
this.prec = prec;
this.leftAssoc = leftAssoc;
}
toString() {
return `reduce ${this.prod.id}`;
}
equals(obj) {
return obj instanceof Reduce && obj.prod == this.prod;
}
isReduce() {
return true;
}
}
exports.Reduce = Reduce;
class Accept extends Operation {
constructor() {
super();
}
equals(obj) {
return obj instanceof Accept;
}
toString() {
return `accept`;
}
isAccept() {
return true;
}
}
exports.Accept = Accept;
class ParsingTable {
constructor() {
_defineProperty(this, "parsingTable", new Map());
}
get table() {
return this.parsingTable;
}
put(state, symbol, op) {
let row = this.parsingTable.get(state);
if (row == undefined) {
row = new Map();
this.parsingTable.set(state, row);
}
row.set(symbol, op);
}
has(state, symbol, op) {
let row = this.parsingTable.get(state);
if (row == undefined) return false;
let exstingOp = row.get(symbol);
if (exstingOp == null) return false;
return exstingOp.equals(op);
}
get(state, symbol) {
let row = this.parsingTable.get(state); // assert(row != null, `state(${state.id}) is not found in parsing table!`)
if (row == undefined) return undefined;
return row.get(symbol);
}
getExpectedSymbols(state) {
let row = this.parsingTable.get(state);
if (row == undefined) return [];
return Array.from(row.keys());
}
getExpectedTokens(state) {
let expS = this.getExpectedSymbols(state);
return expS.filter(s => !(s instanceof _Definition.NonTerminal));
}
}
exports.ParsingTable = ParsingTable;
class ProdsInjector {
constructor() {
_defineProperty(this, "prodIdCounter", 0);
}
inject(nt, rawProds) {
for (let rawProd of rawProds) {
nt.addProd(this.prodIdCounter++, rawProd);
}
}
}
exports.ProdsInjector = ProdsInjector;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MUi9EZWZpbml0aW9uLnRzIl0sIm5hbWVzIjpbIkl0ZW0iLCJjb25zdHJ1Y3RvciIsInByb2R1Y3Rpb24iLCJkb3QiLCJsb29rYWhlYWRTZXQiLCJTZXQiLCJwcm9kIiwiX2RvdCIsImlzRXBzaWxvbiIsImxlbmd0aCIsImRvdFBvcyIsImhhc05leHQiLCJuZXh0U3ltYm9sIiwiRXJyb3IiLCJuZXh0SXRlbSIsInRvU3RyaW5nIiwic3RyIiwic3ltYm9scyIsImkiLCJBcnJheSIsImZyb20iLCJqb2luIiwibmFtZSIsImVxdWFscyIsIm90aGVyIiwiaWQiLCJzaXplIiwidCIsImhhcyIsImlzU2FtZUNvcmVXaXRoIiwiaGFzaENvZGUiLCJoYXNoQ29kZUNhY2hlIiwiSXRlbVNldCIsIml0ZW1zIiwiTWFwIiwiaXRlbSIsImFkZGVkIiwic2V0IiwiY29udGFpbnMiLCJwdXNoT3JNZXJnZSIsImV4aXN0aW5nIiwiZ2V0IiwidW5kZWZpbmVkIiwicHVzaCIsInJlcGxhY2UiLCJvMSIsImhhc01hdGNoZWQiLCJvMiIsImdldE5leHRTeW1ib2xzIiwibmV4dFN5bWJvbHMiLCJhZGQiLCJTdGF0ZSIsImFkZE5leHRTdGF0ZSIsInN5bWJvbCIsIm5leHRTdGF0ZSIsIm1hcHBpbmciLCJnZXROZXh0U3RhdGUiLCJTdGF0ZVNldCIsImdldEV4aXN0aW5nIiwic3RhdGUiLCJzYXRydFN0YXRlIiwiQXVnbWVudGVkR3JhbW1hciIsIkFjdGlvbkdyYW1tYXIiLCJyYXdHcmFtbWFyIiwidHJhaXRzIiwiYWZ0ZXJDb25zdHJ1Y3QiLCJzdGFydE5UIiwicHJvZE9mU3RhcnROVCIsIk9wZXJhdGlvbiIsImlzUmVkdWNlIiwiaXNTaGlmdCIsImlzR290byIsImlzQWNjZXB0IiwiU2hpZnQiLCJwcmVjIiwiYXNzb2MiLCJzZXRJZkxhcmdlciIsIm9iaiIsIkdvdG8iLCJSZWR1Y2UiLCJsZWZ0QXNzb2MiLCJBY2NlcHQiLCJQYXJzaW5nVGFibGUiLCJ0YWJsZSIsInBhcnNpbmdUYWJsZSIsInB1dCIsIm9wIiwicm93IiwiZXhzdGluZ09wIiwiZ2V0RXhwZWN0ZWRTeW1ib2xzIiwia2V5cyIsImdldEV4cGVjdGVkVG9rZW5zIiwiZXhwUyIsImZpbHRlciIsInMiLCJOb25UZXJtaW5hbCIsIlByb2RzSW5qZWN0b3IiLCJpbmplY3QiLCJudCIsInJhd1Byb2RzIiwicmF3UHJvZCIsImFkZFByb2QiLCJwcm9kSWRDb3VudGVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7Ozs7QUFHQTtBQUNPLE1BQU1BLElBQU4sQ0FBVztBQUlqQjs7Ozs7Ozs7OztBQWFBQyxFQUFBQSxXQUFXLENBQUNDLFVBQUQsRUFBeUJDLEdBQVcsR0FBRyxDQUF2QyxFQUEwQ0MsWUFBMkIsR0FBRyxJQUFJQyxHQUFKLEVBQXhFLEVBQTZGO0FBQUE7O0FBQUEsa0NBZGpGLENBY2lGOztBQUFBOztBQUFBOztBQUN2RyxTQUFLQyxJQUFMLEdBQVlKLFVBQVo7QUFDQTs7QUFDQSxTQUFLSyxJQUFMLEdBQVlMLFVBQVUsQ0FBQ00sU0FBWCxLQUF5Qk4sVUFBVSxDQUFDTyxNQUFwQyxHQUE2Q04sR0FBekQ7QUFDQSxTQUFLQyxZQUFMLEdBQW9CQSxZQUFwQjtBQUNBOztBQUVELE1BQUlNLE1BQUosR0FBYTtBQUNaLFdBQU8sS0FBS0gsSUFBWjtBQUNBOztBQUVESSxFQUFBQSxPQUFPLEdBQVk7QUFDbEIsV0FBTyxLQUFLSixJQUFMLEdBQVksS0FBS0QsSUFBTCxDQUFVRyxNQUE3QjtBQUNBOztBQUVERyxFQUFBQSxVQUFVLEdBQVc7QUFDcEIsUUFBSSxDQUFDLEtBQUtELE9BQUwsRUFBTCxFQUNDLE1BQU0sSUFBSUUsS0FBSixDQUFXLEdBQUUsSUFBSyxvQkFBbEIsQ0FBTjtBQUNELFdBQU8sS0FBS1AsSUFBTCxDQUFVLEtBQUtDLElBQWYsQ0FBUDtBQUNBOztBQUNETyxFQUFBQSxRQUFRLEdBQUc7QUFDVixRQUFJLENBQUMsS0FBS0gsT0FBTCxFQUFMLEVBQ0MsTUFBTSxJQUFJRSxLQUFK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RDs7QUFOeUIiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7IFByb2R1Y3Rpb24sIFRlcm1pbmFsLCBTeW1ib2wsIE5vblRlcm1pbmFsLCBBY3Rpb25HcmFtbWFyLCBSYXdBY3Rpb25HcmFtbWFyLCBUcmFpdHNUYWJsZSB9IGZyb20gXCIuLi9EZWZpbml0aW9uXCI7XG5pbXBvcnQgeyBhZGRBbGxfU2V0LCBhc3NlcnQgfSBmcm9tIFwiQGxpZ2h0MHgwMC9zaGltXCI7XG5pbXBvcnQgeyBJTGV4ZXIsIEFTVHJlZSB9IGZyb20gXCJAbGlnaHQweDAwL3BhcnNlci1kZWZpbml0aW9uXCI7XG5cbi8qIOmhueaYr+aJgOWxnumhuembhuS4reeahOS4gOS4quaIkOWRmCzkuIDkuKrjgIzpobnjgI3nlLHjgIzkuqfnlJ/lvI/jgI3lkozkuIDkuKrjgIzngrnjgI3nu4TmiJAs5L6L5aaCIEEtPmHCt0IgKi9cbmV4cG9ydCBjbGFzcyBJdGVtIHtcblxuXHRwcm9kOiBQcm9kdWN0aW9uO1xuXHRwcml2YXRlIF9kb3Q6IG51bWJlciA9IDA7XG5cdC8qXG4gICAg55Sx5LqObG9va2FoZWFkU2V05Y+v6IO96YeN5aSNLOaJgOS7peS9v+eUqFNldOadpeWtmOWCqFxuICAgIOS4uuS7gOS5iGxvb2thaGVhZFNldOWPr+iDvemHjeWkjT9cblxuICAgIFMtPkFcbiAgICBBLT5CQ1xuICAgIEItPmIgfCDwnZ20XG4gICAgQy0+YiB8IPCdnbRcblxuICAgIFMtPsK3QSAsIHskfVxuICAgIEEtPsK3QkMgLCB7YixiLCR9ICAvL+mHjeWkjVxuICAgICovXG5cdGxvb2thaGVhZFNldDogU2V0PFRlcm1pbmFsPlxuXHRjb25zdHJ1Y3Rvcihwcm9kdWN0aW9uOiBQcm9kdWN0aW9uLCBkb3Q6IG51bWJlciA9IDAsIGxvb2thaGVhZFNldDogU2V0PFRlcm1pbmFsPiA9IG5ldyBTZXQ8VGVybWluYWw+KCkpIHtcblx0XHR0aGlzLnByb2QgPSBwcm9kdWN0aW9uO1xuXHRcdC8qIOWvueS6juepuuaOqOWvvCjlvaLlpoJBLT7wnZ20KS4g55u05o6l5bCGIGRvdCDnva7kuo7mnKvlsL4oQS0+8J2dtMK3KSAqL1xuXHRcdHRoaXMuX2RvdCA9IHByb2R1Y3Rpb24uaXNFcHNpbG9uKCkgPyBwcm9kdWN0aW9uLmxlbmd0aCA6IGRvdDtcblx0XHR0aGlzLmxvb2thaGVhZFNldCA9IGxvb2thaGVhZFNldDtcblx0fVxuXG5cdGdldCBkb3RQb3MoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2RvdDtcblx0fVxuXG5cdGhhc05leHQoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2RvdCA8IHRoaXMucHJvZC5sZW5ndGg7XG5cdH1cblxuXHRuZXh0U3ltYm9sKCk6IFN5bWJvbCB7XG5cdFx0aWYgKCF0aGlzLmhhc05leHQoKSlcblx0XHRcdHRocm93IG5ldyBFcnJvcihgJHt0aGlzfSBoYXMgbm8gbmV4dCBpdGVtIWApO1xuXHRcdHJldHVybiB0aGlzLnByb2RbdGhpcy5fZG90XTtcblx0fVxuXHRuZXh0SXRlbSgpIHtcblx0XHRpZiAoIXRoaXMuaGFzTmV4dCgpKVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGAke3RoaXN9IGhhcyBubyBuZXh0IGl0ZW0hYCk7XG5cdFx0Lypcblx0XHRcdPCfmIdOZXcgZmVhdHVyZXMgdG8gc3VwcG9ydCBMUlxuXG5cdFx0XHTkuLrku4DkuYjlvZPliY3pobnlsZXmnJvpm4blupTor6XooqvlkI7nu6fpobnnu6fmib8/XG5cblx0XHRcdOiAg+iZkeWmguS4i+aWh+azlTpcblx0XHRcdFMtPkFzXG5cdFx0XHRBLT5hXG5cblx0XHRcdEkwXG5cdFx0XHRTLT7Ct0FzICwkXG5cdFx0XHRBLT7Ct2EgLHNcblxuXHRcdFx0STFcblx0XHRcdEEtPmHCtyAsc1xuXG5cdFx0XHTlpoLkuIrmiYDnpLosSTDovpPlhaVh5b6X5YiwSTFcblx0XHRcdOWFtuS4reOAjEEtPmHCtyAsc+OAjee7p+aJv+S6huOAjCBBLT7Ct2EgLHPjgI3nmoTlsZXmnJvnrKZcblx0XHRcdCovXG5cdFx0cmV0dXJuIG5ldyBJdGVtKHRoaXMucHJvZCwgdGhpcy5fZG90ICsgMSwgdGhpcy5sb29rYWhlYWRTZXQpO1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdGxldCBzdHIgPSBcIlwiO1xuXHRcdGxldCBzeW1ib2xzID0gdGhpcy5wcm9kO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgc3ltYm9scy5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKHRoaXMuX2RvdCA9PSBpKVxuXHRcdFx0XHRzdHIgKz0gXCLCt1wiO1xuXHRcdFx0c3RyICs9IHN5bWJvbHNbaV07XG5cdFx0fVxuXHRcdGlmICh0aGlzLl9kb3QgPT0gc3ltYm9scy5sZW5ndGgpXG5cdFx0XHRzdHIgKz0gXCLCt1wiO1xuXHRcdHN0ciArPSBcIixcIjtcblx0XHRzdHIgKz0gXCJ7XCIgKyBBcnJheS5mcm9tKHRoaXMubG9va2FoZWFkU2V0KS5qb2luKFwiLFwiKSArIFwifVwiO1xuXHRcdHJldHVybiBgJHt0aGlzLnByb2QubmFtZX0tPiR7c3RyfWA7XG5cdH1cblx0ZXF1YWxzKG90aGVyOiBJdGVtKSB7XG5cdFx0Lypcblx0XHRcdOS4pOS4qumhueaYr+WQpuebuOetiSxcblx0XHRcdDEuIOaJgOWQq+S6p+eUn+W8j+S4gOagt1xuXHRcdFx0Mi4g44CMZG9044CN5omA5Zyo5L2N572u5LiA5qC3XG5cblx0XHRcdPCfmIdOZXcgZmVhdHVyZXMgdG8gc3VwcG9ydCBMUlxuXHRcdFx0My4g5bGV5pyb6ZuGKGxvb2thaGVhZFNldCnkuIDmoLdcblx0XHRcdCovXG5cdFx0aWYgKG90aGVyLnByb2QuaWQgIT0gdGhpcy5wcm9kLmlkKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdGlmIChvdGhlci5fZG90ICE9IHRoaXMuX2RvdClcblx0XHRcdHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChvdGhlci5sb29rYWhlYWRTZXQuc2l6ZSAhPSB0aGlzLmxvb2thaGVhZFNldC5zaXplKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdC8vbjLlpI3mnYLluqYg5pqC5pe25LiN566hXG5cdFx0Zm9yIChsZXQgdCBvZiB0aGlzLmxvb2thaGVhZFNldCkge1xuXHRcdFx0Ly8gbGV0IGZpbmQgPSBmYWxzZVxuXHRcdFx0Ly8gZm9yIChsZXQgbyBvZiBvdGhlci5sb29rYWhlYWRTZXQpIHtcblx0XHRcdC8vICAgICBpZiAobyA9PSB0KSB7XG5cdFx0XHQvLyAgICAgICAgIGZpbmQgPSB0cnVlXG5cdFx0XHQvLyAgICAgICAgIGJyZWFrXG5cdFx0XHQvLyAgICAgfVxuXHRcdFx0Ly8gfVxuXHRcdFx0Ly8gaWYgKCFmaW5kKVxuXHRcdFx0Ly8gICAgIHJldHVybiBmYWxzZVxuXHRcdFx0aWYgKCFvdGhlci5sb29rYWhlYWRTZXQuaGFzKHQpKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblx0LyogIPCfmIdOZXcgZmVhdHVyZXMgdG8gc3VwcG9ydCBMQUxSICovXG5cdGlzU2FtZUNvcmVXaXRoKG90aGVyOiBJdGVtKSB7XG5cdFx0aWYgKG90aGVyLnByb2QuaWQgIT0gdGhpcy5wcm9kLmlkKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdGlmIChvdGhlci5fZG90ICE9IHRoaXMuX2RvdClcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHByaXZhdGUgaGFzaENvZGVDYWNoZTogc3RyaW5nXG5cdGhhc2hDb2RlKCk6IHN0cmluZyB7XG5cdFx0aWYgKHRoaXMuaGFzaENvZGVDYWNoZSA9PSBudWxsKSB7XG5cdFx0XHQvLyB0aGlzLmhhc2hDb2RlQ2FjaGUgPSB0aGlzLnByb2QuaWQgKyAnJyArIHRoaXMuX2RvdCArIGhhc2gua2V5cyh0aGlzLmxvb2thaGVhZFNldClcblx0XHRcdHRoaXMuaGFzaENvZGVDYWNoZSA9IHRoaXMucHJvZC5pZCArIFwiLVwiICsgdGhpcy5fZG90O1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5oYXNoQ29kZUNhY2hlO1xuXHR9XG5cblx0Ly8gcmVkdWNpYmxlKCkge1xuXHQvLyAgICAgcmV0dXJuIHRoaXMuZG90ID09IHRoaXMucHJvZC5sZW5ndGhcblx0Ly8gfVxufVxuXG5leHBvcnQgY2xhc3MgSXRlbVNldCBleHRlbmRzIEFycmF5PEl0ZW0+IHtcblx0Ly/nlKjkuo7orrDlvZXlt7Lnu4/mt7vliqDnmoTpobnnmoRIYXNoIOmYsuatoumAu+i+keS4iueahOmHjeWkjVxuXHRhZGRlZCA9IG5ldyBNYXA8c3RyaW5nLCBJdGVtPigpXG5cdGl0ZW1zID0gbmV3IEFycmF5PEl0ZW0+KClcblx0Y29uc3RydWN0b3IoLi4uaXRlbXM6IEl0ZW1bXSkge1xuXHRcdHN1cGVyKC4uLml0ZW1zKTtcblx0XHRmb3IgKGxldCBpdGVtIG9mIGl0ZW1zKVxuXHRcdFx0dGhpcy5hZGRlZC5zZXQoaXRlbS5oYXNoQ29kZSgpLCBpdGVtKTtcblx0fVxuXG5cdGNvbnRhaW5zKGl0ZW06IEl0ZW0pIHtcblx0XHRyZXR1cm4gdGhpcy5hZGRlZC5oYXMoaXRlbS5oYXNoQ29kZSgpKTtcblx0fVxuXG5cdHB1c2hPck1lcmdlKGl0ZW06IEl0ZW0pIHtcblx0XHRsZXQgZXhpc3RpbmcgPSB0aGlzLmFkZGVkLmdldChpdGVtLmhhc2hDb2RlKCkpO1xuXHRcdGlmIChleGlzdGluZyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0aGlzLnB1c2goaXRlbSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8v5bey57uP5a2Y5ZyoIOWImeWQiOW5tkxS5bGV5pyb56ym6ZuGXG5cdFx0XHRhZGRBbGxfU2V0KGV4aXN0aW5nLmxvb2thaGVhZFNldCwgaXRlbS5sb29rYWhlYWRTZXQpO1xuXHRcdH1cblx0fVxuXHQvL+acgOWlveeahOWKnuazleaYryDlsIbmlbDnu4TkvZzkuLrlhoXpg6jlr7nosaEg6ICM5LiN5piv57un5om/XG5cdHB1c2goaXRlbTogSXRlbSkge1xuXHRcdHRoaXMuYWRkZWQuc2V0KGl0ZW0uaGFzaENvZGUoKSwgaXRlbSk7XG5cdFx0cmV0dXJuIHN1cGVyLnB1c2goaXRlbSk7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRsZXQgc3RyID0gXCJcIjtcblx0XHRmb3IgKGxldCBpdGVtIG9mIHRoaXMpIHtcblx0XHRcdHN0ciArPSBpdGVtLnRvU3RyaW5nKCkgKyBcIlxcblwiO1xuXHRcdH1cblx0XHRyZXR1cm4gc3RyLnJlcGxhY2UoL1xcbiQvLCBcIlwiKTtcblx0fVxuXHRlcXVhbHMob3RoZXI6IEl0ZW1TZXQpIHtcblx0XHQvKiDkuKTkuKrpobnpm4ZB44CBQuaYr+WQpuebuOetiSzlj5blhrPkuo5cblx0XHRcdCAgMS4g5a6D5Lus5omA5YyF5ZCr55qE6aG55Liq5pWw55u4562JXG5cdFx0XHQgIDIuIEHjgIFC5Lit55qE5q+P5LiA5Liq6aG55Zyo5a+55pa56ZuG5ZCI5Lit6YO95a2Y5Zyo55u4562J55qE6aG5XG5cdFx0ICAgKi9cblx0XHRpZiAob3RoZXIubGVuZ3RoICE9IHRoaXMubGVuZ3RoKVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdC8v5Y+I5YaZ5Ye65LiA5LiqbjLlpI3mnYLluqYyMzMzMyAgISHmm7Tlpb3nmoTlip7ms5XmmK/nlKhTZXTmnaXlrZjmlL5cblx0XHRmb3IgKGxldCBvMSBvZiB0aGlzKSB7XG5cdFx0XHRsZXQgaGFzTWF0Y2hlZCA9IGZhbHNlO1xuXHRcdFx0Zm9yIChsZXQgbzIgb2Ygb3RoZXIpIHtcblx0XHRcdFx0aWYgKG8xLmVxdWFscyhvMikpIHtcblx0XHRcdFx0XHRoYXNNYXRjaGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKCFoYXNNYXRjaGVkKVxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LypcbiAgICDov5Tlm57lvZPliY3nirbmgIHnmoTlkI7nu6fnrKblj7fpm4ZcbiAgICDkvos6IOWvueS6juS4i+eKtuaAgSjpobnpm4YpLOWFtuWQjue7p+espuWPt+S4ujoge0UsVCxGLCgsaWR9XG4gICAgSTBcbiAgICAgICAgUy0+wrdFXG4gICAgICAgIEUtPsK3RStUXG4gICAgICAgIEUtPsK3VFxuICAgICAgICBULT7Ct1QqRlxuICAgICAgICBULT7Ct0ZcbiAgICAgICAgRi0+wrcoRSlcbiAgICAgICAgRi0+wrdpZFxuICAgICAqL1xuXHRnZXROZXh0U3ltYm9scygpIHtcblx0XHRsZXQgbmV4dFN5bWJvbHMgPSBuZXcgU2V0PFN5bWJvbD4oKTtcblx0XHRmb3IgKGxldCBpdGVtIG9mIHRoaXMpIHtcblx0XHRcdGlmIChpdGVtLmhhc05leHQoKSkge1xuXHRcdFx0XHRuZXh0U3ltYm9scy5hZGQoaXRlbS5uZXh0U3ltYm9sKCkpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gbmV4dFN5bWJvbHM7XG5cdH1cblxufVxuLyog54q25oCB5Z+65pys562J5ZCM5LqO6aG56ZuGIOWUr+S4gOeahOWMuuWIq+aYr+eKtuaAgemcgOimgWlkIOiAjOmhuembhuS4jemcgOimgSAqL1xuZXhwb3J0IGNsYXNzIFN0YXRlIGV4dGVuZHMgSXRlbVNldCB7XG5cdGlkOiBudW1iZXJcblx0Lyog5o+P6L+w5b2T5YmN54q25oCB5Zyo5o6l5Y+X5p+Q5Liq56ym5Y+35ZCO5Y675b6A55qE5ZCO57un54q25oCBICovXG5cdG1hcHBpbmcgPSBuZXcgTWFwPFN5bWJvbCwgU3RhdGU+KClcblx0Y29uc3RydWN0b3IoaWQ6IG51bWJlciwgaXRlbXM6IEl0ZW1bXSkge1xuXHRcdHN1cGVyKC4uLml0ZW1zKTtcblx0XHR0aGlzLmlkID0gaWQ7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYDwke3RoaXMuaWR9PlxcbiR7c3VwZXIudG9TdHJpbmcoKX1gO1xuXHR9XG5cblx0LyoqXG4gICAgICog5re75Yqg5ZCO57un54q25oCBXG4gICAgICog5re75Yqg5b2T5YmN54q25oCB6L6T5YWl44CM5oyH5a6a56ym5Y+344CN5ZCO5Y675b6A55qE44CM5ZCO57un54q25oCB44CNXG4gICAgICpcbiAgICAgKiDljp/liJnkuIrkuIDkuKrnirbmgIHlr7nkuo7lkIzkuIDnrKblj7flj6rog73mnInkuIDkuKrlkI7nu6fnirbmgIEs5aaC5p6c6YeN5aSN5bCG5oqb5Ye65byC5bi4XG4gICAgICogQHBhcmFtIHN5bWJvbCDovpPlhaXnrKblj7dcbiAgICAgKiBAcGFyYW0gbmV4dFN0YXRlIOWQjue7p+eKtuaAgVxuICAgICAqL1xuXHRhZGROZXh0U3RhdGUoc3ltYm9sOiBTeW1ib2wsIG5leHRTdGF0ZTogU3RhdGUpIHtcblx0XHRhc3NlcnQodGhpcy5tYXBwaW5nLmdldChzeW1ib2wpID09IG51bGwsIGBBIHN0YXRlIGNhbiBvbmx5IGhhdmUgb25lIG5leHQgc3RhdGUgdG8gdGhlIHNhbWUgc3ltYm9sYCk7XG5cdFx0dGhpcy5tYXBwaW5nLnNldChzeW1ib2wsIG5leHRTdGF0ZSk7XG5cdH1cblxuXHRnZXROZXh0U3RhdGUoc3ltYm9sOiBTeW1ib2wpIHtcblx0XHRyZXR1cm4gdGhpcy5tYXBwaW5nLmdldChzeW1ib2wpO1xuXHR9XG5cbn1cblxuZXhwb3J0IGNsYXNzIFN0YXRlU2V0IGV4dGVuZHMgQXJyYXk8U3RhdGU+e1xuXHRtYXBwaW5nID0gbmV3IE1hcDxTdGF0ZSwgTWFwPFN5bWJvbCwgU3RhdGU+PigpXG5cdC8qIOWIpOaWreeKtuaAgembhuS4reaYr+WQpuW3sue7j+WtmOWcqCDnm7jlkIzmgKfotKgo5Y+C6KeBSXRlbVNldOeahGVxdWFsc+aWueazlSkg55qE54q25oCBKOmhuembhikgKi9cblx0Z2V0RXhpc3Rpbmcoc3RhdGU6IEl0ZW1TZXQpOiBudWxsIHwgU3RhdGUge1xuXHRcdGZvciAobGV0IGV4aXN0aW5nIG9mIHRoaXMpIHtcblx0XHRcdGlmIChleGlzdGluZy5lcXVhbHMoc3RhdGUpKSB7XG5cdFx0XHRcdHJldHVybiBleGlzdGluZztcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0c2F0cnRTdGF0ZSgpOiBTdGF0ZSB7XG5cdFx0YXNzZXJ0KHRoaXNbMF0gIT0gbnVsbCk7XG5cdFx0cmV0dXJuIHRoaXNbMF07XG5cdH1cbn1cbi8qXG5MUlxcU0xSIOWcqOaehOmAoOeKtuaAgeaXtuacieaJgOS4jeWQjCDlm6DmraTlsIbkuI3lkIzpg6jliIbni6znq4vlpITnkIZcbiovXG5leHBvcnQgaW50ZXJmYWNlIEF1dG9tYXRhVG9vbHMge1xuXHRHT1RPKEk6IEl0ZW1TZXQsIGlucHV0U3ltYm9sOiBTeW1ib2wpOiBJdGVtU2V0XG5cdGNsb3N1cmUoaXRlbVNldDogSXRlbVNldCk6IEl0ZW1TZXRcblx0Z2V0U3RhcnRTdGF0ZShncmFtbWFyOiBBY3Rpb25HcmFtbWFyKTogU3RhdGVcbn1cblxuLyoqXG4gKlxuICog5bCG5LqM57u05pWw57uE5b2i5byP55qE5Lqn55Sf5byP6ZuGKFN5bWJvbFtdW10pIOi9rOS4uuW4puaciee8luWPt+eahFByb2R1Y3Rpb27pm4blkIgs5bm26LWL5LqI5oyH5a6a55qE6Z2e57uI57uT56ymXG4gKlxuICog5LiA5Liq6Z2e57uI57uT56ym55qE5Lqn55Sf5byP6ZuG5Y+v6KeG5Li65LiA5LiqU3ltYm9s5LqM57u05pWw57uELFxuICog5Li65LqG5L6/5LqO5a6e546wTFLliIbmnpDooags6ZyA6KaB5bCG6L+Z5Liq5LqM57u05pWw57uE6L2s5Li6UHJvZHVjdGlvbumbhuWQiCxcbiAqIOS4lOS4uuavj+S4qlByb2R1Y3Rpb27otYvkuojkuIDkuKrnvJblj7cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdWdtZW50ZWRHcmFtbWFyIGV4dGVuZHMgQWN0aW9uR3JhbW1hciB7XG5cblx0Y29uc3RydWN0b3IocmF3R3JhbW1hcjogUmF3QWN0aW9uR3JhbW1hciwgdHJhaXRzOiBUcmFpdHNUYWJsZSkge1xuXHRcdHN1cGVyKHJhd0dyYW1tYXIsIHRyYWl0cyk7XG5cdH1cblxuXHRhZnRlckNvbnN0cnVjdCgpIHtcblx0XHRhc3NlcnQodGhpcy5zdGFydE5UKCkubGVuZ3RoID09IDEgJiYgdGhpcy5zdGFydE5UKClbMF0ubGVuZ3RoID09IDEsXG5cdFx0XHRcIlRoZSBzdGFydCBzeW1ib2wgb2YgYW4gYXVnbWVudGVkIGdyYW1tYXIgaGFzIG9uZSBhbmQgb25seSBvbmUgcHJvZHVjdGlvbiwgYW5kIHRoZSBwcm9kdWN0aW9uIGNvbnRhaW5zIG9ubHkgb25lIHN5bWJvbCFcIik7XG5cdH1cblx0Lyog5byA5aeL56ym5Y+355qE5Lqn55Sf5byPIOWOn+WImeS4iuWPquiDveacieS4gOS4qiAqL1xuXHRnZXQgcHJvZE9mU3RhcnROVCgpOiBQcm9kdWN0aW9uIHtcblx0XHRyZXR1cm4gdGhpcy5zdGFydE5UKClbMF07XG5cdH1cbn1cblxuLyog6KGo56S6TFLor63ms5XliIbmnpDooajmoLznmoTmk43kvZwgKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBPcGVyYXRpb24ge1xuXHRhYnN0cmFjdCBlcXVhbHMob2JqOiBPYmplY3QpOiBib29sZWFuXG5cblx0aXNSZWR1Y2UoKTogdGhpcyBpcyBSZWR1Y2Uge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRpc1NoaWZ0KCk6IHRoaXMgaXMgU2hpZnQge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGlzR290bygpOiB0aGlzIGlzIEdvdG8ge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdGlzQWNjZXB0KCk6IHRoaXMgaXMgQWNjZXB0IHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFNoaWZ0IGV4dGVuZHMgT3BlcmF0aW9uIHtcblx0bmV4dFN0YXRlOiBTdGF0ZVxuXHRwcmVjOiBudW1iZXI7XG5cdGFzc29jOiBib29sZWFuO1xuXHRjb25zdHJ1Y3RvcihuZXh0U3RhdGU6IFN0YXRlLCBwcmVjOiBudW1iZXIgPSAtMSwgYXNzb2M6IGJvb2xlYW4gPSBmYWxzZSkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5uZXh0U3RhdGUgPSBuZXh0U3RhdGU7XG5cdFx0dGhpcy5wcmVjID0gcHJlYztcblx0XHR0aGlzLmFzc29jID0gYXNzb2M7XG5cdH1cblxuXHRzZXRJZkxhcmdlcihwcmVjOiBudW1iZXIsIGFzc29jOiBib29sZWFuKSB7XG5cdFx0aWYgKHByZWMgPiB0aGlzLnByZWMpIHtcblx0XHRcdHRoaXMucHJlYyA9IHByZWM7XG5cdFx0XHR0aGlzLmFzc29jID0gYXNzb2M7XG5cdFx0fVxuXHR9XG5cblx0dG9TdHJpbmcoKSB7XG5cdFx0cmV0dXJuIGBzaGlmdCAke3RoaXMubmV4dFN0YXRlLmlkfWA7XG5cdH1cblx0ZXF1YWxzKG9iajogT2JqZWN0KSB7XG5cdFx0cmV0dXJuIG9iaiBpbnN0YW5jZW9mIFNoaWZ0ICYmIG9iai5uZXh0U3RhdGUgPT0gdGhpcy5uZXh0U3RhdGU7XG5cdH1cblx0aXNTaGlmdCgpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgR290byBleHRlbmRzIE9wZXJhdGlvbiB7XG5cdG5leHRTdGF0ZTogU3RhdGVcblxuXHRjb25zdHJ1Y3RvcihuZXh0U3RhdGU6IFN0YXRlKSB7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLm5leHRTdGF0ZSA9IG5leHRTdGF0ZTtcblx0fVxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYGdvdG8gJHt0aGlzLm5leHRTdGF0ZS5pZH1gO1xuXHR9XG5cdGVxdWFscyhvYmo6IE9iamVjdCkge1xuXHRcdHJldHVybiBvYmogaW5zdGFuY2VvZiBHb3RvICYmIG9iai5uZXh0U3RhdGUgPT0gdGhpcy5uZXh0U3RhdGU7XG5cdH1cblxuXHRpc0dvdG8oKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cbn1cblxuZXhwb3J0IGNsYXNzIFJlZHVjZSBleHRlbmRzIE9wZXJhdGlvbiB7XG5cdC8qIOeUqOS6juW9kue6pueahOS6p+eUn+W8jyAqL1xuXHRwcm9kOiBQcm9kdWN0aW9uO1xuXHRwcmVjOiBudW1iZXI7XG5cdGxlZnRBc3NvYzogYm9vbGVhbjtcblx0Y29uc3RydWN0b3IocHJvZDogUHJvZHVjdGlvbiwgcHJlYzogbnVtYmVyID0gLTEsIGxlZnRBc3NvYzogYm9vbGVhbiA9IGZhbHNlKSB7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLnByb2QgPSBwcm9kO1xuXHRcdHRoaXMucHJlYyA9IHByZWM7XG5cdFx0dGhpcy5sZWZ0QXNzb2MgPSBsZWZ0QXNzb2M7XG5cdH1cblxuXHR0b1N0cmluZygpIHtcblx0XHRyZXR1cm4gYHJlZHVjZSAke3RoaXMucHJvZC5pZH1gO1xuXHR9XG5cblx0ZXF1YWxzKG9iajogT2JqZWN0KSB7XG5cdFx0cmV0dXJuIG9iaiBpbnN0YW5jZW9mIFJlZHVjZSAmJiBvYmoucHJvZCA9PSB0aGlzLnByb2Q7XG5cdH1cblxuXHRpc1JlZHVjZSgpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQWNjZXB0IGV4dGVuZHMgT3BlcmF0aW9uIHtcblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcblx0fVxuXHRlcXVhbHMob2JqOiBPYmplY3QpIHtcblx0XHRyZXR1cm4gb2JqIGluc3RhbmNlb2YgQWNjZXB0O1xuXHR9XG5cdHRvU3RyaW5nKCkge1xuXHRcdHJldHVybiBgYWNjZXB0YDtcblx0fVxuXHRpc0FjY2VwdCgpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgUGFyc2luZ1RhYmxlIHtcblx0cHJpdmF0ZSBwYXJzaW5nVGFibGUgPSBuZXcgTWFwPFN0YXRlLCBNYXA8U3ltYm9sLCBPcGVyYXRpb24+PigpXG5cblx0Z2V0IHRhYmxlKCkge1xuXHRcdHJldHVybiB0aGlzLnBhcnNpbmdUYWJsZTtcblx0fVxuXG5cdHB1dChzdGF0ZTogU3RhdGUsIHN5bWJvbDogU3ltYm9sLCBvcDogT3BlcmF0aW9uKTogdm9pZCB7XG5cdFx0bGV0IHJvdyA9IHRoaXMucGFyc2luZ1RhYmxlLmdldChzdGF0ZSk7XG5cdFx0aWYgKHJvdyA9PSB1bmRlZmluZWQpIHtcblx0XHRcdHJvdyA9IG5ldyBNYXA8U3ltYm9sLCBPcGVyYXRpb24+KCk7XG5cdFx0XHR0aGlzLnBhcnNpbmdUYWJsZS5zZXQoc3RhdGUsIHJvdyk7XG5cdFx0fVxuXHRcdHJvdy5zZXQoc3ltYm9sLCBvcCk7XG5cdH1cblx0aGFzKHN0YXRlOiBTdGF0ZSwgc3ltYm9sOiBTeW1ib2wsIG9wOiBPcGVyYXRpb24pOiBib29sZWFuIHtcblx0XHRsZXQgcm93ID0gdGhpcy5wYXJzaW5nVGFibGUuZ2V0KHN0YXRlKTtcblx0XHRpZiAocm93ID09IHVuZGVmaW5lZClcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRsZXQgZXhzdGluZ09wID0gcm93LmdldChzeW1ib2wpO1xuXHRcdGlmIChleHN0aW5nT3AgPT0gbnVsbClcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRyZXR1cm4gZXhzdGluZ09wLmVxdWFscyhvcCk7XG5cdH1cblx0Z2V0KHN0YXRlOiBTdGF0ZSwgc3ltYm9sOiBTeW1ib2wpOiBPcGVyYXRpb24gfCB1bmRlZmluZWQge1xuXHRcdGxldCByb3cgPSB0aGlzLnBhcnNpbmdUYWJsZS5nZXQoc3RhdGUpO1xuXHRcdC8vIGFzc2VydChyb3cgIT0gbnVsbCwgYHN0YXRlKCR7c3RhdGUuaWR9KSBpcyBub3QgZm91bmQgaW4gcGFyc2luZyB0YWJsZSFgKVxuXHRcdGlmIChyb3cgPT0gdW5kZWZpbmVkKVxuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRyZXR1cm4gcm93LmdldChzeW1ib2wpO1xuXHR9XG5cblx0Z2V0RXhwZWN0ZWRTeW1ib2xzKHN0YXRlOiBTdGF0ZSk6IFN5bWJvbFtdIHtcblx0XHRsZXQgcm93ID0gdGhpcy5wYXJzaW5nVGFibGUuZ2V0KHN0YXRlKTtcblx0XHRpZiAocm93ID09IHVuZGVmaW5lZClcblx0XHRcdHJldHVybiBbXTtcblx0XHRyZXR1cm4gQXJyYXkuZnJvbShyb3cua2V5cygpKTtcblx0fVxuXG5cdGdldEV4cGVjdGVkVG9rZW5zKHN0YXRlOiBTdGF0ZSkge1xuXHRcdGxldCBleHBTID0gdGhpcy5nZXRFeHBlY3RlZFN5bWJvbHMoc3RhdGUpO1xuXHRcdHJldHVybiBleHBTLmZpbHRlcihzID0+ICEocyBpbnN0YW5jZW9mIE5vblRlcm1pbmFsKSk7XG5cdH1cblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXJzZXIge1xuXHRwYXJzZShsZXhlcjogSUxleGVyKTogQVNUcmVlXG59XG5cbmV4cG9ydCBjbGFzcyBQcm9kc0luamVjdG9yIHtcblx0cHJvZElkQ291bnRlciA9IDBcblx0aW5qZWN0KG50OiBOb25UZXJtaW5hbCwgcmF3UHJvZHM6IFN5bWJvbFtdW10pIHtcblx0XHRmb3IgKGxldCByYXdQcm9kIG9mIHJhd1Byb2RzKSB7XG5cdFx0XHRudC5hZGRQcm9kKHRoaXMucHJvZElkQ291bnRlcisrLCByYXdQcm9kKTtcblx0XHR9XG5cdH1cbn1cblxuIl19