1 | ;
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | const child_process_1 = require("child_process");
|
7 | const os_family_1 = __importDefault(require("os-family"));
|
8 | const promisify_event_1 = __importDefault(require("promisify-event"));
|
9 | const delay_1 = __importDefault(require("../utils/delay"));
|
10 | const CHECK_PROCESS_IS_KILLED_TIMEOUT = 5000;
|
11 | const CHECK_KILLED_DELAY = 1000;
|
12 | const NEW_LINE_SEPERATOR_RE = /(\r\n)|(\n\r)|\n|\r/g;
|
13 | const cannotGetListOfProcessError = 'Cannot get list of processes';
|
14 | const killProcessTimeoutError = 'Kill process timeout';
|
15 | function getProcessOutputUnix() {
|
16 | const error = new Error(cannotGetListOfProcessError);
|
17 | return new Promise((resolve, reject) => {
|
18 | const child = child_process_1.spawn('ps', ['-eo', 'pid,command']);
|
19 | let stdout = '';
|
20 | let stderr = '';
|
21 | child.stdout.on('data', data => {
|
22 | stdout += data.toString();
|
23 | });
|
24 | child.stderr.on('data', data => {
|
25 | stderr += data.toString();
|
26 | });
|
27 | child.on('exit', () => {
|
28 | if (stderr)
|
29 | reject(error);
|
30 | else
|
31 | resolve(stdout);
|
32 | });
|
33 | child.on('error', () => {
|
34 | reject(error);
|
35 | });
|
36 | });
|
37 | }
|
38 | function findProcessIdUnix(browserId, psOutput) {
|
39 | const processIdRegex = new RegExp('^\\s*(\\d+)\\s+.*' + browserId);
|
40 | const lines = psOutput.split(NEW_LINE_SEPERATOR_RE);
|
41 | for (let i = 0; i < lines.length; i++) {
|
42 | const match = processIdRegex.exec(lines[i]);
|
43 | if (match)
|
44 | return parseInt(match[1], 10);
|
45 | }
|
46 | return null;
|
47 | }
|
48 | function isProcessExistUnix(processId, psOutput) {
|
49 | const processIdRegex = new RegExp('^\\s*' + processId + '\\s+.*');
|
50 | const lines = psOutput.split(NEW_LINE_SEPERATOR_RE);
|
51 | return lines.some(line => processIdRegex.test(line));
|
52 | }
|
53 | async function findProcessUnix(browserId) {
|
54 | const output = await getProcessOutputUnix();
|
55 | return findProcessIdUnix(browserId, output);
|
56 | }
|
57 | async function checkUnixProcessIsKilled(processId) {
|
58 | const output = await getProcessOutputUnix();
|
59 | if (isProcessExistUnix(processId, output)) {
|
60 | await delay_1.default(CHECK_KILLED_DELAY);
|
61 | await checkUnixProcessIsKilled();
|
62 | }
|
63 | }
|
64 | async function killProcessUnix(processId) {
|
65 | let timeoutError = false;
|
66 | process.kill(processId);
|
67 | const killTimeoutTimer = delay_1.default(CHECK_PROCESS_IS_KILLED_TIMEOUT)
|
68 | .then(() => {
|
69 | timeoutError = true;
|
70 | });
|
71 | return Promise.race([killTimeoutTimer, checkUnixProcessIsKilled(processId)]).then(() => {
|
72 | if (timeoutError)
|
73 | throw new Error(killProcessTimeoutError);
|
74 | });
|
75 | }
|
76 | async function runWMIC(args) {
|
77 | const wmicProcess = child_process_1.spawn('wmic.exe', args, { detached: true });
|
78 | let wmicOutput = '';
|
79 | wmicProcess.stdout.on('data', data => {
|
80 | wmicOutput += data.toString();
|
81 | });
|
82 | try {
|
83 | await Promise.race([
|
84 | promisify_event_1.default(wmicProcess.stdout, 'end'),
|
85 | promisify_event_1.default(wmicProcess, 'error')
|
86 | ]);
|
87 | return wmicOutput;
|
88 | }
|
89 | catch (e) {
|
90 | return '';
|
91 | }
|
92 | }
|
93 | async function findProcessWin(browserId) {
|
94 | const wmicArgs = ['process', 'where', `commandline like '%${browserId}%' and name <> 'cmd.exe' and name <> 'wmic.exe'`, 'get', 'processid'];
|
95 | const wmicOutput = await runWMIC(wmicArgs);
|
96 | let processList = wmicOutput.split(/\s*\n/);
|
97 | processList = processList
|
98 | // NOTE: remove list's header and empty last element, caused by trailing newline
|
99 | .slice(1, -1)
|
100 | .map(pid => ({ pid: Number(pid) }));
|
101 | return processList[0] ? processList[0].pid : null;
|
102 | }
|
103 | async function killBrowserProcess(browserId) {
|
104 | const processId = os_family_1.default.win ? await findProcessWin(browserId) : await findProcessUnix(browserId);
|
105 | if (!processId)
|
106 | return true;
|
107 | try {
|
108 | if (os_family_1.default.win)
|
109 | process.kill(processId);
|
110 | else
|
111 | await killProcessUnix(processId);
|
112 | return true;
|
113 | }
|
114 | catch (e) {
|
115 | return false;
|
116 | }
|
117 | }
|
118 | exports.killBrowserProcess = killBrowserProcess;
|
119 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wcm9jZXNzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQXNDO0FBQ3RDLDBEQUEyQjtBQUMzQixzRUFBNkM7QUFDN0MsMkRBQW1DO0FBRW5DLE1BQU0sK0JBQStCLEdBQUcsSUFBSSxDQUFDO0FBQzdDLE1BQU0sa0JBQWtCLEdBQWdCLElBQUksQ0FBQztBQUM3QyxNQUFNLHFCQUFxQixHQUFhLHNCQUFzQixDQUFDO0FBQy9ELE1BQU0sMkJBQTJCLEdBQU8sOEJBQThCLENBQUM7QUFDdkUsTUFBTSx1QkFBdUIsR0FBVyxzQkFBc0IsQ0FBQztBQUUvRCxTQUFTLG9CQUFvQjtJQUN6QixNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0lBRXJELE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDbkMsTUFBTSxLQUFLLEdBQUcscUJBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUNsRCxJQUFJLE1BQU0sR0FBSSxFQUFFLENBQUM7UUFDakIsSUFBSSxNQUFNLEdBQUksRUFBRSxDQUFDO1FBRWpCLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBRTtZQUMzQixNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzlCLENBQUMsQ0FBQyxDQUFDO1FBRUgsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFO1lBQzNCLE1BQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUM7UUFFSCxLQUFLLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUU7WUFDbEIsSUFBSSxNQUFNO2dCQUNOLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzs7Z0JBRWQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hCLENBQUMsQ0FBQyxDQUFDO1FBRUgsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFO1lBQ25CLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVELFNBQVMsaUJBQWlCLENBQUUsU0FBUyxFQUFFLFFBQVE7SUFDM0MsTUFBTSxjQUFjLEdBQUssSUFBSSxNQUFNLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFDckUsTUFBTSxLQUFLLEdBQWMsUUFBUSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBRS9ELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ25DLE1BQU0sS0FBSyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFNUMsSUFBSSxLQUFLO1lBQ0wsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQ3JDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDaEIsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQUUsU0FBUyxFQUFFLFFBQVE7SUFDNUMsTUFBTSxjQUFjLEdBQUssSUFBSSxNQUFNLENBQUMsT0FBTyxHQUFHLFNBQVMsR0FBRyxRQUFRLENBQUMsQ0FBQztJQUNwRSxNQUFNLEtBQUssR0FBYyxRQUFRLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFFL0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3pELENBQUM7QUFFRCxLQUFLLFVBQVUsZUFBZSxDQUFFLFNBQVM7SUFDckMsTUFBTSxNQUFNLEdBQUcsTUFBTSxvQkFBb0IsRUFBRSxDQUFDO0lBRTVDLE9BQU8saUJBQWlCLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRCxLQUFLLFVBQVUsd0JBQXdCLENBQUUsU0FBUztJQUM5QyxNQUFNLE1BQU0sR0FBRyxNQUFNLG9CQUFvQixFQUFFLENBQUM7SUFFNUMsSUFBSSxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLEVBQUU7UUFDdkMsTUFBTSxlQUFLLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUVoQyxNQUFNLHdCQUF3QixFQUFFLENBQUM7S0FDcEM7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLGVBQWUsQ0FBRSxTQUFTO0lBQ3JDLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztJQUV6QixPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRXhCLE1BQU0sZ0JBQWdCLEdBQUcsZUFBSyxDQUFDLCtCQUErQixDQUFDO1NBQzFELElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDUCxZQUFZLEdBQUcsSUFBSSxDQUFDO0lBQ3hCLENBQUMsQ0FBQyxDQUFDO0lBRVAsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsd0JBQXdCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDbkYsSUFBSSxZQUFZO1lBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVELEtBQUssVUFBVSxPQUFPLENBQUUsSUFBSTtJQUN4QixNQUFNLFdBQVcsR0FBRyxxQkFBSyxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUVoRSxJQUFJLFVBQVUsR0FBSSxFQUFFLENBQUM7SUFFckIsV0FBVyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFO1FBQ2pDLFVBQVUsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDbEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJO1FBQ0EsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ2YseUJBQWMsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQztZQUN6Qyx5QkFBYyxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUM7U0FDdkMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxVQUFVLENBQUM7S0FDckI7SUFDRCxPQUFPLENBQUMsRUFBRTtRQUNOLE9BQU8sRUFBRSxDQUFDO0tBQ2I7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBRSxTQUFTO0lBQ3BDLE1BQU0sUUFBUSxHQUFNLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxzQkFBc0IsU0FBUyxpREFBaUQsRUFBRSxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDL0ksTUFBTSxVQUFVLEdBQUksTUFBTSxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDNUMsSUFBSSxXQUFXLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUU1QyxXQUFXLEdBQUcsV0FBVztRQUN6QixnRkFBZ0Y7U0FDM0UsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNaLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRXhDLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDdEQsQ0FBQztBQUVNLEtBQUssVUFBVSxrQkFBa0IsQ0FBRSxTQUFTO0lBQy9DLE1BQU0sU0FBUyxHQUFHLG1CQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFOUYsSUFBSSxDQUFDLFNBQVM7UUFDVixPQUFPLElBQUksQ0FBQztJQUVoQixJQUFJO1FBQ0EsSUFBSSxtQkFBRSxDQUFDLEdBQUc7WUFDTixPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDOztZQUV4QixNQUFNLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVyQyxPQUFPLElBQUksQ0FBQztLQUNmO0lBQ0QsT0FBTyxDQUFDLEVBQUU7UUFDTixPQUFPLEtBQUssQ0FBQztLQUNoQjtBQUNMLENBQUM7QUFqQkQsZ0RBaUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCBPUyBmcm9tICdvcy1mYW1pbHknO1xuaW1wb3J0IHByb21pc2lmeUV2ZW50IGZyb20gJ3Byb21pc2lmeS1ldmVudCc7XG5pbXBvcnQgZGVsYXkgZnJvbSAnLi4vdXRpbHMvZGVsYXknO1xuXG5jb25zdCBDSEVDS19QUk9DRVNTX0lTX0tJTExFRF9USU1FT1VUID0gNTAwMDtcbmNvbnN0IENIRUNLX0tJTExFRF9ERUxBWSAgICAgICAgICAgICAgPSAxMDAwO1xuY29uc3QgTkVXX0xJTkVfU0VQRVJBVE9SX1JFICAgICAgICAgICA9IC8oXFxyXFxuKXwoXFxuXFxyKXxcXG58XFxyL2c7XG5jb25zdCBjYW5ub3RHZXRMaXN0T2ZQcm9jZXNzRXJyb3IgICAgID0gJ0Nhbm5vdCBnZXQgbGlzdCBvZiBwcm9jZXNzZXMnO1xuY29uc3Qga2lsbFByb2Nlc3NUaW1lb3V0RXJyb3IgICAgICAgICA9ICdLaWxsIHByb2Nlc3MgdGltZW91dCc7XG5cbmZ1bmN0aW9uIGdldFByb2Nlc3NPdXRwdXRVbml4ICgpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihjYW5ub3RHZXRMaXN0T2ZQcm9jZXNzRXJyb3IpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgY2hpbGQgPSBzcGF3bigncHMnLCBbJy1lbycsICdwaWQsY29tbWFuZCddKTtcbiAgICAgICAgbGV0IHN0ZG91dCAgPSAnJztcbiAgICAgICAgbGV0IHN0ZGVyciAgPSAnJztcblxuICAgICAgICBjaGlsZC5zdGRvdXQub24oJ2RhdGEnLCBkYXRhID0+IHtcbiAgICAgICAgICAgIHN0ZG91dCArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNoaWxkLnN0ZGVyci5vbignZGF0YScsIGRhdGEgPT4ge1xuICAgICAgICAgICAgc3RkZXJyICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY2hpbGQub24oJ2V4aXQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoc3RkZXJyKVxuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShzdGRvdXQpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjaGlsZC5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZmluZFByb2Nlc3NJZFVuaXggKGJyb3dzZXJJZCwgcHNPdXRwdXQpIHtcbiAgICBjb25zdCBwcm9jZXNzSWRSZWdleCAgID0gbmV3IFJlZ0V4cCgnXlxcXFxzKihcXFxcZCspXFxcXHMrLionICsgYnJvd3NlcklkKTtcbiAgICBjb25zdCBsaW5lcyAgICAgICAgICAgID0gcHNPdXRwdXQuc3BsaXQoTkVXX0xJTkVfU0VQRVJBVE9SX1JFKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBwcm9jZXNzSWRSZWdleC5leGVjKGxpbmVzW2ldKTtcblxuICAgICAgICBpZiAobWF0Y2gpXG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQobWF0Y2hbMV0sIDEwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNQcm9jZXNzRXhpc3RVbml4IChwcm9jZXNzSWQsIHBzT3V0cHV0KSB7XG4gICAgY29uc3QgcHJvY2Vzc0lkUmVnZXggICA9IG5ldyBSZWdFeHAoJ15cXFxccyonICsgcHJvY2Vzc0lkICsgJ1xcXFxzKy4qJyk7XG4gICAgY29uc3QgbGluZXMgICAgICAgICAgICA9IHBzT3V0cHV0LnNwbGl0KE5FV19MSU5FX1NFUEVSQVRPUl9SRSk7XG5cbiAgICByZXR1cm4gbGluZXMuc29tZShsaW5lID0+IHByb2Nlc3NJZFJlZ2V4LnRlc3QobGluZSkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmaW5kUHJvY2Vzc1VuaXggKGJyb3dzZXJJZCkge1xuICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IGdldFByb2Nlc3NPdXRwdXRVbml4KCk7XG5cbiAgICByZXR1cm4gZmluZFByb2Nlc3NJZFVuaXgoYnJvd3NlcklkLCBvdXRwdXQpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjaGVja1VuaXhQcm9jZXNzSXNLaWxsZWQgKHByb2Nlc3NJZCkge1xuICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IGdldFByb2Nlc3NPdXRwdXRVbml4KCk7XG5cbiAgICBpZiAoaXNQcm9jZXNzRXhpc3RVbml4KHByb2Nlc3NJZCwgb3V0cHV0KSkge1xuICAgICAgICBhd2FpdCBkZWxheShDSEVDS19LSUxMRURfREVMQVkpO1xuXG4gICAgICAgIGF3YWl0IGNoZWNrVW5peFByb2Nlc3NJc0tpbGxlZCgpO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24ga2lsbFByb2Nlc3NVbml4IChwcm9jZXNzSWQpIHtcbiAgICBsZXQgdGltZW91dEVycm9yID0gZmFsc2U7XG5cbiAgICBwcm9jZXNzLmtpbGwocHJvY2Vzc0lkKTtcblxuICAgIGNvbnN0IGtpbGxUaW1lb3V0VGltZXIgPSBkZWxheShDSEVDS19QUk9DRVNTX0lTX0tJTExFRF9USU1FT1VUKVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICB0aW1lb3V0RXJyb3IgPSB0cnVlO1xuICAgICAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLnJhY2UoW2tpbGxUaW1lb3V0VGltZXIsIGNoZWNrVW5peFByb2Nlc3NJc0tpbGxlZChwcm9jZXNzSWQpXSkudGhlbigoKSA9PiB7XG4gICAgICAgIGlmICh0aW1lb3V0RXJyb3IpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3Ioa2lsbFByb2Nlc3NUaW1lb3V0RXJyb3IpO1xuICAgIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBydW5XTUlDIChhcmdzKSB7XG4gICAgY29uc3Qgd21pY1Byb2Nlc3MgPSBzcGF3bignd21pYy5leGUnLCBhcmdzLCB7IGRldGFjaGVkOiB0cnVlIH0pO1xuXG4gICAgbGV0IHdtaWNPdXRwdXQgID0gJyc7XG5cbiAgICB3bWljUHJvY2Vzcy5zdGRvdXQub24oJ2RhdGEnLCBkYXRhID0+IHtcbiAgICAgICAgd21pY091dHB1dCArPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgcHJvbWlzaWZ5RXZlbnQod21pY1Byb2Nlc3Muc3Rkb3V0LCAnZW5kJyksXG4gICAgICAgICAgICBwcm9taXNpZnlFdmVudCh3bWljUHJvY2VzcywgJ2Vycm9yJylcbiAgICAgICAgXSk7XG5cbiAgICAgICAgcmV0dXJuIHdtaWNPdXRwdXQ7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRQcm9jZXNzV2luIChicm93c2VySWQpIHtcbiAgICBjb25zdCB3bWljQXJncyAgICA9IFsncHJvY2VzcycsICd3aGVyZScsIGBjb21tYW5kbGluZSBsaWtlICclJHticm93c2VySWR9JScgYW5kIG5hbWUgPD4gJ2NtZC5leGUnIGFuZCBuYW1lIDw+ICd3bWljLmV4ZSdgLCAnZ2V0JywgJ3Byb2Nlc3NpZCddO1xuICAgIGNvbnN0IHdtaWNPdXRwdXQgID0gYXdhaXQgcnVuV01JQyh3bWljQXJncyk7XG4gICAgbGV0IHByb2Nlc3NMaXN0ID0gd21pY091dHB1dC5zcGxpdCgvXFxzKlxcbi8pO1xuXG4gICAgcHJvY2Vzc0xpc3QgPSBwcm9jZXNzTGlzdFxuICAgIC8vIE5PVEU6IHJlbW92ZSBsaXN0J3MgaGVhZGVyIGFuZCBlbXB0eSBsYXN0IGVsZW1lbnQsIGNhdXNlZCBieSB0cmFpbGluZyBuZXdsaW5lXG4gICAgICAgIC5zbGljZSgxLCAtMSlcbiAgICAgICAgLm1hcChwaWQgPT4gKHsgcGlkOiBOdW1iZXIocGlkKSB9KSk7XG5cbiAgICByZXR1cm4gcHJvY2Vzc0xpc3RbMF0gPyBwcm9jZXNzTGlzdFswXS5waWQgOiBudWxsO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24ga2lsbEJyb3dzZXJQcm9jZXNzIChicm93c2VySWQpIHtcbiAgICBjb25zdCBwcm9jZXNzSWQgPSBPUy53aW4gPyBhd2FpdCBmaW5kUHJvY2Vzc1dpbihicm93c2VySWQpIDogYXdhaXQgZmluZFByb2Nlc3NVbml4KGJyb3dzZXJJZCk7XG5cbiAgICBpZiAoIXByb2Nlc3NJZClcbiAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICB0cnkge1xuICAgICAgICBpZiAoT1Mud2luKVxuICAgICAgICAgICAgcHJvY2Vzcy5raWxsKHByb2Nlc3NJZCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGF3YWl0IGtpbGxQcm9jZXNzVW5peChwcm9jZXNzSWQpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuIl19 |
\ | No newline at end of file |