appium-ios-simulator
Version:
iOS Simulator interface for Appium.
340 lines (267 loc) • 22.1 kB
JavaScript
;
var _get = require('babel-runtime/helpers/get')['default'];
var _inherits = require('babel-runtime/helpers/inherits')['default'];
var _createClass = require('babel-runtime/helpers/create-class')['default'];
var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['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 _simulatorXcode8 = require('./simulator-xcode-8');
var _simulatorXcode82 = _interopRequireDefault(_simulatorXcode8);
var _asyncLock = require('async-lock');
var _asyncLock2 = _interopRequireDefault(_asyncLock);
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
var _nodeSimctl = require('node-simctl');
var _asyncbox = require('asyncbox');
var SIMULATOR_SHUTDOWN_TIMEOUT = 15 * 1000;
var startupLock = new _asyncLock2['default']();
var SimulatorXcode9 = (function (_SimulatorXcode8) {
_inherits(SimulatorXcode9, _SimulatorXcode8);
function SimulatorXcode9(udid, xcodeVersion) {
_classCallCheck(this, SimulatorXcode9);
_get(Object.getPrototypeOf(SimulatorXcode9.prototype), 'constructor', this).call(this, udid, xcodeVersion);
}
/**
* Executes given Simulator with options. The Simulator will not be restarted if
* it is already running and the current UI state matches to `isHeadless` option.
* @override
*
* @param {object} opts - One or more of available Simulator options:
* - {string} scaleFactor: can be one of ['1.0', '0.75', '0.5', '0.33', '0.25'].
* Defines the window scale value for the UI client window for the current Simulator.
* Equals to null by default, which keeps the current scale unchanged.
* - {boolean} connectHardwareKeyboard: whether to connect the hardware keyboard to the
* Simulator UI client. Equals to false by default.
* - {number} startupTimeout: number of milliseconds to wait until Simulator booting
* process is completed. The default timeout will be used if not set explicitly.
* - {boolean} isHeadless: whether to start the Simulator in headless mode (with UI
* client invisible). `false` by default.
*/
_createClass(SimulatorXcode9, [{
key: 'run',
value: function run() {
var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var bootSimulator, waitForShutdown, shouldWaitForBoot, startTime;
return _regeneratorRuntime.async(function run$(context$2$0) {
var _this = this;
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
opts = _Object$assign({
isHeadless: false,
startupTimeout: this.startupTimeout
}, opts);
bootSimulator = function bootSimulator() {
return _regeneratorRuntime.async(function bootSimulator$(context$3$0) {
while (1) switch (context$3$0.prev = context$3$0.next) {
case 0:
context$3$0.prev = 0;
context$3$0.next = 3;
return _regeneratorRuntime.awrap((0, _nodeSimctl.bootDevice)(this.udid));
case 3:
context$3$0.next = 8;
break;
case 5:
context$3$0.prev = 5;
context$3$0.t0 = context$3$0['catch'](0);
_logger2['default'].warn('\'xcrun simctl boot ' + this.udid + '\' command has returned non-zero code. The problem was: ' + context$3$0.t0.stderr);
case 8:
case 'end':
return context$3$0.stop();
}
}, null, _this, [[0, 5]]);
};
waitForShutdown = function waitForShutdown() {
return _regeneratorRuntime.async(function waitForShutdown$(context$3$0) {
var _this2 = this;
while (1) switch (context$3$0.prev = context$3$0.next) {
case 0:
context$3$0.next = 2;
return _regeneratorRuntime.awrap((0, _asyncbox.waitForCondition)(function callee$3$0() {
var _ref, state;
return _regeneratorRuntime.async(function callee$3$0$(context$4$0) {
while (1) switch (context$4$0.prev = context$4$0.next) {
case 0:
context$4$0.next = 2;
return _regeneratorRuntime.awrap(this.stat());
case 2:
_ref = context$4$0.sent;
state = _ref.state;
return context$4$0.abrupt('return', state === 'Shutdown');
case 5:
case 'end':
return context$4$0.stop();
}
}, null, _this2);
}, { waitMs: SIMULATOR_SHUTDOWN_TIMEOUT, intervalMs: 500 }));
case 2:
case 'end':
return context$3$0.stop();
}
}, null, _this);
};
shouldWaitForBoot = true;
startTime = process.hrtime();
context$2$0.next = 7;
return _regeneratorRuntime.awrap(startupLock.acquire(this.uiClientBundleId, function callee$2$0() {
var stat, serverState, isServerRunning, isUIClientRunning;
return _regeneratorRuntime.async(function callee$2$0$(context$3$0) {
while (1) switch (context$3$0.prev = context$3$0.next) {
case 0:
context$3$0.next = 2;
return _regeneratorRuntime.awrap(this.stat());
case 2:
stat = context$3$0.sent;
serverState = stat.state;
isServerRunning = serverState === 'Booted';
context$3$0.next = 7;
return _regeneratorRuntime.awrap(this.isUIClientRunning());
case 7:
isUIClientRunning = context$3$0.sent;
if (!opts.isHeadless) {
context$3$0.next = 24;
break;
}
if (!(isServerRunning && !isUIClientRunning)) {
context$3$0.next = 13;
break;
}
_logger2['default'].info('Simulator with UDID ' + this.udid + ' already booted in headless mode.');
shouldWaitForBoot = false;
return context$3$0.abrupt('return');
case 13:
context$3$0.next = 15;
return _regeneratorRuntime.awrap(this.killUIClient());
case 15:
if (!context$3$0.sent) {
context$3$0.next = 19;
break;
}
// Stopping the UI client also kills all running servers. Sad but true
_logger2['default'].info('Detected the UI client was running and killed it. Verifying the Simulator is in Shutdown state...');
context$3$0.next = 19;
return _regeneratorRuntime.awrap(waitForShutdown());
case 19:
_logger2['default'].info('Booting Simulator with UDID ' + this.udid + ' in headless mode. All UI-related capabilities are going to be ignored.');
context$3$0.next = 22;
return _regeneratorRuntime.awrap(bootSimulator());
case 22:
context$3$0.next = 46;
break;
case 24:
if (!(isServerRunning && isUIClientRunning)) {
context$3$0.next = 28;
break;
}
_logger2['default'].info('Both Simulator with UDID ' + this.udid + ' and the UI client are currently running');
shouldWaitForBoot = false;
return context$3$0.abrupt('return');
case 28:
if (!(['Shutdown', 'Booted'].indexOf(serverState) === -1)) {
context$3$0.next = 40;
break;
}
_logger2['default'].info('Simulator ' + this.udid + ' is in \'' + serverState + '\' state. Trying to shutdown...');
context$3$0.prev = 30;
context$3$0.next = 33;
return _regeneratorRuntime.awrap(this.shutdown());
case 33:
context$3$0.next = 38;
break;
case 35:
context$3$0.prev = 35;
context$3$0.t0 = context$3$0['catch'](30);
_logger2['default'].warn('Error on Simulator shutdown: ' + context$3$0.t0.message);
case 38:
context$3$0.next = 40;
return _regeneratorRuntime.awrap(waitForShutdown());
case 40:
_logger2['default'].info('Booting Simulator with UDID ' + this.udid + '...');
context$3$0.next = 43;
return _regeneratorRuntime.awrap(bootSimulator());
case 43:
if (isUIClientRunning) {
context$3$0.next = 46;
break;
}
context$3$0.next = 46;
return _regeneratorRuntime.awrap(this.startUIClient(opts));
case 46:
case 'end':
return context$3$0.stop();
}
}, null, _this, [[30, 35]]);
}));
case 7:
if (!shouldWaitForBoot) {
context$2$0.next = 11;
break;
}
context$2$0.next = 10;
return _regeneratorRuntime.awrap(this.waitForBoot(opts.startupTimeout));
case 10:
_logger2['default'].info('Simulator with UDID ' + this.udid + ' booted in ' + process.hrtime(startTime)[0] + ' seconds');
case 11:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Shut down the current Simulator.
* @override
*/
}, {
key: 'shutdown',
value: function shutdown() {
var _ref2, state;
return _regeneratorRuntime.async(function shutdown$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap(this.stat());
case 2:
_ref2 = context$2$0.sent;
state = _ref2.state;
if (!(state === 'Shutdown')) {
context$2$0.next = 6;
break;
}
return context$2$0.abrupt('return');
case 6:
context$2$0.next = 8;
return _regeneratorRuntime.awrap((0, _nodeSimctl.shutdown)(this.udid));
case 8:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
/**
* Reset the current Simulator to the clean state.
* @override
*/
}, {
key: 'clean',
value: function clean() {
return _regeneratorRuntime.async(function clean$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
_logger2['default'].info('Cleaning simulator ' + this.udid);
context$2$0.next = 3;
return _regeneratorRuntime.awrap((0, _nodeSimctl.eraseDevice)(this.udid, 10000));
case 3:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
}]);
return SimulatorXcode9;
})(_simulatorXcode82['default']);
exports['default'] = SimulatorXcode9;
module.exports = exports['default'];
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9zaW11bGF0b3IteGNvZGUtOS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrQkFBNEIscUJBQXFCOzs7O3lCQUMzQixZQUFZOzs7O3NCQUNsQixVQUFVOzs7OzBCQUMwQyxhQUFhOzt3QkFDaEQsVUFBVTs7QUFHM0MsSUFBTSwwQkFBMEIsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQzdDLElBQU0sV0FBVyxHQUFHLDRCQUFlLENBQUM7O0lBRTlCLGVBQWU7WUFBZixlQUFlOztBQUNQLFdBRFIsZUFBZSxDQUNOLElBQUksRUFBRSxZQUFZLEVBQUU7MEJBRDdCLGVBQWU7O0FBRWpCLCtCQUZFLGVBQWUsNkNBRVgsSUFBSSxFQUFFLFlBQVksRUFBRTtHQUMzQjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztlQUhHLGVBQWU7O1dBcUJUO1VBQUMsSUFBSSx5REFBRyxFQUFFO1VBS1osYUFBYSxFQU9iLGVBQWUsRUFNakIsaUJBQWlCLEVBQ2YsU0FBUzs7Ozs7O0FBbEJmLGdCQUFJLEdBQUcsZUFBYztBQUNuQix3QkFBVSxFQUFFLEtBQUs7QUFDakIsNEJBQWMsRUFBRSxJQUFJLENBQUMsY0FBYzthQUNwQyxFQUFFLElBQUksQ0FBQyxDQUFDOztBQUNILHlCQUFhLEdBQUcsU0FBaEIsYUFBYTs7Ozs7O3FEQUVULDRCQUFXLElBQUksQ0FBQyxJQUFJLENBQUM7Ozs7Ozs7Ozs7QUFFM0Isd0NBQUksSUFBSSwwQkFBdUIsSUFBSSxDQUFDLElBQUksZ0VBQTBELGVBQUksTUFBTSxDQUFHLENBQUM7Ozs7Ozs7YUFFbkg7O0FBQ0ssMkJBQWUsR0FBRyxTQUFsQixlQUFlOzs7Ozs7O3FEQUNiLGdDQUFpQjtnQ0FDZCxLQUFLOzs7Ozs7NkRBQVUsSUFBSSxDQUFDLElBQUksRUFBRTs7OztBQUExQixpQ0FBSyxRQUFMLEtBQUs7Z0VBQ0wsS0FBSyxLQUFLLFVBQVU7Ozs7Ozs7cUJBQzVCLEVBQUUsRUFBQyxNQUFNLEVBQUUsMEJBQTBCLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBQyxDQUFDOzs7Ozs7O2FBQzFEOztBQUNHLDZCQUFpQixHQUFHLElBQUk7QUFDdEIscUJBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFOzs2Q0FDNUIsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7a0JBQ3pDLElBQUksRUFDSixXQUFXLEVBQ1gsZUFBZSxFQUNmLGlCQUFpQjs7Ozs7cURBSEosSUFBSSxDQUFDLElBQUksRUFBRTs7O0FBQXhCLHdCQUFJO0FBQ0osK0JBQVcsR0FBRyxJQUFJLENBQUMsS0FBSztBQUN4QixtQ0FBZSxHQUFHLFdBQVcsS0FBSyxRQUFROztxREFDaEIsSUFBSSxDQUFDLGlCQUFpQixFQUFFOzs7QUFBbEQscUNBQWlCOzt5QkFDbkIsSUFBSSxDQUFDLFVBQVU7Ozs7OzBCQUNiLGVBQWUsSUFBSSxDQUFDLGlCQUFpQixDQUFBOzs7OztBQUN2Qyx3Q0FBSSxJQUFJLDBCQUF3QixJQUFJLENBQUMsSUFBSSx1Q0FBb0MsQ0FBQztBQUM5RSxxQ0FBaUIsR0FBRyxLQUFLLENBQUM7Ozs7O3FEQUdsQixJQUFJLENBQUMsWUFBWSxFQUFFOzs7Ozs7Ozs7QUFFM0Isd0NBQUksSUFBSSxxR0FBcUcsQ0FBQzs7cURBQ3hHLGVBQWUsRUFBRTs7O0FBRXpCLHdDQUFJLElBQUksa0NBQWdDLElBQUksQ0FBQyxJQUFJLDZFQUEwRSxDQUFDOztxREFDdEgsYUFBYSxFQUFFOzs7Ozs7OzBCQUVqQixlQUFlLElBQUksaUJBQWlCLENBQUE7Ozs7O0FBQ3RDLHdDQUFJLElBQUksK0JBQTZCLElBQUksQ0FBQyxJQUFJLDhDQUEyQyxDQUFDO0FBQzFGLHFDQUFpQixHQUFHLEtBQUssQ0FBQzs7OzswQkFHeEIsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBOzs7OztBQUNwRCx3Q0FBSSxJQUFJLGdCQUFjLElBQUksQ0FBQyxJQUFJLGlCQUFXLFdBQVcscUNBQWlDLENBQUM7OztxREFFL0UsSUFBSSxDQUFDLFFBQVEsRUFBRTs7Ozs7Ozs7OztBQUVyQix3Q0FBSSxJQUFJLG1DQUFpQyxlQUFJLE9BQU8sQ0FBRyxDQUFDOzs7O3FEQUVwRCxlQUFlLEVBQUU7OztBQUV6Qix3Q0FBSSxJQUFJLGtDQUFnQyxJQUFJLENBQUMsSUFBSSxTQUFNLENBQUM7O3FEQUNsRCxhQUFhLEVBQUU7Ozt3QkFDaEIsaUJBQWlCOzs7Ozs7cURBQ2QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUM7Ozs7Ozs7YUFHbkMsQ0FBQzs7O2lCQUVFLGlCQUFpQjs7Ozs7OzZDQUNiLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQzs7O0FBQzNDLGdDQUFJLElBQUksMEJBQXdCLElBQUksQ0FBQyxJQUFJLG1CQUFjLE9BQU8sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQVcsQ0FBQzs7Ozs7OztLQUVsRzs7Ozs7Ozs7V0FNYztpQkFDTixLQUFLOzs7Ozs7NkNBQVUsSUFBSSxDQUFDLElBQUksRUFBRTs7OztBQUExQixpQkFBSyxTQUFMLEtBQUs7O2tCQUNSLEtBQUssS0FBSyxVQUFVLENBQUE7Ozs7Ozs7Ozs2Q0FHbEIsMEJBQWUsSUFBSSxDQUFDLElBQUksQ0FBQzs7Ozs7OztLQUNoQzs7Ozs7Ozs7V0FNVzs7OztBQUNWLGdDQUFJLElBQUkseUJBQXVCLElBQUksQ0FBQyxJQUFJLENBQUcsQ0FBQzs7NkNBQ3RDLDZCQUFZLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDOzs7Ozs7O0tBQ3BDOzs7U0EzR0csZUFBZTs7O3FCQThHTixlQUFlIiwiZmlsZSI6ImxpYi9zaW11bGF0b3IteGNvZGUtOS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBTaW11bGF0b3JYY29kZTggZnJvbSAnLi9zaW11bGF0b3IteGNvZGUtOCc7XG5pbXBvcnQgQXN5bmNMb2NrIGZyb20gJ2FzeW5jLWxvY2snO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgeyBzaHV0ZG93biBhcyBzaW1jdGxTaHV0ZG93biwgYm9vdERldmljZSwgZXJhc2VEZXZpY2UgfSBmcm9tICdub2RlLXNpbWN0bCc7XG5pbXBvcnQgeyB3YWl0Rm9yQ29uZGl0aW9uIH0gZnJvbSAnYXN5bmNib3gnO1xuXG5cbmNvbnN0IFNJTVVMQVRPUl9TSFVURE9XTl9USU1FT1VUID0gMTUgKiAxMDAwO1xuY29uc3Qgc3RhcnR1cExvY2sgPSBuZXcgQXN5bmNMb2NrKCk7XG5cbmNsYXNzIFNpbXVsYXRvclhjb2RlOSBleHRlbmRzIFNpbXVsYXRvclhjb2RlOCB7XG4gIGNvbnN0cnVjdG9yICh1ZGlkLCB4Y29kZVZlcnNpb24pIHtcbiAgICBzdXBlcih1ZGlkLCB4Y29kZVZlcnNpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGVzIGdpdmVuIFNpbXVsYXRvciB3aXRoIG9wdGlvbnMuIFRoZSBTaW11bGF0b3Igd2lsbCBub3QgYmUgcmVzdGFydGVkIGlmXG4gICAqIGl0IGlzIGFscmVhZHkgcnVubmluZyBhbmQgdGhlIGN1cnJlbnQgVUkgc3RhdGUgbWF0Y2hlcyB0byBgaXNIZWFkbGVzc2Agb3B0aW9uLlxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG9wdHMgLSBPbmUgb3IgbW9yZSBvZiBhdmFpbGFibGUgU2ltdWxhdG9yIG9wdGlvbnM6XG4gICAqICAgLSB7c3RyaW5nfSBzY2FsZUZhY3RvcjogY2FuIGJlIG9uZSBvZiBbJzEuMCcsICcwLjc1JywgJzAuNScsICcwLjMzJywgJzAuMjUnXS5cbiAgICogICBEZWZpbmVzIHRoZSB3aW5kb3cgc2NhbGUgdmFsdWUgZm9yIHRoZSBVSSBjbGllbnQgd2luZG93IGZvciB0aGUgY3VycmVudCBTaW11bGF0b3IuXG4gICAqICAgRXF1YWxzIHRvIG51bGwgYnkgZGVmYXVsdCwgd2hpY2gga2VlcHMgdGhlIGN1cnJlbnQgc2NhbGUgdW5jaGFuZ2VkLlxuICAgKiAgIC0ge2Jvb2xlYW59IGNvbm5lY3RIYXJkd2FyZUtleWJvYXJkOiB3aGV0aGVyIHRvIGNvbm5lY3QgdGhlIGhhcmR3YXJlIGtleWJvYXJkIHRvIHRoZVxuICAgKiAgIFNpbXVsYXRvciBVSSBjbGllbnQuIEVxdWFscyB0byBmYWxzZSBieSBkZWZhdWx0LlxuICAgKiAgIC0ge251bWJlcn0gc3RhcnR1cFRpbWVvdXQ6IG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gd2FpdCB1bnRpbCBTaW11bGF0b3IgYm9vdGluZ1xuICAgKiAgIHByb2Nlc3MgaXMgY29tcGxldGVkLiBUaGUgZGVmYXVsdCB0aW1lb3V0IHdpbGwgYmUgdXNlZCBpZiBub3Qgc2V0IGV4cGxpY2l0bHkuXG4gICAqICAgLSB7Ym9vbGVhbn0gaXNIZWFkbGVzczogd2hldGhlciB0byBzdGFydCB0aGUgU2ltdWxhdG9yIGluIGhlYWRsZXNzIG1vZGUgKHdpdGggVUlcbiAgICogICBjbGllbnQgaW52aXNpYmxlKS4gYGZhbHNlYCBieSBkZWZhdWx0LlxuICAgKi9cbiAgYXN5bmMgcnVuIChvcHRzID0ge30pIHtcbiAgICBvcHRzID0gT2JqZWN0LmFzc2lnbih7XG4gICAgICBpc0hlYWRsZXNzOiBmYWxzZSxcbiAgICAgIHN0YXJ0dXBUaW1lb3V0OiB0aGlzLnN0YXJ0dXBUaW1lb3V0LFxuICAgIH0sIG9wdHMpO1xuICAgIGNvbnN0IGJvb3RTaW11bGF0b3IgPSBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBib290RGV2aWNlKHRoaXMudWRpZCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nLndhcm4oYCd4Y3J1biBzaW1jdGwgYm9vdCAke3RoaXMudWRpZH0nIGNvbW1hbmQgaGFzIHJldHVybmVkIG5vbi16ZXJvIGNvZGUuIFRoZSBwcm9ibGVtIHdhczogJHtlcnIuc3RkZXJyfWApO1xuICAgICAgfVxuICAgIH07XG4gICAgY29uc3Qgd2FpdEZvclNodXRkb3duID0gYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHtzdGF0ZX0gPSBhd2FpdCB0aGlzLnN0YXQoKTtcbiAgICAgICAgcmV0dXJuIHN0YXRlID09PSAnU2h1dGRvd24nO1xuICAgICAgfSwge3dhaXRNczogU0lNVUxBVE9SX1NIVVRET1dOX1RJTUVPVVQsIGludGVydmFsTXM6IDUwMH0pO1xuICAgIH07XG4gICAgbGV0IHNob3VsZFdhaXRGb3JCb290ID0gdHJ1ZTtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBwcm9jZXNzLmhydGltZSgpO1xuICAgIGF3YWl0IHN0YXJ0dXBMb2NrLmFjcXVpcmUodGhpcy51aUNsaWVudEJ1bmRsZUlkLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzdGF0ID0gYXdhaXQgdGhpcy5zdGF0KCk7XG4gICAgICBjb25zdCBzZXJ2ZXJTdGF0ZSA9IHN0YXQuc3RhdGU7XG4gICAgICBjb25zdCBpc1NlcnZlclJ1bm5pbmcgPSBzZXJ2ZXJTdGF0ZSA9PT0gJ0Jvb3RlZCc7XG4gICAgICBjb25zdCBpc1VJQ2xpZW50UnVubmluZyA9IGF3YWl0IHRoaXMuaXNVSUNsaWVudFJ1bm5pbmcoKTtcbiAgICAgIGlmIChvcHRzLmlzSGVhZGxlc3MpIHtcbiAgICAgICAgaWYgKGlzU2VydmVyUnVubmluZyAmJiAhaXNVSUNsaWVudFJ1bm5pbmcpIHtcbiAgICAgICAgICBsb2cuaW5mbyhgU2ltdWxhdG9yIHdpdGggVURJRCAke3RoaXMudWRpZH0gYWxyZWFkeSBib290ZWQgaW4gaGVhZGxlc3MgbW9kZS5gKTtcbiAgICAgICAgICBzaG91bGRXYWl0Rm9yQm9vdCA9IGZhbHNlO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXdhaXQgdGhpcy5raWxsVUlDbGllbnQoKSkge1xuICAgICAgICAgIC8vIFN0b3BwaW5nIHRoZSBVSSBjbGllbnQgYWxzbyBraWxscyBhbGwgcnVubmluZyBzZXJ2ZXJzLiBTYWQgYnV0IHRydWVcbiAgICAgICAgICBsb2cuaW5mbyhgRGV0ZWN0ZWQgdGhlIFVJIGNsaWVudCB3YXMgcnVubmluZyBhbmQga2lsbGVkIGl0LiBWZXJpZnlpbmcgdGhlIFNpbXVsYXRvciBpcyBpbiBTaHV0ZG93biBzdGF0ZS4uLmApO1xuICAgICAgICAgIGF3YWl0IHdhaXRGb3JTaHV0ZG93bigpO1xuICAgICAgICB9XG4gICAgICAgIGxvZy5pbmZvKGBCb290aW5nIFNpbXVsYXRvciB3aXRoIFVESUQgJHt0aGlzLnVkaWR9IGluIGhlYWRsZXNzIG1vZGUuIEFsbCBVSS1yZWxhdGVkIGNhcGFiaWxpdGllcyBhcmUgZ29pbmcgdG8gYmUgaWdub3JlZC5gKTtcbiAgICAgICAgYXdhaXQgYm9vdFNpbXVsYXRvcigpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGlzU2VydmVyUnVubmluZyAmJiBpc1VJQ2xpZW50UnVubmluZykge1xuICAgICAgICAgIGxvZy5pbmZvKGBCb3RoIFNpbXVsYXRvciB3aXRoIFVESUQgJHt0aGlzLnVkaWR9IGFuZCB0aGUgVUkgY2xpZW50IGFyZSBjdXJyZW50bHkgcnVubmluZ2ApO1xuICAgICAgICAgIHNob3VsZFdhaXRGb3JCb290ID0gZmFsc2U7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChbJ1NodXRkb3duJywgJ0Jvb3RlZCddLmluZGV4T2Yoc2VydmVyU3RhdGUpID09PSAtMSkge1xuICAgICAgICAgIGxvZy5pbmZvKGBTaW11bGF0b3IgJHt0aGlzLnVkaWR9IGlzIGluICcke3NlcnZlclN0YXRlfScgc3RhdGUuIFRyeWluZyB0byBzaHV0ZG93bi4uLmApO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNodXRkb3duKCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBsb2cud2FybihgRXJyb3Igb24gU2ltdWxhdG9yIHNodXRkb3duOiAke2Vyci5tZXNzYWdlfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCB3YWl0Rm9yU2h1dGRvd24oKTtcbiAgICAgICAgfVxuICAgICAgICBsb2cuaW5mbyhgQm9vdGluZyBTaW11bGF0b3Igd2l0aCBVRElEICR7dGhpcy51ZGlkfS4uLmApO1xuICAgICAgICBhd2FpdCBib290U2ltdWxhdG9yKCk7XG4gICAgICAgIGlmICghaXNVSUNsaWVudFJ1bm5pbmcpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnN0YXJ0VUlDbGllbnQob3B0cyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChzaG91bGRXYWl0Rm9yQm9vdCkge1xuICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yQm9vdChvcHRzLnN0YXJ0dXBUaW1lb3V0KTtcbiAgICAgIGxvZy5pbmZvKGBTaW11bGF0b3Igd2l0aCBVRElEICR7dGhpcy51ZGlkfSBib290ZWQgaW4gJHtwcm9jZXNzLmhydGltZShzdGFydFRpbWUpWzBdfSBzZWNvbmRzYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNodXQgZG93biB0aGUgY3VycmVudCBTaW11bGF0b3IuXG4gICAqIEBvdmVycmlkZVxuICAgKi9cbiAgYXN5bmMgc2h1dGRvd24gKCkge1xuICAgIGNvbnN0IHtzdGF0ZX0gPSBhd2FpdCB0aGlzLnN0YXQoKTtcbiAgICBpZiAoc3RhdGUgPT09ICdTaHV0ZG93bicpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgc2ltY3RsU2h1dGRvd24odGhpcy51ZGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgY3VycmVudCBTaW11bGF0b3IgdG8gdGhlIGNsZWFuIHN0YXRlLlxuICAgKiBAb3ZlcnJpZGVcbiAgICovXG4gIGFzeW5jIGNsZWFuICgpIHtcbiAgICBsb2cuaW5mbyhgQ2xlYW5pbmcgc2ltdWxhdG9yICR7dGhpcy51ZGlkfWApO1xuICAgIGF3YWl0IGVyYXNlRGV2aWNlKHRoaXMudWRpZCwgMTAwMDApO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNpbXVsYXRvclhjb2RlOTtcbiJdLCJzb3VyY2VSb290IjoiLi4vLi4ifQ==