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.
Files changed (70) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/lib/atoms.d.ts.map +1 -1
  3. package/build/lib/atoms.js +27 -28
  4. package/build/lib/atoms.js.map +1 -1
  5. package/build/lib/index.d.ts.map +1 -1
  6. package/build/lib/index.js +7 -0
  7. package/build/lib/index.js.map +1 -1
  8. package/build/lib/mixins/connect.d.ts.map +1 -1
  9. package/build/lib/mixins/connect.js +21 -25
  10. package/build/lib/mixins/connect.js.map +1 -1
  11. package/build/lib/mixins/execute.d.ts.map +1 -1
  12. package/build/lib/mixins/execute.js +2 -8
  13. package/build/lib/mixins/execute.js.map +1 -1
  14. package/build/lib/mixins/message-handlers.d.ts.map +1 -1
  15. package/build/lib/mixins/message-handlers.js +8 -12
  16. package/build/lib/mixins/message-handlers.js.map +1 -1
  17. package/build/lib/mixins/misc.d.ts.map +1 -1
  18. package/build/lib/mixins/misc.js +5 -39
  19. package/build/lib/mixins/misc.js.map +1 -1
  20. package/build/lib/mixins/navigate.d.ts.map +1 -1
  21. package/build/lib/mixins/navigate.js +20 -55
  22. package/build/lib/mixins/navigate.js.map +1 -1
  23. package/build/lib/mixins/property-accessors.d.ts +24 -0
  24. package/build/lib/mixins/property-accessors.d.ts.map +1 -1
  25. package/build/lib/mixins/property-accessors.js +24 -0
  26. package/build/lib/mixins/property-accessors.js.map +1 -1
  27. package/build/lib/remote-debugger.d.ts +38 -38
  28. package/build/lib/remote-debugger.d.ts.map +1 -1
  29. package/build/lib/remote-debugger.js +64 -69
  30. package/build/lib/remote-debugger.js.map +1 -1
  31. package/build/lib/rpc/remote-messages.d.ts.map +1 -1
  32. package/build/lib/rpc/remote-messages.js +7 -8
  33. package/build/lib/rpc/remote-messages.js.map +1 -1
  34. package/build/lib/rpc/rpc-client-real-device-shim.d.ts.map +1 -1
  35. package/build/lib/rpc/rpc-client-real-device-shim.js +3 -6
  36. package/build/lib/rpc/rpc-client-real-device-shim.js.map +1 -1
  37. package/build/lib/rpc/rpc-client-simulator.d.ts.map +1 -1
  38. package/build/lib/rpc/rpc-client-simulator.js +3 -5
  39. package/build/lib/rpc/rpc-client-simulator.js.map +1 -1
  40. package/build/lib/rpc/rpc-client.d.ts +27 -27
  41. package/build/lib/rpc/rpc-client.d.ts.map +1 -1
  42. package/build/lib/rpc/rpc-client.js +226 -224
  43. package/build/lib/rpc/rpc-client.js.map +1 -1
  44. package/build/lib/rpc/rpc-message-handler.js +7 -10
  45. package/build/lib/rpc/rpc-message-handler.js.map +1 -1
  46. package/build/lib/types.d.ts +19 -19
  47. package/build/lib/types.d.ts.map +1 -1
  48. package/build/lib/utils.d.ts +70 -4
  49. package/build/lib/utils.d.ts.map +1 -1
  50. package/build/lib/utils.js +171 -23
  51. package/build/lib/utils.js.map +1 -1
  52. package/lib/atoms.ts +31 -32
  53. package/lib/index.ts +7 -0
  54. package/lib/mixins/connect.ts +22 -23
  55. package/lib/mixins/execute.ts +3 -5
  56. package/lib/mixins/message-handlers.ts +9 -10
  57. package/lib/mixins/misc.ts +8 -7
  58. package/lib/mixins/navigate.ts +58 -63
  59. package/lib/mixins/property-accessors.ts +24 -0
  60. package/lib/remote-debugger.ts +74 -76
  61. package/lib/rpc/remote-messages.ts +10 -5
  62. package/lib/rpc/rpc-client-real-device-shim.ts +3 -3
  63. package/lib/rpc/rpc-client-simulator.ts +3 -5
  64. package/lib/rpc/rpc-client.ts +259 -247
  65. package/lib/rpc/rpc-message-handler.ts +7 -7
  66. package/lib/types.ts +24 -24
  67. package/lib/utils.ts +181 -23
  68. package/package.json +3 -7
  69. package/scripts/common.mjs +42 -37
  70. 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 (_.isEmpty(pageDict)) {
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 && _.isEqual(previousPages, currentPages)) {
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 (_.isEmpty(getAppDict(this))) {
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: ${_.keys(apps).join(', ')}`);
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 _.values(apps)) {
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
- _.defaults(getAppDict(this), newDict);
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 _.toPairs(getAppDict(this))) {
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 _.toPairs(getAppDict(this))) {
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}' ` +
@@ -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 B.resolve(
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
- ).timeout(timeoutMs);
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 B.resolve(
119
+ await withTimeout(
120
120
  this.requireRpcClient().send('Heap.gc', {
121
121
  appIdKey: getAppIdKey(this),
122
122
  pageIdKey: getPageIdKey(this),
123
123
  }),
124
- ).timeout(timeoutMs);
124
+ timeoutMs,
125
+ );
125
126
  this.log.debug(`Garbage collection successful`);
126
127
  } catch (e: any) {
127
- if (e instanceof BTimeoutError) {
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}`);
@@ -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 = _.toLower(getPageLoadStartegy(this));
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 = 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
- }
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
- 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
- );
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
- retry++;
116
+ return;
129
117
  }
130
- })(),
131
- );
132
- const cancellationPromise = B.resolve(
133
- (async () => {
134
- try {
135
- await getPageLoadDelay(this);
136
- } catch {}
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 B.any([cancellationPromise, pageReadinessPromise]);
135
+ await Promise.race([cancellationPromise, pageReadinessPromise]);
142
136
  } finally {
143
137
  isPageLoading = false;
144
138
  setPageLoading(this, false);
145
- setPageLoadDelay(this, B.resolve());
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 B.resolve(this.execute(readyCmd)).timeout(actualTimeoutMs);
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 BTimeoutError) {
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
- const pageReadinessPromise = new B<void>((resolve) => {
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 = B.resolve(
251
- (async () => {
252
- try {
253
- await getPageLoadDelay(this);
254
- } catch {}
255
- })(),
256
- );
247
+ const cancellationPromise = (async () => {
248
+ try {
249
+ await getPageLoadDelay(this);
250
+ } catch {}
251
+ })();
257
252
 
258
253
  try {
259
- await B.any([cancellationPromise, pageReadinessPromise]);
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, B.resolve());
265
- if (onPageLoadedTimeout && pageReadinessPromise.isFulfilled()) {
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'] {
@@ -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 _ from 'lodash';
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
- // Callbacks
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 = _.isNil(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 (_.isInteger(webInspectorMaxFrameLength)) {
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 _.toPairs(eventMixins.events)) {
266
+ for (const [name, event] of Object.entries(eventMixins.events)) {
269
267
  RemoteDebugger[name] = event;
270
268
  }
271
269