UNPKG

matrix-react-sdk

Version:
153 lines (144 loc) 18.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "PerformanceEntryNames", { enumerable: true, get: function () { return _entryNames.PerformanceEntryNames; } }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _logger = require("matrix-js-sdk/src/logger"); var _entryNames = require("./entry-names"); /* Copyright 2024 New Vector Ltd. Copyright 2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ class PerformanceMonitor { constructor() { (0, _defineProperty2.default)(this, "START_PREFIX", "start:"); (0, _defineProperty2.default)(this, "STOP_PREFIX", "stop:"); (0, _defineProperty2.default)(this, "listeners", []); (0, _defineProperty2.default)(this, "entries", []); } static get instance() { if (!PerformanceMonitor._instance) { PerformanceMonitor._instance = new PerformanceMonitor(); } return PerformanceMonitor._instance; } /** * Starts a performance recording * @param name Name of the recording * @param id Specify an identifier appended to the measurement name * @returns {void} */ start(name, id) { if (!this.supportsPerformanceApi()) { return; } const key = this.buildKey(name, id); if (performance.getEntriesByName(this.START_PREFIX + key).length > 0) { _logger.logger.warn(`Recording already started for: ${name}`); return; } performance.mark(this.START_PREFIX + key); } /** * Stops a performance recording and stores delta duration * with the start marker * @param name Name of the recording * @param id Specify an identifier appended to the measurement name * @returns The measurement */ stop(name, id) { if (!this.supportsPerformanceApi()) { return; } const key = this.buildKey(name, id); if (performance.getEntriesByName(this.START_PREFIX + key).length === 0) { _logger.logger.warn(`No recording started for: ${name}`); return; } performance.mark(this.STOP_PREFIX + key); performance.measure(key, this.START_PREFIX + key, this.STOP_PREFIX + key); this.clear(name, id); const measurement = performance.getEntriesByName(key).pop(); // Keeping a reference to all PerformanceEntry created // by this abstraction for historical events collection // when adding a data callback this.entries.push(measurement); this.listeners.forEach(listener => { if (this.shouldEmit(listener, measurement)) { listener.callback([measurement]); } }); return measurement; } clear(name, id) { if (!this.supportsPerformanceApi()) { return; } const key = this.buildKey(name, id); performance.clearMarks(this.START_PREFIX + key); performance.clearMarks(this.STOP_PREFIX + key); } getEntries({ name, type } = {}) { return this.entries.filter(entry => { const satisfiesName = !name || entry.name === name; const satisfiedType = !type || entry.entryType === type; return satisfiesName && satisfiedType; }); } addPerformanceDataCallback(listener, buffer = false) { this.listeners.push(listener); if (buffer) { const toEmit = this.entries.filter(entry => this.shouldEmit(listener, entry)); if (toEmit.length > 0) { listener.callback(toEmit); } } } removePerformanceDataCallback(callback) { if (!callback) { this.listeners = []; } else { this.listeners.splice(this.listeners.findIndex(listener => listener.callback === callback), 1); } } /** * Tor browser does not support the Performance API * @returns {boolean} true if the Performance API is supported */ supportsPerformanceApi() { return performance !== undefined && performance.mark !== undefined; } shouldEmit(listener, entry) { return !listener.entryNames || listener.entryNames.includes(entry.name); } /** * Internal utility to ensure consistent name for the recording * @param name Name of the recording * @param id Specify an identifier appended to the measurement name * @returns {string} a compound of the name and identifier if present */ buildKey(name, id) { const suffix = id ? `:${id}` : ""; return `${name}${suffix}`; } } // Convenience exports exports.default = PerformanceMonitor; (0, _defineProperty2.default)(PerformanceMonitor, "_instance", void 0); // Exposing those to the window object to bridge them from tests window.mxPerformanceMonitor = PerformanceMonitor.instance; window.mxPerformanceEntryNames = _entryNames.PerformanceEntryNames; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9nZ2VyIiwicmVxdWlyZSIsIl9lbnRyeU5hbWVzIiwiUGVyZm9ybWFuY2VNb25pdG9yIiwiY29uc3RydWN0b3IiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsImluc3RhbmNlIiwiX2luc3RhbmNlIiwic3RhcnQiLCJuYW1lIiwiaWQiLCJzdXBwb3J0c1BlcmZvcm1hbmNlQXBpIiwia2V5IiwiYnVpbGRLZXkiLCJwZXJmb3JtYW5jZSIsImdldEVudHJpZXNCeU5hbWUiLCJTVEFSVF9QUkVGSVgiLCJsZW5ndGgiLCJsb2dnZXIiLCJ3YXJuIiwibWFyayIsInN0b3AiLCJTVE9QX1BSRUZJWCIsIm1lYXN1cmUiLCJjbGVhciIsIm1lYXN1cmVtZW50IiwicG9wIiwiZW50cmllcyIsInB1c2giLCJsaXN0ZW5lcnMiLCJmb3JFYWNoIiwibGlzdGVuZXIiLCJzaG91bGRFbWl0IiwiY2FsbGJhY2siLCJjbGVhck1hcmtzIiwiZ2V0RW50cmllcyIsInR5cGUiLCJmaWx0ZXIiLCJlbnRyeSIsInNhdGlzZmllc05hbWUiLCJzYXRpc2ZpZWRUeXBlIiwiZW50cnlUeXBlIiwiYWRkUGVyZm9ybWFuY2VEYXRhQ2FsbGJhY2siLCJidWZmZXIiLCJ0b0VtaXQiLCJyZW1vdmVQZXJmb3JtYW5jZURhdGFDYWxsYmFjayIsInNwbGljZSIsImZpbmRJbmRleCIsInVuZGVmaW5lZCIsImVudHJ5TmFtZXMiLCJpbmNsdWRlcyIsInN1ZmZpeCIsImV4cG9ydHMiLCJ3aW5kb3ciLCJteFBlcmZvcm1hbmNlTW9uaXRvciIsIm14UGVyZm9ybWFuY2VFbnRyeU5hbWVzIiwiUGVyZm9ybWFuY2VFbnRyeU5hbWVzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BlcmZvcm1hbmNlL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuaW1wb3J0IHsgUGVyZm9ybWFuY2VFbnRyeU5hbWVzIH0gZnJvbSBcIi4vZW50cnktbmFtZXNcIjtcblxuaW50ZXJmYWNlIEdldEVudHJpZXNPcHRpb25zIHtcbiAgICBuYW1lPzogc3RyaW5nO1xuICAgIHR5cGU/OiBzdHJpbmc7XG59XG5cbnR5cGUgUGVyZm9ybWFuY2VDYWxsYmFja0Z1bmN0aW9uID0gKGVudHJ5OiBQZXJmb3JtYW5jZUVudHJ5W10pID0+IHZvaWQ7XG5cbmludGVyZmFjZSBQZXJmb3JtYW5jZURhdGFMaXN0ZW5lciB7XG4gICAgZW50cnlOYW1lcz86IHN0cmluZ1tdO1xuICAgIGNhbGxiYWNrOiBQZXJmb3JtYW5jZUNhbGxiYWNrRnVuY3Rpb247XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBlcmZvcm1hbmNlTW9uaXRvciB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgX2luc3RhbmNlOiBQZXJmb3JtYW5jZU1vbml0b3I7XG5cbiAgICBwcml2YXRlIFNUQVJUX1BSRUZJWCA9IFwic3RhcnQ6XCI7XG4gICAgcHJpdmF0ZSBTVE9QX1BSRUZJWCA9IFwic3RvcDpcIjtcblxuICAgIHByaXZhdGUgbGlzdGVuZXJzOiBQZXJmb3JtYW5jZURhdGFMaXN0ZW5lcltdID0gW107XG4gICAgcHJpdmF0ZSBlbnRyaWVzOiBQZXJmb3JtYW5jZUVudHJ5W10gPSBbXTtcblxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0IGluc3RhbmNlKCk6IFBlcmZvcm1hbmNlTW9uaXRvciB7XG4gICAgICAgIGlmICghUGVyZm9ybWFuY2VNb25pdG9yLl9pbnN0YW5jZSkge1xuICAgICAgICAgICAgUGVyZm9ybWFuY2VNb25pdG9yLl9pbnN0YW5jZSA9IG5ldyBQZXJmb3JtYW5jZU1vbml0b3IoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUGVyZm9ybWFuY2VNb25pdG9yLl9pbnN0YW5jZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdGFydHMgYSBwZXJmb3JtYW5jZSByZWNvcmRpbmdcbiAgICAgKiBAcGFyYW0gbmFtZSBOYW1lIG9mIHRoZSByZWNvcmRpbmdcbiAgICAgKiBAcGFyYW0gaWQgU3BlY2lmeSBhbiBpZGVudGlmaWVyIGFwcGVuZGVkIHRvIHRoZSBtZWFzdXJlbWVudCBuYW1lXG4gICAgICogQHJldHVybnMge3ZvaWR9XG4gICAgICovXG4gICAgcHVibGljIHN0YXJ0KG5hbWU6IHN0cmluZywgaWQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnN1cHBvcnRzUGVyZm9ybWFuY2VBcGkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGtleSA9IHRoaXMuYnVpbGRLZXkobmFtZSwgaWQpO1xuXG4gICAgICAgIGlmIChwZXJmb3JtYW5jZS5nZXRFbnRyaWVzQnlOYW1lKHRoaXMuU1RBUlRfUFJFRklYICsga2V5KS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihgUmVjb3JkaW5nIGFscmVhZHkgc3RhcnRlZCBmb3I6ICR7bmFtZX1gKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHBlcmZvcm1hbmNlLm1hcmsodGhpcy5TVEFSVF9QUkVGSVggKyBrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0b3BzIGEgcGVyZm9ybWFuY2UgcmVjb3JkaW5nIGFuZCBzdG9yZXMgZGVsdGEgZHVyYXRpb25cbiAgICAgKiB3aXRoIHRoZSBzdGFydCBtYXJrZXJcbiAgICAgKiBAcGFyYW0gbmFtZSBOYW1lIG9mIHRoZSByZWNvcmRpbmdcbiAgICAgKiBAcGFyYW0gaWQgU3BlY2lmeSBhbiBpZGVudGlmaWVyIGFwcGVuZGVkIHRvIHRoZSBtZWFzdXJlbWVudCBuYW1lXG4gICAgICogQHJldHVybnMgVGhlIG1lYXN1cmVtZW50XG4gICAgICovXG4gICAgcHVibGljIHN0b3AobmFtZTogc3RyaW5nLCBpZD86IHN0cmluZyk6IFBlcmZvcm1hbmNlRW50cnkgfCB1bmRlZmluZWQge1xuICAgICAgICBpZiAoIXRoaXMuc3VwcG9ydHNQZXJmb3JtYW5jZUFwaSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qga2V5ID0gdGhpcy5idWlsZEtleShuYW1lLCBpZCk7XG4gICAgICAgIGlmIChwZXJmb3JtYW5jZS5nZXRFbnRyaWVzQnlOYW1lKHRoaXMuU1RBUlRfUFJFRklYICsga2V5KS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKGBObyByZWNvcmRpbmcgc3RhcnRlZCBmb3I6ICR7bmFtZX1gKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHBlcmZvcm1hbmNlLm1hcmsodGhpcy5TVE9QX1BSRUZJWCArIGtleSk7XG4gICAgICAgIHBlcmZvcm1hbmNlLm1lYXN1cmUoa2V5LCB0aGlzLlNUQVJUX1BSRUZJWCArIGtleSwgdGhpcy5TVE9QX1BSRUZJWCArIGtleSk7XG5cbiAgICAgICAgdGhpcy5jbGVhcihuYW1lLCBpZCk7XG5cbiAgICAgICAgY29uc3QgbWVhc3VyZW1lbnQgPSBwZXJmb3JtYW5jZS5nZXRFbnRyaWVzQnlOYW1lKGtleSkucG9wKCkhO1xuXG4gICAgICAgIC8vIEtlZXBpbmcgYSByZWZlcmVuY2UgdG8gYWxsIFBlcmZvcm1hbmNlRW50cnkgY3JlYXRlZFxuICAgICAgICAvLyBieSB0aGlzIGFic3RyYWN0aW9uIGZvciBoaXN0b3JpY2FsIGV2ZW50cyBjb2xsZWN0aW9uXG4gICAgICAgIC8vIHdoZW4gYWRkaW5nIGEgZGF0YSBjYWxsYmFja1xuICAgICAgICB0aGlzLmVudHJpZXMucHVzaChtZWFzdXJlbWVudCk7XG5cbiAgICAgICAgdGhpcy5saXN0ZW5lcnMuZm9yRWFjaCgobGlzdGVuZXIpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNob3VsZEVtaXQobGlzdGVuZXIsIG1lYXN1cmVtZW50KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmNhbGxiYWNrKFttZWFzdXJlbWVudF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gbWVhc3VyZW1lbnQ7XG4gICAgfVxuXG4gICAgcHVibGljIGNsZWFyKG5hbWU6IHN0cmluZywgaWQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnN1cHBvcnRzUGVyZm9ybWFuY2VBcGkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGtleSA9IHRoaXMuYnVpbGRLZXkobmFtZSwgaWQpO1xuICAgICAgICBwZXJmb3JtYW5jZS5jbGVhck1hcmtzKHRoaXMuU1RBUlRfUFJFRklYICsga2V5KTtcbiAgICAgICAgcGVyZm9ybWFuY2UuY2xlYXJNYXJrcyh0aGlzLlNUT1BfUFJFRklYICsga2V5KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RW50cmllcyh7IG5hbWUsIHR5cGUgfTogR2V0RW50cmllc09wdGlvbnMgPSB7fSk6IFBlcmZvcm1hbmNlRW50cnlbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVudHJpZXMuZmlsdGVyKChlbnRyeSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2F0aXNmaWVzTmFtZSA9ICFuYW1lIHx8IGVudHJ5Lm5hbWUgPT09IG5hbWU7XG4gICAgICAgICAgICBjb25zdCBzYXRpc2ZpZWRUeXBlID0gIXR5cGUgfHwgZW50cnkuZW50cnlUeXBlID09PSB0eXBlO1xuICAgICAgICAgICAgcmV0dXJuIHNhdGlzZmllc05hbWUgJiYgc2F0aXNmaWVkVHlwZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFkZFBlcmZvcm1hbmNlRGF0YUNhbGxiYWNrKGxpc3RlbmVyOiBQZXJmb3JtYW5jZURhdGFMaXN0ZW5lciwgYnVmZmVyID0gZmFsc2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7XG4gICAgICAgIGlmIChidWZmZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvRW1pdCA9IHRoaXMuZW50cmllcy5maWx0ZXIoKGVudHJ5KSA9PiB0aGlzLnNob3VsZEVtaXQobGlzdGVuZXIsIGVudHJ5KSk7XG4gICAgICAgICAgICBpZiAodG9FbWl0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lci5jYWxsYmFjayh0b0VtaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZVBlcmZvcm1hbmNlRGF0YUNhbGxiYWNrKGNhbGxiYWNrPzogUGVyZm9ybWFuY2VDYWxsYmFja0Z1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxpc3RlbmVycy5zcGxpY2UoXG4gICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lcnMuZmluZEluZGV4KChsaXN0ZW5lcikgPT4gbGlzdGVuZXIuY2FsbGJhY2sgPT09IGNhbGxiYWNrKSxcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRvciBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgdGhlIFBlcmZvcm1hbmNlIEFQSVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSBQZXJmb3JtYW5jZSBBUEkgaXMgc3VwcG9ydGVkXG4gICAgICovXG4gICAgcHJpdmF0ZSBzdXBwb3J0c1BlcmZvcm1hbmNlQXBpKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gcGVyZm9ybWFuY2UgIT09IHVuZGVmaW5lZCAmJiBwZXJmb3JtYW5jZS5tYXJrICE9PSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzaG91bGRFbWl0KGxpc3RlbmVyOiBQZXJmb3JtYW5jZURhdGFMaXN0ZW5lciwgZW50cnk6IFBlcmZvcm1hbmNlRW50cnkpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICFsaXN0ZW5lci5lbnRyeU5hbWVzIHx8IGxpc3RlbmVyLmVudHJ5TmFtZXMuaW5jbHVkZXMoZW50cnkubmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWwgdXRpbGl0eSB0byBlbnN1cmUgY29uc2lzdGVudCBuYW1lIGZvciB0aGUgcmVjb3JkaW5nXG4gICAgICogQHBhcmFtIG5hbWUgTmFtZSBvZiB0aGUgcmVjb3JkaW5nXG4gICAgICogQHBhcmFtIGlkIFNwZWNpZnkgYW4gaWRlbnRpZmllciBhcHBlbmRlZCB0byB0aGUgbWVhc3VyZW1lbnQgbmFtZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IGEgY29tcG91bmQgb2YgdGhlIG5hbWUgYW5kIGlkZW50aWZpZXIgaWYgcHJlc2VudFxuICAgICAqL1xuICAgIHByaXZhdGUgYnVpbGRLZXkobmFtZTogc3RyaW5nLCBpZD86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHN1ZmZpeCA9IGlkID8gYDoke2lkfWAgOiBcIlwiO1xuICAgICAgICByZXR1cm4gYCR7bmFtZX0ke3N1ZmZpeH1gO1xuICAgIH1cbn1cblxuLy8gQ29udmVuaWVuY2UgZXhwb3J0c1xuZXhwb3J0IHsgUGVyZm9ybWFuY2VFbnRyeU5hbWVzIH07XG5cbi8vIEV4cG9zaW5nIHRob3NlIHRvIHRoZSB3aW5kb3cgb2JqZWN0IHRvIGJyaWRnZSB0aGVtIGZyb20gdGVzdHNcbndpbmRvdy5teFBlcmZvcm1hbmNlTW9uaXRvciA9IFBlcmZvcm1hbmNlTW9uaXRvci5pbnN0YW5jZTtcbndpbmRvdy5teFBlcmZvcm1hbmNlRW50cnlOYW1lcyA9IFBlcmZvcm1hbmNlRW50cnlOYW1lcztcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFRQSxJQUFBQSxPQUFBLEdBQUFDLE9BQUE7QUFFQSxJQUFBQyxXQUFBLEdBQUFELE9BQUE7QUFWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFrQmUsTUFBTUUsa0JBQWtCLENBQUM7RUFBQUMsWUFBQTtJQUFBLElBQUFDLGdCQUFBLENBQUFDLE9BQUEsd0JBR2IsUUFBUTtJQUFBLElBQUFELGdCQUFBLENBQUFDLE9BQUEsdUJBQ1QsT0FBTztJQUFBLElBQUFELGdCQUFBLENBQUFDLE9BQUEscUJBRWtCLEVBQUU7SUFBQSxJQUFBRCxnQkFBQSxDQUFBQyxPQUFBLG1CQUNYLEVBQUU7RUFBQTtFQUV4QyxXQUFrQkMsUUFBUUEsQ0FBQSxFQUF1QjtJQUM3QyxJQUFJLENBQUNKLGtCQUFrQixDQUFDSyxTQUFTLEVBQUU7TUFDL0JMLGtCQUFrQixDQUFDSyxTQUFTLEdBQUcsSUFBSUwsa0JBQWtCLENBQUMsQ0FBQztJQUMzRDtJQUNBLE9BQU9BLGtCQUFrQixDQUFDSyxTQUFTO0VBQ3ZDOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNXQyxLQUFLQSxDQUFDQyxJQUFZLEVBQUVDLEVBQVcsRUFBUTtJQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDQyxzQkFBc0IsQ0FBQyxDQUFDLEVBQUU7TUFDaEM7SUFDSjtJQUNBLE1BQU1DLEdBQUcsR0FBRyxJQUFJLENBQUNDLFFBQVEsQ0FBQ0osSUFBSSxFQUFFQyxFQUFFLENBQUM7SUFFbkMsSUFBSUksV0FBVyxDQUFDQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUNDLFlBQVksR0FBR0osR0FBRyxDQUFDLENBQUNLLE1BQU0sR0FBRyxDQUFDLEVBQUU7TUFDbEVDLGNBQU0sQ0FBQ0MsSUFBSSxDQUFDLGtDQUFrQ1YsSUFBSSxFQUFFLENBQUM7TUFDckQ7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