@appium/execute-driver-plugin 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,132 +1,134 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ExecuteDriverPlugin = void 0;
7
- const base_plugin_1 = __importDefault(require("@appium/base-plugin"));
8
- const lodash_1 = __importDefault(require("lodash"));
9
- const child_process_1 = __importDefault(require("child_process"));
10
- const support_1 = require("@appium/support");
11
- const bluebird_1 = __importDefault(require("bluebird"));
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = exports.ExecuteDriverPlugin = void 0;
9
+
10
+ require("source-map-support/register");
11
+
12
+ var _basePlugin = _interopRequireDefault(require("@appium/base-plugin"));
13
+
14
+ var _lodash = _interopRequireDefault(require("lodash"));
15
+
16
+ var _child_process = _interopRequireDefault(require("child_process"));
17
+
18
+ var _support = require("@appium/support");
19
+
20
+ var _bluebird = _interopRequireDefault(require("bluebird"));
21
+
12
22
  const FEAT_FLAG = 'execute_driver_script';
13
- const DEFAULT_SCRIPT_TIMEOUT_MS = 1000 * 60 * 60; // default to 1 hour timeout
23
+ const DEFAULT_SCRIPT_TIMEOUT_MS = 1000 * 60 * 60;
14
24
  const SCRIPT_TYPE_WDIO = 'webdriverio';
