132 lines
16 KiB
JavaScript
132 lines
16 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.killBrowserProcess = void 0;
|
|
const child_process_1 = require("child_process");
|
|
const os_family_1 = __importDefault(require("os-family"));
|
|
const promisify_event_1 = __importDefault(require("promisify-event"));
|
|
const delay_1 = __importDefault(require("../utils/delay"));
|
|
const CHECK_KILLED_DELAY = 2000;
|
|
const HARD_KILL_FLAG = 'SIGKILL';
|
|
const NEW_LINE_SEPERATOR_RE = /(\r\n)|(\n\r)|\n|\r/g;
|
|
const cannotGetListOfProcessError = 'Cannot get list of processes';
|
|
const killProcessTimeoutError = 'Kill process timeout';
|
|
function getProcessOutputUnix() {
|
|
const error = new Error(cannotGetListOfProcessError);
|
|
return new Promise((resolve, reject) => {
|
|
const child = (0, child_process_1.spawn)('ps', ['-eo', 'pid,command']);
|
|
let stdout = '';
|
|
let stderr = '';
|
|
child.stdout.on('data', data => {
|
|
stdout += data.toString();
|
|
});
|
|
child.stderr.on('data', data => {
|
|
stderr += data.toString();
|
|
});
|
|
child.on('exit', () => {
|
|
if (stderr)
|
|
reject(error);
|
|
else
|
|
resolve(stdout);
|
|
});
|
|
child.on('error', () => {
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
function findProcessIdUnix(browserId, psOutput) {
|
|
const processIdRegex = new RegExp('^\\s*(\\d+)\\s+.*' + browserId);
|
|
const lines = psOutput.split(NEW_LINE_SEPERATOR_RE);
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const match = processIdRegex.exec(lines[i]);
|
|
if (match)
|
|
return parseInt(match[1], 10);
|
|
}
|
|
return null;
|
|
}
|
|
function isUnixProcessExist(processId, psOutput) {
|
|
const processIdRegex = new RegExp('^\\s*' + processId + '\\s+.*');
|
|
const lines = psOutput.split(NEW_LINE_SEPERATOR_RE);
|
|
return lines.some(line => processIdRegex.test(line));
|
|
}
|
|
async function findProcessUnix(browserId) {
|
|
const output = await getProcessOutputUnix();
|
|
return findProcessIdUnix(browserId, output);
|
|
}
|
|
async function isUnixProcessKilled(processId) {
|
|
const output = await getProcessOutputUnix();
|
|
return !isUnixProcessExist(processId, output);
|
|
}
|
|
async function killUnixProcessSoft(processId) {
|
|
process.kill(processId);
|
|
}
|
|
async function killUnixProcessHard(processId) {
|
|
process.kill(processId, HARD_KILL_FLAG);
|
|
}
|
|
async function killProcessUnix(processId) {
|
|
const maxSoftTries = 2;
|
|
let softTries = 0;
|
|
let unixProcessKilled = false;
|
|
do {
|
|
await killUnixProcessSoft(processId);
|
|
softTries++;
|
|
await (0, delay_1.default)(CHECK_KILLED_DELAY);
|
|
unixProcessKilled = await isUnixProcessKilled(processId);
|
|
} while (!unixProcessKilled && softTries < maxSoftTries);
|
|
unixProcessKilled = await isUnixProcessKilled(processId);
|
|
if (unixProcessKilled)
|
|
return;
|
|
await killUnixProcessHard(processId);
|
|
await (0, delay_1.default)(CHECK_KILLED_DELAY);
|
|
unixProcessKilled = await isUnixProcessKilled(processId);
|
|
if (unixProcessKilled)
|
|
return;
|
|
// NOTE: if 2 soft-kill and 1 hard-kill with "SIGKILL"-flag didn't work - throw error
|
|
throw new Error(killProcessTimeoutError);
|
|
}
|
|
async function runWMIC(args) {
|
|
const wmicProcess = (0, child_process_1.spawn)('wmic.exe', args, { detached: true });
|
|
let wmicOutput = '';
|
|
wmicProcess.stdout.on('data', data => {
|
|
wmicOutput += data.toString();
|
|
});
|
|
try {
|
|
await Promise.race([
|
|
(0, promisify_event_1.default)(wmicProcess.stdout, 'end'),
|
|
(0, promisify_event_1.default)(wmicProcess, 'error'),
|
|
]);
|
|
return wmicOutput;
|
|
}
|
|
catch (e) {
|
|
return '';
|
|
}
|
|
}
|
|
async function findProcessWin(browserId) {
|
|
const wmicArgs = ['process', 'where', `commandline like '%${browserId}%' and name <> 'cmd.exe' and name <> 'wmic.exe'`, 'get', 'processid'];
|
|
const wmicOutput = await runWMIC(wmicArgs);
|
|
let processList = wmicOutput.split(/\s*\n/);
|
|
processList = processList
|
|
// NOTE: remove list's header and empty last element, caused by trailing newline
|
|
.slice(1, -1)
|
|
.map(pid => ({ pid: Number(pid) }));
|
|
return processList[0] ? processList[0].pid : null;
|
|
}
|
|
async function killBrowserProcess(browserId) {
|
|
const processId = os_family_1.default.win ? await findProcessWin(browserId) : await findProcessUnix(browserId);
|
|
if (!processId)
|
|
return true;
|
|
try {
|
|
if (os_family_1.default.win)
|
|
process.kill(processId);
|
|
else
|
|
await killProcessUnix(processId);
|
|
return true;
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
exports.killBrowserProcess = killBrowserProcess;
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wcm9jZXNzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGlEQUFzQztBQUN0QywwREFBMkI7QUFDM0Isc0VBQTZDO0FBQzdDLDJEQUFtQztBQUVuQyxNQUFNLGtCQUFrQixHQUFnQixJQUFJLENBQUM7QUFDN0MsTUFBTSxjQUFjLEdBQW9CLFNBQVMsQ0FBQztBQUNsRCxNQUFNLHFCQUFxQixHQUFhLHNCQUFzQixDQUFDO0FBQy9ELE1BQU0sMkJBQTJCLEdBQU8sOEJBQThCLENBQUM7QUFDdkUsTUFBTSx1QkFBdUIsR0FBVyxzQkFBc0IsQ0FBQztBQUUvRCxTQUFTLG9CQUFvQjtJQUN6QixNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0lBRXJELE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDbkMsTUFBTSxLQUFLLEdBQUcsSUFBQSxxQkFBSyxFQUFDLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBRWxELElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNoQixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFFaEIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFO1lBQzNCLE1BQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUM7UUFFSCxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUU7WUFDM0IsTUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztRQUVILEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFB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V0FBVyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFNUMsV0FBVyxHQUFHLFdBQVc7UUFDekIsZ0ZBQWdGO1NBQzNFLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDWixHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUV4QyxPQUFPLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ3RELENBQUM7QUFFTSxLQUFLLFVBQVUsa0JBQWtCLENBQUUsU0FBUztJQUMvQyxNQUFNLFNBQVMsR0FBRyxtQkFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTlGLElBQUksQ0FBQyxTQUFTO1FBQ1YsT0FBTyxJQUFJLENBQUM7SUFFaEIsSUFBSTtRQUNBLElBQUksbUJBQUUsQ0FBQyxHQUFHO1lBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQzs7WUFFeEIsTUFBTSxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFckMsT0FBTyxJQUFJLENBQUM7S0FDZjtJQUNELE9BQU8sQ0FBQyxFQUFFO1FBQ04sT0FBTyxLQUFLLENBQUM7S0FDaEI7QUFDTCxDQUFDO0FBakJELGdEQWlCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgT1MgZnJvbSAnb3MtZmFtaWx5JztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IGRlbGF5IGZyb20gJy4uL3V0aWxzL2RlbGF5JztcblxuY29uc3QgQ0hFQ0tfS0lMTEVEX0RFTEFZICAgICAgICAgICAgICA9IDIwMDA7XG5jb25zdCBIQVJEX0tJTExfRkxBRyAgICAgICAgICAgICAgICAgID0gJ1NJR0tJTEwnO1xuY29uc3QgTkVXX0xJTkVfU0VQRVJBVE9SX1JFICAgICAgICAgICA9IC8oXFxyXFxuKXwoXFxuXFxyKXxcXG58XFxyL2c7XG5jb25zdCBjYW5ub3RHZXRMaXN0T2ZQcm9jZXNzRXJyb3IgICAgID0gJ0Nhbm5vdCBnZXQgbGlzdCBvZiBwcm9jZXNzZXMnO1xuY29uc3Qga2lsbFByb2Nlc3NUaW1lb3V0RXJyb3IgICAgICAgICA9ICdLaWxsIHByb2Nlc3MgdGltZW91dCc7XG5cbmZ1bmN0aW9uIGdldFByb2Nlc3NPdXRwdXRVbml4ICgpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihjYW5ub3RHZXRMaXN0T2ZQcm9jZXNzRXJyb3IpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSBzcGF3bigncHMnLCBbJy1lbycsICdwaWQsY29tbWFuZCddKTtcblxuICAgICAgICBsZXQgc3Rkb3V0ID0gJyc7XG4gICAgICAgIGxldCBzdGRlcnIgPSAnJztcblxuICAgICAgICBjaGlsZC5zdGRvdXQub24oJ2RhdGEnLCBkYXRhID0+IHtcbiAgICAgICAgICAgIHN0ZG91dCArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNoaWxkLnN0ZGVyci5vbignZGF0YScsIGRhdGEgPT4ge1xuICAgICAgICAgICAgc3RkZXJyICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY2hpbGQub24oJ2V4aXQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoc3RkZXJyKVxuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShzdGRvdXQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjaGlsZC5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZmluZFByb2Nlc3NJZFVuaXggKGJyb3dzZXJJZCwgcHNPdXRwdXQpIHtcbiAgICBjb25zdCBwcm9jZXNzSWRSZWdleCAgID0gbmV3IFJlZ0V4cCgnXlxcXFxzKihcXFxcZCspXFxcXHMrLionICsgYnJvd3NlcklkKTtcbiAgICBjb25zdCBsaW5lcyAgICAgICAgICAgID0gcHNPdXRwdXQuc3BsaXQoTkVXX0xJTkVfU0VQRVJBVE9SX1JFKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBwcm9jZXNzSWRSZWdleC5leGVjKGxpbmVzW2ldKTtcblxuICAgICAgICBpZiAobWF0Y2gpXG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQobWF0Y2hbMV0sIDEwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNVbml4UHJvY2Vzc0V4aXN0IChwcm9jZXNzSWQsIHBzT3V0cHV0KSB7XG4gICAgY29uc3QgcHJvY2Vzc0lkUmVnZXggICA9IG5ldyBSZWdFeHAoJ15cXFxccyonICsgcHJvY2Vzc0lkICsgJ1xcXFxzKy4qJyk7XG4gICAgY29uc3QgbGluZXMgICAgICAgICAgICA9IHBzT3V0cHV0LnNwbGl0KE5FV19MSU5FX1NFUEVSQVRPUl9SRSk7XG5cbiAgICByZXR1cm4gbGluZXMuc29tZShsaW5lID0+IHByb2Nlc3NJZFJlZ2V4LnRlc3QobGluZSkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmaW5kUHJvY2Vzc1VuaXggKGJyb3dzZXJJZCkge1xuICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IGdldFByb2Nlc3NPdXRwdXRVbml4KCk7XG5cbiAgICByZXR1cm4gZmluZFByb2Nlc3NJZFVuaXgoYnJvd3NlcklkLCBvdXRwdXQpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpc1VuaXhQcm9jZXNzS2lsbGVkIChwcm9jZXNzSWQpIHtcbiAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCBnZXRQcm9jZXNzT3V0cHV0VW5peCgpO1xuXG4gICAgcmV0dXJuICFpc1VuaXhQcm9jZXNzRXhpc3QocHJvY2Vzc0lkLCBvdXRwdXQpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBraWxsVW5peFByb2Nlc3NTb2Z0IChwcm9jZXNzSWQpIHtcbiAgICBwcm9jZXNzLmtpbGwocHJvY2Vzc0lkKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24ga2lsbFVuaXhQcm9jZXNzSGFyZCAocHJvY2Vzc0lkKSB7XG4gICAgcHJvY2Vzcy5raWxsKHByb2Nlc3NJZCwgSEFSRF9LSUxMX0ZMQUcpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBraWxsUHJvY2Vzc1VuaXggKHByb2Nlc3NJZCkge1xuICAgIGNvbnN0IG1heFNvZnRUcmllcyA9IDI7XG5cbiAgICBsZXQgc29mdFRyaWVzICAgICAgICAgPSAwO1xuICAgIGxldCB1bml4UHJvY2Vzc0tpbGxlZCA9IGZhbHNlO1xuXG4gICAgZG8ge1xuICAgICAgICBhd2FpdCBraWxsVW5peFByb2Nlc3NTb2Z0KHByb2Nlc3NJZCk7XG5cbiAgICAgICAgc29mdFRyaWVzKys7XG5cbiAgICAgICAgYXdhaXQgZGVsYXkoQ0hFQ0tfS0lMTEVEX0RFTEFZKTtcblxuICAgICAgICB1bml4UHJvY2Vzc0tpbGxlZCA9IGF3YWl0IGlzVW5peFByb2Nlc3NLaWxsZWQocHJvY2Vzc0lkKTtcbiAgICB9XG4gICAgd2hpbGUgKCF1bml4UHJvY2Vzc0tpbGxlZCAmJiBzb2Z0VHJpZXMgPCBtYXhTb2Z0VHJpZXMpO1xuXG4gICAgdW5peFByb2Nlc3NLaWxsZWQgPSBhd2FpdCBpc1VuaXhQcm9jZXNzS2lsbGVkKHByb2Nlc3NJZCk7XG5cbiAgICBpZiAodW5peFByb2Nlc3NLaWxsZWQpXG4gICAgICAgIHJldHVybjtcblxuICAgIGF3YWl0IGtpbGxVbml4UHJvY2Vzc0hhcmQocHJvY2Vzc0lkKTtcblxuICAgIGF3YWl0IGRlbGF5KENIRUNLX0tJTExFRF9ERUxBWSk7XG5cbiAgICB1bml4UHJvY2Vzc0tpbGxlZCA9IGF3YWl0IGlzVW5peFByb2Nlc3NLaWxsZWQocHJvY2Vzc0lkKTtcblxuICAgIGlmICh1bml4UHJvY2Vzc0tpbGxlZCkgcmV0dXJuO1xuXG4gICAgLy8gTk9URTogaWYgMiBzb2Z0LWtpbGwgYW5kIDEgaGFyZC1raWxsIHdpdGggXCJTSUdLSUxMXCItZmxhZyBkaWRuJ3Qgd29yayAtIHRocm93IGVycm9yXG4gICAgdGhyb3cgbmV3IEVycm9yKGtpbGxQcm9jZXNzVGltZW91dEVycm9yKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuV01JQyAoYXJncykge1xuICAgIGNvbnN0IHdtaWNQcm9jZXNzID0gc3Bhd24oJ3dtaWMuZXhlJywgYXJncywgeyBkZXRhY2hlZDogdHJ1ZSB9KTtcblxuICAgIGxldCB3bWljT3V0cHV0ID0gJyc7XG5cbiAgICB3bWljUHJvY2Vzcy5zdGRvdXQub24oJ2RhdGEnLCBkYXRhID0+IHtcbiAgICAgICAgd21pY091dHB1dCArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgcHJvbWlzaWZ5RXZlbnQod21pY1Byb2Nlc3Muc3Rkb3V0LCAnZW5kJyksXG4gICAgICAgICAgICBwcm9taXNpZnlFdmVudCh3bWljUHJvY2VzcywgJ2Vycm9yJyksXG4gICAgICAgIF0pO1xuXG4gICAgICAgIHJldHVybiB3bWljT3V0cHV0O1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBmaW5kUHJvY2Vzc1dpbiAoYnJvd3NlcklkKSB7XG4gICAgY29uc3Qgd21pY0FyZ3MgICAgPSBbJ3Byb2Nlc3MnLCAnd2hlcmUnLCBgY29tbWFuZGxpbmUgbGlrZSAnJSR7YnJvd3NlcklkfSUnIGFuZCBuYW1lIDw+ICdjbWQuZXhlJyBhbmQgbmFtZSA8PiAnd21pYy5leGUnYCwgJ2dldCcsICdwcm9jZXNzaWQnXTtcbiAgICBjb25zdCB3bWljT3V0cHV0ICA9IGF3YWl0IHJ1bldNSUMod21pY0FyZ3MpO1xuXG4gICAgbGV0IHByb2Nlc3NMaXN0ID0gd21pY091dHB1dC5zcGxpdCgvXFxzKlxcbi8pO1xuXG4gICAgcHJvY2Vzc0xpc3QgPSBwcm9jZXNzTGlzdFxuICAgIC8vIE5PVEU6IHJlbW92ZSBsaXN0J3MgaGVhZGVyIGFuZCBlbXB0eSBsYXN0IGVsZW1lbnQsIGNhdXNlZCBieSB0cmFpbGluZyBuZXdsaW5lXG4gICAgICAgIC5zbGljZSgxLCAtMSlcbiAgICAgICAgLm1hcChwaWQgPT4gKHsgcGlkOiBOdW1iZXIocGlkKSB9KSk7XG5cbiAgICByZXR1cm4gcHJvY2Vzc0xpc3RbMF0gPyBwcm9jZXNzTGlzdFswXS5waWQgOiBudWxsO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24ga2lsbEJyb3dzZXJQcm9jZXNzIChicm93c2VySWQpIHtcbiAgICBjb25zdCBwcm9jZXNzSWQgPSBPUy53aW4gPyBhd2FpdCBmaW5kUHJvY2Vzc1dpbihicm93c2VySWQpIDogYXdhaXQgZmluZFByb2Nlc3NVbml4KGJyb3dzZXJJZCk7XG5cbiAgICBpZiAoIXByb2Nlc3NJZClcbiAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICB0cnkge1xuICAgICAgICBpZiAoT1Mud2luKVxuICAgICAgICAgICAgcHJvY2Vzcy5raWxsKHByb2Nlc3NJZCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGF3YWl0IGtpbGxQcm9jZXNzVW5peChwcm9jZXNzSWQpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuIl19
|