@onekeyfe/hd-transport-electron 1.2.2-alpha.103 → 1.2.2-alpha.104

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.
@@ -55,13 +55,13 @@ function invokeNobleBleIpc(request) {
55
55
 
56
56
  function initNobleBleSupport(webContents) {
57
57
  return __awaiter(this, void 0, void 0, function* () {
58
- const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-eff26dd3.js'); });
58
+ const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-263d4736.js'); });
59
59
  setupNobleBleHandlers(webContents);
60
60
  });
61
61
  }
62
62
  function disposeNobleBleSupport(releaseNoble) {
63
63
  return __awaiter(this, void 0, void 0, function* () {
64
- const handler = yield Promise.resolve().then(function () { return require('./noble-ble-handler-eff26dd3.js'); });
64
+ const handler = yield Promise.resolve().then(function () { return require('./noble-ble-handler-263d4736.js'); });
65
65
  yield handler.disposeNobleBleSupport(releaseNoble);
66
66
  });
67
67
  }
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-052b4b5b.js');
5
+ var index = require('./index-985e2bf3.js');
6
6
 
7
7
 
8
8
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-052b4b5b.js');
3
+ var index = require('./index-985e2bf3.js');
4
4
  var hdShared = require('@onekeyfe/hd-shared');
5
5
  var pRetry = require('p-retry');
6
6
 
@@ -106,6 +106,7 @@ let disposePromise;
106
106
  let windowCleanup;
107
107
  let removeIpcHandlers;
108
108
  const pendingCancellations = new Set();
109
+ const pendingEnumerations = new Set();
109
110
  const nativeConnections = new Set();
110
111
  function trackNativeConnection(operation, cancel) {
111
112
  const connection = {
@@ -873,7 +874,7 @@ function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN
873
874
  });
874
875
  });
875
876
  }
