appium-remote-debugger 12.0.0 → 12.0.1
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 +6 -0
- package/build/lib/mixins/connect.d.ts +8 -52
- package/build/lib/mixins/connect.d.ts.map +1 -1
- package/build/lib/mixins/connect.js +31 -41
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/cookies.d.ts +4 -8
- package/build/lib/mixins/cookies.d.ts.map +1 -1
- package/build/lib/mixins/cookies.js +9 -13
- package/build/lib/mixins/cookies.js.map +1 -1
- package/build/lib/mixins/events.d.ts +10 -16
- package/build/lib/mixins/events.d.ts.map +1 -1
- package/build/lib/mixins/events.js +7 -10
- package/build/lib/mixins/events.js.map +1 -1
- package/build/lib/mixins/execute.d.ts +5 -16
- package/build/lib/mixins/execute.d.ts.map +1 -1
- package/build/lib/mixins/execute.js +17 -21
- package/build/lib/mixins/execute.js.map +1 -1
- package/build/lib/mixins/message-handlers.d.ts +9 -49
- package/build/lib/mixins/message-handlers.d.ts.map +1 -1
- package/build/lib/mixins/message-handlers.js +24 -35
- package/build/lib/mixins/message-handlers.js.map +1 -1
- package/build/lib/mixins/misc.d.ts +6 -10
- package/build/lib/mixins/misc.d.ts.map +1 -1
- package/build/lib/mixins/misc.js +15 -16
- package/build/lib/mixins/misc.js.map +1 -1
- package/build/lib/mixins/navigate.d.ts +9 -47
- package/build/lib/mixins/navigate.d.ts.map +1 -1
- package/build/lib/mixins/navigate.js +38 -44
- package/build/lib/mixins/navigate.js.map +1 -1
- package/build/lib/mixins/property-accessors.d.ts +27 -0
- package/build/lib/mixins/property-accessors.d.ts.map +1 -0
- package/build/lib/mixins/property-accessors.js +95 -0
- package/build/lib/mixins/property-accessors.js.map +1 -0
- package/build/lib/mixins/screenshot.d.ts +2 -10
- package/build/lib/mixins/screenshot.d.ts.map +1 -1
- package/build/lib/mixins/screenshot.js +4 -9
- package/build/lib/mixins/screenshot.js.map +1 -1
- package/build/lib/remote-debugger.d.ts +5 -2
- package/build/lib/remote-debugger.d.ts.map +1 -1
- package/build/lib/remote-debugger.js +14 -1
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/mixins/connect.js +43 -43
- package/lib/mixins/cookies.js +12 -14
- package/lib/mixins/events.js +10 -11
- package/lib/mixins/execute.js +28 -24
- package/lib/mixins/message-handlers.js +33 -37
- package/lib/mixins/misc.js +18 -17
- package/lib/mixins/navigate.js +46 -45
- package/lib/mixins/property-accessors.ts +96 -0
- package/lib/mixins/screenshot.js +8 -10
- package/lib/remote-debugger.ts +20 -3
- package/package.json +1 -1
package/lib/mixins/connect.js
CHANGED
|
@@ -7,6 +7,17 @@ import events from './events';
|
|
|
7
7
|
import { timing, util } from '@appium/support';
|
|
8
8
|
import { retryInterval, waitForCondition } from 'asyncbox';
|
|
9
9
|
import _ from 'lodash';
|
|
10
|
+
import {
|
|
11
|
+
setAppIdKey,
|
|
12
|
+
getAppDict,
|
|
13
|
+
getAppIdKey,
|
|
14
|
+
setPageIdKey,
|
|
15
|
+
getRcpClient,
|
|
16
|
+
getIsSafari,
|
|
17
|
+
getIncludeSafari,
|
|
18
|
+
getBundleId,
|
|
19
|
+
getAdditionalBundleIds,
|
|
20
|
+
} from './property-accessors';
|
|
10
21
|
|
|
11
22
|
const APP_CONNECT_TIMEOUT_MS = 0;
|
|
12
23
|
const APP_CONNECT_INTERVAL_MS = 100;
|
|
@@ -36,7 +47,7 @@ export async function setConnectionKey () {
|
|
|
36
47
|
*
|
|
37
48
|
* @this {RemoteDebugger}
|
|
38
49
|
* @param {number} [timeout=APP_CONNECT_TIMEOUT_MS]
|
|
39
|
-
* @returns {Promise<import('
|
|
50
|
+
* @returns {Promise<import('../types').AppDict>}
|
|
40
51
|
*/
|
|
41
52
|
export async function connect (timeout = APP_CONNECT_TIMEOUT_MS) {
|
|
42
53
|
this.setup();
|
|
@@ -66,19 +77,19 @@ export async function connect (timeout = APP_CONNECT_TIMEOUT_MS) {
|
|
|
66
77
|
const timer = new timing.Timer().start();
|
|
67
78
|
this.log.debug(`Waiting up to ${timeout}ms for applications to be reported`);
|
|
68
79
|
try {
|
|
69
|
-
await waitForCondition(() => !_.isEmpty(this
|
|
80
|
+
await waitForCondition(() => !_.isEmpty(getAppDict(this)), {
|
|
70
81
|
waitMs: timeout,
|
|
71
82
|
intervalMs: APP_CONNECT_INTERVAL_MS,
|
|
72
83
|
});
|
|
73
84
|
this.log.debug(
|
|
74
|
-
`Retrieved ${util.pluralize('application', _.size(this
|
|
85
|
+
`Retrieved ${util.pluralize('application', _.size(getAppDict(this)), true)} ` +
|
|
75
86
|
`within ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`
|
|
76
87
|
);
|
|
77
88
|
} catch (err) {
|
|
78
89
|
this.log.debug(`Timed out waiting for applications to be reported`);
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
|
-
return this
|
|
92
|
+
return _.cloneDeep(getAppDict(this));
|
|
82
93
|
} catch (err) {
|
|
83
94
|
this.log.error(`Error setting connection key: ${err.message}`);
|
|
84
95
|
await this.disconnect();
|
|
@@ -92,9 +103,7 @@ export async function connect (timeout = APP_CONNECT_TIMEOUT_MS) {
|
|
|
92
103
|
* @returns {Promise<void>}
|
|
93
104
|
*/
|
|
94
105
|
export async function disconnect () {
|
|
95
|
-
|
|
96
|
-
await this._rpcClient.disconnect();
|
|
97
|
-
}
|
|
106
|
+
await getRcpClient(this)?.disconnect();
|
|
98
107
|
this.emit(events.EVENT_DISCONNECT, true);
|
|
99
108
|
this.teardown();
|
|
100
109
|
}
|
|
@@ -115,23 +124,23 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
115
124
|
rpcClient.shouldCheckForTarget = false;
|
|
116
125
|
try {
|
|
117
126
|
const timer = new timing.Timer().start();
|
|
118
|
-
if (
|
|
127
|
+
if (_.isEmpty(getAppDict(this))) {
|
|
119
128
|
this.log.debug('No applications currently connected.');
|
|
120
129
|
return [];
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
const { appIdKey } = await searchForApp.bind(this)(currentUrl, maxTries, ignoreAboutBlankUrl);
|
|
124
|
-
if (this
|
|
125
|
-
this.log.debug(`Received altered app id, updating from '${this
|
|
126
|
-
this
|
|
133
|
+
if (getAppIdKey(this) !== appIdKey) {
|
|
134
|
+
this.log.debug(`Received altered app id, updating from '${getAppIdKey(this)}' to '${appIdKey}'`);
|
|
135
|
+
setAppIdKey(this, appIdKey);
|
|
127
136
|
}
|
|
128
137
|
logApplicationDictionary.bind(this)();
|
|
129
138
|
// translate the dictionary into a useful form, and return to sender
|
|
130
|
-
this.log.debug(`Finally selecting app ${this
|
|
139
|
+
this.log.debug(`Finally selecting app ${getAppIdKey(this)}`);
|
|
131
140
|
|
|
132
141
|
/** @type {import('../types').Page[]} */
|
|
133
142
|
const fullPageArray = [];
|
|
134
|
-
for (const [app, info] of _.toPairs(this
|
|
143
|
+
for (const [app, info] of _.toPairs(getAppDict(this))) {
|
|
135
144
|
if (!_.isArray(info.pageArray) || !info.isActive) {
|
|
136
145
|
continue;
|
|
137
146
|
}
|
|
@@ -162,14 +171,15 @@ export async function selectApp (currentUrl = null, maxTries = SELECT_APP_RETRIE
|
|
|
162
171
|
* @returns {Promise<void>}
|
|
163
172
|
*/
|
|
164
173
|
export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
165
|
-
|
|
166
|
-
this
|
|
174
|
+
const fullAppIdKey = _.startsWith(`${appIdKey}`, 'PID:') ? `${appIdKey}` : `PID:${appIdKey}`;
|
|
175
|
+
setAppIdKey(this, fullAppIdKey);
|
|
176
|
+
setPageIdKey(this, pageIdKey);
|
|
167
177
|
|
|
168
|
-
this.log.debug(`Selecting page '${pageIdKey}' on app '${
|
|
178
|
+
this.log.debug(`Selecting page '${pageIdKey}' on app '${fullAppIdKey}' and forwarding socket setup`);
|
|
169
179
|
|
|
170
180
|
const timer = new timing.Timer().start();
|
|
171
181
|
|
|
172
|
-
await this.requireRpcClient().selectPage(
|
|
182
|
+
await this.requireRpcClient().selectPage(fullAppIdKey, pageIdKey);
|
|
173
183
|
|
|
174
184
|
if (!skipReadyCheck && !await this.checkPageIsReady()) {
|
|
175
185
|
await this.waitForDom();
|
|
@@ -178,7 +188,6 @@ export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
|
178
188
|
this.log.debug(`Selected page after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
179
189
|
}
|
|
180
190
|
|
|
181
|
-
|
|
182
191
|
/**
|
|
183
192
|
*
|
|
184
193
|
* @this {RemoteDebugger}
|
|
@@ -188,9 +197,14 @@ export async function selectPage (appIdKey, pageIdKey, skipReadyCheck = false) {
|
|
|
188
197
|
* @returns {Promise<import('../types').AppPage>}
|
|
189
198
|
*/
|
|
190
199
|
async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
200
|
+
/** @type {string[]} */
|
|
201
|
+
const bundleIds = _.compact(
|
|
202
|
+
[
|
|
203
|
+
getBundleId(this),
|
|
204
|
+
...(getAdditionalBundleIds(this) ?? []),
|
|
205
|
+
...(getIncludeSafari(this) && !getIsSafari(this) ? [SAFARI_BUNDLE_ID] : []),
|
|
206
|
+
]
|
|
207
|
+
);
|
|
194
208
|
let retryCount = 0;
|
|
195
209
|
return /** @type {import('../types').AppPage} */ (await retryInterval(maxTries, SELECT_APP_RETRY_SLEEP_MS, async () => {
|
|
196
210
|
logApplicationDictionary.bind(this)();
|
|
@@ -198,7 +212,7 @@ async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
|
198
212
|
this.log.debug(`Trying out the possible app ids: ${possibleAppIds.join(', ')} (try #${retryCount + 1} of ${maxTries})`);
|
|
199
213
|
for (const attemptedAppIdKey of possibleAppIds) {
|
|
200
214
|
try {
|
|
201
|
-
if (!this
|
|
215
|
+
if (!getAppDict(this)[attemptedAppIdKey].isActive) {
|
|
202
216
|
this.log.debug(`Skipping app '${attemptedAppIdKey}' because it is not active`);
|
|
203
217
|
continue;
|
|
204
218
|
}
|
|
@@ -216,12 +230,12 @@ async function searchForApp (currentUrl, maxTries, ignoreAboutBlankUrl) {
|
|
|
216
230
|
}
|
|
217
231
|
|
|
218
232
|
// save the page array for this app
|
|
219
|
-
this
|
|
233
|
+
getAppDict(this)[appIdKey].pageArray = pageArrayFromDict(pageDict);
|
|
220
234
|
|
|
221
235
|
// if we are looking for a particular url, make sure we
|
|
222
236
|
// have the right page. Ignore empty or undefined urls.
|
|
223
237
|
// Ignore about:blank if requested.
|
|
224
|
-
const result = searchForPage.bind(this)(this
|
|
238
|
+
const result = searchForPage.bind(this)(getAppDict(this), currentUrl, ignoreAboutBlankUrl);
|
|
225
239
|
if (result) {
|
|
226
240
|
return result;
|
|
227
241
|
}
|
|
@@ -276,7 +290,7 @@ function searchForPage (appsDict, currentUrl = null, ignoreAboutBlankUrl = false
|
|
|
276
290
|
*/
|
|
277
291
|
function logApplicationDictionary () {
|
|
278
292
|
this.log.debug('Current applications available:');
|
|
279
|
-
for (const [app, info] of _.toPairs(this
|
|
293
|
+
for (const [app, info] of _.toPairs(getAppDict(this))) {
|
|
280
294
|
this.log.debug(` Application: "${app}"`);
|
|
281
295
|
for (const [key, value] of _.toPairs(info)) {
|
|
282
296
|
if (key === 'pageArray' && Array.isArray(value) && value.length) {
|
|
@@ -307,7 +321,7 @@ function logApplicationDictionary () {
|
|
|
307
321
|
export function getPossibleDebuggerAppKeys(bundleIds) {
|
|
308
322
|
if (bundleIds.includes(WILDCARD_BUNDLE_ID)) {
|
|
309
323
|
this.log.debug('Skip checking bundle identifiers because the bundleIds includes a wildcard');
|
|
310
|
-
return _.uniq(Object.keys(this
|
|
324
|
+
return _.uniq(Object.keys(getAppDict(this)));
|
|
311
325
|
}
|
|
312
326
|
|
|
313
327
|
// go through the possible bundle identifiers
|
|
@@ -324,10 +338,10 @@ export function getPossibleDebuggerAppKeys(bundleIds) {
|
|
|
324
338
|
const proxiedAppIds = new Set();
|
|
325
339
|
for (const bundleId of possibleBundleIds) {
|
|
326
340
|
// now we need to determine if we should pick a proxy for this instead
|
|
327
|
-
for (const appId of appIdsForBundle(bundleId, this
|
|
341
|
+
for (const appId of appIdsForBundle(bundleId, getAppDict(this))) {
|
|
328
342
|
proxiedAppIds.add(appId);
|
|
329
343
|
this.log.debug(`Found app id key '${appId}' for bundle '${bundleId}'`);
|
|
330
|
-
for (const [key, data] of _.toPairs(this
|
|
344
|
+
for (const [key, data] of _.toPairs(getAppDict(this))) {
|
|
331
345
|
if (data.isProxy && data.hostId === appId) {
|
|
332
346
|
this.log.debug(
|
|
333
347
|
`Found separate bundleId '${data.bundleId}' ` +
|
|
@@ -343,19 +357,5 @@ export function getPossibleDebuggerAppKeys(bundleIds) {
|
|
|
343
357
|
}
|
|
344
358
|
|
|
345
359
|
/**
|
|
346
|
-
* @typedef {
|
|
347
|
-
* @property {string | null | undefined} _appIdKey
|
|
348
|
-
* @property {string | number | null | undefined} _pageIdKey
|
|
349
|
-
* @property {import('../types').AppDict} _appDict
|
|
350
|
-
* @property {string | undefined} _bundleId
|
|
351
|
-
* @property {import('../rpc/rpc-client').RpcClient | undefined} _rpcClient
|
|
352
|
-
* @property {boolean} _includeSafari
|
|
353
|
-
* @property {boolean} _isSafari
|
|
354
|
-
* @property {string[]} _additionalBundleIds
|
|
355
|
-
* @property {(this: RemoteDebugger, timeoutMs?: number | undefined) => Promise<boolean>} checkPageIsReady:
|
|
356
|
-
* @property {(this: RemoteDebugger, startPageLoadTimer?: timing.Timer | null | undefined) => Promise<void>} waitForDom:
|
|
357
|
-
*/
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* @typedef {import('../remote-debugger').RemoteDebugger & HasConnectionRelatedProperties} RemoteDebugger
|
|
360
|
+
* @typedef {import('../remote-debugger').RemoteDebugger} RemoteDebugger
|
|
361
361
|
*/
|
package/lib/mixins/cookies.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAppIdKey,
|
|
3
|
+
getPageIdKey,
|
|
4
|
+
} from './property-accessors';
|
|
1
5
|
|
|
2
6
|
/**
|
|
3
7
|
*
|
|
@@ -7,8 +11,8 @@
|
|
|
7
11
|
export async function getCookies () {
|
|
8
12
|
this.log.debug('Getting cookies');
|
|
9
13
|
return await this.requireRpcClient().send('Page.getCookies', {
|
|
10
|
-
appIdKey: this
|
|
11
|
-
pageIdKey: this
|
|
14
|
+
appIdKey: getAppIdKey(this),
|
|
15
|
+
pageIdKey: getPageIdKey(this),
|
|
12
16
|
});
|
|
13
17
|
}
|
|
14
18
|
|
|
@@ -21,9 +25,9 @@ export async function getCookies () {
|
|
|
21
25
|
export async function setCookie (cookie) {
|
|
22
26
|
this.log.debug('Setting cookie');
|
|
23
27
|
return await this.requireRpcClient().send('Page.setCookie', {
|
|
24
|
-
appIdKey: this
|
|
25
|
-
pageIdKey: this
|
|
26
|
-
cookie
|
|
28
|
+
appIdKey: getAppIdKey(this),
|
|
29
|
+
pageIdKey: getPageIdKey(this),
|
|
30
|
+
cookie,
|
|
27
31
|
});
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -37,19 +41,13 @@ export async function setCookie (cookie) {
|
|
|
37
41
|
export async function deleteCookie (cookieName, url) {
|
|
38
42
|
this.log.debug(`Deleting cookie '${cookieName}' on '${url}'`);
|
|
39
43
|
return await this.requireRpcClient().send('Page.deleteCookie', {
|
|
40
|
-
appIdKey: this
|
|
41
|
-
pageIdKey: this
|
|
44
|
+
appIdKey: getAppIdKey(this),
|
|
45
|
+
pageIdKey: getPageIdKey(this),
|
|
42
46
|
cookieName,
|
|
43
47
|
url,
|
|
44
48
|
});
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
|
-
* @typedef {
|
|
49
|
-
* @property {string | null | undefined} _appIdKey
|
|
50
|
-
* @property {string | number | null | undefined} _pageIdKey
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @typedef {import('../remote-debugger').RemoteDebugger & HasCookiesRelatedProperties} RemoteDebugger
|
|
52
|
+
* @typedef {import('../remote-debugger').RemoteDebugger} RemoteDebugger
|
|
55
53
|
*/
|
package/lib/mixins/events.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getClientEventListeners,
|
|
3
|
+
} from './property-accessors';
|
|
4
|
+
|
|
1
5
|
// event emitted publically
|
|
2
|
-
export const events = {
|
|
6
|
+
export const events = /** @type {const} */ ({
|
|
3
7
|
EVENT_PAGE_CHANGE: 'remote_debugger_page_change',
|
|
4
8
|
EVENT_FRAMES_DETACHED: 'remote_debugger_frames_detached',
|
|
5
9
|
EVENT_DISCONNECT: 'remote_debugger_disconnect',
|
|
6
|
-
};
|
|
10
|
+
});
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Keep track of the client event listeners so they can be removed
|
|
@@ -14,8 +18,8 @@ export const events = {
|
|
|
14
18
|
* @returns {void}
|
|
15
19
|
*/
|
|
16
20
|
export function addClientEventListener (eventName, listener) {
|
|
17
|
-
this
|
|
18
|
-
this
|
|
21
|
+
getClientEventListeners(this)[eventName] ??= [];
|
|
22
|
+
getClientEventListeners(this)[eventName].push(listener);
|
|
19
23
|
this.requireRpcClient().on(eventName, listener);
|
|
20
24
|
}
|
|
21
25
|
|
|
@@ -25,7 +29,7 @@ export function addClientEventListener (eventName, listener) {
|
|
|
25
29
|
* @returns {void}
|
|
26
30
|
*/
|
|
27
31
|
export function removeClientEventListener (eventName) {
|
|
28
|
-
for (const listener of (this
|
|
32
|
+
for (const listener of (getClientEventListeners(this)[eventName] || [])) {
|
|
29
33
|
this.requireRpcClient().off(eventName, listener);
|
|
30
34
|
}
|
|
31
35
|
}
|
|
@@ -73,10 +77,5 @@ export function stopNetwork () {
|
|
|
73
77
|
export default events;
|
|
74
78
|
|
|
75
79
|
/**
|
|
76
|
-
* @typedef {
|
|
77
|
-
* @property {import('@appium/types').StringRecord<import('../types').EventListener[]>} _clientEventListeners:
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @typedef {import('../remote-debugger').RemoteDebugger & HasEventsRelatedProperties} RemoteDebugger
|
|
80
|
+
* @typedef {import('../remote-debugger').RemoteDebugger} RemoteDebugger
|
|
82
81
|
*/
|
package/lib/mixins/execute.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { errors } from '@appium/base-driver';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
checkParams,
|
|
4
|
+
simpleStringify,
|
|
5
|
+
convertResult,
|
|
6
|
+
RESPONSE_LOG_LENGTH,
|
|
7
|
+
} from '../utils';
|
|
3
8
|
import { getScriptForAtom } from '../atoms';
|
|
4
9
|
import { util, timing } from '@appium/support';
|
|
5
10
|
import { retryInterval } from 'asyncbox';
|
|
6
11
|
import _ from 'lodash';
|
|
7
|
-
|
|
12
|
+
import {
|
|
13
|
+
getAppIdKey,
|
|
14
|
+
getPageIdKey,
|
|
15
|
+
getPageLoading,
|
|
16
|
+
getGarbageCollectOnExecute,
|
|
17
|
+
} from './property-accessors';
|
|
8
18
|
|
|
9
19
|
/* How many milliseconds to wait for webkit to return a response before timing out */
|
|
10
20
|
const RPC_RESPONSE_TIMEOUT_MS = 5000;
|
|
@@ -36,8 +46,8 @@ export async function executeAtom (atom, args = [], frames = []) {
|
|
|
36
46
|
export async function executeAtomAsync (atom, args = [], frames = []) {
|
|
37
47
|
// helper to send directly to the web inspector
|
|
38
48
|
const evaluate = async (method, opts) => await this.requireRpcClient(true).send(method, Object.assign({
|
|
39
|
-
appIdKey: this
|
|
40
|
-
pageIdKey: this
|
|
49
|
+
appIdKey: getAppIdKey(this),
|
|
50
|
+
pageIdKey: getPageIdKey(this),
|
|
41
51
|
returnByValue: false,
|
|
42
52
|
}, opts));
|
|
43
53
|
|
|
@@ -125,19 +135,19 @@ export async function executeAtomAsync (atom, args = [], frames = []) {
|
|
|
125
135
|
*/
|
|
126
136
|
export async function execute (command, override) {
|
|
127
137
|
// if the page is not loaded yet, wait for it
|
|
128
|
-
if (this
|
|
138
|
+
if (getPageLoading(this) && !override) {
|
|
129
139
|
this.log.debug('Trying to execute but page is not loaded.');
|
|
130
140
|
await this.waitForDom();
|
|
131
141
|
}
|
|
132
142
|
|
|
133
|
-
if (_.isNil(this
|
|
143
|
+
if (_.isNil(getAppIdKey(this))) {
|
|
134
144
|
throw new Error('Missing parameter: appIdKey. Is the target web application still alive?');
|
|
135
145
|
}
|
|
136
|
-
if (_.isNil(this
|
|
146
|
+
if (_.isNil(getPageIdKey(this))) {
|
|
137
147
|
throw new Error('Missing parameter: pageIdKey. Is the target web page still alive?');
|
|
138
148
|
}
|
|
139
149
|
|
|
140
|
-
if (this
|
|
150
|
+
if (getGarbageCollectOnExecute(this)) {
|
|
141
151
|
await this.garbageCollect();
|
|
142
152
|
}
|
|
143
153
|
|
|
@@ -145,8 +155,8 @@ export async function execute (command, override) {
|
|
|
145
155
|
const res = await this.requireRpcClient(true).send('Runtime.evaluate', {
|
|
146
156
|
expression: command,
|
|
147
157
|
returnByValue: true,
|
|
148
|
-
appIdKey: this
|
|
149
|
-
pageIdKey: this
|
|
158
|
+
appIdKey: getAppIdKey(this),
|
|
159
|
+
pageIdKey: getPageIdKey(this),
|
|
150
160
|
});
|
|
151
161
|
return convertResult(res);
|
|
152
162
|
}
|
|
@@ -158,9 +168,12 @@ export async function execute (command, override) {
|
|
|
158
168
|
* @param {any[]} [args]
|
|
159
169
|
*/
|
|
160
170
|
export async function callFunction (objectId, fn, args) {
|
|
161
|
-
checkParams({
|
|
171
|
+
checkParams({
|
|
172
|
+
appIdKey: getAppIdKey(this),
|
|
173
|
+
pageIdKey: getPageIdKey(this),
|
|
174
|
+
});
|
|
162
175
|
|
|
163
|
-
if (this
|
|
176
|
+
if (getGarbageCollectOnExecute(this)) {
|
|
164
177
|
await this.garbageCollect();
|
|
165
178
|
}
|
|
166
179
|
|
|
@@ -170,22 +183,13 @@ export async function callFunction (objectId, fn, args) {
|
|
|
170
183
|
functionDeclaration: fn,
|
|
171
184
|
arguments: args,
|
|
172
185
|
returnByValue: true,
|
|
173
|
-
appIdKey: this
|
|
174
|
-
pageIdKey: this
|
|
186
|
+
appIdKey: getAppIdKey(this),
|
|
187
|
+
pageIdKey: getPageIdKey(this),
|
|
175
188
|
});
|
|
176
189
|
|
|
177
190
|
return convertResult(res);
|
|
178
191
|
}
|
|
179
192
|
|
|
180
193
|
/**
|
|
181
|
-
* @typedef {
|
|
182
|
-
* @property {string | null | undefined} _appIdKey
|
|
183
|
-
* @property {string | number | null | undefined} _pageIdKey
|
|
184
|
-
* @property {boolean} _pageLoading
|
|
185
|
-
* @property {boolean} _garbageCollectOnExecute
|
|
186
|
-
* @property {(this: RemoteDebugger, startPageLoadTimer?: timing.Timer | null | undefined) => Promise<void>} waitForDom:
|
|
187
|
-
*/
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* @typedef {import('../remote-debugger').RemoteDebugger & HasExecutionRelatedProperties} RemoteDebugger
|
|
194
|
+
* @typedef {import('../remote-debugger').RemoteDebugger} RemoteDebugger
|
|
191
195
|
*/
|
|
@@ -4,7 +4,16 @@ import {
|
|
|
4
4
|
appInfoFromDict,
|
|
5
5
|
} from '../utils';
|
|
6
6
|
import _ from 'lodash';
|
|
7
|
-
|
|
7
|
+
import {
|
|
8
|
+
setAppIdKey,
|
|
9
|
+
getAppDict,
|
|
10
|
+
getAppIdKey,
|
|
11
|
+
getBundleId,
|
|
12
|
+
getNavigatingToPage,
|
|
13
|
+
setCurrentState,
|
|
14
|
+
setConnectedDrivers,
|
|
15
|
+
getSkippedApps,
|
|
16
|
+
} from './property-accessors';
|
|
8
17
|
|
|
9
18
|
/*
|
|
10
19
|
* Generic callbacks used throughout the lifecycle of the Remote Debugger.
|
|
@@ -26,8 +35,8 @@ export async function onPageChange (err, appIdKey, pageDict) {
|
|
|
26
35
|
|
|
27
36
|
const currentPages = pageArrayFromDict(pageDict);
|
|
28
37
|
// save the page dict for this app
|
|
29
|
-
if (this
|
|
30
|
-
const previousPages = this
|
|
38
|
+
if (getAppDict(this)[appIdKey]) {
|
|
39
|
+
const previousPages = getAppDict(this)[appIdKey].pageArray;
|
|
31
40
|
// we have a pre-existing pageDict
|
|
32
41
|
if (previousPages && _.isEqual(previousPages, currentPages)) {
|
|
33
42
|
this.log.debug(
|
|
@@ -37,13 +46,13 @@ export async function onPageChange (err, appIdKey, pageDict) {
|
|
|
37
46
|
return;
|
|
38
47
|
}
|
|
39
48
|
// keep track of the page dictionary
|
|
40
|
-
this
|
|
49
|
+
getAppDict(this)[appIdKey].pageArray = currentPages;
|
|
41
50
|
this.log.debug(
|
|
42
51
|
`Pages changed for ${appIdKey}: ${JSON.stringify(previousPages)} -> ${JSON.stringify(currentPages)}`
|
|
43
52
|
);
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
if (this
|
|
55
|
+
if (getNavigatingToPage(this)) {
|
|
47
56
|
// in the middle of navigating, so reporting a page change will cause problems
|
|
48
57
|
return;
|
|
49
58
|
}
|
|
@@ -76,19 +85,19 @@ export async function onAppConnect (err, dict) {
|
|
|
76
85
|
export function onAppDisconnect (err, dict) {
|
|
77
86
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
78
87
|
this.log.debug(`Application '${appIdKey}' disconnected. Removing from app dictionary.`);
|
|
79
|
-
this.log.debug(`Current app is '${this
|
|
88
|
+
this.log.debug(`Current app is '${getAppIdKey(this)}'`);
|
|
80
89
|
|
|
81
90
|
// get rid of the entry in our app dictionary,
|
|
82
91
|
// since it is no longer available
|
|
83
|
-
delete this
|
|
92
|
+
delete getAppDict(this)[appIdKey];
|
|
84
93
|
|
|
85
94
|
// if the disconnected app is the one we are connected to, try to find another
|
|
86
|
-
if (this
|
|
95
|
+
if (getAppIdKey(this) === appIdKey) {
|
|
87
96
|
this.log.debug(`No longer have app id. Attempting to find new one.`);
|
|
88
|
-
this
|
|
97
|
+
setAppIdKey(this, getDebuggerAppKey.bind(this)(/** @type {string} */ (getBundleId(this))));
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
if (
|
|
100
|
+
if (_.isEmpty(getAppDict(this))) {
|
|
92
101
|
// this means we no longer have any apps. what the what?
|
|
93
102
|
this.log.debug('Main app disconnected. Disconnecting altogether.');
|
|
94
103
|
this.emit(events.EVENT_DISCONNECT, true);
|
|
@@ -114,8 +123,8 @@ export async function onAppUpdate (err, dict) {
|
|
|
114
123
|
* @returns {void}
|
|
115
124
|
*/
|
|
116
125
|
export function onConnectedDriverList (err, drivers) {
|
|
117
|
-
this
|
|
118
|
-
this.log.debug(`Received connected driver list: ${JSON.stringify(this.
|
|
126
|
+
setConnectedDrivers(this, drivers.WIRDriverDictionaryKey);
|
|
127
|
+
this.log.debug(`Received connected driver list: ${JSON.stringify(this.connectedDrivers)}`);
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
/**
|
|
@@ -125,10 +134,10 @@ export function onConnectedDriverList (err, drivers) {
|
|
|
125
134
|
* @returns {void}
|
|
126
135
|
*/
|
|
127
136
|
export function onCurrentState (err, state) {
|
|
128
|
-
this
|
|
137
|
+
setCurrentState(this, state.WIRAutomationAvailabilityKey);
|
|
129
138
|
// This state changes when 'Remote Automation' in 'Settings app' > 'Safari' > 'Advanced' > 'Remote Automation' changes
|
|
130
139
|
// WIRAutomationAvailabilityAvailable or WIRAutomationAvailabilityNotAvailable
|
|
131
|
-
this.log.debug(`Received connected automation availability state: ${JSON.stringify(this.
|
|
140
|
+
this.log.debug(`Received connected automation availability state: ${JSON.stringify(this.currentState)}`);
|
|
132
141
|
}
|
|
133
142
|
|
|
134
143
|
/**
|
|
@@ -146,13 +155,13 @@ export async function onConnectedApplicationList (err, apps) {
|
|
|
146
155
|
let newDict = {};
|
|
147
156
|
for (const dict of _.values(apps)) {
|
|
148
157
|
const [id, entry] = appInfoFromDict(dict);
|
|
149
|
-
if (this.
|
|
158
|
+
if (getSkippedApps(this).includes(entry.name)) {
|
|
150
159
|
continue;
|
|
151
160
|
}
|
|
152
161
|
newDict[id] = entry;
|
|
153
162
|
}
|
|
154
163
|
// update the object's list of apps
|
|
155
|
-
_.defaults(this
|
|
164
|
+
_.defaults(getAppDict(this), newDict);
|
|
156
165
|
}
|
|
157
166
|
|
|
158
167
|
/**
|
|
@@ -164,17 +173,16 @@ export async function onConnectedApplicationList (err, apps) {
|
|
|
164
173
|
function updateAppsWithDict (dict) {
|
|
165
174
|
// get the dictionary entry into a nice form, and add it to the
|
|
166
175
|
// application dictionary
|
|
167
|
-
this._appDict ??= {};
|
|
168
176
|
const [id, entry] = appInfoFromDict(dict);
|
|
169
|
-
if (this
|
|
177
|
+
if (getAppDict(this)[id]) {
|
|
170
178
|
// preserve the page dictionary for this entry
|
|
171
|
-
entry.pageArray = this
|
|
179
|
+
entry.pageArray = getAppDict(this)[id].pageArray;
|
|
172
180
|
}
|
|
173
|
-
this
|
|
181
|
+
getAppDict(this)[id] = entry;
|
|
174
182
|
|
|
175
183
|
// try to get the app id from our connected apps
|
|
176
|
-
if (!this
|
|
177
|
-
this
|
|
184
|
+
if (!getAppIdKey(this)) {
|
|
185
|
+
setAppIdKey(this, getDebuggerAppKey.bind(this)(/** @type {string} */ (getBundleId(this))));
|
|
178
186
|
}
|
|
179
187
|
}
|
|
180
188
|
|
|
@@ -188,7 +196,7 @@ function updateAppsWithDict (dict) {
|
|
|
188
196
|
*/
|
|
189
197
|
export function getDebuggerAppKey (bundleId) {
|
|
190
198
|
let appId;
|
|
191
|
-
for (const [key, data] of _.toPairs(this
|
|
199
|
+
for (const [key, data] of _.toPairs(getAppDict(this))) {
|
|
192
200
|
if (data.bundleId === bundleId) {
|
|
193
201
|
appId = key;
|
|
194
202
|
break;
|
|
@@ -198,7 +206,7 @@ export function getDebuggerAppKey (bundleId) {
|
|
|
198
206
|
if (appId) {
|
|
199
207
|
this.log.debug(`Found app id key '${appId}' for bundle '${bundleId}'`);
|
|
200
208
|
let proxyAppId;
|
|
201
|
-
for (const [key, data] of _.toPairs(this
|
|
209
|
+
for (const [key, data] of _.toPairs(getAppDict(this))) {
|
|
202
210
|
if (data.isProxy && data.hostId === appId) {
|
|
203
211
|
this.log.debug(`Found separate bundleId '${data.bundleId}' ` +
|
|
204
212
|
`acting as proxy for '${bundleId}', with app id '${key}'`);
|
|
@@ -216,17 +224,5 @@ export function getDebuggerAppKey (bundleId) {
|
|
|
216
224
|
}
|
|
217
225
|
|
|
218
226
|
/**
|
|
219
|
-
* @typedef {
|
|
220
|
-
* @property {string | null | undefined} _appIdKey
|
|
221
|
-
* @property {string | number | null | undefined} _pageIdKey
|
|
222
|
-
* @property {import('../types').AppDict} _appDict
|
|
223
|
-
* @property {boolean} _navigatingToPage
|
|
224
|
-
* @property {string | undefined} _currentState
|
|
225
|
-
* @property {string | undefined} _bundleId
|
|
226
|
-
* @property {string[] | undefined} _connectedDrivers
|
|
227
|
-
* @property {string[]} _skippedApps
|
|
228
|
-
*/
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* @typedef {import('../remote-debugger').RemoteDebugger & HasMessageHandlersRelatedProperties} RemoteDebugger
|
|
227
|
+
* @typedef {import('../remote-debugger').RemoteDebugger} RemoteDebugger
|
|
232
228
|
*/
|
package/lib/mixins/misc.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { checkParams } from '../utils';
|
|
2
2
|
import B from 'bluebird';
|
|
3
|
+
import {
|
|
4
|
+
getAppIdKey,
|
|
5
|
+
getPageIdKey,
|
|
6
|
+
} from './property-accessors';
|
|
3
7
|
|
|
4
8
|
const SAFARI_BUNDLE_ID = 'com.apple.mobilesafari';
|
|
5
9
|
const GARBAGE_COLLECT_TIMEOUT_MS = 5000;
|
|
@@ -23,8 +27,8 @@ export async function startTimeline (fn) {
|
|
|
23
27
|
this.log.debug('Starting to record the timeline');
|
|
24
28
|
this.requireRpcClient().on('Timeline.eventRecorded', fn);
|
|
25
29
|
return await this.requireRpcClient().send('Timeline.start', {
|
|
26
|
-
appIdKey: this
|
|
27
|
-
pageIdKey: this
|
|
30
|
+
appIdKey: getAppIdKey(this),
|
|
31
|
+
pageIdKey: getPageIdKey(this),
|
|
28
32
|
});
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -35,8 +39,8 @@ export async function startTimeline (fn) {
|
|
|
35
39
|
export async function stopTimeline () {
|
|
36
40
|
this.log.debug('Stopping to record the timeline');
|
|
37
41
|
await this.requireRpcClient().send('Timeline.stop', {
|
|
38
|
-
appIdKey: this
|
|
39
|
-
pageIdKey: this
|
|
42
|
+
appIdKey: getAppIdKey(this),
|
|
43
|
+
pageIdKey: getPageIdKey(this),
|
|
40
44
|
});
|
|
41
45
|
}
|
|
42
46
|
|
|
@@ -49,9 +53,9 @@ export async function stopTimeline () {
|
|
|
49
53
|
export async function overrideUserAgent (value) {
|
|
50
54
|
this.log.debug('Setting overrideUserAgent');
|
|
51
55
|
return await this.requireRpcClient().send('Page.overrideUserAgent', {
|
|
52
|
-
appIdKey: this
|
|
53
|
-
pageIdKey: this
|
|
54
|
-
value
|
|
56
|
+
appIdKey: getAppIdKey(this),
|
|
57
|
+
pageIdKey: getPageIdKey(this),
|
|
58
|
+
value,
|
|
55
59
|
});
|
|
56
60
|
}
|
|
57
61
|
|
|
@@ -64,7 +68,10 @@ export async function garbageCollect (timeoutMs = GARBAGE_COLLECT_TIMEOUT_MS) {
|
|
|
64
68
|
this.log.debug(`Garbage collecting with ${timeoutMs}ms timeout`);
|
|
65
69
|
|
|
66
70
|
try {
|
|
67
|
-
checkParams({
|
|
71
|
+
checkParams({
|
|
72
|
+
appIdKey: getAppIdKey(this),
|
|
73
|
+
pageIdKey: getPageIdKey(this),
|
|
74
|
+
});
|
|
68
75
|
} catch (err) {
|
|
69
76
|
this.log.debug(`Unable to collect garbage at this time`);
|
|
70
77
|
return;
|
|
@@ -73,8 +80,8 @@ export async function garbageCollect (timeoutMs = GARBAGE_COLLECT_TIMEOUT_MS) {
|
|
|
73
80
|
try {
|
|
74
81
|
await B.resolve(this.requireRpcClient().send(
|
|
75
82
|
'Heap.gc', {
|
|
76
|
-
appIdKey: this
|
|
77
|
-
pageIdKey: this
|
|
83
|
+
appIdKey: getAppIdKey(this),
|
|
84
|
+
pageIdKey: getPageIdKey(this),
|
|
78
85
|
})
|
|
79
86
|
).timeout(timeoutMs);
|
|
80
87
|
this.log.debug(`Garbage collection successful`);
|
|
@@ -88,11 +95,5 @@ export async function garbageCollect (timeoutMs = GARBAGE_COLLECT_TIMEOUT_MS) {
|
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
/**
|
|
91
|
-
* @typedef {
|
|
92
|
-
* @property {string | null | undefined} _appIdKey
|
|
93
|
-
* @property {string | number | null | undefined} _pageIdKey
|
|
94
|
-
*/
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @typedef {import('../remote-debugger').RemoteDebugger & HasMiscRelatedProperties} RemoteDebugger
|
|
98
|
+
* @typedef {import('../remote-debugger').RemoteDebugger} RemoteDebugger
|
|
98
99
|
*/
|