@browserstack/testcafe
Version:
Automated browser testing for the modern web development stack.
262 lines • 45.4 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const testcafe_browser_tools_1 = __importDefault(require("testcafe-browser-tools"));
const os_family_1 = __importDefault(require("os-family"));
const path_1 = require("path");
const make_dir_1 = __importDefault(require("make-dir"));
const connection_1 = __importDefault(require("../connection"));
const delay_1 = __importDefault(require("../../utils/delay"));
const client_functions_1 = require("./utils/client-functions");
const warning_message_1 = __importDefault(require("../../notifications/warning-message"));
const BROWSER_OPENING_DELAY = 2000;
const RESIZE_DIFF_SIZE = {
width: 100,
height: 100
};
function sumSizes(sizeA, sizeB) {
return {
width: sizeA.width + sizeB.width,
height: sizeA.height + sizeB.height
};
}
function subtractSizes(sizeA, sizeB) {
return {
width: sizeA.width - sizeB.width,
height: sizeA.height - sizeB.height
};
}
class BrowserProvider {
constructor(plugin) {
this.plugin = plugin;
this.initPromise = Promise.resolve(false);
this.isMultiBrowser = this.plugin.isMultiBrowser;
// HACK: The browser window has different border sizes in normal and maximized modes. So, we need to be sure that the window is
// not maximized before resizing it in order to keep the mechanism of correcting the client area size working. When browser is started,
// we are resizing it for the first time to switch the window to normal mode, and for the second time - to restore the client area size.
this.localBrowsersInfo = {};
}
_ensureLocalBrowserInfo(browserId) {
if (this.localBrowsersInfo[browserId])
return;
this.localBrowsersInfo[browserId] = {
windowDescriptor: null,
maxScreenSize: null,
resizeCorrections: null
};
}
_getWindowDescriptor(browserId) {
return this.localBrowsersInfo[browserId] && this.localBrowsersInfo[browserId].windowDescriptor;
}
_getMaxScreenSize(browserId) {
return this.localBrowsersInfo[browserId] && this.localBrowsersInfo[browserId].maxScreenSize;
}
_getResizeCorrections(browserId) {
return this.localBrowsersInfo[browserId] && this.localBrowsersInfo[browserId].resizeCorrections;
}
_isBrowserIdle(browserId) {
const connection = connection_1.default.getById(browserId);
return connection.idle;
}
async _calculateResizeCorrections(browserId) {
if (!this._isBrowserIdle(browserId))
return;
const title = await this.plugin.runInitScript(browserId, client_functions_1.GET_TITLE_SCRIPT);
if (!await testcafe_browser_tools_1.default.isMaximized(title))
return;
const currentSize = await this.plugin.runInitScript(browserId, client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT);
const etalonSize = subtractSizes(currentSize, RESIZE_DIFF_SIZE);
await testcafe_browser_tools_1.default.resize(title, currentSize.width, currentSize.height, etalonSize.width, etalonSize.height);
let resizedSize = await this.plugin.runInitScript(browserId, client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT);
let correctionSize = subtractSizes(resizedSize, etalonSize);
await testcafe_browser_tools_1.default.resize(title, resizedSize.width, resizedSize.height, etalonSize.width, etalonSize.height);
resizedSize = await this.plugin.runInitScript(browserId, client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT);
correctionSize = sumSizes(correctionSize, subtractSizes(resizedSize, etalonSize));
if (this.localBrowsersInfo[browserId])
this.localBrowsersInfo[browserId].resizeCorrections = correctionSize;
await testcafe_browser_tools_1.default.maximize(title);
}
async _calculateMacSizeLimits(browserId) {
if (!this._isBrowserIdle(browserId))
return;
const sizeInfo = await this.plugin.runInitScript(browserId, client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT);
if (this.localBrowsersInfo[browserId]) {
this.localBrowsersInfo[browserId].maxScreenSize = {
width: sizeInfo.availableWidth - (sizeInfo.outerWidth - sizeInfo.width),
height: sizeInfo.availableHeight - (sizeInfo.outerHeight - sizeInfo.height)
};
}
}
async _ensureBrowserWindowDescriptor(browserId) {
if (this._getWindowDescriptor(browserId))
return;
await this._ensureLocalBrowserInfo(browserId);
// NOTE: delay to ensure the window finished the opening
await this.plugin.waitForConnectionReady(browserId);
await delay_1.default(BROWSER_OPENING_DELAY);
if (this.localBrowsersInfo[browserId])
this.localBrowsersInfo[browserId].windowDescriptor = await testcafe_browser_tools_1.default.findWindow(browserId);
}
async _ensureBrowserWindowParameters(browserId) {
await this._ensureBrowserWindowDescriptor(browserId);
if (os_family_1.default.win && !this._getResizeCorrections(browserId))
await this._calculateResizeCorrections(browserId);
else if (os_family_1.default.mac && !this._getMaxScreenSize(browserId))
await this._calculateMacSizeLimits(browserId);
}
async _closeLocalBrowser(browserId) {
if (this.plugin.needCleanUpBrowserInfo)
this.plugin.cleanUpBrowserInfo(browserId);
const windowDescriptor = this._getWindowDescriptor(browserId);
await testcafe_browser_tools_1.default.close(windowDescriptor);
}
async _resizeLocalBrowserWindow(browserId, width, height, currentWidth, currentHeight) {
const resizeCorrections = this._getResizeCorrections(browserId);
if (resizeCorrections && await testcafe_browser_tools_1.default.isMaximized(this._getWindowDescriptor(browserId))) {
width -= resizeCorrections.width;
height -= resizeCorrections.height;
}
await testcafe_browser_tools_1.default.resize(this._getWindowDescriptor(browserId), currentWidth, currentHeight, width, height);
}
async _takeLocalBrowserScreenshot(browserId, screenshotPath) {
await testcafe_browser_tools_1.default.screenshot(this._getWindowDescriptor(browserId), screenshotPath);
}
async _canResizeLocalBrowserWindowToDimensions(browserId, width, height) {
if (!os_family_1.default.mac)
return true;
const maxScreenSize = this._getMaxScreenSize(browserId);
return width <= maxScreenSize.width && height <= maxScreenSize.height;
}
async _maximizeLocalBrowserWindow(browserId) {
await testcafe_browser_tools_1.default.maximize(this._getWindowDescriptor(browserId));
}
async canUseDefaultWindowActions(browserId) {
const isLocalBrowser = await this.plugin.isLocalBrowser(browserId);
const isHeadlessBrowser = await this.plugin.isHeadlessBrowser(browserId);
return isLocalBrowser && !isHeadlessBrowser;
}
async init() {
const initialized = await this.initPromise;
if (initialized)
return;
this.initPromise = this.plugin
.init()
.then(() => true);
try {
await this.initPromise;
}
catch (error) {
this.initPromise = Promise.resolve(false);
throw error;
}
}
async dispose() {
const initialized = await this.initPromise;
if (!initialized)
return;
this.initPromise = this.plugin
.dispose()
.then(() => false);
try {
await this.initPromise;
}
catch (error) {
this.initPromise = Promise.resolve(false);
throw error;
}
}
async isLocalBrowser(browserId, browserName) {
return await this.plugin.isLocalBrowser(browserId, browserName);
}
isHeadlessBrowser(browserId) {
return this.plugin.isHeadlessBrowser(browserId);
}
async openBrowser(browserId, pageUrl, browserName, allowMultipleWindows) {
await this.plugin.openBrowser(browserId, pageUrl, browserName, allowMultipleWindows);
if (await this.canUseDefaultWindowActions(browserId))
await this._ensureBrowserWindowParameters(browserId);
}
async closeBrowser(browserId) {
const canUseDefaultWindowActions = await this.canUseDefaultWindowActions(browserId);
const customActionsInfo = await this.hasCustomActionForBrowser(browserId);
const hasCustomCloseBrowser = customActionsInfo.hasCloseBrowser;
const usePluginsCloseBrowser = hasCustomCloseBrowser || !canUseDefaultWindowActions;
if (usePluginsCloseBrowser)
await this.plugin.closeBrowser(browserId);
else
await this._closeLocalBrowser(browserId);
if (canUseDefaultWindowActions)
delete this.localBrowsersInfo[browserId];
}
async getBrowserList() {
return await this.plugin.getBrowserList();
}
async isValidBrowserName(browserName) {
return await this.plugin.isValidBrowserName(browserName);
}
async resizeWindow(browserId, width, height, currentWidth, currentHeight) {
const canUseDefaultWindowActions = await this.canUseDefaultWindowActions(browserId);
const customActionsInfo = await this.hasCustomActionForBrowser(browserId);
const hasCustomResizeWindow = customActionsInfo.hasResizeWindow;
if (canUseDefaultWindowActions && !hasCustomResizeWindow) {
await this._resizeLocalBrowserWindow(browserId, width, height, currentWidth, currentHeight);
return;
}
await this.plugin.resizeWindow(browserId, width, height, currentWidth, currentHeight);
}
async canResizeWindowToDimensions(browserId, width, height) {
const canUseDefaultWindowActions = await this.canUseDefaultWindowActions(browserId);
const customActionsInfo = await this.hasCustomActionForBrowser(browserId);
const hasCustomCanResizeToDimensions = customActionsInfo.hasCanResizeWindowToDimensions;
if (canUseDefaultWindowActions && !hasCustomCanResizeToDimensions)
return await this._canResizeLocalBrowserWindowToDimensions(browserId, width, height);
return await this.plugin.canResizeWindowToDimensions(browserId, width, height);
}
async maximizeWindow(browserId) {
const canUseDefaultWindowActions = await this.canUseDefaultWindowActions(browserId);
const customActionsInfo = await this.hasCustomActionForBrowser(browserId);
const hasCustomMaximizeWindow = customActionsInfo.hasMaximizeWindow;
if (canUseDefaultWindowActions && !hasCustomMaximizeWindow)
return await this._maximizeLocalBrowserWindow(browserId);
return await this.plugin.maximizeWindow(browserId);
}
async takeScreenshot(browserId, screenshotPath, pageWidth, pageHeight, fullPage) {
const canUseDefaultWindowActions = await this.canUseDefaultWindowActions(browserId);
const customActionsInfo = await this.hasCustomActionForBrowser(browserId);
const hasCustomTakeScreenshot = customActionsInfo.hasTakeScreenshot;
const connection = connection_1.default.getById(browserId);
const takeLocalBrowsersScreenshot = canUseDefaultWindowActions && !hasCustomTakeScreenshot;
const isLocalFullPageMode = takeLocalBrowsersScreenshot && fullPage;
if (isLocalFullPageMode) {
connection.addWarning(warning_message_1.default.screenshotsFullPageNotSupported, connection.browserInfo.alias);
return;
}
await make_dir_1.default(path_1.dirname(screenshotPath));
if (takeLocalBrowsersScreenshot)
await this._takeLocalBrowserScreenshot(browserId, screenshotPath);
else
await this.plugin.takeScreenshot(browserId, screenshotPath, pageWidth, pageHeight, fullPage);
}
async getVideoFrameData(browserId) {
return this.plugin.getVideoFrameData(browserId);
}
async hasCustomActionForBrowser(browserId) {
return this.plugin.hasCustomActionForBrowser(browserId);
}
async reportJobResult(browserId, status, data) {
await this.plugin.reportJobResult(browserId, status, data);
}
getActiveWindowId(browserId) {
if (!this.plugin.supportMultipleWindows)
return null;
return this.plugin.getActiveWindowId(browserId);
}
setActiveWindowId(browserId, val) {
this.plugin.setActiveWindowId(browserId, val);
}
}
exports.default = BrowserProvider;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYnJvd3Nlci9wcm92aWRlci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9GQUFrRDtBQUNsRCwwREFBMkI7QUFDM0IsK0JBQStCO0FBQy9CLHdEQUErQjtBQUMvQiwrREFBOEM7QUFDOUMsOERBQXNDO0FBQ3RDLCtEQUErRjtBQUMvRiwwRkFBa0U7QUFHbEUsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUM7QUFFbkMsTUFBTSxnQkFBZ0IsR0FBRztJQUNyQixLQUFLLEVBQUcsR0FBRztJQUNYLE1BQU0sRUFBRSxHQUFHO0NBQ2QsQ0FBQztBQWFGLFNBQVMsUUFBUSxDQUFFLEtBQVcsRUFBRSxLQUFXO0lBQ3ZDLE9BQU87UUFDSCxLQUFLLEVBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSztRQUNqQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTTtLQUN0QyxDQUFDO0FBQ04sQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFFLEtBQVcsRUFBRSxLQUFXO0lBQzVDLE9BQU87UUFDSCxLQUFLLEVBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSztRQUNqQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTTtLQUN0QyxDQUFDO0FBQ04sQ0FBQztBQUVELE1BQXFCLGVBQWU7SUFNaEMsWUFBb0IsTUFBVztRQUMzQixJQUFJLENBQUMsTUFBTSxHQUFXLE1BQU0sQ0FBQztRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFNLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQztRQUNqRCwrSEFBK0g7UUFDL0gsdUlBQXVJO1FBQ3ZJLHdJQUF3STtR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b3dzZXJUb29scyBmcm9tICd0ZXN0Y2FmZS1icm93c2VyLXRvb2xzJztcbmltcG9ydCBPUyBmcm9tICdvcy1mYW1pbHknO1xuaW1wb3J0IHsgZGlybmFtZSB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IG1ha2VEaXIgZnJvbSAnbWFrZS1kaXInO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uIGZyb20gJy4uL2Nvbm5lY3Rpb24nO1xuaW1wb3J0IGRlbGF5IGZyb20gJy4uLy4uL3V0aWxzL2RlbGF5JztcbmltcG9ydCB7IEdFVF9USVRMRV9TQ1JJUFQsIEdFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVCB9IGZyb20gJy4vdXRpbHMvY2xpZW50LWZ1bmN0aW9ucyc7XG5pbXBvcnQgV0FSTklOR19NRVNTQUdFIGZyb20gJy4uLy4uL25vdGlmaWNhdGlvbnMvd2FybmluZy1tZXNzYWdlJztcbmltcG9ydCB7IERpY3Rpb25hcnkgfSBmcm9tICcuLi8uLi9jb25maWd1cmF0aW9uL2ludGVyZmFjZXMnO1xuXG5jb25zdCBCUk9XU0VSX09QRU5JTkdfREVMQVkgPSAyMDAwO1xuXG5jb25zdCBSRVNJWkVfRElGRl9TSVpFID0ge1xuICAgIHdpZHRoOiAgMTAwLFxuICAgIGhlaWdodDogMTAwXG59O1xuXG5pbnRlcmZhY2UgU2l6ZSB7XG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICBoZWlnaHQ6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIExvY2FsQnJvd3NlckluZm8ge1xuICAgIHdpbmRvd0Rlc2NyaXB0b3I6IG51bGwgfCBzdHJpbmc7XG4gICAgbWF4U2NyZWVuU2l6ZTogbnVsbCB8IFNpemU7XG4gICAgcmVzaXplQ29ycmVjdGlvbnM6IG51bGwgfCBTaXplO1xufVxuXG5mdW5jdGlvbiBzdW1TaXplcyAoc2l6ZUE6IFNpemUsIHNpemVCOiBTaXplKTogU2l6ZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgd2lkdGg6ICBzaXplQS53aWR0aCArIHNpemVCLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IHNpemVBLmhlaWdodCArIHNpemVCLmhlaWdodFxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHN1YnRyYWN0U2l6ZXMgKHNpemVBOiBTaXplLCBzaXplQjogU2l6ZSk6IFNpemUge1xuICAgIHJldHVybiB7XG4gICAgICAgIHdpZHRoOiAgc2l6ZUEud2lkdGggLSBzaXplQi53aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBzaXplQS5oZWlnaHQgLSBzaXplQi5oZWlnaHRcbiAgICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCcm93c2VyUHJvdmlkZXIge1xuICAgIHByaXZhdGUgcGx1Z2luOiBhbnk7XG4gICAgcHJpdmF0ZSBpbml0UHJvbWlzZTogUHJvbWlzZTxhbnk+O1xuICAgIHByaXZhdGUgaXNNdWx0aUJyb3dzZXI6IGJvb2xlYW47XG4gICAgcHJpdmF0ZSByZWFkb25seSBsb2NhbEJyb3dzZXJzSW5mbzogRGljdGlvbmFyeTxMb2NhbEJyb3dzZXJJbmZvPjtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvciAocGx1Z2luOiBhbnkpIHtcbiAgICAgICAgdGhpcy5wbHVnaW4gICAgICAgICA9IHBsdWdpbjtcbiAgICAgICAgdGhpcy5pbml0UHJvbWlzZSAgICA9IFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgICAgIHRoaXMuaXNNdWx0aUJyb3dzZXIgPSB0aGlzLnBsdWdpbi5pc011bHRpQnJvd3NlcjtcbiAgICAgICAgLy8gSEFDSzogVGhlIGJyb3dzZXIgd2luZG93IGhhcyBkaWZmZXJlbnQgYm9yZGVyIHNpemVzIGluIG5vcm1hbCBhbmQgbWF4aW1pemVkIG1vZGVzLiBTbywgd2UgbmVlZCB0byBiZSBzdXJlIHRoYXQgdGhlIHdpbmRvdyBpc1xuICAgICAgICAvLyBub3QgbWF4aW1pemVkIGJlZm9yZSByZXNpemluZyBpdCBpbiBvcmRlciB0byBrZWVwIHRoZSBtZWNoYW5pc20gb2YgY29ycmVjdGluZyB0aGUgY2xpZW50IGFyZWEgc2l6ZSB3b3JraW5nLiBXaGVuIGJyb3dzZXIgaXMgc3RhcnRlZCxcbiAgICAgICAgLy8gd2UgYXJlIHJlc2l6aW5nIGl0IGZvciB0aGUgZmlyc3QgdGltZSB0byBzd2l0Y2ggdGhlIHdpbmRvdyB0byBub3JtYWwgbW9kZSwgYW5kIGZvciB0aGUgc2Vjb25kIHRpbWUgLSB0byByZXN0b3JlIHRoZSBjbGllbnQgYXJlYSBzaXplLlxuICAgICAgICB0aGlzLmxvY2FsQnJvd3NlcnNJbmZvID0ge307XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZW5zdXJlTG9jYWxCcm93c2VySW5mbyAoYnJvd3NlcklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubG9jYWxCcm93c2Vyc0luZm9bYnJvd3NlcklkXSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB0aGlzLmxvY2FsQnJvd3NlcnNJbmZvW2Jyb3dzZXJJZF0gPSB7XG4gICAgICAgICAgICB3aW5kb3dEZXNjcmlwdG9yOiAgbnVsbCxcbiAgICAgICAgICAgIG1heFNjcmVlblNpemU6ICAgICBudWxsLFxuICAgICAgICAgICAgcmVzaXplQ29ycmVjdGlvbnM6IG51bGxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRXaW5kb3dEZXNjcmlwdG9yIChicm93c2VySWQ6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbEJyb3dzZXJzSW5mb1ticm93c2VySWRdICYmIHRoaXMubG9jYWxCcm93c2Vyc0luZm9bYnJvd3NlcklkXS53aW5kb3dEZXNjcmlwdG9yO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldE1heFNjcmVlblNpemUgKGJyb3dzZXJJZDogc3RyaW5nKTogU2l6ZSB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbEJyb3dzZXJzSW5mb1ticm93c2VySWRdICYmIHRoaXMubG9jYWxCcm93c2Vyc0luZm9bYnJvd3NlcklkXS5tYXhTY3JlZW5TaXplO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldFJlc2l6ZUNvcnJlY3Rpb25zIChicm93c2VySWQ6IHN0cmluZyk6IFNpemUgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxCcm93c2Vyc0luZm9bYnJvd3NlcklkXSAmJiB0aGlzLmxvY2FsQnJvd3NlcnNJbmZvW2Jyb3dzZXJJZF0ucmVzaXplQ29ycmVjdGlvbnM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfaXNCcm93c2VySWRsZSAoYnJvd3NlcklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IEJyb3dzZXJDb25uZWN0aW9uLmdldEJ5SWQoYnJvd3NlcklkKSBhcyBCcm93c2VyQ29ubmVjdGlvbjtcblxuICAgICAgICByZXR1cm4gY29ubmVjdGlvbi5pZGxlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2NhbGN1bGF0ZVJlc2l6ZUNvcnJlY3Rpb25zIChicm93c2VySWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMuX2lzQnJvd3NlcklkbGUoYnJvd3NlcklkKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCB0aXRsZSA9IGF3YWl0IHRoaXMucGx1Z2luLnJ1bkluaXRTY3JpcHQoYnJvd3NlcklkLCBHRVRfVElUTEVfU0NSSVBUKTtcblxuICAgICAgICBpZiAoIWF3YWl0IGJyb3dzZXJUb29scy5pc01heGltaXplZCh0aXRsZSkpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgY29uc3QgY3VycmVudFNpemUgPSBhd2FpdCB0aGlzLnBsdWdpbi5ydW5Jbml0U2NyaXB0KGJyb3dzZXJJZCwgR0VUX1dJTkRPV19ESU1FTlNJT05TX0lORk9fU0NSSVBUKTtcbiAgICAgICAgY29uc3QgZXRhbG9uU2l6ZSAgPSBzdWJ0cmFjdFNpemVzKGN1cnJlbnRTaXplLCBSRVNJWkVfRElGRl9TSVpFKTtcblxuICAgICAgICBhd2FpdCBicm93c2VyVG9vbHMucmVzaXplKHRpdGxlLCBjdXJyZW50U2l6ZS53aWR0aCwgY3VycmVudFNpemUuaGVpZ2h0LCBldGFsb25TaXplLndpZHRoLCBldGFsb25TaXplLmhlaWdodCk7XG5cbiAgICAgICAgbGV0IHJlc2l6ZWRTaXplICAgID0gYXdhaXQgdGhpcy5wbHVnaW4ucnVuSW5pdFNjcmlwdChicm93c2VySWQsIEdFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVCk7XG4gICAgICAgIGxldCBjb3JyZWN0aW9uU2l6ZSA9IHN1YnRyYWN0U2l6ZXMocmVzaXplZFNpemUsIGV0YWxvblNpemUpO1xuXG4gICAgICAgIGF3YWl0IGJyb3dzZXJUb29scy5yZXNpemUodGl0bGUsIHJlc2l6ZWRTaXplLndpZHRoLCByZXNpemVkU2l6ZS5oZWlnaHQsIGV0YWxvblNpemUud2lkdGgsIGV0YWxvblNpemUuaGVpZ2h0KTtcblxuICAgICAgICByZXNpemVkU2l6ZSA9IGF3YWl0IHRoaXMucGx1Z2luLnJ1bkluaXRTY3JpcHQoYnJvd3NlcklkLCBHRVRfV0lORE9XX0RJTUVOU0lPTlNfSU5GT19TQ1JJUFQpO1xuXG4gICAgICAgIGNvcnJlY3Rpb25TaXplID0gc3VtU2l6ZXMoY29ycmVjdGlvblNpemUsIHN1YnRyYWN0U2l6ZXMocmVzaXplZFNpemUsIGV0YWxvblNpemUpKTtcblxuICAgICAgICBpZiAodGhpcy5sb2NhbEJyb3dzZXJzSW5mb1ticm93c2VySWRdKVxuICAgICAgICAgICAgdGhpcy5sb2NhbEJyb3dzZXJzSW5mb1ticm93c2VySWRdLnJlc2l6ZUNvcnJlY3Rpb25zID0gY29ycmVjdGlvblNpemU7XG5cbiAgICAgICAgYXdhaXQgYnJvd3NlclRvb2xzLm1heGltaXplKHRpdGxlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9jYWxjdWxhdGVNYWNTaXplTGltaXRzIChicm93c2VySWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMuX2lzQnJvd3NlcklkbGUoYnJvd3NlcklkKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBzaXplSW5mbyA9IGF3YWl0IHRoaXMucGx1Z2luLnJ1bkluaXRTY3JpcHQoYnJvd3NlcklkLCBHRVRfV0lORE9XX0RJTUVOU0lPTlNfSU5GT19TQ1JJUFQpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvY2FsQnJvd3NlcnNJbmZvW2Jyb3dzZXJJZF0pIHtcbiAgICAgICAgICAgIHRoaXMubG9jYWxCcm93c2Vyc0luZm9bYnJvd3NlcklkXS5tYXhTY3JlZW5TaXplID0ge1xuICAgICAgICAgICAgICAgIHdpZHRoOiAgc2l6ZUluZm8uYXZhaWxhYmxlV2lkdGggLSAoc2l6ZUluZm8ub3V0ZXJXaWR0aCAtIHNpemVJbmZvLndpZHRoKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHNpemVJbmZvLmF2YWlsYWJsZUhlaWdodCAtIChzaXplSW5mby5vdXRlckhlaWdodCAtIHNpemVJbmZvLmhlaWdodClcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9lbnN1cmVCcm93c2VyV2luZG93RGVzY3JpcHRvciAoYnJvd3NlcklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMuX2dldFdpbmRvd0Rlc2NyaXB0b3IoYnJvd3NlcklkKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBhd2FpdCB0aGlzLl9lbnN1cmVMb2NhbEJyb3dzZXJJbmZvKGJyb3dzZXJJZCk7XG5cbiAgICAgICAgLy8gTk9URTogZGVsYXkgdG8gZW5zdXJlIHRoZSB3aW5kb3cgZmluaXNoZWQgdGhlIG9wZW5pbmdcbiAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ud2FpdEZvckNvbm5lY3Rpb25SZWFkeShicm93c2VySWQpO1xuICAgICAgICBhd2FpdCBkZWxheShCUk9XU0VSX09QRU5JTkdfREVMQVkpO1xuXG4gICAgICAgIGlmICh0aGlzLmxvY2FsQnJvd3NlcnNJbmZvW2Jyb3dzZXJJZF0pXG4gICAgICAgICAgICB0aGlzLmxvY2FsQnJvd3NlcnNJbmZvW2Jyb3dzZXJJZF0ud2luZG93RGVzY3JpcHRvciA9IGF3YWl0IGJyb3dzZXJUb29scy5maW5kV2luZG93KGJyb3dzZXJJZCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfZW5zdXJlQnJvd3NlcldpbmRvd1BhcmFtZXRlcnMgKGJyb3dzZXJJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2Vuc3VyZUJyb3dzZXJXaW5kb3dEZXNjcmlwdG9yKGJyb3dzZXJJZCk7XG5cbiAgICAgICAgaWYgKE9TLndpbiAmJiAhdGhpcy5fZ2V0UmVzaXplQ29ycmVjdGlvbnMoYnJvd3NlcklkKSlcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2NhbGN1bGF0ZVJlc2l6ZUNvcnJlY3Rpb25zKGJyb3dzZXJJZCk7XG4gICAgICAgIGVsc2UgaWYgKE9TLm1hYyAmJiAhdGhpcy5fZ2V0TWF4U2NyZWVuU2l6ZShicm93c2VySWQpKVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fY2FsY3VsYXRlTWFjU2l6ZUxpbWl0cyhicm93c2VySWQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2Nsb3NlTG9jYWxCcm93c2VyIChicm93c2VySWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5wbHVnaW4ubmVlZENsZWFuVXBCcm93c2VySW5mbylcbiAgICAgICAgICAgIHRoaXMucGx1Z2luLmNsZWFuVXBCcm93c2VySW5mbyhicm93c2VySWQpO1xuXG4gICAgICAgIGNvbnN0IHdpbmRvd0Rlc2NyaXB0b3IgPSB0aGlzLl9nZXRXaW5kb3dEZXNjcmlwdG9yKGJyb3dzZXJJZCk7XG5cbiAgICAgICAgYXdhaXQgYnJvd3NlclRvb2xzLmNsb3NlKHdpbmRvd0Rlc2NyaXB0b3IpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3Jlc2l6ZUxvY2FsQnJvd3NlcldpbmRvdyAoYnJvd3NlcklkOiBzdHJpbmcsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBjdXJyZW50V2lkdGg6IG51bWJlciwgY3VycmVudEhlaWdodDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHJlc2l6ZUNvcnJlY3Rpb25zID0gdGhpcy5fZ2V0UmVzaXplQ29ycmVjdGlvbnMoYnJvd3NlcklkKTtcblxuICAgICAgICBpZiAocmVzaXplQ29ycmVjdGlvbnMgJiYgYXdhaXQgYnJvd3NlclRvb2xzLmlzTWF4aW1pemVkKHRoaXMuX2dldFdpbmRvd0Rlc2NyaXB0b3IoYnJvd3NlcklkKSkpIHtcbiAgICAgICAgICAgIHdpZHRoIC09IHJlc2l6ZUNvcnJlY3Rpb25zLndpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0IC09IHJlc2l6ZUNvcnJlY3Rpb25zLmhlaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IGJyb3dzZXJUb29scy5yZXNpemUodGhpcy5fZ2V0V2luZG93RGVzY3JpcHRvcihicm93c2VySWQpLCBjdXJyZW50V2lkdGgsIGN1cnJlbnRIZWlnaHQsIHdpZHRoLCBoZWlnaHQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3Rha2VMb2NhbEJyb3dzZXJTY3JlZW5zaG90IChicm93c2VySWQ6IHN0cmluZywgc2NyZWVuc2hvdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCBicm93c2VyVG9vbHMuc2NyZWVuc2hvdCh0aGlzLl9nZXRXaW5kb3dEZXNjcmlwdG9yKGJyb3dzZXJJZCksIHNjcmVlbnNob3RQYXRoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9jYW5SZXNpemVMb2NhbEJyb3dzZXJXaW5kb3dUb0RpbWVuc2lvbnMgKGJyb3dzZXJJZDogc3RyaW5nLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBpZiAoIU9TLm1hYylcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgICAgIGNvbnN0IG1heFNjcmVlblNpemUgPSB0aGlzLl9nZXRNYXhTY3JlZW5TaXplKGJyb3dzZXJJZCkgYXMgU2l6ZTtcblxuICAgICAgICByZXR1cm4gd2lkdGggPD0gbWF4U2NyZWVuU2l6ZS53aWR0aCAmJiBoZWlnaHQgPD0gbWF4U2NyZWVuU2l6ZS5oZWlnaHQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfbWF4aW1pemVMb2NhbEJyb3dzZXJXaW5kb3cgKGJyb3dzZXJJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IGJyb3dzZXJUb29scy5tYXhpbWl6ZSh0aGlzLl9nZXRXaW5kb3dEZXNjcmlwdG9yKGJyb3dzZXJJZCkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyAoYnJvd3NlcklkOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgaXNMb2NhbEJyb3dzZXIgICAgPSBhd2FpdCB0aGlzLnBsdWdpbi5pc0xvY2FsQnJvd3Nlcihicm93c2VySWQpO1xuICAgICAgICBjb25zdCBpc0hlYWRsZXNzQnJvd3NlciA9IGF3YWl0IHRoaXMucGx1Z2luLmlzSGVhZGxlc3NCcm93c2VyKGJyb3dzZXJJZCk7XG5cbiAgICAgICAgcmV0dXJuIGlzTG9jYWxCcm93c2VyICYmICFpc0hlYWRsZXNzQnJvd3NlcjtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaW5pdCAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGluaXRpYWxpemVkID0gYXdhaXQgdGhpcy5pbml0UHJvbWlzZTtcblxuICAgICAgICBpZiAoaW5pdGlhbGl6ZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5pbml0UHJvbWlzZSA9IHRoaXMucGx1Z2luXG4gICAgICAgICAgICAuaW5pdCgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0cnVlKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5pbml0UHJvbWlzZTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuXG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBkaXNwb3NlICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgaW5pdGlhbGl6ZWQgPSBhd2FpdCB0aGlzLmluaXRQcm9taXNlO1xuXG4gICAgICAgIGlmICghaW5pdGlhbGl6ZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5pbml0UHJvbWlzZSA9IHRoaXMucGx1Z2luXG4gICAgICAgICAgICAuZGlzcG9zZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiBmYWxzZSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuaW5pdFByb21pc2U7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcblxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaXNMb2NhbEJyb3dzZXIgKGJyb3dzZXJJZD86IHN0cmluZywgYnJvd3Nlck5hbWU/OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucGx1Z2luLmlzTG9jYWxCcm93c2VyKGJyb3dzZXJJZCwgYnJvd3Nlck5hbWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc0hlYWRsZXNzQnJvd3NlciAoYnJvd3NlcklkOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGx1Z2luLmlzSGVhZGxlc3NCcm93c2VyKGJyb3dzZXJJZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIG9wZW5Ccm93c2VyIChicm93c2VySWQ6IHN0cmluZywgcGFnZVVybDogc3RyaW5nLCBicm93c2VyTmFtZTogc3RyaW5nLCBhbGxvd011bHRpcGxlV2luZG93czogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5vcGVuQnJvd3Nlcihicm93c2VySWQsIHBhZ2VVcmwsIGJyb3dzZXJOYW1lLCBhbGxvd011bHRpcGxlV2luZG93cyk7XG5cbiAgICAgICAgaWYgKGF3YWl0IHRoaXMuY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnMoYnJvd3NlcklkKSlcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Vuc3VyZUJyb3dzZXJXaW5kb3dQYXJhbWV0ZXJzKGJyb3dzZXJJZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNsb3NlQnJvd3NlciAoYnJvd3NlcklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnMgPSBhd2FpdCB0aGlzLmNhblVzZURlZmF1bHRXaW5kb3dBY3Rpb25zKGJyb3dzZXJJZCk7XG4gICAgICAgIGNvbnN0IGN1c3RvbUFjdGlvbnNJbmZvICAgICAgICAgID0gYXdhaXQgdGhpcy5oYXNDdXN0b21BY3Rpb25Gb3JCcm93c2VyKGJyb3dzZXJJZCk7XG4gICAgICAgIGNvbnN0IGhhc0N1c3RvbUNsb3NlQnJvd3NlciAgICAgID0gY3VzdG9tQWN0aW9uc0luZm8uaGFzQ2xvc2VCcm93c2VyO1xuICAgICAgICBjb25zdCB1c2VQbHVnaW5zQ2xvc2VCcm93c2VyICAgICA9IGhhc0N1c3RvbUNsb3NlQnJvd3NlciB8fCAhY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnM7XG5cbiAgICAgICAgaWYgKHVzZVBsdWdpbnNDbG9zZUJyb3dzZXIpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5jbG9zZUJyb3dzZXIoYnJvd3NlcklkKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fY2xvc2VMb2NhbEJyb3dzZXIoYnJvd3NlcklkKTtcblxuICAgICAgICBpZiAoY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnMpXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5sb2NhbEJyb3dzZXJzSW5mb1ticm93c2VySWRdO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRCcm93c2VyTGlzdCAoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5wbHVnaW4uZ2V0QnJvd3Nlckxpc3QoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgaXNWYWxpZEJyb3dzZXJOYW1lIChicm93c2VyTmFtZTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnBsdWdpbi5pc1ZhbGlkQnJvd3Nlck5hbWUoYnJvd3Nlck5hbWUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXNpemVXaW5kb3cgKGJyb3dzZXJJZDogc3RyaW5nLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgY3VycmVudFdpZHRoOiBudW1iZXIsIGN1cnJlbnRIZWlnaHQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyA9IGF3YWl0IHRoaXMuY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnMoYnJvd3NlcklkKTtcbiAgICAgICAgY29uc3QgY3VzdG9tQWN0aW9uc0luZm8gICAgICAgICAgPSBhd2FpdCB0aGlzLmhhc0N1c3RvbUFjdGlvbkZvckJyb3dzZXIoYnJvd3NlcklkKTtcbiAgICAgICAgY29uc3QgaGFzQ3VzdG9tUmVzaXplV2luZG93ICAgICAgPSBjdXN0b21BY3Rpb25zSW5mby5oYXNSZXNpemVXaW5kb3c7XG5cblxuICAgICAgICBpZiAoY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnMgJiYgIWhhc0N1c3RvbVJlc2l6ZVdpbmRvdykge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fcmVzaXplTG9jYWxCcm93c2VyV2luZG93KGJyb3dzZXJJZCwgd2lkdGgsIGhlaWdodCwgY3VycmVudFdpZHRoLCBjdXJyZW50SGVpZ2h0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnJlc2l6ZVdpbmRvdyhicm93c2VySWQsIHdpZHRoLCBoZWlnaHQsIGN1cnJlbnRXaWR0aCwgY3VycmVudEhlaWdodCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNhblJlc2l6ZVdpbmRvd1RvRGltZW5zaW9ucyAoYnJvd3NlcklkOiBzdHJpbmcsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIGNvbnN0IGNhblVzZURlZmF1bHRXaW5kb3dBY3Rpb25zICAgICA9IGF3YWl0IHRoaXMuY2FuVXNlRGVmYXVsdFdpbmRvd0FjdGlvbnMoYnJvd3NlcklkKTtcbiAgICAgICAgY29uc3QgY3VzdG9tQWN0aW9uc0luZm8gICAgICAgICAgICAgID0gYXdhaXQgdGhpcy5oYXNDdXN0b21BY3Rpb25Gb3JCcm93c2VyKGJyb3dzZXJJZCk7XG4gICAgICAgIGNvbnN0IGhhc0N1c3RvbUNhblJlc2l6ZVRvRGltZW5zaW9ucyA9IGN1c3RvbUFjdGlvbnNJbmZvLmhhc0NhblJlc2l6ZVdpbmRvd1RvRGltZW5zaW9ucztcblxuXG4gICAgICAgIGlmIChjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyAmJiAhaGFzQ3VzdG9tQ2FuUmVzaXplVG9EaW1lbnNpb25zKVxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2NhblJlc2l6ZUxvY2FsQnJvd3NlcldpbmRvd1RvRGltZW5zaW9ucyhicm93c2VySWQsIHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnBsdWdpbi5jYW5SZXNpemVXaW5kb3dUb0RpbWVuc2lvbnMoYnJvd3NlcklkLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgbWF4aW1pemVXaW5kb3cgKGJyb3dzZXJJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNhblVzZURlZmF1bHRXaW5kb3dBY3Rpb25zID0gYXdhaXQgdGhpcy5jYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyhicm93c2VySWQpO1xuICAgICAgICBjb25zdCBjdXN0b21BY3Rpb25zSW5mbyAgICAgICAgICA9IGF3YWl0IHRoaXMuaGFzQ3VzdG9tQWN0aW9uRm9yQnJvd3Nlcihicm93c2VySWQpO1xuICAgICAgICBjb25zdCBoYXNDdXN0b21NYXhpbWl6ZVdpbmRvdyAgICA9IGN1c3RvbUFjdGlvbnNJbmZvLmhhc01heGltaXplV2luZG93O1xuXG4gICAgICAgIGlmIChjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyAmJiAhaGFzQ3VzdG9tTWF4aW1pemVXaW5kb3cpXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fbWF4aW1pemVMb2NhbEJyb3dzZXJXaW5kb3coYnJvd3NlcklkKTtcblxuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5wbHVnaW4ubWF4aW1pemVXaW5kb3coYnJvd3NlcklkKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgdGFrZVNjcmVlbnNob3QgKGJyb3dzZXJJZDogc3RyaW5nLCBzY3JlZW5zaG90UGF0aDogc3RyaW5nLCBwYWdlV2lkdGg6IG51bWJlciwgcGFnZUhlaWdodDogbnVtYmVyLCBmdWxsUGFnZTogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyAgPSBhd2FpdCB0aGlzLmNhblVzZURlZmF1bHRXaW5kb3dBY3Rpb25zKGJyb3dzZXJJZCk7XG4gICAgICAgIGNvbnN0IGN1c3RvbUFjdGlvbnNJbmZvICAgICAgICAgICA9IGF3YWl0IHRoaXMuaGFzQ3VzdG9tQWN0aW9uRm9yQnJvd3Nlcihicm93c2VySWQpO1xuICAgICAgICBjb25zdCBoYXNDdXN0b21UYWtlU2NyZWVuc2hvdCAgICAgPSBjdXN0b21BY3Rpb25zSW5mby5oYXNUYWtlU2NyZWVuc2hvdDtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbiAgICAgICAgICAgICAgICAgID0gQnJvd3NlckNvbm5lY3Rpb24uZ2V0QnlJZChicm93c2VySWQpIGFzIEJyb3dzZXJDb25uZWN0aW9uO1xuICAgICAgICBjb25zdCB0YWtlTG9jYWxCcm93c2Vyc1NjcmVlbnNob3QgPSBjYW5Vc2VEZWZhdWx0V2luZG93QWN0aW9ucyAmJiAhaGFzQ3VzdG9tVGFrZVNjcmVlbnNob3Q7XG4gICAgICAgIGNvbnN0IGlzTG9jYWxGdWxsUGFnZU1vZGUgICAgICAgICA9IHRha2VMb2NhbEJyb3dzZXJzU2NyZWVuc2hvdCAmJiBmdWxsUGFnZTtcblxuICAgICAgICBpZiAoaXNMb2NhbEZ1bGxQYWdlTW9kZSkge1xuICAgICAgICAgICAgY29ubmVjdGlvbi5hZGRXYXJuaW5nKFdBUk5JTkdfTUVTU0FHRS5zY3JlZW5zaG90c0Z1bGxQYWdlTm90U3VwcG9ydGVkLCBjb25uZWN0aW9uLmJyb3dzZXJJbmZvLmFsaWFzKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgbWFrZURpcihkaXJuYW1lKHNjcmVlbnNob3RQYXRoKSk7XG5cbiAgICAgICAgaWYgKHRha2VMb2NhbEJyb3dzZXJzU2NyZWVuc2hvdClcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX3Rha2VMb2NhbEJyb3dzZXJTY3JlZW5zaG90KGJyb3dzZXJJZCwgc2NyZWVuc2hvdFBhdGgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi50YWtlU2NyZWVuc2hvdChicm93c2VySWQsIHNjcmVlbnNob3RQYXRoLCBwYWdlV2lkdGgsIHBhZ2VIZWlnaHQsIGZ1bGxQYWdlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0VmlkZW9GcmFtZURhdGEgKGJyb3dzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGx1Z2luLmdldFZpZGVvRnJhbWVEYXRhKGJyb3dzZXJJZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGhhc0N1c3RvbUFjdGlvbkZvckJyb3dzZXIgKGJyb3dzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGx1Z2luLmhhc0N1c3RvbUFjdGlvbkZvckJyb3dzZXIoYnJvd3NlcklkKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcmVwb3J0Sm9iUmVzdWx0IChicm93c2VySWQ6IHN0cmluZywgc3RhdHVzOiBzdHJpbmcsIGRhdGE6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRKb2JSZXN1bHQoYnJvd3NlcklkLCBzdGF0dXMsIGRhdGEpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRBY3RpdmVXaW5kb3dJZCAoYnJvd3NlcklkOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgaWYgKCF0aGlzLnBsdWdpbi5zdXBwb3J0TXVsdGlwbGVXaW5kb3dzKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGx1Z2luLmdldEFjdGl2ZVdpbmRvd0lkKGJyb3dzZXJJZCk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldEFjdGl2ZVdpbmRvd0lkIChicm93c2VySWQ6IHN0cmluZywgdmFsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wbHVnaW4uc2V0QWN0aXZlV2luZG93SWQoYnJvd3NlcklkLCB2YWwpO1xuICAgIH1cbn1cbiJdfQ==