UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

431 lines (349 loc) 38.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ListBlockOpcode = exports.ListItemOpcode = exports.TryOpcode = exports.BlockOpcode = exports.ResumableVMStateImpl = exports.default = void 0; var _env = require("@glimmer/env"); var _reference = require("@glimmer/reference"); var _destroyable = require("@glimmer/destroyable"); var _util = require("@glimmer/util"); var _validator = require("@glimmer/validator"); var _bounds = require("../bounds"); var _elementBuilder = require("./element-builder"); class UpdatingVMImpl { constructor(env, { alwaysRevalidate = false }) { this.frameStack = new _util.Stack(); this.env = env; this.dom = env.getDOM(); this.alwaysRevalidate = alwaysRevalidate; } execute(opcodes, handler) { if (_env.DEBUG) { let hasErrored = true; try { (0, _validator.runInTrackingTransaction)(() => 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${(0, _validator.resetTracking)()}\n\n`); } } } else { this._execute(opcodes, handler); } } _execute(opcodes, handler) { let { frameStack } = this; this.try(opcodes, handler); while (true) { if (frameStack.isEmpty()) break; let opcode = this.frame.nextStatement(); if (opcode === undefined) { frameStack.pop(); continue; } opcode.evaluate(this); } } get frame() { return this.frameStack.current; } goto(index) { this.frame.goto(index); } try(ops, handler) { this.frameStack.push(new UpdatingVMFrame(ops, handler)); } throw() { this.frame.handleException(); this.frameStack.pop(); } } exports.default = UpdatingVMImpl; class ResumableVMStateImpl { constructor(state, resumeCallback) { this.state = state; this.resumeCallback = resumeCallback; } resume(runtime, builder) { return this.resumeCallback(runtime, this.state, builder); } } exports.ResumableVMStateImpl = ResumableVMStateImpl; class BlockOpcode { constructor(state, runtime, bounds, children) { this.state = state; this.runtime = runtime; this.children = children; this.bounds = bounds; } parentElement() { return this.bounds.parentElement(); } firstNode() { return this.bounds.firstNode(); } lastNode() { return this.bounds.lastNode(); } evaluate(vm) { vm.try(this.children, null); } } exports.BlockOpcode = BlockOpcode; class TryOpcode extends BlockOpcode { constructor() { super(...arguments); this.type = 'try'; } evaluate(vm) { vm.try(this.children, this); } handleException() { let { state, bounds, runtime } = this; (0, _destroyable.destroyChildren)(this); let elementStack = _elementBuilder.NewElementBuilder.resume(runtime.env, bounds); let vm = state.resume(runtime, elementStack); let updating = []; let children = this.children = []; let result = vm.execute(vm => { vm.pushUpdating(updating); vm.updateWith(this); vm.pushUpdating(children); }); (0, _destroyable.associateDestroyableChild)(this, result.drop); } } exports.TryOpcode = TryOpcode; class ListItemOpcode extends TryOpcode { constructor(state, runtime, bounds, key, memo, value) { super(state, runtime, bounds, []); this.key = key; this.memo = memo; this.value = value; this.retained = false; this.index = -1; } updateReferences(item) { this.retained = true; (0, _reference.updateRef)(this.value, item.value); (0, _reference.updateRef)(this.memo, item.memo); } shouldRemove() { return !this.retained; } reset() { this.retained = false; } } exports.ListItemOpcode = ListItemOpcode; class ListBlockOpcode extends BlockOpcode { constructor(state, runtime, bounds, children, iterableRef) { super(state, runtime, bounds, children); this.iterableRef = iterableRef; this.type = 'list-block'; this.opcodeMap = new Map(); this.marker = null; this.lastIterator = (0, _reference.valueForRef)(iterableRef); } initializeChild(opcode) { opcode.index = this.children.length - 1; this.opcodeMap.set(opcode.key, opcode); } evaluate(vm) { let iterator = (0, _reference.valueForRef)(this.iterableRef); if (this.lastIterator !== iterator) { let { bounds } = this; let { dom } = vm; let 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 super.evaluate(vm); } sync(iterator) { let { opcodeMap: itemMap, children } = this; let currentOpcodeIndex = 0; let seenIndex = 0; this.children = this.bounds.boundList = []; while (true) { let item = iterator.next(); if (item === null) break; let opcode = children[currentOpcodeIndex]; let { key } = item; // 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)) { let 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; let 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 (let 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 (let i = 0; i < children.length; i++) { let opcode = children[i]; if (opcode.retained === false) { this.deleteItem(opcode); } else { opcode.reset(); } } } retainItem(opcode, item) { if (false /* LOCAL_DEBUG */ ) { (0, _util.logStep)('list-updates', ['retain', item.key]); } let { children } = this; (0, _reference.updateRef)(opcode.memo, item.memo); (0, _reference.updateRef)(opcode.value, item.value); opcode.retained = true; opcode.index = children.length; children.push(opcode); } insertItem(item, before) { if (false /* LOCAL_DEBUG */ ) { (0, _util.logStep)('list-updates', ['insert', item.key]); } let { opcodeMap, bounds, state, runtime, children } = this; let { key } = item; let nextSibling = before === undefined ? this.marker : before.firstNode(); let elementStack = _elementBuilder.NewElementBuilder.forInitialRender(runtime.env, { element: bounds.parentElement(), nextSibling }); let vm = state.resume(runtime, elementStack); vm.execute(vm => { vm.pushUpdating(); let opcode = vm.enterItem(item); opcode.index = children.length; children.push(opcode); opcodeMap.set(key, opcode); (0, _destroyable.associateDestroyableChild)(this, opcode); }); } moveItem(opcode, item, before) { let { children } = this; (0, _reference.updateRef)(opcode.memo, item.memo); (0, _reference.updateRef)(opcode.value, item.value); opcode.retained = true; let currentSibling, nextSibling; if (before === undefined) { (0, _bounds.move)(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) { (0, _bounds.move)(opcode, nextSibling); } } opcode.index = children.length; children.push(opcode); if (false /* LOCAL_DEBUG */ ) { let type = currentSibling && currentSibling === nextSibling ? 'move-retain' : 'move'; (0, _util.logStep)('list-updates', [type, item.key]); } } deleteItem(opcode) { if (false /* LOCAL_DEBUG */ ) { (0, _util.logStep)('list-updates', ['delete', opcode.key]); } (0, _destroyable.destroy)(opcode); (0, _bounds.clear)(opcode); this.opcodeMap.delete(opcode.key); } } exports.ListBlockOpcode = ListBlockOpcode; class UpdatingVMFrame { constructor(ops, exceptionHandler) { this.ops = ops; this.exceptionHandler = exceptionHandler; this.current = 0; } goto(index) { this.current = index; } nextStatement() { return this.ops[this.current++]; } handleException() { if (this.exceptionHandler) { this.exceptionHandler.handleException(); } } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL3VwZGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBaUJBOztBQU9BOztBQUNBOztBQUNBOztBQUVBOztBQUVBOztBQUVjLE1BQUEsY0FBQSxDQUFxQjtBQU9qQyxFQUFBLFdBQUEsQ0FBQSxHQUFBLEVBQThCO0FBQUUsSUFBQSxnQkFBZ0IsR0FBRztBQUFyQixHQUE5QixFQUEwRDtBQUZsRCxTQUFBLFVBQUEsR0FBcUMsSUFBckMsV0FBcUMsRUFBckM7QUFHTixTQUFBLEdBQUEsR0FBQSxHQUFBO0FBQ0EsU0FBQSxHQUFBLEdBQVcsR0FBRyxDQUFkLE1BQVcsRUFBWDtBQUNBLFNBQUEsZ0JBQUEsR0FBQSxnQkFBQTtBQUNEOztBQUVELEVBQUEsT0FBTyxDQUFBLE9BQUEsRUFBQSxPQUFBLEVBQXFEO0FBQzFELFFBQUEsVUFBQSxFQUFXO0FBQ1QsVUFBSSxVQUFVLEdBQWQsSUFBQTs7QUFDQSxVQUFJO0FBQ0YsaURBQTBCLE1BQU0sS0FBQSxRQUFBLENBQUEsT0FBQSxFQUFQLE9BQU8sQ0FBaEMsRUFERSxvQkFDRixFQURFLENBR0Y7QUFDQTs7QUFDQSxRQUFBLFVBQVUsR0FBVixLQUFBO0FBTEYsT0FBQSxTQU1VO0FBQ1IsWUFBQSxVQUFBLEVBQWdCO0FBQ2Q7QUFDQSxVQUFBLE9BQU8sQ0FBUCxLQUFBLENBQWMsMEJBQTBCLCtCQUF4QyxNQUFBO0FBQ0Q7QUFDRjtBQWJILEtBQUEsTUFjTztBQUNMLFdBQUEsUUFBQSxDQUFBLE9BQUEsRUFBQSxPQUFBO0FBQ0Q7QUFDRjs7QUFFTyxFQUFBLFFBQVEsQ0FBQSxPQUFBLEVBQUEsT0FBQSxFQUFxRDtBQUNuRSxRQUFJO0FBQUUsTUFBQTtBQUFGLFFBQUosSUFBQTtBQUVBLFNBQUEsR0FBQSxDQUFBLE9BQUEsRUFBQSxPQUFBOztBQUVBLFdBQUEsSUFBQSxFQUFhO0FBQ1gsVUFBSSxVQUFV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Q0FBekI7QUFDRDs7QUFFRCw4QkFBQSxNQUFBO0FBQ0EsdUJBQUEsTUFBQTtBQUNBLFNBQUEsU0FBQSxDQUFBLE1BQUEsQ0FBc0IsTUFBTSxDQUE1QixHQUFBO0FBQ0Q7O0FBbE42Qzs7OztBQXFOaEQsTUFBQSxlQUFBLENBQXFCO0FBR25CLEVBQUEsV0FBQSxDQUFBLEdBQUEsRUFBQSxnQkFBQSxFQUE2RjtBQUF6RSxTQUFBLEdBQUEsR0FBQSxHQUFBO0FBQStCLFNBQUEsZ0JBQUEsR0FBQSxnQkFBQTtBQUYzQyxTQUFBLE9BQUEsR0FBQSxDQUFBO0FBRXlGOztBQUVqRyxFQUFBLElBQUksQ0FBQSxLQUFBLEVBQWM7QUFDaEIsU0FBQSxPQUFBLEdBQUEsS0FBQTtBQUNEOztBQUVELEVBQUEsYUFBYSxHQUFBO0FBQ1gsV0FBTyxLQUFBLEdBQUEsQ0FBUyxLQUFoQixPQUFnQixFQUFULENBQVA7QUFDRDs7QUFFRCxFQUFBLGVBQWUsR0FBQTtBQUNiLFFBQUksS0FBSixnQkFBQSxFQUEyQjtBQUN6QixXQUFBLGdCQUFBLENBQUEsZUFBQTtBQUNEO0FBQ0Y7O0FBakJrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERFQlVHIH0gZnJvbSAnQGdsaW1tZXIvZW52JztcbmltcG9ydCB7XG4gIEJvdW5kcyxcbiAgRHluYW1pY1Njb3BlLFxuICBFbGVtZW50QnVpbGRlcixcbiAgRW52aXJvbm1lbnQsXG4gIEV4Y2VwdGlvbkhhbmRsZXIsXG4gIEdsaW1tZXJUcmVlQ2hhbmdlcyxcbiAgTGl2ZUJsb2NrLFxuICBPcHRpb24sXG4gIFJ1bnRpbWVDb250ZXh0LFxuICBTY29wZSxcbiAgVXBkYXRhYmxlQmxvY2ssXG4gIFVwZGF0aW5nVk0sXG4gIFVwZGF0aW5nT3Bjb2RlLFxufSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IExPQ0FMX0RFQlVHIH0gZnJvbSAnQGdsaW1tZXIvbG9jYWwtZGVidWctZmxhZ3MnO1xuaW1wb3J0IHtcbiAgT3BhcXVlSXRlcmF0aW9uSXRlbSxcbiAgT3BhcXVlSXRlcmF0b3IsXG4gIFJlZmVyZW5jZSxcbiAgdXBkYXRlUmVmLFxuICB2YWx1ZUZvclJlZixcbn0gZnJvbSAnQGdsaW1tZXIvcmVmZXJlbmNlJztcbmltcG9ydCB7IGFzc29jaWF0ZURlc3Ryb3lhYmxlQ2hpbGQsIGRlc3Ryb3ksIGRlc3Ryb3lDaGlsZHJlbiB9IGZyb20gJ0BnbGltbWVyL2Rlc3Ryb3lhYmxlJztcbmltcG9ydCB7IGV4cGVjdCwgU3RhY2ssIGxvZ1N0ZXAgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7IHJlc2V0VHJhY2tpbmcsIHJ1bkluVHJhY2tpbmdUcmFuc2FjdGlvbiB9IGZyb20gJ0BnbGltbWVyL3ZhbGlkYXRvcic7XG5pbXBvcnQgeyBTaW1wbGVDb21tZW50IH0gZnJvbSAnQHNpbXBsZS1kb20vaW50ZXJmYWNlJztcbmltcG9ydCB7IGNsZWFyLCBtb3ZlIGFzIG1vdmVCb3VuZHMgfSBmcm9tICcuLi9ib3VuZHMnO1xuaW1wb3J0IHsgSW50ZXJuYWxWTSwgVm1Jbml0Q2FsbGJhY2sgfSBmcm9tICcuL2FwcGVuZCc7XG5pbXBvcnQgeyBMaXZlQmxvY2tMaXN0LCBOZXdFbGVtZW50QnVpbGRlciB9IGZyb20gJy4vZWxlbWVudC1idWlsZGVyJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVXBkYXRpbmdWTUltcGwgaW1wbGVtZW50cyBVcGRhdGluZ1ZNIHtcbiAgcHVibGljIGVudjogRW52aXJvbm1lbnQ7XG4gIHB1YmxpYyBkb206IEdsaW1tZXJUcmVlQ2hhbmdlcztcbiAgcHVibGljIGFsd2F5c1JldmFsaWRhdGU6IGJvb2xlYW47XG5cbiAgcHJpdmF0ZSBmcmFtZVN0YWNrOiBTdGFjazxVcGRhdGluZ1ZNRnJhbWU+ID0gbmV3IFN0YWNrPFVwZGF0aW5nVk1GcmFtZT4oKTtcblxuICBjb25zdHJ1Y3RvcihlbnY6IEVudmlyb25tZW50LCB7IGFsd2F5c1JldmFsaWRhdGUgPSBmYWxzZSB9KSB7XG4gICAgdGhpcy5lbnYgPSBlbnY7XG4gICAgdGhpcy5kb20gPSBlbnYuZ2V0RE9NKCk7XG4gICAgdGhpcy5hbHdheXNSZXZhbGlkYXRlID0gYWx3YXlzUmV2YWxpZGF0ZTtcbiAgfVxuXG4gIGV4ZWN1dGUob3Bjb2RlczogVXBkYXRpbmdPcGNvZGVbXSwgaGFuZGxlcjogRXhjZXB0aW9uSGFuZGxlcikge1xuICAgIGlmIChERUJVRykge1xuICAgICAgbGV0IGhhc0Vycm9yZWQgPSB0cnVlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcnVuSW5UcmFja2luZ1RyYW5zYWN0aW9uISgoKSA9PiB0aGlzLl9leGVjdXRlKG9wY29kZXMsIGhhbmRsZXIpLCAnLSBXaGlsZSByZW5kZXJpbmc6Jyk7XG5cbiAgICAgICAgLy8gdXNpbmcgYSBib29sZWFuIGhlcmUgdG8gYXZvaWQgYnJlYWtpbmcgZXJnb25vbWljcyBvZiBcInBhdXNlIG9uIHVuY2F1Z2h0IGV4Y2VwdGlvbnNcIlxuICAgICAgICAvLyB3aGljaCB3b3VsZCBoYXBwZW4gd2l0aCBhIGBjYXRjaGAgKyBgdGhyb3dgXG4gICAgICAgIGhhc0Vycm9yZWQgPSBmYWxzZTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGlmIChoYXNFcnJvcmVkKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBcXG5cXG5FcnJvciBvY2N1cnJlZDpcXG5cXG4ke3Jlc2V0VHJhY2tpbmcoKX1cXG5cXG5gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9leGVjdXRlKG9wY29kZXMsIGhhbmRsZXIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2V4ZWN1dGUob3Bjb2RlczogVXBkYXRpbmdPcGNvZGVbXSwgaGFuZGxlcjogRXhjZXB0aW9uSGFuZGxlcikge1xuICAgIGxldCB7IGZyYW1lU3RhY2sgfSA9IHRoaXM7XG5cbiAgICB0aGlzLnRyeShvcGNvZGVzLCBoYW5kbGVyKTtcblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBpZiAoZnJhbWVTdGFjay5pc0VtcHR5KCkpIGJyZWFrO1xuXG4gICAgICBsZXQgb3Bjb2RlID0gdGhpcy5mcmFtZS5uZXh0U3RhdGVtZW50KCk7XG5cbiAgICAgIGlmIChvcGNvZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBmcmFtZVN0YWNrLnBvcCgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgb3Bjb2RlLmV2YWx1YXRlKHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGZyYW1lKCkge1xuICAgIHJldHVybiBleHBlY3QodGhpcy5mcmFtZVN0YWNrLmN1cnJlbnQsICdidWc6IGV4cGVjdGVkIGEgZnJhbWUnKTtcbiAgfVxuXG4gIGdvdG8oaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuZnJhbWUuZ290byhpbmRleCk7XG4gIH1cblxuICB0cnkob3BzOiBVcGRhdGluZ09wY29kZVtdLCBoYW5kbGVyOiBPcHRpb248RXhjZXB0aW9uSGFuZGxlcj4pIHtcbiAgICB0aGlzLmZyYW1lU3RhY2sucHVzaChuZXcgVXBkYXRpbmdWTUZyYW1lKG9wcywgaGFuZGxlcikpO1xuICB9XG5cbiAgdGhyb3coKSB7XG4gICAgdGhpcy5mcmFtZS5oYW5kbGVFeGNlcHRpb24oKTtcbiAgICB0aGlzLmZyYW1lU3RhY2sucG9wKCk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBWTVN0YXRlIHtcbiAgcmVhZG9ubHkgcGM6IG51bWJlcjtcbiAgcmVhZG9ubHkgc2NvcGU6IFNjb3BlO1xuICByZWFkb25seSBkeW5hbWljU2NvcGU6IER5bmFtaWNTY29wZTtcbiAgcmVhZG9ubHkgc3RhY2s6IHVua25vd25bXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXN1bWFibGVWTVN0YXRlIHtcbiAgcmVzdW1lKHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LCBidWlsZGVyOiBFbGVtZW50QnVpbGRlcik6IEludGVybmFsVk07XG59XG5cbmV4cG9ydCBjbGFzcyBSZXN1bWFibGVWTVN0YXRlSW1wbCBpbXBsZW1lbnRzIFJlc3VtYWJsZVZNU3RhdGUge1xuICBjb25zdHJ1Y3RvcihyZWFkb25seSBzdGF0ZTogVk1TdGF0ZSwgcHJpdmF0ZSByZXN1bWVDYWxsYmFjazogVm1Jbml0Q2FsbGJhY2spIHt9XG5cbiAgcmVzdW1lKHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LCBidWlsZGVyOiBFbGVtZW50QnVpbGRlcik6IEludGVybmFsVk0ge1xuICAgIHJldHVybiB0aGlzLnJlc3VtZUNhbGxiYWNrKHJ1bnRpbWUsIHRoaXMuc3RhdGUsIGJ1aWxkZXIpO1xuICB9XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCbG9ja09wY29kZSBpbXBsZW1lbnRzIFVwZGF0aW5nT3Bjb2RlLCBCb3VuZHMge1xuICBwdWJsaWMgY2hpbGRyZW46IFVwZGF0aW5nT3Bjb2RlW107XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGJvdW5kczogTGl2ZUJsb2NrO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBzdGF0ZTogUmVzdW1hYmxlVk1TdGF0ZSxcbiAgICBwcm90ZWN0ZWQgcnVudGltZTogUnVudGltZUNvbnRleHQsXG4gICAgYm91bmRzOiBMaXZlQmxvY2ssXG4gICAgY2hpbGRyZW46IFVwZGF0aW5nT3Bjb2RlW11cbiAgKSB7XG4gICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuO1xuICAgIHRoaXMuYm91bmRzID0gYm91bmRzO1xuICB9XG5cbiAgcGFyZW50RWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5ib3VuZHMucGFyZW50RWxlbWVudCgpO1xuICB9XG5cbiAgZmlyc3ROb2RlKCkge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5maXJzdE5vZGUoKTtcbiAgfVxuXG4gIGxhc3ROb2RlKCkge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5sYXN0Tm9kZSgpO1xuICB9XG5cbiAgZXZhbHVhdGUodm06IFVwZGF0aW5nVk1JbXBsKSB7XG4gICAgdm0udHJ5KHRoaXMuY2hpbGRyZW4sIG51bGwpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUcnlPcGNvZGUgZXh0ZW5kcyBCbG9ja09wY29kZSBpbXBsZW1lbnRzIEV4Y2VwdGlvbkhhbmRsZXIge1xuICBwdWJsaWMgdHlwZSA9ICd0cnknO1xuXG4gIHByb3RlY3RlZCBib3VuZHMhOiBVcGRhdGFibGVCbG9jazsgLy8gSGlkZXMgcHJvcGVydHkgb24gYmFzZSBjbGFzc1xuXG4gIGV2YWx1YXRlKHZtOiBVcGRhdGluZ1ZNSW1wbCkge1xuICAgIHZtLnRyeSh0aGlzLmNoaWxkcmVuLCB0aGlzKTtcbiAgfVxuXG4gIGhhbmRsZUV4Y2VwdGlvbigpIHtcbiAgICBsZXQgeyBzdGF0ZSwgYm91bmRzLCBydW50aW1lIH0gPSB0aGlzO1xuXG4gICAgZGVzdHJveUNoaWxkcmVuKHRoaXMpO1xuXG4gICAgbGV0IGVsZW1lbnRTdGFjayA9IE5ld0VsZW1lbnRCdWlsZGVyLnJlc3VtZShydW50aW1lLmVudiwgYm91bmRzKTtcbiAgICBsZXQgdm0gPSBzdGF0ZS5yZXN1bWUocnVudGltZSwgZWxlbWVudFN0YWNrKTtcblxuICAgIGxldCB1cGRhdGluZzogVXBkYXRpbmdPcGNvZGVbXSA9IFtdO1xuICAgIGxldCBjaGlsZHJlbiA9ICh0aGlzLmNoaWxkcmVuID0gW10pO1xuXG4gICAgbGV0IHJlc3VsdCA9IHZtLmV4ZWN1dGUoKHZtKSA9PiB7XG4gICAgICB2bS5wdXNoVXBkYXRpbmcodXBkYXRpbmcpO1xuICAgICAgdm0udXBkYXRlV2l0aCh0aGlzKTtcbiAgICAgIHZtLnB1c2hVcGRhdGluZyhjaGlsZHJlbik7XG4gICAgfSk7XG5cbiAgICBhc3NvY2lhdGVEZXN0cm95YWJsZUNoaWxkKHRoaXMsIHJlc3VsdC5kcm9wKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTGlzdEl0ZW1PcGNvZGUgZXh0ZW5kcyBUcnlPcGNvZGUge1xuICBwdWJsaWMgcmV0YWluZWQgPSBmYWxzZTtcbiAgcHVibGljIGluZGV4ID0gLTE7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc3RhdGU6IFJlc3VtYWJsZVZNU3RhdGUsXG4gICAgcnVudGltZTogUnVudGltZUNvbnRleHQsXG4gICAgYm91bmRzOiBVcGRhdGFibGVCbG9jayxcbiAgICBwdWJsaWMga2V5OiB1bmtub3duLFxuICAgIHB1YmxpYyBtZW1vOiBSZWZlcmVuY2UsXG4gICAgcHVibGljIHZhbHVlOiBSZWZlcmVuY2VcbiAgKSB7XG4gICAgc3VwZXIoc3RhdGUsIHJ1bnRpbWUsIGJvdW5kcywgW10pO1xuICB9XG5cbiAgdXBkYXRlUmVmZXJlbmNlcyhpdGVtOiBPcGFxdWVJdGVyYXRpb25JdGVtKSB7XG4gICAgdGhpcy5yZXRhaW5lZCA9IHRydWU7XG4gICAgdXBkYXRlUmVmKHRoaXMudmFsdWUsIGl0ZW0udmFsdWUpO1xuICAgIHVwZGF0ZVJlZih0aGlzLm1lbW8sIGl0ZW0ubWVtbyk7XG4gIH1cblxuICBzaG91bGRSZW1vdmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLnJldGFpbmVkO1xuICB9XG5cbiAgcmVzZXQoKSB7XG4gICAgdGhpcy5yZXRhaW5lZCA9IGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBMaXN0QmxvY2tPcGNvZGUgZXh0ZW5kcyBCbG9ja09wY29kZSB7XG4gIHB1YmxpYyB0eXBlID0gJ2xpc3QtYmxvY2snO1xuICBwdWJsaWMgY2hpbGRyZW4hOiBMaXN0SXRlbU9wY29kZVtdO1xuXG4gIHByaXZhdGUgb3Bjb2RlTWFwID0gbmV3IE1hcDx1bmtub3duLCBMaXN0SXRlbU9wY29kZT4oKTtcbiAgcHJpdmF0ZSBtYXJrZXI6IFNpbXBsZUNvbW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsYXN0SXRlcmF0b3I6IE9wYXF1ZUl0ZXJhdG9yO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBib3VuZHMhOiBMaXZlQmxvY2tMaXN0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHN0YXRlOiBSZXN1bWFibGVWTVN0YXRlLFxuICAgIHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LFxuICAgIGJvdW5kczogTGl2ZUJsb2NrTGlzdCxcbiAgICBjaGlsZHJlbjogTGlzdEl0ZW1PcGNvZGVbXSxcbiAgICBwcml2YXRlIGl0ZXJhYmxlUmVmOiBSZWZlcmVuY2U8T3BhcXVlSXRlcmF0b3I+XG4gICkge1xuICAgIHN1cGVyKHN0YXRlLCBydW50aW1lLCBib3VuZHMsIGNoaWxkcmVuKTtcbiAgICB0aGlzLmxhc3RJdGVyYXRvciA9IHZhbHVlRm9yUmVmKGl0ZXJhYmxlUmVmKTtcbiAgfVxuXG4gIGluaXRpYWxpemVDaGlsZChvcGNvZGU6IExpc3RJdGVtT3Bjb2RlKSB7XG4gICAgb3Bjb2RlLmluZGV4ID0gdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxO1xuICAgIHRoaXMub3Bjb2RlTWFwLnNldChvcGNvZGUua2V5LCBvcGNvZGUpO1xuICB9XG5cbiAgZXZhbHVhdGUodm06IFVwZGF0aW5nVk1JbXBsKSB7XG4gICAgbGV0IGl0ZXJhdG9yID0gdmFsdWVGb3JSZWYodGhpcy5pdGVyYWJsZVJlZik7XG5cbiAgICBpZiAodGhpcy5sYXN0SXRlcmF0b3IgIT09IGl0ZXJhdG9yKSB7XG4gICAgICBsZXQgeyBib3VuZHMgfSA9IHRoaXM7XG4gICAgICBsZXQgeyBkb20gfSA9IHZtO1xuXG4gICAgICBsZXQgbWFya2VyID0gKHRoaXMubWFya2VyID0gZG9tLmNyZWF0ZUNvbW1lbnQoJycpKTtcbiAgICAgIGRvbS5pbnNlcnRBZnRlcihcbiAgICAgICAgYm91bmRzLnBhcmVudEVsZW1lbnQoKSxcbiAgICAgICAgbWFya2VyLFxuICAgICAgICBleHBlY3QoYm91bmRzLmxhc3ROb2RlKCksIFwiY2FuJ3QgaW5zZXJ0IGFmdGVyIGFuIGVtcHR5IGJvdW5kc1wiKVxuICAgICAgKTtcblxuICAgICAgdGhpcy5zeW5jKGl0ZXJhdG9yKTtcblxuICAgICAgdGhpcy5wYXJlbnRFbGVtZW50KCkucmVtb3ZlQ2hpbGQobWFya2VyKTtcbiAgICAgIHRoaXMubWFya2VyID0gbnVsbDtcbiAgICAgIHRoaXMubGFzdEl0ZXJhdG9yID0gaXRlcmF0b3I7XG4gICAgfVxuXG4gICAgLy8gUnVuIG5vdy11cGRhdGVkIHVwZGF0aW5nIG9wY29kZXNcbiAgICBzdXBlci5ldmFsdWF0ZSh2bSk7XG4gIH1cblxuICBwcml2YXRlIHN5bmMoaXRlcmF0b3I6IE9wYXF1ZUl0ZXJhdG9yKSB7XG4gICAgbGV0IHsgb3Bjb2RlTWFwOiBpdGVtTWFwLCBjaGlsZHJlbiB9ID0gdGhpcztcblxuICAgIGxldCBjdXJyZW50T3Bjb2RlSW5kZXggPSAwO1xuICAgIGxldCBzZWVuSW5kZXggPSAwO1xuXG4gICAgdGhpcy5jaGlsZHJlbiA9IHRoaXMuYm91bmRzLmJvdW5kTGlzdCA9IFtdO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGxldCBpdGVtID0gaXRlcmF0b3IubmV4dCgpO1xuXG4gICAgICBpZiAoaXRlbSA9PT0gbnVsbCkgYnJlYWs7XG5cbiAgICAgIGxldCBvcGNvZGUgPSBjaGlsZHJlbltjdXJyZW50T3Bjb2RlSW5kZXhdO1xuICAgICAgbGV0IHsga2V5IH0gPSBpdGVtO1xuXG4gICAgICAvLyBJdGVtcyB0aGF0IGhhdmUgYWxyZWFkeSBiZWVuIGZvdW5kIGFuZCBtb3ZlZCB3aWxsIGFscmVhZHkgYmUgcmV0YWluZWQsXG4gICAgICAvLyB3ZSBjYW4gY29udGludWUgdW50aWwgd2UgZmluZCB0aGUgbmV4dCB1bnJldGFpbmVkIGl0ZW1cbiAgICAgIHdoaWxlIChvcGNvZGUgIT09IHVuZGVmaW5lZCAmJiBvcGNvZGUucmV0YWluZWQgPT09IHRydWUpIHtcbiAgICAgICAgb3Bjb2RlID0gY2hpbGRyZW5bKytjdXJyZW50T3Bjb2RlSW5kZXhdO1xuICAgICAgfVxuXG4gICAgICBpZiAob3Bjb2RlICE9PSB1bmRlZmluZWQgJiYgb3Bjb2RlLmtleSA9PT0ga2V5KSB7XG4gICAgICAgIHRoaXMucmV0YWluSXRlbShvcGNvZGUsIGl0ZW0pO1xuICAgICAgICBjdXJyZW50T3Bjb2RlSW5kZXgrKztcbiAgICAgIH0gZWxzZSBpZiAoaXRlbU1hcC5oYXMoa2V5KSkge1xuICAgICAgICBsZXQgaXRlbU9wY29kZSA9IGl0ZW1NYXAuZ2V0KGtleSkhO1xuXG4gICAgICAgIC8vIFRoZSBpdGVtIG9wY29kZSB3YXMgc2VlbiBhbHJlYWR5LCBzbyB3ZSBzaG91bGQgbW92ZSBpdC5cbiAgICAgICAgaWYgKGl0ZW1PcGNvZGUuaW5kZXggPCBzZWVuSW5kZXgpIHtcbiAgICAgICAgICB0aGlzLm1vdmVJdGVtKGl0ZW1PcGNvZGUsIGl0ZW0sIG9wY29kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVXBkYXRlIHRoZSBzZWVuIGluZGV4LCB3ZSBhcmUgZ29pbmcgdG8gYmUgbW92aW5nIHRoaXMgaXRlbSBhcm91bmRcbiAgICAgICAgICAvLyBzbyBhbnkgb3RoZXIgaXRlbXMgdGhhdCBjb21lIGJlZm9yZSBpdCB3aWxsIGxpa2VseSBuZWVkIHRvIG1vdmUgYXNcbiAgICAgICAgICAvLyB3ZWxsLlxuICAgICAgICAgIHNlZW5JbmRleCA9IGl0ZW1PcGNvZGUuaW5kZXg7XG5cbiAgICAgICAgICBsZXQgc2VlblVucmV0YWluZWQgPSBmYWxzZTtcblxuICAgICAgICAgIC8vIGl0ZXJhdGUgdGhyb3VnaCBhbGwgb2YgdGhlIG9wY29kZXMgYmV0d2VlbiB0aGUgY3VycmVudCBwb3NpdGlvbiBhbmRcbiAgICAgICAgICAvLyB0aGUgcG9zaXRpb24gb2YgdGhlIGl0ZW0ncyBvcGNvZGUsIGFuZCBkZXRlcm1pbmUgaWYgdGhleSBhcmUgYWxsXG4gICAgICAgICAgLy8gcmV0YWluZWQuXG4gICAgICAgICAgZm9yIChsZXQgaSA9IGN1cnJlbnRPcGNvZGVJbmRleCArIDE7IGkgPCBzZWVuSW5kZXg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGNoaWxkcmVuW2ldLnJldGFpbmVkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICBzZWVuVW5yZXRhaW5lZCA9IHRydWU7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIElmIHdlIGhhdmUgc2VlbiBvbmx5IHJldGFpbmVkIG9wY29kZXMgYmV0d2VlbiB0aGlzIGFuZCB0aGUgbWF0Y2hpbmdcbiAgICAgICAgICAvLyBvcGNvZGUsIGl0IG1lYW5zIHRoYXQgYWxsIHRoZSBvcGNvZGVzIGluIGJldHdlZW4gaGF2ZSBiZWVuIG1vdmVkXG4gICAgICAgICAgLy8gYWxyZWFkeSwgYW5kIHdlIGNhbiBzYWZlbHkgcmV0YWluIHRoaXMgaXRlbSdzIG9wY29kZS5cbiAgICAgICAgICBpZiAoc2VlblVucmV0YWluZWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICB0aGlzLnJldGFpbkl0ZW0oaXRlbU9wY29kZSwgaXRlbSk7XG4gICAgICAgICAgICBjdXJyZW50T3Bjb2RlSW5kZXggPSBzZWVuSW5kZXggKyAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm1vdmVJdGVtKGl0ZW1PcGNvZGUsIGl0ZW0sIG9wY29kZSk7XG4gICAgICAgICAgICBjdXJyZW50T3Bjb2RlSW5kZXgrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW5zZXJ0SXRlbShpdGVtLCBvcGNvZGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBvcGNvZGUgPSBjaGlsZHJlbltpXTtcblxuICAgICAgaWYgKG9wY29kZS5yZXRhaW5lZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5kZWxldGVJdGVtKG9wY29kZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcGNvZGUucmVzZXQoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJldGFpbkl0ZW0ob3Bjb2RlOiBMaXN0SXRlbU9wY29kZSwgaXRlbTogT3BhcXVlSXRlcmF0aW9uSXRlbSkge1xuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbG9nU3RlcCEoJ2xpc3QtdXBkYXRlcycsIFsncmV0YWluJywgaXRlbS5rZXldKTtcbiAgICB9XG5cbiAgICBsZXQgeyBjaGlsZHJlbiB9ID0gdGhpcztcblxuICAgIHVwZGF0ZVJlZihvcGNvZGUubWVtbywgaXRlbS5tZW1vKTtcbiAgICB1cGRhdGVSZWYob3Bjb2RlLnZhbHVlLCBpdGVtLnZhbHVlKTtcbiAgICBvcGNvZGUucmV0YWluZWQgPSB0cnVlO1xuXG4gICAgb3Bjb2RlLmluZGV4ID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIGNoaWxkcmVuLnB1c2gob3Bjb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgaW5zZXJ0SXRlbShpdGVtOiBPcGFxdWVJdGVyYXRpb25JdGVtLCBiZWZvcmU6IExpc3RJdGVtT3Bjb2RlKSB7XG4gICAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgICBsb2dTdGVwISgnbGlzdC11cGRhdGVzJywgWydpbnNlcnQnLCBpdGVtLmtleV0pO1xuICAgIH1cblxuICAgIGxldCB7IG9wY29kZU1hcCwgYm91bmRzLCBzdGF0ZSwgcnVudGltZSwgY2hpbGRyZW4gfSA9IHRoaXM7XG4gICAgbGV0IHsga2V5IH0gPSBpdGVtO1xuICAgIGxldCBuZXh0U2libGluZyA9IGJlZm9yZSA9PT0gdW5kZWZpbmVkID8gdGhpcy5tYXJrZXIgOiBiZWZvcmUuZmlyc3ROb2RlKCk7XG5cbiAgICBsZXQgZWxlbWVudFN0YWNrID0gTmV3RWxlbWVudEJ1aWxkZXIuZm9ySW5pdGlhbFJlbmRlcihydW50aW1lLmVudiwge1xuICAgICAgZWxlbWVudDogYm91bmRzLnBhcmVudEVsZW1lbnQoKSxcbiAgICAgIG5leHRTaWJsaW5nLFxuICAgIH0pO1xuXG4gICAgbGV0IHZtID0gc3RhdGUucmVzdW1lKHJ1bnRpbWUsIGVsZW1lbnRTdGFjayk7XG5cbiAgICB2bS5leGVjdXRlKCh2bSkgPT4ge1xuICAgICAgdm0ucHVzaFVwZGF0aW5nKCk7XG4gICAgICBsZXQgb3Bjb2RlID0gdm0uZW50ZXJJdGVtKGl0ZW0pO1xuXG4gICAgICBvcGNvZGUuaW5kZXggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICBjaGlsZHJlbi5wdXNoKG9wY29kZSk7XG4gICAgICBvcGNvZGVNYXAuc2V0KGtleSwgb3Bjb2RlKTtcbiAgICAgIGFzc29jaWF0ZURlc3Ryb3lhYmxlQ2hpbGQodGhpcywgb3Bjb2RlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbW92ZUl0ZW0ob3Bjb2RlOiBMaXN0SXRlbU9wY29kZSwgaXRlbTogT3BhcXVlSXRlcmF0aW9uSXRlbSwgYmVmb3JlOiBMaXN0SXRlbU9wY29kZSkge1xuICAgIGxldCB7IGNoaWxkcmVuIH0gPSB0aGlzO1xuXG4gICAgdXBkYXRlUmVmKG9wY29kZS5tZW1vLCBpdGVtLm1lbW8pO1xuICAgIHVwZGF0ZVJlZihvcGNvZGUudmFsdWUsIGl0ZW0udmFsdWUpO1xuICAgIG9wY29kZS5yZXRhaW5lZCA9IHRydWU7XG5cbiAgICBsZXQgY3VycmVudFNpYmxpbmcsIG5leHRTaWJsaW5nO1xuXG4gICAgaWYgKGJlZm9yZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBtb3ZlQm91bmRzKG9wY29kZSwgdGhpcy5tYXJrZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjdXJyZW50U2libGluZyA9IG9wY29kZS5sYXN0Tm9kZSgpLm5leHRTaWJsaW5nO1xuICAgICAgbmV4dFNpYmxpbmcgPSBiZWZvcmUuZmlyc3ROb2RlKCk7XG5cbiAgICAgIC8vIEl0ZW1zIGFyZSBtb3ZlZCB0aHJvdWdob3V0IHRoZSBhbGdvcml0aG0sIHNvIHRoZXJlIGFyZSBjYXNlcyB3aGVyZSB0aGVcbiAgICAgIC8vIHRoZSBpdGVtcyBhbHJlYWR5IGhhcHBlbiB0byBiZSBzaWJsaW5ncyAoZS5nLiBhbiBpdGVtIGluIGJldHdlZW4gd2FzXG4gICAgICAvLyBtb3ZlZCBiZWZvcmUgdGhpcyBtb3ZlIGhhcHBlbmVkKS4gQ2hlY2sgdG8gc2VlIGlmIHRoZXkgYXJlIHNpYmxpbmdzXG4gICAgICAvLyBmaXJzdCBiZWZvcmUgZG9pbmcgdGhlIG1vdmUuXG4gICAgICBpZiAoY3VycmVudFNpYmxpbmcgIT09IG5leHRTaWJsaW5nKSB7XG4gICAgICAgIG1vdmVCb3VuZHMob3Bjb2RlLCBuZXh0U2libGluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgb3Bjb2RlLmluZGV4ID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIGNoaWxkcmVuLnB1c2gob3Bjb2RlKTtcblxuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbGV0IHR5cGUgPSBjdXJyZW50U2libGluZyAmJiBjdXJyZW50U2libGluZyA9PT0gbmV4dFNpYmxpbmcgPyAnbW92ZS1yZXRhaW4nIDogJ21vdmUnO1xuICAgICAgbG9nU3RlcCEoJ2xpc3QtdXBkYXRlcycsIFt0eXBlLCBpdGVtLmtleV0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZGVsZXRlSXRlbShvcGNvZGU6IExpc3RJdGVtT3Bjb2RlKSB7XG4gICAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgICBsb2dTdGVwISgnbGlzdC11cGRhdGVzJywgWydkZWxldGUnLCBvcGNvZGUua2V5XSk7XG4gICAgfVxuXG4gICAgZGVzdHJveShvcGNvZGUpO1xuICAgIGNsZWFyKG9wY29kZSk7XG4gICAgdGhpcy5vcGNvZGVNYXAuZGVsZXRlKG9wY29kZS5rZXkpO1xuICB9XG59XG5cbmNsYXNzIFVwZGF0aW5nVk1GcmFtZSB7XG4gIHByaXZhdGUgY3VycmVudCA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBvcHM6IFVwZGF0aW5nT3Bjb2RlW10sIHByaXZhdGUgZXhjZXB0aW9uSGFuZGxlcjogT3B0aW9uPEV4Y2VwdGlvbkhhbmRsZXI+KSB7fVxuXG4gIGdvdG8oaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuY3VycmVudCA9IGluZGV4O1xuICB9XG5cbiAgbmV4dFN0YXRlbWVudCgpOiBVcGRhdGluZ09wY29kZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMub3BzW3RoaXMuY3VycmVudCsrXTtcbiAgfVxuXG4gIGhhbmRsZUV4Y2VwdGlvbigpIHtcbiAgICBpZiAodGhpcy5leGNlcHRpb25IYW5kbGVyKSB7XG4gICAgICB0aGlzLmV4Y2VwdGlvbkhhbmRsZXIuaGFuZGxlRXhjZXB0aW9uKCk7XG4gICAgfVxuICB9XG59XG4iXSwic291cmNlUm9vdCI6IiJ9