appium
Version:
Automation for Apps.
333 lines (253 loc) • 20.4 kB
JavaScript
require('source-map-support').install();
;
var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _Object$assign = require('babel-runtime/core-js/object/assign')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _logsink = require('./logsink');
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
// logger needs to remain first of imports
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _appiumBaseDriver = require('appium-base-driver');
var _asyncbox = require('asyncbox');
var _parser = require('./parser');
var _parser2 = _interopRequireDefault(_parser);
var _config = require('./config');
var _appium = require('./appium');
var _appium2 = _interopRequireDefault(_appium);
var _gridRegister = require('./grid-register');
var _gridRegister2 = _interopRequireDefault(_gridRegister);
var _utils = require('./utils');
function preflightChecks(parser, args) {
var throwInsteadOfExit = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
return _regeneratorRuntime.async(function preflightChecks$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.prev = 0;
(0, _config.checkNodeOk)();
if (args.asyncTrace) {
require('longjohn').async_trace_limit = -1;
}
if (!args.showConfig) {
context$1$0.next = 7;
break;
}
context$1$0.next = 6;
return _regeneratorRuntime.awrap((0, _config.showConfig)());
case 6:
process.exit(0);
case 7:
(0, _config.warnNodeDeprecations)();
(0, _config.validateServerArgs)(parser, args);
if (!args.tmpDir) {
context$1$0.next = 12;
break;
}
context$1$0.next = 12;
return _regeneratorRuntime.awrap((0, _config.validateTmpDir)(args.tmpDir));
case 12:
context$1$0.next = 20;
break;
case 14:
context$1$0.prev = 14;
context$1$0.t0 = context$1$0['catch'](0);
_logger2['default'].error(context$1$0.t0.message.red);
if (!throwInsteadOfExit) {
context$1$0.next = 19;
break;
}
throw context$1$0.t0;
case 19:
process.exit(1);
case 20:
case 'end':
return context$1$0.stop();
}
}, null, this, [[0, 14]]);
}
function logDeprecationWarning(deprecatedArgs) {
_logger2['default'].warn('Deprecated server args:');
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _getIterator(_lodash2['default'].toPairs(deprecatedArgs)), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _step$value = _slicedToArray(_step.value, 2);
var arg = _step$value[0];
var realArg = _step$value[1];
_logger2['default'].warn(' ' + arg.red + ' => ' + realArg);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
function logNonDefaultArgsWarning(args) {
_logger2['default'].info('Non-default server args:');
(0, _utils.inspectObject)(args);
}
function logDefaultCapabilitiesWarning(caps) {
_logger2['default'].info('Default capabilities, which will be added to each request ' + 'unless overridden by desired capabilities:');
(0, _utils.inspectObject)(caps);
}
function logStartupInfo(parser, args) {
var welcome, appiumRev, showArgs, deprecatedArgs;
return _regeneratorRuntime.async(function logStartupInfo$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
welcome = 'Welcome to Appium v' + _config.APPIUM_VER;
context$1$0.next = 3;
return _regeneratorRuntime.awrap((0, _config.getGitRev)());
case 3:
appiumRev = context$1$0.sent;
if (appiumRev) {
welcome += ' (REV ' + appiumRev + ')';
}
_logger2['default'].info(welcome);
showArgs = (0, _config.getNonDefaultArgs)(parser, args);
if (_lodash2['default'].size(showArgs)) {
logNonDefaultArgsWarning(showArgs);
}
deprecatedArgs = (0, _config.getDeprecatedArgs)(parser, args);
if (_lodash2['default'].size(deprecatedArgs)) {
logDeprecationWarning(deprecatedArgs);
}
if (!_lodash2['default'].isEmpty(args.defaultCapabilities)) {
logDefaultCapabilitiesWarning(args.defaultCapabilities);
}
// TODO: bring back loglevel reporting below once logger is flushed out
//logger.info('Console LogLevel: ' + logger.transports.console.level);
//if (logger.transports.file) {
//logger.info('File LogLevel: ' + logger.transports.file.level);
//}
case 11:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function logServerPort(address, port) {
var logMessage = 'Appium REST http interface listener started on ' + (address + ':' + port);
_logger2['default'].info(logMessage);
}
function initHeapdump(args) {
if (args.heapdumpEnabled) {
require('heapdump');
}
}
function main() {
var args = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
var parser, throwInsteadOfExit, router, server;
return _regeneratorRuntime.async(function main$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
parser = (0, _parser2['default'])();
throwInsteadOfExit = false;
if (args) {
// a containing package passed in their own args, let's fill them out
// with defaults
args = _Object$assign({}, (0, _parser.getDefaultArgs)(), args);
// if we have a containing package instead of running as a CLI process,
// that package might not appreciate us calling 'process.exit' willy-
// nilly, so give it the option to have us throw instead of exit
if (args.throwInsteadOfExit) {
throwInsteadOfExit = true;
// but remove it since it's not a real server arg per se
delete args.throwInsteadOfExit;
}
} else {
// otherwise parse from CLI
args = parser.parseArgs();
}
initHeapdump(args);
context$1$0.next = 6;
return _regeneratorRuntime.awrap((0, _logsink.init)(args));
case 6:
context$1$0.next = 8;
return _regeneratorRuntime.awrap(preflightChecks(parser, args, throwInsteadOfExit));
case 8:
context$1$0.next = 10;
return _regeneratorRuntime.awrap(logStartupInfo(parser, args));
case 10:
router = (0, _appium2['default'])(args);
context$1$0.next = 13;
return _regeneratorRuntime.awrap((0, _appiumBaseDriver.server)(router, args.port, args.address));
case 13:
server = context$1$0.sent;
context$1$0.prev = 14;
if (!(args.nodeconfig !== null)) {
context$1$0.next = 18;
break;
}
context$1$0.next = 18;
return _regeneratorRuntime.awrap((0, _gridRegister2['default'])(args.nodeconfig, args.address, args.port));
case 18:
context$1$0.next = 25;
break;
case 20:
context$1$0.prev = 20;
context$1$0.t0 = context$1$0['catch'](14);
context$1$0.next = 24;
return _regeneratorRuntime.awrap(server.close());
case 24:
throw context$1$0.t0;
case 25:
process.once('SIGINT', function callee$1$0() {
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
_logger2['default'].info('Received SIGINT - shutting down');
context$2$0.next = 3;
return _regeneratorRuntime.awrap(server.close());
case 3:
case 'end':
return context$2$0.stop();
}
}, null, this);
});
process.once('SIGTERM', function callee$1$0() {
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
_logger2['default'].info('Received SIGTERM - shutting down');
context$2$0.next = 3;
return _regeneratorRuntime.awrap(server.close());
case 3:
case 'end':
return context$2$0.stop();
}
}, null, this);
});
logServerPort(args.address, args.port);
return context$1$0.abrupt('return', server);
case 29:
case 'end':
return context$1$0.stop();
}
}, null, this, [[14, 20]]);
}
if (require.main === module) {
(0, _asyncbox.asyncify)(main);
}
exports.main = main;
// TODO prelaunch if args.launch is set
// TODO: startAlertSocket(server, appiumServer);
// configure as node on grid, if necessary
//# sourceMappingURL=data:application/json;charset=utf8;base64,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SSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUM7Ozs7Ozs7Ozs7eUNBR3hELE1BQU0sQ0FBQyxLQUFLLEVBQUU7Ozs7Ozs7QUFJdEIsZUFBTyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7Ozs7QUFDckIsb0NBQU8sSUFBSSxtQ0FBbUMsQ0FBQzs7aURBQ3pDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7Ozs7Ozs7U0FDckIsQ0FBQyxDQUFDOztBQUVILGVBQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFOzs7O0FBQ3RCLG9DQUFPLElBQUksb0NBQW9DLENBQUM7O2lEQUMxQyxNQUFNLENBQUMsS0FBSyxFQUFFOzs7Ozs7O1NBQ3JCLENBQUMsQ0FBQzs7QUFFSCxxQkFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDOzs0Q0FFaEMsTUFBTTs7Ozs7OztDQUNkOztBQUVELElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7QUFDM0IsMEJBQVMsSUFBSSxDQUFDLENBQUM7Q0FDaEI7O1FBRVEsSUFBSSxHQUFKLElBQUkiLCJmaWxlIjoibGliL21haW4uanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbi8vIHRyYW5zcGlsZTptYWluXG5cbmltcG9ydCB7IGluaXQgYXMgbG9nc2lua0luaXQgfSBmcm9tICcuL2xvZ3NpbmsnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuL2xvZ2dlcic7IC8vIGxvZ2dlciBuZWVkcyB0byByZW1haW4gZmlyc3Qgb2YgaW1wb3J0c1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IHNlcnZlciBhcyBiYXNlU2VydmVyIH0gZnJvbSAnYXBwaXVtLWJhc2UtZHJpdmVyJztcbmltcG9ydCB7IGFzeW5jaWZ5IH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IHsgZGVmYXVsdCBhcyBnZXRQYXJzZXIsIGdldERlZmF1bHRBcmdzIH0gZnJvbSAnLi9wYXJzZXInO1xuaW1wb3J0IHsgc2hvd0NvbmZpZywgY2hlY2tOb2RlT2ssIHZhbGlkYXRlU2VydmVyQXJncyxcbiAgICAgICAgIHdhcm5Ob2RlRGVwcmVjYXRpb25zLCB2YWxpZGF0ZVRtcERpciwgZ2V0Tm9uRGVmYXVsdEFyZ3MsXG4gICAgICAgICBnZXREZXByZWNhdGVkQXJncywgZ2V0R2l0UmV2LCBBUFBJVU1fVkVSIH0gZnJvbSAnLi9jb25maWcnO1xuaW1wb3J0IGdldEFwcGl1bVJvdXRlciBmcm9tICcuL2FwcGl1bSc7XG5pbXBvcnQgcmVnaXN0ZXJOb2RlIGZyb20gJy4vZ3JpZC1yZWdpc3Rlcic7XG5pbXBvcnQgeyBpbnNwZWN0T2JqZWN0IH0gZnJvbSAnLi91dGlscyc7XG5cblxuYXN5bmMgZnVuY3Rpb24gcHJlZmxpZ2h0Q2hlY2tzIChwYXJzZXIsIGFyZ3MsIHRocm93SW5zdGVhZE9mRXhpdCA9IGZhbHNlKSB7XG4gIHRyeSB7XG4gICAgY2hlY2tOb2RlT2soKTtcbiAgICBpZiAoYXJncy5hc3luY1RyYWNlKSB7XG4gICAgICByZXF1aXJlKCdsb25nam9obicpLmFzeW5jX3RyYWNlX2xpbWl0ID0gLTE7XG4gICAgfVxuICAgIGlmIChhcmdzLnNob3dDb25maWcpIHtcbiAgICAgIGF3YWl0IHNob3dDb25maWcoKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgwKTtcbiAgICB9XG4gICAgd2Fybk5vZGVEZXByZWNhdGlvbnMoKTtcbiAgICB2YWxpZGF0ZVNlcnZlckFyZ3MocGFyc2VyLCBhcmdzKTtcbiAgICBpZiAoYXJncy50bXBEaXIpIHtcbiAgICAgIGF3YWl0IHZhbGlkYXRlVG1wRGlyKGFyZ3MudG1wRGlyKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci5lcnJvcihlcnIubWVzc2FnZS5yZWQpO1xuICAgIGlmICh0aHJvd0luc3RlYWRPZkV4aXQpIHtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG5cbiAgICBwcm9jZXNzLmV4aXQoMSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gbG9nRGVwcmVjYXRpb25XYXJuaW5nIChkZXByZWNhdGVkQXJncykge1xuICBsb2dnZXIud2FybignRGVwcmVjYXRlZCBzZXJ2ZXIgYXJnczonKTtcbiAgZm9yIChsZXQgW2FyZywgcmVhbEFyZ10gb2YgXy50b1BhaXJzKGRlcHJlY2F0ZWRBcmdzKSkge1xuICAgIGxvZ2dlci53YXJuKGAgICR7YXJnLnJlZH0gPT4gJHtyZWFsQXJnfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGxvZ05vbkRlZmF1bHRBcmdzV2FybmluZyAoYXJncykge1xuICBsb2dnZXIuaW5mbygnTm9uLWRlZmF1bHQgc2VydmVyIGFyZ3M6Jyk7XG4gIGluc3BlY3RPYmplY3QoYXJncyk7XG59XG5cbmZ1bmN0aW9uIGxvZ0RlZmF1bHRDYXBhYmlsaXRpZXNXYXJuaW5nIChjYXBzKSB7XG4gIGxvZ2dlci5pbmZvKCdEZWZhdWx0IGNhcGFiaWxpdGllcywgd2hpY2ggd2lsbCBiZSBhZGRlZCB0byBlYWNoIHJlcXVlc3QgJyArXG4gICAgICAgICAgICAgICd1bmxlc3Mgb3ZlcnJpZGRlbiBieSBkZXNpcmVkIGNhcGFiaWxpdGllczonKTtcbiAgaW5zcGVjdE9iamVjdChjYXBzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9nU3RhcnR1cEluZm8gKHBhcnNlciwgYXJncykge1xuICBsZXQgd2VsY29tZSA9IGBXZWxjb21lIHRvIEFwcGl1bSB2JHtBUFBJVU1fVkVSfWA7XG4gIGxldCBhcHBpdW1SZXYgPSBhd2FpdCBnZXRHaXRSZXYoKTtcbiAgaWYgKGFwcGl1bVJldikge1xuICAgIHdlbGNvbWUgKz0gYCAoUkVWICR7YXBwaXVtUmV2fSlgO1xuICB9XG4gIGxvZ2dlci5pbmZvKHdlbGNvbWUpO1xuXG4gIGxldCBzaG93QXJncyA9IGdldE5vbkRlZmF1bHRBcmdzKHBhcnNlciwgYXJncyk7XG4gIGlmIChfLnNpemUoc2hvd0FyZ3MpKSB7XG4gICAgbG9nTm9uRGVmYXVsdEFyZ3NXYXJuaW5nKHNob3dBcmdzKTtcbiAgfVxuICBsZXQgZGVwcmVjYXRlZEFyZ3MgPSBnZXREZXByZWNhdGVkQXJncyhwYXJzZXIsIGFyZ3MpO1xuICBpZiAoXy5zaXplKGRlcHJlY2F0ZWRBcmdzKSkge1xuICAgIGxvZ0RlcHJlY2F0aW9uV2FybmluZyhkZXByZWNhdGVkQXJncyk7XG4gIH1cbiAgaWYgKCFfLmlzRW1wdHkoYXJncy5kZWZhdWx0Q2FwYWJpbGl0aWVzKSkge1xuICAgIGxvZ0RlZmF1bHRDYXBhYmlsaXRpZXNXYXJuaW5nKGFyZ3MuZGVmYXVsdENhcGFiaWxpdGllcyk7XG4gIH1cbiAgLy8gVE9ETzogYnJpbmcgYmFjayBsb2dsZXZlbCByZXBvcnRpbmcgYmVsb3cgb25jZSBsb2dnZXIgaXMgZmx1c2hlZCBvdXRcbiAgLy9sb2dnZXIuaW5mbygnQ29uc29sZSBMb2dMZXZlbDogJyArIGxvZ2dlci50cmFuc3BvcnRzLmNvbnNvbGUubGV2ZWwpO1xuICAvL2lmIChsb2dnZXIudHJhbnNwb3J0cy5maWxlKSB7XG4gICAgLy9sb2dnZXIuaW5mbygnRmlsZSBMb2dMZXZlbDogJyArIGxvZ2dlci50cmFuc3BvcnRzLmZpbGUubGV2ZWwpO1xuICAvL31cbn1cblxuZnVuY3Rpb24gbG9nU2VydmVyUG9ydCAoYWRkcmVzcywgcG9ydCkge1xuICBsZXQgbG9nTWVzc2FnZSA9IGBBcHBpdW0gUkVTVCBodHRwIGludGVyZmFjZSBsaXN0ZW5lciBzdGFydGVkIG9uIGAgK1xuICAgICAgICAgICAgICAgICAgIGAke2FkZHJlc3N9OiR7cG9ydH1gO1xuICBsb2dnZXIuaW5mbyhsb2dNZXNzYWdlKTtcbn1cblxuZnVuY3Rpb24gaW5pdEhlYXBkdW1wIChhcmdzKSB7XG4gIGlmIChhcmdzLmhlYXBkdW1wRW5hYmxlZCkge1xuICAgIHJlcXVpcmUoJ2hlYXBkdW1wJyk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbiAoYXJncyA9IG51bGwpIHtcbiAgbGV0IHBhcnNlciA9IGdldFBhcnNlcigpO1xuICBsZXQgdGhyb3dJbnN0ZWFkT2ZFeGl0ID0gZmFsc2U7XG4gIGlmIChhcmdzKSB7XG4gICAgLy8gYSBjb250YWluaW5nIHBhY2thZ2UgcGFzc2VkIGluIHRoZWlyIG93biBhcmdzLCBsZXQncyBmaWxsIHRoZW0gb3V0XG4gICAgLy8gd2l0aCBkZWZhdWx0c1xuICAgIGFyZ3MgPSBPYmplY3QuYXNzaWduKHt9LCBnZXREZWZhdWx0QXJncygpLCBhcmdzKTtcblxuICAgIC8vIGlmIHdlIGhhdmUgYSBjb250YWluaW5nIHBhY2thZ2UgaW5zdGVhZCBvZiBydW5uaW5nIGFzIGEgQ0xJIHByb2Nlc3MsXG4gICAgLy8gdGhhdCBwYWNrYWdlIG1pZ2h0IG5vdCBhcHByZWNpYXRlIHVzIGNhbGxpbmcgJ3Byb2Nlc3MuZXhpdCcgd2lsbHktXG4gICAgLy8gbmlsbHksIHNvIGdpdmUgaXQgdGhlIG9wdGlvbiB0byBoYXZlIHVzIHRocm93IGluc3RlYWQgb2YgZXhpdFxuICAgIGlmIChhcmdzLnRocm93SW5zdGVhZE9mRXhpdCkge1xuICAgICAgdGhyb3dJbnN0ZWFkT2ZFeGl0ID0gdHJ1ZTtcbiAgICAgIC8vIGJ1dCByZW1vdmUgaXQgc2luY2UgaXQncyBub3QgYSByZWFsIHNlcnZlciBhcmcgcGVyIHNlXG4gICAgICBkZWxldGUgYXJncy50aHJvd0luc3RlYWRPZkV4aXQ7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIG90aGVyd2lzZSBwYXJzZSBmcm9tIENMSVxuICAgIGFyZ3MgPSBwYXJzZXIucGFyc2VBcmdzKCk7XG4gIH1cbiAgaW5pdEhlYXBkdW1wKGFyZ3MpO1xuICBhd2FpdCBsb2dzaW5rSW5pdChhcmdzKTtcbiAgYXdhaXQgcHJlZmxpZ2h0Q2hlY2tzKHBhcnNlciwgYXJncywgdGhyb3dJbnN0ZWFkT2ZFeGl0KTtcbiAgYXdhaXQgbG9nU3RhcnR1cEluZm8ocGFyc2VyLCBhcmdzKTtcbiAgbGV0IHJvdXRlciA9IGdldEFwcGl1bVJvdXRlcihhcmdzKTtcbiAgbGV0IHNlcnZlciA9IGF3YWl0IGJhc2VTZXJ2ZXIocm91dGVyLCBhcmdzLnBvcnQsIGFyZ3MuYWRkcmVzcyk7XG4gIHRyeSB7XG4gICAgLy8gVE9ETyBwcmVsYXVuY2ggaWYgYXJncy5sYXVuY2ggaXMgc2V0XG4gICAgLy8gVE9ETzogc3RhcnRBbGVydFNvY2tldChzZXJ2ZXIsIGFwcGl1bVNlcnZlcik7XG5cbiAgICAvLyBjb25maWd1cmUgYXMgbm9kZSBvbiBncmlkLCBpZiBuZWNlc3NhcnlcbiAgICBpZiAoYXJncy5ub2RlY29uZmlnICE9PSBudWxsKSB7XG4gICAgICBhd2FpdCByZWdpc3Rlck5vZGUoYXJncy5ub2RlY29uZmlnLCBhcmdzLmFkZHJlc3MsIGFyZ3MucG9ydCk7XG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBhd2FpdCBzZXJ2ZXIuY2xvc2UoKTtcbiAgICB0aHJvdyBlcnI7XG4gIH1cblxuICBwcm9jZXNzLm9uY2UoJ1NJR0lOVCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBsb2dnZXIuaW5mbyhgUmVjZWl2ZWQgU0lHSU5UIC0gc2h1dHRpbmcgZG93bmApO1xuICAgIGF3YWl0IHNlcnZlci5jbG9zZSgpO1xuICB9KTtcblxuICBwcm9jZXNzLm9uY2UoJ1NJR1RFUk0nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgbG9nZ2VyLmluZm8oYFJlY2VpdmVkIFNJR1RFUk0gLSBzaHV0dGluZyBkb3duYCk7XG4gICAgYXdhaXQgc2VydmVyLmNsb3NlKCk7XG4gIH0pO1xuXG4gIGxvZ1NlcnZlclBvcnQoYXJncy5hZGRyZXNzLCBhcmdzLnBvcnQpO1xuXG4gIHJldHVybiBzZXJ2ZXI7XG59XG5cbmlmIChyZXF1aXJlLm1haW4gPT09IG1vZHVsZSkge1xuICBhc3luY2lmeShtYWluKTtcbn1cblxuZXhwb3J0IHsgbWFpbiB9O1xuIl0sInNvdXJjZVJvb3QiOiIuLi8uLiJ9