gst-atom-xcuitest-driver
Version:
ATOM driver for iOS using XCUITest for backend
344 lines (273 loc) • 41.2 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("source-map-support/register");
var _gstAtomIosDriver = require("gst-atom-ios-driver");
var _asyncbox = require("asyncbox");
var _appiumSupport = require("appium-support");
var _logger = _interopRequireDefault(require("../logger"));
var _lodash = _interopRequireDefault(require("lodash"));
var _bluebird = _interopRequireDefault(require("bluebird"));
const IPHONE_TOP_BAR_HEIGHT = 71;
const IPHONE_SCROLLED_TOP_BAR_HEIGHT = 41;
const IPHONE_X_SCROLLED_OFFSET = 55;
const IPHONE_X_NOTCH_OFFSET_IOS = 24;
const IPHONE_X_NOTCH_OFFSET_IOS_13 = 20;
const IPHONE_LANDSCAPE_TOP_BAR_HEIGHT = 51;
const IPHONE_BOTTOM_BAR_OFFSET = 49;
const TAB_BAR_OFFSET = 33;
const IPHONE_WEB_COORD_SMART_APP_BANNER_OFFSET = 84;
const IPAD_WEB_COORD_SMART_APP_BANNER_OFFSET = 95;
const NOTCHED_DEVICE_SIZES = [{
w: 1125,
h: 2436
}, {
w: 828,
h: 1792
}, {
w: 1242,
h: 2688
}];
const ATOM_WAIT_TIMEOUT = 2 * 60000;
const ATOM_WAIT_ALERT_WAIT = 400;
let extensions = {};
Object.assign(extensions, _gstAtomIosDriver.iosCommands.web);
extensions.getSafariIsIphone = _lodash.default.memoize(async function getSafariIsIphone() {
try {
const userAgent = await this.execute('return navigator.userAgent');
return userAgent.toLowerCase().includes('iphone');
} catch (err) {
_logger.default.warn(`Unable to find device type from useragent. Assuming iPhone`);
_logger.default.debug(`Error: ${err.message}`);
}
return true;
});
extensions.getSafariDeviceSize = _lodash.default.memoize(async function getSafariDeviceSize() {
const script = 'return {height: window.screen.availHeight * window.devicePixelRatio, width: window.screen.availWidth * window.devicePixelRatio};';
const {
width,
height
} = await this.execute(script);
const [normHeight, normWidth] = height > width ? [height, width] : [width, height];
return {
width: normWidth,
height: normHeight
};
});
extensions.getSafariIsNotched = _lodash.default.memoize(async function getSafariIsNotched() {
try {
const {
width,
height
} = await this.getSafariDeviceSize();
for (const device of NOTCHED_DEVICE_SIZES) {
if (device.w === width && device.h === height) {
return true;
}
}
} catch (err) {
_logger.default.warn(`Unable to find device type from dimensions. Assuming the device is not notched`);
_logger.default.debug(`Error: ${err.message}`);
}
return false;
});
extensions.getExtraTranslateWebCoordsOffset = async function getExtraTranslateWebCoordsOffset(wvPos, realDims) {
let topOffset = 0;
let bottomOffset = 0;
const isIphone = await this.getSafariIsIphone();
const isNotched = isIphone && (await this.getSafariIsNotched());
const orientation = realDims.h > realDims.w ? 'PORTRAIT' : 'LANDSCAPE';
const notchOffset = isNotched ? _appiumSupport.util.compareVersions(this.opts.platformVersion, '=', '13.0') ? IPHONE_X_NOTCH_OFFSET_IOS_13 : IPHONE_X_NOTCH_OFFSET_IOS : 0;
const isScrolled = await this.execute('return document.documentElement.scrollTop > 0');
if (isScrolled) {
topOffset = IPHONE_SCROLLED_TOP_BAR_HEIGHT + notchOffset;
if (isNotched) {
topOffset -= IPHONE_X_SCROLLED_OFFSET;
}
if (orientation === 'LANDSCAPE' && isIphone) {
topOffset = 0;
}
} else {
topOffset = IPHONE_TOP_BAR_HEIGHT + notchOffset;
if (isIphone) {
if (orientation === 'PORTRAIT') {
bottomOffset = IPHONE_BOTTOM_BAR_OFFSET;
} else {
topOffset = IPHONE_LANDSCAPE_TOP_BAR_HEIGHT;
}
}
if (orientation === 'LANDSCAPE' || !isIphone) {
const tabs = await this.findNativeElementOrElements('-ios predicate string', `name LIKE '*, Tab' AND visible = 1`, true);
if (tabs.length > 0) {
topOffset += TAB_BAR_OFFSET;
}
}
}
topOffset += await this.getExtraNativeWebTapOffset();
wvPos.y += topOffset;
realDims.h -= topOffset + bottomOffset;
};
extensions.getExtraNativeWebTapOffset = async function getExtraNativeWebTapOffset() {
let offset = 0;
const banners = await this.findNativeElementOrElements('accessibility id', 'Close app download offer', true);
if (banners.length > 0) {
offset += (await this.getSafariIsIphone()) ? IPHONE_WEB_COORD_SMART_APP_BANNER_OFFSET : IPAD_WEB_COORD_SMART_APP_BANNER_OFFSET;
}
_logger.default.debug(`Additional native web tap offset computed: ${offset}`);
return offset;
};
async function tapWebElementNatively(driver, atomsElement) {
try {
let text = await driver.executeAtom('get_text', [atomsElement]);
if (!text) {
text = await driver.executeAtom('get_attribute_value', [atomsElement, 'value']);
}
if (text) {
const els = await driver.findNativeElementOrElements('accessibility id', text, true);
if (els.length === 1 || els.length === 2) {
const el = els[0];
const rect = await driver.proxyCommand(`/element/${_appiumSupport.util.unwrapElement(el)}/rect`, 'GET');
if (els.length === 2) {
const el2 = els[1];
const rect2 = await driver.proxyCommand(`/element/${_appiumSupport.util.unwrapElement(el2)}/rect`, 'GET');
if (rect.x !== rect2.x || rect.y !== rect2.y || rect.width !== rect2.width || rect.height !== rect2.height) {
return false;
}
}
const coords = {
x: Math.round(rect.x + rect.width / 2),
y: Math.round(rect.y + rect.height / 2)
};
await driver.clickCoords(coords);
return true;
}
}
} catch (err) {
_logger.default.warn(`Error attempting to click: ${err.message}`);
}
return false;
}
extensions.nativeWebTap = async function nativeWebTap(el) {
const atomsElement = this.useAtomsElement(el);
if (!(await this.settings.getSettings()).nativeWebTapStrict && (await tapWebElementNatively(this, atomsElement))) {
return;
}
_logger.default.warn('Unable to do simple native web tap. Attempting to convert coordinates');
await this.executeAtom('get_size', [atomsElement]);
await this.executeAtom('get_top_left_coordinates', [atomsElement]);
const {
width,
height
} = await this.executeAtom('get_size', [atomsElement]);
let {
x,
y
} = await this.executeAtom('get_top_left_coordinates', [atomsElement]);
x += width / 2;
y += height / 2;
this.curWebCoords = {
x,
y
};
await this.clickWebCoords();
};
extensions.clickCoords = async function clickCoords(coords) {
await this.performTouch([{
action: 'tap',
options: coords
}]);
};
extensions.translateWebCoords = async function translateWebCoords(coords) {
_logger.default.debug(`Translating coordinates (${JSON.stringify(coords)}) to web coordinates`);
let webview = await (0, _asyncbox.retryInterval)(5, 100, async () => {
const webviews = await this.findNativeElementOrElements('class name', 'XCUIElementTypeWebView', true);
if (webviews.length === 0) {
throw new Error(`No webviews found. Unable to translate web coordinates for native web tap`);
}
return webviews[0];
});
webview = _appiumSupport.util.unwrapElement(webview);
const rect = await this.proxyCommand(`/element/${webview}/rect`, 'GET');
const wvPos = {
x: rect.x,
y: rect.y
};
const realDims = {
w: rect.width,
h: rect.height
};
const cmd = '(function () { return {w: window.innerWidth, h: window.innerHeight}; })()';
const wvDims = await this.remote.execute(cmd);
await this.getExtraTranslateWebCoordsOffset(wvPos, realDims);
if (wvDims && realDims && wvPos) {
let xRatio = realDims.w / wvDims.w;
let yRatio = realDims.h / wvDims.h;
let newCoords = {
x: wvPos.x + Math.round(xRatio * coords.x),
y: wvPos.y + Math.round(yRatio * coords.y)
};
_logger.default.debug(`Converted coordinates: ${JSON.stringify(newCoords)}`);
_logger.default.debug(` rect: ${JSON.stringify(rect)}`);
_logger.default.debug(` wvPos: ${JSON.stringify(wvPos)}`);
_logger.default.debug(` realDims: ${JSON.stringify(realDims)}`);
_logger.default.debug(` wvDims: ${JSON.stringify(wvDims)}`);
_logger.default.debug(` xRatio: ${JSON.stringify(xRatio)}`);
_logger.default.debug(` yRatio: ${JSON.stringify(yRatio)}`);
_logger.default.debug(`Converted web coords ${JSON.stringify(coords)} ` + `into real coords ${JSON.stringify(newCoords)}`);
return newCoords;
}
};
extensions.checkForAlert = async function checkForAlert() {
return _lodash.default.isString(await this.getAlertText());
};
extensions.waitForAtom = async function waitForAtom(promise) {
const timer = new _appiumSupport.timing.Timer().start();
let done = false;
let error = null;
promise = _bluebird.default.resolve(promise).timeout(ATOM_WAIT_TIMEOUT).catch(function (err) {
_logger.default.debug(`Error received while executing atom: ${err.message}`);
if (err instanceof _bluebird.default.TimeoutError) {
err = new Error(`Did not get any response for atom execution after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
}
error = err;
}).finally(function () {
done = true;
});
for (let i = 0; i < 10; i++) {
try {
await (0, _asyncbox.waitForCondition)(() => done, {
waitMs: ATOM_WAIT_ALERT_WAIT,
intervalMs: 0
});
break;
} catch (ign) {}
try {
const res = await _bluebird.default.any([this.checkForAlert(), promise]);
if (error) {
throw error;
}
return this.parseExecuteResponse(res);
} catch (err) {
_logger.default.debug(`No alert found: ${err.message}`);
}
}
const res = await promise;
if (error) {
throw error;
}
return this.parseExecuteResponse(res);
};
extensions.mobileWebNav = async function mobileWebNav(navType) {
this.remote.allowNavigationWithoutReload = true;
try {
await this.executeAtom('execute_script', [`history.${navType}();`, null]);
} finally {
this.remote.allowNavigationWithoutReload = false;
}
};
var _default = extensions;
exports.default = _default;require('source-map-support').install();
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9jb21tYW5kcy93ZWIuanMiXSwibmFtZXMiOlsiSVBIT05FX1RPUF9CQVJfSEVJR0hUIiwiSVBIT05FX1NDUk9MTEVEX1RPUF9CQVJfSEVJR0hUIiwiSVBIT05FX1hfU0NST0xMRURfT0ZGU0VUIiwiSVBIT05FX1hfTk9UQ0hfT0ZGU0VUX0lPUyIsIklQSE9ORV9YX05PVENIX09GRlNFVF9JT1NfMTMiLCJJUEhPTkVfTEFORFNDQVBFX1RPUF9CQVJfSEVJR0hUIiwiSVBIT05FX0JPVFRPTV9CQVJfT0ZGU0VUIiwiVEFCX0JBUl9PRkZTRVQiLCJJUEhPTkVfV0VCX0NPT1JEX1NNQVJUX0FQUF9CQU5ORVJfT0ZGU0VUIiwiSVBBRF9XRUJfQ09PUkRfU01BUlRfQVBQX0JBTk5FUl9PRkZTRVQiLCJOT1RDSEVEX0RFVklDRV9TSVpFUyIsInciLCJoIiwiQVRPTV9XQUlUX1RJTUVPVVQiLCJBVE9NX1dBSVRfQUxFUlRfV0FJVCIsImV4dGVuc2lvbnMiLCJPYmplY3QiLCJhc3NpZ24iLCJpb3NDb21tYW5kcyIsIndlYiIsImdldFNhZmFyaUlzSXBob25lIiwiXyIsIm1lbW9pemUiLCJ1c2VyQWdlbnQiLCJleGVjdXRlIiwidG9Mb3dlckNhc2UiLCJpbmNsdWRlcyIsImVyciIsImxvZyIsIndhcm4iLCJkZWJ1ZyIsIm1lc3NhZ2UiLCJnZXRTYWZhcmlEZXZpY2VTaXplIiwic2NyaXB0Iiwid2lkdGgiLCJoZWlnaHQiLCJub3JtSGVpZ2h0Iiwibm9ybVdpZHRoIiwiZ2V0U2FmYXJpSXNOb3RjaGVkIiwiZGV2aWNlIiwiZ2V0RXh0cmFUcmFuc2xhdGVXZWJDb29yZHNPZmZzZXQiLCJ3dlBvcyIsInJlYWxEaW1zIiwidG9wT2Zmc2V0IiwiYm90dG9tT2Zmc2V0IiwiaXNJcGhvbmUiLCJpc05vdGNoZWQiLCJvcmllbnRhdGlvbiIsIm5vdGNoT2Zmc2V0IiwidXRpbCIsImNvbXBhcmVWZXJzaW9ucyIsIm9wdHMiLCJwbGF0Zm9ybVZlcnNpb24iLCJpc1Njcm9sbGVkIiwidGFicyIsImZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cyIsImxlbmd0aCIsImdldEV4dHJhTmF0aXZlV2ViVGFwT2Zmc2V0IiwieSIsIm9mZnNldCIsImJhbm5lcnMiLCJ0YXBXZWJFbGVtZW50TmF0aXZlbHkiLCJkcml2ZXIiLCJhdG9tc0VsZW1lbnQiLCJ0ZXh0IiwiZXhlY3V0ZUF0b20iLCJlbHMiLCJlbCIsInJlY3QiLCJwcm94eUNvbW1hbmQiLCJ1bndyYXBFbGVtZW50IiwiZWwyIiwicmVjdDIiLCJ4IiwiY29vcmRzIiwiTWF0aCIsInJvdW5kIiwiY2xpY2tDb29yZHMiLCJuYXRpdmVXZWJUYXAiLCJ1c2VBdG9tc0VsZW1lbnQiLCJzZXR0aW5ncyIsImdldFNldHRpbmdzIiwibmF0aXZlV2ViVGFwU3RyaWN0IiwiY3VyV2ViQ29vcmRzIiwiY2xpY2tXZWJDb29yZHMiLCJwZXJmb3JtVG91Y2giLCJhY3Rpb24iLCJvcHRpb25zIiwidHJhbnNsYXRlV2ViQ29vcmRzIiwiSlNPTiIsInN0cmluZ2lmeSIsIndlYnZpZXciLCJ3ZWJ2aWV3cyIsIkVycm9yIiwiY21kIiwid3ZEaW1zIiwicmVtb3RlIiwieFJhdGlvIiwieVJhdGlvIiwibmV3Q29vcmRzIiwiY2hlY2tGb3JBbGVydCIsImlzU3RyaW5nIiwiZ2V0QWxlcnRUZXh0Iiwid2FpdEZvckF0b20iLCJwcm9taXNlIiwidGltZXIiLCJ0aW1pbmciLCJUaW1lciIsInN0YXJ0IiwiZG9uZSIsImVycm9yIiwiQiIsInJlc29sdmUiLCJ0aW1lb3V0IiwiY2F0Y2giLCJUaW1lb3V0RXJyb3IiLCJnZXREdXJhdGlvbiIsImFzTWlsbGlTZWNvbmRzIiwidG9GaXhlZCIsImZpbmFsbHkiLCJpIiwid2FpdE1zIiwiaW50ZXJ2YWxNcyIsImlnbiIsInJlcyIsImFueSIsInBhcnNlRXhlY3V0ZVJlc3BvbnNlIiwibW9iaWxlV2ViTmF2IiwibmF2VHlwZSIsImFsbG93TmF2aWdhdGlvbldpdGhvdXRSZWxvYWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7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LENBQUMsS0FBS3pCLGFBQUwsRUFBRCxFQUF1QkksT0FBdkIsQ0FBTixDQUFsQjs7QUFDQSxVQUFJTSxLQUFKLEVBQVc7QUFDVCxjQUFNQSxLQUFOO0FBQ0Q7O0FBQ0QsYUFBTyxLQUFLZ0Isb0JBQUwsQ0FBMEJGLEdBQTFCLENBQVA7QUFDRCxLQU5ELENBTUUsT0FBT2pHLEdBQVAsRUFBWTtBQUVaQyxzQkFBSUUsS0FBSixDQUFXLG1CQUFrQkgsR0FBRyxDQUFDSSxPQUFRLEVBQXpDO0FBQ0Q7QUFDRjs7QUFJRCxRQUFNNkYsR0FBRyxHQUFHLE1BQU1wQixPQUFsQjs7QUFDQSxNQUFJTSxLQUFKLEVBQVc7QUFDVCxVQUFNQSxLQUFOO0FBQ0Q7O0FBQ0QsU0FBTyxLQUFLZ0Isb0JBQUwsQ0FBMEJGLEdBQTFCLENBQVA7QUFDRCxDQXZERDs7QUF5REE3RyxVQUFVLENBQUNnSCxZQUFYLEdBQTBCLGVBQWVBLFlBQWYsQ0FBNkJDLE9BQTdCLEVBQXNDO0FBQzlELE9BQUtoQyxNQUFMLENBQVlpQyw0QkFBWixHQUEyQyxJQUEzQzs7QUFDQSxNQUFJO0FBQ0YsVUFBTSxLQUFLaEUsV0FBTCxDQUFpQixnQkFBakIsRUFBbUMsQ0FBRSxXQUFVK0QsT0FBUSxLQUFwQixFQUEwQixJQUExQixDQUFuQyxDQUFOO0FBQ0QsR0FGRCxTQUVVO0FBQ1IsU0FBS2hDLE1BQUwsQ0FBWWlDLDRCQUFaLEdBQTJDLEtBQTNDO0FBQ0Q7QUFDRixDQVBEOztlQVVlbEgsVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlvc0NvbW1hbmRzIH0gZnJvbSAnZ3N0LWF0b20taW9zLWRyaXZlcic7XG5pbXBvcnQgeyByZXRyeUludGVydmFsLCB3YWl0Rm9yQ29uZGl0aW9uIH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IHsgdXRpbCwgdGltaW5nIH0gZnJvbSAnYXBwaXVtLXN1cHBvcnQnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcblxuY29uc3QgSVBIT05FX1RPUF9CQVJfSEVJR0hUID0gNzE7XG5jb25zdCBJUEhPTkVfU0NST0xMRURfVE9QX0JBUl9IRUlHSFQgPSA0MTtcbmNvbnN0IElQSE9ORV9YX1NDUk9MTEVEX09GRlNFVCA9IDU1O1xuY29uc3QgSVBIT05FX1hfTk9UQ0hfT0ZGU0VUX0lPUyA9IDI0O1xuY29uc3QgSVBIT05FX1hfTk9UQ0hfT0ZGU0VUX0lPU18xMyA9IDIwO1xuXG5jb25zdCBJUEhPTkVfTEFORFNDQVBFX1RPUF9CQVJfSEVJR0hUID0gNTE7XG5jb25zdCBJUEhPTkVfQk9UVE9NX0JBUl9PRkZTRVQgPSA0OTtcbmNvbnN0IFRBQl9CQVJfT0ZGU0VUID0gMzM7XG5jb25zdCBJUEhPTkVfV0VCX0NPT1JEX1NNQVJUX0FQUF9CQU5ORVJfT0ZGU0VUID0gODQ7XG5jb25zdCBJUEFEX1dFQl9DT09SRF9TTUFSVF9BUFBfQkFOTkVSX09GRlNFVCA9IDk1O1xuXG5jb25zdCBOT1RDSEVEX0RFVklDRV9TSVpFUyA9IFtcbiAge3c6IDExMjUsIGg6IDI0MzZ9LCAvLyAxMSBQcm8sIFgsIFhzXG4gIHt3OiA4MjgsIGg6IDE3OTJ9LCAvLyAxMSwgWHJcbiAge3c6IDEyNDIsIGg6IDI2ODh9LCAvLyAxMSBQcm8gTWF4LCBYcyBNYXhcbl07XG5cbmNvbnN0IEFUT01fV0FJVF9USU1FT1VUID0gMiAqIDYwMDAwO1xuY29uc3QgQVRPTV9XQUlUX0FMRVJUX1dBSVQgPSA0MDA7XG5cbmxldCBleHRlbnNpb25zID0ge307XG5cbk9iamVjdC5hc3NpZ24oZXh0ZW5zaW9ucywgaW9zQ29tbWFuZHMud2ViKTtcblxuXG5cbmV4dGVuc2lvbnMuZ2V0U2FmYXJpSXNJcGhvbmUgPSBfLm1lbW9pemUoYXN5bmMgZnVuY3Rpb24gZ2V0U2FmYXJpSXNJcGhvbmUgKCkge1xuICB0cnkge1xuICAgIGNvbnN0IHVzZXJBZ2VudCA9IGF3YWl0IHRoaXMuZXhlY3V0ZSgncmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQnKTtcbiAgICByZXR1cm4gdXNlckFnZW50LnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ2lwaG9uZScpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2cud2FybihgVW5hYmxlIHRvIGZpbmQgZGV2aWNlIHR5cGUgZnJvbSB1c2VyYWdlbnQuIEFzc3VtaW5nIGlQaG9uZWApO1xuICAgIGxvZy5kZWJ1ZyhgRXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59KTtcblxuZXh0ZW5zaW9ucy5nZXRTYWZhcmlEZXZpY2VTaXplID0gXy5tZW1vaXplKGFzeW5jIGZ1bmN0aW9uIGdldFNhZmFyaURldmljZVNpemUgKCkge1xuICBjb25zdCBzY3JpcHQgPSAncmV0dXJuIHtoZWlnaHQ6IHdpbmRvdy5zY3JlZW4uYXZhaWxIZWlnaHQgKiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywgd2lkdGg6IHdpbmRvdy5zY3JlZW4uYXZhaWxXaWR0aCAqIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvfTsnO1xuICBjb25zdCB7d2lkdGgsIGhlaWdodH0gPSBhd2FpdCB0aGlzLmV4ZWN1dGUoc2NyaXB0KTtcbiAgY29uc3QgW25vcm1IZWlnaHQsIG5vcm1XaWR0aF0gPSBoZWlnaHQgPiB3aWR0aCA/IFtoZWlnaHQsIHdpZHRoXSA6IFt3aWR0aCwgaGVpZ2h0XTtcbiAgcmV0dXJuIHtcbiAgICB3aWR0aDogbm9ybVdpZHRoLFxuICAgIGhlaWdodDogbm9ybUhlaWdodCxcbiAgfTtcbn0pO1xuXG5leHRlbnNpb25zLmdldFNhZmFyaUlzTm90Y2hlZCA9IF8ubWVtb2l6ZShhc3luYyBmdW5jdGlvbiBnZXRTYWZhcmlJc05vdGNoZWQgKCkge1xuICB0cnkge1xuICAgIGNvbnN0IHt3aWR0aCwgaGVpZ2h0fSA9IGF3YWl0IHRoaXMuZ2V0U2FmYXJpRGV2aWNlU2l6ZSgpO1xuICAgIGZvciAoY29uc3QgZGV2aWNlIG9mIE5PVENIRURfREVWSUNFX1NJWkVTKSB7XG4gICAgICBpZiAoZGV2aWNlLncgPT09IHdpZHRoICYmIGRldmljZS5oID09PSBoZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2cud2FybihgVW5hYmxlIHRvIGZpbmQgZGV2aWNlIHR5cGUgZnJvbSBkaW1lbnNpb25zLiBBc3N1bWluZyB0aGUgZGV2aWNlIGlzIG5vdCBub3RjaGVkYCk7XG4gICAgbG9nLmRlYnVnKGBFcnJvcjogJHtlcnIubWVzc2FnZX1gKTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59KTtcblxuZXh0ZW5zaW9ucy5nZXRFeHRyYVRyYW5zbGF0ZVdlYkNvb3Jkc09mZnNldCA9IGFzeW5jIGZ1bmN0aW9uIGdldEV4dHJhVHJhbnNsYXRlV2ViQ29vcmRzT2Zmc2V0ICh3dlBvcywgcmVhbERpbXMpIHtcbiAgbGV0IHRvcE9mZnNldCA9IDA7XG4gIGxldCBib3R0b21PZmZzZXQgPSAwO1xuXG4gIGNvbnN0IGlzSXBob25lID0gYXdhaXQgdGhpcy5nZXRTYWZhcmlJc0lwaG9uZSgpO1xuICBjb25zdCBpc05vdGNoZWQgPSBpc0lwaG9uZSAmJiBhd2FpdCB0aGlzLmdldFNhZmFyaUlzTm90Y2hlZCgpO1xuXG4gIGNvbnN0IG9yaWVudGF0aW9uID0gcmVhbERpbXMuaCA+IHJlYWxEaW1zLncgPyAnUE9SVFJBSVQnIDogJ0xBTkRTQ0FQRSc7XG5cbiAgY29uc3Qgbm90Y2hPZmZzZXQgPSBpc05vdGNoZWRcbiAgICA/IHV0aWwuY29tcGFyZVZlcnNpb25zKHRoaXMub3B0cy5wbGF0Zm9ybVZlcnNpb24sICc9JywgJzEzLjAnKVxuICAgICAgPyBJUEhPTkVfWF9OT1RDSF9PRkZTRVRfSU9TXzEzXG4gICAgICA6IElQSE9ORV9YX05PVENIX09GRlNFVF9JT1NcbiAgICA6IDA7XG5cbiAgY29uc3QgaXNTY3JvbGxlZCA9IGF3YWl0IHRoaXMuZXhlY3V0ZSgncmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPiAwJyk7XG4gIGlmIChpc1Njcm9sbGVkKSB7XG4gICAgdG9wT2Zmc2V0ID0gSVBIT05FX1NDUk9MTEVEX1RPUF9CQVJfSEVJR0hUICsgbm90Y2hPZmZzZXQ7XG5cbiAgICBpZiAoaXNOb3RjaGVkKSB7XG4gICAgICB0b3BPZmZzZXQgLT0gSVBIT05FX1hfU0NST0xMRURfT0ZGU0VUO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBpUGhvbmUgaXMgbGFuZHNjYXBlIHRoZW4gdGhlcmUgaXMgbm8gdG9wIGJhclxuICAgIGlmIChvcmllbnRhdGlvbiA9PT0gJ0xBTkRTQ0FQRScgJiYgaXNJcGhvbmUpIHtcbiAgICAgIHRvcE9mZnNldCA9IDA7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRvcE9mZnNldCA9IElQSE9ORV9UT1BfQkFSX0hFSUdIVCArIG5vdGNoT2Zmc2V0O1xuXG4gICAgaWYgKGlzSXBob25lKSB7XG4gICAgICBpZiAob3JpZW50YXRpb24gPT09ICdQT1JUUkFJVCcpIHtcbiAgICAgICAgLy8gVGhlIGJvdHRvbSBiYXIgaXMgb25seSB2aXNpYmxlIHdoZW4gcG9ydHJhaXRcbiAgICAgICAgYm90dG9tT2Zmc2V0ID0gSVBIT05FX0JPVFRPTV9CQVJfT0ZGU0VUO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdG9wT2Zmc2V0ID0gSVBIT05FX0xBTkRTQ0FQRV9UT1BfQkFSX0hFSUdIVDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob3JpZW50YXRpb24gPT09ICdMQU5EU0NBUEUnIHx8ICFpc0lwaG9uZSkge1xuICAgICAgLy8gVGFicyBvbmx5IGFwcGVhciBpZiB0aGUgZGV2aWNlIGlzIGxhbmRzY2FwZSBvciBpZiBpdCdzIGFuIGlQYWQgc28gd2Ugb25seSBjaGVjayB2aXNpYmlsaXR5IGluIHRoaXMgY2FzZVxuICAgICAgY29uc3QgdGFicyA9IGF3YWl0IHRoaXMuZmluZE5hdGl2ZUVsZW1lbnRPckVsZW1lbnRzKCctaW9zIHByZWRpY2F0ZSBzdHJpbmcnLCBgbmFtZSBMSUtFICcqLCBUYWInIEFORCB2aXNpYmxlID0gMWAsIHRydWUpO1xuICAgICAgaWYgKHRhYnMubGVuZ3RoID4gMCkge1xuICAgICAgICB0b3BPZmZzZXQgKz0gVEFCX0JBUl9PRkZTRVQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdG9wT2Zmc2V0ICs9IGF3YWl0IHRoaXMuZ2V0RXh0cmFOYXRpdmVXZWJUYXBPZmZzZXQoKTtcblxuICB3dlBvcy55ICs9IHRvcE9mZnNldDtcbiAgcmVhbERpbXMuaCAtPSAodG9wT2Zmc2V0ICsgYm90dG9tT2Zmc2V0KTtcbn07XG5cbmV4dGVuc2lvbnMuZ2V0RXh0cmFOYXRpdmVXZWJUYXBPZmZzZXQgPSBhc3luYyBmdW5jdGlvbiBnZXRFeHRyYU5hdGl2ZVdlYlRhcE9mZnNldCAoKSB7XG4gIGxldCBvZmZzZXQgPSAwO1xuXG4gIC8vIHRyeSB0byBzZWUgaWYgdGhlcmUgaXMgYW4gU21hcnQgQXBwIEJhbm5lclxuICBjb25zdCBiYW5uZXJzID0gYXdhaXQgdGhpcy5maW5kTmF0aXZlRWxlbWVudE9yRWxlbWVudHMoJ2FjY2Vzc2liaWxpdHkgaWQnLCAnQ2xvc2UgYXBwIGRvd25sb2FkIG9mZmVyJywgdHJ1ZSk7XG4gIGlmIChiYW5uZXJzLmxlbmd0aCA+IDApIHtcbiAgICBvZmZzZXQgKz0gYXdhaXQgdGhpcy5nZXRTYWZhcmlJc0lwaG9uZSgpID9cbiAgICAgIElQSE9ORV9XRUJfQ09PUkRfU01BUlRfQVBQX0JBTk5FUl9PRkZTRVQgOlxuICAgICAgSVBBRF9XRUJfQ09PUkRfU01BUlRfQVBQX0JBTk5FUl9PRkZTRVQ7XG4gIH1cblxuICBsb2cuZGVidWcoYEFkZGl0aW9uYWwgbmF0aXZlIHdlYiB0YXAgb2Zmc2V0IGNvbXB1dGVkOiAke29mZnNldH1gKTtcbiAgcmV0dXJuIG9mZnNldDtcbn07XG5cbmFzeW5jIGZ1bmN0aW9uIHRhcFdlYkVsZW1lbnROYXRpdmVseSAoZHJpdmVyLCBhdG9tc0VsZW1lbnQpIHtcbiAgLy8gdHJ5IHRvIGdldCB0aGUgdGV4dCBvZiB0aGUgZWxlbWVudCwgd2hpY2ggd2lsbCBiZSBhY2Nlc3NpYmxlIGluIHRoZVxuICAvLyBuYXRpdmUgY29udGV4dFxuICB0cnkge1xuICAgIGxldCB0ZXh0ID0gYXdhaXQgZHJpdmVyLmV4ZWN1dGVBdG9tKCdnZXRfdGV4dCcsIFthdG9tc0VsZW1lbnRdKTtcbiAgICBpZiAoIXRleHQpIHtcbiAgICAgIHRleHQgPSBhd2FpdCBkcml2ZXIuZXhlY3V0ZUF0b20oJ2dldF9hdHRyaWJ1dGVfdmFsdWUnLCBbYXRvbXNFbGVtZW50LCAndmFsdWUnXSk7XG4gICAgfVxuXG4gICAgaWYgKHRleHQpIHtcbiAgICAgIGNvbnN0IGVscyA9IGF3YWl0IGRyaXZlci5maW5kTmF0aXZlRWxlbWVudE9yRWxlbWVudHMoJ2FjY2Vzc2liaWxpdHkgaWQnLCB0ZXh0LCB0cnVlKTtcbiAgICAgIGlmIChlbHMubGVuZ3RoID09PSAxIHx8IGVscy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgY29uc3QgZWwgPSBlbHNbMF07XG4gICAgICAgIC8vIHVzZSB0YXAgYmVjYXVzZSBvbiBpT1MgMTEuMiBhbmQgYmVsb3cgYG5hdGl2ZUNsaWNrYCBjcmFzaGVzIFdEQVxuICAgICAgICBjb25zdCByZWN0ID0gYXdhaXQgZHJpdmVyLnByb3h5Q29tbWFuZChgL2VsZW1lbnQvJHt1dGlsLnVud3JhcEVsZW1lbnQoZWwpfS9yZWN0YCwgJ0dFVCcpO1xuICAgICAgICBpZiAoZWxzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgIGNvbnN0IGVsMiA9IGVsc1sxXTtcbiAgICAgICAgICBjb25zdCByZWN0MiA9IGF3YWl0IGRyaXZlci5wcm94eUNvbW1hbmQoYC9lbGVtZW50LyR7dXRpbC51bndyYXBFbGVtZW50KGVsMil9L3JlY3RgLCAnR0VUJyk7XG5cbiAgICAgICAgICBpZiAoKHJlY3QueCAhPT0gcmVjdDIueCB8fCByZWN0LnkgIT09IHJlY3QyLnkpIHx8XG4gICAgICAgICAgKHJlY3Qud2lkdGggIT09IHJlY3QyLndpZHRoIHx8IHJlY3QuaGVpZ2h0ICE9PSByZWN0Mi5oZWlnaHQpKSB7XG4gICAgICAgICAgICAvLyBUaGVzZSAyIG5hdGl2ZSBlbGVtZW50cyBhcmUgbm90IHJlZmVycmluZyB0byB0aGUgc2FtZSB3ZWIgZWxlbWVudFxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb29yZHMgPSB7XG4gICAgICAgICAgeDogTWF0aC5yb3VuZChyZWN0LnggKyByZWN0LndpZHRoIC8gMiksXG4gICAgICAgICAgeTogTWF0aC5yb3VuZChyZWN0LnkgKyByZWN0LmhlaWdodCAvIDIpLFxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCBkcml2ZXIuY2xpY2tDb29yZHMoY29vcmRzKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICAvLyBhbnkgZmFpbHVyZSBzaG91bGQgZmFsbCB0aHJvdWdoIGFuZCB0cmlnZ2VyIHRoZSBtb3JlIGVsYWJvcmF0ZVxuICAgIC8vIG1ldGhvZCBvZiBjbGlja2luZ1xuICAgIGxvZy53YXJuKGBFcnJvciBhdHRlbXB0aW5nIHRvIGNsaWNrOiAke2Vyci5tZXNzYWdlfWApO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXh0ZW5zaW9ucy5uYXRpdmVXZWJUYXAgPSBhc3luYyBmdW5jdGlvbiBuYXRpdmVXZWJUYXAgKGVsKSB7XG4gIGNvbnN0IGF0b21zRWxlbWVudCA9IHRoaXMudXNlQXRvbXNFbGVtZW50KGVsKTtcblxuICAvLyBpZiBzdHJpY3QgbmF0aXZlIHRhcCwgZG8gbm90IHRyeSB0byBkbyBpdCB3aXRoIFdEQSBkaXJlY3RseVxuICBpZiAoIShhd2FpdCB0aGlzLnNldHRpbmdzLmdldFNldHRpbmdzKCkpLm5hdGl2ZVdlYlRhcFN0cmljdCAmJiBhd2FpdCB0YXBXZWJFbGVtZW50TmF0aXZlbHkodGhpcywgYXRvbXNFbGVtZW50KSkge1xuICAgIHJldHVybjtcbiAgfVxuICBsb2cud2FybignVW5hYmxlIHRvIGRvIHNpbXBsZSBuYXRpdmUgd2ViIHRhcC4gQXR0ZW1wdGluZyB0byBjb252ZXJ0IGNvb3JkaW5hdGVzJyk7XG5cbiAgLy8gYGdldF90b3BfbGVmdF9jb29yZGluYXRlc2AgcmV0dXJucyB0aGUgd3JvbmcgdmFsdWUgc29tZXRpbWVzLFxuICAvLyB1bmxlc3Mgd2UgcHJlLWNhbGwgYm90aCBvZiB0aGVzZSBmdW5jdGlvbnMgYmVmb3JlIHRoZSBhY3R1YWwgY2FsbHNcbiAgYXdhaXQgdGhpcy5leGVjdXRlQXRvbSgnZ2V0X3NpemUnLCBbYXRvbXNFbGVtZW50XSk7XG4gIGF3YWl0IHRoaXMuZXhlY3V0ZUF0b20oJ2dldF90b3BfbGVmdF9jb29yZGluYXRlcycsIFthdG9tc0VsZW1lbnRdKTtcblxuICBjb25zdCB7d2lkdGgsIGhlaWdodH0gPSBhd2FpdCB0aGlzLmV4ZWN1dGVBdG9tKCdnZXRfc2l6ZScsIFthdG9tc0VsZW1lbnRdKTtcbiAgbGV0IHt4LCB5fSA9IGF3YWl0IHRoaXMuZXhlY3V0ZUF0b20oJ2dldF90b3BfbGVmdF9jb29yZGluYXRlcycsIFthdG9tc0VsZW1lbnRdKTtcbiAgeCArPSB3aWR0aCAvIDI7XG4gIHkgKz0gaGVpZ2h0IC8gMjtcblxuICB0aGlzLmN1cldlYkNvb3JkcyA9IHt4LCB5fTtcbiAgYXdhaXQgdGhpcy5jbGlja1dlYkNvb3JkcygpO1xufTtcblxuZXh0ZW5zaW9ucy5jbGlja0Nvb3JkcyA9IGFzeW5jIGZ1bmN0aW9uIGNsaWNrQ29vcmRzIChjb29yZHMpIHtcbiAgYXdhaXQgdGhpcy5wZXJmb3JtVG91Y2goW1xuICAgIHtcbiAgICAgIGFjdGlvbjogJ3RhcCcsXG4gICAgICBvcHRpb25zOiBjb29yZHMsXG4gICAgfSxcbiAgXSk7XG59O1xuXG5leHRlbnNpb25zLnRyYW5zbGF0ZVdlYkNvb3JkcyA9IGFzeW5jIGZ1bmN0aW9uIHRyYW5zbGF0ZVdlYkNvb3JkcyAoY29vcmRzKSB7XG4gIGxvZy5kZWJ1ZyhgVHJhbnNsYXRpbmcgY29vcmRpbmF0ZXMgKCR7SlNPTi5zdHJpbmdpZnkoY29vcmRzKX0pIHRvIHdlYiBjb29yZGluYXRlc2ApO1xuXG4gIC8vIGFic29sdXRpemUgd2ViIGNvb3Jkc1xuICBsZXQgd2VidmlldyA9IGF3YWl0IHJldHJ5SW50ZXJ2YWwoNSwgMTAwLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgd2Vidmlld3MgPSBhd2FpdCB0aGlzLmZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cygnY2xhc3MgbmFtZScsICdYQ1VJRWxlbWVudFR5cGVXZWJWaWV3JywgdHJ1ZSk7XG4gICAgaWYgKHdlYnZpZXdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyB3ZWJ2aWV3cyBmb3VuZC4gVW5hYmxlIHRvIHRyYW5zbGF0ZSB3ZWIgY29vcmRpbmF0ZXMgZm9yIG5hdGl2ZSB3ZWIgdGFwYCk7XG4gICAgfVxuICAgIHJldHVybiB3ZWJ2aWV3c1swXTtcbiAgfSk7XG4gIHdlYnZpZXcgPSB1dGlsLnVud3JhcEVsZW1lbnQod2Vidmlldyk7XG5cbiAgY29uc3QgcmVjdCA9IGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvZWxlbWVudC8ke3dlYnZpZXd9L3JlY3RgLCAnR0VUJyk7XG4gIGNvbnN0IHd2UG9zID0ge3g6IHJlY3QueCwgeTogcmVjdC55fTtcbiAgY29uc3QgcmVhbERpbXMgPSB7dzogcmVjdC53aWR0aCwgaDogcmVjdC5oZWlnaHR9O1xuXG4gIGNvbnN0IGNtZCA9ICcoZnVuY3Rpb24gKCkgeyByZXR1cm4ge3c6IHdpbmRvdy5pbm5lcldpZHRoLCBoOiB3aW5kb3cuaW5uZXJIZWlnaHR9OyB9KSgpJztcbiAgY29uc3Qgd3ZEaW1zID0gYXdhaXQgdGhpcy5yZW1vdGUuZXhlY3V0ZShjbWQpO1xuXG4gIGF3YWl0IHRoaXMuZ2V0RXh0cmFUcmFuc2xhdGVXZWJDb29yZHNPZmZzZXQod3ZQb3MsIHJlYWxEaW1zKTtcblxuICBpZiAod3ZEaW1zICYmIHJlYWxEaW1zICYmIHd2UG9zKSB7XG4gICAgbGV0IHhSYXRpbyA9IHJlYWxEaW1zLncgLyB3dkRpbXMudztcbiAgICBsZXQgeVJhdGlvID0gcmVhbERpbXMuaCAvIHd2RGltcy5oO1xuICAgIGxldCBuZXdDb29yZHMgPSB7XG4gICAgICB4OiB3dlBvcy54ICsgTWF0aC5yb3VuZCh4UmF0aW8gKiBjb29yZHMueCksXG4gICAgICB5OiB3dlBvcy55ICsgTWF0aC5yb3VuZCh5UmF0aW8gKiBjb29yZHMueSksXG4gICAgfTtcblxuICAgIC8vIGFkZGl0aW9uYWwgbG9nZ2luZyBmb3IgY29vcmRpbmF0ZXMsIHNpbmNlIGl0IGlzIHNvbWV0aW1lcyBicm9rZW5cbiAgICAvLyAgIHNlZSBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvOTE1OVxuICAgIGxvZy5kZWJ1ZyhgQ29udmVydGVkIGNvb3JkaW5hdGVzOiAke0pTT04uc3RyaW5naWZ5KG5ld0Nvb3Jkcyl9YCk7XG4gICAgbG9nLmRlYnVnKGAgICAgcmVjdDogJHtKU09OLnN0cmluZ2lmeShyZWN0KX1gKTtcbiAgICBsb2cuZGVidWcoYCAgICB3dlBvczogJHtKU09OLnN0cmluZ2lmeSh3dlBvcyl9YCk7XG4gICAgbG9nLmRlYnVnKGAgICAgcmVhbERpbXM6ICR7SlNPTi5zdHJpbmdpZnkocmVhbERpbXMpfWApO1xuICAgIGxvZy5kZWJ1ZyhgICAgIHd2RGltczogJHtKU09OLnN0cmluZ2lmeSh3dkRpbXMpfWApO1xuICAgIGxvZy5kZWJ1ZyhgICAgIHhSYXRpbzogJHtKU09OLnN0cmluZ2lmeSh4UmF0aW8pfWApO1xuICAgIGxvZy5kZWJ1ZyhgICAgIHlSYXRpbzogJHtKU09OLnN0cmluZ2lmeSh5UmF0aW8pfWApO1xuXG4gICAgbG9nLmRlYnVnKGBDb252ZXJ0ZWQgd2ViIGNvb3JkcyAke0pTT04uc3RyaW5naWZ5KGNvb3Jkcyl9IGAgK1xuICAgICAgICAgICAgICBgaW50byByZWFsIGNvb3JkcyAke0pTT04uc3RyaW5naWZ5KG5ld0Nvb3Jkcyl9YCk7XG4gICAgcmV0dXJuIG5ld0Nvb3JkcztcbiAgfVxufTtcblxuZXh0ZW5zaW9ucy5jaGVja0ZvckFsZXJ0ID0gYXN5bmMgZnVuY3Rpb24gY2hlY2tGb3JBbGVydCAoKSB7XG4gIHJldHVybiBfLmlzU3RyaW5nKGF3YWl0IHRoaXMuZ2V0QWxlcnRUZXh0KCkpO1xufTtcblxuZXh0ZW5zaW9ucy53YWl0Rm9yQXRvbSA9IGFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JBdG9tIChwcm9taXNlKSB7XG4gIGNvbnN0IHRpbWVyID0gbmV3IHRpbWluZy5UaW1lcigpLnN0YXJ0KCk7XG5cbiAgLy8gbmVlZCB0byBjaGVjayBmb3IgYWxlcnQgd2hpbGUgdGhlIGF0b20gaXMgYmVpbmcgZXhlY3V0ZWQuXG4gIC8vIHNvIG5vdGlmeSBvdXJzZWx2ZXMgd2hlbiBpdCBoYXBwZW5zXG4gIGxldCBkb25lID0gZmFsc2U7XG4gIGxldCBlcnJvciA9IG51bGw7XG4gIHByb21pc2UgPSBCLnJlc29sdmUocHJvbWlzZSkgLy8gZXNsaW50LWRpc2FibGUtbGluZSBwcm9taXNlL2NhdGNoLW9yLXJldHVyblxuICAgIC50aW1lb3V0KEFUT01fV0FJVF9USU1FT1VUKVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJvbWlzZS9wcmVmZXItYXdhaXQtdG8tY2FsbGJhY2tzXG4gICAgICBsb2cuZGVidWcoYEVycm9yIHJlY2VpdmVkIHdoaWxlIGV4ZWN1dGluZyBhdG9tOiAke2Vyci5tZXNzYWdlfWApO1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEIuVGltZW91dEVycm9yKSB7XG4gICAgICAgIGVyciA9IG5ldyBFcnJvcihgRGlkIG5vdCBnZXQgYW55IHJlc3BvbnNlIGZvciBhdG9tIGV4ZWN1dGlvbiBhZnRlciAke3RpbWVyLmdldER1cmF0aW9uKCkuYXNNaWxsaVNlY29uZHMudG9GaXhlZCgwKX1tc2ApO1xuICAgICAgfVxuICAgICAgLy8gc2F2ZSBhbmQgY2hlY2sgbGF0ZXIsIG9yIGFuIFVuaGFuZGxlZCByZWplY3Rpb24gd2lsbCBiZSByZXBvcnRlZFxuICAgICAgZXJyb3IgPSBlcnI7XG4gICAgfSlcbiAgICAuZmluYWxseShmdW5jdGlvbiAoKSB7XG4gICAgICBkb25lID0gdHJ1ZTtcbiAgICB9KTtcblxuICAvLyB0cnkgdGVuIHRpbWVzIHRvIGNoZWNrIGFsZXJ0XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgMTA7IGkrKykge1xuICAgIC8vIHBhdXNlLCBvciB0aGUgYXRvbSBwcm9taXNlIGlzIHJlc29sdmVkXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oKCkgPT4gZG9uZSwge1xuICAgICAgICB3YWl0TXM6IEFUT01fV0FJVF9BTEVSVF9XQUlULFxuICAgICAgICBpbnRlcnZhbE1zOiAwLCAvLyBqdXN0IGZvciB0aGUgcGF1c2UgaW4gZXhlY3V0aW9uXG4gICAgICB9KTtcbiAgICAgIC8vIGBkb25lYCBiZWNhbWUgdHJ1ZSwgc28gYXRvbSBwcm9taXNlIGlzIHJlc29sdmVkXG4gICAgICBicmVhaztcbiAgICB9IGNhdGNoIChpZ24pIHtcbiAgICAgIC8vIGBkb25lYCBuZXZlciBiZWNhbWUgdHJ1ZSwgc28gbW92ZSBvbiB0byB0cnlpbmcgdG8gZmluZCBhbiBhbGVydFxuICAgIH1cblxuICAgIC8vIGNoZWNrIGlmIHRoZXJlIGlzIGFuIGFsZXJ0LCBvciB0aGUgYXRvbSBwcm9taXNlIGlzIHJlc29sdmVkXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IEIuYW55KFt0aGlzLmNoZWNrRm9yQWxlcnQoKSwgcHJvbWlzZV0pO1xuICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMucGFyc2VFeGVjdXRlUmVzcG9uc2UocmVzKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIG5vIGFsZXJ0IGZvdW5kLCBzbyBwYXNzIHRocm91Z2hcbiAgICAgIGxvZy5kZWJ1ZyhgTm8gYWxlcnQgZm91bmQ6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLy8gYXQgdGhpcyBwb2ludCwgYWxsIHRoYXQgY2FuIGJlIGRvbmUgaXMgd2FpdCBmb3IgdGhlIGF0b20gcHJvbWlzZSB0byBiZVxuICAvLyByZXNvbHZlZFxuICBjb25zdCByZXMgPSBhd2FpdCBwcm9taXNlO1xuICBpZiAoZXJyb3IpIHtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuICByZXR1cm4gdGhpcy5wYXJzZUV4ZWN1dGVSZXNwb25zZShyZXMpO1xufTtcblxuZXh0ZW5zaW9ucy5tb2JpbGVXZWJOYXYgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVXZWJOYXYgKG5hdlR5cGUpIHtcbiAgdGhpcy5yZW1vdGUuYWxsb3dOYXZpZ2F0aW9uV2l0aG91dFJlbG9hZCA9IHRydWU7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5leGVjdXRlQXRvbSgnZXhlY3V0ZV9zY3JpcHQnLCBbYGhpc3RvcnkuJHtuYXZUeXBlfSgpO2AsIG51bGxdKTtcbiAgfSBmaW5hbGx5IHtcbiAgICB0aGlzLnJlbW90ZS5hbGxvd05hdmlnYXRpb25XaXRob3V0UmVsb2FkID0gZmFsc2U7XG4gIH1cbn07XG5cblxuZXhwb3J0IGRlZmF1bHQgZXh0ZW5zaW9ucztcbiJdLCJmaWxlIjoibGliL2NvbW1hbmRzL3dlYi5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLiJ9