@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
396 lines (338 loc) • 38.6 kB
JavaScript
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';
export default class UpdatingVMImpl {
constructor(env, {
alwaysRevalidate = false
}) {
this.frameStack = new Stack();
this.env = env;
this.dom = env.getDOM();
this.alwaysRevalidate = alwaysRevalidate;
}
execute(opcodes, handler) {
if (DEBUG) {
let hasErrored = true;
try {
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${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();
}
}
export class ResumableVMStateImpl {
constructor(state, resumeCallback) {
this.state = state;
this.resumeCallback = resumeCallback;
}
resume(runtime, builder) {
return this.resumeCallback(runtime, this.state, builder);
}
}
export 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);
}
}
export class TryOpcode extends BlockOpcode {
constructor() {
super(...arguments);
this.type = 'try';
}
evaluate(vm) {
vm.try(this.children, this);
}
handleException() {
let {
state,
bounds,
runtime
} = this;
destroyChildren(this);
let elementStack = 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);
});
associateDestroyableChild(this, result.drop);
}
}
export 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;
updateRef(this.value, item.value);
updateRef(this.memo, item.memo);
}
shouldRemove() {
return !this.retained;
}
reset() {
this.retained = false;
}
}
export 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 = valueForRef(iterableRef);
}
initializeChild(opcode) {
opcode.index = this.children.length - 1;
this.opcodeMap.set(opcode.key, opcode);
}
evaluate(vm) {
let iterator = 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 */
) {
logStep('list-updates', ['retain', item.key]);
}
let {
children
} = this;
updateRef(opcode.memo, item.memo);
updateRef(opcode.value, item.value);
opcode.retained = true;
opcode.index = children.length;
children.push(opcode);
}
insertItem(item, before) {
if (false
/* LOCAL_DEBUG */
) {
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 = 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);
associateDestroyableChild(this, opcode);
});
}
moveItem(opcode, item, before) {
let {
children
} = this;
updateRef(opcode.memo, item.memo);
updateRef(opcode.value, item.value);
opcode.retained = true;
let 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 */
) {
let type = currentSibling && currentSibling === nextSibling ? 'move-retain' : 'move';
logStep('list-updates', [type, item.key]);
}
}
deleteItem(opcode) {
if (false
/* LOCAL_DEBUG */
) {
logStep('list-updates', ['delete', opcode.key]);
}
destroy(opcode);
clear(opcode);
this.opcodeMap.delete(opcode.key);
}
}
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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL3ZtL3VwZGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUFTLEtBQVQsUUFBc0IsY0FBdEI7QUFpQkEsU0FJRSxTQUpGLEVBS0UsV0FMRixRQU1PLG9CQU5QO0FBT0EsU0FBUyx5QkFBVCxFQUFvQyxPQUFwQyxFQUE2QyxlQUE3QyxRQUFvRSxzQkFBcEU7QUFDQSxTQUFpQixLQUFqQixFQUF3QixPQUF4QixRQUF1QyxlQUF2QztBQUNBLFNBQVMsYUFBVCxFQUF3Qix3QkFBeEIsUUFBd0Qsb0JBQXhEO0FBRUEsU0FBUyxLQUFULEVBQWdCLElBQUksSUFBSSxVQUF4QixRQUEwQyxXQUExQztBQUVBLFNBQXdCLGlCQUF4QixRQUFpRCxtQkFBakQ7QUFFQSxlQUFjLE1BQU8sY0FBUCxDQUFxQjtBQU9qQyxFQUFBLFdBQUEsQ0FBWSxHQUFaLEVBQThCO0FBQUUsSUFBQSxnQkFBZ0IsR0FBRztBQUFyQixHQUE5QixFQUEwRDtBQUZsRCxTQUFBLFVBQUEsR0FBcUMsSUFBSSxLQUFKLEVBQXJDO0FBR04sU0FBSyxHQUFMLEdBQVcsR0FBWDtBQUNBLFNBQUssR0FBTCxHQUFXLEdBQUcsQ0FBQyxNQUFKLEVBQVg7QUFDQSxTQUFLLGdCQUFMLEdBQXdCLGdCQUF4QjtBQUNEOztBQUVELEVBQUEsT0FBTyxDQUFDLE9BQUQsRUFBNEIsT0FBNUIsRUFBcUQ7QUFDMUQsUUFBSSxLQUFKLEVBQVc7QUFDVCxVQUFJLFVBQVUsR0FBRyxJQUFqQjs7QUFDQSxVQUFJO0FBQ0YsUUFBQSx3QkFBeUIsQ0FBQyxNQUFNLEtBQUssUUFBTCxDQUFjLE9BQWQsRUFBdUIsT0FBdkIsQ0FBUCxFQUF3QyxvQkFBeEMsQ0FBekIsQ0FERSxDQUdGO0FBQ0E7O0FBQ0EsUUFBQSxVQUFVLEdBQUcsS0FBYjtBQUNELE9BTkQsU0FNVTtBQUNSLFlBQUksVUFBSixFQUFnQjtBQUNkO0FBQ0EsVUFBQSxP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QUFBLElBQUksQ0FBQyxLQUFELEVBQWM7QUFDaEIsU0FBSyxPQUFMLEdBQWUsS0FBZjtBQUNEOztBQUVELEVBQUEsYUFBYSxHQUFBO0FBQ1gsV0FBTyxLQUFLLEdBQUwsQ0FBUyxLQUFLLE9BQUwsRUFBVCxDQUFQO0FBQ0Q7O0FBRUQsRUFBQSxlQUFlLEdBQUE7QUFDYixRQUFJLEtBQUssZ0JBQVQsRUFBMkI7QUFDekIsV0FBSyxnQkFBTCxDQUFzQixlQUF0QjtBQUNEO0FBQ0Y7O0FBakJrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERFQlVHIH0gZnJvbSAnQGdsaW1tZXIvZW52JztcbmltcG9ydCB7XG4gIEJvdW5kcyxcbiAgRHluYW1pY1Njb3BlLFxuICBFbGVtZW50QnVpbGRlcixcbiAgRW52aXJvbm1lbnQsXG4gIEV4Y2VwdGlvbkhhbmRsZXIsXG4gIEdsaW1tZXJUcmVlQ2hhbmdlcyxcbiAgTGl2ZUJsb2NrLFxuICBPcHRpb24sXG4gIFJ1bnRpbWVDb250ZXh0LFxuICBTY29wZSxcbiAgVXBkYXRhYmxlQmxvY2ssXG4gIFVwZGF0aW5nVk0sXG4gIFVwZGF0aW5nT3Bjb2RlLFxufSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IExPQ0FMX0RFQlVHIH0gZnJvbSAnQGdsaW1tZXIvbG9jYWwtZGVidWctZmxhZ3MnO1xuaW1wb3J0IHtcbiAgT3BhcXVlSXRlcmF0aW9uSXRlbSxcbiAgT3BhcXVlSXRlcmF0b3IsXG4gIFJlZmVyZW5jZSxcbiAgdXBkYXRlUmVmLFxuICB2YWx1ZUZvclJlZixcbn0gZnJvbSAnQGdsaW1tZXIvcmVmZXJlbmNlJztcbmltcG9ydCB7IGFzc29jaWF0ZURlc3Ryb3lhYmxlQ2hpbGQsIGRlc3Ryb3ksIGRlc3Ryb3lDaGlsZHJlbiB9IGZyb20gJ0BnbGltbWVyL2Rlc3Ryb3lhYmxlJztcbmltcG9ydCB7IGV4cGVjdCwgU3RhY2ssIGxvZ1N0ZXAgfSBmcm9tICdAZ2xpbW1lci91dGlsJztcbmltcG9ydCB7IHJlc2V0VHJhY2tpbmcsIHJ1bkluVHJhY2tpbmdUcmFuc2FjdGlvbiB9IGZyb20gJ0BnbGltbWVyL3ZhbGlkYXRvcic7XG5pbXBvcnQgeyBTaW1wbGVDb21tZW50IH0gZnJvbSAnQHNpbXBsZS1kb20vaW50ZXJmYWNlJztcbmltcG9ydCB7IGNsZWFyLCBtb3ZlIGFzIG1vdmVCb3VuZHMgfSBmcm9tICcuLi9ib3VuZHMnO1xuaW1wb3J0IHsgSW50ZXJuYWxWTSwgVm1Jbml0Q2FsbGJhY2sgfSBmcm9tICcuL2FwcGVuZCc7XG5pbXBvcnQgeyBMaXZlQmxvY2tMaXN0LCBOZXdFbGVtZW50QnVpbGRlciB9IGZyb20gJy4vZWxlbWVudC1idWlsZGVyJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVXBkYXRpbmdWTUltcGwgaW1wbGVtZW50cyBVcGRhdGluZ1ZNIHtcbiAgcHVibGljIGVudjogRW52aXJvbm1lbnQ7XG4gIHB1YmxpYyBkb206IEdsaW1tZXJUcmVlQ2hhbmdlcztcbiAgcHVibGljIGFsd2F5c1JldmFsaWRhdGU6IGJvb2xlYW47XG5cbiAgcHJpdmF0ZSBmcmFtZVN0YWNrOiBTdGFjazxVcGRhdGluZ1ZNRnJhbWU+ID0gbmV3IFN0YWNrPFVwZGF0aW5nVk1GcmFtZT4oKTtcblxuICBjb25zdHJ1Y3RvcihlbnY6IEVudmlyb25tZW50LCB7IGFsd2F5c1JldmFsaWRhdGUgPSBmYWxzZSB9KSB7XG4gICAgdGhpcy5lbnYgPSBlbnY7XG4gICAgdGhpcy5kb20gPSBlbnYuZ2V0RE9NKCk7XG4gICAgdGhpcy5hbHdheXNSZXZhbGlkYXRlID0gYWx3YXlzUmV2YWxpZGF0ZTtcbiAgfVxuXG4gIGV4ZWN1dGUob3Bjb2RlczogVXBkYXRpbmdPcGNvZGVbXSwgaGFuZGxlcjogRXhjZXB0aW9uSGFuZGxlcikge1xuICAgIGlmIChERUJVRykge1xuICAgICAgbGV0IGhhc0Vycm9yZWQgPSB0cnVlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcnVuSW5UcmFja2luZ1RyYW5zYWN0aW9uISgoKSA9PiB0aGlzLl9leGVjdXRlKG9wY29kZXMsIGhhbmRsZXIpLCAnLSBXaGlsZSByZW5kZXJpbmc6Jyk7XG5cbiAgICAgICAgLy8gdXNpbmcgYSBib29sZWFuIGhlcmUgdG8gYXZvaWQgYnJlYWtpbmcgZXJnb25vbWljcyBvZiBcInBhdXNlIG9uIHVuY2F1Z2h0IGV4Y2VwdGlvbnNcIlxuICAgICAgICAvLyB3aGljaCB3b3VsZCBoYXBwZW4gd2l0aCBhIGBjYXRjaGAgKyBgdGhyb3dgXG4gICAgICAgIGhhc0Vycm9yZWQgPSBmYWxzZTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGlmIChoYXNFcnJvcmVkKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGBcXG5cXG5FcnJvciBvY2N1cnJlZDpcXG5cXG4ke3Jlc2V0VHJhY2tpbmcoKX1cXG5cXG5gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9leGVjdXRlKG9wY29kZXMsIGhhbmRsZXIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2V4ZWN1dGUob3Bjb2RlczogVXBkYXRpbmdPcGNvZGVbXSwgaGFuZGxlcjogRXhjZXB0aW9uSGFuZGxlcikge1xuICAgIGxldCB7IGZyYW1lU3RhY2sgfSA9IHRoaXM7XG5cbiAgICB0aGlzLnRyeShvcGNvZGVzLCBoYW5kbGVyKTtcblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBpZiAoZnJhbWVTdGFjay5pc0VtcHR5KCkpIGJyZWFrO1xuXG4gICAgICBsZXQgb3Bjb2RlID0gdGhpcy5mcmFtZS5uZXh0U3RhdGVtZW50KCk7XG5cbiAgICAgIGlmIChvcGNvZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBmcmFtZVN0YWNrLnBvcCgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgb3Bjb2RlLmV2YWx1YXRlKHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGZyYW1lKCkge1xuICAgIHJldHVybiBleHBlY3QodGhpcy5mcmFtZVN0YWNrLmN1cnJlbnQsICdidWc6IGV4cGVjdGVkIGEgZnJhbWUnKTtcbiAgfVxuXG4gIGdvdG8oaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuZnJhbWUuZ290byhpbmRleCk7XG4gIH1cblxuICB0cnkob3BzOiBVcGRhdGluZ09wY29kZVtdLCBoYW5kbGVyOiBPcHRpb248RXhjZXB0aW9uSGFuZGxlcj4pIHtcbiAgICB0aGlzLmZyYW1lU3RhY2sucHVzaChuZXcgVXBkYXRpbmdWTUZyYW1lKG9wcywgaGFuZGxlcikpO1xuICB9XG5cbiAgdGhyb3coKSB7XG4gICAgdGhpcy5mcmFtZS5oYW5kbGVFeGNlcHRpb24oKTtcbiAgICB0aGlzLmZyYW1lU3RhY2sucG9wKCk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBWTVN0YXRlIHtcbiAgcmVhZG9ubHkgcGM6IG51bWJlcjtcbiAgcmVhZG9ubHkgc2NvcGU6IFNjb3BlO1xuICByZWFkb25seSBkeW5hbWljU2NvcGU6IER5bmFtaWNTY29wZTtcbiAgcmVhZG9ubHkgc3RhY2s6IHVua25vd25bXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXN1bWFibGVWTVN0YXRlIHtcbiAgcmVzdW1lKHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LCBidWlsZGVyOiBFbGVtZW50QnVpbGRlcik6IEludGVybmFsVk07XG59XG5cbmV4cG9ydCBjbGFzcyBSZXN1bWFibGVWTVN0YXRlSW1wbCBpbXBsZW1lbnRzIFJlc3VtYWJsZVZNU3RhdGUge1xuICBjb25zdHJ1Y3RvcihyZWFkb25seSBzdGF0ZTogVk1TdGF0ZSwgcHJpdmF0ZSByZXN1bWVDYWxsYmFjazogVm1Jbml0Q2FsbGJhY2spIHt9XG5cbiAgcmVzdW1lKHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LCBidWlsZGVyOiBFbGVtZW50QnVpbGRlcik6IEludGVybmFsVk0ge1xuICAgIHJldHVybiB0aGlzLnJlc3VtZUNhbGxiYWNrKHJ1bnRpbWUsIHRoaXMuc3RhdGUsIGJ1aWxkZXIpO1xuICB9XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCbG9ja09wY29kZSBpbXBsZW1lbnRzIFVwZGF0aW5nT3Bjb2RlLCBCb3VuZHMge1xuICBwdWJsaWMgY2hpbGRyZW46IFVwZGF0aW5nT3Bjb2RlW107XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGJvdW5kczogTGl2ZUJsb2NrO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBzdGF0ZTogUmVzdW1hYmxlVk1TdGF0ZSxcbiAgICBwcm90ZWN0ZWQgcnVudGltZTogUnVudGltZUNvbnRleHQsXG4gICAgYm91bmRzOiBMaXZlQmxvY2ssXG4gICAgY2hpbGRyZW46IFVwZGF0aW5nT3Bjb2RlW11cbiAgKSB7XG4gICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuO1xuICAgIHRoaXMuYm91bmRzID0gYm91bmRzO1xuICB9XG5cbiAgcGFyZW50RWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5ib3VuZHMucGFyZW50RWxlbWVudCgpO1xuICB9XG5cbiAgZmlyc3ROb2RlKCkge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5maXJzdE5vZGUoKTtcbiAgfVxuXG4gIGxhc3ROb2RlKCkge1xuICAgIHJldHVybiB0aGlzLmJvdW5kcy5sYXN0Tm9kZSgpO1xuICB9XG5cbiAgZXZhbHVhdGUodm06IFVwZGF0aW5nVk1JbXBsKSB7XG4gICAgdm0udHJ5KHRoaXMuY2hpbGRyZW4sIG51bGwpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUcnlPcGNvZGUgZXh0ZW5kcyBCbG9ja09wY29kZSBpbXBsZW1lbnRzIEV4Y2VwdGlvbkhhbmRsZXIge1xuICBwdWJsaWMgdHlwZSA9ICd0cnknO1xuXG4gIHByb3RlY3RlZCBib3VuZHMhOiBVcGRhdGFibGVCbG9jazsgLy8gSGlkZXMgcHJvcGVydHkgb24gYmFzZSBjbGFzc1xuXG4gIGV2YWx1YXRlKHZtOiBVcGRhdGluZ1ZNSW1wbCkge1xuICAgIHZtLnRyeSh0aGlzLmNoaWxkcmVuLCB0aGlzKTtcbiAgfVxuXG4gIGhhbmRsZUV4Y2VwdGlvbigpIHtcbiAgICBsZXQgeyBzdGF0ZSwgYm91bmRzLCBydW50aW1lIH0gPSB0aGlzO1xuXG4gICAgZGVzdHJveUNoaWxkcmVuKHRoaXMpO1xuXG4gICAgbGV0IGVsZW1lbnRTdGFjayA9IE5ld0VsZW1lbnRCdWlsZGVyLnJlc3VtZShydW50aW1lLmVudiwgYm91bmRzKTtcbiAgICBsZXQgdm0gPSBzdGF0ZS5yZXN1bWUocnVudGltZSwgZWxlbWVudFN0YWNrKTtcblxuICAgIGxldCB1cGRhdGluZzogVXBkYXRpbmdPcGNvZGVbXSA9IFtdO1xuICAgIGxldCBjaGlsZHJlbiA9ICh0aGlzLmNoaWxkcmVuID0gW10pO1xuXG4gICAgbGV0IHJlc3VsdCA9IHZtLmV4ZWN1dGUoKHZtKSA9PiB7XG4gICAgICB2bS5wdXNoVXBkYXRpbmcodXBkYXRpbmcpO1xuICAgICAgdm0udXBkYXRlV2l0aCh0aGlzKTtcbiAgICAgIHZtLnB1c2hVcGRhdGluZyhjaGlsZHJlbik7XG4gICAgfSk7XG5cbiAgICBhc3NvY2lhdGVEZXN0cm95YWJsZUNoaWxkKHRoaXMsIHJlc3VsdC5kcm9wKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTGlzdEl0ZW1PcGNvZGUgZXh0ZW5kcyBUcnlPcGNvZGUge1xuICBwdWJsaWMgcmV0YWluZWQgPSBmYWxzZTtcbiAgcHVibGljIGluZGV4ID0gLTE7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc3RhdGU6IFJlc3VtYWJsZVZNU3RhdGUsXG4gICAgcnVudGltZTogUnVudGltZUNvbnRleHQsXG4gICAgYm91bmRzOiBVcGRhdGFibGVCbG9jayxcbiAgICBwdWJsaWMga2V5OiB1bmtub3duLFxuICAgIHB1YmxpYyBtZW1vOiBSZWZlcmVuY2UsXG4gICAgcHVibGljIHZhbHVlOiBSZWZlcmVuY2VcbiAgKSB7XG4gICAgc3VwZXIoc3RhdGUsIHJ1bnRpbWUsIGJvdW5kcywgW10pO1xuICB9XG5cbiAgdXBkYXRlUmVmZXJlbmNlcyhpdGVtOiBPcGFxdWVJdGVyYXRpb25JdGVtKSB7XG4gICAgdGhpcy5yZXRhaW5lZCA9IHRydWU7XG4gICAgdXBkYXRlUmVmKHRoaXMudmFsdWUsIGl0ZW0udmFsdWUpO1xuICAgIHVwZGF0ZVJlZih0aGlzLm1lbW8sIGl0ZW0ubWVtbyk7XG4gIH1cblxuICBzaG91bGRSZW1vdmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLnJldGFpbmVkO1xuICB9XG5cbiAgcmVzZXQoKSB7XG4gICAgdGhpcy5yZXRhaW5lZCA9IGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBMaXN0QmxvY2tPcGNvZGUgZXh0ZW5kcyBCbG9ja09wY29kZSB7XG4gIHB1YmxpYyB0eXBlID0gJ2xpc3QtYmxvY2snO1xuICBwdWJsaWMgY2hpbGRyZW4hOiBMaXN0SXRlbU9wY29kZVtdO1xuXG4gIHByaXZhdGUgb3Bjb2RlTWFwID0gbmV3IE1hcDx1bmtub3duLCBMaXN0SXRlbU9wY29kZT4oKTtcbiAgcHJpdmF0ZSBtYXJrZXI6IFNpbXBsZUNvbW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsYXN0SXRlcmF0b3I6IE9wYXF1ZUl0ZXJhdG9yO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBib3VuZHMhOiBMaXZlQmxvY2tMaXN0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHN0YXRlOiBSZXN1bWFibGVWTVN0YXRlLFxuICAgIHJ1bnRpbWU6IFJ1bnRpbWVDb250ZXh0LFxuICAgIGJvdW5kczogTGl2ZUJsb2NrTGlzdCxcbiAgICBjaGlsZHJlbjogTGlzdEl0ZW1PcGNvZGVbXSxcbiAgICBwcml2YXRlIGl0ZXJhYmxlUmVmOiBSZWZlcmVuY2U8T3BhcXVlSXRlcmF0b3I+XG4gICkge1xuICAgIHN1cGVyKHN0YXRlLCBydW50aW1lLCBib3VuZHMsIGNoaWxkcmVuKTtcbiAgICB0aGlzLmxhc3RJdGVyYXRvciA9IHZhbHVlRm9yUmVmKGl0ZXJhYmxlUmVmKTtcbiAgfVxuXG4gIGluaXRpYWxpemVDaGlsZChvcGNvZGU6IExpc3RJdGVtT3Bjb2RlKSB7XG4gICAgb3Bjb2RlLmluZGV4ID0gdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxO1xuICAgIHRoaXMub3Bjb2RlTWFwLnNldChvcGNvZGUua2V5LCBvcGNvZGUpO1xuICB9XG5cbiAgZXZhbHVhdGUodm06IFVwZGF0aW5nVk1JbXBsKSB7XG4gICAgbGV0IGl0ZXJhdG9yID0gdmFsdWVGb3JSZWYodGhpcy5pdGVyYWJsZVJlZik7XG5cbiAgICBpZiAodGhpcy5sYXN0SXRlcmF0b3IgIT09IGl0ZXJhdG9yKSB7XG4gICAgICBsZXQgeyBib3VuZHMgfSA9IHRoaXM7XG4gICAgICBsZXQgeyBkb20gfSA9IHZtO1xuXG4gICAgICBsZXQgbWFya2VyID0gKHRoaXMubWFya2VyID0gZG9tLmNyZWF0ZUNvbW1lbnQoJycpKTtcbiAgICAgIGRvbS5pbnNlcnRBZnRlcihcbiAgICAgICAgYm91bmRzLnBhcmVudEVsZW1lbnQoKSxcbiAgICAgICAgbWFya2VyLFxuICAgICAgICBleHBlY3QoYm91bmRzLmxhc3ROb2RlKCksIFwiY2FuJ3QgaW5zZXJ0IGFmdGVyIGFuIGVtcHR5IGJvdW5kc1wiKVxuICAgICAgKTtcblxuICAgICAgdGhpcy5zeW5jKGl0ZXJhdG9yKTtcblxuICAgICAgdGhpcy5wYXJlbnRFbGVtZW50KCkucmVtb3ZlQ2hpbGQobWFya2VyKTtcbiAgICAgIHRoaXMubWFya2VyID0gbnVsbDtcbiAgICAgIHRoaXMubGFzdEl0ZXJhdG9yID0gaXRlcmF0b3I7XG4gICAgfVxuXG4gICAgLy8gUnVuIG5vdy11cGRhdGVkIHVwZGF0aW5nIG9wY29kZXNcbiAgICBzdXBlci5ldmFsdWF0ZSh2bSk7XG4gIH1cblxuICBwcml2YXRlIHN5bmMoaXRlcmF0b3I6IE9wYXF1ZUl0ZXJhdG9yKSB7XG4gICAgbGV0IHsgb3Bjb2RlTWFwOiBpdGVtTWFwLCBjaGlsZHJlbiB9ID0gdGhpcztcblxuICAgIGxldCBjdXJyZW50T3Bjb2RlSW5kZXggPSAwO1xuICAgIGxldCBzZWVuSW5kZXggPSAwO1xuXG4gICAgdGhpcy5jaGlsZHJlbiA9IHRoaXMuYm91bmRzLmJvdW5kTGlzdCA9IFtdO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGxldCBpdGVtID0gaXRlcmF0b3IubmV4dCgpO1xuXG4gICAgICBpZiAoaXRlbSA9PT0gbnVsbCkgYnJlYWs7XG5cbiAgICAgIGxldCBvcGNvZGUgPSBjaGlsZHJlbltjdXJyZW50T3Bjb2RlSW5kZXhdO1xuICAgICAgbGV0IHsga2V5IH0gPSBpdGVtO1xuXG4gICAgICAvLyBJdGVtcyB0aGF0IGhhdmUgYWxyZWFkeSBiZWVuIGZvdW5kIGFuZCBtb3ZlZCB3aWxsIGFscmVhZHkgYmUgcmV0YWluZWQsXG4gICAgICAvLyB3ZSBjYW4gY29udGludWUgdW50aWwgd2UgZmluZCB0aGUgbmV4dCB1bnJldGFpbmVkIGl0ZW1cbiAgICAgIHdoaWxlIChvcGNvZGUgIT09IHVuZGVmaW5lZCAmJiBvcGNvZGUucmV0YWluZWQgPT09IHRydWUpIHtcbiAgICAgICAgb3Bjb2RlID0gY2hpbGRyZW5bKytjdXJyZW50T3Bjb2RlSW5kZXhdO1xuICAgICAgfVxuXG4gICAgICBpZiAob3Bjb2RlICE9PSB1bmRlZmluZWQgJiYgb3Bjb2RlLmtleSA9PT0ga2V5KSB7XG4gICAgICAgIHRoaXMucmV0YWluSXRlbShvcGNvZGUsIGl0ZW0pO1xuICAgICAgICBjdXJyZW50T3Bjb2RlSW5kZXgrKztcbiAgICAgIH0gZWxzZSBpZiAoaXRlbU1hcC5oYXMoa2V5KSkge1xuICAgICAgICBsZXQgaXRlbU9wY29kZSA9IGl0ZW1NYXAuZ2V0KGtleSkhO1xuXG4gICAgICAgIC8vIFRoZSBpdGVtIG9wY29kZSB3YXMgc2VlbiBhbHJlYWR5LCBzbyB3ZSBzaG91bGQgbW92ZSBpdC5cbiAgICAgICAgaWYgKGl0ZW1PcGNvZGUuaW5kZXggPCBzZWVuSW5kZXgpIHtcbiAgICAgICAgICB0aGlzLm1vdmVJdGVtKGl0ZW1PcGNvZGUsIGl0ZW0sIG9wY29kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gVXBkYXRlIHRoZSBzZWVuIGluZGV4LCB3ZSBhcmUgZ29pbmcgdG8gYmUgbW92aW5nIHRoaXMgaXRlbSBhcm91bmRcbiAgICAgICAgICAvLyBzbyBhbnkgb3RoZXIgaXRlbXMgdGhhdCBjb21lIGJlZm9yZSBpdCB3aWxsIGxpa2VseSBuZWVkIHRvIG1vdmUgYXNcbiAgICAgICAgICAvLyB3ZWxsLlxuICAgICAgICAgIHNlZW5JbmRleCA9IGl0ZW1PcGNvZGUuaW5kZXg7XG5cbiAgICAgICAgICBsZXQgc2VlblVucmV0YWluZWQgPSBmYWxzZTtcblxuICAgICAgICAgIC8vIGl0ZXJhdGUgdGhyb3VnaCBhbGwgb2YgdGhlIG9wY29kZXMgYmV0d2VlbiB0aGUgY3VycmVudCBwb3NpdGlvbiBhbmRcbiAgICAgICAgICAvLyB0aGUgcG9zaXRpb24gb2YgdGhlIGl0ZW0ncyBvcGNvZGUsIGFuZCBkZXRlcm1pbmUgaWYgdGhleSBhcmUgYWxsXG4gICAgICAgICAgLy8gcmV0YWluZWQuXG4gICAgICAgICAgZm9yIChsZXQgaSA9IGN1cnJlbnRPcGNvZGVJbmRleCArIDE7IGkgPCBzZWVuSW5kZXg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGNoaWxkcmVuW2ldLnJldGFpbmVkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICBzZWVuVW5yZXRhaW5lZCA9IHRydWU7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIElmIHdlIGhhdmUgc2VlbiBvbmx5IHJldGFpbmVkIG9wY29kZXMgYmV0d2VlbiB0aGlzIGFuZCB0aGUgbWF0Y2hpbmdcbiAgICAgICAgICAvLyBvcGNvZGUsIGl0IG1lYW5zIHRoYXQgYWxsIHRoZSBvcGNvZGVzIGluIGJldHdlZW4gaGF2ZSBiZWVuIG1vdmVkXG4gICAgICAgICAgLy8gYWxyZWFkeSwgYW5kIHdlIGNhbiBzYWZlbHkgcmV0YWluIHRoaXMgaXRlbSdzIG9wY29kZS5cbiAgICAgICAgICBpZiAoc2VlblVucmV0YWluZWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICB0aGlzLnJldGFpbkl0ZW0oaXRlbU9wY29kZSwgaXRlbSk7XG4gICAgICAgICAgICBjdXJyZW50T3Bjb2RlSW5kZXggPSBzZWVuSW5kZXggKyAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm1vdmVJdGVtKGl0ZW1PcGNvZGUsIGl0ZW0sIG9wY29kZSk7XG4gICAgICAgICAgICBjdXJyZW50T3Bjb2RlSW5kZXgrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW5zZXJ0SXRlbShpdGVtLCBvcGNvZGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBvcGNvZGUgPSBjaGlsZHJlbltpXTtcblxuICAgICAgaWYgKG9wY29kZS5yZXRhaW5lZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5kZWxldGVJdGVtKG9wY29kZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcGNvZGUucmVzZXQoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJldGFpbkl0ZW0ob3Bjb2RlOiBMaXN0SXRlbU9wY29kZSwgaXRlbTogT3BhcXVlSXRlcmF0aW9uSXRlbSkge1xuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbG9nU3RlcCEoJ2xpc3QtdXBkYXRlcycsIFsncmV0YWluJywgaXRlbS5rZXldKTtcbiAgICB9XG5cbiAgICBsZXQgeyBjaGlsZHJlbiB9ID0gdGhpcztcblxuICAgIHVwZGF0ZVJlZihvcGNvZGUubWVtbywgaXRlbS5tZW1vKTtcbiAgICB1cGRhdGVSZWYob3Bjb2RlLnZhbHVlLCBpdGVtLnZhbHVlKTtcbiAgICBvcGNvZGUucmV0YWluZWQgPSB0cnVlO1xuXG4gICAgb3Bjb2RlLmluZGV4ID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIGNoaWxkcmVuLnB1c2gob3Bjb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgaW5zZXJ0SXRlbShpdGVtOiBPcGFxdWVJdGVyYXRpb25JdGVtLCBiZWZvcmU6IExpc3RJdGVtT3Bjb2RlKSB7XG4gICAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgICBsb2dTdGVwISgnbGlzdC11cGRhdGVzJywgWydpbnNlcnQnLCBpdGVtLmtleV0pO1xuICAgIH1cblxuICAgIGxldCB7IG9wY29kZU1hcCwgYm91bmRzLCBzdGF0ZSwgcnVudGltZSwgY2hpbGRyZW4gfSA9IHRoaXM7XG4gICAgbGV0IHsga2V5IH0gPSBpdGVtO1xuICAgIGxldCBuZXh0U2libGluZyA9IGJlZm9yZSA9PT0gdW5kZWZpbmVkID8gdGhpcy5tYXJrZXIgOiBiZWZvcmUuZmlyc3ROb2RlKCk7XG5cbiAgICBsZXQgZWxlbWVudFN0YWNrID0gTmV3RWxlbWVudEJ1aWxkZXIuZm9ySW5pdGlhbFJlbmRlcihydW50aW1lLmVudiwge1xuICAgICAgZWxlbWVudDogYm91bmRzLnBhcmVudEVsZW1lbnQoKSxcbiAgICAgIG5leHRTaWJsaW5nLFxuICAgIH0pO1xuXG4gICAgbGV0IHZtID0gc3RhdGUucmVzdW1lKHJ1bnRpbWUsIGVsZW1lbnRTdGFjayk7XG5cbiAgICB2bS5leGVjdXRlKCh2bSkgPT4ge1xuICAgICAgdm0ucHVzaFVwZGF0aW5nKCk7XG4gICAgICBsZXQgb3Bjb2RlID0gdm0uZW50ZXJJdGVtKGl0ZW0pO1xuXG4gICAgICBvcGNvZGUuaW5kZXggPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICBjaGlsZHJlbi5wdXNoKG9wY29kZSk7XG4gICAgICBvcGNvZGVNYXAuc2V0KGtleSwgb3Bjb2RlKTtcbiAgICAgIGFzc29jaWF0ZURlc3Ryb3lhYmxlQ2hpbGQodGhpcywgb3Bjb2RlKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbW92ZUl0ZW0ob3Bjb2RlOiBMaXN0SXRlbU9wY29kZSwgaXRlbTogT3BhcXVlSXRlcmF0aW9uSXRlbSwgYmVmb3JlOiBMaXN0SXRlbU9wY29kZSkge1xuICAgIGxldCB7IGNoaWxkcmVuIH0gPSB0aGlzO1xuXG4gICAgdXBkYXRlUmVmKG9wY29kZS5tZW1vLCBpdGVtLm1lbW8pO1xuICAgIHVwZGF0ZVJlZihvcGNvZGUudmFsdWUsIGl0ZW0udmFsdWUpO1xuICAgIG9wY29kZS5yZXRhaW5lZCA9IHRydWU7XG5cbiAgICBsZXQgY3VycmVudFNpYmxpbmcsIG5leHRTaWJsaW5nO1xuXG4gICAgaWYgKGJlZm9yZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBtb3ZlQm91bmRzKG9wY29kZSwgdGhpcy5tYXJrZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjdXJyZW50U2libGluZyA9IG9wY29kZS5sYXN0Tm9kZSgpLm5leHRTaWJsaW5nO1xuICAgICAgbmV4dFNpYmxpbmcgPSBiZWZvcmUuZmlyc3ROb2RlKCk7XG5cbiAgICAgIC8vIEl0ZW1zIGFyZSBtb3ZlZCB0aHJvdWdob3V0IHRoZSBhbGdvcml0aG0sIHNvIHRoZXJlIGFyZSBjYXNlcyB3aGVyZSB0aGVcbiAgICAgIC8vIHRoZSBpdGVtcyBhbHJlYWR5IGhhcHBlbiB0byBiZSBzaWJsaW5ncyAoZS5nLiBhbiBpdGVtIGluIGJldHdlZW4gd2FzXG4gICAgICAvLyBtb3ZlZCBiZWZvcmUgdGhpcyBtb3ZlIGhhcHBlbmVkKS4gQ2hlY2sgdG8gc2VlIGlmIHRoZXkgYXJlIHNpYmxpbmdzXG4gICAgICAvLyBmaXJzdCBiZWZvcmUgZG9pbmcgdGhlIG1vdmUuXG4gICAgICBpZiAoY3VycmVudFNpYmxpbmcgIT09IG5leHRTaWJsaW5nKSB7XG4gICAgICAgIG1vdmVCb3VuZHMob3Bjb2RlLCBuZXh0U2libGluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgb3Bjb2RlLmluZGV4ID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgIGNoaWxkcmVuLnB1c2gob3Bjb2RlKTtcblxuICAgIGlmIChMT0NBTF9ERUJVRykge1xuICAgICAgbGV0IHR5cGUgPSBjdXJyZW50U2libGluZyAmJiBjdXJyZW50U2libGluZyA9PT0gbmV4dFNpYmxpbmcgPyAnbW92ZS1yZXRhaW4nIDogJ21vdmUnO1xuICAgICAgbG9nU3RlcCEoJ2xpc3QtdXBkYXRlcycsIFt0eXBlLCBpdGVtLmtleV0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZGVsZXRlSXRlbShvcGNvZGU6IExpc3RJdGVtT3Bjb2RlKSB7XG4gICAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgICBsb2dTdGVwISgnbGlzdC11cGRhdGVzJywgWydkZWxldGUnLCBvcGNvZGUua2V5XSk7XG4gICAgfVxuXG4gICAgZGVzdHJveShvcGNvZGUpO1xuICAgIGNsZWFyKG9wY29kZSk7XG4gICAgdGhpcy5vcGNvZGVNYXAuZGVsZXRlKG9wY29kZS5rZXkpO1xuICB9XG59XG5cbmNsYXNzIFVwZGF0aW5nVk1GcmFtZSB7XG4gIHByaXZhdGUgY3VycmVudCA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBvcHM6IFVwZGF0aW5nT3Bjb2RlW10sIHByaXZhdGUgZXhjZXB0aW9uSGFuZGxlcjogT3B0aW9uPEV4Y2VwdGlvbkhhbmRsZXI+KSB7fVxuXG4gIGdvdG8oaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuY3VycmVudCA9IGluZGV4O1xuICB9XG5cbiAgbmV4dFN0YXRlbWVudCgpOiBVcGRhdGluZ09wY29kZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMub3BzW3RoaXMuY3VycmVudCsrXTtcbiAgfVxuXG4gIGhhbmRsZUV4Y2VwdGlvbigpIHtcbiAgICBpZiAodGhpcy5leGNlcHRpb25IYW5kbGVyKSB7XG4gICAgICB0aGlzLmV4Y2VwdGlvbkhhbmRsZXIuaGFuZGxlRXhjZXB0aW9uKCk7XG4gICAgfVxuICB9XG59XG4iXSwic291cmNlUm9vdCI6IiJ9