@appium/execute-driver-plugin 1.0.1 → 1.0.4
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.
- package/LICENSE +2 -2
- package/build/lib/execute-child.d.ts +3 -0
- package/build/lib/execute-child.d.ts.map +1 -0
- package/build/lib/execute-child.js +124 -114
- package/build/lib/plugin.d.ts +31 -0
- package/build/lib/plugin.d.ts.map +1 -0
- package/build/lib/plugin.js +125 -123
- package/build/tsconfig.tsbuildinfo +1 -1
- package/index.js +1 -3
- package/package.json +17 -13
- package/README.md +0 -65
- package/build/index.js +0 -10
- package/build/test/e2e/plugin-e2e-specs.js +0 -137
- package/build/test/unit/plugin-specs.js +0 -16
package/build/lib/plugin.js
CHANGED
|
@@ -1,132 +1,134 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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;
|
|
23
|
+
const DEFAULT_SCRIPT_TIMEOUT_MS = 1000 * 60 * 60;
|
|
14
24
|
const SCRIPT_TYPE_WDIO = 'webdriverio';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
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==
|