appium-remote-debugger 10.0.2 → 10.1.0
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/CHANGELOG.md +14 -0
- package/build/index.js +18 -33
- package/build/lib/atoms.d.ts +17 -0
- package/build/lib/atoms.d.ts.map +1 -0
- package/build/lib/atoms.js +75 -50
- package/build/lib/atoms.js.map +1 -1
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +5 -11
- package/build/lib/logger.js.map +1 -1
- package/build/lib/mixins/connect.d.ts +125 -0
- package/build/lib/mixins/connect.d.ts.map +1 -0
- package/build/lib/mixins/connect.js +299 -202
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/events.d.ts +7 -0
- package/build/lib/mixins/events.d.ts.map +1 -0
- package/build/lib/mixins/events.js +7 -12
- package/build/lib/mixins/events.js.map +1 -1
- package/build/lib/mixins/execute.d.ts +38 -0
- package/build/lib/mixins/execute.d.ts.map +1 -0
- package/build/lib/mixins/execute.js +162 -122
- package/build/lib/mixins/execute.js.map +1 -1
- package/build/lib/mixins/index.d.ts +5 -0
- package/build/lib/mixins/index.d.ts.map +1 -0
- package/build/lib/mixins/index.js +14 -23
- package/build/lib/mixins/index.js.map +1 -1
- package/build/lib/mixins/message-handlers.d.ts +92 -0
- package/build/lib/mixins/message-handlers.d.ts.map +1 -0
- package/build/lib/mixins/message-handlers.js +160 -97
- package/build/lib/mixins/message-handlers.js.map +1 -1
- package/build/lib/mixins/navigate.d.ts +92 -0
- package/build/lib/mixins/navigate.d.ts.map +1 -0
- package/build/lib/mixins/navigate.js +199 -141
- package/build/lib/mixins/navigate.js.map +1 -1
- package/build/lib/protocol/index.d.ts +14 -0
- package/build/lib/protocol/index.d.ts.map +1 -0
- package/build/lib/protocol/index.js +192 -118
- package/build/lib/protocol/index.js.map +1 -1
- package/build/lib/remote-debugger-real-device.d.ts +6 -0
- package/build/lib/remote-debugger-real-device.d.ts.map +1 -0
- package/build/lib/remote-debugger-real-device.js +29 -32
- package/build/lib/remote-debugger-real-device.js.map +1 -1
- package/build/lib/remote-debugger.d.ts +119 -0
- package/build/lib/remote-debugger.d.ts.map +1 -0
- package/build/lib/remote-debugger.js +256 -226
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/lib/rpc/index.d.ts +4 -0
- package/build/lib/rpc/index.d.ts.map +1 -0
- package/build/lib/rpc/index.js +10 -21
- package/build/lib/rpc/index.js.map +1 -1
- package/build/lib/rpc/remote-messages.d.ts +51 -0
- package/build/lib/rpc/remote-messages.d.ts.map +1 -0
- package/build/lib/rpc/remote-messages.js +203 -224
- package/build/lib/rpc/remote-messages.js.map +1 -1
- package/build/lib/rpc/rpc-client-real-device.d.ts +6 -0
- package/build/lib/rpc/rpc-client-real-device.d.ts.map +1 -0
- package/build/lib/rpc/rpc-client-real-device.js +43 -49
- package/build/lib/rpc/rpc-client-real-device.js.map +1 -1
- package/build/lib/rpc/rpc-client-simulator.d.ts +15 -0
- package/build/lib/rpc/rpc-client-simulator.d.ts.map +1 -0
- package/build/lib/rpc/rpc-client-simulator.js +138 -125
- package/build/lib/rpc/rpc-client-simulator.js.map +1 -1
- package/build/lib/rpc/rpc-client.d.ts +142 -0
- package/build/lib/rpc/rpc-client.d.ts.map +1 -0
- package/build/lib/rpc/rpc-client.js +559 -418
- package/build/lib/rpc/rpc-client.js.map +1 -1
- package/build/lib/rpc/rpc-message-handler.d.ts +13 -0
- package/build/lib/rpc/rpc-message-handler.d.ts.map +1 -0
- package/build/lib/rpc/rpc-message-handler.js +181 -166
- package/build/lib/rpc/rpc-message-handler.js.map +1 -1
- package/build/lib/utils.d.ts +61 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +241 -155
- package/build/lib/utils.js.map +1 -1
- package/lib/atoms.js +25 -4
- package/lib/mixins/connect.js +102 -7
- package/lib/mixins/execute.js +46 -13
- package/lib/mixins/message-handlers.js +44 -1
- package/lib/mixins/navigate.js +55 -3
- package/lib/remote-debugger.js +112 -0
- package/lib/rpc/rpc-client-real-device.js +1 -6
- package/lib/rpc/rpc-client-simulator.js +7 -1
- package/lib/rpc/rpc-client.js +106 -6
- package/lib/rpc/rpc-message-handler.js +1 -1
- package/lib/utils.js +31 -1
- package/package.json +26 -16
|
@@ -1,453 +1,594 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.default = void 0;
|
|
8
|
-
require("source-map-support/register");
|
|
9
|
-
var _remoteMessages = _interopRequireDefault(require("./remote-messages"));
|
|
10
|
-
var _asyncbox = require("asyncbox");
|
|
11
|
-
var _logger = _interopRequireDefault(require("../logger"));
|
|
12
|
-
var _lodash = _interopRequireDefault(require("lodash"));
|
|
13
|
-
var _bluebird = _interopRequireDefault(require("bluebird"));
|
|
14
|
-
var _rpcMessageHandler = _interopRequireDefault(require("./rpc-message-handler"));
|
|
15
|
-
var _support = require("@appium/support");
|
|
16
|
-
const DATA_LOG_LENGTH = {
|
|
17
|
-
length: 200
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
4
|
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const remote_messages_1 = __importDefault(require("./remote-messages"));
|
|
7
|
+
const asyncbox_1 = require("asyncbox");
|
|
8
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
9
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
10
|
+
const bluebird_1 = __importDefault(require("bluebird"));
|
|
11
|
+
const rpc_message_handler_1 = __importDefault(require("./rpc-message-handler"));
|
|
12
|
+
const support_1 = require("@appium/support");
|
|
13
|
+
const DATA_LOG_LENGTH = { length: 200 };
|
|
19
14
|
const WAIT_FOR_TARGET_TIMEOUT = 10000;
|
|
20
15
|
const WAIT_FOR_TARGET_INTERVAL = 1000;
|
|
21
16
|
const MIN_PLATFORM_FOR_TARGET_BASED = '12.2';
|
|
17
|
+
// `Target.exists` protocol method was removed from WebKit in 13.4
|
|
22
18
|
const MIN_PLATFORM_NO_TARGET_EXISTS = '13.4';
|
|
23
19
|
function isTargetBased(isSafari, platformVersion) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
// On iOS 12.2 the messages get sent through the Target domain
|
|
21
|
+
// On iOS 13.0+, WKWebView also needs to follow the Target domain,
|
|
22
|
+
// so here only check the target OS version as the default behaviour.
|
|
23
|
+
const isHighVersion = support_1.util.compareVersions(platformVersion, '>=', MIN_PLATFORM_FOR_TARGET_BASED);
|
|
24
|
+
logger_1.default.debug(`Checking which communication style to use (${isSafari ? '' : 'non-'}Safari on platform version '${platformVersion}')`);
|
|
25
|
+
logger_1.default.debug(`Platform version equal or higher than '${MIN_PLATFORM_FOR_TARGET_BASED}': ${isHighVersion}`);
|
|
26
|
+
return isHighVersion;
|
|
28
27
|
}
|
|
29
28
|
class RpcClient {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.webInspectorMaxFrameLength = webInspectorMaxFrameLength;
|
|
52
|
-
this.fullPageInitialization = fullPageInitialization;
|
|
53
|
-
this.bundleId = bundleId;
|
|
54
|
-
this.platformVersion = platformVersion;
|
|
55
|
-
this._contexts = [];
|
|
56
|
-
this._targets = {};
|
|
57
|
-
this.isTargetBased = isTargetBased(isSafari, this.platformVersion);
|
|
58
|
-
}
|
|
59
|
-
get contexts() {
|
|
60
|
-
return this._contexts;
|
|
61
|
-
}
|
|
62
|
-
get needsTarget() {
|
|
63
|
-
return this.shouldCheckForTarget && this.isTargetBased;
|
|
64
|
-
}
|
|
65
|
-
get targets() {
|
|
66
|
-
return this._targets;
|
|
67
|
-
}
|
|
68
|
-
get shouldCheckForTarget() {
|
|
69
|
-
return this._shouldCheckForTarget;
|
|
70
|
-
}
|
|
71
|
-
set shouldCheckForTarget(shouldCheckForTarget) {
|
|
72
|
-
this._shouldCheckForTarget = !!shouldCheckForTarget;
|
|
73
|
-
}
|
|
74
|
-
get isConnected() {
|
|
75
|
-
return this.connected;
|
|
76
|
-
}
|
|
77
|
-
set isConnected(connected) {
|
|
78
|
-
this.connected = !!connected;
|
|
79
|
-
}
|
|
80
|
-
on(event, listener) {
|
|
81
|
-
this.messageHandler.on(event, listener);
|
|
82
|
-
return this;
|
|
83
|
-
}
|
|
84
|
-
once(event, listener) {
|
|
85
|
-
this.messageHandler.once(event, listener);
|
|
86
|
-
return this;
|
|
87
|
-
}
|
|
88
|
-
off(event, listener) {
|
|
89
|
-
this.messageHandler.off(event, listener);
|
|
90
|
-
return this;
|
|
91
|
-
}
|
|
92
|
-
set isTargetBased(isTargetBased) {
|
|
93
|
-
_logger.default.warn(`Setting communication protocol: using ${isTargetBased ? 'Target-based' : 'full Web Inspector protocol'} communication`);
|
|
94
|
-
this._isTargetBased = isTargetBased;
|
|
95
|
-
if (!this.remoteMessages) {
|
|
96
|
-
this.remoteMessages = new _remoteMessages.default(isTargetBased);
|
|
97
|
-
} else {
|
|
98
|
-
this.remoteMessages.isTargetBased = isTargetBased;
|
|
29
|
+
constructor(opts = {}) {
|
|
30
|
+
this._targets = [];
|
|
31
|
+
this._shouldCheckForTarget = !!opts.shouldCheckForTarget;
|
|
32
|
+
const { bundleId, platformVersion = {}, isSafari = true, logAllCommunication = false, logAllCommunicationHexDump = false, webInspectorMaxFrameLength, socketChunkSize, fullPageInitialization = false, udid, } = opts;
|
|
33
|
+
this.isSafari = isSafari;
|
|
34
|
+
this.isConnected = false;
|
|
35
|
+
this.connId = support_1.util.uuidV4();
|
|
36
|
+
this.senderId = support_1.util.uuidV4();
|
|
37
|
+
this.msgId = 0;
|
|
38
|
+
this.udid = udid;
|
|
39
|
+
this.logAllCommunication = logAllCommunication;
|
|
40
|
+
this.logAllCommunicationHexDump = logAllCommunicationHexDump;
|
|
41
|
+
this.socketChunkSize = socketChunkSize;
|
|
42
|
+
this.webInspectorMaxFrameLength = webInspectorMaxFrameLength;
|
|
43
|
+
this.fullPageInitialization = fullPageInitialization;
|
|
44
|
+
this.bundleId = bundleId;
|
|
45
|
+
this.platformVersion = platformVersion;
|
|
46
|
+
this._contexts = [];
|
|
47
|
+
this._targets = {};
|
|
48
|
+
// start with a best guess for the protocol
|
|
49
|
+
this.isTargetBased = isTargetBased(isSafari, this.platformVersion);
|
|
99
50
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
this.messageHandler.on('Target.targetCreated', this.addTarget.bind(this));
|
|
103
|
-
this.messageHandler.on('Target.didCommitProvisionalTarget', this.updateTarget.bind(this));
|
|
104
|
-
this.messageHandler.on('Target.targetDestroyed', this.removeTarget.bind(this));
|
|
105
|
-
this.messageHandler.on('Runtime.executionContextCreated', this.onExecutionContextCreated.bind(this));
|
|
106
|
-
this.messageHandler.on('Heap.garbageCollected', this.onGarbageCollected.bind(this));
|
|
107
|
-
} else {
|
|
108
|
-
this.messageHandler.isTargetBased = isTargetBased;
|
|
51
|
+
get contexts() {
|
|
52
|
+
return this._contexts;
|
|
109
53
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return this._isTargetBased;
|
|
113
|
-
}
|
|
114
|
-
async waitForTarget(appIdKey, pageIdKey, force = false) {
|
|
115
|
-
if (!force && !this.needsTarget) {
|
|
116
|
-
return;
|
|
54
|
+
get needsTarget() {
|
|
55
|
+
return this.shouldCheckForTarget && this.isTargetBased;
|
|
117
56
|
}
|
|
118
|
-
|
|
119
|
-
|
|
57
|
+
get targets() {
|
|
58
|
+
return this._targets;
|
|
120
59
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
waitMs: WAIT_FOR_TARGET_TIMEOUT,
|
|
124
|
-
intervalMs: WAIT_FOR_TARGET_INTERVAL,
|
|
125
|
-
error: 'No targets found, unable to communicate with device'
|
|
126
|
-
});
|
|
127
|
-
} catch (err) {
|
|
128
|
-
if (!err.message.includes('Condition unmet')) {
|
|
129
|
-
throw err;
|
|
130
|
-
}
|
|
131
|
-
throw new Error('No targets found, unable to communicate with device');
|
|
60
|
+
get shouldCheckForTarget() {
|
|
61
|
+
return this._shouldCheckForTarget;
|
|
132
62
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const timer = new _support.timing.Timer().start();
|
|
136
|
-
const {
|
|
137
|
-
appIdKey,
|
|
138
|
-
pageIdKey
|
|
139
|
-
} = opts;
|
|
140
|
-
try {
|
|
141
|
-
if (!_lodash.default.isEmpty(appIdKey) && !_lodash.default.isEmpty(pageIdKey)) {
|
|
142
|
-
await this.waitForTarget(appIdKey, pageIdKey);
|
|
143
|
-
}
|
|
144
|
-
return await this.sendToDevice(command, opts, waitForResponse);
|
|
145
|
-
} catch (err) {
|
|
146
|
-
let {
|
|
147
|
-
message = ''
|
|
148
|
-
} = err;
|
|
149
|
-
message = message.toLowerCase();
|
|
150
|
-
if (message.includes(`'target' domain was not found`)) {
|
|
151
|
-
_logger.default.info('The target device does not support Target based communication. ' + 'Will follow non-target based communication.');
|
|
152
|
-
this.isTargetBased = false;
|
|
153
|
-
return await this.sendToDevice(command, opts, waitForResponse);
|
|
154
|
-
} else if (message.includes(`domain was not found`) || message.includes(`some arguments of method`) || message.includes(`missing target`)) {
|
|
155
|
-
this.isTargetBased = true;
|
|
156
|
-
await this.waitForTarget(appIdKey, pageIdKey);
|
|
157
|
-
return await this.sendToDevice(command, opts, waitForResponse);
|
|
158
|
-
}
|
|
159
|
-
throw err;
|
|
160
|
-
} finally {
|
|
161
|
-
_logger.default.debug(`Sending to Web Inspector took ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
63
|
+
set shouldCheckForTarget(shouldCheckForTarget) {
|
|
64
|
+
this._shouldCheckForTarget = !!shouldCheckForTarget;
|
|
162
65
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
this.messageHandler.on(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
cmd.__argument.WIRSocketDataKey.id = wrapperMsgId;
|
|
66
|
+
get isConnected() {
|
|
67
|
+
return this.connected;
|
|
68
|
+
}
|
|
69
|
+
set isConnected(connected) {
|
|
70
|
+
this.connected = !!connected;
|
|
71
|
+
}
|
|
72
|
+
on(event, listener) {
|
|
73
|
+
// @ts-ignore messageHandler must be defined here
|
|
74
|
+
this.messageHandler.on(event, listener);
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
once(event, listener) {
|
|
78
|
+
// @ts-ignore messageHandler must be defined here
|
|
79
|
+
this.messageHandler.once(event, listener);
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
off(event, listener) {
|
|
83
|
+
// @ts-ignore messageHandler must be defined here
|
|
84
|
+
this.messageHandler.off(event, listener);
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
set isTargetBased(isTargetBased) {
|
|
88
|
+
logger_1.default.warn(`Setting communication protocol: using ${isTargetBased ? 'Target-based' : 'full Web Inspector protocol'} communication`);
|
|
89
|
+
this._isTargetBased = isTargetBased;
|
|
90
|
+
if (!this.remoteMessages) {
|
|
91
|
+
this.remoteMessages = new remote_messages_1.default(isTargetBased);
|
|
190
92
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return reject(err);
|
|
206
|
-
}
|
|
207
|
-
_logger.default.debug(`Received response from send (id: ${msgId}): '${_lodash.default.truncate(JSON.stringify(args), DATA_LOG_LENGTH)}'`);
|
|
208
|
-
resolve(args);
|
|
209
|
-
});
|
|
210
|
-
} else if (cmd !== null && cmd !== void 0 && (_cmd$__argument2 = cmd.__argument) !== null && _cmd$__argument2 !== void 0 && _cmd$__argument2.WIRSocketDataKey) {
|
|
211
|
-
this.messageHandler.once(msgId.toString(), function (err, value) {
|
|
212
|
-
if (err) {
|
|
213
|
-
return reject(new Error(`Remote debugger error with code '${err.code}': ${err.message}`));
|
|
214
|
-
}
|
|
215
|
-
_logger.default.debug(`Received data response from send (id: ${msgId}): '${_lodash.default.truncate(JSON.stringify(value), DATA_LOG_LENGTH)}'`);
|
|
216
|
-
resolve(value);
|
|
217
|
-
});
|
|
218
|
-
} else {
|
|
219
|
-
messageHandled = false;
|
|
220
|
-
}
|
|
221
|
-
const msg = `Sending '${cmd.__selector}' message` + (fullOpts.appIdKey ? ` to app '${fullOpts.appIdKey}'` : '') + (fullOpts.pageIdKey ? `, page '${fullOpts.pageIdKey}'` : '') + (this.needsTarget && targetId ? `, target '${targetId}'` : '') + ` (id: ${msgId}): '${command}'`;
|
|
222
|
-
_logger.default.debug(msg);
|
|
223
|
-
try {
|
|
224
|
-
const res = await this.sendMessage(cmd);
|
|
225
|
-
if (!messageHandled) {
|
|
226
|
-
resolve(res);
|
|
93
|
+
else {
|
|
94
|
+
this.remoteMessages.isTargetBased = isTargetBased;
|
|
95
|
+
}
|
|
96
|
+
if (!this.messageHandler) {
|
|
97
|
+
this.messageHandler = new rpc_message_handler_1.default(isTargetBased);
|
|
98
|
+
// add handlers for internal events
|
|
99
|
+
this.messageHandler.on('Target.targetCreated', this.addTarget.bind(this));
|
|
100
|
+
this.messageHandler.on('Target.didCommitProvisionalTarget', this.updateTarget.bind(this));
|
|
101
|
+
this.messageHandler.on('Target.targetDestroyed', this.removeTarget.bind(this));
|
|
102
|
+
this.messageHandler.on('Runtime.executionContextCreated', this.onExecutionContextCreated.bind(this));
|
|
103
|
+
this.messageHandler.on('Heap.garbageCollected', this.onGarbageCollected.bind(this));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this.messageHandler.isTargetBased = isTargetBased;
|
|
227
107
|
}
|
|
228
|
-
} catch (err) {
|
|
229
|
-
return reject(err);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
async connect() {
|
|
234
|
-
throw new Error(`Sub-classes need to implement a 'connect' function`);
|
|
235
|
-
}
|
|
236
|
-
async disconnect() {
|
|
237
|
-
this.messageHandler.removeAllListeners();
|
|
238
|
-
}
|
|
239
|
-
async sendMessage() {
|
|
240
|
-
throw new Error(`Sub-classes need to implement a 'sendMessage' function`);
|
|
241
|
-
}
|
|
242
|
-
async receive() {
|
|
243
|
-
throw new Error(`Sub-classes need to implement a 'receive' function`);
|
|
244
|
-
}
|
|
245
|
-
addTarget(err, app, targetInfo) {
|
|
246
|
-
if (_lodash.default.isNil(targetInfo === null || targetInfo === void 0 ? void 0 : targetInfo.targetId)) {
|
|
247
|
-
_logger.default.warn(`Received 'Target.targetCreated' event for app '${app}' with no target. Skipping`);
|
|
248
|
-
return;
|
|
249
108
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return;
|
|
109
|
+
get isTargetBased() {
|
|
110
|
+
return this._isTargetBased;
|
|
253
111
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* @param {string} appIdKey
|
|
115
|
+
* @param {string} pageIdKey
|
|
116
|
+
* @param {boolean} [force]
|
|
117
|
+
* @returns {Promise<void>}
|
|
118
|
+
*/
|
|
119
|
+
async waitForTarget(appIdKey, pageIdKey, force = false) {
|
|
120
|
+
if (!force && !this.needsTarget) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (this.getTarget(appIdKey, pageIdKey)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// otherwise waiting is necessary to see what the target is
|
|
127
|
+
try {
|
|
128
|
+
await (0, asyncbox_1.waitForCondition)(() => !lodash_1.default.isEmpty(this.getTarget(appIdKey, pageIdKey)), {
|
|
129
|
+
waitMs: WAIT_FOR_TARGET_TIMEOUT,
|
|
130
|
+
intervalMs: WAIT_FOR_TARGET_INTERVAL,
|
|
131
|
+
error: 'No targets found, unable to communicate with device',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (!err.message.includes('Condition unmet')) {
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
throw new Error('No targets found, unable to communicate with device');
|
|
139
|
+
}
|
|
257
140
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
* @param {string} command
|
|
144
|
+
* @param {Record<string, any>} [opts]
|
|
145
|
+
* @param {boolean} [waitForResponse]
|
|
146
|
+
* @returns {Promise<any>}
|
|
147
|
+
*/
|
|
148
|
+
async send(command, opts = {}, waitForResponse = true) {
|
|
149
|
+
const timer = new support_1.timing.Timer().start();
|
|
150
|
+
const { appIdKey, pageIdKey } = opts;
|
|
151
|
+
try {
|
|
152
|
+
if (!lodash_1.default.isEmpty(appIdKey) && !lodash_1.default.isEmpty(pageIdKey)) {
|
|
153
|
+
await this.waitForTarget(appIdKey, pageIdKey);
|
|
154
|
+
}
|
|
155
|
+
return await this.sendToDevice(command, opts, waitForResponse);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
let { message = '' } = err;
|
|
159
|
+
message = message.toLowerCase();
|
|
160
|
+
if (message.includes(`'target' domain was not found`)) {
|
|
161
|
+
logger_1.default.info('The target device does not support Target based communication. ' +
|
|
162
|
+
'Will follow non-target based communication.');
|
|
163
|
+
this.isTargetBased = false;
|
|
164
|
+
return await this.sendToDevice(command, opts, waitForResponse);
|
|
165
|
+
}
|
|
166
|
+
else if (message.includes(`domain was not found`) ||
|
|
167
|
+
message.includes(`some arguments of method`) ||
|
|
168
|
+
message.includes(`missing target`)) {
|
|
169
|
+
this.isTargetBased = true;
|
|
170
|
+
await this.waitForTarget(appIdKey, pageIdKey);
|
|
171
|
+
return await this.sendToDevice(command, opts, waitForResponse);
|
|
172
|
+
}
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
logger_1.default.debug(`Sending to Web Inspector took ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
177
|
+
}
|
|
262
178
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
179
|
+
/**
|
|
180
|
+
*
|
|
181
|
+
* @param {string} command
|
|
182
|
+
* @param {Record<string, any>} opts
|
|
183
|
+
* @param {boolean} [waitForResponse]
|
|
184
|
+
* @returns {Promise<any>}
|
|
185
|
+
*/
|
|
186
|
+
async sendToDevice(command, opts = {}, waitForResponse = true) {
|
|
187
|
+
return await new bluebird_1.default(async (resolve, reject) => {
|
|
188
|
+
// promise to be resolved whenever remote debugger
|
|
189
|
+
// replies to our request
|
|
190
|
+
// keep track of the messages coming and going using a simple sequential id
|
|
191
|
+
const msgId = this.msgId++;
|
|
192
|
+
let wrapperMsgId = msgId;
|
|
193
|
+
if (this.isTargetBased) {
|
|
194
|
+
// for target-base communication, everything is wrapped up
|
|
195
|
+
wrapperMsgId = this.msgId++;
|
|
196
|
+
// acknowledge wrapper message
|
|
197
|
+
// @ts-ignore messageHandler must be defined
|
|
198
|
+
this.messageHandler.on(wrapperMsgId.toString(), function (err) {
|
|
199
|
+
if (err) {
|
|
200
|
+
reject(err);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
const appIdKey = opts.appIdKey;
|
|
205
|
+
const pageIdKey = opts.pageIdKey;
|
|
206
|
+
const targetId = this.getTarget(appIdKey, pageIdKey);
|
|
207
|
+
// retrieve the correct command to send
|
|
208
|
+
const fullOpts = lodash_1.default.defaults({
|
|
209
|
+
connId: this.connId,
|
|
210
|
+
senderId: this.senderId,
|
|
211
|
+
targetId,
|
|
212
|
+
id: msgId,
|
|
213
|
+
}, opts);
|
|
214
|
+
// @ts-ignore remoteMessages must be defined
|
|
215
|
+
const cmd = this.remoteMessages.getRemoteCommand(command, fullOpts);
|
|
216
|
+
if (cmd?.__argument?.WIRSocketDataKey) {
|
|
217
|
+
// make sure the message being sent has all the information that is needed
|
|
218
|
+
if (lodash_1.default.isNil(cmd.__argument.WIRSocketDataKey.id)) {
|
|
219
|
+
cmd.__argument.WIRSocketDataKey.id = wrapperMsgId;
|
|
220
|
+
}
|
|
221
|
+
cmd.__argument.WIRSocketDataKey =
|
|
222
|
+
Buffer.from(JSON.stringify(cmd.__argument.WIRSocketDataKey));
|
|
223
|
+
}
|
|
224
|
+
let messageHandled = true;
|
|
225
|
+
if (!waitForResponse) {
|
|
226
|
+
// the promise will be resolved as soon as the socket has been sent
|
|
227
|
+
messageHandled = false;
|
|
228
|
+
// do not log receipts
|
|
229
|
+
// @ts-ignore messageHandler must be defined
|
|
230
|
+
this.messageHandler.once(msgId.toString(), function (err) {
|
|
231
|
+
if (err) {
|
|
232
|
+
// we are not waiting for this, and if it errors it is most likely
|
|
233
|
+
// a protocol change. Log and check during testing
|
|
234
|
+
logger_1.default.error(`Received error from send that is not being waited for (id: ${msgId}): '${lodash_1.default.truncate(JSON.stringify(err), DATA_LOG_LENGTH)}'`);
|
|
235
|
+
// reject, though it is very rare that this will be triggered, since
|
|
236
|
+
// the promise is resolved directlty after send. On the off chance,
|
|
237
|
+
// though, it will alert of a protocol change.
|
|
238
|
+
reject(err);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
// @ts-ignore messageHandler must be defined
|
|
242
|
+
}
|
|
243
|
+
else if (this.messageHandler.listeners(cmd.__selector).length) {
|
|
244
|
+
// @ts-ignore messageHandler must be defined
|
|
245
|
+
this.messageHandler.prependOnceListener(cmd.__selector, function (err, ...args) {
|
|
246
|
+
if (err) {
|
|
247
|
+
return reject(err);
|
|
248
|
+
}
|
|
249
|
+
logger_1.default.debug(`Received response from send (id: ${msgId}): '${lodash_1.default.truncate(JSON.stringify(args), DATA_LOG_LENGTH)}'`);
|
|
250
|
+
resolve(args);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
else if (cmd?.__argument?.WIRSocketDataKey) {
|
|
254
|
+
// @ts-ignore messageHandler must be defined
|
|
255
|
+
this.messageHandler.once(msgId.toString(), function (err, value) {
|
|
256
|
+
if (err) {
|
|
257
|
+
return reject(new Error(`Remote debugger error with code '${err.code}': ${err.message}`));
|
|
258
|
+
}
|
|
259
|
+
logger_1.default.debug(`Received data response from send (id: ${msgId}): '${lodash_1.default.truncate(JSON.stringify(value), DATA_LOG_LENGTH)}'`);
|
|
260
|
+
resolve(value);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// nothing else is handling things, so just resolve when the message is sent
|
|
265
|
+
messageHandled = false;
|
|
266
|
+
}
|
|
267
|
+
const msg = `Sending '${cmd.__selector}' message` +
|
|
268
|
+
(appIdKey ? ` to app '${appIdKey}'` : '') +
|
|
269
|
+
(pageIdKey ? `, page '${pageIdKey}'` : '') +
|
|
270
|
+
(this.needsTarget && targetId ? `, target '${targetId}'` : '') +
|
|
271
|
+
` (id: ${msgId}): '${command}'`;
|
|
272
|
+
logger_1.default.debug(msg);
|
|
273
|
+
try {
|
|
274
|
+
const res = await this.sendMessage(cmd);
|
|
275
|
+
if (!messageHandled) {
|
|
276
|
+
// There are no handlers waiting for a response before resolving,
|
|
277
|
+
// and no errors sending the message over the socket, so resolve
|
|
278
|
+
resolve(res);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
return reject(err);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
271
285
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
newTargetId
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
removeTarget(err, app, targetInfo) {
|
|
278
|
-
var _this$targets$app;
|
|
279
|
-
if (_lodash.default.isNil(targetInfo === null || targetInfo === void 0 ? void 0 : targetInfo.targetId)) {
|
|
280
|
-
_logger.default.debug(`Received 'Target.targetDestroyed' event with no target. Skipping`);
|
|
281
|
-
return;
|
|
286
|
+
async connect() {
|
|
287
|
+
throw new Error(`Sub-classes need to implement a 'connect' function`);
|
|
282
288
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
delete this.targets[app].provisional;
|
|
290
|
-
const targets = this.targets[app];
|
|
291
|
-
for (const [page, targetId] of _lodash.default.toPairs(targets)) {
|
|
292
|
-
if (targetId === oldTargetId) {
|
|
293
|
-
_logger.default.debug(`Found provisional target for app '${app}'. Old target: '${oldTargetId}', new target: '${newTargetId}'. Updating`);
|
|
294
|
-
targets[page] = newTargetId;
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
_logger.default.warn(`Provisional target for app '${app}' found, but no suitable existing target found. This may cause problems`);
|
|
299
|
-
_logger.default.warn(`Old target: '${oldTargetId}', new target: '${newTargetId}'. Existing targets: ${JSON.stringify(targets)}`);
|
|
289
|
+
async disconnect() {
|
|
290
|
+
this.messageHandler?.removeAllListeners();
|
|
291
|
+
}
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
293
|
+
async sendMessage(command) {
|
|
294
|
+
throw new Error(`Sub-classes need to implement a 'sendMessage' function`);
|
|
300
295
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if (targetId === targetInfo.targetId) {
|
|
304
|
-
delete targets[page];
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
296
|
+
async receive( /* data */) {
|
|
297
|
+
throw new Error(`Sub-classes need to implement a 'receive' function`);
|
|
307
298
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
299
|
+
/**
|
|
300
|
+
*
|
|
301
|
+
* @param {Error?} err
|
|
302
|
+
* @param {string} app
|
|
303
|
+
* @param {Record<string, any>} targetInfo
|
|
304
|
+
* @returns {void}
|
|
305
|
+
*/
|
|
306
|
+
addTarget(err, app, targetInfo) {
|
|
307
|
+
if (lodash_1.default.isNil(targetInfo?.targetId)) {
|
|
308
|
+
logger_1.default.warn(`Received 'Target.targetCreated' event for app '${app}' with no target. Skipping`);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (lodash_1.default.isEmpty(this.pendingTargetNotification) && !targetInfo.isProvisional) {
|
|
312
|
+
logger_1.default.warn(`Received 'Target.targetCreated' event for app '${app}' with no pending request: ${JSON.stringify(targetInfo)}`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (targetInfo.isProvisional) {
|
|
316
|
+
logger_1.default.debug(`Provisional target created for app '${app}', '${targetInfo.targetId}'. Ignoring until target update event`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
// @ts-ignore this.pendingTargetNotification must be defined here
|
|
320
|
+
const [appIdKey, pageIdKey] = this.pendingTargetNotification;
|
|
321
|
+
logger_1.default.debug(`Target created for app '${appIdKey}' and page '${pageIdKey}': ${JSON.stringify(targetInfo)}`);
|
|
322
|
+
if (lodash_1.default.has(this.targets[appIdKey], pageIdKey)) {
|
|
323
|
+
logger_1.default.debug(`There is already a target for this app and page ('${this.targets[appIdKey][pageIdKey]}'). This might cause problems`);
|
|
324
|
+
}
|
|
325
|
+
this.targets[app] = this.targets[app] || {};
|
|
326
|
+
this.targets[appIdKey][pageIdKey] = targetInfo.targetId;
|
|
324
327
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
/**
|
|
329
|
+
*
|
|
330
|
+
* @param {Error?} err
|
|
331
|
+
* @param {string} app
|
|
332
|
+
* @param {string} oldTargetId
|
|
333
|
+
* @param {string} newTargetId
|
|
334
|
+
* @returns {void}
|
|
335
|
+
*/
|
|
336
|
+
updateTarget(err, app, oldTargetId, newTargetId) {
|
|
337
|
+
logger_1.default.debug(`Target updated for app '${app}'. Old target: '${oldTargetId}', new target: '${newTargetId}'`);
|
|
338
|
+
if (!this.targets[app]) {
|
|
339
|
+
logger_1.default.warn(`No existing target for app '${app}'. Not sure what to do`);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
// save this, to be used if/when the existing target is destroyed
|
|
343
|
+
this.targets[app].provisional = {
|
|
344
|
+
oldTargetId,
|
|
345
|
+
newTargetId,
|
|
346
|
+
};
|
|
329
347
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
348
|
+
/**
|
|
349
|
+
*
|
|
350
|
+
* @param {Error?} err
|
|
351
|
+
* @param {string} app
|
|
352
|
+
* @param {Record<string, any>} targetInfo
|
|
353
|
+
* @returns {void}
|
|
354
|
+
*/
|
|
355
|
+
removeTarget(err, app, targetInfo) {
|
|
356
|
+
if (lodash_1.default.isNil(targetInfo?.targetId)) {
|
|
357
|
+
logger_1.default.debug(`Received 'Target.targetDestroyed' event with no target. Skipping`);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
logger_1.default.debug(`Target destroyed for app '${app}': ${targetInfo.targetId}`);
|
|
361
|
+
// go through the targets and find the one that has a waiting provisional target
|
|
362
|
+
if (this.targets[app]?.provisional?.oldTargetId === targetInfo.targetId) {
|
|
363
|
+
const { oldTargetId, newTargetId } = this.targets[app].provisional;
|
|
364
|
+
delete this.targets[app].provisional;
|
|
365
|
+
// we do not know the page, so go through and find the existing target
|
|
366
|
+
const targets = this.targets[app];
|
|
367
|
+
for (const [page, targetId] of lodash_1.default.toPairs(targets)) {
|
|
368
|
+
if (targetId === oldTargetId) {
|
|
369
|
+
logger_1.default.debug(`Found provisional target for app '${app}'. Old target: '${oldTargetId}', new target: '${newTargetId}'. Updating`);
|
|
370
|
+
targets[page] = newTargetId;
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
logger_1.default.warn(`Provisional target for app '${app}' found, but no suitable existing target found. This may cause problems`);
|
|
375
|
+
logger_1.default.warn(`Old target: '${oldTargetId}', new target: '${newTargetId}'. Existing targets: ${JSON.stringify(targets)}`);
|
|
376
|
+
}
|
|
377
|
+
// if there is no waiting provisional target, just get rid of the existing one
|
|
378
|
+
const targets = this.targets[app];
|
|
379
|
+
for (const [page, targetId] of lodash_1.default.toPairs(targets)) {
|
|
380
|
+
if (targetId === targetInfo.targetId) {
|
|
381
|
+
delete targets[page];
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
logger_1.default.debug(`Target '${targetInfo.targetId}' deleted for app '${app}', but no such target exists`);
|
|
335
386
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
await this.send('Page.enable', sendOpts, false);
|
|
344
|
-
await this.send('Network.enable', sendOpts, false);
|
|
345
|
-
await this.send('Runtime.enable', sendOpts, false);
|
|
346
|
-
await this.send('Heap.enable', sendOpts, false);
|
|
347
|
-
await this.send('Debugger.enable', sendOpts, false);
|
|
348
|
-
await this.send('Console.enable', sendOpts, false);
|
|
349
|
-
await this.send('Inspector.initialized', sendOpts, false);
|
|
350
|
-
}
|
|
351
|
-
async initializePageFull(appIdKey, pageIdKey) {
|
|
352
|
-
const sendOpts = {
|
|
353
|
-
appIdKey,
|
|
354
|
-
pageIdKey
|
|
355
|
-
};
|
|
356
|
-
await this.send('Inspector.enable', sendOpts, false);
|
|
357
|
-
await this.send('Page.enable', sendOpts, false);
|
|
358
|
-
await this.send('Page.getResourceTree', sendOpts, false);
|
|
359
|
-
await this.send('Network.enable', sendOpts, false);
|
|
360
|
-
await this.send('Network.setResourceCachingDisabled', Object.assign({
|
|
361
|
-
disabled: false
|
|
362
|
-
}, sendOpts), false);
|
|
363
|
-
await this.send('DOMStorage.enable', sendOpts, false);
|
|
364
|
-
await this.send('Database.enable', sendOpts, false);
|
|
365
|
-
await this.send('IndexedDB.enable', sendOpts, false);
|
|
366
|
-
await this.send('CSS.enable', sendOpts, false);
|
|
367
|
-
await this.send('Runtime.enable', sendOpts, false);
|
|
368
|
-
await this.send('Heap.enable', sendOpts, false);
|
|
369
|
-
await this.send('Memory.enable', sendOpts, false);
|
|
370
|
-
await this.send('ApplicationCache.enable', sendOpts, false);
|
|
371
|
-
await this.send('ApplicationCache.getFramesWithManifests', sendOpts, false);
|
|
372
|
-
await this.send('Timeline.setInstruments', Object.assign({
|
|
373
|
-
instruments: ['Timeline', 'ScriptProfiler', 'CPU']
|
|
374
|
-
}, sendOpts), false);
|
|
375
|
-
await this.send('Timeline.setAutoCaptureEnabled', Object.assign({
|
|
376
|
-
enabled: false
|
|
377
|
-
}, sendOpts), false);
|
|
378
|
-
await this.send('Debugger.enable', sendOpts, false);
|
|
379
|
-
await this.send('Debugger.setBreakpointsActive', Object.assign({
|
|
380
|
-
active: true
|
|
381
|
-
}, sendOpts), false);
|
|
382
|
-
await this.send('Debugger.setPauseOnExceptions', Object.assign({
|
|
383
|
-
state: 'none'
|
|
384
|
-
}, sendOpts), false);
|
|
385
|
-
await this.send('Debugger.setPauseOnAssertions', Object.assign({
|
|
386
|
-
enabled: false
|
|
387
|
-
}, sendOpts), false);
|
|
388
|
-
await this.send('Debugger.setAsyncStackTraceDepth', Object.assign({
|
|
389
|
-
depth: 200
|
|
390
|
-
}, sendOpts), false);
|
|
391
|
-
await this.send('Debugger.setPauseForInternalScripts', Object.assign({
|
|
392
|
-
shouldPause: false
|
|
393
|
-
}, sendOpts), false);
|
|
394
|
-
await this.send('LayerTree.enable', sendOpts, false);
|
|
395
|
-
await this.send('Worker.enable', sendOpts, false);
|
|
396
|
-
await this.send('Canvas.enable', sendOpts, false);
|
|
397
|
-
await this.send('Console.enable', sendOpts, false);
|
|
398
|
-
await this.send('DOM.getDocument', sendOpts, false);
|
|
399
|
-
const loggingChannels = await this.send('Console.getLoggingChannels', sendOpts);
|
|
400
|
-
for (const source of (loggingChannels.channels || []).map(entry => entry.source)) {
|
|
401
|
-
await this.send('Console.setLoggingChannelLevel', Object.assign({
|
|
402
|
-
source,
|
|
403
|
-
level: 'verbose'
|
|
404
|
-
}, sendOpts), false);
|
|
387
|
+
/**
|
|
388
|
+
* @param {string} appIdKey
|
|
389
|
+
* @param {string} pageIdKey
|
|
390
|
+
* @returns {any}
|
|
391
|
+
*/
|
|
392
|
+
getTarget(appIdKey, pageIdKey) {
|
|
393
|
+
return (this.targets[appIdKey] || {})[pageIdKey];
|
|
405
394
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
395
|
+
/**
|
|
396
|
+
* @param {string} appIdKey
|
|
397
|
+
* @param {string} pageIdKey
|
|
398
|
+
* @returns {Promise<void>}
|
|
399
|
+
*/
|
|
400
|
+
async selectPage(appIdKey, pageIdKey) {
|
|
401
|
+
/** @type {[string, string]} */
|
|
402
|
+
this.pendingTargetNotification = [appIdKey, pageIdKey];
|
|
403
|
+
this.shouldCheckForTarget = false;
|
|
404
|
+
// go through the steps that the Desktop Safari system
|
|
405
|
+
// goes through to initialize the Web Inspector session
|
|
406
|
+
const sendOpts = {
|
|
407
|
+
appIdKey,
|
|
408
|
+
pageIdKey,
|
|
409
|
+
};
|
|
410
|
+
// highlight and then un-highlight the webview
|
|
411
|
+
for (const enabled of [true, false]) {
|
|
412
|
+
await this.send('indicateWebView', Object.assign({
|
|
413
|
+
enabled,
|
|
414
|
+
}, sendOpts), false);
|
|
413
415
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (
|
|
417
|
-
|
|
416
|
+
await this.send('setSenderKey', sendOpts);
|
|
417
|
+
logger_1.default.debug('Sender key set');
|
|
418
|
+
if (this.isTargetBased && support_1.util.compareVersions(this.platformVersion, '<', MIN_PLATFORM_NO_TARGET_EXISTS)) {
|
|
419
|
+
await this.send('Target.exists', sendOpts, false);
|
|
418
420
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return (async () => {
|
|
423
|
-
let pageDict, connectedAppIdKey;
|
|
424
|
-
try {
|
|
425
|
-
[connectedAppIdKey, pageDict] = await this.send('connectToApp', {
|
|
426
|
-
appIdKey
|
|
427
|
-
});
|
|
428
|
-
} catch (err) {
|
|
429
|
-
_logger.default.warn(`Unable to connect to app: ${err.message}`);
|
|
430
|
-
reject(err);
|
|
421
|
+
this.shouldCheckForTarget = true;
|
|
422
|
+
if (this.fullPageInitialization) {
|
|
423
|
+
await this.initializePageFull(appIdKey, pageIdKey);
|
|
431
424
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
_logger.default.debug(msg);
|
|
435
|
-
reject(new Error(msg));
|
|
436
|
-
} else {
|
|
437
|
-
resolve([connectedAppIdKey, pageDict]);
|
|
425
|
+
else {
|
|
426
|
+
await this.initializePage(appIdKey, pageIdKey);
|
|
438
427
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Perform the minimal initialization to get the Web Inspector working
|
|
431
|
+
* @param {string} appIdKey
|
|
432
|
+
* @param {string} pageIdKey
|
|
433
|
+
* @returns {Promise<void>}
|
|
434
|
+
*/
|
|
435
|
+
async initializePage(appIdKey, pageIdKey) {
|
|
436
|
+
const sendOpts = {
|
|
437
|
+
appIdKey,
|
|
438
|
+
pageIdKey,
|
|
439
|
+
};
|
|
440
|
+
await this.send('Inspector.enable', sendOpts, false);
|
|
441
|
+
await this.send('Page.enable', sendOpts, false);
|
|
442
|
+
// go through the tasks to initialize
|
|
443
|
+
await this.send('Network.enable', sendOpts, false);
|
|
444
|
+
await this.send('Runtime.enable', sendOpts, false);
|
|
445
|
+
await this.send('Heap.enable', sendOpts, false);
|
|
446
|
+
await this.send('Debugger.enable', sendOpts, false);
|
|
447
|
+
await this.send('Console.enable', sendOpts, false);
|
|
448
|
+
await this.send('Inspector.initialized', sendOpts, false);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Mimic every step that Desktop Safari Develop tools uses to initialize a
|
|
452
|
+
* Web Inspector session
|
|
453
|
+
*
|
|
454
|
+
* @param {string} appIdKey
|
|
455
|
+
* @param {string} pageIdKey
|
|
456
|
+
* @returns {Promise<void>}
|
|
457
|
+
*/
|
|
458
|
+
async initializePageFull(appIdKey, pageIdKey) {
|
|
459
|
+
const sendOpts = {
|
|
460
|
+
appIdKey,
|
|
461
|
+
pageIdKey,
|
|
462
|
+
};
|
|
463
|
+
await this.send('Inspector.enable', sendOpts, false);
|
|
464
|
+
await this.send('Page.enable', sendOpts, false);
|
|
465
|
+
// go through the tasks to initialize
|
|
466
|
+
await this.send('Page.getResourceTree', sendOpts, false);
|
|
467
|
+
await this.send('Network.enable', sendOpts, false);
|
|
468
|
+
await this.send('Network.setResourceCachingDisabled', Object.assign({
|
|
469
|
+
disabled: false,
|
|
470
|
+
}, sendOpts), false);
|
|
471
|
+
await this.send('DOMStorage.enable', sendOpts, false);
|
|
472
|
+
await this.send('Database.enable', sendOpts, false);
|
|
473
|
+
await this.send('IndexedDB.enable', sendOpts, false);
|
|
474
|
+
await this.send('CSS.enable', sendOpts, false);
|
|
475
|
+
await this.send('Runtime.enable', sendOpts, false);
|
|
476
|
+
await this.send('Heap.enable', sendOpts, false);
|
|
477
|
+
await this.send('Memory.enable', sendOpts, false);
|
|
478
|
+
await this.send('ApplicationCache.enable', sendOpts, false);
|
|
479
|
+
await this.send('ApplicationCache.getFramesWithManifests', sendOpts, false);
|
|
480
|
+
await this.send('Timeline.setInstruments', Object.assign({
|
|
481
|
+
instruments: ['Timeline', 'ScriptProfiler', 'CPU'],
|
|
482
|
+
}, sendOpts), false);
|
|
483
|
+
await this.send('Timeline.setAutoCaptureEnabled', Object.assign({
|
|
484
|
+
enabled: false,
|
|
485
|
+
}, sendOpts), false);
|
|
486
|
+
await this.send('Debugger.enable', sendOpts, false);
|
|
487
|
+
await this.send('Debugger.setBreakpointsActive', Object.assign({
|
|
488
|
+
active: true,
|
|
489
|
+
}, sendOpts), false);
|
|
490
|
+
await this.send('Debugger.setPauseOnExceptions', Object.assign({
|
|
491
|
+
state: 'none',
|
|
492
|
+
}, sendOpts), false);
|
|
493
|
+
await this.send('Debugger.setPauseOnAssertions', Object.assign({
|
|
494
|
+
enabled: false,
|
|
495
|
+
}, sendOpts), false);
|
|
496
|
+
await this.send('Debugger.setAsyncStackTraceDepth', Object.assign({
|
|
497
|
+
depth: 200,
|
|
498
|
+
}, sendOpts), false);
|
|
499
|
+
await this.send('Debugger.setPauseForInternalScripts', Object.assign({
|
|
500
|
+
shouldPause: false,
|
|
501
|
+
}, sendOpts), false);
|
|
502
|
+
await this.send('LayerTree.enable', sendOpts, false);
|
|
503
|
+
await this.send('Worker.enable', sendOpts, false);
|
|
504
|
+
await this.send('Canvas.enable', sendOpts, false);
|
|
505
|
+
await this.send('Console.enable', sendOpts, false);
|
|
506
|
+
await this.send('DOM.getDocument', sendOpts, false);
|
|
507
|
+
const loggingChannels = await this.send('Console.getLoggingChannels', sendOpts);
|
|
508
|
+
for (const source of (loggingChannels.channels || []).map((entry) => entry.source)) {
|
|
509
|
+
await this.send('Console.setLoggingChannelLevel', Object.assign({
|
|
510
|
+
source,
|
|
511
|
+
level: 'verbose',
|
|
512
|
+
}, sendOpts), false);
|
|
513
|
+
}
|
|
514
|
+
await this.send('Inspector.initialized', sendOpts, false);
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
*
|
|
518
|
+
* @param {string} appIdKey
|
|
519
|
+
* @returns {Promise<[string, Record<string, any>]>}
|
|
520
|
+
*/
|
|
521
|
+
async selectApp(appIdKey) {
|
|
522
|
+
return await new bluebird_1.default((resolve, reject) => {
|
|
523
|
+
// local callback, temporarily added as callback to
|
|
524
|
+
// `_rpc_applicationConnected:` remote debugger response
|
|
525
|
+
// to handle the initial connection
|
|
526
|
+
const onAppChange = (err, dict) => {
|
|
527
|
+
if (err) {
|
|
528
|
+
return reject(err);
|
|
529
|
+
}
|
|
530
|
+
// from the dictionary returned, get the ids
|
|
531
|
+
const oldAppIdKey = dict.WIRHostApplicationIdentifierKey;
|
|
532
|
+
const correctAppIdKey = dict.WIRApplicationIdentifierKey;
|
|
533
|
+
// if this is a report of a proxy redirect from the remote debugger
|
|
534
|
+
// we want to update our dictionary and get a new app id
|
|
535
|
+
if (oldAppIdKey && correctAppIdKey !== oldAppIdKey) {
|
|
536
|
+
logger_1.default.debug(`We were notified we might have connected to the wrong app. ` +
|
|
537
|
+
`Using id ${correctAppIdKey} instead of ${oldAppIdKey}`);
|
|
538
|
+
}
|
|
539
|
+
reject(new Error('New application has connected'));
|
|
540
|
+
};
|
|
541
|
+
// @ts-ignore messageHandler must be defined
|
|
542
|
+
this.messageHandler.prependOnceListener('_rpc_applicationConnected:', onAppChange);
|
|
543
|
+
// do the actual connecting to the app
|
|
544
|
+
return (async () => {
|
|
545
|
+
let pageDict, connectedAppIdKey;
|
|
546
|
+
try {
|
|
547
|
+
([connectedAppIdKey, pageDict] = await this.send('connectToApp', {
|
|
548
|
+
appIdKey
|
|
549
|
+
}));
|
|
550
|
+
}
|
|
551
|
+
catch (err) {
|
|
552
|
+
logger_1.default.warn(`Unable to connect to app: ${err.message}`);
|
|
553
|
+
reject(err);
|
|
554
|
+
}
|
|
555
|
+
// sometimes the connect logic happens, but with an empty dictionary
|
|
556
|
+
// which leads to the remote debugger getting disconnected, and into a loop
|
|
557
|
+
if (lodash_1.default.isEmpty(pageDict)) {
|
|
558
|
+
let msg = 'Empty page dictionary received';
|
|
559
|
+
logger_1.default.debug(msg);
|
|
560
|
+
reject(new Error(msg));
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
resolve([connectedAppIdKey, pageDict]);
|
|
564
|
+
}
|
|
565
|
+
})();
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
*
|
|
570
|
+
* @param {Error?} err
|
|
571
|
+
* @param {Record<string, any>} context
|
|
572
|
+
*/
|
|
573
|
+
onExecutionContextCreated(err, context) {
|
|
574
|
+
// { id: 2, isPageContext: true, name: '', frameId: '0.1' }
|
|
575
|
+
// right now we have no way to map contexts to apps/pages
|
|
576
|
+
// so just store
|
|
577
|
+
this.contexts.push(context.id);
|
|
578
|
+
}
|
|
579
|
+
onGarbageCollected() {
|
|
580
|
+
// just want to log that this is happening, as it can affect opertion
|
|
581
|
+
logger_1.default.debug(`Web Inspector garbage collected`);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
*
|
|
585
|
+
* @param {Error?} err
|
|
586
|
+
* @param {Record<string, any>} scriptInfo
|
|
587
|
+
*/
|
|
588
|
+
onScriptParsed(err, scriptInfo) {
|
|
589
|
+
// { scriptId: '13', url: '', startLine: 0, startColumn: 0, endLine: 82, endColumn: 3 }
|
|
590
|
+
logger_1.default.debug(`Script parsed: ${JSON.stringify(scriptInfo)}`);
|
|
591
|
+
}
|
|
451
592
|
}
|
|
452
593
|
exports.default = RpcClient;
|
|
453
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVtb3RlTWVzc2FnZXMiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9hc3luY2JveCIsIl9sb2dnZXIiLCJfbG9kYXNoIiwiX2JsdWViaXJkIiwiX3JwY01lc3NhZ2VIYW5kbGVyIiwiX3N1cHBvcnQiLCJEQVRBX0xPR19MRU5HVEgiLCJsZW5ndGgiLCJXQUlUX0ZPUl9UQVJHRVRfVElNRU9VVCIsIldBSVRfRk9SX1RBUkdFVF9JTlRFUlZBTCIsIk1JTl9QTEFURk9STV9GT1JfVEFSR0VUX0JBU0VEIiwiTUlOX1BMQVRGT1JNX05PX1RBUkdFVF9FWElTVFMiLCJpc1RhcmdldEJhc2VkIiwiaXNTYWZhcmkiLCJwbGF0Zm9ybVZlcnNpb24iLCJpc0hpZ2hWZXJzaW9uIiwidXRpbCIsImNvbXBhcmVWZXJzaW9ucyIsImxvZyIsImRlYnVnIiwiUnBjQ2xpZW50IiwiY29uc3RydWN0b3IiLCJvcHRzIiwiX3RhcmdldHMiLCJfc2hvdWxkQ2hlY2tGb3JUYXJnZXQiLCJzaG91bGRDaGVja0ZvclRhcmdldCIsImJ1bmRsZUlkIiwibG9nQWxsQ29tbXVuaWNhdGlvbiIsImxvZ0FsbENvbW11bmljYXRpb25IZXhEdW1wIiwid2ViSW5zcGVjdG9yTWF4RnJhbWVMZW5ndGgiLCJzb2NrZXRDaHVua1NpemUiLCJmdWxsUGFnZUluaXRpYWxpemF0aW9uIiwiaXNDb25uZWN0ZWQiLCJjb25uSWQiLCJ1dWlkVjQiLCJzZW5kZXJJZCIsIm1zZ0lkIiwiX2NvbnRleHRzIiwiY29udGV4dHMiLCJuZWVkc1RhcmdldCIsInRhcmdldHMiLCJjb25uZWN0ZWQiLCJvbiIsImV2ZW50IiwibGlzdGVuZXIiLCJtZXNzYWdlSGFuZGxlciIsIm9uY2UiLCJvZmYiLCJ3YXJuIiwiX2lzVGFyZ2V0QmFzZWQiLCJyZW1vdGVNZXNzYWdlcyIsIlJlbW90ZU1lc3NhZ2VzIiwiUnBjTWVzc2FnZUhhbmRsZXIiLCJhZGRUYXJnZXQiLCJiaW5kIiwidXBkYXRlVGFyZ2V0IiwicmVtb3ZlVGFyZ2V0Iiwib25FeGVjdXRpb25Db250ZXh0Q3JlYXRlZCIsIm9uR2FyYmFnZUNvbGxlY3RlZCIsIndhaXRGb3JUYXJnZXQiLCJhcHBJZEtleSIsInBhZ2VJZEtleSIsImZvcmNlIiwiZ2V0VGFyZ2V0Iiwid2FpdEZvckNvbmRpdGlvbiIsIl8iLCJpc0VtcHR5Iiwid2FpdE1zIiwiaW50ZXJ2YWxNcyIsImVycm9yIiwiZXJyIiwibWVzc2FnZSIsImluY2x1ZGVzIiwiRXJyb3IiLCJzZW5kIiwiY29tbWFuZCIsIndhaXRGb3JSZXNwb25zZSIsInRpbWVyIiwidGltaW5nIiwiVGltZXIiLCJzdGFydCIsInNlbmRUb0RldmljZSIsInRvTG93ZXJDYXNlIiwiaW5mbyIsImdldER1cmF0aW9uIiwiYXNNaWxsaVNlY29uZHMiLCJ0b0ZpeGVkIiwiQiIsInJlc29sdmUiLCJyZWplY3QiLCJfY21kJF9fYXJndW1lbnQiLCJfY21kJF9fYXJndW1lbnQyIiwid3JhcHBlck1zZ0lkIiwidG9TdHJpbmciLCJ0YXJnZXRJZCIsImZ1bGxPcHRzIiwiZGVmYXVsdHMiLCJpZCIsImNtZCIsImdldFJlbW90ZUNvbW1hbmQiLCJfX2FyZ3VtZW50IiwiV0lSU29ja2V0RGF0YUtleSIsImlzTmlsIiwiQnVmZmVyIiwiZnJvbSIsIkpTT04iLCJzdHJpbmdpZnkiLCJtZXNzYWdlSGFuZGxlZCIsInRydW5jYXRlIiwibGlzdGVuZXJzIiwiX19zZWxlY3RvciIsInByZXBlbmRPbmNlTGlzdGVuZXIiLCJhcmdzIiwidmFsdWUiLCJjb2RlIiwibXNnIiwicmVzIiwic2VuZE1lc3NhZ2UiLCJjb25uZWN0IiwiZGlzY29ubmVjdCIsInJlbW92ZUFsbExpc3RlbmVycyIsInJlY2VpdmUiLCJhcHAiLCJ0YXJnZXRJbmZvIiwicGVuZGluZ1RhcmdldE5vdGlmaWNhdGlvbiIsImlzUHJvdmlzaW9uYWwiLCJoYXMiLCJvbGRUYXJnZXRJZCIsIm5ld1RhcmdldElkIiwicHJvdmlzaW9uYWwiLCJfdGhpcyR0YXJnZXRzJGFwcCIsInBhZ2UiLCJ0b1BhaXJzIiwic2VsZWN0UGFnZSIsInNlbmRPcHRzIiwiZW5hYmxlZCIsIk9iamVjdCIsImFzc2lnbiIsImluaXRpYWxpemVQYWdlRnVsbCIsImluaXRpYWxpemVQYWdlIiwiZGlzYWJsZWQiLCJpbnN0cnVtZW50cyIsImFjdGl2ZSIsInN0YXRlIiwiZGVwdGgiLCJzaG91bGRQYXVzZSIsImxvZ2dpbmdDaGFubmVscyIsInNvdXJjZSIsImNoYW5uZWxzIiwibWFwIiwiZW50cnkiLCJsZXZlbCIsInNlbGVjdEFwcCIsIm9uQXBwQ2hhbmdlIiwiZGljdCIsIm9sZEFwcElkS2V5IiwiV0lSSG9zdEFwcGxpY2F0aW9uSWRlbnRpZmllcktleSIsImNvcnJlY3RBcHBJZEtleSIsIldJUkFwcGxpY2F0aW9uSWRlbnRpZmllcktleSIsInBhZ2VEaWN0IiwiY29ubmVjdGVkQXBwSWRLZXkiLCJjb250ZXh0IiwicHVzaCIsIm9uU2NyaXB0UGFyc2VkIiwic2NyaXB0SW5mbyIsImV4cG9ydHMiLCJkZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vbGliL3JwYy9ycGMtY2xpZW50LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZW1vdGVNZXNzYWdlcyBmcm9tICcuL3JlbW90ZS1tZXNzYWdlcyc7XG5pbXBvcnQgeyB3YWl0Rm9yQ29uZGl0aW9uIH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBScGNNZXNzYWdlSGFuZGxlciBmcm9tICcuL3JwYy1tZXNzYWdlLWhhbmRsZXInO1xuaW1wb3J0IHsgdXRpbCwgdGltaW5nIH0gZnJvbSAnQGFwcGl1bS9zdXBwb3J0JztcblxuXG5jb25zdCBEQVRBX0xPR19MRU5HVEggPSB7bGVuZ3RoOiAyMDB9O1xuXG5jb25zdCBXQUlUX0ZPUl9UQVJHRVRfVElNRU9VVCA9IDEwMDAwO1xuY29uc3QgV0FJVF9GT1JfVEFSR0VUX0lOVEVSVkFMID0gMTAwMDtcblxuY29uc3QgTUlOX1BMQVRGT1JNX0ZPUl9UQVJHRVRfQkFTRUQgPSAnMTIuMic7XG5cbi8vIGBUYXJnZXQuZXhpc3RzYCBwcm90b2NvbCBtZXRob2Qgd2FzIHJlbW92ZWQgZnJvbSBXZWJLaXQgaW4gMTMuNFxuY29uc3QgTUlOX1BMQVRGT1JNX05PX1RBUkdFVF9FWElTVFMgPSAnMTMuNCc7XG5cbmZ1bmN0aW9uIGlzVGFyZ2V0QmFzZWQgKGlzU2FmYXJpLCBwbGF0Zm9ybVZlcnNpb24pIHtcbiAgLy8gT24gaU9TIDEyLjIgdGhlIG1lc3NhZ2VzIGdldCBzZW50IHRocm91Z2ggdGhlIFRhcmdldCBkb21haW5cbiAgLy8gT24gaU9TIDEzLjArLCBXS1dlYlZpZXcgYWxzbyBuZWVkcyB0byBmb2xsb3cgdGhlIFRhcmdldCBkb21haW4sXG4gIC8vIHNvIGhlcmUgb25seSBjaGVjayB0aGUgdGFyZ2V0IE9TIHZlcnNpb24gYXMgdGhlIGRlZmF1bHQgYmVoYXZpb3VyLlxuICBjb25zdCBpc0hpZ2hWZXJzaW9uID0gdXRpbC5jb21wYXJlVmVyc2lvbnMocGxhdGZvcm1WZXJzaW9uLCAnPj0nLCBNSU5fUExBVEZPUk1fRk9SX1RBUkdFVF9CQVNFRCk7XG4gIGxvZy5kZWJ1ZyhgQ2hlY2tpbmcgd2hpY2ggY29tbXVuaWNhdGlvbiBzdHlsZSB0byB1c2UgKCR7aXNTYWZhcmkgPyAnJyA6ICdub24tJ31TYWZhcmkgb24gcGxhdGZvcm0gdmVyc2lvbiAnJHtwbGF0Zm9ybVZlcnNpb259JylgKTtcbiAgbG9nLmRlYnVnKGBQbGF0Zm9ybSB2ZXJzaW9uIGVxdWFsIG9yIGhpZ2hlciB0aGFuICcke01JTl9QTEFURk9STV9GT1JfVEFSR0VUX0JBU0VEfSc6ICR7aXNIaWdoVmVyc2lvbn1gKTtcbiAgcmV0dXJuIGlzSGlnaFZlcnNpb247XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJwY0NsaWVudCB7XG4gIGNvbnN0cnVjdG9yIChvcHRzID0ge30pIHtcbiAgICB0aGlzLl90YXJnZXRzID0gW107XG4gICAgdGhpcy5fc2hvdWxkQ2hlY2tGb3JUYXJnZXQgPSAhIW9wdHMuc2hvdWxkQ2hlY2tGb3JUYXJnZXQ7XG5cbiAgICBjb25zdCB7XG4gICAgICBidW5kbGVJZCxcbiAgICAgIHBsYXRmb3JtVmVyc2lvbiA9IHt9LFxuICAgICAgaXNTYWZhcmkgPSB0cnVlLFxuICAgICAgbG9nQWxsQ29tbXVuaWNhdGlvbiA9IGZhbHNlLFxuICAgICAgbG9nQWxsQ29tbXVuaWNhdGlvbkhleER1bXAgPSBmYWxzZSxcbiAgICAgIHdlYkluc3BlY3Rvck1heEZyYW1lTGVuZ3RoLFxuICAgICAgc29ja2V0Q2h1bmtTaXplLFxuICAgICAgZnVsbFBhZ2VJbml0aWFsaXphdGlvbiA9IGZhbHNlLFxuICAgIH0gPSBvcHRzO1xuXG4gICAgdGhpcy5pc1NhZmFyaSA9IGlzU2FmYXJpO1xuXG4gICAgdGhpcy5pc0Nvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubklkID0gdXRpbC51dWlkVjQoKTtcbiAgICB0aGlzLnNlbmRlcklkID0gdXRpbC51dWlkVjQoKTtcbiAgICB0aGlzLm1zZ0lkID0gMDtcblxuICAgIHRoaXMubG9nQWxsQ29tbXVuaWNhdGlvbiA9IGxvZ0FsbENvbW11bmljYXRpb247XG4gICAgdGhpcy5sb2dBbGxDb21tdW5pY2F0aW9uSGV4RHVtcCA9IGxvZ0FsbENvbW11bmljYXRpb25IZXhEdW1wO1xuICAgIHRoaXMuc29ja2V0Q2h1bmtTaXplID0gc29ja2V0Q2h1bmtTaXplO1xuICAgIHRoaXMud2ViSW5zcGVjdG9yTWF4RnJhbWVMZW5ndGggPSB3ZWJJbnNwZWN0b3JNYXhGcmFtZUxlbmd0aDtcblxuICAgIHRoaXMuZnVsbFBhZ2VJbml0aWFsaXphdGlvbiA9IGZ1bGxQYWdlSW5pdGlhbGl6YXRpb247XG5cbiAgICB0aGlzLmJ1bmRsZUlkID0gYnVuZGxlSWQ7XG4gICAgdGhpcy5wbGF0Zm9ybVZlcnNpb24gPSBwbGF0Zm9ybVZlcnNpb247XG5cbiAgICB0aGlzLl9jb250ZXh0cyA9IFtdO1xuICAgIHRoaXMuX3RhcmdldHMgPSB7fTtcblxuICAgIC8vIHN0YXJ0IHdpdGggYSBiZXN0IGd1ZXNzIGZvciB0aGUgcHJvdG9jb2xcbiAgICB0aGlzLmlzVGFyZ2V0QmFzZWQgPSBpc1RhcmdldEJhc2VkKGlzU2FmYXJpLCB0aGlzLnBsYXRmb3JtVmVyc2lvbik7XG4gIH1cblxuICBnZXQgY29udGV4dHMgKCkge1xuICAgIHJldHVybiB0aGlzLl9jb250ZXh0cztcbiAgfVxuXG4gIGdldCBuZWVkc1RhcmdldCAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc2hvdWxkQ2hlY2tGb3JUYXJnZXQgJiYgdGhpcy5pc1RhcmdldEJhc2VkO1xuICB9XG5cbiAgZ2V0IHRhcmdldHMgKCkge1xuICAgIHJldHVybiB0aGlzLl90YXJnZXRzO1xuICB9XG5cbiAgZ2V0IHNob3VsZENoZWNrRm9yVGFyZ2V0ICgpIHtcbiAgICByZXR1cm4gdGhpcy5fc2hvdWxkQ2hlY2tGb3JUYXJnZXQ7XG4gIH1cblxuICBzZXQgc2hvdWxkQ2hlY2tGb3JUYXJnZXQgKHNob3VsZENoZWNrRm9yVGFyZ2V0KSB7XG4gICAgdGhpcy5fc2hvdWxkQ2hlY2tGb3JUYXJnZXQgPSAhIXNob3VsZENoZWNrRm9yVGFyZ2V0O1xuICB9XG5cbiAgZ2V0IGlzQ29ubmVjdGVkICgpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0ZWQ7XG4gIH1cblxuICBzZXQgaXNDb25uZWN0ZWQgKGNvbm5lY3RlZCkge1xuICAgIHRoaXMuY29ubmVjdGVkID0gISFjb25uZWN0ZWQ7XG4gIH1cblxuICBvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgdGhpcy5tZXNzYWdlSGFuZGxlci5vbihldmVudCwgbGlzdGVuZXIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgb25jZSAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgdGhpcy5tZXNzYWdlSGFuZGxlci5vbmNlKGV2ZW50LCBsaXN0ZW5lcik7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvZmYgKGV2ZW50LCBsaXN0ZW5lcikge1xuICAgIHRoaXMubWVzc2FnZUhhbmRsZXIub2ZmKGV2ZW50LCBsaXN0ZW5lcik7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXQgaXNUYXJnZXRCYXNlZCAoaXNUYXJnZXRCYXNlZCkge1xuICAgIGxvZy53YXJuKGBTZXR0aW5nIGNvbW11bmljYXRpb24gcHJvdG9jb2w6IHVzaW5nICR7aXNUYXJnZXRCYXNlZCA/ICdUYXJnZXQtYmFzZWQnIDogJ2Z1bGwgV2ViIEluc3BlY3RvciBwcm90b2NvbCd9IGNvbW11bmljYXRpb25gKTtcbiAgICB0aGlzLl9pc1RhcmdldEJhc2VkID0gaXNUYXJnZXRCYXNlZDtcblxuICAgIGlmICghdGhpcy5yZW1vdGVNZXNzYWdlcykge1xuICAgICAgdGhpcy5yZW1vdGVNZXNzYWdlcyA9IG5ldyBSZW1vdGVNZXNzYWdlcyhpc1RhcmdldEJhc2VkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZW1vdGVNZXNzYWdlcy5pc1RhcmdldEJhc2VkID0gaXNUYXJnZXRCYXNlZDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMubWVzc2FnZUhhbmRsZXIpIHtcbiAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXIgPSBuZXcgUnBjTWVzc2FnZUhhbmRsZXIoaXNUYXJnZXRCYXNlZCk7XG5cbiAgICAgIC8vIGFkZCBoYW5kbGVycyBmb3IgaW50ZXJuYWwgZXZlbnRzXG4gICAgICB0aGlzLm1lc3NhZ2VIYW5kbGVyLm9uKCdUYXJnZXQudGFyZ2V0Q3JlYXRlZCcsIHRoaXMuYWRkVGFyZ2V0LmJpbmQodGhpcykpO1xuICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlci5vbignVGFyZ2V0LmRpZENvbW1pdFByb3Zpc2lvbmFsVGFyZ2V0JywgdGhpcy51cGRhdGVUYXJnZXQuYmluZCh0aGlzKSk7XG4gICAgICB0aGlzLm1lc3NhZ2VIYW5kbGVyLm9uKCdUYXJnZXQudGFyZ2V0RGVzdHJveWVkJywgdGhpcy5yZW1vdmVUYXJnZXQuYmluZCh0aGlzKSk7XG4gICAgICB0aGlzLm1lc3NhZ2VIYW5kbGVyLm9uKCdSdW50aW1lLmV4ZWN1dGlvbkNvbnRleHRDcmVhdGVkJywgdGhpcy5vbkV4ZWN1dGlvbkNvbnRleHRDcmVhdGVkLmJpbmQodGhpcykpO1xuICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlci5vbignSGVhcC5nYXJiYWdlQ29sbGVjdGVkJywgdGhpcy5vbkdhcmJhZ2VDb2xsZWN0ZWQuYmluZCh0aGlzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXIuaXNUYXJnZXRCYXNlZCA9IGlzVGFyZ2V0QmFzZWQ7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGlzVGFyZ2V0QmFzZWQgKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1RhcmdldEJhc2VkO1xuICB9XG5cbiAgYXN5bmMgd2FpdEZvclRhcmdldCAoYXBwSWRLZXksIHBhZ2VJZEtleSwgZm9yY2UgPSBmYWxzZSkge1xuICAgIGlmICghZm9yY2UgJiYgIXRoaXMubmVlZHNUYXJnZXQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5nZXRUYXJnZXQoYXBwSWRLZXksIHBhZ2VJZEtleSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBvdGhlcndpc2Ugd2FpdGluZyBpcyBuZWNlc3NhcnkgdG8gc2VlIHdoYXQgdGhlIHRhcmdldCBpc1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3YWl0Rm9yQ29uZGl0aW9uKCgpID0+ICFfLmlzRW1wdHkodGhpcy5nZXRUYXJnZXQoYXBwSWRLZXksIHBhZ2VJZEtleSkpLCB7XG4gICAgICAgIHdhaXRNczogV0FJVF9GT1JfVEFSR0VUX1RJTUVPVVQsXG4gICAgICAgIGludGVydmFsTXM6IFdBSVRfRk9SX1RBUkdFVF9JTlRFUlZBTCxcbiAgICAgICAgZXJyb3I6ICdObyB0YXJnZXRzIGZvdW5kLCB1bmFibGUgdG8gY29tbXVuaWNhdGUgd2l0aCBkZXZpY2UnLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoIWVyci5tZXNzYWdlLmluY2x1ZGVzKCdDb25kaXRpb24gdW5tZXQnKSkge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHRhcmdldHMgZm91bmQsIHVuYWJsZSB0byBjb21tdW5pY2F0ZSB3aXRoIGRldmljZScpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNlbmQgKGNvbW1hbmQsIG9wdHMgPSB7fSwgd2FpdEZvclJlc3BvbnNlID0gdHJ1ZSkge1xuICAgIGNvbnN0IHRpbWVyID0gbmV3IHRpbWluZy5UaW1lcigpLnN0YXJ0KCk7XG4gICAgY29uc3Qge1xuICAgICAgYXBwSWRLZXksXG4gICAgICBwYWdlSWRLZXlcbiAgICB9ID0gb3B0cztcbiAgICB0cnkge1xuICAgICAgaWYgKCFfLmlzRW1wdHkoYXBwSWRLZXkpICYmICFfLmlzRW1wdHkocGFnZUlkS2V5KSkge1xuICAgICAgICBhd2FpdCB0aGlzLndhaXRGb3JUYXJnZXQoYXBwSWRLZXksIHBhZ2VJZEtleSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5zZW5kVG9EZXZpY2UoY29tbWFuZCwgb3B0cywgd2FpdEZvclJlc3BvbnNlKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxldCB7IG1lc3NhZ2UgPSAnJyB9ID0gZXJyO1xuICAgICAgbWVzc2FnZSA9IG1lc3NhZ2UudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChtZXNzYWdlLmluY2x1ZGVzKGAndGFyZ2V0JyBkb21haW4gd2FzIG5vdCBmb3VuZGApKSB7XG4gICAgICAgIGxvZy5pbmZvKCdUaGUgdGFyZ2V0IGRldmljZSBkb2VzIG5vdCBzdXBwb3J0IFRhcmdldCBiYXNlZCBjb21tdW5pY2F0aW9uLiAnICtcbiAgICAgICAgICAnV2lsbCBmb2xsb3cgbm9uLXRhcmdldCBiYXNlZCBjb21tdW5pY2F0aW9uLicpO1xuICAgICAgICB0aGlzLmlzVGFyZ2V0QmFzZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuc2VuZFRvRGV2aWNlKGNvbW1hbmQsIG9wdHMsIHdhaXRGb3JSZXNwb25zZSk7XG4gICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UuaW5jbHVkZXMoYGRvbWFpbiB3YXMgbm90IGZvdW5kYCkgfHxcbiAgICAgICAgICBtZXNzYWdlLmluY2x1ZGVzKGBzb21lIGFyZ3VtZW50cyBvZiBtZXRob2RgKSB8fFxuICAgICAgICAgIG1lc3NhZ2UuaW5jbHVkZXMoYG1pc3NpbmcgdGFyZ2V0YCkpIHtcbiAgICAgICAgdGhpcy5pc1RhcmdldEJhc2VkID0gdHJ1ZTtcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yVGFyZ2V0KGFwcElkS2V5LCBwYWdlSWRLZXkpO1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5zZW5kVG9EZXZpY2UoY29tbWFuZCwgb3B0cywgd2FpdEZvclJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgbG9nLmRlYnVnKGBTZW5kaW5nIHRvIFdlYiBJbnNwZWN0b3IgdG9vayAke3RpbWVyLmdldER1cmF0aW9uKCkuYXNNaWxsaVNlY29uZHMudG9GaXhlZCgwKX1tc2ApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNlbmRUb0RldmljZSAoY29tbWFuZCwgb3B0cyA9IHt9LCB3YWl0Rm9yUmVzcG9uc2UgPSB0cnVlKSB7XG4gICAgcmV0dXJuIGF3YWl0IG5ldyBCKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIHByb21pc2UgdG8gYmUgcmVzb2x2ZWQgd2hlbmV2ZXIgcmVtb3RlIGRlYnVnZ2VyXG4gICAgICAvLyByZXBsaWVzIHRvIG91ciByZXF1ZXN0XG5cbiAgICAgIC8vIGtlZXAgdHJhY2sgb2YgdGhlIG1lc3NhZ2VzIGNvbWluZyBhbmQgZ29pbmcgdXNpbmcgYSBzaW1wbGUgc2VxdWVudGlhbCBpZFxuICAgICAgY29uc3QgbXNnSWQgPSB0aGlzLm1zZ0lkKys7XG4gICAgICBsZXQgd3JhcHBlck1zZ0lkID0gbXNnSWQ7XG4gICAgICBpZiAodGhpcy5pc1RhcmdldEJhc2VkKSB7XG4gICAgICAgIC8vIGZvciB0YXJnZXQtYmFzZSBjb21tdW5pY2F0aW9uLCBldmVyeXRoaW5nIGlzIHdyYXBwZWQgdXBcbiAgICAgICAgd3JhcHBlck1zZ0lkID0gdGhpcy5tc2dJZCsrO1xuICAgICAgICAvLyBhY2tub3dsZWRnZSB3cmFwcGVyIG1lc3NhZ2VcbiAgICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlci5vbih3cmFwcGVyTXNnSWQudG9TdHJpbmcoKSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFwcElkS2V5ID0gb3B0cy5hcHBJZEtleTtcbiAgICAgIGNvbnN0IHBhZ2VJZEtleSA9IG9wdHMucGFnZUlkS2V5O1xuICAgICAgY29uc3QgdGFyZ2V0SWQgPSB0aGlzLmdldFRhcmdldChhcHBJZEtleSwgcGFnZUlkS2V5KTtcblxuICAgICAgLy8gcmV0cmlldmUgdGhlIGNvcnJlY3QgY29tbWFuZCB0byBzZW5kXG4gICAgICBjb25zdCBmdWxsT3B0cyA9IF8uZGVmYXVsdHMoe1xuICAgICAgICBjb25uSWQ6IHRoaXMuY29ubklkLFxuICAgICAgICBzZW5kZXJJZDogdGhpcy5zZW5kZXJJZCxcbiAgICAgICAgdGFyZ2V0SWQsXG4gICAgICAgIGlkOiBtc2dJZCxcbiAgICAgIH0sIG9wdHMpO1xuICAgICAgY29uc3QgY21kID0gdGhpcy5yZW1vdGVNZXNzYWdlcy5nZXRSZW1vdGVDb21tYW5kKGNvbW1hbmQsIGZ1bGxPcHRzKTtcblxuICAgICAgaWYgKGNtZD8uX19hcmd1bWVudD8uV0lSU29ja2V0RGF0YUtleSkge1xuICAgICAgICAvLyBtYWtlIHN1cmUgdGhlIG1lc3NhZ2UgYmVpbmcgc2VudCBoYXMgYWxsIHRoZSBpbmZvcm1hdGlvbiB0aGF0IGlzIG5lZWRlZFxuICAgICAgICBpZiAoXy5pc05pbChjbWQuX19hcmd1bWVudC5XSVJTb2NrZXREYXRhS2V5LmlkKSkge1xuICAgICAgICAgIGNtZC5fX2FyZ3VtZW50LldJUlNvY2tldERhdGFLZXkuaWQgPSB3cmFwcGVyTXNnSWQ7XG4gICAgICAgIH1cbiAgICAgICAgY21kLl9fYXJndW1lbnQuV0lSU29ja2V0RGF0YUtleSA9XG4gICAgICAgICAgQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoY21kLl9fYXJndW1lbnQuV0lSU29ja2V0RGF0YUtleSkpO1xuICAgICAgfVxuXG4gICAgICBsZXQgbWVzc2FnZUhhbmRsZWQgPSB0cnVlO1xuICAgICAgaWYgKCF3YWl0Rm9yUmVzcG9uc2UpIHtcbiAgICAgICAgLy8gdGhlIHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCBhcyBzb29uIGFzIHRoZSBzb2NrZXQgaGFzIGJlZW4gc2VudFxuICAgICAgICBtZXNzYWdlSGFuZGxlZCA9IGZhbHNlO1xuICAgICAgICAvLyBkbyBub3QgbG9nIHJlY2VpcHRzXG4gICAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXIub25jZShtc2dJZC50b1N0cmluZygpLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgLy8gd2UgYXJlIG5vdCB3YWl0aW5nIGZvciB0aGlzLCBhbmQgaWYgaXQgZXJyb3JzIGl0IGlzIG1vc3QgbGlrZWx5XG4gICAgICAgICAgICAvLyBhIHByb3RvY29sIGNoYW5nZS4gTG9nIGFuZCBjaGVjayBkdXJpbmcgdGVzdGluZ1xuICAgICAgICAgICAgbG9nLmVycm9yKGBSZWNlaXZlZCBlcnJvciBmcm9tIHNlbmQgdGhhdCBpcyBub3QgYmVpbmcgd2FpdGVkIGZvciAoaWQ6ICR7bXNnSWR9KTogJyR7Xy50cnVuY2F0ZShKU09OLnN0cmluZ2lmeShlcnIpLCBEQVRBX0xPR19MRU5HVEgpfSdgKTtcbiAgICAgICAgICAgIC8vIHJlamVjdCwgdGhvdWdoIGl0IGlzIHZlcnkgcmFyZSB0aGF0IHRoaXMgd2lsbCBiZSB0cmlnZ2VyZWQsIHNpbmNlXG4gICAgICAgICAgICAvLyB0aGUgcHJvbWlzZSBpcyByZXNvbHZlZCBkaXJlY3RsdHkgYWZ0ZXIgc2VuZC4gT24gdGhlIG9mZiBjaGFuY2UsXG4gICAgICAgICAgICAvLyB0aG91Z2gsIGl0IHdpbGwgYWxlcnQgb2YgYSBwcm90b2NvbCBjaGFuZ2UuXG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLm1lc3NhZ2VIYW5kbGVyLmxpc3RlbmVycyhjbWQuX19zZWxlY3RvcikubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXIucHJlcGVuZE9uY2VMaXN0ZW5lcihjbWQuX19zZWxlY3RvciwgZnVuY3Rpb24gKGVyciwgLi4uYXJncykge1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbG9nLmRlYnVnKGBSZWNlaXZlZCByZXNwb25zZSBmcm9tIHNlbmQgKGlkOiAke21zZ0lkfSk6ICcke18udHJ1bmNhdGUoSlNPTi5zdHJpbmdpZnkoYXJncyksIERBVEFfTE9HX0xFTkdUSCl9J2ApO1xuICAgICAgICAgIHJlc29sdmUoYXJncyk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChjbWQ/Ll9fYXJndW1lbnQ/LldJUlNvY2tldERhdGFLZXkpIHtcbiAgICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlci5vbmNlKG1zZ0lkLnRvU3RyaW5nKCksIGZ1bmN0aW9uIChlcnIsIHZhbHVlKSB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoYFJlbW90ZSBkZWJ1Z2dlciBlcnJvciB3aXRoIGNvZGUgJyR7ZXJyLmNvZGV9JzogJHtlcnIubWVzc2FnZX1gKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxvZy5kZWJ1ZyhgUmVjZWl2ZWQgZGF0YSByZXNwb25zZSBmcm9tIHNlbmQgKGlkOiAke21zZ0lkfSk6ICcke18udHJ1bmNhdGUoSlNPTi5zdHJpbmdpZnkodmFsdWUpLCBEQVRBX0xPR19MRU5HVEgpfSdgKTtcbiAgICAgICAgICByZXNvbHZlKHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBub3RoaW5nIGVsc2UgaXMgaGFuZGxpbmcgdGhpbmdzLCBzbyBqdXN0IHJlc29sdmUgd2hlbiB0aGUgbWVzc2FnZSBpcyBzZW50XG4gICAgICAgIG1lc3NhZ2VIYW5kbGVkID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1zZyA9IGBTZW5kaW5nICcke2NtZC5fX3NlbGVjdG9yfScgbWVzc2FnZWAgK1xuICAgICAgICAoZnVsbE9wdHMuYXBwSWRLZXkgPyBgIHRvIGFwcCAnJHtmdWxsT3B0cy5hcHBJZEtleX0nYCA6ICcnKSArXG4gICAgICAgIChmdWxsT3B0cy5wYWdlSWRLZXkgPyBgLCBwYWdlICcke2Z1bGxPcHRzLnBhZ2VJZEtleX0nYCA6ICcnKSArXG4gICAgICAgICh0aGlzLm5lZWRzVGFyZ2V0ICYmIHRhcmdldElkID8gYCwgdGFyZ2V0ICcke3RhcmdldElkfSdgIDogJycpICtcbiAgICAgICAgYCAoaWQ6ICR7bXNnSWR9KTogJyR7Y29tbWFuZH0nYDtcbiAgICAgIGxvZy5kZWJ1Zyhtc2cpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5zZW5kTWVzc2FnZShjbWQpO1xuICAgICAgICBpZiAoIW1lc3NhZ2VIYW5kbGVkKSB7XG4gICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGhhbmRsZXJzIHdhaXRpbmcgZm9yIGEgcmVzcG9uc2UgYmVmb3JlIHJlc29sdmluZyxcbiAgICAgICAgICAvLyBhbmQgbm8gZXJyb3JzIHNlbmRpbmcgdGhlIG1lc3NhZ2Ugb3ZlciB0aGUgc29ja2V0LCBzbyByZXNvbHZlXG4gICAgICAgICAgcmVzb2x2ZShyZXMpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgY29ubmVjdCAoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcmVxdWlyZS1hd2FpdFxuICAgIHRocm93IG5ldyBFcnJvcihgU3ViLWNsYXNzZXMgbmVlZCB0byBpbXBsZW1lbnQgYSAnY29ubmVjdCcgZnVuY3Rpb25gKTtcbiAgfVxuXG4gIGFzeW5jIGRpc2Nvbm5lY3QgKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICB0aGlzLm1lc3NhZ2VIYW5kbGVyLnJlbW92ZUFsbExpc3RlbmVycygpO1xuICB9XG5cbiAgYXN5bmMgc2VuZE1lc3NhZ2UgKC8qIGNvbW1hbmQgKi8pIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSByZXF1aXJlLWF3YWl0XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTdWItY2xhc3NlcyBuZWVkIHRvIGltcGxlbWVudCBhICdzZW5kTWVzc2FnZScgZnVuY3Rpb25gKTtcbiAgfVxuXG4gIGFzeW5jIHJlY2VpdmUgKC8qIGRhdGEgKi8pIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSByZXF1aXJlLWF3YWl0XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTdWItY2xhc3NlcyBuZWVkIHRvIGltcGxlbWVudCBhICdyZWNlaXZlJyBmdW5jdGlvbmApO1xuICB9XG5cbiAgYWRkVGFyZ2V0IChlcnIsIGFwcCwgdGFyZ2V0SW5mbykge1xuICAgIGlmIChfLmlzTmlsKHRhcmdldEluZm8/LnRhcmdldElkKSkge1xuICAgICAgbG9nLndhcm4oYFJlY2VpdmVkICdUYXJnZXQudGFyZ2V0Q3JlYXRlZCcgZXZlbnQgZm9yIGFwcCAnJHthcHB9JyB3aXRoIG5vIHRhcmdldC4gU2tpcHBpbmdgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKF8uaXNFbXB0eSh0aGlzLnBlbmRpbmdUYXJnZXROb3RpZmljYXRpb24pICYmICF0YXJnZXRJbmZvLmlzUHJvdmlzaW9uYWwpIHtcbiAgICAgIGxvZy53YXJuKGBSZWNlaXZlZCAnVGFyZ2V0LnRhcmdldENyZWF0ZWQnIGV2ZW50IGZvciBhcHAgJyR7YXBwfScgd2l0aCBubyBwZW5kaW5nIHJlcXVlc3Q6ICR7SlNPTi5zdHJpbmdpZnkodGFyZ2V0SW5mbyl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRhcmdldEluZm8uaXNQcm92aXNpb25hbCkge1xuICAgICAgbG9nLmRlYnVnKGBQcm92aXNpb25hbCB0YXJnZXQgY3JlYXRlZCBmb3IgYXBwICcke2FwcH0nLCAnJHt0YXJnZXRJbmZvLnRhcmdldElkfScuIElnbm9yaW5nIHVudGlsIHRhcmdldCB1cGRhdGUgZXZlbnRgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBbYXBwSWRLZXksIHBhZ2VJZEtleV0gPSB0aGlzLnBlbmRpbmdUYXJnZXROb3RpZmljYXRpb247XG5cbiAgICBsb2cuZGVidWcoYFRhcmdldCBjcmVhdGVkIGZvciBhcHAgJyR7YXBwSWRLZXl9JyBhbmQgcGFnZSAnJHtwYWdlSWRLZXl9JzogJHtKU09OLnN0cmluZ2lmeSh0YXJnZXRJbmZvKX1gKTtcbiAgICBpZiAoXy5oYXModGhpcy50YXJnZXRzW2FwcElkS2V5XSwgcGFnZUlkS2V5KSkge1xuICAgICAgbG9nLmRlYnVnKGBUaGVyZSBpcyBhbHJlYWR5IGEgdGFyZ2V0IGZvciB0aGlzIGFwcCBhbmQgcGFnZSAoJyR7dGhpcy50YXJnZXRzW2FwcElkS2V5XVtwYWdlSWRLZXldfScpLiBUaGlzIG1pZ2h0IGNhdXNlIHByb2JsZW1zYCk7XG4gICAgfVxuICAgIHRoaXMudGFyZ2V0c1thcHBdID0gdGhpcy50YXJnZXRzW2FwcF0gfHwge307XG4gICAgdGhpcy50YXJnZXRzW2FwcElkS2V5XVtwYWdlSWRLZXldID0gdGFyZ2V0SW5mby50YXJnZXRJZDtcbiAgfVxuXG4gIHVwZGF0ZVRhcmdldCAoZXJyLCBhcHAsIG9sZFRhcmdldElkLCBuZXdUYXJnZXRJZCkge1xuICAgIGxvZy5kZWJ1ZyhgVGFyZ2V0IHVwZGF0ZWQgZm9yIGFwcCAnJHthcHB9Jy4gT2xkIHRhcmdldDogJyR7b2xkVGFyZ2V0SWR9JywgbmV3IHRhcmdldDogJyR7bmV3VGFyZ2V0SWR9J2ApO1xuICAgIGlmICghdGhpcy50YXJnZXRzW2FwcF0pIHtcbiAgICAgIGxvZy53YXJuKGBObyBleGlzdGluZyB0YXJnZXQgZm9yIGFwcCAnJHthcHB9Jy4gTm90IHN1cmUgd2hhdCB0byBkb2ApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBzYXZlIHRoaXMsIHRvIGJlIHVzZWQgaWYvd2hlbiB0aGUgZXhpc3RpbmcgdGFyZ2V0IGlzIGRlc3Ryb3llZFxuICAgIHRoaXMudGFyZ2V0c1thcHBdLnByb3Zpc2lvbmFsID0ge1xuICAgICAgb2xkVGFyZ2V0SWQsXG4gICAgICBuZXdUYXJnZXRJZCxcbiAgICB9O1xuICB9XG5cbiAgcmVtb3ZlVGFyZ2V0IChlcnIsIGFwcCwgdGFyZ2V0SW5mbykge1xuICAgIGlmIChfLmlzTmlsKHRhcmdldEluZm8/LnRhcmdldElkKSkge1xuICAgICAgbG9nLmRlYnVnKGBSZWNlaXZlZCAnVGFyZ2V0LnRhcmdldERlc3Ryb3llZCcgZXZlbnQgd2l0aCBubyB0YXJnZXQuIFNraXBwaW5nYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbG9nLmRlYnVnKGBUYXJnZXQgZGVzdHJveWVkIGZvciBhcHAgJyR7YXBwfSc6ICR7dGFyZ2V0SW5mby50YXJnZXRJZH1gKTtcblxuICAgIC8vIGdvIHRocm91Z2ggdGhlIHRhcmdldHMgYW5kIGZpbmQgdGhlIG9uZSB0aGF0IGhhcyBhIHdhaXRpbmcgcHJvdmlzaW9uYWwgdGFyZ2V0XG4gICAgaWYgKHRoaXMudGFyZ2V0c1thcHBdPy5wcm92aXNpb25hbD8ub2xkVGFyZ2V0SWQgPT09IHRhcmdldEluZm8udGFyZ2V0SWQpIHtcbiAgICAgIGNvbnN0IHtvbGRUYXJnZXRJZCwgbmV3VGFyZ2V0SWR9ID0gdGhpcy50YXJnZXRzW2FwcF0ucHJvdmlzaW9uYWw7XG4gICAgICBkZWxldGUgdGhpcy50YXJnZXRzW2FwcF0ucHJvdmlzaW9uYWw7XG5cbiAgICAgIC8vIHdlIGRvIG5vdCBrbm93IHRoZSBwYWdlLCBzbyBnbyB0aHJvdWdoIGFuZCBmaW5kIHRoZSBleGlzdGluZyB0YXJnZXRcbiAgICAgIGNvbnN0IHRhcmdldHMgPSB0aGlzLnRhcmdldHNbYXBwXTtcbiAgICAgIGZvciAoY29uc3QgW3BhZ2UsIHRhcmdldElkXSBvZiBfLnRvUGFpcnModGFyZ2V0cykpIHtcbiAgICAgICAgaWYgKHRhcmdldElkID09PSBvbGRUYXJnZXRJZCkge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhgRm91bmQgcHJvdmlzaW9uYWwgdGFyZ2V0IGZvciBhcHAgJyR7YXBwfScuIE9sZCB0YXJnZXQ6ICcke29sZFRhcmdldElkfScsIG5ldyB0YXJnZXQ6ICcke25ld1RhcmdldElkfScuIFVwZGF0aW5nYCk7XG4gICAgICAgICAgdGFyZ2V0c1twYWdlXSA9IG5ld1RhcmdldElkO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbG9nLndhcm4oYFByb3Zpc2lvbmFsIHRhcmdldCBmb3IgYXBwICcke2FwcH0nIGZvdW5kLCBidXQgbm8gc3VpdGFibGUgZXhpc3RpbmcgdGFyZ2V0IGZvdW5kLiBUaGlzIG1heSBjYXVzZSBwcm9ibGVtc2ApO1xuICAgICAgbG9nLndhcm4oYE9sZCB0YXJnZXQ6ICcke29sZFRhcmdldElkfScsIG5ldyB0YXJnZXQ6ICcke25ld1RhcmdldElkfScuIEV4aXN0aW5nIHRhcmdldHM6ICR7SlNPTi5zdHJpbmdpZnkodGFyZ2V0cyl9YCk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgbm8gd2FpdGluZyBwcm92aXNpb25hbCB0YXJnZXQsIGp1c3QgZ2V0IHJpZCBvZiB0aGUgZXhpc3Rpbmcgb25lXG4gICAgY29uc3QgdGFyZ2V0cyA9IHRoaXMudGFyZ2V0c1thcHBdO1xuICAgIGZvciAoY29uc3QgW3BhZ2UsIHRhcmdldElkXSBvZiBfLnRvUGFpcnModGFyZ2V0cykpIHtcbiAgICAgIGlmICh0YXJnZXRJZCA9PT0gdGFyZ2V0SW5mby50YXJnZXRJZCkge1xuICAgICAgICBkZWxldGUgdGFyZ2V0c1twYWdlXTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cbiAgICBsb2cuZGVidWcoYFRhcmdldCAnJHt0YXJnZXRJbmZvLnRhcmdldElkfScgZGVsZXRlZCBmb3IgYXBwICcke2FwcH0nLCBidXQgbm8gc3VjaCB0YXJnZXQgZXhpc3RzYCk7XG4gIH1cblxuICBnZXRUYXJnZXQgKGFwcElkS2V5LCBwYWdlSWRLZXkpIHtcbiAgICByZXR1cm4gKHRoaXMudGFyZ2V0c1thcHBJZEtleV0gfHwge30pW3BhZ2VJZEtleV07XG4gIH1cblxuICBhc3luYyBzZWxlY3RQYWdlIChhcHBJZEtleSwgcGFnZUlkS2V5KSB7XG4gICAgdGhpcy5wZW5kaW5nVGFyZ2V0Tm90aWZpY2F0aW9uID0gW2FwcElkS2V5LCBwYWdlSWRLZXldO1xuICAgIHRoaXMuc2hvdWxkQ2hlY2tGb3JUYXJnZXQgPSBmYWxzZTtcblxuICAgIC8vIGdvIHRocm91Z2ggdGhlIHN0ZXBzIHRoYXQgdGhlIERlc2t0b3AgU2FmYXJpIHN5c3RlbVxuICAgIC8vIGdvZXMgdGhyb3VnaCB0byBpbml0aWFsaXplIHRoZSBXZWIgSW5zcGVjdG9yIHNlc3Npb25cblxuICAgIGNvbnN0IHNlbmRPcHRzID0ge1xuICAgICAgYXBwSWRLZXksXG4gICAgICBwYWdlSWRLZXksXG4gICAgfTtcblxuICAgIC8vIGhpZ2hsaWdodCBhbmQgdGhlbiB1bi1oaWdobGlnaHQgdGhlIHdlYnZpZXdcbiAgICBmb3IgKGNvbnN0IGVuYWJsZWQgb2YgW3RydWUsIGZhbHNlXSkge1xuICAgICAgYXdhaXQgdGhpcy5zZW5kKCdpbmRpY2F0ZVdlYlZpZXcnLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgZW5hYmxlZCxcbiAgICAgIH0sIHNlbmRPcHRzKSwgZmFsc2UpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2VuZCgnc2V0U2VuZGVyS2V5Jywgc2VuZE9wdHMpO1xuICAgIGxvZy5kZWJ1ZygnU2VuZGVyIGtleSBzZXQnKTtcblxuICAgIGlmICh0aGlzLmlzVGFyZ2V0QmFzZWQgJiYgdXRpbC5jb21wYXJlVmVyc2lvbnModGhpcy5wbGF0Zm9ybVZlcnNpb24sICc8JywgTUlOX1BMQVRGT1JNX05PX1RBUkdFVF9FWElTVFMpKSB7XG4gICAgICBhd2FpdCB0aGlzLnNlbmQoJ1RhcmdldC5leGlzdHMnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIH1cblxuICAgIHRoaXMuc2hvdWxkQ2hlY2tGb3JUYXJnZXQgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMuZnVsbFBhZ2VJbml0aWFsaXphdGlvbikge1xuICAgICAgYXdhaXQgdGhpcy5pbml0aWFsaXplUGFnZUZ1bGwoYXBwSWRLZXksIHBhZ2VJZEtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZVBhZ2UoYXBwSWRLZXksIHBhZ2VJZEtleSk7XG4gICAgfVxuICB9XG5cbiAgLypcbiAgICogUGVyZm9ybSB0aGUgbWluaW1hbCBpbml0aWFsaXphdGlvbiB0byBnZXQgdGhlIFdlYiBJbnNwZWN0b3Igd29ya2luZ1xuICAgKi9cbiAgYXN5bmMgaW5pdGlhbGl6ZVBhZ2UgKGFwcElkS2V5LCBwYWdlSWRLZXkpIHtcbiAgICBjb25zdCBzZW5kT3B0cyA9IHtcbiAgICAgIGFwcElkS2V5LFxuICAgICAgcGFnZUlkS2V5LFxuICAgIH07XG5cbiAgICBhd2FpdCB0aGlzLnNlbmQoJ0luc3BlY3Rvci5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnUGFnZS5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuXG4gICAgLy8gZ28gdGhyb3VnaCB0aGUgdGFza3MgdG8gaW5pdGlhbGl6ZVxuICAgIGF3YWl0IHRoaXMuc2VuZCgnTmV0d29yay5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnUnVudGltZS5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnSGVhcC5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnRGVidWdnZXIuZW5hYmxlJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ0NvbnNvbGUuZW5hYmxlJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ0luc3BlY3Rvci5pbml0aWFsaXplZCcsIHNlbmRPcHRzLCBmYWxzZSk7XG4gIH1cblxuICAvKlxuICAgKiBNaW1pYyBldmVyeSBzdGVwIHRoYXQgRGVza3RvcCBTYWZhcmkgRGV2ZWxvcCB0b29scyB1c2VzIHRvIGluaXRpYWxpemUgYVxuICAgKiBXZWIgSW5zcGVjdG9yIHNlc3Npb25cbiAgICovXG4gIGFzeW5jIGluaXRpYWxpemVQYWdlRnVsbCAoYXBwSWRLZXksIHBhZ2VJZEtleSkge1xuICAgIGNvbnN0IHNlbmRPcHRzID0ge1xuICAgICAgYXBwSWRLZXksXG4gICAgICBwYWdlSWRLZXksXG4gICAgfTtcblxuICAgIGF3YWl0IHRoaXMuc2VuZCgnSW5zcGVjdG9yLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdQYWdlLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG5cbiAgICAvLyBnbyB0aHJvdWdoIHRoZSB0YXNrcyB0byBpbml0aWFsaXplXG4gICAgYXdhaXQgdGhpcy5zZW5kKCdQYWdlLmdldFJlc291cmNlVHJlZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdOZXR3b3JrLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdOZXR3b3JrLnNldFJlc291cmNlQ2FjaGluZ0Rpc2FibGVkJywgT2JqZWN0LmFzc2lnbih7XG4gICAgICBkaXNhYmxlZDogZmFsc2UsXG4gICAgfSwgc2VuZE9wdHMpLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdET01TdG9yYWdlLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdEYXRhYmFzZS5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnSW5kZXhlZERCLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdDU1MuZW5hYmxlJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ1J1bnRpbWUuZW5hYmxlJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ0hlYXAuZW5hYmxlJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ01lbW9yeS5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnQXBwbGljYXRpb25DYWNoZS5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnQXBwbGljYXRpb25DYWNoZS5nZXRGcmFtZXNXaXRoTWFuaWZlc3RzJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ1RpbWVsaW5lLnNldEluc3RydW1lbnRzJywgT2JqZWN0LmFzc2lnbih7XG4gICAgICBpbnN0cnVtZW50czogWydUaW1lbGluZScsICdTY3JpcHRQcm9maWxlcicsICdDUFUnXSxcbiAgICB9LCBzZW5kT3B0cyksIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ1RpbWVsaW5lLnNldEF1dG9DYXB0dXJlRW5hYmxlZCcsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgfSwgc2VuZE9wdHMpLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdEZWJ1Z2dlci5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnRGVidWdnZXIuc2V0QnJlYWtwb2ludHNBY3RpdmUnLCBPYmplY3QuYXNzaWduKHtcbiAgICAgIGFjdGl2ZTogdHJ1ZSxcbiAgICB9LCBzZW5kT3B0cyksIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ0RlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zJywgT2JqZWN0LmFzc2lnbih7XG4gICAgICBzdGF0ZTogJ25vbmUnLFxuICAgIH0sIHNlbmRPcHRzKSwgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnRGVidWdnZXIuc2V0UGF1c2VPbkFzc2VydGlvbnMnLCBPYmplY3QuYXNzaWduKHtcbiAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgIH0sIHNlbmRPcHRzKSwgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnRGVidWdnZXIuc2V0QXN5bmNTdGFja1RyYWNlRGVwdGgnLCBPYmplY3QuYXNzaWduKHtcbiAgICAgIGRlcHRoOiAyMDAsXG4gICAgfSwgc2VuZE9wdHMpLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdEZWJ1Z2dlci5zZXRQYXVzZUZvckludGVybmFsU2NyaXB0cycsIE9iamVjdC5hc3NpZ24oe1xuICAgICAgc2hvdWxkUGF1c2U6IGZhbHNlLFxuICAgIH0sIHNlbmRPcHRzKSwgZmFsc2UpO1xuXG4gICAgYXdhaXQgdGhpcy5zZW5kKCdMYXllclRyZWUuZW5hYmxlJywgc2VuZE9wdHMsIGZhbHNlKTtcbiAgICBhd2FpdCB0aGlzLnNlbmQoJ1dvcmtlci5lbmFibGUnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGF3YWl0IHRoaXMuc2VuZCgnQ2FudmFzLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdDb25zb2xlLmVuYWJsZScsIHNlbmRPcHRzLCBmYWxzZSk7XG4gICAgYXdhaXQgdGhpcy5zZW5kKCdET00uZ2V0RG9jdW1lbnQnLCBzZW5kT3B0cywgZmFsc2UpO1xuICAgIGNvbnN0IGxvZ2dpbmdDaGFubmVscyA9IGF3YWl0IHRoaXMuc2VuZCgnQ29uc29sZS5nZXRMb2dnaW5nQ2hhbm5lbHMnLCBzZW5kT3B0cyk7XG4gICAgZm9yIChjb25zdCBzb3VyY2Ugb2YgKGxvZ2dpbmdDaGFubmVscy5jaGFubmVscyB8fCBbXSkubWFwKChlbnRyeSkgPT4gZW50cnkuc291cmNlKSkge1xuICAgICAgYXdhaXQgdGhpcy5zZW5kKCdDb25zb2xlLnNldExvZ2dpbmdDaGFubmVsTGV2ZWwnLCBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgc291cmNlLFxuICAgICAgICBsZXZlbDogJ3ZlcmJvc2UnLFxuICAgICAgfSwgc2VuZE9wdHMpLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5zZW5kKCdJbnNwZWN0b3IuaW5pdGlhbGl6ZWQnLCBzZW5kT3B0cywgZmFsc2UpO1xuICB9XG5cbiAgYXN5bmMgc2VsZWN0QXBwIChhcHBJZEtleSkge1xuICAgIHJldHVybiBhd2FpdCBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBsb2NhbCBjYWxsYmFjaywgdGVtcG9yYXJpbHkgYWRkZWQgYXMgY2FsbGJhY2sgdG9cbiAgICAgIC8vIGBfcnBjX2FwcGxpY2F0aW9uQ29ubmVjdGVkOmAgcmVtb3RlIGRlYnVnZ2VyIHJlc3BvbnNlXG4gICAgICAvLyB0byBoYW5kbGUgdGhlIGluaXRpYWwgY29ubmVjdGlvblxuICAgICAgY29uc3Qgb25BcHBDaGFuZ2UgPSAoZXJyLCBkaWN0KSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZnJvbSB0aGUgZGljdGlvbmFyeSByZXR1cm5lZCwgZ2V0IHRoZSBpZHNcbiAgICAgICAgY29uc3Qgb2xkQXBwSWRLZXkgPSBkaWN0LldJUkhvc3RBcHBsaWNhdGlvbklkZW50aWZpZXJLZXk7XG4gICAgICAgIGNvbnN0IGNvcnJlY3RBcHBJZEtleSA9IGRpY3QuV0lSQXBwbGljYXRpb25JZGVudGlmaWVyS2V5O1xuXG4gICAgICAgIC8vIGlmIHRoaXMgaXMgYSByZXBvcnQgb2YgYSBwcm94eSByZWRpcmVjdCBmcm9tIHRoZSByZW1vdGUgZGVidWdnZXJcbiAgICAgICAgLy8gd2Ugd2FudCB0byB1cGRhdGUgb3VyIGRpY3Rpb25hcnkgYW5kIGdldCBhIG5ldyBhcHAgaWRcbiAgICAgICAgaWYgKG9sZEFwcElkS2V5ICYmIGNvcnJlY3RBcHBJZEtleSAhPT0gb2xkQXBwSWRLZXkpIHtcbiAgICAgICAgICBsb2cuZGVidWcoYFdlIHdlcmUgbm90aWZpZWQgd2UgbWlnaHQgaGF2ZSBjb25uZWN0ZWQgdG8gdGhlIHdyb25nIGFwcC4gYCArXG4gICAgICAgICAgICAgICAgICAgIGBVc2luZyBpZCAke2NvcnJlY3RBcHBJZEtleX0gaW5zdGVhZCBvZiAke29sZEFwcElkS2V5fWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignTmV3IGFwcGxpY2F0aW9uIGhhcyBjb25uZWN0ZWQnKSk7XG4gICAgICB9O1xuICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlci5wcmVwZW5kT25jZUxpc3RlbmVyKCdfcnBjX2FwcGxpY2F0aW9uQ29ubmVjdGVkOicsIG9uQXBwQ2hhbmdlKTtcblxuICAgICAgLy8gZG8gdGhlIGFjdHVhbCBjb25uZWN0aW5nIHRvIHRoZSBhcHBcbiAgICAgIHJldHVybiAoYXN5bmMgKCkgPT4ge1xuICAgICAgICBsZXQgcGFnZURpY3QsIGNvbm5lY3RlZEFwcElkS2V5O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIChbY29ubmVjdGVkQXBwSWRLZXksIHBhZ2VEaWN0XSA9IGF3YWl0IHRoaXMuc2VuZCgnY29ubmVjdFRvQXBwJywge1xuICAgICAgICAgICAgYXBwSWRLZXlcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGxvZy53YXJuKGBVbmFibGUgdG8gY29ubmVjdCB0byBhcHA6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzb21ldGltZXMgdGhlIGNvbm5lY3QgbG9naWMgaGFwcGVucywgYnV0IHdpdGggYW4gZW1wdHkgZGljdGlvbmFyeVxuICAgICAgICAvLyB3aGljaCBsZWFkcyB0byB0aGUgcmVtb3RlIGRlYnVnZ2VyIGdldHRpbmcgZGlzY29ubmVjdGVkLCBhbmQgaW50byBhIGxvb3BcbiAgICAgICAgaWYgKF8uaXNFbXB0eShwYWdlRGljdCkpIHtcbiAgICAgICAgICBsZXQgbXNnID0gJ0VtcHR5IHBhZ2UgZGljdGlvbmFyeSByZWNlaXZlZCc7XG4gICAgICAgICAgbG9nLmRlYnVnKG1zZyk7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihtc2cpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKFtjb25uZWN0ZWRBcHBJZEtleSwgcGFnZURpY3RdKTtcbiAgICAgICAgfVxuICAgICAgfSkoKTtcbiAgICB9KTtcbiAgfVxuXG4gIG9uRXhlY3V0aW9uQ29udGV4dENyZWF0ZWQgKGVyciwgY29udGV4dCkge1xuICAgIC8vIHsgaWQ6IDIsIGlzUGFnZUNvbnRleHQ6IHRydWUsIG5hbWU6ICcnLCBmcmFtZUlkOiAnMC4xJyB9XG4gICAgLy8gcmlnaHQgbm93IHdlIGhhdmUgbm8gd2F5IHRvIG1hcCBjb250ZXh0cyB0byBhcHBzL3BhZ2VzXG4gICAgLy8gc28ganVzdCBzdG9yZVxuICAgIHRoaXMuY29udGV4dHMucHVzaChjb250ZXh0LmlkKTtcbiAgfVxuXG4gIG9uR2FyYmFnZUNvbGxlY3RlZCAoKSB7XG4gICAgLy8ganVzdCB3YW50IHRvIGxvZyB0aGF0IHRoaXMgaXMgaGFwcGVuaW5nLCBhcyBpdCBjYW4gYWZmZWN0IG9wZXJ0aW9uXG4gICAgbG9nLmRlYnVnKGBXZWIgSW5zcGVjdG9yIGdhcmJhZ2UgY29sbGVjdGVkYCk7XG4gIH1cblxuICBvblNjcmlwdFBhcnNlZCAoZXJyLCBzY3JpcHRJbmZvKSB7XG4gICAgLy8geyBzY3JpcHRJZDogJzEzJywgdXJsOiAnJywgc3RhcnRMaW5lOiAwLCBzdGFydENvbHVtbjogMCwgZW5kTGluZTogODIsIGVuZENvbHVtbjogMyB9XG4gICAgbG9nLmRlYnVnKGBTY3JpcHQgcGFyc2VkOiAke0pTT04uc3RyaW5naWZ5KHNjcmlwdEluZm8pfWApO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUEsSUFBQUEsZUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsU0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsT0FBQSxHQUFBSCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUksU0FBQSxHQUFBTCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUssa0JBQUEsR0FBQU4sc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFNLFFBQUEsR0FBQU4sT0FBQTtBQUdBLE1BQU1PLGVBQWUsR0FBRztFQUFDQyxNQUFNLEVBQUU7QUFBRyxDQUFDO0FBRXJDLE1BQU1DLHVCQUF1QixHQUFHLEtBQUs7QUFDckMsTUFBTUMsd0JBQXdCLEdBQUcsSUFBSTtBQUVyQyxNQUFNQyw2QkFBNkIsR0FBRyxNQUFNO0FBRzVDLE1BQU1DLDZCQUE2QixHQUFHLE1BQU07QUFFNUMsU0FBU0MsYUFBYUEsQ0FBRUMsUUFBUSxFQUFFQyxlQUFlLEVBQUU7RUFJakQsTUFBTUMsYUFBYSxHQUFHQyxhQUFJLENBQUNDLGVBQWUsQ0FBQ0gsZUFBZSxFQUFFLElBQUksRUFBRUosNkJBQTZCLENBQUM7RUFDaEdRLGVBQUcsQ0FB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
|
|
594
|
+
//# sourceMappingURL=rpc-client.js.map
|