Innovenergy_trunk/frontend/node_modules/testcafe/lib/runner/browser-set.js

118 lines
21 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const events_1 = require("events");
const time_limit_promise_1 = __importDefault(require("time-limit-promise"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const lodash_1 = require("lodash");
const runtime_1 = require("../errors/runtime");
const types_1 = require("../errors/types");
const status_1 = __importDefault(require("../browser/connection/status"));
const get_hints_1 = __importDefault(require("../browser/connection/get-hints"));
const string_1 = require("../utils/string");
const RELEASE_TIMEOUT = 10000;
const COUNT_OWN_AND_OUTER_LISTENERS = 3;
class BrowserSet extends events_1.EventEmitter {
constructor(browserConnectionGroups, options) {
super();
this._pendingReleases = [];
this.browserConnectionGroups = browserConnectionGroups;
this._browserConnections = (0, lodash_1.flatten)(browserConnectionGroups);
this._options = options;
this._browserErrorHandler = (error) => this.emit('error', error);
this._browserConnections.forEach(bc => bc.on('error', this._browserErrorHandler));
// NOTE: We're setting an empty error handler, because Node kills the process on an 'error' event
// if there is no handler. See: https://nodejs.org/api/events.html#events_class_events_eventemitter
this.on('error', lodash_1.noop);
this.setMaxListeners(COUNT_OWN_AND_OUTER_LISTENERS + this._browserConnections.length);
}
static async _waitIdle(bc) {
if (bc.idle || !bc.isReady())
return;
await (0, promisify_event_1.default)(bc, 'idle');
}
static async _closeConnection(bc) {
if (bc.status === status_1.default.closed || bc.status === status_1.default.closing)
return;
await bc.close();
}
async _waitConnectionOpened(bc) {
const openedTimeout = this._options.browserInitTimeout || await bc.getDefaultBrowserInitTimeout();
const timeoutErr = new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotEstablishBrowserConnection);
const openedOrError = Promise.race([
(0, promisify_event_1.default)(this, 'error'),
(0, promisify_event_1.default)(bc, 'opened'),
]);
return (0, time_limit_promise_1.default)(openedOrError, openedTimeout, { rejectWith: timeoutErr });
}
async _waitConnectionsOpened() {
return Promise.all(this._browserConnections
.filter(bc => bc.status !== status_1.default.opened)
.map(notOpenedConnection => this._waitConnectionOpened(notOpenedConnection)));
}
_checkForDisconnections() {
const disconnectedUserAgents = this._browserConnections
.filter(bc => bc.status === status_1.default.closed)
.map(bc => bc.userAgent);
if (disconnectedUserAgents.length)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotRunAgainstDisconnectedBrowsers, disconnectedUserAgents.join(', '));
}
async prepareConnections() {
await this._checkForDisconnections();
await this._waitConnectionsOpened();
}
// NOTE: creates and prepares BrowserSet instance with given browser connections
static async from(browserConnections, opts) {
const browserSet = new BrowserSet(browserConnections, opts);
try {
const prepareConnections = browserSet.prepareConnections();
const browserSetError = (0, promisify_event_1.default)(browserSet, 'error');
await Promise.race([prepareConnections, browserSetError]);
return browserSet;
}
catch (e) {
const finalError = e.code === types_1.RUNTIME_ERRORS.cannotEstablishBrowserConnection
? browserSet.createBrowserConnectionError(e)
: e;
await browserSet.dispose();
throw finalError;
}
}
createBrowserConnectionError(error) {
const notOpenedConnections = this._browserConnections.filter(bc => bc.status !== status_1.default.opened);
const numOfAllConnections = this._browserConnections.length;
const numOfNotOpenedConnections = notOpenedConnections.length;
const listOfNotOpenedConnections = (0, string_1.createList)(notOpenedConnections.map(bc => bc.browserInfo.alias));
const listOfHints = (0, string_1.createList)((0, get_hints_1.default)(this._browserConnections, this._options));
return new runtime_1.BrowserConnectionError(error.message, numOfNotOpenedConnections, numOfAllConnections, listOfNotOpenedConnections, listOfHints);
}
async releaseConnection(bc) {
if (!this._browserConnections.includes(bc))
return;
(0, lodash_1.pull)(this._browserConnections, bc);
bc.removeListener('error', this._browserErrorHandler);
const appropriateStateSwitch = bc.permanent ?
BrowserSet._waitIdle(bc) :
BrowserSet._closeConnection(bc);
const release = (0, time_limit_promise_1.default)(appropriateStateSwitch, RELEASE_TIMEOUT)
.then(() => (0, lodash_1.pull)(this._pendingReleases, release));
this._pendingReleases.push(release);
return release; // eslint-disable-line consistent-return
}
async dispose() {
// NOTE: When browserConnection is cancelled, it is removed from
// the this.connections array, which leads to shifting indexes
// towards the beginning. So, we must copy the array in order to iterate it,
// or we can perform iteration from the end to the beginning.
await this._browserConnections.reduceRight(async (_, bc) => {
await this.releaseConnection(bc);
return bc;
}, Promise.resolve({}));
await Promise.all(this._pendingReleases);
}
}
exports.default = BrowserSet;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJvd3Nlci1zZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2Jyb3dzZXItc2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQXNDO0FBQ3RDLDRFQUF1RDtBQUN2RCxzRUFBNkM7QUFDN0MsbUNBSWdCO0FBRWhCLCtDQUF5RTtBQUN6RSwyQ0FBaUQ7QUFFakQsMEVBQW1FO0FBRW5FLGdGQUF3RTtBQUN4RSw0Q0FBNkM7QUFFN0MsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDO0FBRTlCLE1BQU0sNkJBQTZCLEdBQUcsQ0FBQyxDQUFDO0FBRXhDLE1BQXFCLFVBQVcsU0FBUSxxQkFBWTtJQU9oRCxZQUFvQix1QkFBOEMsRUFBRSxPQUEwQjtRQUMxRixLQUFLLEVBQUUsQ0FBQztRQUVSLElBQUksQ0FBQyxnQkFBZ0IsR0FBVyxFQUFFLENBQUM7UUFDbkMsSUFBSSxDQUFDLHVCQUF1QixHQUFJLHVCQUF1QixDQUFDO1FBQ3hELElBQUksQ0FBQyxtQkFBbUIsR0FBUSxJQUFBLGdCQUFPLEVBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUNqRSxJQUFJLENBQUMsUUFBUSxHQUFtQixPQUFPLENBQUM7UUFFeEMsSUFBSSxDQUFDLG9CQUFvQixHQUFHLENBQUMsS0FBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztRQUV4RSxJQUFJLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQztRQUVsRixpR0FBaUc7UUFDakcsbUdBQW1HO1FBQ25HLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLGFBQUksQ0FBQyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxlQUFlLENBQUMsNkJBQTZCLEdBQUcsSUFBSSxD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O0NBQ0o7QUFsSkQsNkJBa0pDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCBnZXRUaW1lTGltaXRlZFByb21pc2UgZnJvbSAndGltZS1saW1pdC1wcm9taXNlJztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IHtcbiAgICBmbGF0dGVuLFxuICAgIG5vb3AsXG4gICAgcHVsbCBhcyByZW1vdmUsXG59IGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCB7IEJyb3dzZXJDb25uZWN0aW9uRXJyb3IsIEdlbmVyYWxFcnJvciB9IGZyb20gJy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCB7IFJVTlRJTUVfRVJST1JTIH0gZnJvbSAnLi4vZXJyb3JzL3R5cGVzJztcbmltcG9ydCBCcm93c2VyQ29ubmVjdGlvbiBmcm9tICcuLi9icm93c2VyL2Nvbm5lY3Rpb24nO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzIGZyb20gJy4uL2Jyb3dzZXIvY29ubmVjdGlvbi9zdGF0dXMnO1xuaW1wb3J0IHsgQnJvd3NlclNldE9wdGlvbnMgfSBmcm9tICcuL2ludGVyZmFjZXMnO1xuaW1wb3J0IGdldEJyb3dzZXJDb25uZWN0aW9uSGludHMgZnJvbSAnLi4vYnJvd3Nlci9jb25uZWN0aW9uL2dldC1oaW50cyc7XG5pbXBvcnQgeyBjcmVhdGVMaXN0IH0gZnJvbSAnLi4vdXRpbHMvc3RyaW5nJztcblxuY29uc3QgUkVMRUFTRV9USU1FT1VUID0gMTAwMDA7XG5cbmNvbnN0IENPVU5UX09XTl9BTkRfT1VURVJfTElTVEVORVJTID0gMztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQnJvd3NlclNldCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfYnJvd3NlckNvbm5lY3Rpb25zOiBCcm93c2VyQ29ubmVjdGlvbltdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2Jyb3dzZXJFcnJvckhhbmRsZXI6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfcGVuZGluZ1JlbGVhc2VzOiBQcm9taXNlPHZvaWQ+W107XG4gICAgcHJpdmF0ZSByZWFkb25seSBfb3B0aW9uczogQnJvd3NlclNldE9wdGlvbnM7XG4gICAgcHVibGljIGJyb3dzZXJDb25uZWN0aW9uR3JvdXBzOiBCcm93c2VyQ29ubmVjdGlvbltdW107XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IgKGJyb3dzZXJDb25uZWN0aW9uR3JvdXBzOiBCcm93c2VyQ29ubmVjdGlvbltdW10sIG9wdGlvbnM6IEJyb3dzZXJTZXRPcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5fcGVuZGluZ1JlbGVhc2VzICAgICAgICAgPSBbXTtcbiAgICAgICAgdGhpcy5icm93c2VyQ29ubmVjdGlvbkdyb3VwcyAgPSBicm93c2VyQ29ubmVjdGlvbkdyb3VwcztcbiAgICAgICAgdGhpcy5fYnJvd3NlckNvbm5lY3Rpb25zICAgICAgPSBmbGF0dGVuKGJyb3dzZXJDb25uZWN0aW9uR3JvdXBzKTtcbiAgICAgICAgdGhpcy5fb3B0aW9ucyAgICAgICAgICAgICAgICAgPSBvcHRpb25zO1xuXG4gICAgICAgIHRoaXMuX2Jyb3dzZXJFcnJvckhhbmRsZXIgPSAoZXJyb3I6IEVycm9yKSA9PiB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IpO1xuXG4gICAgICAgIHRoaXMuX2Jyb3dzZXJDb25uZWN0aW9ucy5mb3JFYWNoKGJjID0+IGJjLm9uKCdlcnJvcicsIHRoaXMuX2Jyb3dzZXJFcnJvckhhbmRsZXIpKTtcblxuICAgICAgICAvLyBOT1RFOiBXZSdyZSBzZXR0aW5nIGFuIGVtcHR5IGVycm9yIGhhbmRsZXIsIGJlY2F1c2UgTm9kZSBraWxscyB0aGUgcHJvY2VzcyBvbiBhbiAnZXJyb3InIGV2ZW50XG4gICAgICAgIC8vIGlmIHRoZXJlIGlzIG5vIGhhbmRsZXIuIFNlZTogaHR0cHM6Ly9ub2RlanMub3JnL2FwaS9ldmVudHMuaHRtbCNldmVudHNfY2xhc3NfZXZlbnRzX2V2ZW50ZW1pdHRlclxuICAgICAgICB0aGlzLm9uKCdlcnJvcicsIG5vb3ApO1xuICAgICAgICB0aGlzLnNldE1heExpc3RlbmVycyhDT1VOVF9PV05fQU5EX09VVEVSX0xJU1RFTkVSUyArIHRoaXMuX2Jyb3dzZXJDb25uZWN0aW9ucy5sZW5ndGgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGFzeW5jIF93YWl0SWRsZSAoYmM6IEJyb3dzZXJDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmIChiYy5pZGxlIHx8ICFiYy5pc1JlYWR5KCkpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQoYmMsICdpZGxlJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgYXN5bmMgX2Nsb3NlQ29ubmVjdGlvbiAoYmM6IEJyb3dzZXJDb25uZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmIChiYy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3NlZCB8fCBiYy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3NpbmcpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgYXdhaXQgYmMuY2xvc2UoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF93YWl0Q29ubmVjdGlvbk9wZW5lZCAoYmM6IEJyb3dzZXJDb25uZWN0aW9uKTogUHJvbWlzZTxCcm93c2VyQ29ubmVjdGlvbj4ge1xuICAgICAgICBjb25zdCBvcGVuZWRUaW1lb3V0ID0gdGhpcy5fb3B0aW9ucy5icm93c2VySW5pdFRpbWVvdXQgfHwgYXdhaXQgYmMuZ2V0RGVmYXVsdEJyb3dzZXJJbml0VGltZW91dCgpO1xuICAgICAgICBjb25zdCB0aW1lb3V0RXJyICAgID0gbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5jYW5ub3RFc3RhYmxpc2hCcm93c2VyQ29ubmVjdGlvbik7XG4gICAgICAgIGNvbnN0IG9wZW5lZE9yRXJyb3IgPSBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgcHJvbWlzaWZ5RXZlbnQodGhpcywgJ2Vycm9yJyksXG4gICAgICAgICAgICBwcm9taXNpZnlFdmVudChiYywgJ29wZW5lZCcpLFxuICAgICAgICBdKTtcblxuICAgICAgICByZXR1cm4gZ2V0VGltZUxpbWl0ZWRQcm9taXNlKG9wZW5lZE9yRXJyb3IsIG9wZW5lZFRpbWVvdXQsIHsgcmVqZWN0V2l0aDogdGltZW91dEVyciB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF93YWl0Q29ubmVjdGlvbnNPcGVuZWQgKCk6IFByb21pc2U8QnJvd3NlckNvbm5lY3Rpb25bXT4ge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICB0aGlzLl9icm93c2VyQ29ubmVjdGlvbnNcbiAgICAgICAgICAgICAgICAuZmlsdGVyKGJjID0+IGJjLnN0YXR1cyAhPT0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMub3BlbmVkKVxuICAgICAgICAgICAgICAgIC5tYXAobm90T3BlbmVkQ29ubmVjdGlvbiA9PiB0aGlzLl93YWl0Q29ubmVjdGlvbk9wZW5lZChub3RPcGVuZWRDb25uZWN0aW9uKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jaGVja0ZvckRpc2Nvbm5lY3Rpb25zICgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZGlzY29ubmVjdGVkVXNlckFnZW50cyA9IHRoaXMuX2Jyb3dzZXJDb25uZWN0aW9uc1xuICAgICAgICAgICAgLmZpbHRlcihiYyA9PiBiYy5zdGF0dXMgPT09IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLmNsb3NlZClcbiAgICAgICAgICAgIC5tYXAoYmMgPT4gYmMudXNlckFnZW50KTtcblxuICAgICAgICBpZiAoZGlzY29ubmVjdGVkVXNlckFnZW50cy5sZW5ndGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmNhbm5vdFJ1bkFnYWluc3REaXNjb25uZWN0ZWRCcm93c2VycywgZGlzY29ubmVjdGVkVXNlckFnZW50cy5qb2luKCcsICcpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcHJlcGFyZUNvbm5lY3Rpb25zICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5fY2hlY2tGb3JEaXNjb25uZWN0aW9ucygpO1xuICAgICAgICBhd2FpdCB0aGlzLl93YWl0Q29ubmVjdGlvbnNPcGVuZWQoKTtcbiAgICB9XG5cbiAgICAvLyBOT1RFOiBjcmVhdGVzIGFuZCBwcmVwYXJlcyBCcm93c2VyU2V0IGluc3RhbmNlIHdpdGggZ2l2ZW4gYnJvd3NlciBjb25uZWN0aW9uc1xuICAgIHB1YmxpYyBzdGF0aWMgYXN5bmMgZnJvbSAoYnJvd3NlckNvbm5lY3Rpb25zOiBCcm93c2VyQ29ubmVjdGlvbltdW10sIG9wdHM6IEJyb3dzZXJTZXRPcHRpb25zKTogUHJvbWlzZTxCcm93c2VyU2V0PiB7XG4gICAgICAgIGNvbnN0IGJyb3dzZXJTZXQgPSBuZXcgQnJvd3NlclNldChicm93c2VyQ29ubmVjdGlvbnMsIG9wdHMpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBwcmVwYXJlQ29ubmVjdGlvbnMgPSBicm93c2VyU2V0LnByZXBhcmVDb25uZWN0aW9ucygpO1xuICAgICAgICAgICAgY29uc3QgYnJvd3NlclNldEVycm9yICAgID0gcHJvbWlzaWZ5RXZlbnQoYnJvd3NlclNldCwgJ2Vycm9yJyk7XG5cbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UucmFjZShbIHByZXBhcmVDb25uZWN0aW9ucywgYnJvd3NlclNldEVycm9yIF0pO1xuXG4gICAgICAgICAgICByZXR1cm4gYnJvd3NlclNldDtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBjb25zdCBmaW5hbEVycm9yID0gZS5jb2RlID09PSBSVU5USU1FX0VSUk9SUy5jYW5ub3RFc3RhYmxpc2hCcm93c2VyQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgID8gYnJvd3NlclNldC5jcmVhdGVCcm93c2VyQ29ubmVjdGlvbkVycm9yKGUpXG4gICAgICAgICAgICAgICAgOiBlO1xuXG4gICAgICAgICAgICBhd2FpdCBicm93c2VyU2V0LmRpc3Bvc2UoKTtcblxuICAgICAgICAgICAgdGhyb3cgZmluYWxFcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBjcmVhdGVCcm93c2VyQ29ubmVjdGlvbkVycm9yIChlcnJvcjogRXJyb3IpOiBCcm93c2VyQ29ubmVjdGlvbkVycm9yIHtcbiAgICAgICAgY29uc3Qgbm90T3BlbmVkQ29ubmVjdGlvbnMgPSB0aGlzLl9icm93c2VyQ29ubmVjdGlvbnMuZmlsdGVyKGJjID0+IGJjLnN0YXR1cyAhPT0gQnJvd3NlckNvbm5lY3Rpb25TdGF0dXMub3BlbmVkKTtcblxuICAgICAgICBjb25zdCBudW1PZkFsbENvbm5lY3Rpb25zICAgICAgID0gdGhpcy5fYnJvd3NlckNvbm5lY3Rpb25zLmxlbmd0aDtcbiAgICAgICAgY29uc3QgbnVtT2ZOb3RPcGVuZWRDb25uZWN0aW9ucyA9IG5vdE9wZW5lZENvbm5lY3Rpb25zLmxlbmd0aDtcblxuICAgICAgICBjb25zdCBsaXN0T2ZOb3RPcGVuZWRDb25uZWN0aW9ucyA9IGNyZWF0ZUxpc3Qobm90T3BlbmVkQ29ubmVjdGlvbnMubWFwKGJjID0+IGJjLmJyb3dzZXJJbmZvLmFsaWFzKSk7XG4gICAgICAgIGNvbnN0IGxpc3RPZkhpbnRzICAgICAgICAgICAgICAgID0gY3JlYXRlTGlzdChnZXRCcm93c2VyQ29ubmVjdGlvbkhpbnRzKHRoaXMuX2Jyb3dzZXJDb25uZWN0aW9ucywgdGhpcy5fb3B0aW9ucykpO1xuXG4gICAgICAgIHJldHVybiBuZXcgQnJvd3NlckNvbm5lY3Rpb25FcnJvcihcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICBudW1PZk5vdE9wZW5lZENvbm5lY3Rpb25zLFxuICAgICAgICAgICAgbnVtT2ZBbGxDb25uZWN0aW9ucyxcbiAgICAgICAgICAgIGxpc3RPZk5vdE9wZW5lZENvbm5lY3Rpb25zLFxuICAgICAgICAgICAgbGlzdE9mSGludHNcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcmVsZWFzZUNvbm5lY3Rpb24gKGJjOiBCcm93c2VyQ29ubmVjdGlvbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMuX2Jyb3dzZXJDb25uZWN0aW9ucy5pbmNsdWRlcyhiYykpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgcmVtb3ZlKHRoaXMuX2Jyb3dzZXJDb25uZWN0aW9ucywgYmMpO1xuXG4gICAgICAgIGJjLnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIHRoaXMuX2Jyb3dzZXJFcnJvckhhbmRsZXIpO1xuXG4gICAgICAgIGNvbnN0IGFwcHJvcHJpYXRlU3RhdGVTd2l0Y2ggPSBiYy5wZXJtYW5lbnQgP1xuICAgICAgICAgICAgQnJvd3NlclNldC5fd2FpdElkbGUoYmMpIDpcbiAgICAgICAgICAgIEJyb3dzZXJTZXQuX2Nsb3NlQ29ubmVjdGlvbihiYyk7XG5cbiAgICAgICAgY29uc3QgcmVsZWFzZSA9IGdldFRpbWVMaW1pdGVkUHJvbWlzZShhcHByb3ByaWF0ZVN0YXRlU3dpdGNoLCBSRUxFQVNFX1RJTUVPVVQpXG4gICAgICAgICAgICAudGhlbigoKSA9PiByZW1vdmUodGhpcy5fcGVuZGluZ1JlbGVhc2VzLCByZWxlYXNlKSkgYXMgUHJvbWlzZTx2b2lkPjtcblxuICAgICAgICB0aGlzLl9wZW5kaW5nUmVsZWFzZXMucHVzaChyZWxlYXNlKTtcblxuICAgICAgICByZXR1cm4gcmVsZWFzZTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb25zaXN0ZW50LXJldHVyblxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBkaXNwb3NlICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgLy8gTk9URTogV2hlbiBicm93c2VyQ29ubmVjdGlvbiBpcyBjYW5jZWxsZWQsIGl0IGlzIHJlbW92ZWQgZnJvbVxuICAgICAgICAvLyB0aGUgdGhpcy5jb25uZWN0aW9ucyBhcnJheSwgd2hpY2ggbGVhZHMgdG8gc2hpZnRpbmcgaW5kZXhlc1xuICAgICAgICAvLyB0b3dhcmRzIHRoZSBiZWdpbm5pbmcuIFNvLCB3ZSBtdXN0IGNvcHkgdGhlIGFycmF5IGluIG9yZGVyIHRvIGl0ZXJhdGUgaXQsXG4gICAgICAgIC8vIG9yIHdlIGNhbiBwZXJmb3JtIGl0ZXJhdGlvbiBmcm9tIHRoZSBlbmQgdG8gdGhlIGJlZ2lubmluZy5cbiAgICAgICAgYXdhaXQgdGhpcy5fYnJvd3NlckNvbm5lY3Rpb25zLnJlZHVjZVJpZ2h0KGFzeW5jIChfLCBiYykgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZWxlYXNlQ29ubmVjdGlvbihiYyk7XG5cbiAgICAgICAgICAgIHJldHVybiBiYztcbiAgICAgICAgfSwgUHJvbWlzZS5yZXNvbHZlKHt9KSk7XG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodGhpcy5fcGVuZGluZ1JlbGVhc2VzKTtcbiAgICB9XG59XG4iXX0=