appium-remote-debugger 15.3.3 → 15.3.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/atoms.d.ts.map +1 -1
- package/build/lib/atoms.js +2 -2
- package/build/lib/atoms.js.map +1 -1
- package/build/lib/index.d.ts +2 -1
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +0 -1
- package/build/lib/index.js.map +1 -1
- package/build/lib/logger.js.map +1 -1
- package/build/lib/mixins/connect.d.ts.map +1 -1
- package/build/lib/mixins/connect.js +11 -8
- package/build/lib/mixins/connect.js.map +1 -1
- package/build/lib/mixins/cookies.d.ts.map +1 -1
- package/build/lib/mixins/cookies.js.map +1 -1
- package/build/lib/mixins/events.d.ts.map +1 -1
- package/build/lib/mixins/events.js +1 -1
- package/build/lib/mixins/events.js.map +1 -1
- package/build/lib/mixins/execute.d.ts.map +1 -1
- package/build/lib/mixins/execute.js +2 -2
- 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.map +1 -1
- package/build/lib/mixins/misc.d.ts.map +1 -1
- package/build/lib/mixins/misc.js +1 -1
- 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 +2 -3
- package/build/lib/mixins/navigate.js.map +1 -1
- package/build/lib/mixins/property-accessors.d.ts +20 -20
- package/build/lib/mixins/property-accessors.d.ts.map +1 -1
- package/build/lib/mixins/property-accessors.js.map +1 -1
- package/build/lib/mixins/screenshot.d.ts.map +1 -1
- package/build/lib/mixins/screenshot.js +5 -1
- package/build/lib/mixins/screenshot.js.map +1 -1
- package/build/lib/protocol/index.d.ts.map +1 -1
- package/build/lib/protocol/index.js +2 -3
- package/build/lib/protocol/index.js.map +1 -1
- package/build/lib/remote-debugger-real-device.d.ts.map +1 -1
- package/build/lib/remote-debugger-real-device.js.map +1 -1
- package/build/lib/remote-debugger.d.ts.map +1 -1
- package/build/lib/remote-debugger.js +3 -1
- package/build/lib/remote-debugger.js.map +1 -1
- package/build/lib/rpc/index.d.ts.map +1 -1
- package/build/lib/rpc/index.js.map +1 -1
- package/build/lib/rpc/remote-messages.d.ts.map +1 -1
- package/build/lib/rpc/remote-messages.js +16 -15
- package/build/lib/rpc/remote-messages.js.map +1 -1
- package/build/lib/rpc/rpc-client-real-device.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client-real-device.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 -4
- package/build/lib/rpc/rpc-client-simulator.js.map +1 -1
- package/build/lib/rpc/rpc-client.d.ts.map +1 -1
- package/build/lib/rpc/rpc-client.js +6 -6
- package/build/lib/rpc/rpc-client.js.map +1 -1
- package/build/lib/rpc/rpc-message-handler.d.ts.map +1 -1
- package/build/lib/rpc/rpc-message-handler.js +3 -4
- package/build/lib/rpc/rpc-message-handler.js.map +1 -1
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +6 -5
- package/build/lib/utils.js.map +1 -1
- package/lib/atoms.ts +8 -6
- package/lib/index.ts +18 -11
- package/lib/logger.ts +1 -1
- package/lib/mixins/connect.ts +63 -47
- package/lib/mixins/cookies.ts +5 -11
- package/lib/mixins/events.ts +8 -19
- package/lib/mixins/execute.ts +43 -35
- package/lib/mixins/message-handlers.ts +21 -20
- package/lib/mixins/misc.ts +12 -15
- package/lib/mixins/navigate.ts +68 -61
- package/lib/mixins/property-accessors.ts +48 -23
- package/lib/mixins/screenshot.ts +10 -11
- package/lib/protocol/index.ts +11 -9
- package/lib/remote-debugger-real-device.ts +5 -5
- package/lib/remote-debugger.ts +22 -28
- package/lib/rpc/index.ts +2 -2
- package/lib/rpc/remote-messages.ts +48 -48
- package/lib/rpc/rpc-client-real-device.ts +4 -4
- package/lib/rpc/rpc-client-simulator.ts +23 -20
- package/lib/rpc/rpc-client.ts +161 -108
- package/lib/rpc/rpc-message-handler.ts +34 -24
- package/lib/types.ts +3 -3
- package/lib/utils.ts +24 -17
- package/package.json +3 -1
package/lib/mixins/execute.ts
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {errors} from '@appium/base-driver';
|
|
2
2
|
import {
|
|
3
3
|
checkParams,
|
|
4
4
|
simpleStringify,
|
|
5
5
|
convertJavascriptEvaluationResult,
|
|
6
6
|
RESPONSE_LOG_LENGTH,
|
|
7
7
|
} from '../utils';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import {getScriptForAtom} from '../atoms';
|
|
9
|
+
import {util, timing} from '@appium/support';
|
|
10
|
+
import {retryInterval} from 'asyncbox';
|
|
11
11
|
import _ from 'lodash';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
getGarbageCollectOnExecute,
|
|
16
|
-
} from './property-accessors';
|
|
17
|
-
import type { RemoteDebugger } from '../remote-debugger';
|
|
18
|
-
import type { AppIdKey, PageIdKey } from '../types';
|
|
12
|
+
import {getAppIdKey, getPageIdKey, getGarbageCollectOnExecute} from './property-accessors';
|
|
13
|
+
import type {RemoteDebugger} from '../remote-debugger';
|
|
14
|
+
import type {AppIdKey, PageIdKey} from '../types';
|
|
19
15
|
|
|
20
16
|
/* How many milliseconds to wait for webkit to return a response before timing out */
|
|
21
17
|
const RPC_RESPONSE_TIMEOUT_MS = 5000;
|
|
@@ -33,14 +29,16 @@ export async function executeAtom(
|
|
|
33
29
|
this: RemoteDebugger,
|
|
34
30
|
atom: string,
|
|
35
31
|
args: any[] = [],
|
|
36
|
-
frames: string[] = []
|
|
32
|
+
frames: string[] = [],
|
|
37
33
|
): Promise<any> {
|
|
38
34
|
this.log.debug(`Executing atom '${atom}' with 'args=${JSON.stringify(args)}; frames=${frames}'`);
|
|
39
35
|
const script = await getScriptForAtom(atom, args, frames);
|
|
40
36
|
const value = await this.execute(script);
|
|
41
|
-
this.log.debug(
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
this.log.debug(
|
|
38
|
+
`Received result for atom '${atom}' execution: ${_.truncate(simpleStringify(value), {
|
|
39
|
+
length: RESPONSE_LOG_LENGTH,
|
|
40
|
+
})}`,
|
|
41
|
+
);
|
|
44
42
|
return value;
|
|
45
43
|
}
|
|
46
44
|
|
|
@@ -59,20 +57,26 @@ export async function executeAtomAsync(
|
|
|
59
57
|
this: RemoteDebugger,
|
|
60
58
|
atom: string,
|
|
61
59
|
args: any[] = [],
|
|
62
|
-
frames: string[] = []
|
|
60
|
+
frames: string[] = [],
|
|
63
61
|
): Promise<any> {
|
|
64
62
|
// helper to send directly to the web inspector
|
|
65
|
-
const evaluate = async (method: string, opts: any) =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
const evaluate = async (method: string, opts: any) =>
|
|
64
|
+
await this.requireRpcClient(true).send(
|
|
65
|
+
method,
|
|
66
|
+
Object.assign(
|
|
67
|
+
{
|
|
68
|
+
appIdKey: getAppIdKey(this),
|
|
69
|
+
pageIdKey: getPageIdKey(this),
|
|
70
|
+
returnByValue: false,
|
|
71
|
+
},
|
|
72
|
+
opts,
|
|
73
|
+
),
|
|
74
|
+
);
|
|
70
75
|
|
|
71
76
|
// first create a Promise on the page, saving the resolve/reject functions
|
|
72
77
|
// as properties
|
|
73
78
|
const promiseName = `appiumAsyncExecutePromise${util.uuidV4().replace(/-/g, '')}`;
|
|
74
|
-
const script =
|
|
75
|
-
`var res, rej;
|
|
79
|
+
const script = `var res, rej;
|
|
76
80
|
window.${promiseName} = new Promise(function (resolve, reject) {
|
|
77
81
|
res = resolve;
|
|
78
82
|
rej = reject;
|
|
@@ -86,8 +90,7 @@ export async function executeAtomAsync(
|
|
|
86
90
|
const promiseObjectId = obj.result.objectId;
|
|
87
91
|
|
|
88
92
|
// execute the atom, calling back to the resolve function
|
|
89
|
-
const asyncCallBack =
|
|
90
|
-
`function (res) {
|
|
93
|
+
const asyncCallBack = `function (res) {
|
|
91
94
|
window.${promiseName}.resolve(res);
|
|
92
95
|
window.${promiseName}Value = res;
|
|
93
96
|
}`;
|
|
@@ -109,7 +112,7 @@ export async function executeAtomAsync(
|
|
|
109
112
|
}
|
|
110
113
|
// awaitPromise is not always available, so simulate it with poll
|
|
111
114
|
const retryWait = 100;
|
|
112
|
-
const timeout =
|
|
115
|
+
const timeout = args.length >= 3 ? args[2] : RPC_RESPONSE_TIMEOUT_MS;
|
|
113
116
|
// if the timeout math turns up 0 retries, make sure it happens once
|
|
114
117
|
const retries = parseInt(`${timeout / retryWait}`, 10) || 1;
|
|
115
118
|
const timer = new timing.Timer().start();
|
|
@@ -130,14 +133,18 @@ export async function executeAtomAsync(
|
|
|
130
133
|
});
|
|
131
134
|
}
|
|
132
135
|
// throw a TimeoutError, or else it needs to be caught and re-thrown
|
|
133
|
-
throw new errors.TimeoutError(
|
|
134
|
-
|
|
136
|
+
throw new errors.TimeoutError(
|
|
137
|
+
`Timed out waiting for asynchronous script ` +
|
|
138
|
+
`result after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms'));`,
|
|
139
|
+
);
|
|
135
140
|
});
|
|
136
141
|
} finally {
|
|
137
142
|
try {
|
|
138
143
|
// try to get rid of the promise
|
|
139
144
|
await this.executeAtom(
|
|
140
|
-
'execute_script',
|
|
145
|
+
'execute_script',
|
|
146
|
+
[`delete window.${promiseName};`, [null, null], subcommandTimeout],
|
|
147
|
+
frames,
|
|
141
148
|
);
|
|
142
149
|
} catch {}
|
|
143
150
|
}
|
|
@@ -154,7 +161,11 @@ export async function executeAtomAsync(
|
|
|
154
161
|
* converted to a usable format.
|
|
155
162
|
*/
|
|
156
163
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
157
|
-
export async function execute(
|
|
164
|
+
export async function execute(
|
|
165
|
+
this: RemoteDebugger,
|
|
166
|
+
command: string,
|
|
167
|
+
override?: boolean,
|
|
168
|
+
): Promise<any> {
|
|
158
169
|
const {appIdKey, pageIdKey} = checkParams({
|
|
159
170
|
appIdKey: getAppIdKey(this),
|
|
160
171
|
pageIdKey: getPageIdKey(this),
|
|
@@ -165,10 +176,7 @@ export async function execute(this: RemoteDebugger, command: string, override?:
|
|
|
165
176
|
}
|
|
166
177
|
|
|
167
178
|
const rpcClient = this.requireRpcClient(true);
|
|
168
|
-
await rpcClient.waitForPage(
|
|
169
|
-
appIdKey as AppIdKey,
|
|
170
|
-
pageIdKey as PageIdKey
|
|
171
|
-
);
|
|
179
|
+
await rpcClient.waitForPage(appIdKey as AppIdKey, pageIdKey as PageIdKey);
|
|
172
180
|
this.log.debug(`Sending javascript command: '${_.truncate(command, {length: 50})}'`);
|
|
173
181
|
const res = await rpcClient.send('Runtime.evaluate', {
|
|
174
182
|
expression: command,
|
|
@@ -193,7 +201,7 @@ export async function callFunction(
|
|
|
193
201
|
this: RemoteDebugger,
|
|
194
202
|
objectId: string,
|
|
195
203
|
fn: string,
|
|
196
|
-
args?: any[]
|
|
204
|
+
args?: any[],
|
|
197
205
|
): Promise<any> {
|
|
198
206
|
const {appIdKey, pageIdKey} = checkParams({
|
|
199
207
|
appIdKey: getAppIdKey(this),
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
pageArrayFromDict,
|
|
4
|
-
appInfoFromDict,
|
|
5
|
-
} from '../utils';
|
|
1
|
+
import {events} from './events';
|
|
2
|
+
import {pageArrayFromDict, appInfoFromDict} from '../utils';
|
|
6
3
|
import _ from 'lodash';
|
|
7
4
|
import {
|
|
8
5
|
setAppIdKey,
|
|
@@ -14,9 +11,9 @@ import {
|
|
|
14
11
|
setConnectedDrivers,
|
|
15
12
|
getSkippedApps,
|
|
16
13
|
} from './property-accessors';
|
|
17
|
-
import type {
|
|
18
|
-
import type {
|
|
19
|
-
import type {
|
|
14
|
+
import type {RemoteDebugger} from '../remote-debugger';
|
|
15
|
+
import type {StringRecord} from '@appium/types';
|
|
16
|
+
import type {AppDict} from '../types';
|
|
20
17
|
|
|
21
18
|
/*
|
|
22
19
|
* Generic callbacks used throughout the lifecycle of the Remote Debugger.
|
|
@@ -36,7 +33,7 @@ export async function onPageChange(
|
|
|
36
33
|
this: RemoteDebugger,
|
|
37
34
|
err: Error | null | undefined,
|
|
38
35
|
appIdKey: string,
|
|
39
|
-
pageDict: StringRecord
|
|
36
|
+
pageDict: StringRecord,
|
|
40
37
|
): Promise<void> {
|
|
41
38
|
if (_.isEmpty(pageDict)) {
|
|
42
39
|
return;
|
|
@@ -50,14 +47,14 @@ export async function onPageChange(
|
|
|
50
47
|
if (previousPages && _.isEqual(previousPages, currentPages)) {
|
|
51
48
|
this.log.debug(
|
|
52
49
|
`Received page change notice for app '${appIdKey}' ` +
|
|
53
|
-
|
|
50
|
+
`but the listing has not changed. Ignoring.`,
|
|
54
51
|
);
|
|
55
52
|
return;
|
|
56
53
|
}
|
|
57
54
|
// keep track of the page dictionary
|
|
58
55
|
getAppDict(this)[appIdKey].pageArray = currentPages;
|
|
59
56
|
this.log.debug(
|
|
60
|
-
`Pages changed for ${appIdKey}: ${JSON.stringify(previousPages)} -> ${JSON.stringify(currentPages)}
|
|
57
|
+
`Pages changed for ${appIdKey}: ${JSON.stringify(previousPages)} -> ${JSON.stringify(currentPages)}`,
|
|
61
58
|
);
|
|
62
59
|
}
|
|
63
60
|
|
|
@@ -83,7 +80,7 @@ export async function onPageChange(
|
|
|
83
80
|
export async function onAppConnect(
|
|
84
81
|
this: RemoteDebugger,
|
|
85
82
|
err: Error | null | undefined,
|
|
86
|
-
dict: StringRecord
|
|
83
|
+
dict: StringRecord,
|
|
87
84
|
): Promise<void> {
|
|
88
85
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
89
86
|
this.log.debug(`Notified that new application '${appIdKey}' has connected`);
|
|
@@ -103,7 +100,7 @@ export async function onAppConnect(
|
|
|
103
100
|
export function onAppDisconnect(
|
|
104
101
|
this: RemoteDebugger,
|
|
105
102
|
err: Error | null | undefined,
|
|
106
|
-
dict: StringRecord
|
|
103
|
+
dict: StringRecord,
|
|
107
104
|
): void {
|
|
108
105
|
const appIdKey = dict.WIRApplicationIdentifierKey;
|
|
109
106
|
this.log.debug(`Application '${appIdKey}' disconnected. Removing from app dictionary.`);
|
|
@@ -137,7 +134,7 @@ export function onAppDisconnect(
|
|
|
137
134
|
export async function onAppUpdate(
|
|
138
135
|
this: RemoteDebugger,
|
|
139
136
|
err: Error | null | undefined,
|
|
140
|
-
dict: StringRecord
|
|
137
|
+
dict: StringRecord,
|
|
141
138
|
): Promise<void> {
|
|
142
139
|
this.log.debug(`Notified that an application has been updated`);
|
|
143
140
|
updateAppsWithDict.bind(this)(dict);
|
|
@@ -154,7 +151,7 @@ export async function onAppUpdate(
|
|
|
154
151
|
export function onConnectedDriverList(
|
|
155
152
|
this: RemoteDebugger,
|
|
156
153
|
err: Error | null | undefined,
|
|
157
|
-
drivers: StringRecord
|
|
154
|
+
drivers: StringRecord,
|
|
158
155
|
): void {
|
|
159
156
|
setConnectedDrivers(this, drivers.WIRDriverDictionaryKey);
|
|
160
157
|
this.log.debug(`Received connected driver list: ${JSON.stringify(this.connectedDrivers)}`);
|
|
@@ -173,12 +170,14 @@ export function onConnectedDriverList(
|
|
|
173
170
|
export function onCurrentState(
|
|
174
171
|
this: RemoteDebugger,
|
|
175
172
|
err: Error | null | undefined,
|
|
176
|
-
state: StringRecord
|
|
173
|
+
state: StringRecord,
|
|
177
174
|
): void {
|
|
178
175
|
setCurrentState(this, state.WIRAutomationAvailabilityKey);
|
|
179
176
|
// This state changes when 'Remote Automation' in 'Settings app' > 'Safari' > 'Advanced' > 'Remote Automation' changes
|
|
180
177
|
// WIRAutomationAvailabilityAvailable or WIRAutomationAvailabilityNotAvailable
|
|
181
|
-
this.log.debug(
|
|
178
|
+
this.log.debug(
|
|
179
|
+
`Received connected automation availability state: ${JSON.stringify(this.currentState)}`,
|
|
180
|
+
);
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
/**
|
|
@@ -192,7 +191,7 @@ export function onCurrentState(
|
|
|
192
191
|
export async function onConnectedApplicationList(
|
|
193
192
|
this: RemoteDebugger,
|
|
194
193
|
err: Error | null | undefined,
|
|
195
|
-
apps: StringRecord
|
|
194
|
+
apps: StringRecord,
|
|
196
195
|
): Promise<void> {
|
|
197
196
|
this.log.debug(`Received connected applications list: ${_.keys(apps).join(', ')}`);
|
|
198
197
|
|
|
@@ -233,8 +232,10 @@ export function getDebuggerAppKey(this: RemoteDebugger, bundleId: string): strin
|
|
|
233
232
|
let proxyAppId: string | undefined;
|
|
234
233
|
for (const [key, data] of _.toPairs(getAppDict(this))) {
|
|
235
234
|
if (data.isProxy && data.hostId === appId) {
|
|
236
|
-
this.log.debug(
|
|
237
|
-
|
|
235
|
+
this.log.debug(
|
|
236
|
+
`Found separate bundleId '${data.bundleId}' ` +
|
|
237
|
+
`acting as proxy for '${bundleId}', with app id '${key}'`,
|
|
238
|
+
);
|
|
238
239
|
// set the app id... the last one will be used, so just keep re-assigning
|
|
239
240
|
proxyAppId = key;
|
|
240
241
|
}
|
package/lib/mixins/misc.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import B, {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
getPageIdKey,
|
|
6
|
-
} from './property-accessors';
|
|
7
|
-
import type { RemoteDebugger } from '../remote-debugger';
|
|
1
|
+
import {checkParams} from '../utils';
|
|
2
|
+
import B, {TimeoutError as BTimeoutError} from 'bluebird';
|
|
3
|
+
import {getAppIdKey, getPageIdKey} from './property-accessors';
|
|
4
|
+
import type {RemoteDebugger} from '../remote-debugger';
|
|
8
5
|
|
|
9
6
|
const SAFARI_BUNDLE_ID = 'com.apple.mobilesafari';
|
|
10
7
|
const GARBAGE_COLLECT_TIMEOUT_MS = 5000;
|
|
@@ -15,7 +12,7 @@ const GARBAGE_COLLECT_TIMEOUT_MS = 5000;
|
|
|
15
12
|
*/
|
|
16
13
|
export async function launchSafari(this: RemoteDebugger): Promise<void> {
|
|
17
14
|
await this.requireRpcClient().send('launchApplication', {
|
|
18
|
-
bundleId: SAFARI_BUNDLE_ID
|
|
15
|
+
bundleId: SAFARI_BUNDLE_ID,
|
|
19
16
|
});
|
|
20
17
|
}
|
|
21
18
|
|
|
@@ -28,7 +25,7 @@ export async function launchSafari(this: RemoteDebugger): Promise<void> {
|
|
|
28
25
|
*/
|
|
29
26
|
export async function startTimeline(
|
|
30
27
|
this: RemoteDebugger,
|
|
31
|
-
fn: import('../types').EventListener
|
|
28
|
+
fn: import('../types').EventListener,
|
|
32
29
|
): Promise<any> {
|
|
33
30
|
this.log.debug('Starting to record the timeline');
|
|
34
31
|
this.requireRpcClient().on('Timeline.eventRecorded', fn);
|
|
@@ -77,7 +74,7 @@ export async function overrideUserAgent(this: RemoteDebugger, value: string): Pr
|
|
|
77
74
|
*/
|
|
78
75
|
export async function isJavascriptExecutionBlocked(
|
|
79
76
|
this: RemoteDebugger,
|
|
80
|
-
timeoutMs: number = 1000
|
|
77
|
+
timeoutMs: number = 1000,
|
|
81
78
|
): Promise<boolean> {
|
|
82
79
|
try {
|
|
83
80
|
await B.resolve(
|
|
@@ -86,7 +83,7 @@ export async function isJavascriptExecutionBlocked(
|
|
|
86
83
|
returnByValue: true,
|
|
87
84
|
appIdKey: getAppIdKey(this),
|
|
88
85
|
pageIdKey: getPageIdKey(this),
|
|
89
|
-
})
|
|
86
|
+
}),
|
|
90
87
|
).timeout(timeoutMs);
|
|
91
88
|
return false;
|
|
92
89
|
} catch {
|
|
@@ -104,7 +101,7 @@ export async function isJavascriptExecutionBlocked(
|
|
|
104
101
|
*/
|
|
105
102
|
export async function garbageCollect(
|
|
106
103
|
this: RemoteDebugger,
|
|
107
|
-
timeoutMs: number = GARBAGE_COLLECT_TIMEOUT_MS
|
|
104
|
+
timeoutMs: number = GARBAGE_COLLECT_TIMEOUT_MS,
|
|
108
105
|
): Promise<void> {
|
|
109
106
|
this.log.debug(`Garbage collecting with ${timeoutMs}ms timeout`);
|
|
110
107
|
|
|
@@ -119,11 +116,11 @@ export async function garbageCollect(
|
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
try {
|
|
122
|
-
await B.resolve(
|
|
123
|
-
'Heap.gc', {
|
|
119
|
+
await B.resolve(
|
|
120
|
+
this.requireRpcClient().send('Heap.gc', {
|
|
124
121
|
appIdKey: getAppIdKey(this),
|
|
125
122
|
pageIdKey: getPageIdKey(this),
|
|
126
|
-
})
|
|
123
|
+
}),
|
|
127
124
|
).timeout(timeoutMs);
|
|
128
125
|
this.log.debug(`Garbage collection successful`);
|
|
129
126
|
} catch (e: any) {
|
package/lib/mixins/navigate.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {checkParams} from '../utils';
|
|
2
|
+
import {events} from './events';
|
|
3
|
+
import {timing, util} from '@appium/support';
|
|
4
4
|
import _ from 'lodash';
|
|
5
|
-
import B, {
|
|
5
|
+
import B, {TimeoutError as BTimeoutError} from 'bluebird';
|
|
6
6
|
import {
|
|
7
7
|
getAppIdKey,
|
|
8
8
|
setPageLoading,
|
|
@@ -13,8 +13,8 @@ import {
|
|
|
13
13
|
getPageIdKey,
|
|
14
14
|
setNavigatingToPage,
|
|
15
15
|
} from './property-accessors';
|
|
16
|
-
import type {
|
|
17
|
-
import type {
|
|
16
|
+
import type {RemoteDebugger} from '../remote-debugger';
|
|
17
|
+
import type {AppIdKey, PageIdKey} from '../types';
|
|
18
18
|
|
|
19
19
|
export const DEFAULT_PAGE_READINESS_TIMEOUT_MS = 20 * 1000;
|
|
20
20
|
const PAGE_READINESS_CHECK_INTERVAL_MS = 50;
|
|
@@ -25,7 +25,7 @@ const PAGE_READINESS_CHECK_INTERVAL_MS = 50;
|
|
|
25
25
|
const PAGE_LOAD_STRATEGY = Object.freeze({
|
|
26
26
|
EAGER: 'eager',
|
|
27
27
|
NONE: 'none',
|
|
28
|
-
NORMAL: 'normal'
|
|
28
|
+
NORMAL: 'normal',
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -78,7 +78,10 @@ export function isPageLoadingCompleted(this: RemoteDebugger, readyState: string)
|
|
|
78
78
|
* @param startPageLoadTimer - Optional timer instance to use for tracking elapsed time.
|
|
79
79
|
* If not provided, a new timer will be created and started.
|
|
80
80
|
*/
|
|
81
|
-
export async function waitForDom(
|
|
81
|
+
export async function waitForDom(
|
|
82
|
+
this: RemoteDebugger,
|
|
83
|
+
startPageLoadTimer?: timing.Timer,
|
|
84
|
+
): Promise<void> {
|
|
82
85
|
const readinessTimeoutMs = this.pageLoadMs;
|
|
83
86
|
this.log.debug(`Waiting up to ${readinessTimeoutMs}ms for the page to be ready`);
|
|
84
87
|
const timer = startPageLoadTimer ?? new timing.Timer().start();
|
|
@@ -86,49 +89,53 @@ export async function waitForDom(this: RemoteDebugger, startPageLoadTimer?: timi
|
|
|
86
89
|
let isPageLoading = true;
|
|
87
90
|
setPageLoading(this, true);
|
|
88
91
|
setPageLoadDelay(this, util.cancellableDelay(readinessTimeoutMs));
|
|
89
|
-
const pageReadinessPromise = B.resolve(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
this
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
92
|
+
const pageReadinessPromise = B.resolve(
|
|
93
|
+
(async () => {
|
|
94
|
+
let retry = 0;
|
|
95
|
+
while (isPageLoading) {
|
|
96
|
+
// if we are ready, or we've spend too much time on this
|
|
97
|
+
const elapsedMs = timer.getDuration().asMilliSeconds;
|
|
98
|
+
// exponential retry
|
|
99
|
+
const intervalMs = Math.min(
|
|
100
|
+
PAGE_READINESS_CHECK_INTERVAL_MS * Math.pow(2, retry),
|
|
101
|
+
readinessTimeoutMs - elapsedMs,
|
|
102
|
+
);
|
|
103
|
+
await B.delay(intervalMs);
|
|
104
|
+
// we can get this called in the middle of trying to find a new app
|
|
105
|
+
if (!getAppIdKey(this)) {
|
|
106
|
+
this.log.debug('Not connected to an application. Ignoring page readiess check');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!isPageLoading) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
108
112
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
const maxWaitMs = (readinessTimeoutMs - elapsedMs) * 0.95;
|
|
114
|
+
if (await this.checkPageIsReady(maxWaitMs)) {
|
|
115
|
+
if (isPageLoading) {
|
|
116
|
+
this.log.debug(`Page is ready in ${elapsedMs}ms`);
|
|
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
|
+
);
|
|
113
125
|
isPageLoading = false;
|
|
126
|
+
return;
|
|
114
127
|
}
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
if (elapsedMs > readinessTimeoutMs) {
|
|
118
|
-
this.log.info(
|
|
119
|
-
`Timed out after ${readinessTimeoutMs}ms of waiting for the page readiness. Continuing anyway`
|
|
120
|
-
);
|
|
121
|
-
isPageLoading = false;
|
|
122
|
-
return;
|
|
128
|
+
retry++;
|
|
123
129
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
})(),
|
|
131
|
+
);
|
|
132
|
+
const cancellationPromise = B.resolve(
|
|
133
|
+
(async () => {
|
|
134
|
+
try {
|
|
135
|
+
await getPageLoadDelay(this);
|
|
136
|
+
} catch {}
|
|
137
|
+
})(),
|
|
138
|
+
);
|
|
132
139
|
|
|
133
140
|
try {
|
|
134
141
|
await B.any([cancellationPromise, pageReadinessPromise]);
|
|
@@ -152,13 +159,12 @@ export async function checkPageIsReady(this: RemoteDebugger, timeoutMs?: number)
|
|
|
152
159
|
const readyCmd = 'document.readyState;';
|
|
153
160
|
const actualTimeoutMs = timeoutMs ?? getPageReadyTimeout(this);
|
|
154
161
|
try {
|
|
155
|
-
const readyState = await B.resolve(this.execute(readyCmd))
|
|
156
|
-
.timeout(actualTimeoutMs);
|
|
162
|
+
const readyState = await B.resolve(this.execute(readyCmd)).timeout(actualTimeoutMs);
|
|
157
163
|
this.log.debug(
|
|
158
164
|
JSON.stringify({
|
|
159
165
|
readyState,
|
|
160
166
|
pageLoadStrategy: getPageLoadStartegy(this) ?? PAGE_LOAD_STRATEGY.NORMAL,
|
|
161
|
-
})
|
|
167
|
+
}),
|
|
162
168
|
);
|
|
163
169
|
return this.isPageLoadingCompleted(readyState);
|
|
164
170
|
} catch (err: any) {
|
|
@@ -194,10 +200,7 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
194
200
|
|
|
195
201
|
this.log.debug(`Navigating to new URL: '${url}'`);
|
|
196
202
|
setNavigatingToPage(this, true);
|
|
197
|
-
await rpcClient.waitForPage(
|
|
198
|
-
appIdKey as AppIdKey,
|
|
199
|
-
pageIdKey as PageIdKey
|
|
200
|
-
);
|
|
203
|
+
await rpcClient.waitForPage(appIdKey as AppIdKey, pageIdKey as PageIdKey);
|
|
201
204
|
const readinessTimeoutMs = this.pageLoadMs;
|
|
202
205
|
let onPageLoaded: (() => void) | undefined;
|
|
203
206
|
let onPageLoadedTimeout: NodeJS.Timeout | undefined | null;
|
|
@@ -212,7 +215,7 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
212
215
|
isPageLoading = false;
|
|
213
216
|
this.log.info(
|
|
214
217
|
`Timed out after ${start.getDuration().asMilliSeconds.toFixed(0)}ms of waiting ` +
|
|
215
|
-
|
|
218
|
+
`for the ${url} page readiness. Continuing anyway`,
|
|
216
219
|
);
|
|
217
220
|
}
|
|
218
221
|
return resolve();
|
|
@@ -221,7 +224,9 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
221
224
|
onPageLoaded = () => {
|
|
222
225
|
if (isPageLoading) {
|
|
223
226
|
isPageLoading = false;
|
|
224
|
-
this.log.debug(
|
|
227
|
+
this.log.debug(
|
|
228
|
+
`The page ${url} is ready in ${start.getDuration().asMilliSeconds.toFixed(0)}ms`,
|
|
229
|
+
);
|
|
225
230
|
}
|
|
226
231
|
if (onPageLoadedTimeout) {
|
|
227
232
|
clearTimeout(onPageLoadedTimeout);
|
|
@@ -239,11 +244,13 @@ export async function navToUrl(this: RemoteDebugger, url: string): Promise<void>
|
|
|
239
244
|
pageIdKey,
|
|
240
245
|
});
|
|
241
246
|
});
|
|
242
|
-
const cancellationPromise = B.resolve(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
+
const cancellationPromise = B.resolve(
|
|
248
|
+
(async () => {
|
|
249
|
+
try {
|
|
250
|
+
await getPageLoadDelay(this);
|
|
251
|
+
} catch {}
|
|
252
|
+
})(),
|
|
253
|
+
);
|
|
247
254
|
|
|
248
255
|
try {
|
|
249
256
|
await B.any([cancellationPromise, pageReadinessPromise]);
|