appium-remote-debugger 11.5.3 → 11.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/mixins/connect.d.ts +15 -41
  3. package/build/lib/mixins/connect.d.ts.map +1 -1
  4. package/build/lib/mixins/connect.js +80 -95
  5. package/build/lib/mixins/connect.js.map +1 -1
  6. package/build/lib/mixins/message-handlers.d.ts +4 -4
  7. package/build/lib/mixins/message-handlers.d.ts.map +1 -1
  8. package/build/lib/mixins/message-handlers.js +25 -67
  9. package/build/lib/mixins/message-handlers.js.map +1 -1
  10. package/build/lib/remote-debugger-real-device.d.ts.map +1 -1
  11. package/build/lib/remote-debugger-real-device.js +1 -5
  12. package/build/lib/remote-debugger-real-device.js.map +1 -1
  13. package/build/lib/remote-debugger.d.ts +0 -2
  14. package/build/lib/remote-debugger.d.ts.map +1 -1
  15. package/build/lib/remote-debugger.js +0 -2
  16. package/build/lib/remote-debugger.js.map +1 -1
  17. package/build/lib/rpc/remote-messages.d.ts +1 -1
  18. package/build/lib/rpc/remote-messages.d.ts.map +1 -1
  19. package/build/lib/rpc/remote-messages.js.map +1 -1
  20. package/build/lib/rpc/rpc-client-real-device.d.ts +10 -2
  21. package/build/lib/rpc/rpc-client-real-device.d.ts.map +1 -1
  22. package/build/lib/rpc/rpc-client-real-device.js +17 -0
  23. package/build/lib/rpc/rpc-client-real-device.js.map +1 -1
  24. package/build/lib/rpc/rpc-client-simulator.d.ts +33 -9
  25. package/build/lib/rpc/rpc-client-simulator.d.ts.map +1 -1
  26. package/build/lib/rpc/rpc-client-simulator.js +25 -1
  27. package/build/lib/rpc/rpc-client-simulator.js.map +1 -1
  28. package/build/lib/rpc/rpc-client.d.ts +114 -27
  29. package/build/lib/rpc/rpc-client.d.ts.map +1 -1
  30. package/build/lib/rpc/rpc-client.js +101 -27
  31. package/build/lib/rpc/rpc-client.js.map +1 -1
  32. package/build/lib/utils.d.ts +14 -7
  33. package/build/lib/utils.d.ts.map +1 -1
  34. package/build/lib/utils.js +15 -20
  35. package/build/lib/utils.js.map +1 -1
  36. package/build/tsconfig.tsbuildinfo +1 -1
  37. package/lib/mixins/connect.js +84 -105
  38. package/lib/mixins/message-handlers.js +30 -70
  39. package/lib/remote-debugger-real-device.js +1 -5
  40. package/lib/remote-debugger.js +1 -3
  41. package/lib/rpc/remote-messages.js +1 -2
  42. package/lib/rpc/rpc-client-real-device.js +18 -1
  43. package/lib/rpc/rpc-client-simulator.js +41 -2
  44. package/lib/rpc/rpc-client.js +149 -33
  45. package/lib/utils.js +15 -20
  46. package/package.json +1 -2
@@ -8,17 +8,18 @@ import { util, timing } from '@appium/support';
8
8
  import { EventEmitter } from 'node:events';
9
9
  import { ON_TARGET_PROVISIONED_EVENT } from './constants';
10
10
 
11
-
12
11
  const DATA_LOG_LENGTH = {length: 200};
13
-
14
- const WAIT_FOR_TARGET_TIMEOUT = 10000;
15
- const WAIT_FOR_TARGET_INTERVAL = 1000;
16
-
12
+ const WAIT_FOR_TARGET_TIMEOUT_MS = 10000;
13
+ const WAIT_FOR_TARGET_INTERVAL_MS = 1000;
17
14
  const MIN_PLATFORM_FOR_TARGET_BASED = '12.2';
18
-
19
15
  // `Target.exists` protocol method was removed from WebKit in 13.4
20
16
  const MIN_PLATFORM_NO_TARGET_EXISTS = '13.4';
21
17
 