876
- function enumerateDevices() {
877
+ function enumerateDevices(isWindowDestroyed) {
877
878
  return index.__awaiter(this, void 0, void 0, function* () {
878
879
  if (!noble) {
879
880
  yield initializeNoble();
@@ -882,6 +883,8 @@ function enumerateDevices() {
882
883
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Noble not available');
883
884
  }
884
885
  assertBleActive();
886
+ if (isWindowDestroyed())
887
+ return [];
885
888
  const nobleInstance = noble;
886
889
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Starting device enumeration');
887
890
  discoveredDevices.clear();
@@ -890,14 +893,20 @@ function enumerateDevices() {
890
893
  const devices = [];
891
894
  let settled = false;
892
895
  let intervalId;
893
- const cleanup = () => index.__awaiter(this, void 0, void 0, function* () {
894
- settled = true;
895
- pendingCancellations.delete(cancel);
896
- clearTimeout(timeoutId);
897
- if (intervalId)
898
- clearInterval(intervalId);
899
- yield waitForNobleScanStop(nobleInstance);
900
- });
896
+ let cleanupPromise;
897
+ const cleanup = () => {
898
+ if (!cleanupPromise) {
899
+ settled = true;
900
+ pendingCancellations.delete(cancel);
901
+ clearTimeout(timeoutId);
902
+ if (intervalId)
903
+ clearInterval(intervalId);
904
+ cleanupPromise = waitForNobleScanStop(nobleInstance).finally(() => {
905
+ pendingEnumerations.delete(cancel);
906
+ });
907
+ }
908
+ return cleanupPromise;
909
+ };
901
910
  const pushDevice = (peripheral, id) => {
902
911
  var _a;
903
912
  if (devices.some(d => d.id === id))
@@ -921,10 +930,9 @@ function enumerateDevices() {
921
930
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scan completed, found devices:', devices.length);
922
931
  resolve(devices);
923
932
  }), DEVICE_SCAN_TIMEOUT);
924
- const cancel = () => {
925
- cleanup().then(() => resolve([]), reject);
926
- };
933
+ const cancel = () => cleanup().then(() => resolve([]), reject);
927
934
  pendingCancellations.add(cancel);
935
+ pendingEnumerations.add(cancel);
928
936
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning for OneKey BLE devices');
929
937
  nobleInstance.startScanning([], true, (error) => index.__awaiter(this, void 0, void 0, function* () {
930
938
  if (settled)
@@ -1545,7 +1553,7 @@ function setupNobleBleHandlers(webContents) {
1545
1553
  safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
1546
1554
  handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
1547
1555
  try {
1548
- const devices = yield enumerateDevices();
1556
+ const devices = yield enumerateDevices(() => windowDestroyed);
1549
1557
  safeLog(logger, 'debug', 'Enumeration completed', {
1550
1558
  count: devices.length,
1551
1559
  devices: devices.map(device => ({ id: device.id, name: device.name })),
@@ -1642,9 +1650,11 @@ function setupNobleBleHandlers(webContents) {
1642
1650
  return;
1643
1651
  safeLog(logger, 'info', 'Cleaning up Noble BLE handlers');
1644
1652
  const previousCleanup = windowCleanup;
1653
+ const enumerations = Array.from(pendingEnumerations, cancel => cancel());
1645
1654
  windowCleanup = (() => index.__awaiter(this, void 0, void 0, function* () {
1646
1655
  if (previousCleanup)
1647
1656
  yield previousCleanup;
1657
+ yield Promise.allSettled(enumerations);
1648
1658
  if (disposing)
1649
1659
  return;
1650
1660
  const deviceIds = Array.from(connectedDevices.keys());
@@ -1 +1 @@
1
- {"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgC1F,KAAK,mBAAmB,GAAG,KAAK,GAAG;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,mBAAmB,EAAE,aAAa,SAAK,+CAiB3F;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAgCvF;AA+KD,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE,oBAAoB,UAI7E;AA4xDD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CA+NpE;AAOD,wBAAgB,sBAAsB,CACpC,YAAY,GAAE,CAAC,QAAQ,EAAE;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,KAAK,IAAkC,GAC/E,OAAO,CAAC,IAAI,CAAC,CAiEf"}
1
+ {"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAiC1F,KAAK,mBAAmB,GAAG,KAAK,GAAG;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,mBAAmB,EAAE,aAAa,SAAK,+CAiB3F;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAgCvF;AA+KD,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE,oBAAoB,UAI7E;AAkyDD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAkOpE;AAOD,wBAAgB,sBAAsB,CACpC,YAAY,GAAE,CAAC,QAAQ,EAAE;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,KAAK,IAAkC,GAC/E,OAAO,CAAC,IAAI,CAAC,CAiEf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-electron",
3
- "version": "1.2.2-alpha.103",
3
+ "version": "1.2.2-alpha.104",
4
4
  "author": "OneKey",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -25,9 +25,9 @@
25
25
  "electron-log": ">=4.0.0"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-core": "1.2.2-alpha.103",
29
- "@onekeyfe/hd-shared": "1.2.2-alpha.103",
30
- "@onekeyfe/hd-transport": "1.2.2-alpha.103",
28
+ "@onekeyfe/hd-core": "1.2.2-alpha.104",
29
+ "@onekeyfe/hd-shared": "1.2.2-alpha.104",
30
+ "@onekeyfe/hd-transport": "1.2.2-alpha.104",
31
31
  "@stoprocent/noble": "2.3.16",
32
32
  "p-retry": "^4.6.2"
33
33
  },
@@ -36,5 +36,5 @@
36
36
  "electron": "^25.0.0",
37
37
  "typescript": "^5.3.3"
38
38
  },
39
- "gitHead": "cd5aaa8a42a61c93f28b7d4931081fb7cd652e26"
39
+ "gitHead": "67835939d9f779ffd50cd8b482d8c5b53bd580bd"
40
40
  }
@@ -947,4 +947,72 @@ describe('Noble BLE process shutdown', () => {
947
947
  await sdk.disposeNobleBleSupport();
948
948
  expect(native.stop).toHaveBeenCalledTimes(1);
949
949
  });
950
+
951
+ test.each(['started', 'late-start-callback'])(
952
+ 'retires an old enumeration before a shared native scan resumes: %s',
953
+ async scanState => {
954
+ jest.useFakeTimers({ doNotFake: ['performance', 'setImmediate'] });
955
+ const { sdk, native, handlers, window } = await setup();
956
+ let lateStart: (() => void) | undefined;
957
+ if (scanState === 'late-start-callback') {
958
+ native.startScanning.mockImplementationOnce((_uuids, _duplicates, callback) => {
959
+ lateStart = callback;
960
+ });
961
+ }
962
+ let oldScanSettled = false;
963
+ const oldScan = Promise.resolve(
964
+ handlers.get(EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE)?.({})
965
+ ).then(result => {
966
+ oldScanSettled = true;
967
+ return result;
968
+ });
969
+ await flushCallbacks();
970
+ jest.advanceTimersByTime(1000);
971
+
972
+ let finishOldScan: (() => void) | undefined;
973
+ native.stopScanning.mockImplementationOnce(callback => {
974
+ finishOldScan = callback;
975
+ });
976
+ window.emit('destroyed');
977
+ sdk.setupNobleBleHandlers(new EventEmitter() as unknown as WebContents);
978
+ const replacementReady = handlers.get(EOneKeyBleMessageKeys.BLE_AVAILABILITY_CHECK)?.({});
979
+ let replacementSettled = false;
980
+ Promise.resolve(replacementReady).then(() => {
981
+ replacementSettled = true;
982
+ });
983
+ await flushCallbacks();
984
+ expect(replacementSettled).toBe(false);
985
+ finishOldScan?.();
986
+ await replacementReady;
987
+ await flushCallbacks();
988
+ expect(oldScanSettled).toBe(true);
989
+ expect(await oldScan).toEqual([]);
990
+
991
+ // Another transport can now scan on the same process-wide Noble instance.
992
+ native.startScanning([], true, () => undefined);
993
+ const stopCount = native.stopScanning.mock.calls.length;
994
+ lateStart?.();
995
+ jest.advanceTimersByTime(5000);
996
+ await flushCallbacks();
997
+ expect(native.stopScanning).toHaveBeenCalledTimes(stopCount);
998
+ expect(jest.getTimerCount()).toBe(0);
999
+ expect(native.stop).not.toHaveBeenCalled();
1000
+ await sdk.disposeNobleBleSupport();
1001
+ }
1002
+ );
1003
+
1004
+ test('does not start an old window enumeration after Bluetooth becomes ready', async () => {
1005
+ const { sdk, native, handlers, window } = await setup('unknown');
1006
+ const oldScan = handlers.get(EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE)?.({});
1007
+ await flushCallbacks();
1008
+ window.emit('destroyed');
1009
+ sdk.setupNobleBleHandlers(new EventEmitter() as unknown as WebContents);
1010
+ await handlers.get(EOneKeyBleMessageKeys.BLE_AVAILABILITY_CHECK)?.({});
1011
+
1012
+ native.state = 'poweredOn';
1013
+ native.emit('stateChange', 'poweredOn');
1014
+ expect(await oldScan).toEqual([]);
1015
+ expect(native.startScanning).not.toHaveBeenCalled();
1016
+ await sdk.disposeNobleBleSupport();
1017
+ });
950
1018
  });
@@ -46,6 +46,7 @@ let disposePromise: Promise<void> | undefined;
46
46
  let windowCleanup: Promise<void> | undefined;
47
47
  let removeIpcHandlers: (() => void) | undefined;
48
48
  const pendingCancellations = new Set<() => void>();
49
+ const pendingEnumerations = new Set<() => Promise<void>>();
49
50
  const nativeConnections = new Set<{ cancel: () => void; settled: Promise<void> }>();
50
51
 
51
52
  function trackNativeConnection(operation: Promise<unknown>, cancel: () => void): void {
@@ -1150,7 +1151,7 @@ async function performTargetedScan(
1150
1151
  }
1151
1152
 
1152
1153
  // Enumerate devices
1153
- async function enumerateDevices(): Promise<DeviceInfo[]> {
1154
+ async function enumerateDevices(isWindowDestroyed: () => boolean): Promise<DeviceInfo[]> {
1154
1155
  if (!noble) {
1155
1156
  await initializeNoble();
1156
1157
  }
@@ -1160,6 +1161,7 @@ async function enumerateDevices(): Promise<DeviceInfo[]> {
1160
1161
  }
1161
1162
 
1162
1163
  assertBleActive();
1164
+ if (isWindowDestroyed()) return [];
1163
1165
  // Capture noble reference for use in closures (TypeScript narrowing)
1164
1166
  const nobleInstance = noble;
1165
1167
 
@@ -1176,16 +1178,22 @@ async function enumerateDevices(): Promise<DeviceInfo[]> {
1176
1178
  const devices: DeviceInfo[] = [];
1177
1179
  let settled = false;
1178
1180
  let intervalId: ReturnType<typeof setInterval> | undefined;
1181
+ let cleanupPromise: Promise<void> | undefined;
1179
1182
 
1180
1183
  // Cleanup function: clears timers and waits until Noble confirms scanning
1181
1184
  // has stopped. Resolving enumerate before this callback creates a race with
1182
1185
  // an immediately-following connection attempt.
1183
- const cleanup = async () => {
1184
- settled = true;
1185
- pendingCancellations.delete(cancel);
1186
- clearTimeout(timeoutId);
1187
- if (intervalId) clearInterval(intervalId);
1188
- await waitForNobleScanStop(nobleInstance);
1186
+ const cleanup = () => {
1187
+ if (!cleanupPromise) {
1188
+ settled = true;
1189
+ pendingCancellations.delete(cancel);
1190
+ clearTimeout(timeoutId);
1191
+ if (intervalId) clearInterval(intervalId);
1192
+ cleanupPromise = waitForNobleScanStop(nobleInstance).finally(() => {
1193
+ pendingEnumerations.delete(cancel);
1194
+ });
1195
+ }
1196
+ return cleanupPromise;
1189
1197
  };
1190
1198
 
1191
1199
  // Collect discovered devices into the devices array
@@ -1214,10 +1222,9 @@ async function enumerateDevices(): Promise<DeviceInfo[]> {
1214
1222
  resolve(devices);
1215
1223
  }, DEVICE_SCAN_TIMEOUT);
1216
1224
 
1217
- const cancel = () => {
1218
- cleanup().then(() => resolve([]), reject);
1219
- };
1225
+ const cancel = () => cleanup().then(() => resolve([]), reject);
1220
1226
  pendingCancellations.add(cancel);
1227
+ pendingEnumerations.add(cancel);
1221
1228
 
1222
1229
  // Start scanning without a service UUID filter so Pro2 advertisements with
1223
1230
  // short vendor UUIDs can be found. Repeated advertisements are required when
@@ -2163,7 +2170,7 @@ export function setupNobleBleHandlers(webContents: WebContents): void {
2163
2170
  // Handle enumerate request
2164
2171
  handle(EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, async () => {
2165
2172
  try {
2166
- const devices = await enumerateDevices();
2173
+ const devices = await enumerateDevices(() => windowDestroyed);
2167
2174
  safeLog(logger, 'debug', 'Enumeration completed', {
2168
2175
  count: devices.length,
2169
2176
  devices: devices.map(device => ({ id: device.id, name: device.name })),
@@ -2312,8 +2319,11 @@ export function setupNobleBleHandlers(webContents: WebContents): void {
2312
2319
  if (disposing) return;
2313
2320
  safeLog(logger, 'info', 'Cleaning up Noble BLE handlers');
2314
2321
  const previousCleanup = windowCleanup;
2322
+ // Cancel before yielding so old timers cannot stop a replacement renderer's scan.
2323
+ const enumerations = Array.from(pendingEnumerations, cancel => cancel());
2315
2324
  windowCleanup = (async () => {
2316
2325
  if (previousCleanup) await previousCleanup;
2326
+ await Promise.allSettled(enumerations);
2317
2327
  if (disposing) return;
2318
2328
  const deviceIds = Array.from(connectedDevices.keys());
2319
2329
  for (const deviceId of deviceIds) {