appium-remote-debugger 15.7.3 → 15.8.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 +6 -0
- package/build/lib/atoms.d.ts.map +1 -1
- package/build/lib/atoms.js +27 -28
- package/build/lib/atoms.js.map +1 -1
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +7 -0
- package/build/lib/index.js.map +1 -1
- package/build/lib/mixins/connect.d.ts.map +1 -1
- package/build/lib/mixins/connect.js +21 -25
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/execute.d.ts.map +1 -1
- package/build/lib/mixins/execute.js +2 -8
- package/build/lib/mixins/execute.js.map +1 -1
- package/build/lib/mixins/message-handlers.d.ts.map +1 -1
- package/build/lib/mixins/message-handlers.js +8 -12
- package/build/lib/mixins/message-handlers.js.map +1 -1
- package/build/lib/mixins/misc.d.ts.map +1 -1
- package/build/lib/mixins/misc.js +5 -39
- package/build/lib/mixins/misc.js.map +1 -1
- package/build/lib/mixins/navigate.d.ts.map +1 -1
- package/build/lib/mixins/navigate.js +20 -55
- package/build/lib/mixins/navigate.js.map +1 -1
- package/build/lib/mixins/property-accessors.d.ts +24 -0
- package/build/lib/mixins/property-accessors.d.ts.map +1 -1
- package/build/lib/mixins/property-accessors.js +24 -0
- package/build/lib/mixins/property-accessors.js.map +1 -1
- package/build/lib/remote-debugger.d.ts +38 -38
- package/build/lib/remote-debugger.d.ts.map +1 -1
- package/build/lib/remote-debugger.js +64 -69
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/lib/rpc/remote-messages.d.ts.map +1 -1
- package/build/lib/rpc/remote-messages.js +7 -8
- package/build/lib/rpc/remote-messages.js.map +1 -1
- package/build/lib/rpc/rpc-client-real-device-shim.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client-real-device-shim.js +3 -6
- package/build/lib/rpc/rpc-client-real-device-shim.js.map +1 -1
- package/build/lib/rpc/rpc-client-simulator.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client-simulator.js +3 -5
- package/build/lib/rpc/rpc-client-simulator.js.map +1 -1
- package/build/lib/rpc/rpc-client.d.ts +27 -27
- package/build/lib/rpc/rpc-client.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client.js +226 -224
- package/build/lib/rpc/rpc-client.js.map +1 -1
- package/build/lib/rpc/rpc-message-handler.js +7 -10
- package/build/lib/rpc/rpc-message-handler.js.map +1 -1
- package/build/lib/types.d.ts +19 -19
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/utils.d.ts +70 -4
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +171 -23
- package/build/lib/utils.js.map +1 -1
- package/lib/atoms.ts +31 -32
- package/lib/index.ts +7 -0
- package/lib/mixins/connect.ts +22 -23
- package/lib/mixins/execute.ts +3 -5
- package/lib/mixins/message-handlers.ts +9 -10
- package/lib/mixins/misc.ts +8 -7
- package/lib/mixins/navigate.ts +58 -63
- package/lib/mixins/property-accessors.ts +24 -0
- package/lib/remote-debugger.ts +74 -76
- package/lib/rpc/remote-messages.ts +10 -5
- package/lib/rpc/rpc-client-real-device-shim.ts +3 -3
- package/lib/rpc/rpc-client-simulator.ts +3 -5
- package/lib/rpc/rpc-client.ts +259 -247
- package/lib/rpc/rpc-message-handler.ts +7 -7
- package/lib/types.ts +24 -24
- package/lib/utils.ts +181 -23
- package/package.json +3 -7
- package/scripts/common.mjs +42 -37
- package/scripts/web_inspector_proxy.mjs +3 -5
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {events} from './events';
|
|
2
|
-
import {pageArrayFromDict, appInfoFromDict} from '../utils';
|
|
3
|
-
import _ from 'lodash';
|
|
2
|
+
import {deepEqual, defaults, isEmpty, pageArrayFromDict, appInfoFromDict} from '../utils';
|
|
4
3
|
import {
|
|
5
4
|
setAppIdKey,
|
|
6
5
|
getAppDict,
|
|
@@ -35,7 +34,7 @@ export async function onPageChange(
|
|
|
35
34
|
appIdKey: string,
|
|
36
35
|
pageDict: StringRecord,
|
|
37
36
|
): Promise<void> {
|
|
38
|
-
if (
|
|
37
|
+
if (isEmpty(pageDict)) {
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -44,7 +43,7 @@ export async function onPageChange(
|
|
|
44
43
|
if (getAppDict(this)[appIdKey]) {
|
|
45
44
|
const previousPages = getAppDict(this)[appIdKey].pageArray;
|
|
46
45
|
// we have a pre-existing pageDict
|
|
47
|
-
if (previousPages &&
|
|
46
|
+
if (previousPages && deepEqual(previousPages, currentPages)) {
|
|
48
47
|
this.log.debug(
|
|
49
48
|
`Received page change notice for app '${appIdKey}' ` +
|
|
50
49
|
`but the listing has not changed. Ignoring.`,
|
|
@@ -116,7 +115,7 @@ export function onAppDisconnect(
|
|
|
116
115
|
setAppIdKey(this, getDebuggerAppKey.bind(this)(getBundleId(this) as string));
|
|
117
116
|
}
|
|
118
117
|
|
|
119
|
-
if (
|
|
118
|
+
if (isEmpty(getAppDict(this))) {
|
|
120
119
|
// this means we no longer have any apps. what the what?
|
|
121
120
|
this.log.debug('Main app disconnected. Disconnecting altogether.');
|
|
122
121
|
this.emit(events.EVENT_DISCONNECT, true);
|
|
@@ -193,12 +192,12 @@ export async function onConnectedApplicationList(
|
|
|
193
192
|
err: Error | null | undefined,
|
|
194
193
|
apps: StringRecord,
|
|
195
194
|
): Promise<void> {
|
|
196
|
-
this.log.debug(`Received connected applications list: ${
|
|
195
|
+
this.log.debug(`Received connected applications list: ${Object.keys(apps).join(', ')}`);
|
|
197
196
|
|
|
198
197
|
// translate the received information into an easier-to-manage
|
|
199
198
|
// hash with app id as key, and app info as value
|
|
200
199
|
const newDict: AppDict = {};
|
|
201
|
-
for (const dict of
|
|
200
|
+
for (const dict of Object.values(apps)) {
|
|
202
201
|
const [id, entry] = appInfoFromDict(dict);
|
|
203
202
|
if (getSkippedApps(this).includes(entry.name)) {
|
|
204
203
|
continue;
|
|
@@ -206,7 +205,7 @@ export async function onConnectedApplicationList(
|
|
|
206
205
|
newDict[id] = entry;
|
|
207
206
|
}
|
|
208
207
|
// update the object's list of apps
|
|
209
|
-
|
|
208
|
+
Object.assign(getAppDict(this), defaults(getAppDict(this), newDict));
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
/**
|
|
@@ -220,7 +219,7 @@ export async function onConnectedApplicationList(
|
|
|
220
219
|
*/
|
|
221
220
|
export function getDebuggerAppKey(this: RemoteDebugger, bundleId: string): string | undefined {
|
|
222
221
|
let appId: string | undefined;
|
|
223
|
-
for (const [key, data] of
|
|
222
|
+
for (const [key, data] of Object.entries(getAppDict(this))) {
|
|
224
223
|
if (data.bundleId === bundleId) {
|
|
225
224
|
appId = key;
|
|
226
225
|
break;
|
|
@@ -230,7 +229,7 @@ export function getDebuggerAppKey(this: RemoteDebugger, bundleId: string): strin
|
|
|
230
229
|
if (appId) {
|
|
231
230
|
this.log.debug(`Found app id key '${appId}' for bundle '${bundleId}'`);
|
|
232
231
|
let proxyAppId: string | undefined;
|
|
233
|
-
for (const [key, data] of
|
|
232
|
+
for (const [key, data] of Object.entries(getAppDict(this))) {
|
|
234
233
|
if (data.isProxy && data.hostId === appId) {
|
|
235
234
|
this.log.debug(
|
|
236
235
|
`Found separate bundleId '${data.bundleId}' ` +
|
package/lib/mixins/misc.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {checkParams} from '../utils';
|
|
2
|
-
import B, {TimeoutError as BTimeoutError} from 'bluebird';
|
|
1
|
+
import {checkParams, TimeoutError, withTimeout} from '../utils';
|
|
3
2
|
import {getAppIdKey, getPageIdKey} from './property-accessors';
|
|
4
3
|
import type {RemoteDebugger} from '../remote-debugger';
|
|
5
4
|
|
|
@@ -77,14 +76,15 @@ export async function isJavascriptExecutionBlocked(
|
|
|
77
76
|
timeoutMs: number = 1000,
|
|
78
77
|
): Promise<boolean> {
|
|
79
78
|
try {
|
|
80
|
-
await
|
|
79
|
+
await withTimeout(
|
|
81
80
|
this.requireRpcClient().send('Runtime.evaluate', {
|
|
82
81
|
expression: '1+1;',
|
|
83
82
|
returnByValue: true,
|
|
84
83
|
appIdKey: getAppIdKey(this),
|
|
85
84
|
pageIdKey: getPageIdKey(this),
|
|
86
85
|
}),
|
|
87
|
-
|
|
86
|
+
timeoutMs,
|
|
87
|
+
);
|
|
88
88
|
return false;
|
|
89
89
|
} catch {
|
|
90
90
|
return true;
|
|
@@ -116,15 +116,16 @@ export async function garbageCollect(
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
try {
|
|
119
|
-
await
|
|
119
|
+
await withTimeout(
|
|
120
120
|
this.requireRpcClient().send('Heap.gc', {
|
|
121
121
|
appIdKey: getAppIdKey(this),
|
|
122
122
|
pageIdKey: getPageIdKey(this),
|
|
123
123
|
}),
|
|
124
|
-
|
|
124
|
+
timeoutMs,
|
|
125
|
+
);
|
|
125
126
|
this.log.debug(`Garbage collection successful`);
|
|
126
127
|
} catch (e: any) {
|
|
127
|
-
if (e instanceof
|
|
128
|
+
if (e instanceof TimeoutError) {
|
|
128
129
|
this.log.debug(`Garbage collection timed out after ${timeoutMs}ms`);
|
|
129
130
|
} else {
|
|
130
131
|
this.log.debug(`Unable to collect garbage: ${e.message}`);
|
package/lib/mixins/navigate.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {checkParams} from '../utils';
|
|
1
|
+
import {checkParams, delay, TimeoutError, withTimeout} from '../utils';
|
|
2
2
|
import {events} from './events';
|
|
3
3
|
import {timing, util} from '@appium/support';
|
|
4
|
-
import _ from 'lodash';
|
|
5
|
-
import B, {TimeoutError as BTimeoutError} from 'bluebird';
|
|
6
4
|
import {
|
|
7
5
|
getAppIdKey,
|
|
8
6
|
setPageLoading,
|
|
@@ -57,7 +55,7 @@ export function cancelPageLoad(this: RemoteDebugger): void {
|
|
|
57
55
|
* - 'normal' (default): returns true only when readyState is 'complete'
|
|
58
56
|
*/
|
|
59
57
|
export function isPageLoadingCompleted(this: RemoteDebugger, readyState: string): boolean {
|
|
60
|
-
const pageLoadStrategy =
|
|
58
|
+
const pageLoadStrategy = (getPageLoadStartegy(this) ?? '').toLowerCase();
|
|
61
59
|
switch (pageLoadStrategy) {
|
|
62
60
|
case PAGE_LOAD_STRATEGY.EAGER:
|
|
63
61
|
// This could include 'interactive' or 'complete'
|
|
@@ -89,60 +87,56 @@ export async function waitForDom(
|
|
|
89
87
|
let isPageLoading = true;
|
|
90
88
|
setPageLoading(this, true);
|
|
91
89
|
setPageLoadDelay(this, util.cancellableDelay(readinessTimeoutMs));
|
|
92
|
-
const pageReadinessPromise =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
90
|
+
const pageReadinessPromise = (async () => {
|
|
91
|
+
let retry = 0;
|
|
92
|
+
while (isPageLoading) {
|
|
93
|
+
// if we are ready, or we've spend too much time on this
|
|
94
|
+
const elapsedMs = timer.getDuration().asMilliSeconds;
|
|
95
|
+
// exponential retry
|
|
96
|
+
const intervalMs = Math.min(
|
|
97
|
+
PAGE_READINESS_CHECK_INTERVAL_MS * Math.pow(2, retry),
|
|
98
|
+
readinessTimeoutMs - elapsedMs,
|
|
99
|
+
);
|
|
100
|
+
await delay(intervalMs);
|
|
101
|
+
// we can get this called in the middle of trying to find a new app
|
|
102
|
+
if (!getAppIdKey(this)) {
|
|
103
|
+
this.log.debug('Not connected to an application. Ignoring page readiess check');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (!isPageLoading) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
112
109
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
isPageLoading = false;
|
|
118
|
-
}
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (elapsedMs > readinessTimeoutMs) {
|
|
122
|
-
this.log.info(
|
|
123
|
-
`Timed out after ${readinessTimeoutMs}ms of waiting for the page readiness. Continuing anyway`,
|
|
124
|
-
);
|
|
110
|
+
const maxWaitMs = (readinessTimeoutMs - elapsedMs) * 0.95;
|
|
111
|
+
if (await this.checkPageIsReady(maxWaitMs)) {
|
|
112
|
+
if (isPageLoading) {
|
|
113
|
+
this.log.debug(`Page is ready in ${elapsedMs}ms`);
|
|
125
114
|
isPageLoading = false;
|
|
126
|
-
return;
|
|
127
115
|
}
|
|
128
|
-
|
|
116
|
+
return;
|
|
129
117
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
118
|
+
if (elapsedMs > readinessTimeoutMs) {
|
|
119
|
+
this.log.info(
|
|
120
|
+
`Timed out after ${readinessTimeoutMs}ms of waiting for the page readiness. Continuing anyway`,
|
|
121
|
+
);
|
|
122
|
+
isPageLoading = false;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
retry++;
|
|
126
|
+
}
|
|
127
|
+
})();
|
|
128
|
+
const cancellationPromise = (async () => {
|
|
129
|
+
try {
|
|
130
|
+
await getPageLoadDelay(this);
|
|
131
|
+
} catch {}
|
|
132
|
+
})();
|
|
139
133
|
|
|
140
134
|
try {
|
|
141
|
-
await
|
|
135
|
+
await Promise.race([cancellationPromise, pageReadinessPromise]);
|
|
142
136
|
} finally {
|
|
143
137
|
isPageLoading = false;
|
|
144
138
|
setPageLoading(this, false);
|
|
145
|
-
setPageLoadDelay(this,
|
|
139
|
+
setPageLoadDelay(this, undefined);
|
|
146
140
|
}
|
|
147
141
|
}
|
|
148
142
|
|
|
@@ -159,7 +153,7 @@ export async function checkPageIsReady(this: RemoteDebugger, timeoutMs?: number)
|
|
|
159
153
|
const readyCmd = 'document.readyState;';
|
|
160
154
|
const actualTimeoutMs = timeoutMs ?? getPageReadyTimeout(this);
|
|
161
155
|
try {
|
|
162
|
-
const readyState = await
|
|
156
|
+
const readyState = await withTimeout(this.execute(readyCmd), actualTimeoutMs);
|
|
163
157
|
this.log.debug(
|
|
164
158
|
JSON.stringify({
|
|
165
159
|
readyState,
|
|
@@ -168,7 +162,7 @@ export async function checkPageIsReady(this: RemoteDebugger, timeoutMs?: number)
|
|
|
168
162
|
);
|
|
169
163
|
return this.isPageLoadingCompleted(readyState);
|
|
170
164
|
} catch (err: any) {
|
|
171
|
-
if (err instanceof
|
|
165
|
+
if (err instanceof TimeoutError) {
|
|
172
166
|
this.log.debug(`Page readiness check timed out after ${actualTimeoutMs}ms`);
|
|
173
167
|
} else {
|
|
174
168
|
this.log.warn(`Page readiness check has failed. Original error: ${err.message}`);
|
|
@@ -210,7 +204,8 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
210
204
|
let isPageLoading = true;
|
|
211
205
|
const start = new timing.Timer().start();
|
|
212
206
|
|
|
213
|
-
|
|
207
|
+
let pageReadinessResolved = false;
|
|
208
|
+
const pageReadinessPromise = new Promise<void>((resolve) => {
|
|
214
209
|
onPageLoadedTimeout = setTimeout(() => {
|
|
215
210
|
if (isPageLoading) {
|
|
216
211
|
isPageLoading = false;
|
|
@@ -219,6 +214,7 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
219
214
|
`for the ${url} page readiness. Continuing anyway`,
|
|
220
215
|
);
|
|
221
216
|
}
|
|
217
|
+
pageReadinessResolved = true;
|
|
222
218
|
return resolve();
|
|
223
219
|
}, readinessTimeoutMs);
|
|
224
220
|
|
|
@@ -233,6 +229,7 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
233
229
|
clearTimeout(onPageLoadedTimeout);
|
|
234
230
|
onPageLoadedTimeout = null;
|
|
235
231
|
}
|
|
232
|
+
pageReadinessResolved = true;
|
|
236
233
|
return resolve();
|
|
237
234
|
};
|
|
238
235
|
|
|
@@ -241,28 +238,26 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
241
238
|
|
|
242
239
|
// Page.navigate was removed from the WebKit Inspector protocol since iOS 26.4
|
|
243
240
|
// See https://github.com/appium/appium/issues/21976
|
|
244
|
-
rpcClient.send('Runtime.evaluate', {
|
|
241
|
+
void rpcClient.send('Runtime.evaluate', {
|
|
245
242
|
expression: `window.location.href = ${JSON.stringify(url)};`,
|
|
246
243
|
appIdKey,
|
|
247
244
|
pageIdKey,
|
|
248
245
|
});
|
|
249
246
|
});
|
|
250
|
-
const cancellationPromise =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
})(),
|
|
256
|
-
);
|
|
247
|
+
const cancellationPromise = (async () => {
|
|
248
|
+
try {
|
|
249
|
+
await getPageLoadDelay(this);
|
|
250
|
+
} catch {}
|
|
251
|
+
})();
|
|
257
252
|
|
|
258
253
|
try {
|
|
259
|
-
await
|
|
254
|
+
await Promise.race([cancellationPromise, pageReadinessPromise]);
|
|
260
255
|
} finally {
|
|
261
256
|
setPageLoading(this, false);
|
|
262
257
|
isPageLoading = false;
|
|
263
258
|
setNavigatingToPage(this, false);
|
|
264
|
-
setPageLoadDelay(this,
|
|
265
|
-
if (onPageLoadedTimeout &&
|
|
259
|
+
setPageLoadDelay(this, undefined);
|
|
260
|
+
if (onPageLoadedTimeout && pageReadinessResolved) {
|
|
266
261
|
clearTimeout(onPageLoadedTimeout);
|
|
267
262
|
onPageLoadedTimeout = null;
|
|
268
263
|
}
|
|
@@ -3,26 +3,32 @@ import type {StringRecord} from '@appium/types';
|
|
|
3
3
|
import type {RemoteDebugger} from '../remote-debugger';
|
|
4
4
|
import type {EventListener} from '../types';
|
|
5
5
|
|
|
6
|
+
/** Gets the current app dictionary snapshot reference. */
|
|
6
7
|
export function getAppDict(instance: RemoteDebugger): (typeof instance)['_appDict'] {
|
|
7
8
|
return instance['_appDict'];
|
|
8
9
|
}
|
|
9
10
|
|
|
11
|
+
/** Gets the currently selected application id key. */
|
|
10
12
|
export function getAppIdKey(instance: RemoteDebugger): (typeof instance)['_appIdKey'] {
|
|
11
13
|
return instance['_appIdKey'];
|
|
12
14
|
}
|
|
13
15
|
|
|
16
|
+
/** Sets the currently selected application id key. */
|
|
14
17
|
export function setAppIdKey(instance: RemoteDebugger, value: (typeof instance)['_appIdKey']): void {
|
|
15
18
|
instance['_appIdKey'] = value;
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
/** Gets the current RPC client instance. */
|
|
18
22
|
export function getRcpClient(instance: RemoteDebugger): (typeof instance)['_rpcClient'] {
|
|
19
23
|
return instance['_rpcClient'];
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
/** Gets the currently selected page id key. */
|
|
22
27
|
export function getPageIdKey(instance: RemoteDebugger): (typeof instance)['_pageIdKey'] {
|
|
23
28
|
return instance['_pageIdKey'];
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
/** Sets the currently selected page id key. */
|
|
26
32
|
export function setPageIdKey(
|
|
27
33
|
instance: RemoteDebugger,
|
|
28
34
|
value: (typeof instance)['_pageIdKey'],
|
|
@@ -30,58 +36,70 @@ export function setPageIdKey(
|
|
|
30
36
|
instance['_pageIdKey'] = value;
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
/** Gets whether Safari automation mode is enabled. */
|
|
33
40
|
export function getIsSafari(instance: RemoteDebugger): (typeof instance)['_isSafari'] {
|
|
34
41
|
return instance['_isSafari'];
|
|
35
42
|
}
|
|
36
43
|
|
|
44
|
+
/** Gets whether Safari should be included in app listing. */
|
|
37
45
|
export function getIncludeSafari(instance: RemoteDebugger): (typeof instance)['_includeSafari'] {
|
|
38
46
|
return instance['_includeSafari'];
|
|
39
47
|
}
|
|
40
48
|
|
|
49
|
+
/** Gets the configured primary bundle identifier. */
|
|
41
50
|
export function getBundleId(instance: RemoteDebugger): (typeof instance)['_bundleId'] {
|
|
42
51
|
return instance['_bundleId'];
|
|
43
52
|
}
|
|
44
53
|
|
|
54
|
+
/** Gets additional bundle identifiers used for matching apps. */
|
|
45
55
|
export function getAdditionalBundleIds(
|
|
46
56
|
instance: RemoteDebugger,
|
|
47
57
|
): (typeof instance)['_additionalBundleIds'] {
|
|
48
58
|
return instance['_additionalBundleIds'];
|
|
49
59
|
}
|
|
50
60
|
|
|
61
|
+
/** Gets bundle identifiers to be ignored during matching. */
|
|
51
62
|
export function getIgnoredBundleIds(
|
|
52
63
|
instance: RemoteDebugger,
|
|
53
64
|
): (typeof instance)['_ignoredBundleIds'] {
|
|
54
65
|
return instance['_ignoredBundleIds'];
|
|
55
66
|
}
|
|
56
67
|
|
|
68
|
+
/** Gets the list of apps that were skipped. */
|
|
57
69
|
export function getSkippedApps(instance: RemoteDebugger): (typeof instance)['_skippedApps'] {
|
|
58
70
|
return instance['_skippedApps'];
|
|
59
71
|
}
|
|
60
72
|
|
|
73
|
+
/** Gets registered client event listeners grouped by event name. */
|
|
61
74
|
export function getClientEventListeners(instance: RemoteDebugger): StringRecord<EventListener[]> {
|
|
62
75
|
return instance['_clientEventListeners'];
|
|
63
76
|
}
|
|
64
77
|
|
|
78
|
+
/** Gets whether page loading is currently in progress. */
|
|
65
79
|
export function getPageLoading(instance: RemoteDebugger): boolean {
|
|
66
80
|
return instance['_pageLoading'];
|
|
67
81
|
}
|
|
68
82
|
|
|
83
|
+
/** Sets whether page loading is currently in progress. */
|
|
69
84
|
export function setPageLoading(instance: RemoteDebugger, value: boolean): void {
|
|
70
85
|
instance['_pageLoading'] = value;
|
|
71
86
|
}
|
|
72
87
|
|
|
88
|
+
/** Gets whether GC should run after JavaScript execution. */
|
|
73
89
|
export function getGarbageCollectOnExecute(
|
|
74
90
|
instance: RemoteDebugger,
|
|
75
91
|
): (typeof instance)['_garbageCollectOnExecute'] {
|
|
76
92
|
return instance['_garbageCollectOnExecute'];
|
|
77
93
|
}
|
|
78
94
|
|
|
95
|
+
/** Gets whether a navigation-to-page operation is active. */
|
|
79
96
|
export function getNavigatingToPage(
|
|
80
97
|
instance: RemoteDebugger,
|
|
81
98
|
): (typeof instance)['_navigatingToPage'] {
|
|
82
99
|
return instance['_navigatingToPage'];
|
|
83
100
|
}
|
|
84
101
|
|
|
102
|
+
/** Sets whether a navigation-to-page operation is active. */
|
|
85
103
|
export function setNavigatingToPage(
|
|
86
104
|
instance: RemoteDebugger,
|
|
87
105
|
value: (typeof instance)['_navigatingToPage'],
|
|
@@ -89,6 +107,7 @@ export function setNavigatingToPage(
|
|
|
89
107
|
instance['_navigatingToPage'] = value;
|
|
90
108
|
}
|
|
91
109
|
|
|
110
|
+
/** Sets the current state string reported by the remote debugger. */
|
|
92
111
|
export function setCurrentState(
|
|
93
112
|
instance: RemoteDebugger,
|
|
94
113
|
value: (typeof instance)['_currentState'],
|
|
@@ -96,6 +115,7 @@ export function setCurrentState(
|
|
|
96
115
|
instance['_currentState'] = value;
|
|
97
116
|
}
|
|
98
117
|
|
|
118
|
+
/** Sets the currently connected driver list. */
|
|
99
119
|
export function setConnectedDrivers(
|
|
100
120
|
instance: RemoteDebugger,
|
|
101
121
|
value: (typeof instance)['_connectedDrivers'],
|
|
@@ -103,10 +123,12 @@ export function setConnectedDrivers(
|
|
|
103
123
|
instance['_connectedDrivers'] = value;
|
|
104
124
|
}
|
|
105
125
|
|
|
126
|
+
/** Gets the cancellable page-load delay promise. */
|
|
106
127
|
export function getPageLoadDelay(instance: RemoteDebugger): (typeof instance)['_pageLoadDelay'] {
|
|
107
128
|
return instance['_pageLoadDelay'];
|
|
108
129
|
}
|
|
109
130
|
|
|
131
|
+
/** Sets the cancellable page-load delay promise. */
|
|
110
132
|
export function setPageLoadDelay(
|
|
111
133
|
instance: RemoteDebugger,
|
|
112
134
|
value: (typeof instance)['_pageLoadDelay'],
|
|
@@ -114,12 +136,14 @@ export function setPageLoadDelay(
|
|
|
114
136
|
instance['_pageLoadDelay'] = value;
|
|
115
137
|
}
|
|
116
138
|
|
|
139
|
+
/** Gets the configured page load strategy. */
|
|
117
140
|
export function getPageLoadStartegy(
|
|
118
141
|
instance: RemoteDebugger,
|
|
119
142
|
): (typeof instance)['_pageLoadStrategy'] {
|
|
120
143
|
return instance['_pageLoadStrategy'];
|
|
121
144
|
}
|
|
122
145
|
|
|
146
|
+
/** Gets the configured page readiness timeout in milliseconds. */
|
|
123
147
|
export function getPageReadyTimeout(
|
|
124
148
|
instance: RemoteDebugger,
|
|
125
149
|
): (typeof instance)['_pageReadyTimeout'] {
|
package/lib/remote-debugger.ts
CHANGED
|
@@ -10,50 +10,16 @@ import * as cookieMixins from './mixins/cookies';
|
|
|
10
10
|
import * as screenshotMixins from './mixins/screenshot';
|
|
11
11
|
import * as eventMixins from './mixins/events';
|
|
12
12
|
import * as miscellaneousMixins from './mixins/misc';
|
|
13
|
-
import
|
|
13
|
+
import {util} from '@appium/support';
|
|
14
14
|
import type {RemoteDebuggerOptions, AppDict, EventListener, PageIdKey, AppIdKey} from './types';
|
|
15
15
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
16
16
|
import type {RpcClient} from './rpc/rpc-client';
|
|
17
|
-
import type B from 'bluebird';
|
|
18
17
|
|
|
19
18
|
export const REMOTE_DEBUGGER_PORT = 27753;
|
|
20
19
|
const PAGE_READY_TIMEOUT_MS = 5000;
|
|
21
20
|
const {version: MODULE_VERSION} = getModuleProperties();
|
|
22
21
|
|
|
23
22
|
export class RemoteDebugger extends EventEmitter {
|
|
24
|
-
protected _skippedApps: string[];
|
|
25
|
-
protected _clientEventListeners: StringRecord<EventListener[]>;
|
|
26
|
-
protected _appDict: AppDict;
|
|
27
|
-
protected _appIdKey?: AppIdKey;
|
|
28
|
-
protected _pageIdKey?: PageIdKey;
|
|
29
|
-
protected _connectedDrivers?: StringRecord[];
|
|
30
|
-
protected _currentState?: string;
|
|
31
|
-
protected _pageLoadDelay?: B<void>;
|
|
32
|
-
protected _rpcClient: RpcClient | null;
|
|
33
|
-
protected _pageLoading: boolean;
|
|
34
|
-
protected _navigatingToPage: boolean;
|
|
35
|
-
protected _allowNavigationWithoutReload: boolean;
|
|
36
|
-
protected _pageLoadMs?: number;
|
|
37
|
-
protected readonly _pageLoadStrategy?: string;
|
|
38
|
-
protected readonly _log: AppiumLogger;
|
|
39
|
-
protected readonly _bundleId?: string;
|
|
40
|
-
protected readonly _additionalBundleIds?: string[];
|
|
41
|
-
protected readonly _ignoredBundleIds?: string[];
|
|
42
|
-
protected readonly _platformVersion?: string;
|
|
43
|
-
protected readonly _isSafari: boolean;
|
|
44
|
-
protected readonly _includeSafari: boolean;
|
|
45
|
-
protected readonly _garbageCollectOnExecute: boolean;
|
|
46
|
-
protected readonly _host?: string;
|
|
47
|
-
protected readonly _port?: number;
|
|
48
|
-
protected readonly _socketPath?: string;
|
|
49
|
-
protected readonly _remoteDebugProxy?: any;
|
|
50
|
-
protected readonly _pageReadyTimeout: number;
|
|
51
|
-
protected readonly _logAllCommunication: boolean;
|
|
52
|
-
protected readonly _logAllCommunicationHexDump: boolean;
|
|
53
|
-
protected readonly _socketChunkSize?: number;
|
|
54
|
-
protected readonly _webInspectorMaxFrameLength?: number;
|
|
55
|
-
protected readonly _fullPageInitialization?: boolean;
|
|
56
|
-
|
|
57
23
|
// events
|
|
58
24
|
static readonly EVENT_PAGE_CHANGE: string;
|
|
59
25
|
static readonly EVENT_DISCONNECT: string;
|
|
@@ -90,7 +56,7 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
90
56
|
garbageCollect = miscellaneousMixins.garbageCollect;
|
|
91
57
|
isJavascriptExecutionBlocked = miscellaneousMixins.isJavascriptExecutionBlocked;
|
|
92
58
|
|
|
93
|
-
//
|
|
59
|
+
// callbacks
|
|
94
60
|
onPageChange = messageHandlerMixins.onPageChange;
|
|
95
61
|
onConnectedApplicationList = messageHandlerMixins.onConnectedApplicationList;
|
|
96
62
|
onAppConnect = messageHandlerMixins.onAppConnect;
|
|
@@ -100,6 +66,39 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
100
66
|
onCurrentState = messageHandlerMixins.onCurrentState;
|
|
101
67
|
frameDetached = navigationMixins.frameDetached;
|
|
102
68
|
|
|
69
|
+
protected _skippedApps: string[];
|
|
70
|
+
protected _clientEventListeners: StringRecord<EventListener[]>;
|
|
71
|
+
protected _appDict: AppDict;
|
|
72
|
+
protected _appIdKey?: AppIdKey;
|
|
73
|
+
protected _pageIdKey?: PageIdKey;
|
|
74
|
+
protected _connectedDrivers?: StringRecord[];
|
|
75
|
+
protected _currentState?: string;
|
|
76
|
+
protected _pageLoadDelay?: ReturnType<typeof util.cancellableDelay>;
|
|
77
|
+
protected _rpcClient: RpcClient | null;
|
|
78
|
+
protected _pageLoading: boolean;
|
|
79
|
+
protected _navigatingToPage: boolean;
|
|
80
|
+
protected _allowNavigationWithoutReload: boolean;
|
|
81
|
+
protected _pageLoadMs?: number;
|
|
82
|
+
protected readonly _pageLoadStrategy?: string;
|
|
83
|
+
protected readonly _log: AppiumLogger;
|
|
84
|
+
protected readonly _bundleId?: string;
|
|
85
|
+
protected readonly _additionalBundleIds?: string[];
|
|
86
|
+
protected readonly _ignoredBundleIds?: string[];
|
|
87
|
+
protected readonly _platformVersion?: string;
|
|
88
|
+
protected readonly _isSafari: boolean;
|
|
89
|
+
protected readonly _includeSafari: boolean;
|
|
90
|
+
protected readonly _garbageCollectOnExecute: boolean;
|
|
91
|
+
protected readonly _host?: string;
|
|
92
|
+
protected readonly _port?: number;
|
|
93
|
+
protected readonly _socketPath?: string;
|
|
94
|
+
protected readonly _remoteDebugProxy?: any;
|
|
95
|
+
protected readonly _pageReadyTimeout: number;
|
|
96
|
+
protected readonly _logAllCommunication: boolean;
|
|
97
|
+
protected readonly _logAllCommunicationHexDump: boolean;
|
|
98
|
+
protected readonly _socketChunkSize?: number;
|
|
99
|
+
protected readonly _webInspectorMaxFrameLength?: number;
|
|
100
|
+
protected readonly _fullPageInitialization?: boolean;
|
|
101
|
+
|
|
103
102
|
constructor(opts: RemoteDebuggerOptions = {}) {
|
|
104
103
|
super();
|
|
105
104
|
|
|
@@ -146,13 +145,12 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
146
145
|
this._remoteDebugProxy = remoteDebugProxy;
|
|
147
146
|
this._pageReadyTimeout = pageReadyTimeout;
|
|
148
147
|
|
|
149
|
-
this._logAllCommunication =
|
|
150
|
-
? !!logFullResponse
|
|
151
|
-
: !!logAllCommunication;
|
|
148
|
+
this._logAllCommunication =
|
|
149
|
+
logAllCommunication == null ? !!logFullResponse : !!logAllCommunication;
|
|
152
150
|
this._logAllCommunicationHexDump = logAllCommunicationHexDump;
|
|
153
151
|
this._socketChunkSize = socketChunkSize;
|
|
154
152
|
|
|
155
|
-
if (
|
|
153
|
+
if (Number.isInteger(webInspectorMaxFrameLength)) {
|
|
156
154
|
this._webInspectorMaxFrameLength = webInspectorMaxFrameLength;
|
|
157
155
|
}
|
|
158
156
|
|
|
@@ -168,6 +166,41 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
168
166
|
return this._log;
|
|
169
167
|
}
|
|
170
168
|
|
|
169
|
+
get isConnected(): boolean {
|
|
170
|
+
return !!this._rpcClient?.isConnected;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Only use this getter to read the appDict value.
|
|
174
|
+
// Any changes to it don't mutate the original property
|
|
175
|
+
// because the getter always returns the copy of it
|
|
176
|
+
get appDict(): AppDict {
|
|
177
|
+
return structuredClone(this._appDict);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get allowNavigationWithoutReload(): boolean {
|
|
181
|
+
return !!this._allowNavigationWithoutReload;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get currentState(): string | undefined {
|
|
185
|
+
return this._currentState;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
get connectedDrivers(): StringRecord[] | undefined {
|
|
189
|
+
return this._connectedDrivers;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
get pageLoadMs(): number {
|
|
193
|
+
return this._pageLoadMs ?? navigationMixins.DEFAULT_PAGE_READINESS_TIMEOUT_MS;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
set allowNavigationWithoutReload(allow: boolean) {
|
|
197
|
+
this._allowNavigationWithoutReload = allow;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
set pageLoadMs(value: number) {
|
|
201
|
+
this._pageLoadMs = value;
|
|
202
|
+
}
|
|
203
|
+
|
|
171
204
|
requireRpcClient(checkConnected: boolean = false): RpcClient {
|
|
172
205
|
if (!this._rpcClient) {
|
|
173
206
|
throw new Error(`rpcClient is undefined. Has 'initRpcClient' been called before?`);
|
|
@@ -228,44 +261,9 @@ export class RemoteDebugger extends EventEmitter {
|
|
|
228
261
|
pageLoadTimeoutMs: this._pageLoadMs,
|
|
229
262
|
});
|
|
230
263
|
}
|
|
231
|
-
|
|
232
|
-
get isConnected(): boolean {
|
|
233
|
-
return !!this._rpcClient?.isConnected;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Only use this getter to read the appDict value.
|
|
237
|
-
// Any changes to it don't mutate the original property
|
|
238
|
-
// because the getter always returns the copy of it
|
|
239
|
-
get appDict(): AppDict {
|
|
240
|
-
return _.cloneDeep(this._appDict);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
set allowNavigationWithoutReload(allow: boolean) {
|
|
244
|
-
this._allowNavigationWithoutReload = allow;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
get allowNavigationWithoutReload(): boolean {
|
|
248
|
-
return !!this._allowNavigationWithoutReload;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
get currentState(): string | undefined {
|
|
252
|
-
return this._currentState;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
get connectedDrivers(): StringRecord[] | undefined {
|
|
256
|
-
return this._connectedDrivers;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
get pageLoadMs(): number {
|
|
260
|
-
return this._pageLoadMs ?? navigationMixins.DEFAULT_PAGE_READINESS_TIMEOUT_MS;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
set pageLoadMs(value: number) {
|
|
264
|
-
this._pageLoadMs = value;
|
|
265
|
-
}
|
|
266
264
|
}
|
|
267
265
|
|
|
268
|
-
for (const [name, event] of
|
|
266
|
+
for (const [name, event] of Object.entries(eventMixins.events)) {
|
|
269
267
|
RemoteDebugger[name] = event;
|
|
270
268
|
}
|
|
271
269
|
|