UNPKG

@glimmer/util

Version:

Common utilities used in Glimmer

704 lines (581 loc) 73.1 kB
define('@glimmer/util', ['exports', '@glimmer/env'], function (exports, env) { 'use strict'; var EMPTY_ARRAY = Object.freeze([]); function emptyArray() { return EMPTY_ARRAY; } var EMPTY_STRING_ARRAY = emptyArray(); var EMPTY_NUMBER_ARRAY = emptyArray(); /** * This function returns `true` if the input array is the special empty array sentinel, * which is sometimes used for optimizations. */ function isEmptyArray(input) { return input === EMPTY_ARRAY; } // import Logger from './logger'; function debugAssert(test, msg) { // if (!alreadyWarned) { // alreadyWarned = true; // Logger.warn("Don't leave debug assertions on in public builds"); // } if (!test) { throw new Error(msg || 'assertion failure'); } } function deprecate(desc) { LOCAL_LOGGER.warn("DEPRECATION: " + desc); } 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; } function dict() { return Object.create(null); } function isDict(u) { return u !== null && u !== undefined; } function isObject(u) { return typeof u === 'function' || typeof u === 'object' && u !== null; } var StackImpl = /*#__PURE__*/function () { function StackImpl(values) { if (values === void 0) { values = []; } this.current = null; this.stack = values; } var _proto = StackImpl.prototype; _proto.push = function push(item) { this.current = item; this.stack.push(item); }; _proto.pop = function pop() { var item = this.stack.pop(); var len = this.stack.length; this.current = len === 0 ? null : this.stack[len - 1]; return item === undefined ? null : item; }; _proto.nth = function nth(from) { var len = this.stack.length; return len < from ? null : this.stack[len - from]; }; _proto.isEmpty = function isEmpty() { return this.stack.length === 0; }; _proto.toArray = function toArray() { return this.stack; }; _createClass(StackImpl, [{ key: "size", get: function get() { return this.stack.length; } }]); return StackImpl; }(); function clearElement(parent) { var current = parent.firstChild; while (current) { var next = current.nextSibling; parent.removeChild(current); current = next; } } var SERIALIZATION_FIRST_NODE_STRING = '%+b:0%'; function isSerializationFirstNode(node) { return node.nodeValue === SERIALIZATION_FIRST_NODE_STRING; } var assign = Object.assign; function fillNulls(count) { var arr = new Array(count); for (var i = 0; i < count; i++) { arr[i] = null; } return arr; } function values(obj) { var vals = []; for (var key in obj) { vals.push(obj[key]); } return vals; } /** Strongly hint runtimes to intern the provided string. When do I need to use this function? For the most part, never. Pre-mature optimization is bad, and often the runtime does exactly what you need it to, and more often the trade-off isn't worth it. Why? Runtimes store strings in at least 2 different representations: Ropes and Symbols (interned strings). The Rope provides a memory efficient data-structure for strings created from concatenation or some other string manipulation like splitting. Unfortunately checking equality of different ropes can be quite costly as runtimes must resort to clever string comparison algorithms. These algorithms typically cost in proportion to the length of the string. Luckily, this is where the Symbols (interned strings) shine. As Symbols are unique by their string content, equality checks can be done by pointer comparison. How do I know if my string is a rope or symbol? Typically (warning general sweeping statement, but truthy in runtimes at present) static strings created as part of the JS source are interned. Strings often used for comparisons can be interned at runtime if some criteria are met. One of these criteria can be the size of the entire rope. For example, in chrome 38 a rope longer then 12 characters will not intern, nor will segments of that rope. Some numbers: http://jsperf.com/eval-vs-keys/8 Known Trick™ @private @return {String} interned version of the provided string */ function intern(str) { var obj = {}; obj[str] = 1; for (var key in obj) { if (key === str) { return key; } } return str; } var HAS_NATIVE_PROXY = typeof Proxy === 'function'; var HAS_NATIVE_SYMBOL = function () { if (typeof Symbol !== 'function') { return false; } // eslint-disable-next-line symbol-description return typeof Symbol() === 'symbol'; }(); function keys(obj) { return Object.keys(obj); } function unwrap(val) { if (val === null || val === undefined) throw new Error("Expected value to be present"); return val; } function expect(val, message) { if (val === null || val === undefined) throw new Error(message); return val; } function unreachable(message) { if (message === void 0) { message = 'unreachable'; } return new Error(message); } function exhausted(value) { throw new Error("Exhausted " + value); } var tuple = function tuple() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return args; }; function enumerableSymbol(key) { return intern("__" + key + Math.floor(Math.random() * Date.now()) + "__"); } var symbol = HAS_NATIVE_SYMBOL ? Symbol : enumerableSymbol; function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function strip(strings) { var out = ''; for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } for (var i = 0; i < strings.length; i++) { var string = strings[i]; var dynamic = args[i] !== undefined ? String(args[i]) : ''; out += "" + string + dynamic; } var lines = out.split('\n'); while (lines.length && lines[0].match(/^\s*$/)) { lines.shift(); } while (lines.length && lines[lines.length - 1].match(/^\s*$/)) { lines.pop(); } var min = Infinity; for (var _iterator = _createForOfIteratorHelperLoose(lines), _step; !(_step = _iterator()).done;) { var line = _step.value; var leading = line.match(/^\s*/)[0].length; min = Math.min(min, leading); } var stripped = []; for (var _iterator2 = _createForOfIteratorHelperLoose(lines), _step2; !(_step2 = _iterator2()).done;) { var _line = _step2.value; stripped.push(_line.slice(min)); } return stripped.join('\n'); } function isHandle(value) { return value >= 0; } function isNonPrimitiveHandle(value) { return value > 3 /* ENCODED_UNDEFINED_HANDLE */ ; } function constants() { for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) { values[_key] = arguments[_key]; } return [false, true, null, undefined].concat(values); } function isSmallInt(value) { return value % 1 === 0 && value <= 536870911 /* MAX_INT */ && value >= -536870912 /* MIN_INT */ ; } function encodeNegative(num) { return num & -536870913 /* SIGN_BIT */ ; } function decodeNegative(num) { return num | ~-536870913 /* SIGN_BIT */ ; } function encodePositive(num) { return ~num; } function decodePositive(num) { return ~num; } function encodeHandle(num) { return num; } function decodeHandle(num) { return num; } function encodeImmediate(num) { num |= 0; return num < 0 ? encodeNegative(num) : encodePositive(num); } function decodeImmediate(num) { num |= 0; return num > -536870913 /* SIGN_BIT */ ? decodePositive(num) : decodeNegative(num); } // Warm [1, -1].forEach(function (x) { return decodeImmediate(encodeImmediate(x)); }); function unwrapHandle(handle) { if (typeof handle === 'number') { return handle; } else { var error = handle.errors[0]; throw new Error("Compile Error: " + error.problem + " @ " + error.span.start + ".." + error.span.end); } } function unwrapTemplate(template) { if (template.result === 'error') { throw new Error("Compile Error: " + template.problem + " @ " + template.span.start + ".." + template.span.end); } return template; } function extractHandle(handle) { if (typeof handle === 'number') { return handle; } else { return handle.handle; } } function isOkHandle(handle) { return typeof handle === 'number'; } function isErrHandle(handle) { return typeof handle === 'number'; } var weakSet = typeof WeakSet === 'function' ? WeakSet : /*#__PURE__*/function () { function WeakSetPolyFill() { this._map = new WeakMap(); } var _proto = WeakSetPolyFill.prototype; _proto.add = function add(val) { this._map.set(val, true); return this; }; _proto["delete"] = function _delete(val) { return this._map["delete"](val); }; _proto.has = function has(val) { return this._map.has(val); }; return WeakSetPolyFill; }(); function castToSimple(node) { if (isDocument(node)) { return node; } else if (isElement(node)) { return node; } else { return node; } } function castToBrowser(node, sugaryCheck) { if (node === null || node === undefined) { return null; } if (typeof document === undefined) { throw new Error('Attempted to cast to a browser node in a non-browser context'); } if (isDocument(node)) { return node; } if (node.ownerDocument !== document) { throw new Error('Attempted to cast to a browser node with a node that was not created from this document'); } return checkNode(node, sugaryCheck); } function checkError(from, check) { return new Error("cannot cast a " + from + " into " + check); } function isDocument(node) { return node.nodeType === 9 /* DOCUMENT_NODE */ ; } function isElement(node) { return node.nodeType === 1 /* ELEMENT_NODE */ ; } function checkNode(node, check) { var isMatch = false; if (node !== null) { if (typeof check === 'string') { isMatch = stringCheckNode(node, check); } else if (Array.isArray(check)) { isMatch = check.some(function (c) { return stringCheckNode(node, c); }); } else { throw unreachable(); } } if (isMatch) { return node; } else { throw checkError("SimpleElement(" + node + ")", check); } } function stringCheckNode(node, check) { switch (check) { case 'NODE': return true; case 'HTML': return node instanceof HTMLElement; case 'SVG': return node instanceof SVGElement; case 'ELEMENT': return node instanceof Element; default: if (check.toUpperCase() === check) { throw new Error("BUG: this code is missing handling for a generic node type"); } return node instanceof Element && node.tagName.toLowerCase() === check; } } function _createForOfIteratorHelperLoose$1(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); } function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function isPresent(list) { return list.length > 0; } function ifPresent(list, ifPresent, otherwise) { if (isPresent(list)) { return ifPresent(list); } else { return otherwise(); } } function toPresentOption(list) { if (isPresent(list)) { return list; } else { return null; } } function assertPresent(list, message) { if (message === void 0) { message = "unexpected empty list"; } if (!isPresent(list)) { throw new Error(message); } } function mapPresent(list, callback) { if (list === null) { return null; } var out = []; for (var _iterator = _createForOfIteratorHelperLoose$1(list), _step; !(_step = _iterator()).done;) { var item = _step.value; out.push(callback(item)); } return out; } function buildUntouchableThis(source) { var context = null; if (env.DEBUG && HAS_NATIVE_PROXY) { var assertOnProperty = function assertOnProperty(property) { throw new Error("You accessed `this." + String(property) + "` from a function passed to the " + source + ", but the function itself was not bound to a valid `this` context. Consider updating to use a bound function (for instance, use an arrow function, `() => {}`)."); }; context = new Proxy({}, { get: function get(_target, property) { assertOnProperty(property); }, set: function set(_target, property) { assertOnProperty(property); return false; }, has: function has(_target, property) { assertOnProperty(property); return false; } }); } return context; } var debugToString; if (env.DEBUG) { var getFunctionName = function getFunctionName(fn) { var functionName = fn.name; if (functionName === undefined) { var match = Function.prototype.toString.call(fn).match(/function (\w+)\s*\(/); functionName = match && match[1] || ''; } return functionName.replace(/^bound /, ''); }; var getObjectName = function getObjectName(obj) { var name; var className; if (obj.constructor && typeof obj.constructor === 'function') { className = getFunctionName(obj.constructor); } if ('toString' in obj && obj.toString !== Object.prototype.toString && obj.toString !== Function.prototype.toString) { name = obj.toString(); } // If the class has a decent looking name, and the `toString` is one of the // default Ember toStrings, replace the constructor portion of the toString // with the class name. We check the length of the class name to prevent doing // this when the value is minified. if (name && name.match(/<.*:ember\d+>/) && className && className[0] !== '_' && className.length > 2 && className !== 'Class') { return name.replace(/<.*:/, "<" + className + ":"); } return name || className; }; var getPrimitiveName = function getPrimitiveName(value) { return String(value); }; debugToString = function debugToString(value) { if (typeof value === 'function') { return getFunctionName(value) || "(unknown function)"; } else if (typeof value === 'object' && value !== null) { return getObjectName(value) || "(unknown object)"; } else { return getPrimitiveName(value); } }; } var debugToString$1 = debugToString; var beginTestSteps; var endTestSteps; var verifySteps; var logStep; /** * This constant exists to make it easier to differentiate normal logs from * errant console.logs. LOCAL_LOGGER should only be used inside a * LOCAL_SHOULD_LOG check. * * It does not alleviate the need to check LOCAL_SHOULD_LOG, which is used * for stripping. */ var LOCAL_LOGGER = console; /** * This constant exists to make it easier to differentiate normal logs from * errant console.logs. LOGGER can be used outside of LOCAL_SHOULD_LOG checks, * and is meant to be used in the rare situation where a console.* call is * actually appropriate. */ var LOGGER = console; function assertNever(value, desc) { if (desc === void 0) { desc = 'unexpected unreachable branch'; } LOGGER.log('unreachable', value); LOGGER.log(desc + " :: " + JSON.stringify(value) + " (" + value + ")"); throw new Error("code reached unreachable"); } exports.EMPTY_ARRAY = EMPTY_ARRAY; exports.EMPTY_NUMBER_ARRAY = EMPTY_NUMBER_ARRAY; exports.EMPTY_STRING_ARRAY = EMPTY_STRING_ARRAY; exports.HAS_NATIVE_PROXY = HAS_NATIVE_PROXY; exports.HAS_NATIVE_SYMBOL = HAS_NATIVE_SYMBOL; exports.LOCAL_LOGGER = LOCAL_LOGGER; exports.LOGGER = LOGGER; exports.SERIALIZATION_FIRST_NODE_STRING = SERIALIZATION_FIRST_NODE_STRING; exports.Stack = StackImpl; exports._WeakSet = weakSet; exports.assert = debugAssert; exports.assertNever = assertNever; exports.assertPresent = assertPresent; exports.assign = assign; exports.beginTestSteps = beginTestSteps; exports.buildUntouchableThis = buildUntouchableThis; exports.castToBrowser = castToBrowser; exports.castToSimple = castToSimple; exports.checkNode = checkNode; exports.clearElement = clearElement; exports.constants = constants; exports.debugToString = debugToString$1; exports.decodeHandle = decodeHandle; exports.decodeImmediate = decodeImmediate; exports.decodeNegative = decodeNegative; exports.decodePositive = decodePositive; exports.deprecate = deprecate; exports.dict = dict; exports.emptyArray = emptyArray; exports.encodeHandle = encodeHandle; exports.encodeImmediate = encodeImmediate; exports.encodeNegative = encodeNegative; exports.encodePositive = encodePositive; exports.endTestSteps = endTestSteps; exports.enumerableSymbol = enumerableSymbol; exports.exhausted = exhausted; exports.expect = expect; exports.extractHandle = extractHandle; exports.fillNulls = fillNulls; exports.ifPresent = ifPresent; exports.intern = intern; exports.isDict = isDict; exports.isEmptyArray = isEmptyArray; exports.isErrHandle = isErrHandle; exports.isHandle = isHandle; exports.isNonPrimitiveHandle = isNonPrimitiveHandle; exports.isObject = isObject; exports.isOkHandle = isOkHandle; exports.isPresent = isPresent; exports.isSerializationFirstNode = isSerializationFirstNode; exports.isSmallInt = isSmallInt; exports.keys = keys; exports.logStep = logStep; exports.mapPresent = mapPresent; exports.strip = strip; exports.symbol = symbol; exports.toPresentOption = toPresentOption; exports.tuple = tuple; exports.unreachable = unreachable; exports.unwrap = unwrap; exports.unwrapHandle = unwrapHandle; exports.unwrapTemplate = unwrapTemplate; exports.values = values; exports.verifySteps = verifySteps; Object.defineProperty(exports, '__esModule', { value: true }); }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2xpbW1lci11dGlsLmpzIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9AZ2xpbW1lci91dGlsL2xpYi9hcnJheS11dGlscy50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3V0aWwvbGliL2Fzc2VydC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3V0aWwvbGliL2NvbGxlY3Rpb25zLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvZG9tLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvaXMtc2VyaWFsaXphdGlvbi1maXJzdC1ub2RlLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvb2JqZWN0LXV0aWxzLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvaW50ZXJuLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvcGxhdGZvcm0tdXRpbHMudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9AZ2xpbW1lci91dGlsL2xpYi9zdHJpbmcudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9AZ2xpbW1lci91dGlsL2xpYi9pbW1lZGlhdGUudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9AZ2xpbW1lci91dGlsL2xpYi90ZW1wbGF0ZS50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3V0aWwvbGliL3dlYWstc2V0LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvc2ltcGxlLWNhc3QudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9AZ2xpbW1lci91dGlsL2xpYi9wcmVzZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9saWIvdW50b3VjaGFibGUtdGhpcy50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3V0aWwvbGliL2RlYnVnLXRvLXN0cmluZy50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3V0aWwvbGliL2RlYnVnLXN0ZXBzLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvQGdsaW1tZXIvdXRpbC9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY29uc3QgRU1QVFlfQVJSQVk6IHJlYWRvbmx5IHVua25vd25bXSA9IE9iamVjdC5mcmVlemUoW10pIGFzIHJlYWRvbmx5IHVua25vd25bXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGVtcHR5QXJyYXk8VCBleHRlbmRzIHVua25vd24+KCk6IFRbXSB7XG4gIHJldHVybiBFTVBUWV9BUlJBWSBhcyBUW107XG59XG5cbmV4cG9ydCBjb25zdCBFTVBUWV9TVFJJTkdfQVJSQVkgPSBlbXB0eUFycmF5PHN0cmluZz4oKTtcbmV4cG9ydCBjb25zdCBFTVBUWV9OVU1CRVJfQVJSQVkgPSBlbXB0eUFycmF5PG51bWJlcj4oKTtcblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgYHRydWVgIGlmIHRoZSBpbnB1dCBhcnJheSBpcyB0aGUgc3BlY2lhbCBlbXB0eSBhcnJheSBzZW50aW5lbCxcbiAqIHdoaWNoIGlzIHNvbWV0aW1lcyB1c2VkIGZvciBvcHRpbWl6YXRpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eUFycmF5KGlucHV0OiB1bmtub3duW10gfCByZWFkb25seSB1bmtub3duW10pOiBib29sZWFuIHtcbiAgcmV0dXJuIGlucHV0ID09PSBFTVBUWV9BUlJBWTtcbn1cbiIsIi8vIGltcG9ydCBMb2dnZXIgZnJvbSAnLi9sb2dnZXInO1xuXG5pbXBvcnQgeyBMT0NBTF9MT0dHRVIgfSBmcm9tICcuLi9pbmRleCc7XG5cbi8vIGxldCBhbHJlYWR5V2FybmVkID0gZmFsc2U7XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWJ1Z0Fzc2VydCh0ZXN0OiBhbnksIG1zZzogc3RyaW5nKTogYXNzZXJ0cyB0ZXN0IHtcbiAgLy8gaWYgKCFhbHJlYWR5V2FybmVkKSB7XG4gIC8vICAgYWxyZWFkeVdhcm5lZCA9IHRydWU7XG4gIC8vICAgTG9nZ2VyLndhcm4oXCJEb24ndCBsZWF2ZSBkZWJ1ZyBhc3NlcnRpb25zIG9uIGluIHB1YmxpYyBidWlsZHNcIik7XG4gIC8vIH1cblxuICBpZiAoIXRlc3QpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IobXNnIHx8ICdhc3NlcnRpb24gZmFpbHVyZScpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcm9kQXNzZXJ0KCkge31cblxuZXhwb3J0IGZ1bmN0aW9uIGRlcHJlY2F0ZShkZXNjOiBzdHJpbmcpIHtcbiAgTE9DQUxfTE9HR0VSLndhcm4oYERFUFJFQ0FUSU9OOiAke2Rlc2N9YCk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGRlYnVnQXNzZXJ0O1xuIiwiaW1wb3J0IHsgRGljdCwgT3B0aW9uLCBTdGFjayB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gZGljdDxUID0gdW5rbm93bj4oKTogRGljdDxUPiB7XG4gIHJldHVybiBPYmplY3QuY3JlYXRlKG51bGwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNEaWN0PFQ+KHU6IFQpOiB1IGlzIERpY3QgJiBUIHtcbiAgcmV0dXJuIHUgIT09IG51bGwgJiYgdSAhPT0gdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNPYmplY3Q8VD4odTogVCk6IHUgaXMgb2JqZWN0ICYgVCB7XG4gIHJldHVybiB0eXBlb2YgdSA9PT0gJ2Z1bmN0aW9uJyB8fCAodHlwZW9mIHUgPT09ICdvYmplY3QnICYmIHUgIT09IG51bGwpO1xufVxuXG5leHBvcnQgY2xhc3MgU3RhY2tJbXBsPFQ+IGltcGxlbWVudHMgU3RhY2s8VD4ge1xuICBwcml2YXRlIHN0YWNrOiBUW107XG4gIHB1YmxpYyBjdXJyZW50OiBPcHRpb248VD4gPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlczogVFtdID0gW10pIHtcbiAgICB0aGlzLnN0YWNrID0gdmFsdWVzO1xuICB9XG5cbiAgcHVibGljIGdldCBzaXplKCkge1xuICAgIHJldHVybiB0aGlzLnN0YWNrLmxlbmd0aDtcbiAgfVxuXG4gIHB1c2goaXRlbTogVCkge1xuICAgIHRoaXMuY3VycmVudCA9IGl0ZW07XG4gICAgdGhpcy5zdGFjay5wdXNoKGl0ZW0pO1xuICB9XG5cbiAgcG9wKCk6IE9wdGlvbjxUPiB7XG4gICAgbGV0IGl0ZW0gPSB0aGlzLnN0YWNrLnBvcCgpO1xuICAgIGxldCBsZW4gPSB0aGlzLnN0YWNrLmxlbmd0aDtcbiAgICB0aGlzLmN1cnJlbnQgPSBsZW4gPT09IDAgPyBudWxsIDogdGhpcy5zdGFja1tsZW4gLSAxXTtcblxuICAgIHJldHVybiBpdGVtID09PSB1bmRlZmluZWQgPyBudWxsIDogaXRlbTtcbiAgfVxuXG4gIG50aChmcm9tOiBudW1iZXIpOiBPcHRpb248VD4ge1xuICAgIGxldCBsZW4gPSB0aGlzLnN0YWNrLmxlbmd0aDtcbiAgICByZXR1cm4gbGVuIDwgZnJvbSA/IG51bGwgOiB0aGlzLnN0YWNrW2xlbiAtIGZyb21dO1xuICB9XG5cbiAgaXNFbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGFjay5sZW5ndGggPT09IDA7XG4gIH1cblxuICB0b0FycmF5KCk6IFRbXSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhY2s7XG4gIH1cbn1cbiIsImltcG9ydCB7IE9wdGlvbiB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgU2ltcGxlRWxlbWVudCwgU2ltcGxlTm9kZSB9IGZyb20gJ0BzaW1wbGUtZG9tL2ludGVyZmFjZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGVhckVsZW1lbnQocGFyZW50OiBTaW1wbGVFbGVtZW50KSB7XG4gIGxldCBjdXJyZW50OiBPcHRpb248U2ltcGxlTm9kZT4gPSBwYXJlbnQuZmlyc3RDaGlsZDtcblxuICB3aGlsZSAoY3VycmVudCkge1xuICAgIGxldCBuZXh0ID0gY3VycmVudC5uZXh0U2libGluZztcbiAgICBwYXJlbnQucmVtb3ZlQ2hpbGQoY3VycmVudCk7XG4gICAgY3VycmVudCA9IG5leHQ7XG4gIH1cbn1cbiIsImltcG9ydCB7IFNpbXBsZU5vZGUgfSBmcm9tICdAc2ltcGxlLWRvbS9pbnRlcmZhY2UnO1xuXG5leHBvcnQgY29uc3QgU0VSSUFMSVpBVElPTl9GSVJTVF9OT0RFX1NUUklORyA9ICclK2I6MCUnO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNTZXJpYWxpemF0aW9uRmlyc3ROb2RlKG5vZGU6IFNpbXBsZU5vZGUpOiBib29sZWFuIHtcbiAgcmV0dXJuIG5vZGUubm9kZVZhbHVlID09PSBTRVJJQUxJWkFUSU9OX0ZJUlNUX05PREVfU1RSSU5HO1xufVxuIiwiZXhwb3J0IGxldCBhc3NpZ24gPSBPYmplY3QuYXNzaWduO1xuXG5leHBvcnQgZnVuY3Rpb24gZmlsbE51bGxzPFQ+KGNvdW50OiBudW1iZXIpOiBUW10ge1xuICBsZXQgYXJyID0gbmV3IEFycmF5KGNvdW50KTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICBhcnJbaV0gPSBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGFycjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbHVlczxUPihvYmo6IHsgW3M6IHN0cmluZ106IFQgfSk6IFRbXSB7XG4gIGNvbnN0IHZhbHMgPSBbXTtcbiAgZm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgdmFscy5wdXNoKG9ialtrZXldKTtcbiAgfVxuICByZXR1cm4gdmFscztcbn1cbiIsIi8qKlxuICBTdHJvbmdseSBoaW50IHJ1bnRpbWVzIHRvIGludGVybiB0aGUgcHJvdmlkZWQgc3RyaW5nLlxuXG4gIFdoZW4gZG8gSSBuZWVkIHRvIHVzZSB0aGlzIGZ1bmN0aW9uP1xuXG4gIEZvciB0aGUgbW9zdCBwYXJ0LCBuZXZlci4gUHJlLW1hdHVyZSBvcHRpbWl6YXRpb24gaXMgYmFkLCBhbmQgb2Z0ZW4gdGhlXG4gIHJ1bnRpbWUgZG9lcyBleGFjdGx5IHdoYXQgeW91IG5lZWQgaXQgdG8sIGFuZCBtb3JlIG9mdGVuIHRoZSB0cmFkZS1vZmYgaXNuJ3RcbiAgd29ydGggaXQuXG5cbiAgV2h5P1xuXG4gIFJ1bnRpbWVzIHN0b3JlIHN0cmluZ3MgaW4gYXQgbGVhc3QgMiBkaWZmZXJlbnQgcmVwcmVzZW50YXRpb25zOlxuICBSb3BlcyBhbmQgU3ltYm9scyAoaW50ZXJuZWQgc3RyaW5ncykuIFRoZSBSb3BlIHByb3ZpZGVzIGEgbWVtb3J5IGVmZmljaWVudFxuICBkYXRhLXN0cnVjdHVyZSBmb3Igc3RyaW5ncyBjcmVhdGVkIGZyb20gY29uY2F0ZW5hdGlvbiBvciBzb21lIG90aGVyIHN0cmluZ1xuICBtYW5pcHVsYXRpb24gbGlrZSBzcGxpdHRpbmcuXG5cbiAgVW5mb3J0dW5hdGVseSBjaGVja2luZyBlcXVhbGl0eSBvZiBkaWZmZXJlbnQgcm9wZXMgY2FuIGJlIHF1aXRlIGNvc3RseSBhc1xuICBydW50aW1lcyBtdXN0IHJlc29ydCB0byBjbGV2ZXIgc3RyaW5nIGNvbXBhcmlzb24gYWxnb3JpdGhtcy4gVGhlc2VcbiAgYWxnb3JpdGhtcyB0eXBpY2FsbHkgY29zdCBpbiBwcm9wb3J0aW9uIHRvIHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZy5cbiAgTHVja2lseSwgdGhpcyBpcyB3aGVyZSB0aGUgU3ltYm9scyAoaW50ZXJuZWQgc3RyaW5ncykgc2hpbmUuIEFzIFN5bWJvbHMgYXJlXG4gIHVuaXF1ZSBieSB0aGVpciBzdHJpbmcgY29udGVudCwgZXF1YWxpdHkgY2hlY2tzIGNhbiBiZSBkb25lIGJ5IHBvaW50ZXJcbiAgY29tcGFyaXNvbi5cblxuICBIb3cgZG8gSSBrbm93IGlmIG15IHN0cmluZyBpcyBhIHJvcGUgb3Igc3ltYm9sP1xuXG4gIFR5cGljYWxseSAod2FybmluZyBnZW5lcmFsIHN3ZWVwaW5nIHN0YXRlbWVudCwgYnV0IHRydXRoeSBpbiBydW50aW1lcyBhdFxuICBwcmVzZW50KSBzdGF0aWMgc3RyaW5ncyBjcmVhdGVkIGFzIHBhcnQgb2YgdGhlIEpTIHNvdXJjZSBhcmUgaW50ZXJuZWQuXG4gIFN0cmluZ3Mgb2Z0ZW4gdXNlZCBmb3IgY29tcGFyaXNvbnMgY2FuIGJlIGludGVybmVkIGF0IHJ1bnRpbWUgaWYgc29tZVxuICBjcml0ZXJpYSBhcmUgbWV0LiAgT25lIG9mIHRoZXNlIGNyaXRlcmlhIGNhbiBiZSB0aGUgc2l6ZSBvZiB0aGUgZW50aXJlIHJvcGUuXG4gIEZvciBleGFtcGxlLCBpbiBjaHJvbWUgMzggYSByb3BlIGxvbmdlciB0aGVuIDEyIGNoYXJhY3RlcnMgd2lsbCBub3RcbiAgaW50ZXJuLCBub3Igd2lsbCBzZWdtZW50cyBvZiB0aGF0IHJvcGUuXG5cbiAgU29tZSBudW1iZXJzOiBodHRwOi8vanNwZXJmLmNvbS9ldmFsLXZzLWtleXMvOFxuXG4gIEtub3duIFRyaWNr4oSiXG5cbiAgQHByaXZhdGVcbiAgQHJldHVybiB7U3RyaW5nfSBpbnRlcm5lZCB2ZXJzaW9uIG9mIHRoZSBwcm92aWRlZCBzdHJpbmdcbiovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBpbnRlcm4oc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgb2JqOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG4gIG9ialtzdHJdID0gMTtcbiAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgIGlmIChrZXkgPT09IHN0cikge1xuICAgICAgcmV0dXJuIGtleTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0cjtcbn1cbiIsImltcG9ydCB7IE1heWJlIH0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgaW50ZXJuIGZyb20gJy4vaW50ZXJuJztcblxuZXhwb3J0IHR5cGUgRmFjdG9yeTxUPiA9IG5ldyAoLi4uYXJnczogdW5rbm93bltdKSA9PiBUO1xuXG5leHBvcnQgY29uc3QgSEFTX05BVElWRV9QUk9YWSA9IHR5cGVvZiBQcm94eSA9PT0gJ2Z1bmN0aW9uJztcblxuZXhwb3J0IGNvbnN0IEhBU19OQVRJVkVfU1lNQk9MID0gKGZ1bmN0aW9uICgpIHtcbiAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc3ltYm9sLWRlc2NyaXB0aW9uXG4gIHJldHVybiB0eXBlb2YgU3ltYm9sKCkgPT09ICdzeW1ib2wnO1xufSkoKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGtleXM8VD4ob2JqOiBUKTogQXJyYXk8a2V5b2YgVD4ge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKSBhcyBBcnJheTxrZXlvZiBUPjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVud3JhcDxUPih2YWw6IE1heWJlPFQ+KTogVCB7XG4gIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgdmFsdWUgdG8gYmUgcHJlc2VudGApO1xuICByZXR1cm4gdmFsIGFzIFQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHBlY3Q8VD4odmFsOiBNYXliZTxUPiwgbWVzc2FnZTogc3RyaW5nKTogVCB7XG4gIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgcmV0dXJuIHZhbCBhcyBUO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5yZWFjaGFibGUobWVzc2FnZSA9ICd1bnJlYWNoYWJsZScpOiBFcnJvciB7XG4gIHJldHVybiBuZXcgRXJyb3IobWVzc2FnZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleGhhdXN0ZWQodmFsdWU6IG5ldmVyKTogbmV2ZXIge1xuICB0aHJvdyBuZXcgRXJyb3IoYEV4aGF1c3RlZCAke3ZhbHVlfWApO1xufVxuXG5leHBvcnQgdHlwZSBMaXQgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgdW5kZWZpbmVkIHwgbnVsbCB8IHZvaWQgfCB7fTtcblxuZXhwb3J0IGNvbnN0IHR1cGxlID0gPFQgZXh0ZW5kcyBMaXRbXT4oLi4uYXJnczogVCkgPT4gYXJncztcblxuZXhwb3J0IGZ1bmN0aW9uIGVudW1lcmFibGVTeW1ib2woa2V5OiBzdHJpbmcpOiBhbnkge1xuICByZXR1cm4gaW50ZXJuKGBfXyR7a2V5fSR7TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogRGF0ZS5ub3coKSl9X19gKTtcbn1cblxuZXhwb3J0IGNvbnN0IHN5bWJvbCA9IEhBU19OQVRJVkVfU1lNQk9MID8gU3ltYm9sIDogZW51bWVyYWJsZVN5bWJvbDtcbiIsImV4cG9ydCBmdW5jdGlvbiBzdHJpcChzdHJpbmdzOiBUZW1wbGF0ZVN0cmluZ3NBcnJheSwgLi4uYXJnczogdW5rbm93bltdKSB7XG4gIGxldCBvdXQgPSAnJztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHJpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IHN0cmluZyA9IHN0cmluZ3NbaV07XG4gICAgbGV0IGR5bmFtaWMgPSBhcmdzW2ldICE9PSB1bmRlZmluZWQgPyBTdHJpbmcoYXJnc1tpXSkgOiAnJztcblxuICAgIG91dCArPSBgJHtzdHJpbmd9JHtkeW5hbWljfWA7XG4gIH1cblxuICBsZXQgbGluZXMgPSBvdXQuc3BsaXQoJ1xcbicpO1xuXG4gIHdoaWxlIChsaW5lcy5sZW5ndGggJiYgbGluZXNbMF0ubWF0Y2goL15cXHMqJC8pKSB7XG4gICAgbGluZXMuc2hpZnQoKTtcbiAgfVxuXG4gIHdoaWxlIChsaW5lcy5sZW5ndGggJiYgbGluZXNbbGluZXMubGVuZ3RoIC0gMV0ubWF0Y2goL15cXHMqJC8pKSB7XG4gICAgbGluZXMucG9wKCk7XG4gIH1cblxuICBsZXQgbWluID0gSW5maW5pdHk7XG5cbiAgZm9yIChsZXQgbGluZSBvZiBsaW5lcykge1xuICAgIGxldCBsZWFkaW5nID0gbGluZS5tYXRjaCgvXlxccyovKSFbMF0ubGVuZ3RoO1xuXG4gICAgbWluID0gTWF0aC5taW4obWluLCBsZWFkaW5nKTtcbiAgfVxuXG4gIGxldCBzdHJpcHBlZCA9IFtdO1xuXG4gIGZvciAobGV0IGxpbmUgb2YgbGluZXMpIHtcbiAgICBzdHJpcHBlZC5wdXNoKGxpbmUuc2xpY2UobWluKSk7XG4gIH1cblxuICByZXR1cm4gc3RyaXBwZWQuam9pbignXFxuJyk7XG59XG4iLCJpbXBvcnQgeyBMT0NBTF9ERUJVRyB9IGZyb20gJ0BnbGltbWVyL2xvY2FsLWRlYnVnLWZsYWdzJztcbmltcG9ydCB7IGRlYnVnQXNzZXJ0IGFzIGFzc2VydCB9IGZyb20gJy4vYXNzZXJ0JztcblxuLypcbiAgRW5jb2Rpbmcgbm90ZXNcblxuICBXZSB1c2UgMzAgYml0IGludGVnZXJzIGZvciBlbmNvZGluZywgc28gdGhhdCB3ZSBkb24ndCBldmVyIGVuY29kZSBhIG5vbi1TTUlcbiAgaW50ZWdlciB0byBwdXNoIG9uIHRoZSBzdGFjay5cblxuICBIYW5kbGVzIGFyZSA+PSAwXG4gIEltbWVkaWF0ZXMgYXJlIDwgMFxuXG4gIFRydWUsIEZhbHNlLCBVbmRlZmluZWQgYW5kIE51bGwgYXJlIHB1c2hlZCBhcyBoYW5kbGVzIGludG8gdGhlIHN5bWJvbCB0YWJsZSxcbiAgd2l0aCB3ZWxsIGtub3duIGhhbmRsZXMgKDAsIDEsIDIsIDMpXG5cbiAgVGhlIG5lZ2F0aXZlIHNwYWNlIGlzIGRpdmlkZWQgaW50byBwb3NpdGl2ZXMgYW5kIG5lZ2F0aXZlcy4gUG9zaXRpdmVzIGFyZVxuICBoaWdoZXIgbnVtYmVycyAoLTEsIC0yLCAtMywgZXRjKSwgbmVnYXRpdmVzIGFyZSBsb3dlci5cblxuICBXZSBvbmx5IGVuY29kZSBpbW1lZGlhdGVzIGZvciB0d28gcmVhc29uczpcblxuICAxLiBUbyB0cmFuc2ZlciBvdmVyIHRoZSB3aXJlLCBzbyB0aGV5J3JlIHNtYWxsZXIgaW4gZ2VuZXJhbFxuICAyLiBXaGVuIHB1c2hpbmcgdmFsdWVzIG9udG8gdGhlIHN0YWNrIGZyb20gdGhlIGxvdyBsZXZlbC9pbm5lciBWTSwgd2hpY2ggbWF5XG4gICAgIGJlIGNvbnZlcnRlZCBpbnRvIFdBU00gb25lIGRheS5cblxuICBUaGlzIGFsbG93cyB0aGUgbG93LWxldmVsIFZNIHRvIGFsd2F5cyB1c2UgU01JcywgYW5kIHRvIG1pbmltaXplIHVzaW5nIEpTXG4gIHZhbHVlcyB2aWEgaGFuZGxlcyBmb3IgdGhpbmdzIGxpa2UgdGhlIHN0YWNrIHBvaW50ZXIgYW5kIGZyYW1lIHBvaW50ZXIuXG4gIEV4dGVybmFsbHksIG1vc3QgY29kZSBwdXNoZXMgdmFsdWVzIGFzIEpTIHZhbHVlcywgZXhjZXB0IHdoZW4gYmVpbmcgcHVsbGVkXG4gIGZyb20gdGhlIGFwcGVuZCBieXRlIGNvZGUgd2hlcmUgaXQgd2FzIGFscmVhZHkgZW5jb2RlZC5cblxuICBMb2dpY2FsbHksIHRoaXMgaXMgYmVjYXVzZSB0aGUgbG93IGxldmVsIFZNIGRvZXNuJ3QgcmVhbGx5IGNhcmUgYWJvdXQgdGhlc2VcbiAgaGlnaGVyIGxldmVsIHZhbHVlcy4gRm9yIGluc3RhbmNlLCB0aGUgcmVzdWx0IG9mIGEgdXNlcmxhbmQgaGVscGVyIG1heSBiZSBhXG4gIG51bWJlciwgb3IgYSBib29sZWFuLCBvciB1bmRlZmluZWQvbnVsbCwgYnV0IGl0J3MgZXh0cmEgd29yayB0byBmaWd1cmUgdGhhdFxuICBvdXQgYW5kIHB1c2ggaXQgY29ycmVjdGx5LCB2cy4ganVzdCBwdXNoaW5nIHRoZSB2YWx1ZSBhcyBhIEpTIHZhbHVlIHdpdGggYVxuICBoYW5kbGUuXG5cbiAgTm90ZTogVGhlIGRldGFpbHMgY291bGQgY2hhbmdlIGhlcmUgaW4gdGhlIGZ1dHVyZSwgdGhpcyBpcyBqdXN0IHRoZSBjdXJyZW50XG4gIHN0cmF0ZWd5LlxuKi9cblxuZXhwb3J0IGNvbnN0IGVudW0gSW1tZWRpYXRlQ29uc3RhbnRzIHtcbiAgTUFYX1NNSSA9IDIgKiogMzAgLSAxLFxuICBNSU5fU01JID0gfk1BWF9TTUksXG4gIFNJR05fQklUID0gfigyICoqIDI5KSxcbiAgTUFYX0lOVCA9IH5TSUdOX0JJVCAtIDEsXG4gIE1JTl9JTlQgPSB+TUFYX0lOVCxcblxuICBGQUxTRV9IQU5ETEUgPSAwLFxuICBUUlVFX0hBTkRMRSA9IDEsXG4gIE5VTExfSEFORExFID0gMixcbiAgVU5ERUZJTkVEX0hBTkRMRSA9IDMsXG5cbiAgRU5DT0RFRF9GQUxTRV9IQU5ETEUgPSBGQUxTRV9IQU5ETEUsXG4gIEVOQ09ERURfVFJVRV9IQU5ETEUgPSBUUlVFX0hBTkRMRSxcbiAgRU5DT0RFRF9OVUxMX0hBTkRMRSA9IE5VTExfSEFORExFLFxuICBFTkNPREVEX1VOREVGSU5FRF9IQU5ETEUgPSBVTkRFRklORURfSEFORExFLFxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNIYW5kbGUodmFsdWU6IG51bWJlcikge1xuICByZXR1cm4gdmFsdWUgPj0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTm9uUHJpbWl0aXZlSGFuZGxlKHZhbHVlOiBudW1iZXIpIHtcbiAgcmV0dXJuIHZhbHVlID4gSW1tZWRpYXRlQ29uc3RhbnRzLkVOQ09ERURfVU5ERUZJTkVEX0hBTkRMRTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN0YW50cyguLi52YWx1ZXM6IHVua25vd25bXSk6IHVua25vd25bXSB7XG4gIHJldHVybiBbZmFsc2UsIHRydWUsIG51bGwsIHVuZGVmaW5lZCwgLi4udmFsdWVzXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU21hbGxJbnQodmFsdWU6IG51bWJlcikge1xuICByZXR1cm4gKFxuICAgIHZhbHVlICUgMSA9PT0gMCAmJiB2YWx1ZSA8PSBJbW1lZGlhdGVDb25zdGFudHMuTUFYX0lOVCAmJiB2YWx1ZSA+PSBJbW1lZGlhdGVDb25zdGFudHMuTUlOX0lOVFxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5jb2RlTmVnYXRpdmUobnVtOiBudW1iZXIpIHtcbiAgaWYgKExPQ0FMX0RFQlVHKSB7XG4gICAgYXNzZXJ0KFxuICAgICAgbnVtICUgMSA9PT0gMCAmJiBudW0gPj0gSW1tZWRpYXRlQ29uc3RhbnRzLk1JTl9JTlQgJiYgbnVtIDwgMCxcbiAgICAgIGBDb3VsZCBub3QgZW5jb2RlIG5lZ2F0aXZlOiAke251bX1gXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBudW0gJiBJbW1lZGlhdGVDb25zdGFudHMuU0lHTl9CSVQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVOZWdhdGl2ZShudW06IG51bWJlcikge1xuICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICBhc3NlcnQoXG4gICAgICBudW0gJSAxID09PSAwICYmIG51bSA8IH5JbW1lZGlhdGVDb25zdGFudHMuTUFYX0lOVCAmJiBudW0gPj0gSW1tZWRpYXRlQ29uc3RhbnRzLk1JTl9TTUksXG4gICAgICBgQ291bGQgbm90IGRlY29kZSBuZWdhdGl2ZTogJHtudW19YFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gbnVtIHwgfkltbWVkaWF0ZUNvbnN0YW50cy5TSUdOX0JJVDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZVBvc2l0aXZlKG51bTogbnVtYmVyKSB7XG4gIGlmIChMT0NBTF9ERUJVRykge1xuICAgIGFzc2VydChcbiAgICAgIG51bSAlIDEgPT09IDAgJiYgbnVtID49IDAgJiYgbnVtIDw9IEltbWVkaWF0ZUNvbnN0YW50cy5NQVhfSU5ULFxuICAgICAgYENvdWxkIG5vdCBlbmNvZGUgcG9zaXRpdmU6ICR7bnVtfWBcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIH5udW07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVQb3NpdGl2ZShudW06IG51bWJlcikge1xuICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICBhc3NlcnQoXG4gICAgICBudW0gJSAxID09PSAwICYmIG51bSA8PSAwICYmIG51bSA+PSB+SW1tZWRpYXRlQ29uc3RhbnRzLk1BWF9JTlQsXG4gICAgICBgQ291bGQgbm90IGRlY29kZSBwb3NpdGl2ZTogJHtudW19YFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gfm51bTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZUhhbmRsZShudW06IG51bWJlcikge1xuICBpZiAoTE9DQUxfREVCVUcpIHtcbiAgICBhc3NlcnQoXG4gICAgICBudW0gJSAxID09PSAwICYmIG51bSA+PSAwICYmIG51bSA8PSBJbW1lZGlhdGVDb25zdGFudHMuTUFYX1NNSSxcbiAgICAgIGBDb3VsZCBub3QgZW5jb2RlIGhhbmRsZTogJHtudW19YFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gbnVtO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlSGFuZGxlKG51bTogbnVtYmVyKSB7XG4gIGlmIChMT0NBTF9ERUJVRykge1xuICAgIGFzc2VydChcbiAgICAgIG51bSAlIDEgPT09IDAgJiYgbnVtIDw9IEltbWVkaWF0ZUNvbnN0YW50cy5NQVhfU01JICYmIG51bSA+PSAwLFxuICAgICAgYENvdWxkIG5vdCBkZWNvZGUgaGFuZGxlOiAke251bX1gXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBudW07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVJbW1lZGlhdGUobnVtOiBudW1iZXIpIHtcbiAgbnVtIHw9IDA7XG4gIHJldHVybiBudW0gPCAwID8gZW5jb2RlTmVnYXRpdmUobnVtKSA6IGVuY29kZVBvc2l0aXZlKG51bSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVJbW1lZGlhdGUobnVtOiBudW1iZXIpIHtcbiAgbnVtIHw9IDA7XG4gIHJldHVybiBudW0gPiBJbW1lZGlhdGVDb25zdGFudHMuU0lHTl9CSVQgPyBkZWNvZGVQb3NpdGl2ZShudW0pIDogZGVjb2RlTmVnYXRpdmUobnVtKTtcbn1cblxuLy8gV2FybVxuWzEsIDIsIDNdLmZvckVhY2goKHgpID0+IGRlY29kZUhhbmRsZShlbmNvZGVIYW5kbGUoeCkpKTtcblsxLCAtMV0uZm9yRWFjaCgoeCkgPT4gZGVjb2RlSW1tZWRpYXRlKGVuY29kZUltbWVkaWF0ZSh4KSkpO1xuIiwiaW1wb3J0IHsgSGFuZGxlUmVzdWx0LCBUZW1wbGF0ZSwgVGVtcGxhdGVPaywgT2tIYW5kbGUsIEVyckhhbmRsZSB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gdW53cmFwSGFuZGxlKGhhbmRsZTogSGFuZGxlUmVzdWx0KTogbnVtYmVyIHtcbiAgaWYgKHR5cGVvZiBoYW5kbGUgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIGhhbmRsZTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZXJyb3IgPSBoYW5kbGUuZXJyb3JzWzBdO1xuICAgIHRocm93IG5ldyBFcnJvcihgQ29tcGlsZSBFcnJvcjogJHtlcnJvci5wcm9ibGVtfSBAICR7ZXJyb3Iuc3Bhbi5zdGFydH0uLiR7ZXJyb3Iuc3Bhbi5lbmR9YCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVud3JhcFRlbXBsYXRlKHRlbXBsYXRlOiBUZW1wbGF0ZSk6IFRlbXBsYXRlT2sge1xuICBpZiAodGVtcGxhdGUucmVzdWx0ID09PSAnZXJyb3InKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYENvbXBpbGUgRXJyb3I6ICR7dGVtcGxhdGUucHJvYmxlbX0gQCAke3RlbXBsYXRlLnNwYW4uc3RhcnR9Li4ke3RlbXBsYXRlLnNwYW4uZW5kfWBcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHRlbXBsYXRlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEhhbmRsZShoYW5kbGU6IEhhbmRsZVJlc3VsdCk6IG51bWJlciB7XG4gIGlmICh0eXBlb2YgaGFuZGxlID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiBoYW5kbGU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGhhbmRsZS5oYW5kbGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzT2tIYW5kbGUoaGFuZGxlOiBIYW5kbGVSZXN1bHQpOiBoYW5kbGUgaXMgT2tIYW5kbGUge1xuICByZXR1cm4gdHlwZW9mIGhhbmRsZSA9PT0gJ251bWJlcic7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0VyckhhbmRsZShoYW5kbGU6IEhhbmRsZVJlc3VsdCk6IGhhbmRsZSBpcyBFcnJIYW5kbGUge1xuICByZXR1cm4gdHlwZW9mIGhhbmRsZSA9PT0gJ251bWJlcic7XG59XG4iLCJleHBvcnQgZGVmYXVsdCAodHlwZW9mIFdlYWtTZXQgPT09ICdmdW5jdGlvbidcbiAgPyBXZWFrU2V0XG4gIDogY2xhc3MgV2Vha1NldFBvbHlGaWxsPFQgZXh0ZW5kcyBvYmplY3Q+IHtcbiAgICAgIHByaXZhdGUgX21hcCA9IG5ldyBXZWFrTWFwKCk7XG5cbiAgICAgIGFkZCh2YWw6IFQpOiB0aGlzIHtcbiAgICAgICAgdGhpcy5fbWFwLnNldCh2YWwsIHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgZGVsZXRlKHZhbDogVCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWFwLmRlbGV0ZSh2YWwpO1xuICAgICAgfVxuXG4gICAgICBoYXModmFsOiBUKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9tYXAuaGFzKHZhbCk7XG4gICAgICB9XG4gICAgfSkgYXMgV2Vha1NldENvbnN0cnVjdG9yO1xuIiwiaW1wb3J0IHsgdW5yZWFjaGFibGUgfSBmcm9tICcuL3BsYXRmb3JtLXV0aWxzJztcbmltcG9ydCB7IE5vZGVUeXBlLCBTaW1wbGVEb2N1bWVudCwgU2ltcGxlRWxlbWVudCwgU2ltcGxlTm9kZSB9IGZyb20gJ0BzaW1wbGUtZG9tL2ludGVyZmFjZSc7XG5cbmludGVyZmFjZSBHZW5lcmljRWxlbWVudFRhZ3Mge1xuICBIVE1MOiBIVE1MRWxlbWVudDtcbiAgU1ZHOiBTVkdFbGVtZW50O1xuICBFTEVNRU5UOiBIVE1MRWxlbWVudCB8IFNWR0VsZW1lbnQ7XG59XG5cbmludGVyZmFjZSBHZW5lcmljTm9kZVRhZ3Mge1xuICBOT0RFOiBOb2RlO1xufVxuXG50eXBlIEdlbmVyaWNOb2RlVGFnID0ga2V5b2YgR2VuZXJpY05vZGVUYWdzO1xuXG5pbnRlcmZhY2UgQnJvd3NlckVsZW1lbnRUYWdzIGV4dGVuZHMgSFRNTEVsZW1lbnRUYWdOYW1lTWFwLCBHZW5lcmljRWxlbWVudFRhZ3Mge31cbnR5cGUgQnJvd3NlckVsZW1lbnRUYWcgPSBrZXlvZiBCcm93c2VyRWxlbWVudFRhZ3M7XG5cbmludGVyZmFjZSBCcm93c2VyVGFncyBleHRlbmRzIEJyb3dzZXJFbGVtZW50VGFncywgR2VuZXJpY05vZGVUYWdzIHt9XG50eXBlIEJyb3dzZXJUYWcgPSBrZXlvZiBCcm93c2VyVGFncztcblxudHlwZSBOb2RlQ2hlY2s8TiBleHRlbmRzIE5vZGU+ID0gKG5vZGU6IE5vZGUpID0+IG5vZGUgaXMgTjtcbnR5cGUgU3VnYXJ5Tm9kZUNoZWNrPEsgZXh0ZW5kcyBCcm93c2VyVGFnID0gQnJvd3NlclRhZz4gPSBOb2RlQ2hlY2s8QnJvd3NlclRhZ3NbS10+IHwgSyB8IEtbXTtcbnR5cGUgTm9kZUZvclN1Z2FyeUNoZWNrPFMgZXh0ZW5kcyBTdWdhcnlOb2RlQ2hlY2s8QnJvd3NlclRhZz4+ID0gUyBleHRlbmRzIE5vZGVDaGVjazxpbmZlciBOPlxuICA/IE5cbiAgOiBTIGV4dGVuZHMga2V5b2YgQnJvd3NlclRhZ3NcbiAgPyBCcm93c2VyVGFnc1tTXVxuICA6IFMgZXh0ZW5kcyAoa2V5b2YgQnJvd3NlclRhZ3MpW11cbiAgPyBCcm93c2VyVGFnc1tTW251bWJlcl1dXG4gIDogbmV2ZXI7XG5cbnR5cGUgQnJvd3Nlck5vZGUgPSBFbGVtZW50IHwgRG9jdW1lbnQgfCBEb2N1bWVudEZyYWdtZW50IHwgVGV4dCB8IENvbW1lbnQgfCBOb2RlO1xuXG5leHBvcnQgZnVuY3Rpb24gY2FzdFRvU2ltcGxlKGRvYzogRG9jdW1lbnQgfCBTaW1wbGVEb2N1bWVudCk6IFNpbXBsZURvY3VtZW50O1xuZXhwb3J0IGZ1bmN0aW9uIGNhc3RUb1NpbXBsZShlbGVtOiBFbGVtZW50IHwgU2ltcGxlRWxlbWVudCk6IFNpbXBsZUVsZW1lbnQ7XG5leHBvcnQgZnVuY3Rpb24gY2FzdFRvU2ltcGxlKG5vZGU6IE5vZGUgfCBTaW1wbGVOb2RlKTogU2ltcGxlTm9kZTtcbmV4cG9ydCBmdW5jdGlvbiBjYXN0VG9TaW1wbGUoXG4gIG5vZGU6IERvY3VtZW50IHwgRWxlbWVudCB8IE5vZGUgfCBTaW1wbGVEb2N1bWVudCB8IFNpbXBsZUVsZW1lbnQgfCBTaW1wbGVOb2RlXG4pIHtcbiAgaWYgKGlzRG9jdW1lbnQobm9kZSkpIHtcbiAgICByZXR1cm4gbm9kZSBhcyBTaW1wbGVEb2N1bWVudDtcbiAgfSBlbHNlIGlmIChpc0VsZW1lbnQobm9kZSkpIHtcbiAgICByZXR1cm4gbm9kZSBhcyBTaW1wbGVFbGVtZW50O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBub2RlIGFzIFNpbXBsZU5vZGU7XG4gIH1cbn1cblxuLy8gSWYgcGFzc2VkIGEgZG9jdW1lbnQsIHZlcmlmeSB3ZSdyZSBpbiB0aGUgYnJvd3NlciBhbmQgcmV0dXJuIGl0IGFzIGEgRG9jdW1lbnRcbmV4cG9ydCBmdW5jdGlvbiBjYXN0VG9Ccm93c2VyKGRvYzogRG9jdW1lbnQgfCBTaW1wbGVEb2N1bWVudCk6IERvY3VtZW50O1xuLy8gSWYgd2UgZG9uJ3Qga25vdyB3aGF0IHRoaXMgaXMsIGJ1dCB0aGUgY2hlY2sgcmVxdWlyZXMgaXQgdG8gYmUgYW4gZWxlbWVudCxcbi8vIHRoZSBjYXN0IHdpbGwgbWFuZGF0ZSB0aGF0IGl0J3MgYSBicm93c2VyIGVsZW1lbnRcbmV4cG9ydCBmdW5jdGlvbiBjYXN0VG9Ccm93c2VyPFMgZXh0ZW5kcyBTdWdhcnlOb2RlQ2hlY2s8QnJvd3NlckVsZW1lbnRUYWc+PihcbiAgbm9kZTogQnJvd3Nlck5vZGUgfCBTaW1wbGVOb2RlLFxuICBjaGVjazogU1xuKTogTm9kZUZvclN1Z2FyeUNoZWNrPFM+O1xuLy8gRmluYWxseSwgaWYgaXQncyBhIG1vcmUgZ2VuZXJpYyBjaGVjaywgdGhlIGNhc3Qgd2lsbCBtYW5kYXRlIHRoYXQgaXQncyBhXG4vLyBicm93c2VyIG5vZGUgYW5kIHJldHVybiBhIEJyb3dzZXJOb2RlVXRpbHMgY29ycmVzcG9uZGluZyB0byB0aGUgY2hlY2tcbmV4cG9ydCBmdW5jdGlvbiBjYXN0VG9Ccm93c2VyPFMgZXh0ZW5kcyBTdWdhcnlOb2RlQ2hlY2s8R2VuZXJpY05vZGVUYWc+PihcbiAgZWxlbWVudDogQnJvd3Nlck5vZGUgfCBTaW1wbGVOb2RlLFxuICBjaGVjazogU1xuKTogTm9kZUZvclN1Z2FyeUNoZWNrPFM+O1xuZXhwb3J0IGZ1bmN0aW9uIGNhc3RUb0Jyb3dzZXI8SyBleHRlbmRzIGtleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcD4oXG4gIGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQgfCBFbGVtZW50LFxuICBjaGVjazogS1xuKTogSFRNTEVsZW1lbnRUYWdOYW1lTWFwW0tdO1xuZXhwb3J0IGZ1bmN0aW9uIGNhc3RUb0Jyb3dzZXI8UyBleHRlbmRzIFN1Z2FyeU5vZGVDaGVjaz4oXG4gIG5vZGU6IFNpbXBsZU5vZGUgfCBCcm93c2VyTm9kZSB8IG51bGwgfCB1bmRlZmluZWQsXG4gIHN1Z2FyeUNoZWNrPzogU1xuKTogRG9jdW1lbnQgfCBOb2RlRm9yU3VnYXJ5Q2hlY2s8Uz4gfCBudWxsIHtcbiAgaWYgKG5vZGUgPT09IG51bGwgfHwgbm9kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0F0dGVtcHRlZCB0byBjYXN0IHRvIGEgYnJvd3NlciBub2RlIGluIGEgbm9uLWJyb3dzZXIgY29udGV4dCcpO1xuICB9XG5cbiAgaWYgKGlzRG9jdW1lbnQobm9kZSkpIHtcbiAgICByZXR1cm4gbm9kZSBhcyBEb2N1bWVudDtcbiAgfVxuXG4gIGlmIChub2RlLm93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ0F0dGVtcHRlZCB0byBjYXN0IHRvIGEgYnJvd3NlciBub2RlIHdpdGggYSBub2RlIHRoYXQgd2FzIG5vdCBjcmVhdGVkIGZyb20gdGhpcyBkb2N1bWVudCdcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIGNoZWNrTm9kZTxTPihub2RlLCBzdWdhcnlDaGVjayEpO1xufVxuXG5mdW5jdGlvbiBjaGVja0Vycm9yKGZyb206IHN0cmluZywgY2hlY2s6IFN1Z2FyeU5vZGVDaGVjayk6IEVycm9yIHtcbiAgcmV0dXJuIG5ldyBFcnJvcihgY2Fubm90IGNhc3QgYSAke2Zyb219IGludG8gJHtjaGVja31gKTtcbn1cblxuZnVuY3Rpb24gaXNEb2N1bWVudChub2RlOiBOb2RlIHwgU2ltcGxlTm9kZSB8IFNpbXBsZURvY3VtZW50KTogbm9kZSBpcyBEb2N1bWVudCB8IFNpbXBsZURvY3VtZW50IHtcbiAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IE5vZGVUeXBlLkRPQ1VNRU5UX05PREU7XG59XG5cbmZ1bmN0aW9uIGlzRWxlbWVudChub2RlOiBOb2RlIHwgU2ltcGxlTm9kZSB8IFNpbXBsZUVsZW1lbnQpOiBub2RlIGlzIEVsZW1lbnQgfCBTaW1wbGVFbGVtZW50IHtcbiAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IE5vZGVUeXBlLkVMRU1FTlRfTk9ERTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrTm9kZTxTIGV4dGVuZHMgU3VnYXJ5Tm9kZUNoZWNrPihcbiAgbm9kZTogTm9kZSB8IG51bGwsXG4gIGNoZWNrOiBTXG4pOiBOb2RlRm9yU3VnYXJ5Q2hlY2s8Uz4ge1xuICBsZXQgaXNNYXRjaCA9IGZhbHNlO1xuXG4gIGlmIChub2RlICE9PSBudWxsKSB7XG4gICAgaWYgKHR5cGVvZiBjaGVjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlzTWF0Y2ggPSBzdHJpbmdDaGVja05vZGUobm9kZSwgY2hlY2sgYXMgQnJvd3NlclRhZyk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGNoZWNrKSkge1xuICAgICAgaXNNYXRjaCA9IGNoZWNrLnNvbWUoKGMpID0+IHN0cmluZ0NoZWNrTm9kZShub2RlLCBjIGFzIEJyb3dzZXJUYWcpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgdW5yZWFjaGFibGUoKTtcbiAgICB9XG4gIH1cblxuICBpZiAoaXNNYXRjaCkge1xuICAgIHJldHVybiBub2RlIGFzIE5vZGVGb3JTdWdhcnlDaGVjazxTPjtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBjaGVja0Vycm9yKGBTaW1wbGVFbGVtZW50KCR7bm9kZX0pYCwgY2hlY2spO1xuICB9XG59XG5cbmZ1bmN0aW9uIHN0cmluZ0NoZWNrTm9kZTxTIGV4dGVuZHMgQnJvd3NlclRhZz4obm9kZTogTm9kZSwgY2hlY2s6IFMpOiBub2RlIGlzIEJyb3dzZXJUYWdzW1NdIHtcbiAgc3dpdGNoIChjaGVjaykge1xuICAgIGNhc2UgJ05PREUnOlxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgY2FzZSAnSFRNTCc6XG4gICAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50O1xuICAgIGNhc2UgJ1NWRyc6XG4gICAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIFNWR0VsZW1lbnQ7XG4gICAgY2FzZSAnRUxFTUVOVCc6XG4gICAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIEVsZW1lbnQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIGlmIChjaGVjay50b1VwcGVyQ2FzZSgpID09PSBjaGVjaykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJVRzogdGhpcyBjb2RlIGlzIG1pc3NpbmcgaGFuZGxpbmcgZm9yIGEgZ2VuZXJpYyBub2RlIHR5cGVgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBub2RlIGluc3RhbmNlb2YgRWxlbWVudCAmJiBub2RlLnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gY2hlY2s7XG4gIH1cbn1cbiIsImltcG9ydCB7IE9wdGlvbiwgUHJlc2VudEFycmF5IH0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ByZXNlbnQ8VD4obGlzdDogcmVhZG9ubHkgVFtdKTogbGlzdCBpcyBQcmVzZW50QXJyYXk8VD4ge1xuICByZXR1cm4gbGlzdC5sZW5ndGggPiAwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaWZQcmVzZW50PFQsIFUsIFY+KFxuICBsaXN0OiBUW10sXG4gIGlmUHJlc2VudDogKGlucHV0OiBQcmVzZW50QXJyYXk8VD4pID0+IFUsXG4gIG90aGVyd2lzZTogKCkgPT4gVlxuKTogVSB8IFYge1xuICBpZiAoaXNQcmVzZW50KGxpc3QpKSB7XG4gICAgcmV0dXJuIGlmUHJlc2VudChsaXN0KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gb3RoZXJ3aXNlKCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUHJlc2VudE9wdGlvbjxUPihsaXN0OiBUW10pOiBPcHRpb248UHJlc2VudEFycmF5PFQ+PiB7XG4gIGlmIChpc1ByZXNlbnQobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0UHJlc2VudDxUPihcbiAgbGlzdDogVFtdLFxuICBtZXNzYWdlID0gYHVuZXhwZWN0ZWQgZW1wdHkgbGlzdGBcbik6IGFzc2VydHMgbGlzdCBpcyBQcmVzZW50QXJyYXk8VD4ge1xuICBpZiAoIWlzUHJlc2VudChsaXN0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFwUHJlc2VudDxULCBVPihsaXN0OiBQcmVzZW50QXJyYXk8VD4sIGNhbGxiYWNrOiAoaW5wdXQ6IFQpID0+IFUpOiBQcmVzZW50QXJyYXk8VT47XG5leHBvcnQgZnVuY3Rpb24gbWFwUHJlc2VudDxULCBVPihcbiAgbGlzdDogUHJlc2VudEFycmF5PFQ+IHwgbnVsbCxcbiAgY2FsbGJhY2s6IChpbnB1dDogVCkgPT4gVVxuKTogUHJlc2VudEFycmF5PFU+IHwgbnVsbDtcbmV4cG9ydCBmdW5jdGlvbiBtYXBQcmVzZW50PFQsIFU+KFxuICBsaXN0OiBQcmVzZW50QXJyYXk8VD4gfCBudWxsLFxuICBjYWxsYmFjazogKGlucHV0OiBUKSA9PiBVXG4pOiBQcmVzZW50QXJyYXk8VT4gfCBudWxsIHtcbiAgaWYgKGxpc3QgPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBsZXQgb3V0OiBVW10gPSBbXTtcblxuICBmb3IgKGxldCBpdGVtIG9mIGxpc3QpIHtcbiAgICBvdXQucHVzaChjYWxsYmFjayhpdGVtKSk7XG4gIH1cblxuICByZXR1cm4gb3V0IGFzIFByZXNlbnRBcnJheTxVPjtcbn1cbiIsImltcG9ydCB7IERFQlVHIH0gZnJvbSAnQGdsaW1tZXIvZW52JztcbmltcG9ydCB7IEhBU19OQVRJVkVfUFJPWFkgfSBmcm9tICcuL3BsYXRmb3JtLXV0aWxzJztcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gYnVpbGRVbnRvdWNoYWJsZVRoaXMoc291cmNlOiBzdHJpbmcpOiBudWxsIHwgb2JqZWN0IHtcbiAgbGV0IGNvbnRleHQ6IG51bGwgfCBvYmplY3QgPSBudWxsO1xuICBpZiAoREVCVUcgJiYgSEFTX05BVElWRV9QUk9YWSkge1xuICAgIGxldCBhc3NlcnRPblByb3BlcnR5ID0gKHByb3BlcnR5OiBzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2wpID0+IHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFlvdSBhY2Nlc3NlZCBcXGB0aGlzLiR7U3RyaW5nKFxuICAgICAgICAgIHByb3BlcnR5XG4gICAgICAgICl9XFxgIGZyb20gYSBmdW5jdGlvbiBwYXNzZWQgdG8gdGhlICR7c291cmNlfSwgYnV0IHRoZSBmdW5jdGlvbiBpdHNlbGYgd2FzIG5vdCBib3VuZCB0byBhIHZhbGlkIFxcYHRoaXNcXGAgY29udGV4dC4gQ29uc2lkZXIgdXBkYXRpbmcgdG8gdXNlIGEgYm91bmQgZnVuY3Rpb24gKGZvciBpbnN0YW5jZSwgdXNlIGFuIGFycm93IGZ1bmN0aW9uLCBcXGAoKSA9PiB7fVxcYCkuYFxuICAgICAgKTtcbiAgICB9O1xuXG4gICAgY29udGV4dCA9IG5ldyBQcm94eShcbiAgICAgIHt9LFxuICAgICAge1xuICAgICAgICBnZXQoX3RhcmdldDoge30sIHByb3BlcnR5OiBzdHJpbmcgfCBzeW1ib2wpIHtcbiAgICAgICAgICBhc3NlcnRPblByb3BlcnR5KHByb3BlcnR5KTtcbiAgICAgICAgfSxcblxuICAgICAgICBzZXQoX3RhcmdldDoge30sIHByb3BlcnR5OiBzdHJpbmcgfCBzeW1ib2wpIHtcbiAgICAgICAgICBhc3NlcnRPblByb3BlcnR5KHByb3BlcnR5KTtcblxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSxcblxuICAgICAgICBoYXMoX3RhcmdldDoge30sIHByb3BlcnR5OiBzdHJpbmcgfCBzeW1ib2wpIHtcbiAgICAgICAgICBhc3NlcnRPblByb3BlcnR5KHByb3BlcnR5KTtcblxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSxcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIGNvbnRleHQ7XG59XG4iLCJpbXBvcnQgeyBERUJVRyB9IGZyb20gJ0BnbGltbWVyL2Vudic7XG5cbmxldCBkZWJ1Z1RvU3RyaW5nOiB1bmRlZmluZWQgfCAoKHZhbHVlOiB1bmtub3duKSA9PiBzdHJpbmcpO1xuXG5pZiAoREVCVUcpIHtcbiAgbGV0IGdldEZ1bmN0aW9uTmFtZSA9IChmbjogRnVuY3Rpb24pID0+IHtcbiAgICBsZXQgZnVuY3