18
+ /**
19
+ * @param {boolean} isSafari
20
+ * @param {string} platformVersion
21
+ * @returns {boolean}
22
+ */
22
23
  function isTargetBased (isSafari, platformVersion) {
23
24
  // On iOS 12.2 the messages get sent through the Target domain
24
25
  // On iOS 13.0+, WKWebView also needs to follow the Target domain,
@@ -39,13 +40,62 @@ export class RpcClient {
39
40
  /** @type {boolean} */
40
41
  connected;
41
42
 
42
- constructor (opts = {}) {
43
- this._targets = [];
44
- this._shouldCheckForTarget = !!opts.shouldCheckForTarget;
43
+ /** @type {boolean} */
44
+ isSafari;
45
+
46
+ /** @type {string} */
47
+ connId;
48
+
49
+ /** @type {string} */
50
+ senderId;
51
+
52
+ /** @type {number} */
53
+ msgId;
54
+
55
+ /** @type {string|undefined} */
56
+ udid;
57
+
58
+ /** @type {boolean|undefined} */
59
+ logAllCommunication;
60
+
61
+ /** @type {boolean|undefined} */
62
+ logAllCommunicationHexDump;
63
+
64
+ /** @type {number|undefined} */
65
+ socketChunkSize;
66
+
67
+ /** @type {number|undefined} */
68
+ webInspectorMaxFrameLength;
69
+
70
+ /** @type {boolean|undefined} */
71
+ fullPageInitialization;
72
+
73
+ /** @type {string|undefined} */
74
+ bundleId;
75
+
76
+ /** @type {string} */
77
+ platformVersion;
45
78
 
79
+ /** @type {string[]} */
80
+ _contexts;
81
+
82
+ /** @type {import('@appium/types').StringRecord} */
83
+ _targets;
84
+
85
+ /** @type {EventEmitter} */
86
+ _targetSubscriptions;
87
+
88
+ /** @type {boolean} */
89
+ _shouldCheckForTarget;
90
+
91
+ /**
92
+ *
93
+ * @param {RpcClientOptions} [opts={}]
94
+ */
95
+ constructor (opts = {}) {
46
96
  const {
47
97
  bundleId,
48
- platformVersion = {},
98
+ platformVersion = '',
49
99
  isSafari = true,
50
100
  logAllCommunication = false,
51
101
  logAllCommunicationHexDump = false,
@@ -79,21 +129,34 @@ export class RpcClient {
79
129
  this._targetSubscriptions = new EventEmitter();
80
130
 
81
131
  // start with a best guess for the protocol
82
- this.isTargetBased = isTargetBased(isSafari, this.platformVersion);
132
+ this._shouldCheckForTarget = !!opts.shouldCheckForTarget;
133
+ this.isTargetBased = platformVersion ? isTargetBased(isSafari, platformVersion) : true;
83
134
  }
84
135
 
136
+ /**
137
+ * @returns {string[]}
138
+ */
85
139
  get contexts () {
86
140
  return this._contexts;
87
141
  }
88
142
 
143
+ /**
144
+ * @returns {boolean}
145
+ */
89
146
  get needsTarget () {
90
147
  return this.shouldCheckForTarget && this.isTargetBased;
91
148
  }
92
149
 
150
+ /**
151
+ * @returns {import('@appium/types').StringRecord}
152
+ */
93
153
  get targets () {
94
154
  return this._targets;
95
155
  }
96
156
 
157
+ /**
158
+ * @returns {boolean}
159
+ */
97
160
  get shouldCheckForTarget () {
98
161
  return this._shouldCheckForTarget;
99
162
  }
@@ -102,36 +165,65 @@ export class RpcClient {
102
165
  this._shouldCheckForTarget = !!shouldCheckForTarget;
103
166
  }
104
167
 
168
+ /**
169
+ * @returns {boolean}
170
+ */
105
171
  get isConnected () {
106
172
  return this.connected;
107
173
  }
108
174
 
175
+ /**
176
+ * @param {boolean} connected
177
+ */
109
178
  set isConnected (connected) {
110
179
  this.connected = !!connected;
111
180
  }
112
181
 
182
+ /**
183
+ * @returns {EventEmitter}
184
+ */
113
185
  get targetSubscriptions() {
114
186
  return this._targetSubscriptions;
115
187
  }
116
188
 
189
+ /**
190
+ *
191
+ * @param {string} event
192
+ * @param {Function} listener
193
+ * @returns {this}
194
+ */
117
195
  on (event, listener) {
118
196
  // @ts-ignore messageHandler must be defined here
119
197
  this.messageHandler.on(event, listener);
120
198
  return this;
121
199
  }
122
200
 
201
+ /**
202
+ *
203
+ * @param {string} event
204
+ * @param {Function} listener
205
+ * @returns {this}
206
+ */
123
207
  once (event, listener) {
124
208
  // @ts-ignore messageHandler must be defined here
125
209
  this.messageHandler.once(event, listener);
126
210
  return this;
127
211
  }
128
212
 
213
+ /**
214
+ * @param {string} event
215
+ * @param {Function} listener
216
+ * @returns {this}
217
+ */
129
218
  off (event, listener) {
130
219
  // @ts-ignore messageHandler must be defined here
131
220
  this.messageHandler.off(event, listener);
132
221
  return this;
133
222
  }
134
223
 
224
+ /**
225
+ * @param {boolean} isTargetBased
226
+ */
135
227
  set isTargetBased (isTargetBased) {
136
228
  log.warn(`Setting communication protocol: using ${isTargetBased ? 'Target-based' : 'full Web Inspector protocol'} communication`);
137
229
  this._isTargetBased = isTargetBased;
@@ -156,8 +248,11 @@ export class RpcClient {
156
248
  }
157
249
  }
158
250
 
251
+ /**
252
+ * @returns {boolean}
253
+ */
159
254
  get isTargetBased () {
160
- return this._isTargetBased;
255
+ return !!this._isTargetBased;
161
256
  }
162
257
 
163
258
  /**
@@ -179,8 +274,8 @@ export class RpcClient {
179
274
  // otherwise waiting is necessary to see what the target is
180
275
  try {
181
276
  await waitForCondition(() => !_.isEmpty(this.getTarget(appIdKey, pageIdKey)), {
182
- waitMs: WAIT_FOR_TARGET_TIMEOUT,
183
- intervalMs: WAIT_FOR_TARGET_INTERVAL,
277
+ waitMs: WAIT_FOR_TARGET_TIMEOUT_MS,
278
+ intervalMs: WAIT_FOR_TARGET_INTERVAL_MS,
184
279
  error: 'No targets found, unable to communicate with device',
185
280
  });
186
281
  } catch (err) {
@@ -348,12 +443,21 @@ export class RpcClient {
348
443
  this.messageHandler?.removeAllListeners();
349
444
  }
350
445
 
446
+ /**
447
+ * @param {string} command
448
+ * @returns {Promise<void>}
449
+ */
351
450
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
352
451
  async sendMessage (command) { // eslint-disable-line require-await
353
452
  throw new Error(`Sub-classes need to implement a 'sendMessage' function`);
354
453
  }
355
454
 
356
- async receive (/* data */) { // eslint-disable-line require-await
455
+ /**
456
+ * @param {any} data
457
+ * @returns {Promise<void>}
458
+ */
459
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
460
+ async receive (data) { // eslint-disable-line require-await
357
461
  throw new Error(`Sub-classes need to implement a 'receive' function`);
358
462
  }
359
463
 
@@ -641,29 +745,24 @@ export class RpcClient {
641
745
 
642
746
  reject(new Error('New application has connected'));
643
747
  };
644
- // @ts-ignore messageHandler must be defined
645
- this.messageHandler.prependOnceListener('_rpc_applicationConnected:', onAppChange);
748
+ this.messageHandler?.prependOnceListener('_rpc_applicationConnected:', onAppChange);
646
749
 
647
750
  // do the actual connecting to the app
648
- return (async () => {
649
- let pageDict, connectedAppIdKey;
751
+ (async () => {
650
752
  try {
651
- ([connectedAppIdKey, pageDict] = await this.send('connectToApp', {
652
- appIdKey
653
- }));
753
+ const [connectedAppIdKey, pageDict] = await this.send('connectToApp', {appIdKey});
754
+ // sometimes the connect logic happens, but with an empty dictionary
755
+ // which leads to the remote debugger getting disconnected, and into a loop
756
+ if (_.isEmpty(pageDict)) {
757
+ reject(new Error('Empty page dictionary received'));
758
+ } else {
759
+ resolve([connectedAppIdKey, pageDict]);
760
+ }
654
761
  } catch (err) {
655
- log.warn(`Unable to connect to app: ${err.message}`);
762
+ log.warn(`Unable to connect to the app: ${err.message}`);
656
763
  reject(err);
657
- }
658
-
659
- // sometimes the connect logic happens, but with an empty dictionary
660
- // which leads to the remote debugger getting disconnected, and into a loop
661
- if (_.isEmpty(pageDict)) {
662
- let msg = 'Empty page dictionary received';
663
- log.debug(msg);
664
- reject(new Error(msg));
665
- } else {
666
- resolve([connectedAppIdKey, pageDict]);
764
+ } finally {
765
+ this.messageHandler?.off('_rpc_applicationConnected:', onAppChange);
667
766
  }
668
767
  })();
669
768
  });
@@ -681,6 +780,9 @@ export class RpcClient {
681
780
  this.contexts.push(context.id);
682
781
  }
683
782
 
783
+ /**
784
+ * @returns {void}
785
+ */
684
786
  onGarbageCollected () {
685
787
  // just want to log that this is happening, as it can affect opertion
686
788
  log.debug(`Web Inspector garbage collected`);
@@ -698,3 +800,17 @@ export class RpcClient {
698
800
  }
699
801
 
700
802
  export default RpcClient;
803
+
804
+ /**
805
+ * @typedef {Object} RpcClientOptions
806
+ * @property {string} [bundleId]
807
+ * @property {string} [platformVersion='']
808
+ * @property {boolean} [isSafari=true]
809
+ * @property {boolean} [logAllCommunication=false]
810
+ * @property {boolean} [logAllCommunicationHexDump=false]
811
+ * @property {number} [webInspectorMaxFrameLength]
812
+ * @property {number} [socketChunkSize]
813
+ * @property {boolean} [fullPageInitialization=false]
814
+ * @property {string} [udid]
815
+ * @property {boolean} [shouldCheckForTarget]
816
+ */
package/lib/utils.js CHANGED
@@ -38,10 +38,10 @@ export const RESPONSE_LOG_LENGTH = 100;
38
38
  * @property {boolean} isProxy
39
39
  * @property {string} name
40
40
  * @property {string} bundleId
41
- * @property {string} hostId
41
+ * @property {string} [hostId]
42
42
  * @property {boolean} isActive
43
43
  * @property {boolean|string} isAutomationEnabled
44
- * @property {any[]|undefined|DeferredPromise} [pageArray]
44
+ * @property {import('./mixins/connect').Page[]} [pageArray]
45
45
  */
46
46
 
47
47
  /**
@@ -83,28 +83,23 @@ export function appInfoFromDict (dict) {
83
83
  return [id, entry];
84
84
  }
85
85
 
86
- /*
86
+ /**
87
87
  * Take a dictionary from the remote debugger and makes a more manageable
88
88
  * dictionary of pages available.
89
+ *
90
+ * @param {import('@appium/types').StringRecord} pageDict
91
+ * @returns {import('./mixins/connect').Page[]}
89
92
  */
90
93
  export function pageArrayFromDict (pageDict) {
91
- if (pageDict.id) {
92
- // the page is already translated, so wrap in an array and pass back
93
- return [pageDict];
94
- }
95
- let newPageArray = [];
96
- for (const dict of _.values(pageDict)) {
94
+ return _.values(pageDict)
97
95
  // count only WIRTypeWeb pages and ignore all others (WIRTypeJavaScript etc)
98
- if (_.isUndefined(dict.WIRTypeKey) || ACCEPTED_PAGE_TYPES.includes(dict.WIRTypeKey)) {
99
- newPageArray.push({
100
- id: dict.WIRPageIdentifierKey,
101
- title: dict.WIRTitleKey,
102
- url: dict.WIRURLKey,
103
- isKey: !_.isUndefined(dict.WIRConnectionIdentifierKey),
104
- });
105
- }
106
- }
107
- return newPageArray;
96
+ .filter((dict) => _.isUndefined(dict.WIRTypeKey) || ACCEPTED_PAGE_TYPES.includes(dict.WIRTypeKey))
97
+ .map((dict) => ({
98
+ id: dict.WIRPageIdentifierKey,
99
+ title: dict.WIRTitleKey,
100
+ url: dict.WIRURLKey,
101
+ isKey: !_.isUndefined(dict.WIRConnectionIdentifierKey),
102
+ }));
108
103
  }
109
104
 
110
105
  /**
@@ -147,7 +142,7 @@ export function getDebuggerAppKey (bundleId, appDict) {
147
142
  * Find app keys based on assigned bundleIds from appDict
148
143
  * When bundleIds includes a wildcard ('*'), returns all appKeys in appDict.
149
144
  * @param {string[]} bundleIds
150
- * @param {Record<string, any>} appDict
145
+ * @param {Record<string, AppInfo>} appDict
151
146
  * @returns {string[]}
152
147
  */
153
148
  export function getPossibleDebuggerAppKeys(bundleIds, appDict) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "keywords": [
5
5
  "appium"
6
6
  ],
7
- "version": "11.5.3",
7
+ "version": "11.5.5",
8
8
  "author": "Appium Contributors",
9
9
  "license": "Apache-2.0",
10
10
  "repository": {
@@ -36,7 +36,6 @@
36
36
  "@appium/base-driver": "^9.0.0",
37
37
  "@appium/support": "^5.0.3",
38
38
  "appium-ios-device": "^2.0.0",
39
- "async-lock": "^1.2.2",
40
39
  "asyncbox": "^3.0.0",
41
40
  "bluebird": "^3.4.7",
42
41
  "fancy-log": "^2.0.0",