testcafe-browser-provider-browserstack
Version:
Browserstack TestCafe browser provider plugin.
246 lines • 40.1 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 url_1 = require("url");
const pinkie_1 = __importDefault(require("pinkie"));
const util_1 = require("util");
const desired_capabilities_1 = __importDefault(require("desired-capabilities"));
const lodash_1 = require("lodash");
const connector_1 = __importDefault(require("./connector"));
const js_testing_1 = __importDefault(require("./backends/js-testing"));
const automate_1 = __importDefault(require("./backends/automate"));
const browser_proxy_1 = __importDefault(require("./browser-proxy"));
const is_env_var_true_1 = __importDefault(require("./utils/is-env-var-true"));
const mime_db_1 = __importDefault(require("mime-db"));
const ANDROID_PROXY_RESPONSE_DELAY = 500;
const isAutomateEnabled = () => (0, is_env_var_true_1.default)('BROWSERSTACK_USE_AUTOMATE');
const isLocalEnabled = () => !!process.env.BROWSERSTACK_LOCAL_IDENTIFIER || !(0, is_env_var_true_1.default)('BROWSERSTACK_NO_LOCAL');
function getMimeTypes() {
const mimeTypes = Object.keys(mime_db_1.default);
return mimeTypes.filter(mimeType => {
const { extensions } = mime_db_1.default[mimeType];
return extensions && extensions.length;
}).join(',');
}
module.exports = {
// Multiple browsers support
isMultiBrowser: true,
backend: null,
connectorPromise: pinkie_1.default.resolve(null),
browserProxyPromise: pinkie_1.default.resolve(null),
workers: {},
platformsInfo: [],
browserNames: [],
_createConnector() {
this.connectorPromise = this.connectorPromise
.then(async (connector) => {
if (!connector) {
connector = new connector_1.default(process.env['BROWSERSTACK_ACCESS_KEY']);
await connector.create();
}
return connector;
});
return this.connectorPromise;
},
_disposeConnector() {
this.connectorPromise = this.connectorPromise
.then(async (connector) => {
if (connector)
await connector.destroy();
return null;
});
return this.connectorPromise;
},
_getBrowserProxy(protocol, host, port) {
this.browserProxyPromise = this.browserProxyPromise
.then(async (browserProxy) => {
if (!browserProxy) {
browserProxy = new browser_proxy_1.default(host, port, { targetProtocol: protocol, responseDelay: ANDROID_PROXY_RESPONSE_DELAY });
await browserProxy.init();
}
return browserProxy;
});
return this.browserProxyPromise;
},
_disposeBrowserProxy() {
this.browserProxyPromise = this.browserProxyPromise
.then(async (browserProxy) => {
if (browserProxy)
await browserProxy.dispose();
return null;
});
return this.browserProxyPromise;
},
async _getDeviceList() {
this.platformsInfo = await this.backend.getBrowsersList();
},
_createQuery(capabilities) {
var { browserName, browserVersion, platform } = (0, desired_capabilities_1.default)(capabilities)[0];
browserName = browserName.toLowerCase();
if (browserName === 'internet explorer')
browserName = 'ie';
return {
name: browserName,
version: browserVersion.toLowerCase(),
platform: platform.toLowerCase()
};
},
_generateBasicCapabilities(browserName) {
return this._filterPlatformInfo(this._createQuery(browserName))[0];
},
_getCapabilitiesFromEnvironment() {
// NOTE: This function maps env vars to browserstack capabilities.
// For the full list of capabilities, see https://www.browserstack.com/automate/capabilities
return {
'build': process.env['BROWSERSTACK_BUILD_ID'] || process.env['BROWSERSTACK_BUILD_NAME'],
'project': process.env['BROWSERSTACK_PROJECT_NAME'],
'resolution': process.env['BROWSERSTACK_DISPLAY_RESOLUTION'],
'name': process.env['BROWSERSTACK_TEST_RUN_NAME'],
'browserstack.debug': process.env['BROWSERSTACK_DEBUG'],
'browserstack.console': process.env['BROWSERSTACK_CONSOLE'],
'browserstack.networkLogs': process.env['BROWSERSTACK_NETWORK_LOGS'],
'browserstack.video': process.env['BROWSERSTACK_VIDEO'],
'browserstack.timezone': process.env['BROWSERSTACK_TIMEZONE'],
'browserstack.geoLocation': process.env['BROWSERSTACK_GEO_LOCATION'],
'browserstack.customNetwork': process.env['BROWSERSTACK_CUSTOM_NETWORK'],
'browserstack.networkProfile': process.env['BROWSERSTACK_NETWORK_PROFILE'],
'acceptSslCerts': process.env['BROWSERSTACK_ACCEPT_SSL_CERTS']
};
},
_getCapabilitiesFromConfig() {
const configPath = process.env.BROWSERSTACK_CAPABILITIES_CONFIG_PATH;
if (!configPath)
return {};
return require(configPath);
},
_getAdditionalCapabilities() {
const capabilitiesFromEnvironment = (0, lodash_1.pickBy)(this._getCapabilitiesFromEnvironment(), value => value !== void 0);
return Object.assign(Object.assign({}, this._getCapabilitiesFromConfig()), capabilitiesFromEnvironment);
},
_filterPlatformInfo(query) {
let filteredPlatformInfo = this.platformsInfo
.filter(info => {
var browserNameMatched = info['browser'] && info['browser'].toLowerCase() === query.name;
var deviceNameMatched = info['device'] && info['device'].toLowerCase() === query.name;
var browserVersionMatched = info['browser_version'] && String(info['browser_version']) === String(query.version);
var platformVersionMatched = info['os_version'] && String(info['os_version']).toLowerCase() === String(query.version);
var platformNameMatched = info['os'].toLowerCase() === query.platform ||
`${info['os'].toLowerCase()} ${info['os_version'].toLowerCase()}` === query.platform;
var isAnyVersion = query.version === 'any';
var isAnyPlatform = query.platform === 'any';
var desktopBrowserMatched = browserNameMatched &&
(browserVersionMatched || isAnyVersion) &&
(platformNameMatched || isAnyPlatform);
var mobileBrowserMatched = deviceNameMatched &&
(platformVersionMatched || isAnyVersion);
return desktopBrowserMatched || mobileBrowserMatched;
});
if (filteredPlatformInfo.length && query.version === 'any') {
filteredPlatformInfo = filteredPlatformInfo.filter(info => {
const browserVersion = info['browser_version'] || '';
return !browserVersion.includes('beta');
});
}
return filteredPlatformInfo;
},
_generateBrowserNames() {
this.browserNames = this.platformsInfo
.map(info => {
var isDesktop = !info['device'];
var name = isDesktop ? info['browser'] : info['device'];
var version = isDesktop ? info['browser_version'] : info['os_version'];
var platform = isDesktop ? `${info['os']} ${info['os_version']}` : '';
return `${name}@${version}${platform ? ':' + platform : ''}`;
});
},
_prepareChromeCapabilities(capabilities) {
if (process.env['BROWSERSTACK_CHROME_ARGS'] && process.env['BROWSERSTACK_CHROME_ARGS'].length > 0)
capabilities.chromeOptions = { args: [process.env['BROWSERSTACK_CHROME_ARGS']] };
},
async _prepareFirefoxCapabilities(capabilities) {
if (!process.env['BROWSERSTACK_USE_AUTOMATE'])
return;
const FirefoxProfile = require('firefox-profile');
const profile = new FirefoxProfile();
profile.defaultPreferences = {};
profile.setPreference('browser.helperApps.neverAsk.saveToDisk', getMimeTypes());
profile.updatePreferences();
capabilities['firefox_profile'] = await (0, util_1.promisify)(profile.encoded).bind(profile)();
},
async _encodeFirefoxProfile(profile) {
return new pinkie_1.default((resolve, reject) => {
profile.encoded(function (err, encodedProfile) {
if (err)
reject(err);
else
resolve(encodedProfile);
});
});
},
// Required - must be implemented
// Browser control
async openBrowser(id, pageUrl, browserName) {
const capabilities = Object.assign(Object.assign({}, this._generateBasicCapabilities(browserName)), this._getAdditionalCapabilities());
capabilities.local = isLocalEnabled();
// Give preference to the already running local identifier
capabilities.localIdentifier = process.env.BROWSERSTACK_LOCAL_IDENTIFIER;
if (capabilities.local && !capabilities.localIdentifier) {
const connector = await this._createConnector();
capabilities.localIdentifier = connector.connectorInstance.localIdentifierFlag;
}
if (capabilities.os.toLowerCase() === 'android') {
const parsedPageUrl = (0, url_1.parse)(pageUrl);
const browserProxy = await this._getBrowserProxy(parsedPageUrl.protocol, parsedPageUrl.hostname, parsedPageUrl.port);
pageUrl = 'http://' + browserProxy.targetHost + ':' + browserProxy.proxyPort + parsedPageUrl.path;
}
if (!capabilities.name)
capabilities.name = `TestCafe test run ${id}`;
if (browserName.includes('chrome'))
this._prepareChromeCapabilities(capabilities);
if (browserName.includes('firefox'))
await this._prepareFirefoxCapabilities(capabilities);
await this.backend.openBrowser(id, pageUrl, capabilities);
this.setUserAgentMetaInfo(id, this.backend.getSessionUrl(id));
},
async closeBrowser(id) {
await this.backend.closeBrowser(id);
},
// Optional - implement methods you need, remove other methods
// Initialization
async init() {
var reportWarning = (...args) => this.reportWarning(...args);
this.backend = isAutomateEnabled() ? new automate_1.default(reportWarning) : new js_testing_1.default(reportWarning);
await this._getDeviceList();
this._generateBrowserNames();
},
async dispose() {
await this._disposeConnector();
await this._disposeBrowserProxy();
},
// Browser names handling
async getBrowserList() {
return this.browserNames;
},
async isValidBrowserName(browserName) {
return (0, desired_capabilities_1.default)(browserName).length === 1 && !!this._filterPlatformInfo(this._createQuery(browserName)).length;
},
// Extra methods
async resizeWindow(id, width, height, currentWidth, currentHeight) {
await this.backend.resizeWindow(id, width, height, currentWidth, currentHeight);
},
async maximizeWindow(id) {
await this.backend.maximizeWindow(id);
},
async takeScreenshot(id, screenshotPath) {
await this.backend.takeScreenshot(id, screenshotPath);
},
async reportJobResult(id, jobResult, jobData) {
await this.backend.reportJobResult(id, jobResult, jobData, this.JOB_RESULT);
},
async getOSInfo(id) {
return await this.backend.getOSInfo(id);
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBd0M7QUFDeEMsb0RBQTZCO0FBQzdCLCtCQUFpQztBQUNqQyxnRkFBcUQ7QUFDckQsbUNBQWdDO0FBQ2hDLDREQUFnRDtBQUNoRCx1RUFBcUQ7QUFDckQsbUVBQWtEO0FBQ2xELG9FQUEyQztBQUMzQyw4RUFBbUQ7QUFDbkQsc0RBQXlCO0FBRXpCLE1BQU0sNEJBQTRCLEdBQUcsR0FBRyxDQUFDO0FBRXpDLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBQSx5QkFBWSxFQUFDLDJCQUEyQixDQUFDLENBQUM7QUFDMUUsTUFBTSxjQUFjLEdBQU0sR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsNkJBQTZCLElBQUksQ0FBQyxJQUFBLHlCQUFZLEVBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUV0SCxTQUFTLFlBQVk7SUFDakIsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBRSxDQUFDLENBQUM7SUFFbEMsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1FBQy9CLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxpQkFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXBDLE9BQU8sVUFBVSxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDM0MsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxNQUFNLENBQUMsT0FBTyxHQUFHO0lBQ2IsNEJBQTRCO0lBQzVCLGNBQWMsRUFBRSxJQUFJO0lBRXBCLE9BQU8sRUFBRSxJQUFJO0lBRWIsZ0JBQWdCLEVBQUssZ0JBQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQzFDLG1CQUFtQixFQUFFLGdCQUFPLENBQUMsT0FB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QUFDO0lBR0QsS0FBSyxDQUFDLGNBQWMsQ0FBRSxFQUFFLEVBQUUsY0FBYztRQUNwQyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRUQsS0FBSyxDQUFDLGVBQWUsQ0FBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLE9BQU87UUFDekMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUVELEtBQUssQ0FBQyxTQUFTLENBQUUsRUFBRTtRQUNmLE9BQU8sTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1QyxDQUFDO0NBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHBhcnNlIGFzIHBhcnNlVXJsIH0gZnJvbSAndXJsJztcbmltcG9ydCBQcm9taXNlIGZyb20gJ3BpbmtpZSc7XG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJztcbmltcG9ydCBwYXJzZUNhcGFiaWxpdGllcyBmcm9tICdkZXNpcmVkLWNhcGFiaWxpdGllcyc7XG5pbXBvcnQgeyBwaWNrQnkgfSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IEJyb3dzZXJzdGFja0Nvbm5lY3RvciBmcm9tICcuL2Nvbm5lY3Rvcic7XG5pbXBvcnQgSlNUZXN0aW5nQmFja2VuZCBmcm9tICcuL2JhY2tlbmRzL2pzLXRlc3RpbmcnO1xuaW1wb3J0IEF1dG9tYXRlQmFja2VuZCBmcm9tICcuL2JhY2tlbmRzL2F1dG9tYXRlJztcbmltcG9ydCBCcm93c2VyUHJveHkgZnJvbSAnLi9icm93c2VyLXByb3h5JztcbmltcG9ydCBpc0VudlZhclRydWUgZnJvbSAnLi91dGlscy9pcy1lbnYtdmFyLXRydWUnO1xuaW1wb3J0IGRiIGZyb20gJ21pbWUtZGInO1xuXG5jb25zdCBBTkRST0lEX1BST1hZX1JFU1BPTlNFX0RFTEFZID0gNTAwO1xuXG5jb25zdCBpc0F1dG9tYXRlRW5hYmxlZCA9ICgpID0+IGlzRW52VmFyVHJ1ZSgnQlJPV1NFUlNUQUNLX1VTRV9BVVRPTUFURScpO1xuY29uc3QgaXNMb2NhbEVuYWJsZWQgICAgPSAoKSA9PiAhIXByb2Nlc3MuZW52LkJST1dTRVJTVEFDS19MT0NBTF9JREVOVElGSUVSIHx8ICFpc0VudlZhclRydWUoJ0JST1dTRVJTVEFDS19OT19MT0NBTCcpO1xuXG5mdW5jdGlvbiBnZXRNaW1lVHlwZXMgKCkge1xuICAgIGNvbnN0IG1pbWVUeXBlcyA9IE9iamVjdC5rZXlzKGRiKTtcblxuICAgIHJldHVybiBtaW1lVHlwZXMuZmlsdGVyKG1pbWVUeXBlID0+IHtcbiAgICAgICAgY29uc3QgeyBleHRlbnNpb25zIH0gPSBkYlttaW1lVHlwZV07XG5cbiAgICAgICAgcmV0dXJuIGV4dGVuc2lvbnMgJiYgZXh0ZW5zaW9ucy5sZW5ndGg7XG4gICAgfSkuam9pbignLCcpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBNdWx0aXBsZSBicm93c2VycyBzdXBwb3J0XG4gICAgaXNNdWx0aUJyb3dzZXI6IHRydWUsXG5cbiAgICBiYWNrZW5kOiBudWxsLFxuXG4gICAgY29ubmVjdG9yUHJvbWlzZTogICAgUHJvbWlzZS5yZXNvbHZlKG51bGwpLFxuICAgIGJyb3dzZXJQcm94eVByb21pc2U6IFByb21pc2UucmVzb2x2ZShudWxsKSxcblxuICAgIHdvcmtlcnM6ICAgICAgIHt9LFxuICAgIHBsYXRmb3Jtc0luZm86IFtdLFxuICAgIGJyb3dzZXJOYW1lczogIFtdLFxuXG4gICAgX2NyZWF0ZUNvbm5lY3RvciAoKSB7XG4gICAgICAgIHRoaXMuY29ubmVjdG9yUHJvbWlzZSA9IHRoaXMuY29ubmVjdG9yUHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgY29ubmVjdG9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbm5lY3Rvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0b3IgPSBuZXcgQnJvd3NlcnN0YWNrQ29ubmVjdG9yKHByb2Nlc3MuZW52WydCUk9XU0VSU1RBQ0tfQUNDRVNTX0tFWSddKTtcblxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBjb25uZWN0b3IuY3JlYXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbm5lY3RvcjtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3RvclByb21pc2U7XG4gICAgfSxcblxuICAgIF9kaXNwb3NlQ29ubmVjdG9yICgpIHtcbiAgICAgICAgdGhpcy5jb25uZWN0b3JQcm9taXNlID0gdGhpcy5jb25uZWN0b3JQcm9taXNlXG4gICAgICAgICAgICAudGhlbihhc3luYyBjb25uZWN0b3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb25uZWN0b3IpXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGNvbm5lY3Rvci5kZXN0cm95KCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3RvclByb21pc2U7XG4gICAgfSxcblxuICAgIF9nZXRCcm93c2VyUHJveHkgKHByb3RvY29sLCBob3N0LCBwb3J0KSB7XG4gICAgICAgIHRoaXMuYnJvd3NlclByb3h5UHJvbWlzZSA9IHRoaXMuYnJvd3NlclByb3h5UHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgYnJvd3NlclByb3h5ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWJyb3dzZXJQcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBicm93c2VyUHJveHkgPSBuZXcgQnJvd3NlclByb3h5KGhvc3QsIHBvcnQsIHsgdGFyZ2V0UHJvdG9jb2w6IHByb3RvY29sLCByZXNwb25zZURlbGF5OiBBTkRST0lEX1BST1hZX1JFU1BPTlNFX0RFTEFZIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQcm94eS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJyb3dzZXJQcm94eTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmJyb3dzZXJQcm94eVByb21pc2U7XG4gICAgfSxcblxuICAgIF9kaXNwb3NlQnJvd3NlclByb3h5ICgpIHtcbiAgICAgICAgdGhpcy5icm93c2VyUHJveHlQcm9taXNlID0gdGhpcy5icm93c2VyUHJveHlQcm9taXNlXG4gICAgICAgICAgICAudGhlbihhc3luYyBicm93c2VyUHJveHkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChicm93c2VyUHJveHkpXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJyb3dzZXJQcm94eS5kaXNwb3NlKCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmJyb3dzZXJQcm94eVByb21pc2U7XG4gICAgfSxcblxuICAgIGFzeW5jIF9nZXREZXZpY2VMaXN0ICgpIHtcbiAgICAgICAgdGhpcy5wbGF0Zm9ybXNJbmZvID0gYXdhaXQgdGhpcy5iYWNrZW5kLmdldEJyb3dzZXJzTGlzdCgpO1xuICAgIH0sXG5cbiAgICBfY3JlYXRlUXVlcnkgKGNhcGFiaWxpdGllcykge1xuICAgICAgICB2YXIgeyBicm93c2VyTmFtZSwgYnJvd3NlclZlcnNpb24sIHBsYXRmb3JtIH0gPSBwYXJzZUNhcGFiaWxpdGllcyhjYXBhYmlsaXRpZXMpWzBdO1xuXG4gICAgICAgIGJyb3dzZXJOYW1lID0gYnJvd3Nlck5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgICBpZiAoYnJvd3Nlck5hbWUgPT09ICdpbnRlcm5ldCBleHBsb3JlcicpXG4gICAgICAgICAgICBicm93c2VyTmFtZSA9ICdpZSc7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5hbWU6ICAgICBicm93c2VyTmFtZSxcbiAgICAgICAgICAgIHZlcnNpb246ICBicm93c2VyVmVyc2lvbi50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgICAgcGxhdGZvcm06IHBsYXRmb3JtLnRvTG93ZXJDYXNlKClcbiAgICAgICAgfTtcbiAgICB9LFxuXG4gICAgX2dlbmVyYXRlQmFzaWNDYXBhYmlsaXRpZXMgKGJyb3dzZXJOYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9maWx0ZXJQbGF0Zm9ybUluZm8odGhpcy5fY3JlYXRlUXVlcnkoYnJvd3Nlck5hbWUpKVswXTtcbiAgICB9LFxuXG4gICAgX2dldENhcGFiaWxpdGllc0Zyb21FbnZpcm9ubWVudCAoKSB7XG4gICAgICAgIC8vIE5PVEU6IFRoaXMgZnVuY3Rpb24gbWFwcyBlbnYgdmFycyB0byBicm93c2Vyc3RhY2sgY2FwYWJpbGl0aWVzLlxuICAgICAgICAvLyBGb3IgdGhlIGZ1bGwgbGlzdCBvZiBjYXBhYmlsaXRpZXMsIHNlZSBodHRwczovL3d3dy5icm93c2Vyc3RhY2suY29tL2F1dG9tYXRlL2NhcGFiaWxpdGllc1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnYnVpbGQnOiAgICAgICAgICAgICAgICAgICAgICAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19CVUlMRF9JRCddIHx8IHByb2Nlc3MuZW52WydCUk9XU0VSU1RBQ0tfQlVJTERfTkFNRSddLFxuICAgICAgICAgICAgJ3Byb2plY3QnOiAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3MuZW52WydCUk9XU0VSU1RBQ0tfUFJPSkVDVF9OQU1FJ10sXG4gICAgICAgICAgICAncmVzb2x1dGlvbic6ICAgICAgICAgICAgICAgICAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19ESVNQTEFZX1JFU09MVVRJT04nXSxcbiAgICAgICAgICAgICduYW1lJzogICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmVudlsnQlJPV1NFUlNUQUNLX1RFU1RfUlVOX05BTUUnXSxcbiAgICAgICAgICAgICdicm93c2Vyc3RhY2suZGVidWcnOiAgICAgICAgICBwcm9jZXNzLmVudlsnQlJPV1NFUlNUQUNLX0RFQlVHJ10sXG4gICAgICAgICAgICAnYnJvd3NlcnN0YWNrLmNvbnNvbGUnOiAgICAgICAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19DT05TT0xFJ10sXG4gICAgICAgICAgICAnYnJvd3NlcnN0YWNrLm5ldHdvcmtMb2dzJzogICAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19ORVRXT1JLX0xPR1MnXSxcbiAgICAgICAgICAgICdicm93c2Vyc3RhY2sudmlkZW8nOiAgICAgICAgICBwcm9jZXNzLmVudlsnQlJPV1NFUlNUQUNLX1ZJREVPJ10sXG4gICAgICAgICAgICAnYnJvd3NlcnN0YWNrLnRpbWV6b25lJzogICAgICAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19USU1FWk9ORSddLFxuICAgICAgICAgICAgJ2Jyb3dzZXJzdGFjay5nZW9Mb2NhdGlvbic6ICAgIHByb2Nlc3MuZW52WydCUk9XU0VSU1RBQ0tfR0VPX0xPQ0FUSU9OJ10sXG4gICAgICAgICAgICAnYnJvd3NlcnN0YWNrLmN1c3RvbU5ldHdvcmsnOiAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19DVVNUT01fTkVUV09SSyddLFxuICAgICAgICAgICAgJ2Jyb3dzZXJzdGFjay5uZXR3b3JrUHJvZmlsZSc6IHByb2Nlc3MuZW52WydCUk9XU0VSU1RBQ0tfTkVUV09SS19QUk9GSUxFJ10sXG4gICAgICAgICAgICAnYWNjZXB0U3NsQ2VydHMnOiAgICAgICAgICAgICAgcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19BQ0NFUFRfU1NMX0NFUlRTJ11cbiAgICAgICAgfTtcbiAgICB9LFxuXG4gICAgX2dldENhcGFiaWxpdGllc0Zyb21Db25maWcgKCkge1xuICAgICAgICBjb25zdCBjb25maWdQYXRoID0gcHJvY2Vzcy5lbnYuQlJPV1NFUlNUQUNLX0NBUEFCSUxJVElFU19DT05GSUdfUEFUSDtcblxuICAgICAgICBpZiAoIWNvbmZpZ1BhdGgpXG4gICAgICAgICAgICByZXR1cm4ge307XG5cbiAgICAgICAgcmV0dXJuIHJlcXVpcmUoY29uZmlnUGF0aCk7XG4gICAgfSxcblxuICAgIF9nZXRBZGRpdGlvbmFsQ2FwYWJpbGl0aWVzICgpIHtcbiAgICAgICAgY29uc3QgY2FwYWJpbGl0aWVzRnJvbUVudmlyb25tZW50ID0gcGlja0J5KHRoaXMuX2dldENhcGFiaWxpdGllc0Zyb21FbnZpcm9ubWVudCgpLCB2YWx1ZSA9PiB2YWx1ZSAhPT0gdm9pZCAwKTtcblxuICAgICAgICByZXR1cm4geyAuLi50aGlzLl9nZXRDYXBhYmlsaXRpZXNGcm9tQ29uZmlnKCksIC4uLmNhcGFiaWxpdGllc0Zyb21FbnZpcm9ubWVudCB9O1xuICAgIH0sXG5cbiAgICBfZmlsdGVyUGxhdGZvcm1JbmZvIChxdWVyeSkge1xuICAgICAgICBsZXQgZmlsdGVyZWRQbGF0Zm9ybUluZm8gPSB0aGlzLnBsYXRmb3Jtc0luZm9cbiAgICAgICAgICAgIC5maWx0ZXIoaW5mbyA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIGJyb3dzZXJOYW1lTWF0Y2hlZCA9IGluZm9bJ2Jyb3dzZXInXSAmJiBpbmZvWydicm93c2VyJ10udG9Mb3dlckNhc2UoKSA9PT0gcXVlcnkubmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZGV2aWNlTmFtZU1hdGNoZWQgID0gaW5mb1snZGV2aWNlJ10gJiYgaW5mb1snZGV2aWNlJ10udG9Mb3dlckNhc2UoKSA9PT0gcXVlcnkubmFtZTtcblxuICAgICAgICAgICAgICAgIHZhciBicm93c2VyVmVyc2lvbk1hdGNoZWQgID0gaW5mb1snYnJvd3Nlcl92ZXJzaW9uJ10gJiYgU3RyaW5nKGluZm9bJ2Jyb3dzZXJfdmVyc2lvbiddKSA9PT0gU3RyaW5nKHF1ZXJ5LnZlcnNpb24pO1xuICAgICAgICAgICAgICAgIHZhciBwbGF0Zm9ybVZlcnNpb25NYXRjaGVkID0gaW5mb1snb3NfdmVyc2lvbiddICYmIFN0cmluZyhpbmZvWydvc192ZXJzaW9uJ10pLnRvTG93ZXJDYXNlKCkgPT09IFN0cmluZyhxdWVyeS52ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB2YXIgcGxhdGZvcm1OYW1lTWF0Y2hlZCAgICA9IGluZm9bJ29zJ10udG9Mb3dlckNhc2UoKSA9PT0gcXVlcnkucGxhdGZvcm0gfHxcbiAgICAgICAgICAgICAgICAgICAgYCR7aW5mb1snb3MnXS50b0xvd2VyQ2FzZSgpfSAke2luZm9bJ29zX3ZlcnNpb24nXS50b0xvd2VyQ2FzZSgpfWAgPT09IHF1ZXJ5LnBsYXRmb3JtO1xuXG4gICAgICAgICAgICAgICAgdmFyIGlzQW55VmVyc2lvbiAgPSBxdWVyeS52ZXJzaW9uID09PSAnYW55JztcbiAgICAgICAgICAgICAgICB2YXIgaXNBbnlQbGF0Zm9ybSA9IHF1ZXJ5LnBsYXRmb3JtID09PSAnYW55JztcblxuICAgICAgICAgICAgICAgIHZhciBkZXNrdG9wQnJvd3Nlck1hdGNoZWQgPSBicm93c2VyTmFtZU1hdGNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGJyb3dzZXJWZXJzaW9uTWF0Y2hlZCB8fCBpc0FueVZlcnNpb24pICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwbGF0Zm9ybU5hbWVNYXRjaGVkIHx8IGlzQW55UGxhdGZvcm0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vYmlsZUJyb3dzZXJNYXRjaGVkID0gZGV2aWNlTmFtZU1hdGNoZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocGxhdGZvcm1WZXJzaW9uTWF0Y2hlZCB8fCBpc0FueVZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlc2t0b3BCcm93c2VyTWF0Y2hlZCB8fCBtb2JpbGVCcm93c2VyTWF0Y2hlZDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChmaWx0ZXJlZFBsYXRmb3JtSW5mby5sZW5ndGggJiYgcXVlcnkudmVyc2lvbiA9PT0gJ2FueScpIHtcbiAgICAgICAgICAgIGZpbHRlcmVkUGxhdGZvcm1JbmZvID0gZmlsdGVyZWRQbGF0Zm9ybUluZm8uZmlsdGVyKGluZm8gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJyb3dzZXJWZXJzaW9uID0gaW5mb1snYnJvd3Nlcl92ZXJzaW9uJ10gfHwgJyc7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gIWJyb3dzZXJWZXJzaW9uLmluY2x1ZGVzKCdiZXRhJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmaWx0ZXJlZFBsYXRmb3JtSW5mbztcbiAgICB9LFxuXG4gICAgX2dlbmVyYXRlQnJvd3Nlck5hbWVzICgpIHtcbiAgICAgICAgdGhpcy5icm93c2VyTmFtZXMgPSB0aGlzLnBsYXRmb3Jtc0luZm9cbiAgICAgICAgICAgIC5tYXAoaW5mbyA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIGlzRGVza3RvcCA9ICFpbmZvWydkZXZpY2UnXTtcbiAgICAgICAgICAgICAgICB2YXIgbmFtZSAgICAgID0gaXNEZXNrdG9wID8gaW5mb1snYnJvd3NlciddIDogaW5mb1snZGV2aWNlJ107XG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb24gICA9IGlzRGVza3RvcCA/IGluZm9bJ2Jyb3dzZXJfdmVyc2lvbiddIDogaW5mb1snb3NfdmVyc2lvbiddO1xuICAgICAgICAgICAgICAgIHZhciBwbGF0Zm9ybSAgPSBpc0Rlc2t0b3AgPyBgJHtpbmZvWydvcyddfSAke2luZm9bJ29zX3ZlcnNpb24nXX1gIDogJyc7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7bmFtZX1AJHt2ZXJzaW9ufSR7cGxhdGZvcm0gPyAnOicgKyBwbGF0Zm9ybSA6ICcnfWA7XG4gICAgICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgX3ByZXBhcmVDaHJvbWVDYXBhYmlsaXRpZXMgKGNhcGFiaWxpdGllcykge1xuICAgICAgICBpZiAocHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19DSFJPTUVfQVJHUyddICYmIHByb2Nlc3MuZW52WydCUk9XU0VSU1RBQ0tfQ0hST01FX0FSR1MnXS5sZW5ndGggPiAwKVxuICAgICAgICAgICAgY2FwYWJpbGl0aWVzLmNocm9tZU9wdGlvbnMgPSB7IGFyZ3M6IFtwcm9jZXNzLmVudlsnQlJPV1NFUlNUQUNLX0NIUk9NRV9BUkdTJ11dIH07XG4gICAgfSxcblxuICAgIGFzeW5jIF9wcmVwYXJlRmlyZWZveENhcGFiaWxpdGllcyAoY2FwYWJpbGl0aWVzKSB7XG4gICAgICAgIGlmICghcHJvY2Vzcy5lbnZbJ0JST1dTRVJTVEFDS19VU0VfQVVUT01BVEUnXSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBGaXJlZm94UHJvZmlsZSA9IHJlcXVpcmUoJ2ZpcmVmb3gtcHJvZmlsZScpO1xuICAgICAgICBjb25zdCBwcm9maWxlICAgICAgICA9IG5ldyBGaXJlZm94UHJvZmlsZSgpO1xuXG4gICAgICAgIHByb2ZpbGUuZGVmYXVsdFByZWZlcmVuY2VzID0ge307XG5cbiAgICAgICAgcHJvZmlsZS5zZXRQcmVmZXJlbmNlKCdicm93c2VyLmhlbHBlckFwcHMubmV2ZXJBc2suc2F2ZVRvRGlzaycsIGdldE1pbWVUeXBlcygpKTtcbiAgICAgICAgcHJvZmlsZS51cGRhdGVQcmVmZXJlbmNlcygpO1xuXG4gICAgICAgIGNhcGFiaWxpdGllc1snZmlyZWZveF9wcm9maWxlJ10gPSBhd2FpdCBwcm9taXNpZnkocHJvZmlsZS5lbmNvZGVkKS5iaW5kKHByb2ZpbGUpKCk7XG4gICAgfSxcblxuICAgIGFzeW5jIF9lbmNvZGVGaXJlZm94UHJvZmlsZSAocHJvZmlsZSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcHJvZmlsZS5lbmNvZGVkKGZ1bmN0aW9uIChlcnIsIGVuY29kZWRQcm9maWxlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycilcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGVuY29kZWRQcm9maWxlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgLy8gUmVxdWlyZWQgLSBtdXN0IGJlIGltcGxlbWVudGVkXG4gICAgLy8gQnJvd3NlciBjb250cm9sXG4gICAgYXN5bmMgb3BlbkJyb3dzZXIgKGlkLCBwYWdlVXJsLCBicm93c2VyTmFtZSkge1xuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSB7XG4gICAgICAgICAgICAuLi50aGlzLl9nZW5lcmF0ZUJhc2ljQ2FwYWJpbGl0aWVzKGJyb3dzZXJOYW1lKSxcbiAgICAgICAgICAgIC4uLnRoaXMuX2dldEFkZGl0aW9uYWxDYXBhYmlsaXRpZXMoKVxuICAgICAgICB9O1xuXG4gICAgICAgIGNhcGFiaWxpdGllcy5sb2NhbCA9IGlzTG9jYWxFbmFibGVkKCk7XG5cbiAgICAgICAgLy8gR2l2ZSBwcmVmZXJlbmNlIHRvIHRoZSBhbHJlYWR5IHJ1bm5pbmcgbG9jYWwgaWRlbnRpZmllclxuICAgICAgICBjYXBhYmlsaXRpZXMubG9jYWxJZGVudGlmaWVyID0gcHJvY2Vzcy5lbnYuQlJPV1NFUlNUQUNLX0xPQ0FMX0lERU5USUZJRVI7XG5cbiAgICAgICAgaWYgKGNhcGFiaWxpdGllcy5sb2NhbCAmJiAhY2FwYWJpbGl0aWVzLmxvY2FsSWRlbnRpZmllcikge1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdG9yID0gYXdhaXQgdGhpcy5fY3JlYXRlQ29ubmVjdG9yKCk7XG5cbiAgICAgICAgICAgIGNhcGFiaWxpdGllcy5sb2NhbElkZW50aWZpZXIgPSBjb25uZWN0b3IuY29ubmVjdG9ySW5zdGFuY2UubG9jYWxJZGVudGlmaWVyRmxhZztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjYXBhYmlsaXRpZXMub3MudG9Mb3dlckNhc2UoKSA9PT0gJ2FuZHJvaWQnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWRQYWdlVXJsID0gcGFyc2VVcmwocGFnZVVybCk7XG4gICAgICAgICAgICBjb25zdCBicm93c2VyUHJveHkgID0gYXdhaXQgdGhpcy5fZ2V0QnJvd3NlclByb3h5KHBhcnNlZFBhZ2VVcmwucHJvdG9jb2wsIHBhcnNlZFBhZ2VVcmwuaG9zdG5hbWUsIHBhcnNlZFBhZ2VVcmwucG9ydCk7XG5cbiAgICAgICAgICAgIHBhZ2VVcmwgPSAnaHR0cDovLycgKyBicm93c2VyUHJveHkudGFyZ2V0SG9zdCArICc6JyArIGJyb3dzZXJQcm94eS5wcm94eVBvcnQgKyBwYXJzZWRQYWdlVXJsLnBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNhcGFiaWxpdGllcy5uYW1lKVxuICAgICAgICAgICAgY2FwYWJpbGl0aWVzLm5hbWUgPSBgVGVzdENhZmUgdGVzdCBydW4gJHtpZH1gO1xuXG4gICAgICAgIGlmIChicm93c2VyTmFtZS5pbmNsdWRlcygnY2hyb21lJykpXG4gICAgICAgICAgICB0aGlzLl9wcmVwYXJlQ2hyb21lQ2FwYWJpbGl0aWVzKGNhcGFiaWxpdGllcyk7XG5cbiAgICAgICAgaWYgKGJyb3dzZXJOYW1lLmluY2x1ZGVzKCdmaXJlZm94JykpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9wcmVwYXJlRmlyZWZveENhcGFiaWxpdGllcyhjYXBhYmlsaXRpZXMpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuYmFja2VuZC5vcGVuQnJvd3NlcihpZCwgcGFnZVVybCwgY2FwYWJpbGl0aWVzKTtcblxuICAgICAgICB0aGlzLnNldFVzZXJBZ2VudE1ldGFJbmZvKGlkLCB0aGlzLmJhY2tlbmQuZ2V0U2Vzc2lvblVybChpZCkpO1xuICAgIH0sXG5cbiAgICBhc3luYyBjbG9zZUJyb3dzZXIgKGlkKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYmFja2VuZC5jbG9zZUJyb3dzZXIoaWQpO1xuICAgIH0sXG5cbiAgICAvLyBPcHRpb25hbCAtIGltcGxlbWVudCBtZXRob2RzIHlvdSBuZWVkLCByZW1vdmUgb3RoZXIgbWV0aG9kc1xuICAgIC8vIEluaXRpYWxpemF0aW9uXG4gICAgYXN5bmMgaW5pdCAoKSB7XG4gICAgICAgIHZhciByZXBvcnRXYXJuaW5nID0gKC4uLmFyZ3MpID0+IHRoaXMucmVwb3J0V2FybmluZyguLi5hcmdzKTtcblxuICAgICAgICB0aGlzLmJhY2tlbmQgPSBpc0F1dG9tYXRlRW5hYmxlZCgpID8gbmV3IEF1dG9tYXRlQmFja2VuZChyZXBvcnRXYXJuaW5nKSA6IG5ldyBKU1Rlc3RpbmdCYWNrZW5kKHJlcG9ydFdhcm5pbmcpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX2dldERldmljZUxpc3QoKTtcblxuICAgICAgICB0aGlzLl9nZW5lcmF0ZUJyb3dzZXJOYW1lcygpO1xuICAgIH0sXG5cbiAgICBhc3luYyBkaXNwb3NlICgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fZGlzcG9zZUNvbm5lY3RvcigpO1xuICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlQnJvd3NlclByb3h5KCk7XG4gICAgfSxcblxuXG4gICAgLy8gQnJvd3NlciBuYW1lcyBoYW5kbGluZ1xuICAgIGFzeW5jIGdldEJyb3dzZXJMaXN0ICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYnJvd3Nlck5hbWVzO1xuICAgIH0sXG5cbiAgICBhc3luYyBpc1ZhbGlkQnJvd3Nlck5hbWUgKGJyb3dzZXJOYW1lKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUNhcGFiaWxpdGllcyhicm93c2VyTmFtZSkubGVuZ3RoID09PSAxICYmICEhdGhpcy5fZmlsdGVyUGxhdGZvcm1JbmZvKHRoaXMuX2NyZWF0ZVF1ZXJ5KGJyb3dzZXJOYW1lKSkubGVuZ3RoO1xuICAgIH0sXG5cblxuICAgIC8vIEV4dHJhIG1ldGhvZHNcbiAgICBhc3luYyByZXNpemVXaW5kb3cgKGlkLCB3aWR0aCwgaGVpZ2h0LCBjdXJyZW50V2lkdGgsIGN1cnJlbnRIZWlnaHQpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5iYWNrZW5kLnJlc2l6ZVdpbmRvdyhpZCwgd2lkdGgsIGhlaWdodCwgY3VycmVudFdpZHRoLCBjdXJyZW50SGVpZ2h0KTtcbiAgICB9LFxuXG4gICAgYXN5bmMgbWF4aW1pemVXaW5kb3cgKGlkKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYmFja2VuZC5tYXhpbWl6ZVdpbmRvdyhpZCk7XG4gICAgfSxcblxuXG4gICAgYXN5bmMgdGFrZVNjcmVlbnNob3QgKGlkLCBzY3JlZW5zaG90UGF0aCkge1xuICAgICAgICBhd2FpdCB0aGlzLmJhY2tlbmQudGFrZVNjcmVlbnNob3QoaWQsIHNjcmVlbnNob3RQYXRoKTtcbiAgICB9LFxuXG4gICAgYXN5bmMgcmVwb3J0Sm9iUmVzdWx0IChpZCwgam9iUmVzdWx0LCBqb2JEYXRhKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYmFja2VuZC5yZXBvcnRKb2JSZXN1bHQoaWQsIGpvYlJlc3VsdCwgam9iRGF0YSwgdGhpcy5KT0JfUkVTVUxUKTtcbiAgICB9LFxuXG4gICAgYXN5bmMgZ2V0T1NJbmZvIChpZCkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5iYWNrZW5kLmdldE9TSW5mbyhpZCk7XG4gICAgfVxufTtcbiJdfQ==