UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

432 lines (353 loc) 41.9 kB
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } import { DEBUG } from '@glimmer/env'; import { updateRef, valueForRef } from '@glimmer/reference'; import { associateDestroyableChild, destroy, destroyChildren } from '@glimmer/destroyable'; import { Stack, logStep } from '@glimmer/util'; import { resetTracking, runInTrackingTransaction } from '@glimmer/validator'; import { clear, move as moveBounds } from '../bounds'; import { NewElementBuilder } from './element-builder'; var UpdatingVMImpl = /*#__PURE__*/function () { function UpdatingVMImpl(env, _ref) { var _ref$alwaysRevalidate = _ref.alwaysRevalidate, alwaysRevalidate = _ref$alwaysRevalidate === void 0 ? false : _ref$alwaysRevalidate; this.frameStack = new Stack(); this.env = env; this.dom = env.getDOM(); this.alwaysRevalidate = alwaysRevalidate; } var _proto = UpdatingVMImpl.prototype; _proto.execute = function execute(opcodes, handler) { var _this = this; if (DEBUG) { var hasErrored = true; try { runInTrackingTransaction(function () { return _this._execute(opcodes, handler); }, '- While rendering:'); // using a boolean here to avoid breaking ergonomics of "pause on uncaught exceptions" // which would happen with a `catch` + `throw` hasErrored = false; } finally { if (hasErrored) { // eslint-disable-next-line no-console console.error("\n\nError occurred:\n\n" + resetTracking() + "\n\n"); } } } else { this._execute(opcodes, handler); } }; _proto._execute = function _execute(opcodes, handler) { var frameStack = this.frameStack; this["try"](opcodes, handler); while (true) { if (frameStack.isEmpty()) break; var opcode = this.frame.nextStatement(); if (opcode === undefined) { frameStack.pop(); continue; } opcode.evaluate(this); } }; _proto["goto"] = function goto(index) { this.frame["goto"](index); }; _proto["try"] = function _try(ops, handler) { this.frameStack.push(new UpdatingVMFrame(ops, handler)); }; _proto["throw"] = function _throw() { this.frame.handleException(); this.frameStack.pop(); }; _createClass(UpdatingVMImpl, [{ key: "frame", get: function get() { return this.frameStack.current; } }]); return UpdatingVMImpl; }(); export { UpdatingVMImpl as default }; export var ResumableVMStateImpl = /*#__PURE__*/function () { function ResumableVMStateImpl(state, resumeCallback) { this.state = state; this.resumeCallback = resumeCallback; } var _proto2 = ResumableVMStateImpl.prototype; _proto2.resume = function resume(runtime, builder) { return this.resumeCallback(runtime, this.state, builder); }; return ResumableVMStateImpl; }(); export var BlockOpcode = /*#__PURE__*/function () { function BlockOpcode(state, runtime, bounds, children) { this.state = state; this.runtime = runtime; this.children = children; this.bounds = bounds; } var _proto3 = BlockOpcode.prototype; _proto3.parentElement = function parentElement() { return this.bounds.parentElement(); }; _proto3.firstNode = function firstNode() { return this.bounds.firstNode(); }; _proto3.lastNode = function lastNode() { return this.bounds.lastNode(); }; _proto3.evaluate = function evaluate(vm) { vm["try"](this.children, null); }; return BlockOpcode; }(); export var TryOpcode = /*#__PURE__*/function (_BlockOpcode) { _inheritsLoose(TryOpcode, _BlockOpcode); function TryOpcode() { var _this2; _this2 = _BlockOpcode.apply(this, arguments) || this; _this2.type = 'try'; return _this2; } var _proto4 = TryOpcode.prototype; _proto4.evaluate = function evaluate(vm) { vm["try"](this.children, this); }; _proto4.handleException = function handleException() { var _this3 = this; var state = this.state, bounds = this.bounds, runtime = this.runtime; destroyChildren(this); var elementStack = NewElementBuilder.resume(runtime.env, bounds); var vm = state.resume(runtime, elementStack); var updating = []; var children = this.children = []; var result = vm.execute(function (vm) { vm.pushUpdating(updating); vm.updateWith(_this3); vm.pushUpdating(children); }); associateDestroyableChild(this, result.drop); }; return TryOpcode; }(BlockOpcode); export var ListItemOpcode = /*#__PURE__*/function (_TryOpcode) { _inheritsLoose(ListItemOpcode, _TryOpcode); function ListItemOpcode(state, runtime, bounds, key, memo, value) { var _this4; _this4 = _TryOpcode.call(this, state, runtime, bounds, []) || this; _this4.key = key; _this4.memo = memo; _this4.value = value; _this4.retained = false; _this4.index = -1; return _this4; } var _proto5 = ListItemOpcode.prototype; _proto5.updateReferences = function updateReferences(item) { this.retained = true; updateRef(this.value, item.value); updateRef(this.memo, item.memo); }; _proto5.shouldRemove = function shouldRemove() { return !this.retained; }; _proto5.reset = function reset() { this.retained = false; }; return ListItemOpcode; }(TryOpcode); export var ListBlockOpcode = /*#__PURE__*/function (_BlockOpcode2) { _inheritsLoose(ListBlockOpcode, _BlockOpcode2); function ListBlockOpcode(state, runtime, bounds, children, iterableRef) { var _this5; _this5 = _BlockOpcode2.call(this, state, runtime, bounds, children) || this; _this5.iterableRef = iterableRef; _this5.type = 'list-block'; _this5.opcodeMap = new Map(); _this5.marker = null; _this5.lastIterator = valueForRef(iterableRef); return _this5; } var _proto6 = ListBlockOpcode.prototype; _proto6.initializeChild = function initializeChild(opcode) { opcode.index = this.children.length - 1; this.opcodeMap.set(opcode.key, opcode); }; _proto6.evaluate = function evaluate(vm) { var iterator = valueForRef(this.iterableRef); if (this.lastIterator !== iterator) { var bounds = this.bounds; var dom = vm.dom; var marker = this.marker = dom.createComment(''); dom.insertAfter(bounds.parentElement(), marker, bounds.lastNode()); this.sync(iterator); this.parentElement().removeChild(marker); this.marker = null; this.lastIterator = iterator; } // Run now-updated updating opcodes _BlockOpcode2.prototype.evaluate.call(this, vm); }; _proto6.sync = function sync(iterator) { var itemMap = this.opcodeMap, children = this.children; var currentOpcodeIndex = 0; var seenIndex = 0; this.children = this.bounds.boundList = []; while (true) { var item = iterator.next(); if (item === null) break; var opcode = children[currentOpcodeIndex]; var key = item.key; // Items that have already been found and moved will already be retained, // we can continue until we find the next unretained item while (opcode !== undefined && opcode.retained === true) { opcode = children[++currentOpcodeIndex]; } if (opcode !== undefined && opcode.key === key) { this.retainItem(opcode, item); currentOpcodeIndex++; } else if (itemMap.has(key)) { var itemOpcode = itemMap.get(key); // The item opcode was seen already, so we should move it. if (itemOpcode.index < seenIndex) { this.moveItem(itemOpcode, item, opcode); } else { // Update the seen index, we are going to be moving this item around // so any other items that come before it will likely need to move as // well. seenIndex = itemOpcode.index; var seenUnretained = false; // iterate through all of the opcodes between the current position and // the position of the item's opcode, and determine if they are all // retained. for (var i = currentOpcodeIndex + 1; i < seenIndex; i++) { if (children[i].retained === false) { seenUnretained = true; break; } } // If we have seen only retained opcodes between this and the matching // opcode, it means that all the opcodes in between have been moved // already, and we can safely retain this item's opcode. if (seenUnretained === false) { this.retainItem(itemOpcode, item); currentOpcodeIndex = seenIndex + 1; } else { this.moveItem(itemOpcode, item, opcode); currentOpcodeIndex++; } } } else { this.insertItem(item, opcode); } } for (var _i = 0; _i < children.length; _i++) { var _opcode = children[_i]; if (_opcode.retained === false) { this.deleteItem(_opcode); } else { _opcode.reset(); } } }; _proto6.retainItem = function retainItem(opcode, item) { if (false /* LOCAL_DEBUG */ ) { logStep('list-updates', ['retain', item.key]); } var children = this.children; updateRef(opcode.memo, item.memo); updateRef(opcode.value, item.value); opcode.retained = true; opcode.index = children.length; children.push(opcode); }; _proto6.insertItem = function insertItem(item, before) { var _this6 = this; if (false /* LOCAL_DEBUG */ ) { logStep('list-updates', ['insert', item.key]); } var opcodeMap = this.opcodeMap, bounds = this.bounds, state = this.state, runtime = this.runtime, children = this.children; var key = item.key; var nextSibling = before === undefined ? this.marker : before.firstNode(); var elementStack = NewElementBuilder.forInitialRender(runtime.env, { element: bounds.parentElement(), nextSibling: nextSibling }); var vm = state.resume(runtime, elementStack); vm.execute(function (vm) { vm.pushUpdating(); var opcode = vm.enterItem(item); opcode.index = children.length; children.push(opcode); opcodeMap.set(key, opcode); associateDestroyableChild(_this6, opcode); }); }; _proto6.moveItem = function moveItem(opcode, item, before) { var children = this.children; updateRef(opcode.memo, item.memo); updateRef(opcode.value, item.value); opcode.retained = true; var currentSibling, nextSibling; if (before === undefined) { moveBounds(opcode, this.marker); } else { currentSibling = opcode.lastNode().nextSibling; nextSibling = before.firstNode(); // Items are moved throughout the algorithm, so there are cases where the // the items already happen to be siblings (e.g. an item in between was // moved before this move happened). Check to see if they are siblings // first before doing the move. if (currentSibling !== nextSibling) { moveBounds(opcode, nextSibling); } } opcode.index = children.length; children.push(opcode); if (false /* LOCAL_DEBUG */ ) { var type = currentSibling && currentSibling === nextSibling ? 'move-retain' : 'move'; logStep('list-updates', [type, item.key]); } }; _proto6.deleteItem = function deleteItem(opcode) { if (false /* LOCAL_DEBUG */ ) { logStep('list-updates', ['delete', opcode.key]); } destroy(opcode); clear(opcode); this.opcodeMap["delete"](opcode.key); }; return ListBlockOpcode; }(BlockOpcode); var UpdatingVMFrame = /*#__PURE__*/function () { function UpdatingVMFrame(ops, exceptionHandler) { this.ops = ops; this.exceptionHandler = exceptionHandler; this.current = 0; } var _proto7 = UpdatingVMFrame.prototype; _proto7["goto"] = function goto(index) { this.current = index; }; _proto7.nextStatement = function nextStatement() { return this.ops[this.current++]; }; _proto7.handleException = function handleException() { if (this.exceptionHandler) { this.exceptionHandler.handleException(); } }; return UpdatingVMFrame; }(); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL3VwZGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxTQUFBLEtBQUEsUUFBQSxjQUFBO0FBaUJBLFNBQUEsU0FBQSxFQUFBLFdBQUEsUUFBQSxvQkFBQTtBQU9BLFNBQUEseUJBQUEsRUFBQSxPQUFBLEVBQUEsZUFBQSxRQUFBLHNCQUFBO0FBQ0EsU0FBQSxLQUFBLEVBQUEsT0FBQSxRQUFBLGVBQUE7QUFDQSxTQUFBLGFBQUEsRUFBQSx3QkFBQSxRQUFBLG9CQUFBO0FBRUEsU0FBQSxLQUFBLEVBQWdCLElBQUksSUFBcEIsVUFBQSxRQUFBLFdBQUE7QUFFQSxTQUFBLGlCQUFBLFFBQUEsbUJBQUE7O0lBRWMsYztBQU9aLDBCQUFBLEdBQUEsUUFBMEQ7QUFBQSxxQ0FBMUIsZ0JBQTBCO0FBQUEsUUFBMUIsZ0JBQTBCLHNDQUFQLEtBQU87QUFGbEQsU0FBQSxVQUFBLEdBQXFDLElBQXJDLEtBQXFDLEVBQXJDO0FBR04sU0FBQSxHQUFBLEdBQUEsR0FBQTtBQUNBLFNBQUEsR0FBQSxHQUFXLEdBQUcsQ0FBZCxNQUFXLEVBQVg7QUFDQSxTQUFBLGdCQUFBLEdBQUEsZ0JBQUE7QUFDRDs7OztTQUVELE8sR0FBQSxpQkFBTyxPQUFQLEVBQU8sT0FBUCxFQUE0RDtBQUFBOztBQUMxRCxRQUFBLEtBQUEsRUFBVztBQUNULFVBQUksVUFBVSxHQUFkLElBQUE7O0FBQ0EsVUFBSTtBQUNGLFFBQUEsd0JBQXlCLENBQUM7QUFBQSxpQkFBTSxLQUFBLENBQUEsUUFBQSxDQUFBLE9BQUEsRUFBUCxPQUFPLENBQU47QUFBQSxTQUFELEVBRHZCLG9CQUN1QixDQUF6QixDQURFLENBR0Y7QUFDQTs7QUFDQSxRQUFBLFVBQVUsR0FBVixLQUFBO0FBTEYsT0FBQSxTQU1VO0FBQ1IsWUFBQSxVQUFBLEVBQWdCO0FBQ2Q7QUFDQSxVQUFBLE9BQU8sQ0FBUCxLQUFBLDZCQUF3QyxhQUF4QyxFQUFBO0FBQ0Q7QUFDRjtBQWJILEtBQUEsTUFjTztBQUNMLFdBQUEsUUFBQSxDQUFBLE9BQUEsRUFBQSxPQUFBO0FBQ0Q7QUFDRixHOztTQUVPLFEsR0FBQSxrQkFBUSxPQUFSLEVBQVEsT0FBUixFQUE2RDtBQUFBLFFBQzdELFVBRDZELEdBQ25FLElBRG1FLENBQzdELFVBRDZEO0FBR25FLGdCQUFBLE9BQUEsRUFBQSxPQUFBOztBQUVBLFdBQUEsSUFBQSxFQUFhO0FBQ1gsVUFBSSxVQUFVLENBQWQsT0FBSSxFQUFKLEVBQTBCO0FBRTFCLFVBQUksTUFBTSxHQUFHLEtBQUEsS0FBQSxDQUFiLGFBQWEsRUFBYjs7QUFFQSxVQUFJLE1BQU0sS0FBVixTQUFBLEVBQTBCO0FBQ3hCLFFBQUEsVUFBVSxDQUFWLEdBQUE7QUFDQTtBQUNEOztBQUVELE1BQUEsTUFBTSxDQUFOLFFBQUEsQ0FBQSxJQUFBO0FBQ0Q7QUFDRixHOzttQkFNRCxjQUFJLEtBQUosRUFBa0I7QUFDaEIsU0FBQSxLQUFBLFNBQUEsS0FBQTtBQUNELEc7O2tCQUVELGNBQUcsR0FBSCxFQUFHLE9BQUgsRUFBNEQ7QUFDMUQsU0FBQSxVQUFBLENBQUEsSUFBQSxDQUFxQixJQUFBLGVBQUEsQ0FBQSxHQUFBLEVBQXJCLE9BQXFCLENBQXJCO0FBQ0QsRzs7b0JBRUQsa0JBQUs7QUFDSCxTQUFBLEtBQUEsQ0FBQSxlQUFBO0FBQ0EsU0FBQSxVQUFBLENBQUEsR0FBQTtBQUNELEc7Ozs7d0JBZmdCO0FBQ2YsYUFBYyxLQUFBLFVBQUEsQ0FBZCxPQUFBO0FBQ0Q7Ozs7OztTQXREVyxjO0FBaUZkLFdBQU0sb0JBQU47QUFDRSxnQ0FBQSxLQUFBLEVBQUEsY0FBQSxFQUEyRTtBQUF0RCxTQUFBLEtBQUEsR0FBQSxLQUFBO0FBQXdCLFNBQUEsY0FBQSxHQUFBLGNBQUE7QUFBa0M7O0FBRGpGOztBQUFBLFVBR0UsTUFIRixHQUdFLGdCQUFNLE9BQU4sRUFBTSxPQUFOLEVBQXVEO0FBQ3JELFdBQU8sS0FBQSxjQUFBLENBQUEsT0FBQSxFQUE2QixLQUE3QixLQUFBLEVBQVAsT0FBTyxDQUFQO0FBQ0QsR0FMSDs7QUFBQTtBQUFBO0FBUUEsV0FBTSxXQUFOO0FBS0UsdUJBQUEsS0FBQSxFQUFBLE9BQUEsRUFBQSxNQUFBLEVBQUEsUUFBQSxFQUk0QjtBQUhoQixTQUFBLEtBQUEsR0FBQSxLQUFBO0FBQ0EsU0FBQSxPQUFBLEdBQUEsT0FBQTtBQUlWLFNBQUEsUUFBQSxHQUFBLFFBQUE7QUFDQSxTQUFBLE1BQUEsR0FBQSxNQUFBO0FBQ0Q7O0FBYkg7O0FBQUEsVUFlRSxhQWZGLEdBZUUseUJBQWE7QUFDWCxXQUFPLEtBQUEsTUFBQSxDQUFQLGFBQU8sRUFBUDtBQUNELEdBakJIOztBQUFBLFVBbUJFLFNBbkJGLEdBbUJFLHFCQUFTO0FBQ1AsV0FBTyxLQUFBLE1BQUEsQ0FBUCxTQUFPLEVBQVA7QUFDRCxHQXJCSDs7QUFBQSxVQXVCRSxRQXZCRixHQXVCRSxvQkFBUTtBQUNOLFdBQU8sS0FBQSxNQUFBLENBQVAsUUFBTyxFQUFQO0FBQ0QsR0F6Qkg7O0FBQUEsVUEyQkUsUUEzQkYsR0EyQkUsa0JBQVEsRUFBUixFQUEyQjtBQUN6QixJQUFBLEVBQUEsT0FBQSxDQUFPLEtBQVAsUUFBQSxFQUFBLElBQUE7QUFDRCxHQTdCSDs7QUFBQTtBQUFBO0FBZ0NBLFdBQU0sU0FBTjtBQUFBOztBQUFBLHVCQUFBO0FBQUE7OztBQUNTLFdBQUEsSUFBQSxHQUFBLEtBQUE7QUFEVDtBQTRCQzs7QUE1QkQ7O0FBQUEsVUFLRSxRQUxGLEdBS0Usa0JBQVEsRUFBUixFQUEyQjtBQUN6QixJQUFBLEVBQUEsT0FBQSxDQUFPLEtBQVAsUUFBQSxFQUFBLElBQUE7QUFDRCxHQVBIOztBQUFBLFVBU0UsZUFURixHQVNFLDJCQUFlO0FBQUE7O0FBQUEsUUFDVCxLQURTLEdBQ2IsSUFEYSxDQUNULEtBRFM7QUFBQSxRQUNULE1BRFMsR0FDYixJQURhLENBQ1QsTUFEUztBQUFBLFFBQ1EsT0FEUixHQUNiLElBRGEsQ0FDUSxPQURSO0FBR2IsSUFBQSxlQUFlLENBQWYsSUFBZSxDQUFmO0FBRUEsUUFBSSxZQUFZLEdBQUcsaUJBQWlCLENBQWpCLE1BQUEsQ0FBeUIsT0FBTyxDQUFoQyxHQUFBLEVBQW5CLE1BQW1CLENBQW5CO0FBQ0EsUUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFMLE1BQUEsQ0FBQSxPQUFBLEVBQVQsWUFBUyxDQUFUO0FBRUEsUUFBSSxRQUFRLEdBQVosRUFBQTtBQUNBLFFBQUksUUFBUSxHQUFJLEtBQUEsUUFBQSxHQUFoQixFQUFBO0FBRUEsUUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFGLE9BQUEsQ0FBWSxVQUFBLEVBQUQsRUFBTztBQUM3QixNQUFBLEVBQUUsQ0FBRixZQUFBLENBQUEsUUFBQTtBQUNBLE1BQUEsRUFBRSxDQUFGLFVBQUEsQ0FBQSxNQUFBO0FBQ0EsTUFBQSxFQUFFLENBQUYsWUFBQSxDQUFBLFFBQUE7QUFIRixLQUFhLENBQWI7QUFNQSxJQUFBLHlCQUF5QixDQUFBLElBQUEsRUFBTyxNQUFNLENBQXRDLElBQXlCLENBQXpCO0FBQ0QsR0EzQkg7O0FBQUE7QUFBQSxFQUFNLFdBQU47QUE4QkEsV0FBTSxjQUFOO0FBQUE7O0FBSUUsMEJBQUEsS0FBQSxFQUFBLE9BQUEsRUFBQSxNQUFBLEVBQUEsR0FBQSxFQUFBLElBQUEsRUFBQSxLQUFBLEVBTXlCO0FBQUE7O0FBRXZCLG1DQUFBLEtBQUEsRUFBQSxPQUFBLEVBQUEsTUFBQSxFQUFBLEVBQUE7QUFKTyxXQUFBLEdBQUEsR0FBQSxHQUFBO0FBQ0EsV0FBQSxJQUFBLEdBQUEsSUFBQTtBQUNBLFdBQUEsS0FBQSxHQUFBLEtBQUE7QUFURixXQUFBLFFBQUEsR0FBQSxLQUFBO0FBQ0EsV0FBQSxLQUFBLEdBQVEsQ0FBUixDQUFBO0FBUWtCO0FBR3hCOztBQWJIOztBQUFBLFVBZUUsZ0JBZkYsR0FlRSwwQkFBZ0IsSUFBaEIsRUFBMEM7QUFDeEMsU0FBQSxRQUFBLEdBQUEsSUFBQTtBQUNBLElBQUEsU0FBUyxDQUFDLEtBQUQsS0FBQSxFQUFhLElBQUksQ0FBMUIsS0FBUyxDQUFUO0FBQ0EsSUFBQSxTQUFTLENBQUMsS0FBRCxJQUFBLEVBQVksSUFBSSxDQUF6QixJQUFTLENBQVQ7QUFDRCxHQW5CSDs7QUFBQSxVQXFCRSxZQXJCRixHQXFCRSx3QkFBWTtBQUNWLFdBQU8sQ0FBQyxLQUFSLFFBQUE7QUFDRCxHQXZCSDs7QUFBQSxVQXlCRSxLQXpCRixHQXlCRSxpQkFBSztBQUNILFNBQUEsUUFBQSxHQUFBLEtBQUE7QUFDRCxHQTNCSDs7QUFBQTtBQUFBLEVBQU0sU0FBTjtBQThCQSxXQUFNLGVBQU47QUFBQTs7QUFVRSwyQkFBQSxLQUFBLEVBQUEsT0FBQSxFQUFBLE1BQUEsRUFBQSxRQUFBLEVBQUEsV0FBQSxFQUtnRDtBQUFBOztBQUU5QyxzQ0FBQSxLQUFBLEVBQUEsT0FBQSxFQUFBLE1BQUEsRUFBQSxRQUFBO0FBRlEsV0FBQSxXQUFBLEdBQUEsV0FBQTtBQWRILFdBQUEsSUFBQSxHQUFBLFlBQUE7QUFHQyxXQUFBLFNBQUEsR0FBWSxJQUFaLEdBQVksRUFBWjtBQUNBLFdBQUEsTUFBQSxHQUFBLElBQUE7QUFhTixXQUFBLFlBQUEsR0FBb0IsV0FBVyxDQUEvQixXQUErQixDQUEvQjtBQUg4QztBQUkvQzs7QUFuQkg7O0FBQUEsVUFxQkUsZUFyQkYsR0FxQkUseUJBQWUsTUFBZixFQUFzQztBQUNwQyxJQUFBLE1BQU0sQ0FBTixLQUFBLEdBQWUsS0FBQSxRQUFBLENBQUEsTUFBQSxHQUFmLENBQUE7QUFDQSxTQUFBLFNBQUEsQ0FBQSxHQUFBLENBQW1CLE1BQU0sQ0FBekIsR0FBQSxFQUFBLE1BQUE7QUFDRCxHQXhCSDs7QUFBQSxVQTBCRSxRQTFCRixHQTBCRSxrQkFBUSxFQUFSLEVBQTJCO0FBQ3pCLFFBQUksUUFBUSxHQUFHLFdBQVcsQ0FBQyxLQUEzQixXQUEwQixDQUExQjs7QUFFQSxRQUFJLEtBQUEsWUFBQSxLQUFKLFFBQUEsRUFBb0M7QUFBQSxVQUM1QixNQUQ0QixHQUNsQyxJQURrQyxDQUM1QixNQUQ0QjtBQUFBLFVBRTVCLEdBRjRCLEdBRWxDLEVBRmtDLENBRTVCLEdBRjRCO0FBSWxDLFVBQUksTUFBTSxHQUFJLEtBQUEsTUFBQSxHQUFjLEdBQUcsQ0FBSCxhQUFBLENBQTVCLEVBQTRCLENBQTVCO0FBQ0EsTUFBQSxHQUFHLENBQUgsV0FBQSxDQUNFLE1BQU0sQ0FEUixhQUNFLEVBREYsRUFBQSxNQUFBLEVBR1MsTUFBTSxDQUhmLFFBR1MsRUFIVDtBQU1BLFdBQUEsSUFBQSxDQUFBLFFBQUE7QUFFQSxXQUFBLGFBQUEsR0FBQSxXQUFBLENBQUEsTUFBQTtBQUNBLFdBQUEsTUFBQSxHQUFBLElBQUE7QUFDQSxXQUFBLFlBQUEsR0FBQSxRQUFBO0FBbEJ1QixLQUFBLENBcUJ6Qjs7O0FBQ0EsNEJBQUEsUUFBQSxZQUFBLEVBQUE7QUFDRCxHQWpESDs7QUFBQSxVQW1EVSxJQW5EVixHQW1EVSxjQUFJLFFBQUosRUFBNkI7QUFBQSxRQUMvQixPQUQrQixHQUNuQyxJQURtQyxDQUM3QixTQUQ2QjtBQUFBLFFBQ1QsUUFEUyxHQUNuQyxJQURtQyxDQUNULFFBRFM7QUFHbkMsUUFBSSxrQkFBa0IsR0FBdEIsQ0FBQTtBQUNBLFFBQUksU0FBUyxHQUFiLENBQUE7QUFFQSxTQUFBLFFBQUEsR0FBZ0IsS0FBQSxNQUFBLENBQUEsU0FBQSxHQUFoQixFQUFBOztBQUVBLFdBQUEsSUFBQSxFQUFhO0FBQ1gsVUFBSSxJQUFJLEdBQUcsUUFBUSxDQUFuQixJQUFXLEVBQVg7QUFFQSxVQUFJLElBQUksS0FBUixJQUFBLEVBQW1CO0FBRW5CLFVBQUksTUFBTSxHQUFHLFFBQVEsQ0FBckIsa0JBQXFCLENBQXJCO0FBTFcsVUFNTCxHQU5LLEdBQUEsSUFBQSxDQU1MLEdBTkssRUFRWDtBQUNBOztBQUNBLGFBQU8sTUFBTSxLQUFOLFNBQUEsSUFBd0IsTUFBTSxDQUFOLFFBQUEsS0FBL0IsSUFBQSxFQUF5RDtBQUN2RCxRQUFBLE1BQU0sR0FBRyxRQUFRLENBQUMsRUFBbEIsa0JBQWlCLENBQWpCO0FBQ0Q7O0FBRUQsVUFBSSxNQUFNLEtBQU4sU0FBQSxJQUF3QixNQUFNLENBQU4sR0FBQSxLQUE1QixHQUFBLEVBQWdEO0FBQzlDLGFBQUEsVUFBQSxDQUFBLE1BQUEsRUFBQSxJQUFBO0FBQ0EsUUFBQSxrQkFBa0I7QUFGcEIsT0FBQSxNQUdPLElBQUksT0FBTyxDQUFQLEdBQUEsQ0FBSixHQUFJLENBQUosRUFBc0I7QUFDM0IsWUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFQLEdBQUEsQ0FEVSxHQUNWLENBQWpCLENBRDJCLENBRzNCOztBQUNBLFlBQUksVUFBVSxDQUFWLEtBQUEsR0FBSixTQUFBLEVBQWtDO0FBQ2hDLGVBQUEsUUFBQSxDQUFBLFVBQUEsRUFBQSxJQUFBLEVBQUEsTUFBQTtBQURGLFNBQUEsTUFFTztBQUNMO0FBQ0E7QUFDQTtBQUNBLFVBQUEsU0FBUyxHQUFHLFVBQVUsQ0FBdEIsS0FBQTtBQUVBLGNBQUksY0FBYyxHQU5iLEtBTUwsQ0FOSyxDQVFMO0FBQ0E7QUFDQTs7QUFDQSxlQUFLLElBQUksQ0FBQyxHQUFHLGtCQUFrQixHQUEvQixDQUFBLEVBQXFDLENBQUMsR0FBdEMsU0FBQSxFQUFvRCxDQUFwRCxFQUFBLEVBQXlEO0FBQ3ZELGdCQUFJLFFBQVEsQ0FBUixDQUFRLENBQVIsQ0FBQSxRQUFBLEtBQUosS0FBQSxFQUFvQztBQUNsQyxjQUFBLGNBQWMsR0FBZCxJQUFBO0FBQ0E7QUFDRDtBQWZFLFdBQUEsQ0FrQkw7QUFDQTtBQUNBOzs7QUFDQSxjQUFJLGNBQWMsS0FBbEIsS0FBQSxFQUE4QjtBQUM1QixpQkFBQSxVQUFBLENBQUEsVUFBQSxFQUFBLElBQUE7QUFDQSxZQUFBLGtCQUFrQixHQUFHLFNBQVMsR0FBOUIsQ0FBQTtBQUZGLFdBQUEsTUFHTztBQUNMLGlCQUFBLFFBQUEsQ0FBQSxVQUFBLEVBQUEsSUFBQSxFQUFBLE1BQUE7QUFDQSxZQUFBLGtCQUFrQjtBQUNuQjtBQUNGO0FBbENJLE9BQUEsTUFtQ0E7QUFDTCxhQUFBLFVBQUEsQ0FBQSxJQUFBLEVBQUEsTUFBQTtBQUNEO0FBQ0Y7O0FBRUQsU0FBSyxJQUFJLEVBQUMsR0FBVixDQUFBLEVBQWdCLEVBQUMsR0FBRyxRQUFRLENBQTVCLE1BQUEsRUFBcUMsRUFBckMsRUFBQSxFQUEwQztBQUN4QyxVQUFJLE9BQU0sR0FBRyxRQUFRLENBQXJCLEVBQXFCLENBQXJCOztBQUVBLFVBQUksT0FBTSxDQUFOLFFBQUEsS0FBSixLQUFBLEVBQStCO0FBQzdCLGFBQUEsVUFBQSxDQUFBLE9BQUE7QUFERixPQUFBLE1BRU87QUFDTCxRQUFBLE9BQU0sQ0FBTixLQUFBO0FBQ0Q7QUFDRjtBQUNGLEdBN0hIOztBQUFBLFVBK0hVLFVBL0hWLEdBK0hVLG9CQUFVLE1BQVYsRUFBVSxJQUFWLEVBQTREO0FBQ2xFLFFBQUE7QUFBQTtBQUFBLE1BQWlCO0FBQ2YsUUFBQSxPQUFRLENBQUEsY0FBQSxFQUFpQixDQUFBLFFBQUEsRUFBVyxJQUFJLENBQXhDLEdBQXlCLENBQWpCLENBQVI7QUFDRDs7QUFIaUUsUUFLNUQsUUFMNEQsR0FLbEUsSUFMa0UsQ0FLNUQsUUFMNEQ7QUFPbEUsSUFBQSxTQUFTLENBQUMsTUFBTSxDQUFQLElBQUEsRUFBYyxJQUFJLENBQTNCLElBQVMsQ0FBVDtBQUNBLElBQUEsU0FBUyxDQUFDLE1BQU0sQ0FBUCxLQUFBLEVBQWUsSUFBSSxDQUE1QixLQUFTLENBQVQ7QUFDQSxJQUFBLE1BQU0sQ0FBTixRQUFBLEdBQUEsSUFBQTtBQUVBLElBQUEsTUFBTSxDQUFOLEtBQUEsR0FBZSxRQUFRLENBQXZCLE1BQUE7QUFDQSxJQUFBLFFBQVEsQ0FBUixJQUFBLENBQUEsTUFBQTtBQUNELEdBNUlIOztBQUFBLFVBOElVLFVBOUlWLEdBOElVLG9CQUFVLElBQVYsRUFBVSxNQUFWLEVBQTREO0FBQUE7O0FBQ2xFLFFBQUE7QUFBQTtBQUFBLE1BQWlCO0FBQ2YsUUFBQSxPQUFRLENBQUEsY0FBQSxFQUFpQixDQUFBLFFBQUEsRUFBVyxJQUFJLENBQXhDLEdBQXlCLENBQWpCLENBQVI7QUFDRDs7QUFIaUUsUUFLOUQsU0FMOEQsR0FLbEUsSUFMa0UsQ0FLOUQsU0FMOEQ7QUFBQSxRQUs5RCxNQUw4RCxHQUtsRSxJQUxrRSxDQUs5RCxNQUw4RDtBQUFBLFFBSzlELEtBTDhELEdBS2xFLElBTGtFLENBSzlELEtBTDhEO0FBQUEsUUFLOUQsT0FMOEQsR0FLbEUsSUFMa0UsQ0FLOUQsT0FMOEQ7QUFBQSxRQUt6QixRQUx5QixHQUtsRSxJQUxrRSxDQUt6QixRQUx5QjtBQUFBLFFBTTVELEdBTjRELEdBTWxFLElBTmtFLENBTTVELEdBTjREO0FBT2xFLFFBQUksV0FBVyxHQUFHLE1BQU0sS0FBTixTQUFBLEdBQXVCLEtBQXZCLE1BQUEsR0FBcUMsTUFBTSxDQUE3RCxTQUF1RCxFQUF2RDtBQUVBLFFBQUksWUFBWSxHQUFHLGlCQUFpQixDQUFqQixnQkFBQSxDQUFtQyxPQUFPLENBQTFDLEdBQUEsRUFBZ0Q7QUFDakUsTUFBQSxPQUFPLEVBQUUsTUFBTSxDQURrRCxhQUN4RCxFQUR3RDtBQUVqRSxNQUFBLFdBQUEsRUFBQTtBQUZpRSxLQUFoRCxDQUFuQjtBQUtBLFFBQUksRUFBRSxHQUFHLEtBQUssQ0FBTCxNQUFBLENBQUEsT0FBQSxFQUFULFlBQVMsQ0FBVDtBQUVBLElBQUEsRUFBRSxDQUFGLE9BQUEsQ0FBWSxVQUFBLEVBQUQsRUFBTztBQUNoQixNQUFBLEVBQUUsQ0FBRixZQUFBO0FBQ0EsVUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFGLFNBQUEsQ0FBYixJQUFhLENBQWI7QUFFQSxNQUFBLE1BQU0sQ0FBTixLQUFBLEdBQWUsUUFBUSxDQUF2QixNQUFBO0FBQ0EsTUFBQSxRQUFRLENBQVIsSUFBQSxDQUFBLE1BQUE7QUFDQSxNQUFBLFNBQVMsQ0FBVCxHQUFBLENBQUEsR0FBQSxFQUFBLE1BQUE7QUFDQSxNQUFBLHlCQUF5QixDQUFBLE1BQUEsRUFBekIsTUFBeUIsQ0FBekI7QUFQRixLQUFBO0FBU0QsR0F2S0g7O0FBQUEsVUF5S1UsUUF6S1YsR0F5S1Usa0JBQVEsTUFBUixFQUFRLElBQVIsRUFBUSxNQUFSLEVBQWtGO0FBQUEsUUFDbEYsUUFEa0YsR0FDeEYsSUFEd0YsQ0FDbEYsUUFEa0Y7QUFHeEYsSUFBQSxTQUFTLENBQUMsTUFBTSxDQUFQLElBQUEsRUFBYyxJQUFJLENBQTNCLElBQVMsQ0FBVDtBQUNBLElBQUEsU0FBUyxDQUFDLE1BQU0sQ0FBUCxLQUFBLEVBQWUsSUFBSSxDQUE1QixLQUFTLENBQVQ7QUFDQSxJQUFBLE1BQU0sQ0FBTixRQUFBLEdBQUEsSUFBQTtBQUVBLFFBQUEsY0FBQSxFQUFBLFdBQUE7O0FBRUEsUUFBSSxNQUFNLEtBQVYsU0FBQSxFQUEwQjtBQUN4QixNQUFBLFVBQVUsQ0FBQSxNQUFBLEVBQVMsS0FBbkIsTUFBVSxDQUFWO0FBREYsS0FBQSxNQUVPO0FBQ0wsTUFBQSxjQUFjLEdBQUcsTUFBTSxDQUFOLFFBQUEsR0FBakIsV0FBQTtBQUNBLE1BQUEsV0FBVyxHQUFHLE1BQU0sQ0FGZixTQUVTLEVBQWQsQ0FGSyxDQUlMO0FBQ0E7QUFDQTtBQUNBOztBQUNBLFVBQUksY0FBYyxLQUFsQixXQUFBLEVBQW9DO0FBQ2xDLFFBQUEsVUFBVSxDQUFBLE1BQUEsRUFBVixXQUFVLENBQVY7QUFDRDtBQUNGOztBQUVELElBQUEsTUFBTSxDQUFOLEtBQUEsR0FBZSxRQUFRLENBQXZCLE1BQUE7QUFDQSxJQUFBLFFBQVEsQ0FBUixJQUFBLENBQUEsTUFBQTs7QUFFQSxRQUFBO0FBQUE7QUFBQSxNQUFpQjtBQUNmLFlBQUksSUFBSSxHQUFHLGNBQWMsSUFBSSxjQUFjLEtBQWhDLFdBQUEsR0FBQSxhQUFBLEdBQVgsTUFBQTtBQUNBLFFBQUEsT0FBUSxDQUFBLGNBQUEsRUFBaUIsQ0FBQSxJQUFBLEVBQU8sSUFBSSxDQUFwQyxHQUF5QixDQUFqQixDQUFSO0FBQ0Q7QUFDRixHQXhNSDs7QUFBQSxVQTBNVSxVQTFNVixHQTBNVSxvQkFBVSxNQUFWLEVBQWlDO0FBQ3ZDLFFBQUE7QUFBQTtBQUFBLE1BQWlCO0FBQ2YsUUFBQSxPQUFRLENBQUEsY0FBQSxFQUFpQixDQUFBLFFBQUEsRUFBVyxNQUFNLENBQTFDLEdBQXlCLENBQWpCLENBQVI7QUFDRDs7QUFFRCxJQUFBLE9BQU8sQ0FBUCxNQUFPLENBQVA7QUFDQSxJQUFBLEtBQUssQ0FBTCxNQUFLLENBQUw7QUFDQSxTQUFBLFNBQUEsV0FBc0IsTUFBTSxDQUE1QixHQUFBO0FBQ0QsR0FsTkg7O0FBQUE7QUFBQSxFQUFNLFdBQU47O0lBcU5BLGU7QUFHRSwyQkFBQSxHQUFBLEVBQUEsZ0JBQUEsRUFBNkY7QUFBekUsU0FBQSxHQUFBLEdBQUEsR0FBQTtBQUErQixTQUFBLGdCQUFBLEdBQUEsZ0JBQUE7QUFGM0MsU0FBQSxPQUFBLEdBQUEsQ0FBQTtBQUV5Rjs7OztvQkFFakcsY0FBSSxLQUFKLEVBQWtCO0FBQ2hCLFNBQUEsT0FBQSxHQUFBLEtBQUE7QUFDRCxHOztVQUVELGEsR0FBQSx5QkFBYTtBQUNYLFdBQU8sS0FBQSxHQUFBLENBQVMsS0FBaEIsT0FBZ0IsRUFBVCxDQUFQO0FBQ0QsRzs7VUFFRCxlLEdBQUEsMkJBQWU7QUFDYixRQUFJLEtBQUosZ0JBQUEsRUFBMkI7QUFDekIsV0FBQSxnQkFBQSxDQUFBLGVBQUE7QUFDRDtBQUNGLEciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBERUJVRyB9IGZyb20gJ0BnbGltbWVyL2Vudic7XG5pbXBvcnQge1xuICBCb3VuZHMsXG4gIER5bmFtaWNTY29wZSxcbiAgRWxlbWVudEJ1aWxkZXIsXG4gIEVudmlyb25tZW50LFxuICBFeGNlcHRpb25IYW5kbGVyLFxuICBHbGltbWVyVHJlZUNoYW5nZXMsXG4gIExpdmVCbG9jayxcbiAgT3B0aW9uLFxuICBSdW50aW1lQ29udGV4dCxcbiAgU2NvcGUsXG4gIFVwZGF0YWJsZUJsb2NrLFxuICBVcGRhdGluZ1ZNLFxuICBVcGRhdGluZ09wY29kZSxcbn0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBMT0NBTF9ERUJVRyB9IGZyb20gJ0BnbGltbWVyL2xvY2FsLWRlYnVnLWZsYWdzJztcbmltcG9ydCB7XG4gIE9wYXF1ZUl0ZXJhdGlvbkl0ZW0sXG4gIE9wYXF1ZUl0ZXJhdG9yLFxuICBSZWZlcmVuY2UsXG4gIHVwZGF0ZVJlZixcbiAgdmFsdWVGb3JSZWYsXG59IGZyb20gJ0BnbGltbWVyL3JlZmVyZW5jZSc7XG5pbXBvcnQgeyBhc3NvY2lhdGVEZXN0cm95YWJsZUNoaWxkLCBkZXN0cm95LCBkZXN0cm95Q2hpbGRyZW4gfSBmcm9tICdAZ2xpbW1lci9kZXN0cm95YWJsZSc7XG5pbXBvcnQgeyBleHBlY3QsIFN0YWNrLCBsb2dTdGVwIH0gZnJvbSAnQGdsaW1tZXIvdXRpbCc7XG5pbXBvcnQgeyByZXNldFRyYWNraW5nLCBydW5JblRyYWNraW5nVHJhbnNhY3Rpb24gfSBmcm9tICdAZ2xpbW1lci92YWxpZGF0b3InO1xuaW1wb3J0IHsgU2ltcGxlQ29tbWVudCB9IGZyb20gJ0BzaW1wbGUtZG9tL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBjbGVhciwgbW92ZSBhcyBtb3ZlQm91bmRzIH0gZnJvbSAnLi4vYm91bmRzJztcbmltcG9ydCB7IEludGVybmFsVk0sIFZtSW5pdENhbGxiYWNrIH0gZnJvbSAnLi9hcHBlbmQnO1xuaW1wb3J0IHsgTGl2ZUJsb2NrTGlzdCwgTmV3RWxlbWVudEJ1aWxkZXIgfSBmcm9tICcuL2VsZW1lbnQtYnVpbGRlcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFVwZGF0aW5nVk1JbXBsIGltcGxlbWVudHMgVXBkYXRpbmdWTSB7XG4gIHB1YmxpYyBlbnY6IEVudmlyb25tZW50O1xuICBwdWJsaWMgZG9tOiBHbGltbWVyVHJlZUNoYW5nZXM7XG4gIHB1YmxpYyBhbHdheXNSZXZhbGlkYXRlOiBib29sZWFuO1xuXG4gIHByaXZhdGUgZnJhbWVTdGFjazogU3RhY2s8VXBkYXRpbmdWTUZyYW1lPiA9IG5ldyBTdGFjazxVcGRhdGluZ1ZNRnJhbWU+KCk7XG5cbiAgY29uc3RydWN0b3IoZW52OiBFbnZpcm9ubWVudCwgeyBhbHdheXNSZXZhbGlkYXRlID0gZmFsc2UgfSkge1xuICAgIHRoaXMuZW52ID0gZW52O1xuICAgIHRoaXMuZG9tID0gZW52LmdldERPTSgpO1xuICAgIHRoaXMuYWx3YXlzUmV2YWxpZGF0ZSA9IGFsd2F5c1JldmFsaWRhdGU7XG4gIH1cblxuICBleGVjdXRlKG9wY29kZXM6IFVwZGF0aW5nT3Bjb2RlW10sIGhhbmRsZXI6IEV4Y2VwdGlvbkhhbmRsZXIpIHtcbiAgICBpZiAoREVCVUcpIHtcbiAgICAgIGxldCBoYXNFcnJvcmVkID0gdHJ1ZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJ1bkluVHJhY2tpbmdUcmFuc2FjdGlvbiEoKCkgPT4gdGhpcy5fZXhlY3V0ZShvcGNvZGVzLCBoYW5kbGVyKSwgJy0gV2hpbGUgcmVuZGVyaW5nOicpO1xuXG4gICAgICAgIC8vIHVzaW5nIGEgYm9vbGVhbiBoZXJlIHRvIGF2b2lkIGJyZWFraW5nIGVyZ29ub21pY3Mgb2YgXCJwYXVzZSBvbiB1bmNhdWdodCBleGNlcHRpb25zXCJcbiAgICAgICAgLy8gd2hpY2ggd291bGQgaGFwcGVuIHdpdGggYSBgY2F0Y2hgICsgYHRocm93YFxuICAgICAgICBoYXNFcnJvcmVkID0gZmFsc2U7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBpZiAoaGFzRXJyb3JlZCkge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgY29uc29sZS5lcnJvcihgXFxuXFxuRXJyb3Igb2NjdXJyZWQ6XFxuXFxuJHtyZXNldFRyYWNraW5nKCl9XFxuXFxuYCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZXhlY3V0ZShvcGNvZGVzLCBoYW5kbGVyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9leGVjdXRlKG9wY29kZXM6IFVwZGF0aW5nT3Bjb2RlW10sIGhhbmRsZXI6IEV4Y2VwdGlvbkhhbmRsZXIpIHtcbiAgICBsZXQgeyBmcmFtZVN0YWNrIH0gPSB0aGlzO1xuXG4gICAgdGhpcy50cnkob3Bjb2RlcywgaGFuZGxlcik7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgaWYgKGZyYW1lU3RhY2suaXNFbXB0eSgpKSBicmVhaztcblxuICAgICAgbGV0IG9wY29kZSA9IHRoaXMuZnJhbWUubmV4dFN0YXRlbWVudCgpO1xuXG4gICAgICBpZiAob3Bjb2RlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZnJhbWVTdGFjay5wb3AoKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIG9wY29kZS5ldmFsdWF0ZSh0aGlzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldCBmcmFtZSgpIHtcbiAgICByZXR1cm4gZXhwZWN0KHRoaXMuZnJhbWVTdGFjay5jdXJyZW50LCAnYnVnOiBleHBlY3RlZCBhIGZyYW1lJyk7XG4gIH1cblxuICBnb3RvKGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLmZyYW1lLmdvdG8oaW5kZXgpO1xuICB9XG5cbiAgdHJ5KG9wczogVXBkYXRpbmdPcGNvZGVbXSwgaGFuZGxlcjogT3B0aW9uPEV4Y2VwdGlvbkhhbmRsZXI+KSB7XG4gICAgdGhpcy5mcmFtZVN0YWNrLnB1c2gobmV3IFVwZGF0aW5nVk1GcmFtZShvcHMsIGhhbmRsZXIpKTtcbiAgfVxuXG4gIHRocm93KCkge1xuICAgIHRoaXMuZnJhbWUuaGFuZGxlRXhjZXB0aW9uKCk7XG4gICAgdGhpcy5mcmFtZVN0YWNrLnBvcCgpO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVk1TdGF0ZSB7XG4gIHJlYWRvbmx5IHBjOiBudW1iZXI7XG4gIHJlYWRvbmx5IHNjb3BlOiBTY29wZTtcbiAgcmVhZG9ubHkgZHluYW1pY1Njb3BlOiBEeW5hbWljU2NvcGU7XG4gIHJlYWRvbmx5IHN0YWNrOiB1bmtub3duW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdW1hYmxlVk1TdGF0ZSB7XG4gIHJlc3VtZShydW50aW1lOiBSdW50aW1lQ29udGV4dCwgYnVpbGRlcjogRWxlbWVudEJ1aWxkZXIpOiBJbnRlcm5hbFZNO1xufVxuXG5leHBvcnQgY2xhc3MgUmVzdW1hYmxlVk1TdGF0ZUltcGwgaW1wbGVtZW50cyBSZXN1bWFibGVWTVN0YXRlIHtcbiAgY29uc3RydWN0b3IocmVhZG9ubHkgc3RhdGU6IFZNU3RhdGUsIHByaXZhdGUgcmVzdW1lQ2FsbGJhY2s6IFZtSW5pdENhbGxiYWNrKSB7fVxuXG4gIHJlc3VtZShydW50aW1lOiBSdW50aW1lQ29udGV4dCwgYnVpbGRlcjogRWxlbWVudEJ1aWxkZXIpOiBJbnRlcm5hbFZNIHtcbiAgICByZXR1cm4gdGhpcy5yZXN1bWVDYWxsYmFjayhydW50aW1lLCB0aGlzLnN0YXRlLCBidWlsZGVyKTtcbiAgfVxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmxvY2tPcGNvZGUgaW1wbGVtZW50cyBVcGRhdGluZ09wY29kZSwgQm91bmRzIHtcbiAgcHVibGljIGNoaWxkcmVuOiBVcGRhdGluZ09wY29kZVtdO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBib3VuZHM6IExpdmVCbG9jaztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgc3RhdGU6IFJlc3VtYWJsZVZNU3RhdGUsXG4gICAgcHJvdGVjdGVkIHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LFxuICAgIGJvdW5kczogTGl2ZUJsb2NrLFxuICAgIGNoaWxkcmVuOiBVcGRhdGluZ09wY29kZVtdXG4gICkge1xuICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbjtcbiAgICB0aGlzLmJvdW5kcyA9IGJvdW5kcztcbiAgfVxuXG4gIHBhcmVudEVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuYm91bmRzLnBhcmVudEVsZW1lbnQoKTtcbiAgfVxuXG4gIGZpcnN0Tm9kZSgpIHtcbiAgICByZXR1cm4gdGhpcy5ib3VuZHMuZmlyc3ROb2RlKCk7XG4gIH1cblxuICBsYXN0Tm9kZSgpIHtcbiAgICByZXR1cm4gdGhpcy5ib3VuZHMubGFzdE5vZGUoKTtcbiAgfVxuXG4gIGV2YWx1YXRlKHZtOiBVcGRhdGluZ1ZNSW1wbCkge1xuICAgIHZtLnRyeSh0aGlzLmNoaWxkcmVuLCBudWxsKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgVHJ5T3Bjb2RlIGV4dGVuZHMgQmxvY2tPcGNvZGUgaW1wbGVtZW50cyBFeGNlcHRpb25IYW5kbGVyIHtcbiAgcHVibGljIHR5cGUgPSAndHJ5JztcblxuICBwcm90ZWN0ZWQgYm91bmRzITogVXBkYXRhYmxlQmxvY2s7IC8vIEhpZGVzIHByb3BlcnR5IG9uIGJhc2UgY2xhc3NcblxuICBldmFsdWF0ZSh2bTogVXBkYXRpbmdWTUltcGwpIHtcbiAgICB2bS50cnkodGhpcy5jaGlsZHJlbiwgdGhpcyk7XG4gIH1cblxuICBoYW5kbGVFeGNlcHRpb24oKSB7XG4gICAgbGV0IHsgc3RhdGUsIGJvdW5kcywgcnVudGltZSB9ID0gdGhpcztcblxuICAgIGRlc3Ryb3lDaGlsZHJlbih0aGlzKTtcblxuICAgIGxldCBlbGVtZW50U3RhY2sgPSBOZXdFbGVtZW50QnVpbGRlci5yZXN1bWUocnVudGltZS5lbnYsIGJvdW5kcyk7XG4gICAgbGV0IHZtID0gc3RhdGUucmVzdW1lKHJ1bnRpbWUsIGVsZW1lbnRTdGFjayk7XG5cbiAgICBsZXQgdXBkYXRpbmc6IFVwZGF0aW5nT3Bjb2RlW10gPSBbXTtcbiAgICBsZXQgY2hpbGRyZW4gPSAodGhpcy5jaGlsZHJlbiA9IFtdKTtcblxuICAgIGxldCByZXN1bHQgPSB2bS5leGVjdXRlKCh2bSkgPT4ge1xuICAgICAgdm0ucHVzaFVwZGF0aW5nKHVwZGF0aW5nKTtcbiAgICAgIHZtLnVwZGF0ZVdpdGgodGhpcyk7XG4gICAgICB2bS5wdXNoVXBkYXRpbmcoY2hpbGRyZW4pO1xuICAgIH0pO1xuXG4gICAgYXNzb2NpYXRlRGVzdHJveWFibGVDaGlsZCh0aGlzLCByZXN1bHQuZHJvcCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIExpc3RJdGVtT3Bjb2RlIGV4dGVuZHMgVHJ5T3Bjb2RlIHtcbiAgcHVibGljIHJldGFpbmVkID0gZmFsc2U7XG4gIHB1YmxpYyBpbmRleCA9IC0xO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHN0YXRlOiBSZXN1bWFibGVWTVN0YXRlLFxuICAgIHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LFxuICAgIGJvdW5kczogVXBkYXRhYmxlQmxvY2ssXG4gICAgcHVibGljIGtleTogdW5rbm93bixcbiAgICBwdWJsaWMgbWVtbzogUmVmZXJlbmNlLFxuICAgIHB1YmxpYyB2YWx1ZTogUmVmZXJlbmNlXG4gICkge1xuICAgIHN1cGVyKHN0YXRlLCBydW50aW1lLCBib3VuZHMsIFtdKTtcbiAgfVxuXG4gIHVwZGF0ZVJlZmVyZW5jZXMoaXRlbTogT3BhcXVlSXRlcmF0aW9uSXRlbSkge1xuICAgIHRoaXMucmV0YWluZWQgPSB0cnVlO1xuICAgIHVwZGF0ZVJlZih0aGlzLnZhbHVlLCBpdGVtLnZhbHVlKTtcbiAgICB1cGRhdGVSZWYodGhpcy5tZW1vLCBpdGVtLm1lbW8pO1xuICB9XG5cbiAgc2hvdWxkUmVtb3ZlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5yZXRhaW5lZDtcbiAgfVxuXG4gIHJlc2V0KCkge1xuICAgIHRoaXMucmV0YWluZWQgPSBmYWxzZTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTGlzdEJsb2NrT3Bjb2RlIGV4dGVuZHMgQmxvY2tPcGNvZGUge1xuICBwdWJsaWMgdHlwZSA9ICdsaXN0LWJsb2NrJztcbiAgcHVibGljIGNoaWxkcmVuITogTGlzdEl0ZW1PcGNvZGVbXTtcblxuICBwcml2YXRlIG9wY29kZU1hcCA9IG5ldyBNYXA8dW5rbm93biwgTGlzdEl0ZW1PcGNvZGU+KCk7XG4gIHByaXZhdGUgbWFya2VyOiBTaW1wbGVDb21tZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbGFzdEl0ZXJhdG9yOiBPcGFxdWVJdGVyYXRvcjtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYm91bmRzITogTGl2ZUJsb2NrTGlzdDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzdGF0ZTogUmVzdW1hYmxlVk1TdGF0ZSxcbiAgICBydW50aW1lOiBSdW50aW1lQ29udGV4dCxcbiAgICBib3VuZHM6IExpdmVCbG9ja0xpc3QsXG4gICAgY2hpbGRyZW46IExpc3RJdGVtT3Bjb2RlW10sXG4gICAgcHJpdmF0ZSBpdGVyYWJsZVJlZjogUmVmZXJlbmNlPE9wYXF1ZUl0ZXJhdG9yPlxuICApIHtcbiAgICBzdXBlcihzdGF0ZSwgcnVudGltZSwgYm91bmRzLCBjaGlsZHJlbik7XG4gICAgdGhpcy5sYXN0SXRlcmF0b3IgPSB2YWx1ZUZvclJlZihpdGVyYWJsZVJlZik7XG4gIH1cblxuICBpbml0aWFsaXplQ2hpbGQob3Bjb2RlOiBMaXN0SXRlbU9wY29kZSkge1xuICAgIG9wY29kZS5pbmRleCA9IHRoaXMuY2hpbGRyZW4ubGVuZ3RoIC0gMTtcbiAgICB0aGlzLm9wY29kZU1hcC5zZXQob3Bjb2RlLmtleSwgb3Bjb2RlKTtcbiAgfVxuXG4gIGV2YWx1YXRlKHZtOiBVcGRhdGluZ1ZNSW1wbCkge1xuICAgIGxldCBpdGVyYXRvciA9IHZhbHVlRm9yUmVmKHRoaXMuaXRlcmFibGVSZWYpO1xuXG4gICAgaWYgKHRoaXMubGFzdEl0ZXJhdG9yICE9PSBpdGVyYXRvcikge1xuICAgICAgbGV0IHsgYm91bmRzIH0gPSB0aGlzO1xuICAgICAgbGV0IHsgZG9tIH0gPSB2bTtcblxuICAgICAgbGV0IG1hcmtlciA9ICh0aGlzLm1hcmtlciA9IGRvbS5jcmVhdGVDb21tZW50KCcnKSk7XG4gICAgICBkb20uaW5zZXJ0QWZ0ZXIoXG4gICAgICAgIGJvdW5kcy5wYXJlbnRFbGVtZW50KCksXG4gICAgICAgIG1hcmtlcixcbiAgICAgICAgZXhwZWN0KGJvdW5kcy5sYXN0Tm9kZSgpLCBcImNhbid0IGluc2VydCBhZnRlciBhbiBlbXB0eSBib3VuZHNcIilcbiAgICAgICk7XG5cbiAgICAgIHRoaXMuc3luYyhpdGVyYXRvcik7XG5cbiAgICAgIHRoaXMucGFyZW50RWxlbWVudCgpLnJlbW92ZUNoaWxkKG1hcmtlcik7XG4gICAgICB0aGlzLm1hcmtlciA9IG51bGw7XG4gICAgICB0aGlzLmxhc3RJdGVyYXRvciA9IGl0ZXJhdG9yO1xuICAgIH1cblxuICAgIC8vIFJ1biBub3ctdXBkYXRlZCB1cGRhdGluZyBvcGNvZGVzXG4gICAgc3VwZXIuZXZhbHVhdGUodm0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzeW5jKGl0ZXJhdG9yOiBPcGFxdWVJdGVyYXRvcikge1xuICAgIGxldCB7IG9wY29kZU1hcDogaXRlbU1hcCwgY2hpbGRyZW4gfSA9IHRoaXM7XG5cbiAgICBsZXQgY3VycmVudE9wY29kZUluZGV4ID0gMDtcbiAgICBsZXQgc2VlbkluZGV4ID0gMDtcblxuICAgIHRoaXMuY2hpbGRyZW4gPSB0aGlzLmJvdW5kcy5ib3VuZExpc3QgPSBbXTtcblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBsZXQgaXRlbSA9IGl0ZXJhdG9yLm5leHQoKTtcblxuICAgICAgaWYgKGl0ZW0gPT09IG51bGwpIGJyZWFrO1xuXG4gICAgICBsZXQgb3Bjb2RlID0gY2hpbGRyZW5bY3VycmVudE9wY29kZUluZGV4XTtcbiAgICAgIGxldCB7IGtleSB9ID0gaXRlbTtcblxuICAgICAgLy8gSXRlbXMgdGhhdCBoYXZlIGFscmVhZHkgYmVlbiBmb3VuZCBhbmQgbW92ZWQgd2lsbCBhbHJlYWR5IGJlIHJldGFpbmVkLFxuICAgICAgLy8gd2UgY2FuIGNvbnRpbnVlIHVudGlsIHdlIGZpbmQgdGhlIG5leHQgdW5yZXRhaW5lZCBpdGVtXG4gICAgICB3aGlsZSAob3Bjb2RlICE9PSB1bmRlZmluZWQgJiYgb3Bjb2RlLnJldGFpbmVkID09PSB0cnVlKSB7XG4gICAgICAgIG9wY29kZSA9IGNoaWxkcmVuWysrY3VycmVudE9wY29kZUluZGV4XTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wY29kZSAhPT0gdW5kZWZpbmVkICYmIG9wY29kZS5rZXkgPT09IGtleSkge1xuICAgICAgICB0aGlzLnJldGFpbkl0ZW0ob3Bjb2RlLCBpdGVtKTtcbiAgICAgICAgY3VycmVudE9wY29kZUluZGV4Kys7XG4gICAgICB9IGVsc2UgaWYgKGl0ZW1NYXAuaGFzKGtleSkpIHtcbiAgICAgICAgbGV0IGl0ZW1PcGNvZGUgPSBpdGVtTWFwLmdldChrZXkpITtcblxuICAgICAgICAvLyBUaGUgaXRlbSBvcGNvZGUgd2FzIHNlZW4gYWxyZWFkeSwgc28gd2Ugc2hvdWxkIG1vdmUgaXQuXG4gICAgICAgIGlmIChpdGVtT3Bjb2RlLmluZGV4IDwgc2VlbkluZGV4KSB7XG4gICAgICAgICAgdGhpcy5tb3ZlSXRlbShpdGVtT3Bjb2RlLCBpdGVtLCBvcGNvZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgc2VlbiBpbmRleCwgd2UgYXJlIGdvaW5nIHRvIGJlIG1vdmluZyB0aGlzIGl0ZW0gYXJvdW5kXG4gICAgICAgICAgLy8gc28gYW55IG90aGVyIGl0ZW1zIHRoYXQgY29tZSBiZWZvcmUgaXQgd2lsbCBsaWtlbHkgbmVlZCB0byBtb3ZlIGFzXG4gICAgICAgICAgLy8gd2VsbC5cbiAgICAgICAgICBzZWVuSW5kZXggPSBpdGVtT3Bjb2RlLmluZGV4O1xuXG4gICAgICAgICAgbGV0IHNlZW5VbnJldGFpbmVkID0gZmFsc2U7XG5cbiAgICAgICAgICAvLyBpdGVyYXRlIHRocm91Z2ggYWxsIG9mIHRoZSBvcGNvZGVzIGJldHdlZW4gdGhlIGN1cnJlbnQgcG9zaXRpb24gYW5kXG4gICAgICAgICAgLy8gdGhlIHBvc2l0aW9uIG9mIHRoZSBpdGVtJ3Mgb3Bjb2RlLCBhbmQgZGV0ZXJtaW5lIGlmIHRoZXkgYXJlIGFsbFxuICAgICAgICAgIC8vIHJldGFpbmVkLlxuICAgICAgICAgIGZvciAobGV0IGkgPSBjdXJyZW50T3Bjb2RlSW5kZXggKyAxOyBpIDwgc2VlbkluZGV4OyBpKyspIHtcbiAgICAgICAgICAgIGlmIChjaGlsZHJlbltpXS5yZXRhaW5lZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgc2VlblVucmV0YWluZWQgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBJZiB3ZSBoYXZlIHNlZW4gb25seSByZXRhaW5lZCBvcGNvZGVzIGJldHdlZW4gdGhpcyBhbmQgdGhlIG1hdGNoaW5nXG4gICAgICAgICAgLy8gb3Bjb2RlLCBpdCBtZWFucyB0aGF0IGFsbCB0aGUgb3Bjb2RlcyBpbiBiZXR3ZWVuIGhhdmUgYmVlbiBtb3ZlZFxuICAgICAgICAgIC8vIGFscmVhZHksIGFuZCB3ZSBjYW4gc2FmZWx5IHJldGFpbiB0aGlzIGl0ZW0ncyBvcGNvZGUuXG4gICAgICAgICAgaWYgKHNlZW5VbnJldGFpbmVkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy5yZXRhaW5JdGVtKGl0ZW1PcGNvZGUsIGl0ZW0pO1xuICAgICAgICAgICAgY3VycmVudE9wY29kZUluZGV4ID0gc2VlbkluZGV4ICsgMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5tb3ZlSXRlbShpdGVtT3Bjb2RlLCBpdGVtLCBvcGNvZGUpO1xuICAgICAgICAgICAgY3VycmVudE9wY29kZUluZGV4Kys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmluc2VydEl0ZW0oaXRlbSwgb3Bjb2RlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgb3Bjb2RlID0gY2hpbGRyZW5baV07XG5cbiAgICAgIGlmIChvcGNvZGUucmV0YWluZWQgPT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMuZGVsZXRlSXRlbShvcGNvZGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3Bjb2RlLnJlc2V0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXRhaW5JdGVtKG9wY29kZTogTGlzdEl0ZW1PcGNvZGUsIGl0ZW06IE9wYXF1ZUl0ZXJhdGlvbkl0ZW0pIHtcbiAgICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICAgIGxvZ1N0ZXAhKCdsaXN0LXVwZGF0ZXMnLCBbJ3JldGFpbicsIGl0ZW0ua2V5XSk7XG4gICAgfVxuXG4gICAgbGV0IHsgY2hpbGRyZW4gfSA9IHRoaXM7XG5cbiAgICB1cGRhdGVSZWYob3Bjb2RlLm1lbW8sIGl0ZW0ubWVtbyk7XG4gICAgdXBkYXRlUmVmKG9wY29kZS52YWx1ZSwgaXRlbS52YWx1ZSk7XG4gICAgb3Bjb2RlLnJldGFpbmVkID0gdHJ1ZTtcblxuICAgIG9wY29kZS5pbmRleCA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICBjaGlsZHJlbi5wdXNoKG9wY29kZSk7XG4gIH1cblxuICBwcml2YXRlIGluc2VydEl0ZW0oaXRlbTogT3BhcXVlSXRlcmF0aW9uSXRlbSwgYmVmb3JlOiBMaXN0SXRlbU9wY29kZSkge1xuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbG9nU3RlcCEoJ2xpc3QtdXBkYXRlcycsIFsnaW5zZXJ0JywgaXRlbS5rZXldKTtcbiAgICB9XG5cbiAgICBsZXQgeyBvcGNvZGVNYXAsIGJvdW5kcywgc3RhdGUsIHJ1bnRpbWUsIGNoaWxkcmVuIH0gPSB0aGlzO1xuICAgIGxldCB7IGtleSB9ID0gaXRlbTtcbiAgICBsZXQgbmV4dFNpYmxpbmcgPSBiZWZvcmUgPT09IHVuZGVmaW5lZCA/IHRoaXMubWFya2VyIDogYmVmb3JlLmZpcnN0Tm9kZSgpO1xuXG4gICAgbGV0IGVsZW1lbnRTdGFjayA9IE5ld0VsZW1lbnRCdWlsZGVyLmZvckluaXRpYWxSZW5kZXIocnVudGltZS5lbnYsIHtcbiAgICAgIGVsZW1lbnQ6IGJvdW5kcy5wYXJlbnRFbGVtZW50KCksXG4gICAgICBuZXh0U2libGluZyxcbiAgICB9KTtcblxuICAgIGxldCB2bSA9IHN0YXRlLnJlc3VtZShydW50aW1lLCBlbGVtZW50U3RhY2spO1xuXG4gICAgdm0uZXhlY3V0ZSgodm0pID0+IHtcbiAgICAgIHZtLnB1c2hVcGRhdGluZygpO1xuICAgICAgbGV0IG9wY29kZSA9IHZtLmVudGVySXRlbShpdGVtKTtcblxuICAgICAgb3Bjb2RlLmluZGV4ID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgY2hpbGRyZW4ucHVzaChvcGNvZGUpO1xuICAgICAgb3Bjb2RlTWFwLnNldChrZXksIG9wY29kZSk7XG4gICAgICBhc3NvY2lhdGVEZXN0cm95YWJsZUNoaWxkKHRoaXMsIG9wY29kZSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIG1vdmVJdGVtKG9wY29kZTogTGlzdEl0ZW1PcGNvZGUsIGl0ZW06IE9wYXF1ZUl0ZXJhdGlvbkl0ZW0sIGJlZm9yZTogTGlzdEl0ZW1PcGNvZGUpIHtcbiAgICBsZXQgeyBjaGlsZHJlbiB9ID0gdGhpcztcblxuICAgIHVwZGF0ZVJlZihvcGNvZGUubWVtbywgaXRlbS5tZW1vKTtcbiAgICB1cGRhdGVSZWYob3Bjb2RlLnZhbHVlLCBpdGVtLnZhbHVlKTtcbiAgICBvcGNvZGUucmV0YWluZWQgPSB0cnVlO1xuXG4gICAgbGV0IGN1cnJlbnRTaWJsaW5nLCBuZXh0U2libGluZztcblxuICAgIGlmIChiZWZvcmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbW92ZUJvdW5kcyhvcGNvZGUsIHRoaXMubWFya2VyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3VycmVudFNpYmxpbmcgPSBvcGNvZGUubGFzdE5vZGUoKS5uZXh0U2libGluZztcbiAgICAgIG5leHRTaWJsaW5nID0gYmVmb3JlLmZpcnN0Tm9kZSgpO1xuXG4gICAgICAvLyBJdGVtcyBhcmUgbW92ZWQgdGhyb3VnaG91dCB0aGUgYWxnb3JpdGhtLCBzbyB0aGVyZSBhcmUgY2FzZXMgd2hlcmUgdGhlXG4gICAgICAvLyB0aGUgaXRlbXMgYWxyZWFkeSBoYXBwZW4gdG8gYmUgc2libGluZ3MgKGUuZy4gYW4gaXRlbSBpbiBiZXR3ZWVuIHdhc1xuICAgICAgLy8gbW92ZWQgYmVmb3JlIHRoaXMgbW92ZSBoYXBwZW5lZCkuIENoZWNrIHRvIHNlZSBpZiB0aGV5IGFyZSBzaWJsaW5nc1xuICAgICAgLy8gZmlyc3QgYmVmb3JlIGRvaW5nIHRoZSBtb3ZlLlxuICAgICAgaWYgKGN1cnJlbnRTaWJsaW5nICE9PSBuZXh0U2libGluZykge1xuICAgICAgICBtb3ZlQm91bmRzKG9wY29kZSwgbmV4dFNpYmxpbmcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIG9wY29kZS5pbmRleCA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICBjaGlsZHJlbi5wdXNoKG9wY29kZSk7XG5cbiAgICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICAgIGxldCB0eXBlID0gY3VycmVudFNpYmxpbmcgJiYgY3VycmVudFNpYmxpbmcgPT09IG5leHRTaWJsaW5nID8gJ21vdmUtcmV0YWluJyA6ICdtb3ZlJztcbiAgICAgIGxvZ1N0ZXAhKCdsaXN0LXVwZGF0ZXMnLCBbdHlwZSwgaXRlbS5rZXldKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRlbGV0ZUl0ZW0ob3Bjb2RlOiBMaXN0SXRlbU9wY29kZSkge1xuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbG9nU3RlcCEoJ2xpc3QtdXBkYXRlcycsIFsnZGVsZXRlJywgb3Bjb2RlLmtleV0pO1xuICAgIH1cblxuICAgIGRlc3Ryb3kob3Bjb2RlKTtcbiAgICBjbGVhcihvcGNvZGUpO1xuICAgIHRoaXMub3Bjb2RlTWFwLmRlbGV0ZShvcGNvZGUua2V5KTtcbiAgfVxufVxuXG5jbGFzcyBVcGRhdGluZ1ZNRnJhbWUge1xuICBwcml2YXRlIGN1cnJlbnQgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgb3BzOiBVcGRhdGluZ09wY29kZVtdLCBwcml2YXRlIGV4Y2VwdGlvbkhhbmRsZXI6IE9wdGlvbjxFeGNlcHRpb25IYW5kbGVyPikge31cblxuICBnb3RvKGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLmN1cnJlbnQgPSBpbmRleDtcbiAgfVxuXG4gIG5leHRTdGF0ZW1lbnQoKTogVXBkYXRpbmdPcGNvZGUgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLm9wc1t0aGlzLmN1cnJlbnQrK107XG4gIH1cblxuICBoYW5kbGVFeGNlcHRpb24oKSB7XG4gICAgaWYgKHRoaXMuZXhjZXB0aW9uSGFuZGxlcikge1xuICAgICAgdGhpcy5leGNlcHRpb25IYW5kbGVyLmhhbmRsZUV4Y2VwdGlvbigpO1xuICAgIH1cbiAgfVxufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==