@onekeyfe/hd-transport-web-device 1.2.2-alpha.120 → 1.2.2-alpha.122

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.
@@ -205,12 +205,52 @@ describe('ElectronBleTransport protocol detection', () => {
205
205
  expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
206
206
  });
207
207
 
208
- test('sends a native disconnect even before acquire marks the device connected', async () => {
208
+ test('cancels a pending native connect acquire has not registered yet', async () => {
209
209
  const device = { id: 'pending-connect-id', name: 'OneKey Pro 2' };
210
210
  const nobleBle = createNobleBle(device);
211
+ // Never calls back: the field case the Core acquire deadline has to break.
212
+ nobleBle.connect.mockImplementation(
213
+ () =>
214
+ new Promise<void>(() => {
215
+ // intentionally never settles
216
+ })
217
+ );
218
+ const bleTransport = configureTransport(nobleBle) as any;
219
+
220
+ const pendingAcquire = bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
221
+ pendingAcquire.catch(() => undefined);
222
+ await new Promise(resolve => {
223
+ setTimeout(resolve, 10);
224
+ });
225
+
226
+ // What the deadline / user abort calls. connectedDevices is still empty
227
+ // here, so this only works because the acquire is tracked as in flight.
228
+ await bleTransport.disconnect(device.id);
229
+
230
+ expect(nobleBle.unsubscribe).not.toHaveBeenCalled();
231
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
232
+ });
233
+
234
+ test('leaves a kept-alive link up when a released device is disconnected', async () => {
235
+ const device = { id: 'kept-alive-id', name: 'OneKey Pro 2' };
236
+ const nobleBle = createNobleBle(device);
237
+ const bleTransport = configureTransport(nobleBle) as any;
238
+
239
+ // No acquire in flight and nothing in connectedDevices: the link was
240
+ // released logically and belongs to the main-process keep-alive timer.
241
+ // The routine post-call cancel must not cost the next call a cold connect.
242
+ await bleTransport.disconnect(device.id);
243
+
244
+ expect(nobleBle.disconnect).not.toHaveBeenCalled();
245
+ expect(nobleBle.unsubscribe).not.toHaveBeenCalled();
246
+ });
247
+
248
+ test('forceNative disconnects a device the renderer no longer tracks', async () => {
249
+ const device = { id: 'presumed-dead-id', name: 'OneKey Pro 2' };
250
+ const nobleBle = createNobleBle(device);
211
251
  const bleTransport = configureTransport(nobleBle) as any;
212
252
 
213
- await bleTransport.releaseNative(device.id);
253
+ await bleTransport.releaseNative(device.id, { forceNative: true });
214
254
 
215
255
  expect(nobleBle.unsubscribe).not.toHaveBeenCalled();
216
256
  expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
@@ -31,6 +31,39 @@ function buildAcquirableTransport(path = 'pro-webusb') {
31
31
  }
32
32
 
33
33
  describe('WebUsbTransport protocol probe cache', () => {
34
+ test.each([
35
+ ['V1', false, 0],
36
+ ['V1', true, 1],
37
+ ['V2', false, 1],
38
+ [undefined, false, 1],
39
+ ] as const)(
40
+ 'reconnect protocol=%s first=%s resets USB %s times',
41
+ async (protocol, first, resets) => {
42
+ const webusb = new WebUsbTransport();
43
+ const path = 'connected-usb-device';
44
+ const device = {
45
+ opened: true,
46
+ configuration: { configurationValue: 1 },
47
+ configurations: [],
48
+ reset: jest.fn().mockResolvedValue(undefined),
49
+ selectConfiguration: jest.fn().mockResolvedValue(undefined),
50
+ claimInterface: jest.fn().mockResolvedValue(undefined),
51
+ clearHalt: jest.fn().mockResolvedValue(undefined),
52
+ };
53
+ jest.spyOn(webusb, 'findDevice').mockResolvedValue(device as unknown as USBDevice);
54
+ jest.spyOn(webusb, 'getConnectedDevices').mockResolvedValue([]);
55
+ if (protocol) {
56
+ const state = webusb as unknown as { deviceProtocol: Map<string, 'V1' | 'V2'> };
57
+ state.deviceProtocol.set(path, protocol);
58
+ }
59
+
60
+ await webusb.connectToDevice(path, first);
61
+
62
+ expect(device.reset).toHaveBeenCalledTimes(resets);
63
+ expect(device.claimInterface).toHaveBeenCalledWith(0);
64
+ }
65
+ );
66
+
34
67
  test('acquire skips the wire probe when the protocol is already cached', async () => {
35
68
  const webusb = buildAcquirableTransport();
36
69
  const path = 'pro-webusb';
@@ -25,6 +25,7 @@ export default class ElectronBleTransport {
25
25
  Log?: any;
26
26
  emitter?: EventEmitter;
27
27
  private connectedDevices;
28
+ private acquiringDevices;
28
29
  private deviceProtocol;
29
30
  private deviceProtocolHints;
30
31
  private deviceMtus;
@@ -1 +1 @@
1
- {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -216,6 +216,14 @@ declare class ElectronBleTransport {
216
216
  Log?: any;
217
217
  emitter?: EventEmitter;
218
218
  private connectedDevices;
219
+ /**
220
+ * Devices whose acquire() is still in flight.
221
+ *
222
+ * A native connect that never calls back has not reached `connectedDevices`
223
+ * yet, so this is the only record that the renderer is still trying to own
224
+ * the link; `releaseNative()` needs it to cancel that pending connect.
225
+ */
226
+ private acquiringDevices;
219
227
  private deviceProtocol;
220
228
  private deviceProtocolHints;
221
229
  private deviceMtus;
package/dist/index.js CHANGED
@@ -375,11 +375,13 @@ class WebUsbTransport extends transport.ProtocolV2UsbTransportBase {
375
375
  if (!device.opened) {
376
376
  yield device.open();
377
377
  }
378
- try {
379
- yield device.reset();
380
- }
381
- catch (error) {
382
- (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[WebUsbTransport] reset before claim failed, continuing:', error);
378
+ if (first || this.deviceProtocol.get(path) !== 'V1') {
379
+ try {
380
+ yield device.reset();
381
+ }
382
+ catch (error) {
383
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[WebUsbTransport] reset before claim failed, continuing:', error);
384
+ }
383
385
  }
384
386
  yield this.getConnectedDevices();
385
387
  device = yield this.findDevice(path);
@@ -848,6 +850,7 @@ class ElectronBleTransport {
848
850
  this.runPromise = null;
849
851
  this.runPromiseDeviceId = null;
850
852
  this.connectedDevices = new Set();
853
+ this.acquiringDevices = new Set();
851
854
  this.deviceProtocol = new Map();
852
855
  this.deviceProtocolHints = new Map();
853
856
  this.deviceMtus = new Map();
@@ -873,7 +876,7 @@ class ElectronBleTransport {
873
876
  this.rejectProtocolV2Frames(uuid, new Error(reason));
874
877
  (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('[Electron BLE] Protocol V2 link invalidated:', uuid, reason);
875
878
  if (reason.startsWith('Protocol V2 link-fatal error:')) {
876
- yield this.releaseNative(uuid);
879
+ yield this.releaseNative(uuid, { forceNative: true });
877
880
  }
878
881
  }),
879
882
  });
@@ -1032,6 +1035,7 @@ class ElectronBleTransport {
1032
1035
  this.runPromise = null;
1033
1036
  this.runPromiseDeviceId = null;
1034
1037
  }
1038
+ this.acquiringDevices.add(uuid);
1035
1039
  try {
1036
1040
  if (!((_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle)) {
1037
1041
  throw new Error('Noble BLE API not available');
@@ -1098,6 +1102,9 @@ class ElectronBleTransport {
1098
1102
  this.cleanupDeviceState(uuid);
1099
1103
  this.handleBluetoothError(error);
1100
1104
  }
1105
+ finally {
1106
+ this.acquiringDevices.delete(uuid);
1107
+ }
1101
1108
  });
1102
1109
  }
1103
1110
  release(id, _onclose, keepSession) {
@@ -1118,12 +1125,14 @@ class ElectronBleTransport {
1118
1125
  return this.releaseNative(id);
1119
1126
  });
1120
1127
  }
1121
- releaseNative(id) {
1128
+ releaseNative(id, options) {
1122
1129
  var _a, _b;
1123
1130
  return __awaiter(this, void 0, void 0, function* () {
1131
+ const rendererOwnsLink = this.connectedDevices.has(id) || this.acquiringDevices.has(id);
1132
+ const shouldDisconnect = (options === null || options === void 0 ? void 0 : options.forceNative) === true || rendererOwnsLink;
1124
1133
  try {
1125
1134
  const nobleBle = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle;
1126
- if (nobleBle) {
1135
+ if (nobleBle && shouldDisconnect) {
1127
1136
  if (this.connectedDevices.has(id)) {
1128
1137
  yield invokeNobleBle(nobleBle.unsubscribe(id)).catch(error => {
1129
1138
  var _a;
@@ -1562,7 +1571,7 @@ class ElectronBleTransport {
1562
1571
  this.notificationCleanups.delete(uuid);
1563
1572
  this.notificationTokens.delete(uuid);
1564
1573
  if (!isProbeTimeout) {
1565
- yield this.releaseNative(uuid);
1574
+ yield this.releaseNative(uuid, { forceNative: true });
1566
1575
  }
1567
1576
  }
1568
1577
  throw this.normalizeBluetoothError(e);
@@ -1 +1 @@
1
- {"version":3,"file":"webusb.d.ts","sourceRoot":"","sources":["../src/webusb.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webusb.d.ts","sourceRoot":"","sources":["../src/webusb.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-web-device",
3
- "version": "1.2.2-alpha.120",
3
+ "version": "1.2.2-alpha.122",
4
4
  "author": "OneKey",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -21,13 +21,13 @@
21
21
  "lint:fix": "eslint . --fix"
22
22
  },
23
23
  "dependencies": {
24
- "@onekeyfe/hd-shared": "1.2.2-alpha.120",
25
- "@onekeyfe/hd-transport": "1.2.2-alpha.120"
24
+ "@onekeyfe/hd-shared": "1.2.2-alpha.122",
25
+ "@onekeyfe/hd-transport": "1.2.2-alpha.122"
26
26
  },
27
27
  "devDependencies": {
28
- "@onekeyfe/hd-transport-electron": "1.2.2-alpha.120",
28
+ "@onekeyfe/hd-transport-electron": "1.2.2-alpha.122",
29
29
  "@types/w3c-web-usb": "^1.0.6",
30
30
  "@types/web-bluetooth": "^0.0.17"
31
31
  },
32
- "gitHead": "26958fa2be6aa34a07f42403fb7022d2785e70b9"
32
+ "gitHead": "37770cd3ae109751f082715228b6155487b7da56"
33
33
  }
@@ -117,6 +117,15 @@ export default class ElectronBleTransport {
117
117
 
118
118
  private connectedDevices: Set<string> = new Set();
119
119
 
120
+ /**
121
+ * Devices whose acquire() is still in flight.
122
+ *
123
+ * A native connect that never calls back has not reached `connectedDevices`
124
+ * yet, so this is the only record that the renderer is still trying to own
125
+ * the link; `releaseNative()` needs it to cancel that pending connect.
126
+ */
127
+ private acquiringDevices: Set<string> = new Set();
128
+
120
129
  private deviceProtocol: Map<string, ProtocolType> = new Map();
121
130
 
122
131
  private deviceProtocolHints: Map<string, ProtocolType> = new Map();
@@ -149,7 +158,7 @@ export default class ElectronBleTransport {
149
158
  this.rejectProtocolV2Frames(uuid, new Error(reason));
150
159
  this.Log?.debug('[Electron BLE] Protocol V2 link invalidated:', uuid, reason);
151
160
  if (reason.startsWith('Protocol V2 link-fatal error:')) {
152
- await this.releaseNative(uuid);
161
+ await this.releaseNative(uuid, { forceNative: true });
153
162
  }
154
163
  },
155
164
  });
@@ -363,6 +372,7 @@ export default class ElectronBleTransport {
363
372
  this.runPromiseDeviceId = null;
364
373
  }
365
374
 
375
+ this.acquiringDevices.add(uuid);
366
376
  try {
367
377
  if (!window.desktopApi?.nobleBle) {
368
378
  throw new Error('Noble BLE API not available');
@@ -434,6 +444,8 @@ export default class ElectronBleTransport {
434
444
  }
435
445
  this.cleanupDeviceState(uuid);
436
446
  this.handleBluetoothError(error);
447
+ } finally {
448
+ this.acquiringDevices.delete(uuid);
437
449
  }
438
450
  }
439
451
 
@@ -454,10 +466,23 @@ export default class ElectronBleTransport {
454
466
  }
455
467
 
456
468
  // Hard teardown, error paths only: a link presumed dead must not be reused.
457
- private async releaseNative(id: string) {
469
+ //
470
+ // The native disconnect is sent while the renderer still owns the link, or is
471
+ // still trying to get it: a stuck acquire has not reached `connectedDevices`
472
+ // yet, and its pending native connect can only be cancelled from here, so the
473
+ // Core acquire deadline would otherwise be unable to terminate it.
474
+ //
475
+ // It is NOT sent for a device the renderer has already released logically.
476
+ // That link belongs to the main-process keep-alive timer, and dropping it on
477
+ // the routine post-call `cancel()` (Device.interruptionFromUser, no acquire
478
+ // held, empty request queue) costs a full cold reconnect on the very next
479
+ // operation — measured 2.93s on Pro and 17-26s on Pro 2.
480
+ private async releaseNative(id: string, options?: { forceNative?: boolean }) {
481
+ const rendererOwnsLink = this.connectedDevices.has(id) || this.acquiringDevices.has(id);
482
+ const shouldDisconnect = options?.forceNative === true || rendererOwnsLink;
458
483
  try {
459
484
  const nobleBle = window.desktopApi?.nobleBle;
460
- if (nobleBle) {
485
+ if (nobleBle && shouldDisconnect) {
461
486
  if (this.connectedDevices.has(id)) {
462
487
  await invokeNobleBle(nobleBle.unsubscribe(id)).catch(error => {
463
488
  this.Log?.debug('[Electron BLE] release unsubscribe failed:', error);
@@ -970,7 +995,7 @@ export default class ElectronBleTransport {
970
995
  this.notificationCleanups.delete(uuid);
971
996
  this.notificationTokens.delete(uuid);
972
997
  if (!isProbeTimeout) {
973
- await this.releaseNative(uuid);
998
+ await this.releaseNative(uuid, { forceNative: true });
974
999
  }
975
1000
  }
976
1001
  throw this.normalizeBluetoothError(e);
package/src/webusb.ts CHANGED
@@ -566,10 +566,14 @@ export default class WebUsbTransport extends ProtocolV2UsbTransportBase<string>
566
566
  if (!device.opened) {
567
567
  await device.open();
568
568
  }
569
- try {
570
- await device.reset();
571
- } catch (error) {
572
- this.Log?.debug('[WebUsbTransport] reset before claim failed, continuing:', error);
569
+ // A V1 packet retry continues an in-flight exchange. Preserve its endpoint
570
+ // state as in the legacy transport; probing and V2 recovery still reset.
571
+ if (first || this.deviceProtocol.get(path) !== 'V1') {
572
+ try {
573
+ await device.reset();
574
+ } catch (error) {
575
+ this.Log?.debug('[WebUsbTransport] reset before claim failed, continuing:', error);
576
+ }
573
577
  }
574
578
  await this.getConnectedDevices();
575
579
  device = await this.findDevice(path);