15
- class ExecuteDriverPlugin extends base_plugin_1.default {
16
- /**
17
- * This method takes a string which is executed as javascript in the context of
18
- * a new nodejs VM, and which has available a webdriverio driver object, having
19
- * already been attached to the currently running session.
20
- *
21
- * @param {function} next - standard behaviour for executeDriverScript
22
- * @param {BaseDriver} driver - Appium driver handling this command
23
- * @param {string} script - the string representing the driver script to run
24
- * @param {string} [scriptType='webdriverio'] - the name of the driver script
25
- * library (currently only webdriverio is supported)
26
- * @param {number} [timeoutMs=3600000] - timeout for the script process
27
- *
28
- * @returns {Object} - a JSONifiable object representing the return value of
29
- * the script
30
- */
31
- async executeDriverScript(next, driver, script, scriptType = 'webdriverio', timeoutMs = DEFAULT_SCRIPT_TIMEOUT_MS) {
32
- if (!driver.isFeatureEnabled(FEAT_FLAG)) {
33
- throw new Error(`Execute driver script functionality is not available ` +
34
- `unless server is started with --allow-insecure including ` +
35
- `the '${FEAT_FLAG}' flag, e.g., --allow-insecure=${FEAT_FLAG}`);
36
- }
37
- if (scriptType !== SCRIPT_TYPE_WDIO) {
38
- throw new TypeError(`Only the '${SCRIPT_TYPE_WDIO}' script type is currently supported`);
39
- }
40
- if (!driver.serverHost || !driver.serverPort) {
41
- throw new Error('Address or port of running server were not defined; this ' +
42
- 'is required. This is probably a programming error in the driver');
43
- }
44
- if (!lodash_1.default.isNumber(timeoutMs)) {
45
- throw new TypeError('Timeout parameter must be a number');
25
+
26
+ class ExecuteDriverPlugin extends _basePlugin.default {
27
+ static newMethodMap = {
28
+ '/session/:sessionId/appium/execute_driver': {
29
+ POST: {
30
+ command: 'executeDriverScript',
31
+ payloadParams: {
32
+ required: ['script'],
33
+ optional: ['type', 'timeout']
46
34
  }
47
- const driverOpts = {
48
- sessionId: driver.sessionId,
49
- // Appium probably won't be behind ssl locally; if it ever is, might need to update this to
50
- // provide a user configurable parameter
51
- protocol: 'http',
52
- hostname: driver.serverHost,
53
- port: driver.serverPort,
54
- path: driver.serverPath,
55
- isW3C: true,
56
- isMobile: true,
57
- capabilities: driver.caps
58
- };
59
- this.logger.info(`Constructed webdriverio driver options; W3C mode is ${driverOpts.isW3C ? 'on' : 'off'}`);
60
- // fork the execution script as a child process
61
- const childScript = require.resolve('./execute-child.js');
62
- this.logger.info(`Forking process to run webdriver script as child using ${childScript}`);
63
- const scriptProc = child_process_1.default.fork(childScript);
64
- // keep track of whether we have canceled the script timeout, so we can stop
65
- // waiting for it and allow this process to finish gracefully
66
- let timeoutCanceled = false;
67
- try {
68
- const timer = new support_1.timing.Timer();
69
- timer.start();
70
- // promise that deals with the result from the child process
71
- const waitForResult = async () => {
72
- const res = await new bluebird_1.default((res) => {
73
- scriptProc.on('message', res); // this is node IPC
74
- });
75
- this.logger.info('Received execute driver script result from child process, shutting it down');
76
- if (res.error) {
77
- throw new Error(res.error.message);
78
- }
79
- return res.success;
80
- };
81
- // promise that waits up to the timeout and throws an error if so, or does
82
- // nothing if the timeout is canceled because we got a result from the
83
- // child script
84
- const waitForTimeout = async () => {
85
- while (!timeoutCanceled && timer.getDuration().asMilliSeconds < timeoutMs) {
86
- await bluebird_1.default.delay(500);
87
- }
88
- if (timeoutCanceled) {
89
- return;
90
- }
91
- throw new Error(`Execute driver script timed out after ${timeoutMs}ms. ` +
92
- `You can adjust this with the 'timeout' parameter.`);
93
- };
94
- // now that the child script is alive, send it the data it needs to start
95
- // running the driver script
96
- this.logger.info('Sending driver and script data to child');
97
- scriptProc.send({ driverOpts, script, timeoutMs });
98
- // and set up a race between the response from the child and the timeout
99
- return await bluebird_1.default.race([waitForResult(), waitForTimeout()]);
35
+ }
36
+ }
37
+ };
38
+
39
+ async executeDriverScript(next, driver, script, scriptType = 'webdriverio', timeoutMs = DEFAULT_SCRIPT_TIMEOUT_MS) {
40
+ if (!driver.isFeatureEnabled(FEAT_FLAG)) {
41
+ throw new Error(`Execute driver script functionality is not available ` + `unless server is started with --allow-insecure including ` + `the '${FEAT_FLAG}' flag, e.g., --allow-insecure=${FEAT_FLAG}`);
42
+ }
43
+
44
+ if (scriptType !== SCRIPT_TYPE_WDIO) {
45
+ throw new TypeError(`Only the '${SCRIPT_TYPE_WDIO}' script type is currently supported`);
46
+ }
47
+
48
+ if (!driver.serverHost || !driver.serverPort) {
49
+ throw new Error('Address or port of running server were not defined; this ' + 'is required. This is probably a programming error in the driver');
50
+ }
51
+
52
+ if (!_lodash.default.isNumber(timeoutMs)) {
53
+ throw new TypeError('Timeout parameter must be a number');
54
+ }
55
+
56
+ const driverOpts = {
57
+ sessionId: driver.sessionId,
58
+ protocol: 'http',
59
+ hostname: driver.serverHost,
60
+ port: driver.serverPort,
61
+ path: driver.serverPath,
62
+ isW3C: true,
63
+ isMobile: true,
64
+ capabilities: driver.caps
65
+ };
66
+ this.logger.info(`Constructed webdriverio driver options; W3C mode is ${driverOpts.isW3C ? 'on' : 'off'}`);
67
+
68
+ const childScript = require.resolve('./execute-child.js');
69
+
70
+ this.logger.info(`Forking process to run webdriver script as child using ${childScript}`);
71
+
72
+ const scriptProc = _child_process.default.fork(childScript);
73
+
74
+ let timeoutCanceled = false;
75
+
76
+ try {
77
+ const timer = new _support.timing.Timer();
78
+ timer.start();
79
+
80
+ const waitForResult = async () => {
81
+ const res = await new _bluebird.default(res => {
82
+ scriptProc.on('message', res);
83
+ });
84
+ this.logger.info('Received execute driver script result from child process, shutting it down');
85
+
86
+ if (res.error) {
87
+ throw new Error(res.error.message);
100
88
  }
101
- catch (err) {
102
- throw new Error(`Could not execute driver script. Original error was: ${err}`);
89
+
90
+ return res.success;
91
+ };
92
+
93
+ const waitForTimeout = async () => {
94
+ while (!timeoutCanceled && timer.getDuration().asMilliSeconds < timeoutMs) {
95
+ await _bluebird.default.delay(500);
103
96
  }
104
- finally {
105
- // ensure we always cancel the timeout so that the timeout promise stops
106
- // spinning and allows this process to die gracefully
107
- timeoutCanceled = true;
108
- if (scriptProc.connected) {
109
- this.logger.info('Disconnecting from child proc');
110
- scriptProc.disconnect();
111
- }
112
- if (scriptProc.exitCode === null) {
113
- this.logger.info('Disconnecting from and killing driver script child proc');
114
- scriptProc.kill();
115
- }
116
- else {
117
- this.logger.info('Script already ended on its own, no need to kill it');
118
- }
97
+
98
+ if (timeoutCanceled) {
99
+ return;
119
100
  }
101
+
102
+ throw new Error(`Execute driver script timed out after ${timeoutMs}ms. ` + `You can adjust this with the 'timeout' parameter.`);
103
+ };
104
+
105
+ this.logger.info('Sending driver and script data to child');
106
+ scriptProc.send({
107
+ driverOpts,
108
+ script,
109
+ timeoutMs
110
+ });
111
+ return await _bluebird.default.race([waitForResult(), waitForTimeout()]);
112
+ } catch (err) {
113
+ throw new Error(`Could not execute driver script. Original error was: ${err}`);
114
+ } finally {
115
+ timeoutCanceled = true;
116
+
117
+ if (scriptProc.connected) {
118
+ this.logger.info('Disconnecting from child proc');
119
+ scriptProc.disconnect();
120
+ }
121
+
122
+ if (scriptProc.exitCode === null) {
123
+ this.logger.info('Disconnecting from and killing driver script child proc');
124
+ scriptProc.kill();
125
+ } else {
126
+ this.logger.info('Script already ended on its own, no need to kill it');
127
+ }
120
128
  }
129
+ }
130
+
121
131
  }
122
- exports.default = ExecuteDriverPlugin;
123
- exports.ExecuteDriverPlugin = ExecuteDriverPlugin;
124
- ExecuteDriverPlugin.newMethodMap = {
125
- '/session/:sessionId/appium/execute_driver': {
126
- POST: {
127
- command: 'executeDriverScript',
128
- payloadParams: { required: ['script'], optional: ['type', 'timeout'] }
129
- }
130
- }
131
- };
132
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vbGliL3BsdWdpbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxzRUFBNkM7QUFDN0Msb0RBQXVCO0FBQ3ZCLGtFQUErQjtBQUMvQiw2Q0FBeUM7QUFDekMsd0RBQXlCO0FBRXpCLE1BQU0sU0FBUyxHQUFHLHVCQUF1QixDQUFDO0FBQzFDLE1BQU0seUJBQXlCLEdBQUcsSUFBSSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyw0QkFBNEI7QUFDOUUsTUFBTSxnQkFBZ0IsR0FBRyxhQUFhLENBQUM7QUFFdkMsTUFBcUIsbUJBQW9CLFNBQVEscUJBQVU7SUFXekQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDSCxLQUFLLENBQUMsbUJBQW1CLENBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxHQUFHLGFBQWEsRUFDekUsU0FBUyxHQUFHLHlCQUF5QjtRQUVyQyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVEO2dCQUN2RCwyREFBMkQ7Z0JBQzNELFFBQVEsU0FBUyxrQ0FBa0MsU0FBUyxFQUFFLENBQUMsQ0FBQztTQUNqRjtRQUVELElBQUksVUFBVSxLQUFLLGdCQUFnQixFQUFFO1lBQ25DLE1BQU0sSUFBSSxTQUFTLENBQUMsYUFBYSxnQkFBZ0Isc0NBQXNDLENBQUMsQ0FBQztTQUMxRjtRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUM1QyxNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRDtnQkFDM0QsaUVBQWlFLENBQUMsQ0FBQztTQUNwRjtRQUVELElBQUksQ0FBQyxnQkFBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUMxQixNQUFNLElBQUksU0FBUyxDQUFDLG9D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
132
+
133
+ exports.ExecuteDriverPlugin = exports.default = ExecuteDriverPlugin;
134
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9wbHVnaW4uanMiXSwibmFtZXMiOlsiRkVBVF9GTEFHIiwiREVGQVVMVF9TQ1JJUFRfVElNRU9VVF9NUyIsIlNDUklQVF9UWVBFX1dESU8iLCJFeGVjdXRlRHJpdmVyUGx1Z2luIiwiQmFzZVBsdWdpbiIsIm5ld01ldGhvZE1hcCIsIlBPU1QiLCJjb21tYW5kIiwicGF5bG9hZFBhcmFtcyIsInJlcXVpcmVkIiwib3B0aW9uYWwiLCJleGVjdXRlRHJpdmVyU2NyaXB0IiwibmV4dCIsImRyaXZlciIsInNjcmlwdCIsInNjcmlwdFR5cGUiLCJ0aW1lb3V0TXMiLCJpc0ZlYXR1cmVFbmFibGVkIiwiRXJyb3IiLCJUeXBlRXJyb3IiLCJzZXJ2ZXJIb3N0Iiwic2VydmVyUG9ydCIsIl8iLCJpc051bWJlciIsImRyaXZlck9wdHMiLCJzZXNzaW9uSWQiLCJwcm90b2NvbCIsImhvc3RuYW1lIiwicG9ydCIsInBhdGgiLCJzZXJ2ZXJQYXRoIiwiaXNXM0MiLCJpc01vYmlsZSIsImNhcGFiaWxpdGllcyIsImNhcHMiLCJsb2dnZXIiLCJpbmZvIiwiY2hpbGRTY3JpcHQiLCJyZXF1aXJlIiwicmVzb2x2ZSIsInNjcmlwdFByb2MiLCJjcCIsImZvcmsiLCJ0aW1lb3V0Q2FuY2VsZWQiLCJ0aW1lciIsInRpbWluZyIsIlRpbWVyIiwic3RhcnQiLCJ3YWl0Rm9yUmVzdWx0IiwicmVzIiwiQiIsIm9uIiwiZXJyb3IiLCJtZXNzYWdlIiwic3VjY2VzcyIsIndhaXRGb3JUaW1lb3V0IiwiZ2V0RHVyYXRpb24iLCJhc01pbGxpU2Vjb25kcyIsImRlbGF5Iiwic2VuZCIsInJhY2UiLCJlcnIiLCJjb25uZWN0ZWQiLCJkaXNjb25uZWN0IiwiZXhpdENvZGUiLCJraWxsIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUVBLE1BQU1BLFNBQVMsR0FBRyx1QkFBbEI7QUFDQSxNQUFNQyx5QkFBeUIsR0FBRyxPQUFP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LElBQVg7QUFDRCxPQUhELE1BR087QUFDTCxhQUFLOUIsTUFBTCxDQUFZQyxJQUFaLENBQWlCLHFEQUFqQjtBQUNEO0FBQ0Y7QUFDRjs7QUFySXlEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEJhc2VQbHVnaW4gZnJvbSAnQGFwcGl1bS9iYXNlLXBsdWdpbic7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGNwIGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgdGltaW5nIH0gZnJvbSAnQGFwcGl1bS9zdXBwb3J0JztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcblxuY29uc3QgRkVBVF9GTEFHID0gJ2V4ZWN1dGVfZHJpdmVyX3NjcmlwdCc7XG5jb25zdCBERUZBVUxUX1NDUklQVF9USU1FT1VUX01TID0gMTAwMCAqIDYwICogNjA7IC8vIGRlZmF1bHQgdG8gMSBob3VyIHRpbWVvdXRcbmNvbnN0IFNDUklQVF9UWVBFX1dESU8gPSAnd2ViZHJpdmVyaW8nO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFeGVjdXRlRHJpdmVyUGx1Z2luIGV4dGVuZHMgQmFzZVBsdWdpbiB7XG5cbiAgc3RhdGljIG5ld01ldGhvZE1hcCA9IHtcbiAgICAnL3Nlc3Npb24vOnNlc3Npb25JZC9hcHBpdW0vZXhlY3V0ZV9kcml2ZXInOiB7XG4gICAgICBQT1NUOiB7XG4gICAgICAgIGNvbW1hbmQ6ICdleGVjdXRlRHJpdmVyU2NyaXB0JyxcbiAgICAgICAgcGF5bG9hZFBhcmFtczoge3JlcXVpcmVkOiBbJ3NjcmlwdCddLCBvcHRpb25hbDogWyd0eXBlJywgJ3RpbWVvdXQnXX1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHRha2VzIGEgc3RyaW5nIHdoaWNoIGlzIGV4ZWN1dGVkIGFzIGphdmFzY3JpcHQgaW4gdGhlIGNvbnRleHQgb2ZcbiAgICogYSBuZXcgbm9kZWpzIFZNLCBhbmQgd2hpY2ggaGFzIGF2YWlsYWJsZSBhIHdlYmRyaXZlcmlvIGRyaXZlciBvYmplY3QsIGhhdmluZ1xuICAgKiBhbHJlYWR5IGJlZW4gYXR0YWNoZWQgdG8gdGhlIGN1cnJlbnRseSBydW5uaW5nIHNlc3Npb24uXG4gICAqXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IG5leHQgLSBzdGFuZGFyZCBiZWhhdmlvdXIgZm9yIGV4ZWN1dGVEcml2ZXJTY3JpcHRcbiAgICogQHBhcmFtIHtCYXNlRHJpdmVyfSBkcml2ZXIgLSBBcHBpdW0gZHJpdmVyIGhhbmRsaW5nIHRoaXMgY29tbWFuZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2NyaXB0IC0gdGhlIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGRyaXZlciBzY3JpcHQgdG8gcnVuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbc2NyaXB0VHlwZT0nd2ViZHJpdmVyaW8nXSAtIHRoZSBuYW1lIG9mIHRoZSBkcml2ZXIgc2NyaXB0XG4gICAqIGxpYnJhcnkgKGN1cnJlbnRseSBvbmx5IHdlYmRyaXZlcmlvIGlzIHN1cHBvcnRlZClcbiAgICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lb3V0TXM9MzYwMDAwMF0gLSB0aW1lb3V0IGZvciB0aGUgc2NyaXB0IHByb2Nlc3NcbiAgICpcbiAgICogQHJldHVybnMge09iamVjdH0gLSBhIEpTT05pZmlhYmxlIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHJldHVybiB2YWx1ZSBvZlxuICAgKiB0aGUgc2NyaXB0XG4gICAqL1xuICBhc3luYyBleGVjdXRlRHJpdmVyU2NyaXB0IChuZXh0LCBkcml2ZXIsIHNjcmlwdCwgc2NyaXB0VHlwZSA9ICd3ZWJkcml2ZXJpbycsXG4gICAgdGltZW91dE1zID0gREVGQVVMVF9TQ1JJUFRfVElNRU9VVF9NUykge1xuXG4gICAgaWYgKCFkcml2ZXIuaXNGZWF0dXJlRW5hYmxlZChGRUFUX0ZMQUcpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4ZWN1dGUgZHJpdmVyIHNjcmlwdCBmdW5jdGlvbmFsaXR5IGlzIG5vdCBhdmFpbGFibGUgYCArXG4gICAgICAgICAgICAgICAgICAgICAgYHVubGVzcyBzZXJ2ZXIgaXMgc3RhcnRlZCB3aXRoIC0tYWxsb3ctaW5zZWN1cmUgaW5jbHVkaW5nIGAgK1xuICAgICAgICAgICAgICAgICAgICAgIGB0aGUgJyR7RkVBVF9GTEFHfScgZmxhZywgZS5nLiwgLS1hbGxvdy1pbnNlY3VyZT0ke0ZFQVRfRkxBR31gKTtcbiAgICB9XG5cbiAgICBpZiAoc2NyaXB0VHlwZSAhPT0gU0NSSVBUX1RZUEVfV0RJTykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgT25seSB0aGUgJyR7U0NSSVBUX1RZUEVfV0RJT30nIHNjcmlwdCB0eXBlIGlzIGN1cnJlbnRseSBzdXBwb3J0ZWRgKTtcbiAgICB9XG5cbiAgICBpZiAoIWRyaXZlci5zZXJ2ZXJIb3N0IHx8ICFkcml2ZXIuc2VydmVyUG9ydCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBZGRyZXNzIG9yIHBvcnQgb2YgcnVubmluZyBzZXJ2ZXIgd2VyZSBub3QgZGVmaW5lZDsgdGhpcyAnICtcbiAgICAgICAgICAgICAgICAgICAgICAnaXMgcmVxdWlyZWQuIFRoaXMgaXMgcHJvYmFibHkgYSBwcm9ncmFtbWluZyBlcnJvciBpbiB0aGUgZHJpdmVyJyk7XG4gICAgfVxuXG4gICAgaWYgKCFfLmlzTnVtYmVyKHRpbWVvdXRNcykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RpbWVvdXQgcGFyYW1ldGVyIG11c3QgYmUgYSBudW1iZXInKTtcbiAgICB9XG5cbiAgICBjb25zdCBkcml2ZXJPcHRzID0ge1xuICAgICAgc2Vzc2lvbklkOiBkcml2ZXIuc2Vzc2lvbklkLFxuICAgICAgLy8gQXBwaXVtIHByb2JhYmx5IHdvbid0IGJlIGJlaGluZCBzc2wgbG9jYWxseTsgaWYgaXQgZXZlciBpcywgbWlnaHQgbmVlZCB0byB1cGRhdGUgdGhpcyB0b1xuICAgICAgLy8gcHJvdmlkZSBhIHVzZXIgY29uZmlndXJhYmxlIHBhcmFtZXRlclxuICAgICAgcHJvdG9jb2w6ICdodHRwJyxcbiAgICAgIGhvc3RuYW1lOiBkcml2ZXIuc2VydmVySG9zdCxcbiAgICAgIHBvcnQ6IGRyaXZlci5zZXJ2ZXJQb3J0LFxuICAgICAgcGF0aDogZHJpdmVyLnNlcnZlclBhdGgsXG4gICAgICBpc1czQzogdHJ1ZSxcbiAgICAgIGlzTW9iaWxlOiB0cnVlLFxuICAgICAgY2FwYWJpbGl0aWVzOiBkcml2ZXIuY2Fwc1xuICAgIH07XG4gICAgdGhpcy5sb2dnZXIuaW5mbyhgQ29uc3RydWN0ZWQgd2ViZHJpdmVyaW8gZHJpdmVyIG9wdGlvbnM7IFczQyBtb2RlIGlzICR7ZHJpdmVyT3B0cy5pc1czQyA/ICdvbicgOiAnb2ZmJ31gKTtcblxuXG4gICAgLy8gZm9yayB0aGUgZXhlY3V0aW9uIHNjcmlwdCBhcyBhIGNoaWxkIHByb2Nlc3NcbiAgICBjb25zdCBjaGlsZFNjcmlwdCA9IHJlcXVpcmUucmVzb2x2ZSgnLi9leGVjdXRlLWNoaWxkLmpzJyk7XG4gICAgdGhpcy5sb2dnZXIuaW5mbyhgRm9ya2luZyBwcm9jZXNzIHRvIHJ1biB3ZWJkcml2ZXIgc2NyaXB0IGFzIGNoaWxkIHVzaW5nICR7Y2hpbGRTY3JpcHR9YCk7XG4gICAgY29uc3Qgc2NyaXB0UHJvYyA9IGNwLmZvcmsoY2hpbGRTY3JpcHQpO1xuXG4gICAgLy8ga2VlcCB0cmFjayBvZiB3aGV0aGVyIHdlIGhhdmUgY2FuY2VsZWQgdGhlIHNjcmlwdCB0aW1lb3V0LCBzbyB3ZSBjYW4gc3RvcFxuICAgIC8vIHdhaXRpbmcgZm9yIGl0IGFuZCBhbGxvdyB0aGlzIHByb2Nlc3MgdG8gZmluaXNoIGdyYWNlZnVsbHlcbiAgICBsZXQgdGltZW91dENhbmNlbGVkID0gZmFsc2U7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdGltZXIgPSBuZXcgdGltaW5nLlRpbWVyKCk7XG4gICAgICB0aW1lci5zdGFydCgpO1xuXG4gICAgICAvLyBwcm9taXNlIHRoYXQgZGVhbHMgd2l0aCB0aGUgcmVzdWx0IGZyb20gdGhlIGNoaWxkIHByb2Nlc3NcbiAgICAgIGNvbnN0IHdhaXRGb3JSZXN1bHQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IG5ldyBCKChyZXMpID0+IHtcbiAgICAgICAgICBzY3JpcHRQcm9jLm9uKCdtZXNzYWdlJywgcmVzKTsgLy8gdGhpcyBpcyBub2RlIElQQ1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKCdSZWNlaXZlZCBleGVjdXRlIGRyaXZlciBzY3JpcHQgcmVzdWx0IGZyb20gY2hpbGQgcHJvY2Vzcywgc2h1dHRpbmcgaXQgZG93bicpO1xuXG4gICAgICAgIGlmIChyZXMuZXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IocmVzLmVycm9yLm1lc3NhZ2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlcy5zdWNjZXNzO1xuICAgICAgfTtcblxuICAgICAgLy8gcHJvbWlzZSB0aGF0IHdhaXRzIHVwIHRvIHRoZSB0aW1lb3V0IGFuZCB0aHJvd3MgYW4gZXJyb3IgaWYgc28sIG9yIGRvZXNcbiAgICAgIC8vIG5vdGhpbmcgaWYgdGhlIHRpbWVvdXQgaXMgY2FuY2VsZWQgYmVjYXVzZSB3ZSBnb3QgYSByZXN1bHQgZnJvbSB0aGVcbiAgICAgIC8vIGNoaWxkIHNjcmlwdFxuICAgICAgY29uc3Qgd2FpdEZvclRpbWVvdXQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgIHdoaWxlICghdGltZW91dENhbmNlbGVkICYmIHRpbWVyLmdldER1cmF0aW9uKCkuYXNNaWxsaVNlY29uZHMgPCB0aW1lb3V0TXMpIHtcbiAgICAgICAgICBhd2FpdCBCLmRlbGF5KDUwMCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGltZW91dENhbmNlbGVkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeGVjdXRlIGRyaXZlciBzY3JpcHQgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dE1zfW1zLiBgICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGBZb3UgY2FuIGFkanVzdCB0aGlzIHdpdGggdGhlICd0aW1lb3V0JyBwYXJhbWV0ZXIuYCk7XG4gICAgICB9O1xuXG4gICAgICAvLyBub3cgdGhhdCB0aGUgY2hpbGQgc2NyaXB0IGlzIGFsaXZlLCBzZW5kIGl0IHRoZSBkYXRhIGl0IG5lZWRzIHRvIHN0YXJ0XG4gICAgICAvLyBydW5uaW5nIHRoZSBkcml2ZXIgc2NyaXB0XG4gICAgICB0aGlzLmxvZ2dlci5pbmZvKCdTZW5kaW5nIGRyaXZlciBhbmQgc2NyaXB0IGRhdGEgdG8gY2hpbGQnKTtcbiAgICAgIHNjcmlwdFByb2Muc2VuZCh7ZHJpdmVyT3B0cywgc2NyaXB0LCB0aW1lb3V0TXN9KTtcblxuICAgICAgLy8gYW5kIHNldCB1cCBhIHJhY2UgYmV0d2VlbiB0aGUgcmVzcG9uc2UgZnJvbSB0aGUgY2hpbGQgYW5kIHRoZSB0aW1lb3V0XG4gICAgICByZXR1cm4gYXdhaXQgQi5yYWNlKFt3YWl0Rm9yUmVzdWx0KCksIHdhaXRGb3JUaW1lb3V0KCldKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGV4ZWN1dGUgZHJpdmVyIHNjcmlwdC4gT3JpZ2luYWwgZXJyb3Igd2FzOiAke2Vycn1gKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gZW5zdXJlIHdlIGFsd2F5cyBjYW5jZWwgdGhlIHRpbWVvdXQgc28gdGhhdCB0aGUgdGltZW91dCBwcm9taXNlIHN0b3BzXG4gICAgICAvLyBzcGlubmluZyBhbmQgYWxsb3dzIHRoaXMgcHJvY2VzcyB0byBkaWUgZ3JhY2VmdWxseVxuICAgICAgdGltZW91dENhbmNlbGVkID0gdHJ1ZTtcblxuICAgICAgaWYgKHNjcmlwdFByb2MuY29ubmVjdGVkKSB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmluZm8oJ0Rpc2Nvbm5lY3RpbmcgZnJvbSBjaGlsZCBwcm9jJyk7XG4gICAgICAgIHNjcmlwdFByb2MuZGlzY29ubmVjdCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NyaXB0UHJvYy5leGl0Q29kZSA9PT0gbnVsbCkge1xuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKCdEaXNjb25uZWN0aW5nIGZyb20gYW5kIGtpbGxpbmcgZHJpdmVyIHNjcmlwdCBjaGlsZCBwcm9jJyk7XG4gICAgICAgIHNjcmlwdFByb2Mua2lsbCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuaW5mbygnU2NyaXB0IGFscmVhZHkgZW5kZWQgb24gaXRzIG93biwgbm8gbmVlZCB0byBraWxsIGl0Jyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCB7IEV4ZWN1dGVEcml2ZXJQbHVnaW4gfTtcbiJdfQ==