UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

146 lines 19.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = require("child_process"); const debug_1 = __importDefault(require("debug")); const promisify_event_1 = __importDefault(require("promisify-event")); const pinkie_1 = __importDefault(require("pinkie")); const promisified_functions_1 = require("../../promisified-functions"); const commands_1 = __importDefault(require("./commands")); const WORKER_PATH = require.resolve('./worker'); const WORKER_STDIO_CONFIG = ['ignore', 'pipe', 'pipe', 'ipc']; const DEBUG_LOGGER = debug_1.default('testcafe:utils:temp-directory:cleanup-process'); class CleanupProcess { constructor() { this.worker = null; this.initialized = false; this.initPromise = pinkie_1.default.resolve(void 0); this.errorPromise = null; this.messageCounter = 0; this.pendingResponses = {}; } _sendMessage(id, msg) { return pinkie_1.default.race([ promisified_functions_1.sendMessageToChildProcess(this.worker, Object.assign({ id }, msg)), this._waitProcessError() ]); } _onResponse(response) { const pendingResponse = this.pendingResponses[response.id]; if (response.error) { if (pendingResponse) pendingResponse.control.reject(response.error); else this.pendingResponses[response.id] = pinkie_1.default.reject(response.error); } else if (pendingResponse) pendingResponse.control.resolve(); else this.pendingResponses[response.id] = pinkie_1.default.resolve(); } async _waitResponse(id) { if (!this.pendingResponses[id]) { const promiseControl = {}; this.pendingResponses[id] = new pinkie_1.default((resolve, reject) => { Object.assign(promiseControl, { resolve, reject }); }); this.pendingResponses[id].control = promiseControl; } try { await this.pendingResponses[id]; } finally { delete this.pendingResponses[id]; } } async _waitResponseForMessage(msg) { const currentId = this.messageCounter; this.messageCounter++; await this._sendMessage(currentId, msg); await this._waitResponse(currentId); } _waitProcessExit() { return promisify_event_1.default(this.worker, 'exit') .then(exitCode => pinkie_1.default.reject(new Error(`Worker process terminated with code ${exitCode}`))); } _waitProcessError() { if (this.errorPromise) return this.errorPromise; this.errorPromise = promisify_event_1.default(this.worker, 'error'); this.errorPromise.then(() => { this.errorPromise = null; }); return this.errorPromise; } _setupWorkerEventHandlers() { this.worker.on('message', message => this._onResponse(message)); this.worker.stdout.on('data', data => DEBUG_LOGGER('Worker process stdout:\n', String(data))); this.worker.stderr.on('data', data => DEBUG_LOGGER('Worker process stderr:\n', String(data))); } _unrefWorkerProcess() { this.worker.unref(); this.worker.stdout.unref(); this.worker.stderr.unref(); const channel = this.worker.channel || this.worker._channel; channel.unref(); } _handleProcessError(error) { this.initialized = false; DEBUG_LOGGER(error); } init() { this.initPromise = this.initPromise .then(async (initialized) => { if (initialized !== void 0) return initialized; this.worker = child_process_1.spawn(process.argv[0], [WORKER_PATH], { detached: true, stdio: WORKER_STDIO_CONFIG }); this._setupWorkerEventHandlers(); this._unrefWorkerProcess(); const exitPromise = this._waitProcessExit(); try { await pinkie_1.default.race([ this._waitResponseForMessage({ command: commands_1.default.init }), this._waitProcessError(), exitPromise ]); this.initialized = true; exitPromise.catch(error => this._handleProcessError(error)); this.worker.on('error', error => this._handleProcessError(error)); } catch (e) { DEBUG_LOGGER('Failed to start cleanup process'); DEBUG_LOGGER(e); this.initialized = false; } return this.initialized; }); return this.initPromise; } async addDirectory(path) { if (!this.initialized) return; try { await this._waitResponseForMessage({ command: commands_1.default.add, path }); } catch (e) { DEBUG_LOGGER(`Failed to add the ${path} directory to cleanup process`); DEBUG_LOGGER(e); } } async removeDirectory(path) { if (!this.initialized) return; try { await this._waitResponseForMessage({ command: commands_1.default.remove, path }); } catch (e) { DEBUG_LOGGER(`Failed to remove the ${path} directory in cleanup process`); DEBUG_LOGGER(e); } } } exports.default = new CleanupProcess(); module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvdGVtcC1kaXJlY3RvcnkvY2xlYW51cC1wcm9jZXNzL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQXNDO0FBQ3RDLGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0Msb0RBQTZCO0FBQzdCLHVFQUF3RTtBQUN4RSwwREFBa0M7QUFHbEMsTUFBTSxXQUFXLEdBQVcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUN4RCxNQUFNLG1CQUFtQixHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFFOUQsTUFBTSxZQUFZLEdBQUcsZUFBSyxDQUFDLCtDQUErQyxDQUFDLENBQUM7QUFFNUUsTUFBTSxjQUFjO0lBQ2hCO1FBQ0ksSUFBSSxDQUFDLE1BQU0sR0FBUyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLFdBQVcsR0FBSSxLQUFLLENBQUM7UUFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBSSxnQkFBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBRXpCLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELFlBQVksQ0FBRSxFQUFFLEVBQUUsR0FBRztRQUNqQixPQUFPLGdCQUFPLENBQUMsSUFBSSxDQUFDO1lBQ2hCLGlEQUF5QixDQUFDLElBQUksQ0FBQyxNQUFNLGtCQUFJLEVBQUUsSUFBSyxHQUFHLEVBQUc7WUFDdEQsSUFBSSxDQUFDLGlCQUFpQixFQUFFO1NBQzNCLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxXQUFXLENBQUUsUUFBUTtRQUNqQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRTNELElBQUksUUFBUSxDQUFDLEtBQUssRUFBRTtZQUNoQixJQUFJLGVBQWU7Z0JBQ2YsZUFBZSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDOztnQkFFL0MsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxnQkFBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDM0U7YUFDSSxJQUFJLGVBQWU7WUFDcEIsZUFBZSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQzs7WUFFbEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxnQkFBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQy9ELENBQUM7SUFFRCxLQUFLLENBQUMsYUFBYSxDQUFFLEVBQUU7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUM1QixNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7WUFFMUIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksZ0JBQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDeEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUN2RCxDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLEdBQUcsY0FBYyxDQUFDO1NBQ3REO1FBRUQsSUFBSTtZQUNBLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ25DO2dCQUNPO1lBQ0osT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDcEM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLHVCQUF1QixDQUFFLEdBQUc7UUFDOUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUV0QyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFdEIsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN4QyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVELGdCQUFnQjtRQUNaLE9BQU8seUJBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQzthQUNyQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxnQkFBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEcsQ0FBQztJQUVELGlCQUFpQjtRQUNiLElBQUksSUFBSSxDQUFDLFlBQVk7WUFDakIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBRTdCLElBQUksQ0FBQyxZQUFZLEdBQUcseUJBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRXpELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUN4QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUM3QixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUM3QixDQUFDO0lBRUQseUJBQXlCO1FBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUVoRSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLDBCQUEwQixFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQywwQkFBMEIsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFFRCxtQkFBbUI7UUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRTNCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1FBRTVELE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQsbUJBQW1CLENBQUUsS0FBSztRQUN0QixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztRQUV6QixZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUVELElBQUk7UUFDQSxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXO2FBQzlCLElBQUksQ0FBQyxLQUFLLEVBQUMsV0FBVyxFQUFDLEVBQUU7WUFDdEIsSUFBSSxXQUFXLEtBQUssS0FBSyxDQUFDO2dCQUN0QixPQUFPLFdBQVcsQ0FBQztZQUV2QixJQUFJLENBQUMsTUFBTSxHQUFHLHFCQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDO1lBRXBHLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQ2pDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRTNCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBRTVDLElBQUk7Z0JBQ0EsTUFBTSxnQkFBTyxDQUFDLElBQUksQ0FBQztvQkFDZixJQUFJLENBQUMsdUJBQXVCLENBQUMsRUFBRSxPQUFPLEVBQUUsa0JBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDeEQsSUFBSSxDQUFDLGlCQUFpQixFQUFFO29CQUN4QixXQUFXO2lCQUNkLENBQUMsQ0FBQztnQkFFSCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztnQkFFeEIsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUU1RCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQzthQUNyRTtZQUNELE9BQU8sQ0FBQyxFQUFFO2dCQUNOLFlBQVksQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO2dCQUNoRCxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRWhCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO2FBQzVCO1lBRUQsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQzVCLENBQUMsQ0FBQyxDQUFDO1FBRVAsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzVCLENBQUM7SUFFRCxLQUFLLENBQUMsWUFBWSxDQUFFLElBQUk7UUFDcEIsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXO1lBQ2pCLE9BQU87UUFFWCxJQUFJO1lBQ0EsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsRUFBRSxPQUFPLEVBQUUsa0JBQVEsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUN2RTtRQUNELE9BQU8sQ0FBQyxFQUFFO1lBQ04sWUFBWSxDQUFDLHFCQUFxQixJQUFJLCtCQUErQixDQUFDLENBQUM7WUFDdkUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ25CO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlLENBQUUsSUFBSTtRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVc7WUFDakIsT0FBTztRQUVYLElBQUk7WUFDQSxNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFLE9BQU8sRUFBRSxrQkFBUSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1NBQzFFO1FBQ0QsT0FBTyxDQUFDLEVBQUU7WUFDTixZQUFZLENBQUMsd0JBQXdCLElBQUksK0JBQStCLENBQUMsQ0FBQztZQUMxRSxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDbkI7SUFDTCxDQUFDO0NBQ0o7QUFFRCxrQkFBZSxJQUFJLGNBQWMsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1Zyc7XG5pbXBvcnQgcHJvbWlzaWZ5RXZlbnQgZnJvbSAncHJvbWlzaWZ5LWV2ZW50JztcbmltcG9ydCBQcm9taXNlIGZyb20gJ3BpbmtpZSc7XG5pbXBvcnQgeyBzZW5kTWVzc2FnZVRvQ2hpbGRQcm9jZXNzIH0gZnJvbSAnLi4vLi4vcHJvbWlzaWZpZWQtZnVuY3Rpb25zJztcbmltcG9ydCBDT01NQU5EUyBmcm9tICcuL2NvbW1hbmRzJztcblxuXG5jb25zdCBXT1JLRVJfUEFUSCAgICAgICAgID0gcmVxdWlyZS5yZXNvbHZlKCcuL3dvcmtlcicpO1xuY29uc3QgV09SS0VSX1NURElPX0NPTkZJRyA9IFsnaWdub3JlJywgJ3BpcGUnLCAncGlwZScsICdpcGMnXTtcblxuY29uc3QgREVCVUdfTE9HR0VSID0gZGVidWcoJ3Rlc3RjYWZlOnV0aWxzOnRlbXAtZGlyZWN0b3J5OmNsZWFudXAtcHJvY2VzcycpO1xuXG5jbGFzcyBDbGVhbnVwUHJvY2VzcyB7XG4gICAgY29uc3RydWN0b3IgKCkge1xuICAgICAgICB0aGlzLndvcmtlciAgICAgICA9IG51bGw7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaW5pdFByb21pc2UgID0gUHJvbWlzZS5yZXNvbHZlKHZvaWQgMCk7XG4gICAgICAgIHRoaXMuZXJyb3JQcm9taXNlID0gbnVsbDtcblxuICAgICAgICB0aGlzLm1lc3NhZ2VDb3VudGVyID0gMDtcblxuICAgICAgICB0aGlzLnBlbmRpbmdSZXNwb25zZXMgPSB7fTtcbiAgICB9XG5cbiAgICBfc2VuZE1lc3NhZ2UgKGlkLCBtc2cpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmFjZShbXG4gICAgICAgICAgICBzZW5kTWVzc2FnZVRvQ2hpbGRQcm9jZXNzKHRoaXMud29ya2VyLCB7IGlkLCAuLi5tc2cgfSksXG4gICAgICAgICAgICB0aGlzLl93YWl0UHJvY2Vzc0Vycm9yKClcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgX29uUmVzcG9uc2UgKHJlc3BvbnNlKSB7XG4gICAgICAgIGNvbnN0IHBlbmRpbmdSZXNwb25zZSA9IHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tyZXNwb25zZS5pZF07XG5cbiAgICAgICAgaWYgKHJlc3BvbnNlLmVycm9yKSB7XG4gICAgICAgICAgICBpZiAocGVuZGluZ1Jlc3BvbnNlKVxuICAgICAgICAgICAgICAgIHBlbmRpbmdSZXNwb25zZS5jb250cm9sLnJlamVjdChyZXNwb25zZS5lcnJvcik7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW3Jlc3BvbnNlLmlkXSA9IFByb21pc2UucmVqZWN0KHJlc3BvbnNlLmVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChwZW5kaW5nUmVzcG9uc2UpXG4gICAgICAgICAgICBwZW5kaW5nUmVzcG9uc2UuY29udHJvbC5yZXNvbHZlKCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tyZXNwb25zZS5pZF0gPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfd2FpdFJlc3BvbnNlIChpZCkge1xuICAgICAgICBpZiAoIXRoaXMucGVuZGluZ1Jlc3BvbnNlc1tpZF0pIHtcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VDb250cm9sID0ge307XG5cbiAgICAgICAgICAgIHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tpZF0gPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihwcm9taXNlQ29udHJvbCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW2lkXS5jb250cm9sID0gcHJvbWlzZUNvbnRyb2w7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW2lkXTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBlbmRpbmdSZXNwb25zZXNbaWRdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgX3dhaXRSZXNwb25zZUZvck1lc3NhZ2UgKG1zZykge1xuICAgICAgICBjb25zdCBjdXJyZW50SWQgPSB0aGlzLm1lc3NhZ2VDb3VudGVyO1xuXG4gICAgICAgIHRoaXMubWVzc2FnZUNvdW50ZXIrKztcblxuICAgICAgICBhd2FpdCB0aGlzLl9zZW5kTWVzc2FnZShjdXJyZW50SWQsIG1zZyk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3dhaXRSZXNwb25zZShjdXJyZW50SWQpO1xuICAgIH1cblxuICAgIF93YWl0UHJvY2Vzc0V4aXQgKCkge1xuICAgICAgICByZXR1cm4gcHJvbWlzaWZ5RXZlbnQodGhpcy53b3JrZXIsICdleGl0JylcbiAgICAgICAgICAgIC50aGVuKGV4aXRDb2RlID0+IFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihgV29ya2VyIHByb2Nlc3MgdGVybWluYXRlZCB3aXRoIGNvZGUgJHtleGl0Q29kZX1gKSkpO1xuICAgIH1cblxuICAgIF93YWl0UHJvY2Vzc0Vycm9yICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZXJyb3JQcm9taXNlKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3JQcm9taXNlO1xuXG4gICAgICAgIHRoaXMuZXJyb3JQcm9taXNlID0gcHJvbWlzaWZ5RXZlbnQodGhpcy53b3JrZXIsICdlcnJvcicpO1xuXG4gICAgICAgIHRoaXMuZXJyb3JQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lcnJvclByb21pc2UgPSBudWxsO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5lcnJvclByb21pc2U7XG4gICAgfVxuXG4gICAgX3NldHVwV29ya2VyRXZlbnRIYW5kbGVycyAoKSB7XG4gICAgICAgIHRoaXMud29ya2VyLm9uKCdtZXNzYWdlJywgbWVzc2FnZSA9PiB0aGlzLl9vblJlc3BvbnNlKG1lc3NhZ2UpKTtcblxuICAgICAgICB0aGlzLndvcmtlci5zdGRvdXQub24oJ2RhdGEnLCBkYXRhID0+IERFQlVHX0xPR0dFUignV29ya2VyIHByb2Nlc3Mgc3Rkb3V0OlxcbicsIFN0cmluZyhkYXRhKSkpO1xuICAgICAgICB0aGlzLndvcmtlci5zdGRlcnIub24oJ2RhdGEnLCBkYXRhID0+IERFQlVHX0xPR0dFUignV29ya2VyIHByb2Nlc3Mgc3RkZXJyOlxcbicsIFN0cmluZyhkYXRhKSkpO1xuICAgIH1cblxuICAgIF91bnJlZldvcmtlclByb2Nlc3MgKCkge1xuICAgICAgICB0aGlzLndvcmtlci51bnJlZigpO1xuICAgICAgICB0aGlzLndvcmtlci5zdGRvdXQudW5yZWYoKTtcbiAgICAgICAgdGhpcy53b3JrZXIuc3RkZXJyLnVucmVmKCk7XG5cbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IHRoaXMud29ya2VyLmNoYW5uZWwgfHwgdGhpcy53b3JrZXIuX2NoYW5uZWw7XG5cbiAgICAgICAgY2hhbm5lbC51bnJlZigpO1xuICAgIH1cblxuICAgIF9oYW5kbGVQcm9jZXNzRXJyb3IgKGVycm9yKSB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcblxuICAgICAgICBERUJVR19MT0dHRVIoZXJyb3IpO1xuICAgIH1cblxuICAgIGluaXQgKCkge1xuICAgICAgICB0aGlzLmluaXRQcm9taXNlID0gdGhpcy5pbml0UHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgaW5pdGlhbGl6ZWQgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsaXplZCAhPT0gdm9pZCAwKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5pdGlhbGl6ZWQ7XG5cbiAgICAgICAgICAgICAgICB0aGlzLndvcmtlciA9IHNwYXduKHByb2Nlc3MuYXJndlswXSwgW1dPUktFUl9QQVRIXSwgeyBkZXRhY2hlZDogdHJ1ZSwgc3RkaW86IFdPUktFUl9TVERJT19DT05GSUcgfSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9zZXR1cFdvcmtlckV2ZW50SGFuZGxlcnMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl91bnJlZldvcmtlclByb2Nlc3MoKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGV4aXRQcm9taXNlID0gdGhpcy5fd2FpdFByb2Nlc3NFeGl0KCk7XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2FpdFJlc3BvbnNlRm9yTWVzc2FnZSh7IGNvbW1hbmQ6IENPTU1BTkRTLmluaXQgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93YWl0UHJvY2Vzc0Vycm9yKCksXG4gICAgICAgICAgICAgICAgICAgICAgICBleGl0UHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICBdKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICBleGl0UHJvbWlzZS5jYXRjaChlcnJvciA9PiB0aGlzLl9oYW5kbGVQcm9jZXNzRXJyb3IoZXJyb3IpKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLndvcmtlci5vbignZXJyb3InLCBlcnJvciA9PiB0aGlzLl9oYW5kbGVQcm9jZXNzRXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgREVCVUdfTE9HR0VSKCdGYWlsZWQgdG8gc3RhcnQgY2xlYW51cCBwcm9jZXNzJyk7XG4gICAgICAgICAgICAgICAgICAgIERFQlVHX0xPR0dFUihlKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5pdGlhbGl6ZWQ7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5pbml0UHJvbWlzZTtcbiAgICB9XG5cbiAgICBhc3luYyBhZGREaXJlY3RvcnkgKHBhdGgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl93YWl0UmVzcG9uc2VGb3JNZXNzYWdlKHsgY29tbWFuZDogQ09NTUFORFMuYWRkLCBwYXRoIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBERUJVR19MT0dHRVIoYEZhaWxlZCB0byBhZGQgdGhlICR7cGF0aH0gZGlyZWN0b3J5IHRvIGNsZWFudXAgcHJvY2Vzc2ApO1xuICAgICAgICAgICAgREVCVUdfTE9HR0VSKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgcmVtb3ZlRGlyZWN0b3J5IChwYXRoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbml0aWFsaXplZClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fd2FpdFJlc3BvbnNlRm9yTWVzc2FnZSh7IGNvbW1hbmQ6IENPTU1BTkRTLnJlbW92ZSwgcGF0aCB9KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgREVCVUdfTE9HR0VSKGBGYWlsZWQgdG8gcmVtb3ZlIHRoZSAke3BhdGh9IGRpcmVjdG9yeSBpbiBjbGVhbnVwIHByb2Nlc3NgKTtcbiAgICAgICAgICAgIERFQlVHX0xPR0dFUihlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgbmV3IENsZWFudXBQcm9jZXNzKCk7XG4iXX0=