appium-remote-debugger 11.5.3 → 11.5.5
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 +12 -0
- package/build/lib/mixins/connect.d.ts +15 -41
- package/build/lib/mixins/connect.d.ts.map +1 -1
- package/build/lib/mixins/connect.js +80 -95
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/message-handlers.d.ts +4 -4
- package/build/lib/mixins/message-handlers.d.ts.map +1 -1
- package/build/lib/mixins/message-handlers.js +25 -67
- package/build/lib/mixins/message-handlers.js.map +1 -1
- package/build/lib/remote-debugger-real-device.d.ts.map +1 -1
- package/build/lib/remote-debugger-real-device.js +1 -5
- package/build/lib/remote-debugger-real-device.js.map +1 -1
- package/build/lib/remote-debugger.d.ts +0 -2
- package/build/lib/remote-debugger.d.ts.map +1 -1
- package/build/lib/remote-debugger.js +0 -2
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/lib/rpc/remote-messages.d.ts +1 -1
- package/build/lib/rpc/remote-messages.d.ts.map +1 -1
- package/build/lib/rpc/remote-messages.js.map +1 -1
- package/build/lib/rpc/rpc-client-real-device.d.ts +10 -2
- package/build/lib/rpc/rpc-client-real-device.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client-real-device.js +17 -0
- package/build/lib/rpc/rpc-client-real-device.js.map +1 -1
- package/build/lib/rpc/rpc-client-simulator.d.ts +33 -9
- package/build/lib/rpc/rpc-client-simulator.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client-simulator.js +25 -1
- package/build/lib/rpc/rpc-client-simulator.js.map +1 -1
- package/build/lib/rpc/rpc-client.d.ts +114 -27
- package/build/lib/rpc/rpc-client.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client.js +101 -27
- package/build/lib/rpc/rpc-client.js.map +1 -1
- package/build/lib/utils.d.ts +14 -7
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +15 -20
- package/build/lib/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/mixins/connect.js +84 -105
- package/lib/mixins/message-handlers.js +30 -70
- package/lib/remote-debugger-real-device.js +1 -5
- package/lib/remote-debugger.js +1 -3
- package/lib/rpc/remote-messages.js +1 -2
- package/lib/rpc/rpc-client-real-device.js +18 -1
- package/lib/rpc/rpc-client-simulator.js +41 -2
- package/lib/rpc/rpc-client.js +149 -33
- package/lib/utils.js +15 -20
- package/package.json +1 -2
package/lib/mixins/connect.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pageArrayFromDict,
|
|
3
3
|
getPossibleDebuggerAppKeys,
|
|
4
|
-
simpleStringify,
|
|
5
4
|
} from '../utils';
|
|
6
5
|
import events from './events';
|
|
7
6
|
import { timing } from '@appium/support';
|
|
8
7
|
import { retryInterval, waitForCondition } from 'asyncbox';
|
|
9
8
|
import _ from 'lodash';
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
const APP_CONNECT_TIMEOUT_MS = 0;
|
|
13
11
|
const APP_CONNECT_INTERVAL_MS = 100;
|
|
14
12
|
const SELECT_APP_RETRIES = 20;
|
|
@@ -16,19 +14,6 @@ const SELECT_APP_RETRY_SLEEP_MS = 500;
|
|
|
16
14
|
const SAFARI_BUNDLE_ID = 'com.apple.mobilesafari';
|
|
17
15
|
const BLANK_PAGE_URL = 'about:blank';
|
|
18
16
|
|
|
19
|
-
/**
|
|
20
|
-
* @typedef {Object} AppPages
|
|
21
|
-
* @property {string} appIdKey
|
|
22
|
-
* @property {Record<string, any>} pageDict
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {Object} App
|
|
27
|
-
* @property {string} id
|
|
28
|
-
* @property {string} bundleId
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
17
|
/**
|
|
33
18
|
*
|
|
34
19
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
@@ -104,21 +89,12 @@ export async function disconnect () {
|
|
|
104
89
|
this.teardown();
|
|
105
90
|
}
|
|
106
91
|
|
|
107
|
-
/**
|
|
108
|
-
* @typedef {Object} Page
|
|
109
|
-
* @property {string} url
|
|
110
|
-
* @property {string} title
|
|
111
|
-
* @property {number} id
|
|
112
|
-
* @property {boolean} isKey
|
|
113
|
-
* @property {string} [bundleId]
|
|
114
|
-
*/
|
|
115
|
-
|
|
116
92
|
/**
|
|
117
93
|
*
|
|
118
94
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
119
|
-
* @param {string?} currentUrl
|
|
120
|
-
* @param {number} [maxTries]
|
|
121
|
-
* @param {boolean} [ignoreAboutBlankUrl]
|
|
95
|
+
* @param {string?} [currentUrl=null]
|
|
96
|
+
* @param {number} [maxTries=SELECT_APP_RETRIES]
|
|
97
|
+
* @param {boolean} [ignoreAboutBlankUrl=false]
|
|
122
98
|
* @returns {Promise<Page[]>}
|
|
123
99
|
*/
|
|
124
100
|
export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIES, ignoreAboutBlankUrl = false) {
|
|
@@ -134,25 +110,14 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
134
110
|
return [];
|
|
135
111
|
}
|
|
136
112
|
|
|
137
|
-
const {appIdKey
|
|
138
|
-
|
|
139
|
-
// if, after all this, we have no dictionary, we have failed
|
|
140
|
-
if (!appIdKey || !pageDict) {
|
|
141
|
-
throw this.log.errorWithException(`Could not connect to a valid app after ${maxTries} tries.`);
|
|
142
|
-
}
|
|
143
|
-
|
|
113
|
+
const { appIdKey } = await this.searchForApp(currentUrl, maxTries, ignoreAboutBlankUrl);
|
|
144
114
|
if (this.appIdKey !== appIdKey) {
|
|
145
115
|
this.log.debug(`Received altered app id, updating from '${this.appIdKey}' to '${appIdKey}'`);
|
|
146
116
|
this.appIdKey = appIdKey;
|
|
147
117
|
}
|
|
148
|
-
|
|
149
|
-
logApplicationDictionary.bind(this)(this.appDict);
|
|
150
|
-
|
|
118
|
+
logApplicationDictionary.bind(this)();
|
|
151
119
|
// translate the dictionary into a useful form, and return to sender
|
|
152
|
-
|
|
153
|
-
? pageArrayFromDict(pageDict)
|
|
154
|
-
: this.appDict[appIdKey].pageArray;
|
|
155
|
-
this.log.debug(`Finally selecting app ${this.appIdKey}: ${simpleStringify(pageArray)}`);
|
|
120
|
+
this.log.debug(`Finally selecting app ${this.appIdKey}`);
|
|
156
121
|
|
|
157
122
|
/** @type {Page[]} */
|
|
158
123
|
const fullPageArray = [];
|
|
@@ -184,80 +149,85 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
184
149
|
* @param {string?} currentUrl
|
|
185
150
|
* @param {number} maxTries
|
|
186
151
|
* @param {boolean} ignoreAboutBlankUrl
|
|
187
|
-
* @returns {Promise<
|
|
152
|
+
* @returns {Promise<AppPage>}
|
|
188
153
|
*/
|
|
189
154
|
export async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
190
155
|
const bundleIds = this.includeSafari && !this.isSafari
|
|
191
156
|
? [this.bundleId, ...this.additionalBundleIds, SAFARI_BUNDLE_ID]
|
|
192
157
|
: [this.bundleId, ...this.additionalBundleIds];
|
|
193
158
|
let retryCount = 0;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
159
|
+
return /** @type {AppPage} */ (await retryInterval(maxTries, SELECT_APP_RETRY_SLEEP_MS, async () => {
|
|
160
|
+
logApplicationDictionary.bind(this)();
|
|
161
|
+
const possibleAppIds = getPossibleDebuggerAppKeys(/** @type {string[]} */ (bundleIds), this.appDict);
|
|
162
|
+
this.log.debug(`Trying out the possible app ids: ${possibleAppIds.join(', ')} (try #${retryCount + 1} of ${maxTries})`);
|
|
163
|
+
for (const attemptedAppIdKey of possibleAppIds) {
|
|
164
|
+
try {
|
|
165
|
+
if (!this.appDict[attemptedAppIdKey].isActive) {
|
|
166
|
+
this.log.debug(`Skipping app '${attemptedAppIdKey}' because it is not active`);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.log.debug(`Attempting app '${attemptedAppIdKey}'`);
|
|
171
|
+
/** @type {string} */
|
|
172
|
+
let appIdKey;
|
|
173
|
+
/** @type {import('@appium/types').StringRecord} */
|
|
174
|
+
let pageDict;
|
|
200
175
|
try {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const [appIdKey, pageDict] = await this.requireRpcClient().selectApp(attemptedAppIdKey);
|
|
207
|
-
// in iOS 8.2 the connect logic happens, but with an empty dictionary
|
|
208
|
-
// which leads to the remote debugger getting disconnected, and into a loop
|
|
209
|
-
if (_.isEmpty(pageDict)) {
|
|
210
|
-
this.log.debug('Empty page dictionary received. Trying again.');
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
176
|
+
[appIdKey, pageDict] = await this.requireRpcClient().selectApp(attemptedAppIdKey);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
this.log.info(`Skipping app '${attemptedAppIdKey}'. Original error: ${e.message}`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
213
181
|
|
|
214
|
-
|
|
215
|
-
|
|
182
|
+
// save the page array for this app
|
|
183
|
+
this.appDict[appIdKey].pageArray = pageArrayFromDict(pageDict);
|
|
216
184
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
185
|
+
// if we are looking for a particular url, make sure we
|
|
186
|
+
// have the right page. Ignore empty or undefined urls.
|
|
187
|
+
// Ignore about:blank if requested.
|
|
188
|
+
const result = this.searchForPage(this.appDict, currentUrl, ignoreAboutBlankUrl);
|
|
189
|
+
if (result) {
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
224
192
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
} catch (err) {
|
|
231
|
-
this.log.debug(`Error checking application: '${err.message}'. Retrying connection`);
|
|
193
|
+
if (currentUrl) {
|
|
194
|
+
this.log.debug(`Received app, but expected url ('${currentUrl}') was not found. Trying again.`);
|
|
195
|
+
} else {
|
|
196
|
+
this.log.debug('Received app, but no match was found. Trying again.');
|
|
232
197
|
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
this.log.debug(err.stack);
|
|
200
|
+
this.log.warn(`Error checking application ${attemptedAppIdKey}: '${err.message}'`);
|
|
233
201
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
return null;
|
|
202
|
+
}
|
|
203
|
+
retryCount++;
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Could not connect to a valid webapp. Make sure it is debuggable and has at least one active page.`
|
|
206
|
+
);
|
|
207
|
+
}));
|
|
241
208
|
}
|
|
242
209
|
|
|
243
210
|
/**
|
|
244
211
|
*
|
|
245
212
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
246
|
-
* @param {Record<string,
|
|
213
|
+
* @param {Record<string, import('../utils').AppInfo>} appsDict
|
|
247
214
|
* @param {string?} currentUrl
|
|
248
215
|
* @param {boolean} [ignoreAboutBlankUrl]
|
|
249
|
-
* @returns {
|
|
216
|
+
* @returns {AppPage?}
|
|
250
217
|
*/
|
|
251
218
|
export function searchForPage (appsDict, currentUrl = null, ignoreAboutBlankUrl = false) {
|
|
252
219
|
for (const appDict of _.values(appsDict)) {
|
|
253
|
-
if (!appDict || !appDict.isActive || !appDict.pageArray || appDict.pageArray
|
|
220
|
+
if (!appDict || !appDict.isActive || !appDict.pageArray || _.isEmpty(appDict.pageArray)) {
|
|
254
221
|
continue;
|
|
255
222
|
}
|
|
256
223
|
|
|
257
|
-
for (const
|
|
258
|
-
if ((!ignoreAboutBlankUrl ||
|
|
259
|
-
(!currentUrl ||
|
|
260
|
-
return {
|
|
224
|
+
for (const page of appDict.pageArray) {
|
|
225
|
+
if ((!ignoreAboutBlankUrl || page.url !== BLANK_PAGE_URL) &&
|
|
226
|
+
(!currentUrl || page.url === currentUrl || page.url === `${currentUrl}/`)) {
|
|
227
|
+
return {
|
|
228
|
+
appIdKey: appDict.id,
|
|
229
|
+
pageDict: page
|
|
230
|
+
};
|
|
261
231
|
}
|
|
262
232
|
}
|
|
263
233
|
}
|
|
@@ -292,23 +262,11 @@ export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
|
292
262
|
|
|
293
263
|
/**
|
|
294
264
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
295
|
-
* @param {Record<string, any>} apps
|
|
296
265
|
* @returns {void}
|
|
297
266
|
*/
|
|
298
|
-
function logApplicationDictionary (
|
|
299
|
-
|
|
300
|
-
function getValueString (key, value) {
|
|
301
|
-
if (_.isFunction(value)) {
|
|
302
|
-
return '[Function]';
|
|
303
|
-
}
|
|
304
|
-
if (key === 'pageArray' && !_.isArray(value)) {
|
|
305
|
-
return `"Waiting for data"`;
|
|
306
|
-
}
|
|
307
|
-
return JSON.stringify(value);
|
|
308
|
-
}
|
|
309
|
-
|
|
267
|
+
function logApplicationDictionary () {
|
|
310
268
|
this.log.debug('Current applications available:');
|
|
311
|
-
for (const [app, info] of _.toPairs(
|
|
269
|
+
for (const [app, info] of _.toPairs(this.appDict)) {
|
|
312
270
|
this.log.debug(` Application: "${app}"`);
|
|
313
271
|
for (const [key, value] of _.toPairs(info)) {
|
|
314
272
|
if (key === 'pageArray' && Array.isArray(value) && value.length) {
|
|
@@ -321,9 +279,30 @@ function logApplicationDictionary (apps) {
|
|
|
321
279
|
}
|
|
322
280
|
}
|
|
323
281
|
} else {
|
|
324
|
-
const valueString =
|
|
282
|
+
const valueString = _.isFunction(value) ? '[Function]' : JSON.stringify(value);
|
|
325
283
|
this.log.debug(` ${key}: ${valueString}`);
|
|
326
284
|
}
|
|
327
285
|
}
|
|
328
286
|
}
|
|
329
287
|
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @typedef {Object} AppPage
|
|
291
|
+
* @property {string} appIdKey
|
|
292
|
+
* @property {Page} pageDict
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @typedef {Object} App
|
|
297
|
+
* @property {string} id
|
|
298
|
+
* @property {string} bundleId
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* @typedef {Object} Page
|
|
303
|
+
* @property {string} url
|
|
304
|
+
* @property {string} title
|
|
305
|
+
* @property {number} id
|
|
306
|
+
* @property {boolean} isKey
|
|
307
|
+
* @property {string} [bundleId]
|
|
308
|
+
*/
|
|
@@ -2,9 +2,7 @@ import events from './events';
|
|
|
2
2
|
import {
|
|
3
3
|
pageArrayFromDict,
|
|
4
4
|
getDebuggerAppKey,
|
|
5
|
-
simpleStringify,
|
|
6
5
|
appInfoFromDict,
|
|
7
|
-
deferredPromise,
|
|
8
6
|
} from '../utils';
|
|
9
7
|
import _ from 'lodash';
|
|
10
8
|
|
|
@@ -21,48 +19,39 @@ import _ from 'lodash';
|
|
|
21
19
|
* @param {Record<string, any>} pageDict
|
|
22
20
|
* @returns {Promise<void>}
|
|
23
21
|
*/
|
|
22
|
+
// eslint-disable-next-line require-await
|
|
24
23
|
export async function onPageChange (err, appIdKey, pageDict) {
|
|
25
24
|
if (_.isEmpty(pageDict)) {
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// we have a pre-existing pageDict
|
|
41
|
-
if (_.isEqual(this.appDict[appIdKey].pageArray, pageArray)) {
|
|
42
|
-
this.log.debug(`Received page change notice for app '${appIdKey}' ` +
|
|
43
|
-
`but the listing has not changed. Ignoring.`);
|
|
44
|
-
return done();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// keep track of the page dictionary
|
|
49
|
-
this.appDict[appIdKey].pageArray = pageArray;
|
|
50
|
-
}
|
|
51
|
-
} finally {
|
|
52
|
-
done();
|
|
28
|
+
const currentPages = pageArrayFromDict(pageDict);
|
|
29
|
+
// save the page dict for this app
|
|
30
|
+
if (this.appDict[appIdKey]) {
|
|
31
|
+
const previousPages = this.appDict[appIdKey].pageArray;
|
|
32
|
+
// we have a pre-existing pageDict
|
|
33
|
+
if (previousPages && _.isEqual(previousPages, currentPages)) {
|
|
34
|
+
this.log.debug(
|
|
35
|
+
`Received page change notice for app '${appIdKey}' ` +
|
|
36
|
+
`but the listing has not changed. Ignoring.`
|
|
37
|
+
);
|
|
38
|
+
return;
|
|
53
39
|
}
|
|
54
|
-
|
|
40
|
+
// keep track of the page dictionary
|
|
41
|
+
this.appDict[appIdKey].pageArray = currentPages;
|
|
42
|
+
this.log.debug(
|
|
43
|
+
`Pages changed for ${appIdKey}: ${JSON.stringify(previousPages)} -> ${JSON.stringify(currentPages)}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
55
46
|
|
|
56
47
|
if (this._navigatingToPage) {
|
|
57
48
|
// in the middle of navigating, so reporting a page change will cause problems
|
|
58
49
|
return;
|
|
59
50
|
}
|
|
60
51
|
|
|
61
|
-
this.log.debug(`Page changed: ${simpleStringify(pageDict, true)}`);
|
|
62
|
-
|
|
63
52
|
this.emit(events.EVENT_PAGE_CHANGE, {
|
|
64
53
|
appIdKey: appIdKey.replace('PID:', ''),
|
|
65
|
-
pageArray,
|
|
54
|
+
pageArray: currentPages,
|
|
66
55
|
});
|
|
67
56
|
}
|
|
68
57
|
|
|
@@ -72,28 +61,23 @@ export async function onPageChange (err, appIdKey, pageDict) {
|
|
|
72
61
|
* @param {Record<string, any>} dict
|
|
73
62
|
* @returns {Promise<void>}
|
|
74
63
|
*/
|
|
64
|
+
// eslint-disable-next-line require-await
|
|
75
65
|
export async function onAppConnect (err, dict) {
|
|
76
66
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
77
67
|
this.log.debug(`Notified that new application '${appIdKey}' has connected`);
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
updateAppsWithDict.bind(this)(dict);
|
|
81
|
-
} finally {
|
|
82
|
-
done();
|
|
83
|
-
}
|
|
84
|
-
});
|
|
68
|
+
updateAppsWithDict.bind(this)(dict);
|
|
85
69
|
}
|
|
86
70
|
|
|
87
71
|
/**
|
|
88
72
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
89
73
|
* @param {Error?} err
|
|
90
|
-
* @param {
|
|
74
|
+
* @param {import('@appium/types').StringRecord} dict
|
|
91
75
|
* @returns {void}
|
|
92
76
|
*/
|
|
93
77
|
export function onAppDisconnect (err, dict) {
|
|
94
78
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
95
79
|
this.log.debug(`Application '${appIdKey}' disconnected. Removing from app dictionary.`);
|
|
96
|
-
|
|
80
|
+
this.log.debug(`Current app is '${this.appIdKey}'`);
|
|
97
81
|
|
|
98
82
|
// get rid of the entry in our app dictionary,
|
|
99
83
|
// since it is no longer available
|
|
@@ -119,14 +103,10 @@ export function onAppDisconnect (err, dict) {
|
|
|
119
103
|
* @param {Record<string, any>} dict
|
|
120
104
|
* @returns {Promise<void>}
|
|
121
105
|
*/
|
|
106
|
+
// eslint-disable-next-line require-await
|
|
122
107
|
export async function onAppUpdate (err, dict) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
updateAppsWithDict.bind(this)(dict);
|
|
126
|
-
} finally {
|
|
127
|
-
done();
|
|
128
|
-
}
|
|
129
|
-
});
|
|
108
|
+
this.log.debug(`Notified that an application has been updated`);
|
|
109
|
+
updateAppsWithDict.bind(this)(dict);
|
|
130
110
|
}
|
|
131
111
|
|
|
132
112
|
/**
|
|
@@ -159,6 +139,7 @@ export function onCurrentState (err, state) {
|
|
|
159
139
|
* @param {Record<string, any>} apps
|
|
160
140
|
* @returns {Promise<void>}
|
|
161
141
|
*/
|
|
142
|
+
// eslint-disable-next-line require-await
|
|
162
143
|
export async function onConnectedApplicationList (err, apps) {
|
|
163
144
|
this.log.debug(`Received connected applications list: ${_.keys(apps).join(', ')}`);
|
|
164
145
|
|
|
@@ -173,25 +154,9 @@ export async function onConnectedApplicationList (err, apps) {
|
|
|
173
154
|
newDict[id] = entry;
|
|
174
155
|
}
|
|
175
156
|
// update the object's list of apps
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
_.defaults(this.appDict, newDict);
|
|
179
|
-
} finally {
|
|
180
|
-
done();
|
|
181
|
-
}
|
|
182
|
-
});
|
|
157
|
+
_.defaults(this.appDict, newDict);
|
|
183
158
|
}
|
|
184
159
|
|
|
185
|
-
/**
|
|
186
|
-
* @this {import('../remote-debugger').RemoteDebugger}
|
|
187
|
-
* @param {(done: () => any) => any} fn
|
|
188
|
-
* @returns {Promise<any>}
|
|
189
|
-
*/
|
|
190
|
-
async function useAppDictLock (fn) {
|
|
191
|
-
return await this._lock.acquire('appDict', fn);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
160
|
/**
|
|
196
161
|
*
|
|
197
162
|
* @this {import('../remote-debugger').RemoteDebugger}
|
|
@@ -201,19 +166,14 @@ async function useAppDictLock (fn) {
|
|
|
201
166
|
function updateAppsWithDict (dict) {
|
|
202
167
|
// get the dictionary entry into a nice form, and add it to the
|
|
203
168
|
// application dictionary
|
|
204
|
-
this.appDict
|
|
205
|
-
|
|
169
|
+
this.appDict ??= {};
|
|
170
|
+
const [id, entry] = appInfoFromDict(dict);
|
|
206
171
|
if (this.appDict[id]) {
|
|
207
172
|
// preserve the page dictionary for this entry
|
|
208
173
|
entry.pageArray = this.appDict[id].pageArray;
|
|
209
174
|
}
|
|
210
175
|
this.appDict[id] = entry;
|
|
211
176
|
|
|
212
|
-
// add a promise to get the page dictionary
|
|
213
|
-
if (_.isUndefined(entry.pageArray)) {
|
|
214
|
-
entry.pageArray = deferredPromise();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
177
|
// try to get the app id from our connected apps
|
|
218
178
|
if (!this.appIdKey) {
|
|
219
179
|
this.appIdKey = getDebuggerAppKey(/** @type {string} */ (this.bundleId), this.appDict);
|
|
@@ -29,15 +29,11 @@ export default class RemoteDebuggerRealDevice extends RemoteDebugger {
|
|
|
29
29
|
bundleId: this.bundleId,
|
|
30
30
|
platformVersion: this.platformVersion,
|
|
31
31
|
isSafari: this.isSafari,
|
|
32
|
-
host: this.host,
|
|
33
|
-
port: this.port,
|
|
34
|
-
socketPath: this.socketPath,
|
|
35
|
-
messageProxy: this.remoteDebugProxy,
|
|
36
32
|
logAllCommunication: this.logAllCommunication,
|
|
37
33
|
logAllCommunicationHexDump: this.logAllCommunicationHexDump,
|
|
38
34
|
socketChunkSize: this.socketChunkSize,
|
|
39
35
|
webInspectorMaxFrameLength: this.webInspectorMaxFrameLength,
|
|
40
|
-
udid: this.udid
|
|
36
|
+
udid: this.udid,
|
|
41
37
|
});
|
|
42
38
|
}
|
|
43
39
|
}
|
package/lib/remote-debugger.js
CHANGED
|
@@ -11,7 +11,7 @@ import * as screenshotMixins from './mixins/screenshot';
|
|
|
11
11
|
import * as eventMixins from './mixins/events';
|
|
12
12
|
import * as miscellaneousMixins from './mixins/misc';
|
|
13
13
|
import _ from 'lodash';
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
|
|
16
16
|
export const REMOTE_DEBUGGER_PORT = 27753;
|
|
17
17
|
/* How many milliseconds to wait for webkit to return a response before timing out */
|
|
@@ -160,8 +160,6 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
160
160
|
this.fullPageInitialization = fullPageInitialization;
|
|
161
161
|
|
|
162
162
|
this.pageLoadStrategy = pageLoadStrategy;
|
|
163
|
-
|
|
164
|
-
this._lock = new AsyncLock();
|
|
165
163
|
}
|
|
166
164
|
|
|
167
165
|
/**
|
|
@@ -24,7 +24,7 @@ const COMMANDS = {
|
|
|
24
24
|
'Timeline.stop': FULL_COMMAND,
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
class RemoteMessages {
|
|
27
|
+
export class RemoteMessages {
|
|
28
28
|
constructor (isTargetBased = false) {
|
|
29
29
|
this.isTargetBased = isTargetBased;
|
|
30
30
|
}
|
|
@@ -249,5 +249,4 @@ class RemoteMessages {
|
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
export { RemoteMessages };
|
|
253
252
|
export default RemoteMessages;
|
|
@@ -3,13 +3,19 @@ import RpcClient from './rpc-client';
|
|
|
3
3
|
import { services } from 'appium-ios-device';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
export
|
|
6
|
+
export class RpcClientRealDevice extends RpcClient {
|
|
7
|
+
/**
|
|
8
|
+
* @param {import('./rpc-client').RpcClientOptions} [opts={}]
|
|
9
|
+
*/
|
|
7
10
|
constructor (opts = {}) {
|
|
8
11
|
super(Object.assign({
|
|
9
12
|
shouldCheckForTarget: false,
|
|
10
13
|
}, opts));
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @override
|
|
18
|
+
*/
|
|
13
19
|
async connect () {
|
|
14
20
|
this.service = await services.startWebInspectorService(this.udid, {
|
|
15
21
|
osVersion: this.platformVersion,
|
|
@@ -24,6 +30,9 @@ export default class RpcClientRealDevice extends RpcClient {
|
|
|
24
30
|
this.isConnected = true;
|
|
25
31
|
}
|
|
26
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @override
|
|
35
|
+
*/
|
|
27
36
|
async disconnect () {
|
|
28
37
|
if (!this.isConnected) {
|
|
29
38
|
return;
|
|
@@ -35,10 +44,16 @@ export default class RpcClientRealDevice extends RpcClient {
|
|
|
35
44
|
this.isConnected = false;
|
|
36
45
|
}
|
|
37
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @override
|
|
49
|
+
*/
|
|
38
50
|
async sendMessage (cmd) { // eslint-disable-line require-await
|
|
39
51
|
this.service.sendMessage(cmd);
|
|
40
52
|
}
|
|
41
53
|
|
|
54
|
+
/**
|
|
55
|
+
* @override
|
|
56
|
+
*/
|
|
42
57
|
async receive (data) {
|
|
43
58
|
if (!this.isConnected) {
|
|
44
59
|
return;
|
|
@@ -47,3 +62,5 @@ export default class RpcClientRealDevice extends RpcClient {
|
|
|
47
62
|
await this.messageHandler.handleMessage(data);
|
|
48
63
|
}
|
|
49
64
|
}
|
|
65
|
+
|
|
66
|
+
export default RpcClientRealDevice;
|
|
@@ -5,8 +5,25 @@ import net from 'net';
|
|
|
5
5
|
import RpcClient from './rpc-client';
|
|
6
6
|
import { services } from 'appium-ios-device';
|
|
7
7
|
|
|
8
|
+
export class RpcClientSimulator extends RpcClient {
|
|
9
|
+
/** @type {string|undefined} */
|
|
10
|
+
host;
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
/** @type {number|undefined} */
|
|
13
|
+
port;
|
|
14
|
+
|
|
15
|
+
/** @type {any} */
|
|
16
|
+
messageProxy;
|
|
17
|
+
|
|
18
|
+
/** @type {import('node:net').Socket|null} */
|
|
19
|
+
socket;
|
|
20
|
+
|
|
21
|
+
/** @type {string|undefined} */
|
|
22
|
+
socketPath;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {import('./rpc-client').RpcClientOptions & RpcClientSimulatorOptions} [opts={}]
|
|
26
|
+
*/
|
|
10
27
|
constructor (opts = {}) {
|
|
11
28
|
super(Object.assign({
|
|
12
29
|
shouldCheckForTarget: false,
|
|
@@ -28,6 +45,9 @@ export default class RpcClientSimulator extends RpcClient {
|
|
|
28
45
|
this.socketPath = socketPath;
|
|
29
46
|
}
|
|
30
47
|
|
|
48
|
+
/**
|
|
49
|
+
* @override
|
|
50
|
+
*/
|
|
31
51
|
async connect () {
|
|
32
52
|
// create socket and handle its messages
|
|
33
53
|
if (this.socketPath) {
|
|
@@ -59,7 +79,7 @@ export default class RpcClientSimulator extends RpcClient {
|
|
|
59
79
|
// tcp socket
|
|
60
80
|
log.debug(`Connecting to remote debugger ${this.messageProxy ? 'via proxy ' : ''}through TCP: ${this.host}:${this.port}`);
|
|
61
81
|
this.socket = new net.Socket();
|
|
62
|
-
this.socket.connect(this.port, this.host);
|
|
82
|
+
this.socket.connect(/** @type {number} */ (this.port), /** @type {String} */ (this.host));
|
|
63
83
|
}
|
|
64
84
|
|
|
65
85
|
this.socket.setNoDelay(true);
|
|
@@ -107,6 +127,9 @@ export default class RpcClientSimulator extends RpcClient {
|
|
|
107
127
|
});
|
|
108
128
|
}
|
|
109
129
|
|
|
130
|
+
/**
|
|
131
|
+
* @override
|
|
132
|
+
*/
|
|
110
133
|
async disconnect () {
|
|
111
134
|
if (!this.isConnected) {
|
|
112
135
|
return;
|
|
@@ -118,6 +141,9 @@ export default class RpcClientSimulator extends RpcClient {
|
|
|
118
141
|
this.isConnected = false;
|
|
119
142
|
}
|
|
120
143
|
|
|
144
|
+
/**
|
|
145
|
+
* @override
|
|
146
|
+
*/
|
|
121
147
|
async sendMessage (cmd) {
|
|
122
148
|
let onSocketError;
|
|
123
149
|
|
|
@@ -148,6 +174,9 @@ export default class RpcClientSimulator extends RpcClient {
|
|
|
148
174
|
});
|
|
149
175
|
}
|
|
150
176
|
|
|
177
|
+
/**
|
|
178
|
+
* @override
|
|
179
|
+
*/
|
|
151
180
|
async receive (data) {
|
|
152
181
|
if (!this.isConnected) {
|
|
153
182
|
return;
|
|
@@ -166,3 +195,13 @@ export default class RpcClientSimulator extends RpcClient {
|
|
|
166
195
|
await this.messageHandler.handleMessage(data);
|
|
167
196
|
}
|
|
168
197
|
}
|
|
198
|
+
|
|
199
|
+
export default RpcClientSimulator;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @typedef {Object} RpcClientSimulatorOptions
|
|
203
|
+
* @property {string} [socketPath]
|
|
204
|
+
* @property {string} [host='::1']
|
|
205
|
+
* @property {number} [port]
|
|
206
|
+
* @property {any} [messageProxy]
|
|
207
|
+
*/
|