@onekeyfe/hd-core 1.2.2-alpha.112 → 1.2.2-alpha.113
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/__tests__/core-error-output.test.ts +71 -0
- package/__tests__/device-lifecycle-events.test.ts +8 -8
- package/__tests__/search-devices.test.ts +39 -3
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.js +45 -12
- package/package.json +4 -4
- package/src/api/SearchDevices.ts +14 -3
- package/src/core/index.ts +38 -13
|
@@ -4,6 +4,8 @@ import { initConnector, initCore } from '../src/core';
|
|
|
4
4
|
import { DataManager } from '../src/data-manager';
|
|
5
5
|
import TransportManager from '../src/data-manager/TransportManager';
|
|
6
6
|
import { IFRAME } from '../src/events';
|
|
7
|
+
import SearchDevices from '../src/api/SearchDevices';
|
|
8
|
+
import { DeviceList } from '../src/device/DeviceList';
|
|
7
9
|
|
|
8
10
|
jest.mock('../src/data/config', () => ({
|
|
9
11
|
getSDKVersion: jest.fn(() => '1.0.0-test'),
|
|
@@ -24,6 +26,75 @@ describe('Core 错误输出边界', () => {
|
|
|
24
26
|
jest.restoreAllMocks();
|
|
25
27
|
});
|
|
26
28
|
|
|
29
|
+
test.each([
|
|
30
|
+
['webusb', false],
|
|
31
|
+
['desktop-webusb', false],
|
|
32
|
+
['desktop-webusb', true],
|
|
33
|
+
] as const)(
|
|
34
|
+
'%s waits for discovery without masking initialization or cancellation (cancel=%s)',
|
|
35
|
+
async (env, shouldCancel) => {
|
|
36
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue(env as never);
|
|
37
|
+
const error = ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed, 'probe failed');
|
|
38
|
+
let finishSearch!: () => void;
|
|
39
|
+
let searchStarted!: () => void;
|
|
40
|
+
const started = new Promise<void>(resolve => {
|
|
41
|
+
searchStarted = resolve;
|
|
42
|
+
});
|
|
43
|
+
const search = jest.spyOn(SearchDevices.prototype, 'run').mockImplementation(async () => {
|
|
44
|
+
searchStarted();
|
|
45
|
+
await new Promise<void>(resolve => {
|
|
46
|
+
finishSearch = resolve;
|
|
47
|
+
});
|
|
48
|
+
return [];
|
|
49
|
+
});
|
|
50
|
+
const initialize = jest
|
|
51
|
+
.spyOn(DeviceList.prototype, 'getDeviceLists')
|
|
52
|
+
.mockRejectedValue(error);
|
|
53
|
+
const core = initCore();
|
|
54
|
+
initConnector();
|
|
55
|
+
try {
|
|
56
|
+
const discovery = core.handleMessage({
|
|
57
|
+
id: 10,
|
|
58
|
+
type: IFRAME.CALL,
|
|
59
|
+
payload: { method: 'searchDevices' },
|
|
60
|
+
} as never);
|
|
61
|
+
await started;
|
|
62
|
+
const request = core.handleMessage({
|
|
63
|
+
id: 11,
|
|
64
|
+
type: IFRAME.CALL,
|
|
65
|
+
payload: { method: 'getDeviceState', connectId: 'serial-V2' },
|
|
66
|
+
} as never);
|
|
67
|
+
await new Promise(resolve => {
|
|
68
|
+
setTimeout(resolve, 0);
|
|
69
|
+
});
|
|
70
|
+
expect(initialize).not.toHaveBeenCalled();
|
|
71
|
+
if (shouldCancel) {
|
|
72
|
+
await core.handleMessage({
|
|
73
|
+
type: IFRAME.CANCEL,
|
|
74
|
+
payload: { connectId: 'serial-V2' },
|
|
75
|
+
} as never);
|
|
76
|
+
}
|
|
77
|
+
finishSearch();
|
|
78
|
+
await expect(discovery).resolves.toMatchObject({ success: true });
|
|
79
|
+
const expectedError = shouldCancel
|
|
80
|
+
? ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)
|
|
81
|
+
: error;
|
|
82
|
+
await expect(request).resolves.toMatchObject({
|
|
83
|
+
success: false,
|
|
84
|
+
payload: { code: expectedError.errorCode, error: expectedError.message },
|
|
85
|
+
});
|
|
86
|
+
await new Promise(resolve => {
|
|
87
|
+
setTimeout(resolve, 0);
|
|
88
|
+
});
|
|
89
|
+
expect(search).toHaveBeenCalledTimes(1);
|
|
90
|
+
expect(initialize).toHaveBeenCalledTimes(shouldCancel ? 0 : 1);
|
|
91
|
+
} finally {
|
|
92
|
+
finishSearch?.();
|
|
93
|
+
await core.dispose();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
27
98
|
test.each([
|
|
28
99
|
HardwareErrorCode.BleDeviceNotBonded,
|
|
29
100
|
HardwareErrorCode.BleDeviceBondedCanceled,
|
|
@@ -362,12 +362,12 @@ describe('public device lifecycle events', () => {
|
|
|
362
362
|
}
|
|
363
363
|
);
|
|
364
364
|
|
|
365
|
-
test('
|
|
365
|
+
test('clears the cleanup barrier when its deadline expires', async () => {
|
|
366
366
|
const realSetTimeout = setTimeout;
|
|
367
367
|
jest
|
|
368
368
|
.spyOn(global, 'setTimeout')
|
|
369
369
|
.mockImplementation((callback, delay, ...args) =>
|
|
370
|
-
realSetTimeout(callback, delay ===
|
|
370
|
+
realSetTimeout(callback, delay === 5_000 ? 0 : delay, ...args)
|
|
371
371
|
);
|
|
372
372
|
{
|
|
373
373
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
@@ -382,13 +382,13 @@ describe('public device lifecycle events', () => {
|
|
|
382
382
|
type: IFRAME.CALL,
|
|
383
383
|
payload: { method: 'getDeviceState', connectId: 'draining-device', connectProtocol: 'V2' },
|
|
384
384
|
} as CoreMessage);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
payload: { code: HardwareErrorCode.DeviceBusy },
|
|
388
|
-
});
|
|
389
|
-
expect(acquire).not.toHaveBeenCalled();
|
|
390
|
-
expect(context.getPrePendingCallPromise('draining-device')).toBe(gate.promise);
|
|
385
|
+
setImmediate(() => cancel(context, 'draining-device'));
|
|
386
|
+
await expect(result).resolves.toBeDefined();
|
|
391
387
|
gate.resolve();
|
|
388
|
+
await new Promise(resolve => {
|
|
389
|
+
setImmediate(resolve);
|
|
390
|
+
});
|
|
391
|
+
expect(context.getPrePendingCallPromise('draining-device')).toBeUndefined();
|
|
392
392
|
}
|
|
393
393
|
});
|
|
394
394
|
|
|
@@ -17,15 +17,16 @@ jest.mock('../src/data-manager', () => ({
|
|
|
17
17
|
jest.mock('../src/device/DevicePool', () => ({
|
|
18
18
|
DevicePool: {
|
|
19
19
|
getDevices: jest.fn(),
|
|
20
|
+
getDeviceByPath: jest.fn(),
|
|
20
21
|
},
|
|
21
22
|
}));
|
|
22
23
|
|
|
23
24
|
const transportManagerMock: { default: { configure: jest.Mock } } = jest.requireMock(
|
|
24
25
|
'../src/data-manager/TransportManager'
|
|
25
26
|
);
|
|
26
|
-
const devicePoolMock: {
|
|
27
|
-
|
|
28
|
-
);
|
|
27
|
+
const devicePoolMock: {
|
|
28
|
+
DevicePool: { getDevices: jest.Mock; getDeviceByPath: jest.Mock };
|
|
29
|
+
} = jest.requireMock('../src/device/DevicePool');
|
|
29
30
|
const dataManagerMock: {
|
|
30
31
|
DataManager: {
|
|
31
32
|
getSettings: jest.Mock;
|
|
@@ -40,8 +41,43 @@ describe('SearchDevices', () => {
|
|
|
40
41
|
beforeEach(() => {
|
|
41
42
|
jest.clearAllMocks();
|
|
42
43
|
mockIsBleConnect.mockReturnValue(false);
|
|
44
|
+
dataManagerMock.DataManager.getSettings.mockReturnValue('webusb');
|
|
43
45
|
});
|
|
44
46
|
|
|
47
|
+
test.each(['webusb', 'desktop-webusb'])(
|
|
48
|
+
'%s discovery leaves active V1/V2 requests and their schemas untouched',
|
|
49
|
+
async env => {
|
|
50
|
+
dataManagerMock.DataManager.getSettings.mockReturnValue(env);
|
|
51
|
+
const devices = ['V1', 'V2'].map(protocol => ({
|
|
52
|
+
features: { protocol },
|
|
53
|
+
toMessageObject: () => ({ connectId: `serial-${protocol}` }),
|
|
54
|
+
}));
|
|
55
|
+
devicePoolMock.DevicePool.getDeviceByPath.mockImplementation(
|
|
56
|
+
(path: string) => devices[['usb-V1', 'usb-V2'].indexOf(path)]
|
|
57
|
+
);
|
|
58
|
+
const method = new SearchDevices({
|
|
59
|
+
id: 1,
|
|
60
|
+
payload: { method: 'searchDevices' },
|
|
61
|
+
} as never);
|
|
62
|
+
method.init();
|
|
63
|
+
method.context = {
|
|
64
|
+
requestQueue: { getRequestTasksId: () => [2] },
|
|
65
|
+
} as never;
|
|
66
|
+
method.connector = {
|
|
67
|
+
enumerate: jest.fn().mockResolvedValue({
|
|
68
|
+
descriptors: [{ path: 'usb-V1' }, { path: 'usb-V2' }, { path: 'not-initialized' }],
|
|
69
|
+
}),
|
|
70
|
+
} as never;
|
|
71
|
+
|
|
72
|
+
await expect(method.run()).resolves.toEqual([
|
|
73
|
+
{ connectId: 'serial-V1' },
|
|
74
|
+
{ connectId: 'serial-V2' },
|
|
75
|
+
]);
|
|
76
|
+
expect(mockGetDevices).not.toHaveBeenCalled();
|
|
77
|
+
expect(mockConfigureTransport).not.toHaveBeenCalled();
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
45
81
|
test('搜索忽略调用方协议并主动探测,单个无响应设备不阻断后续结果', async () => {
|
|
46
82
|
const unresponsiveDescriptor = {
|
|
47
83
|
path: 'stale-usb-device',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchDevices.d.ts","sourceRoot":"","sources":["../../src/api/SearchDevices.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM1C,OAAO,KAAK,eAAe,MAAM,2BAA2B,CAAC;AAI7D,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAU;IACnD,SAAS,CAAC,EAAE,eAAe,CAAC;IAE5B,IAAI;IAME,GAAG;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"SearchDevices.d.ts","sourceRoot":"","sources":["../../src/api/SearchDevices.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM1C,OAAO,KAAK,eAAe,MAAM,2BAA2B,CAAC;AAI7D,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAU;IACnD,SAAS,CAAC,EAAE,eAAe,CAAC;IAE5B,IAAI;IAME,GAAG;;;;;;;;;;;;;;;CA0EV"}
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAEL,KAAK,6BAA6B,EAElC,KAAK,YAAY,EAIlB,MAAM,wBAAwB,CAAC;AAiChC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAYpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA0E7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAEL,KAAK,6BAA6B,EAElC,KAAK,YAAY,EAIlB,MAAM,wBAAwB,CAAC;AAiChC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAYpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA0E7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBA0FvE,CAAC;AAyFF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3F;AA8mBD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAoB/E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,WAEzD;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,WAI3D;AAiKD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,CAMtF;AAwMD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SA4G9D,CAAC;AA8GF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IAuChB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -47270,26 +47270,35 @@ class SearchDevices extends BaseMethod {
|
|
|
47270
47270
|
this.skipForceUpdateCheck = true;
|
|
47271
47271
|
}
|
|
47272
47272
|
run() {
|
|
47273
|
-
var _a, _b, _c, _d, _e;
|
|
47273
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
47274
47274
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47275
|
-
yield TransportManager.configure();
|
|
47276
|
-
const deviceDiff = yield ((_a = this.connector) === null || _a === void 0 ? void 0 : _a.enumerate());
|
|
47277
|
-
const devicesDescriptor = (_b = deviceDiff === null || deviceDiff === void 0 ? void 0 : deviceDiff.descriptors) !== null && _b !== void 0 ? _b : [];
|
|
47278
47275
|
const env = DataManager.getSettings('env');
|
|
47276
|
+
const useCachedWebUsbDevices = (env === 'webusb' || env === 'desktop-webusb') &&
|
|
47277
|
+
((_b = (_a = this.context) === null || _a === void 0 ? void 0 : _a.requestQueue.getRequestTasksId().length) !== null && _b !== void 0 ? _b : 0) > 0;
|
|
47278
|
+
if (!useCachedWebUsbDevices)
|
|
47279
|
+
yield TransportManager.configure();
|
|
47280
|
+
const deviceDiff = yield ((_c = this.connector) === null || _c === void 0 ? void 0 : _c.enumerate());
|
|
47281
|
+
const devicesDescriptor = (_d = deviceDiff === null || deviceDiff === void 0 ? void 0 : deviceDiff.descriptors) !== null && _d !== void 0 ? _d : [];
|
|
47279
47282
|
if (DataManager.isBleConnect(env)) {
|
|
47280
47283
|
const devices = [];
|
|
47281
47284
|
const seenIds = new Set();
|
|
47282
47285
|
for (const device of devicesDescriptor) {
|
|
47283
|
-
const lowerId = (
|
|
47286
|
+
const lowerId = (_e = device.id) === null || _e === void 0 ? void 0 : _e.toLowerCase();
|
|
47284
47287
|
if (!seenIds.has(lowerId)) {
|
|
47285
47288
|
seenIds.add(lowerId);
|
|
47286
|
-
const rawBleName = (
|
|
47289
|
+
const rawBleName = (_g = (_f = device.name) !== null && _f !== void 0 ? _f : device.localName) !== null && _g !== void 0 ? _g : '';
|
|
47287
47290
|
const bleName = hdShared.canonicalizePro2BleAdvertisementName(rawBleName);
|
|
47288
47291
|
devices.push(Object.assign(Object.assign({}, device), { connectId: device.id, serialNo: null, uuid: '', deviceId: null, name: bleName || device.name, deviceType: getDeviceTypeByBleName(bleName) }));
|
|
47289
47292
|
}
|
|
47290
47293
|
}
|
|
47291
47294
|
return devices;
|
|
47292
47295
|
}
|
|
47296
|
+
if (useCachedWebUsbDevices) {
|
|
47297
|
+
return devicesDescriptor.flatMap(descriptor => {
|
|
47298
|
+
const device = DevicePool.getDeviceByPath(descriptor.path);
|
|
47299
|
+
return (device === null || device === void 0 ? void 0 : device.features) ? [device.toMessageObject()] : [];
|
|
47300
|
+
});
|
|
47301
|
+
}
|
|
47293
47302
|
const deviceList = [];
|
|
47294
47303
|
for (const descriptor of devicesDescriptor) {
|
|
47295
47304
|
try {
|
|
@@ -65850,7 +65859,7 @@ const createUiProgressMessageFilter = (intervalMs = DEFAULT_UI_PROGRESS_INTERVAL
|
|
|
65850
65859
|
|
|
65851
65860
|
const Log = getLogger(exports.LoggerNames.Core);
|
|
65852
65861
|
const PRE_INITIALIZE_TTL_MS = 60 * 1000;
|
|
65853
|
-
const PRE_PENDING_CALL_TIMEOUT_MS =
|
|
65862
|
+
const PRE_PENDING_CALL_TIMEOUT_MS = 5 * 1000;
|
|
65854
65863
|
const PRO2_USB_SIGNING_COOLDOWN_MS = 1000;
|
|
65855
65864
|
const preWarmInflight = new Map();
|
|
65856
65865
|
const preWarmDoneAt = new Map();
|
|
@@ -65930,6 +65939,7 @@ const callAPI = (context, message) => __awaiter(void 0, void 0, void 0, function
|
|
|
65930
65939
|
}
|
|
65931
65940
|
};
|
|
65932
65941
|
(_a = method.setContext) === null || _a === void 0 ? void 0 : _a.call(method, context);
|
|
65942
|
+
method.context = context;
|
|
65933
65943
|
method.requestContext = createRequestContext(method.responseID, method.name, {
|
|
65934
65944
|
sdkInstanceId: context.sdkInstanceId,
|
|
65935
65945
|
connectId: method.connectId,
|
|
@@ -65947,7 +65957,11 @@ const callAPI = (context, message) => __awaiter(void 0, void 0, void 0, function
|
|
|
65947
65957
|
if (!method.useDevice) {
|
|
65948
65958
|
updateMethodRequestContext(method, { status: 'running' });
|
|
65949
65959
|
try {
|
|
65950
|
-
const
|
|
65960
|
+
const env = DataManager.getSettings('env');
|
|
65961
|
+
const response = method.name === 'searchDevices' &&
|
|
65962
|
+
(DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env))
|
|
65963
|
+
? yield context.methodSynchronize(() => method.run(), 'webusb-discovery')
|
|
65964
|
+
: yield method.run();
|
|
65951
65965
|
completeMethodRequestContext(method);
|
|
65952
65966
|
return createResponseMessage(method.responseID, true, response);
|
|
65953
65967
|
}
|
|
@@ -66018,20 +66032,25 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
|
|
|
66018
66032
|
if (pendingPromise) {
|
|
66019
66033
|
Log.debug('pre pending call promise before call method, wait for it');
|
|
66020
66034
|
let timer;
|
|
66035
|
+
let timedOut = false;
|
|
66021
66036
|
try {
|
|
66022
66037
|
yield Promise.race([
|
|
66023
66038
|
pendingPromise,
|
|
66024
|
-
new Promise(
|
|
66039
|
+
new Promise(resolve => {
|
|
66025
66040
|
timer = setTimeout(() => {
|
|
66026
|
-
|
|
66041
|
+
timedOut = true;
|
|
66042
|
+
resolve();
|
|
66027
66043
|
}, PRE_PENDING_CALL_TIMEOUT_MS);
|
|
66028
66044
|
}),
|
|
66029
66045
|
]);
|
|
66030
|
-
removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
|
|
66031
66046
|
}
|
|
66032
66047
|
finally {
|
|
66033
66048
|
if (timer)
|
|
66034
66049
|
clearTimeout(timer);
|
|
66050
|
+
removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
|
|
66051
|
+
}
|
|
66052
|
+
if (timedOut) {
|
|
66053
|
+
Log.warn('pre pending call promise timed out before call method', { connectId });
|
|
66035
66054
|
}
|
|
66036
66055
|
Log.debug('pre pending call promise before call method done');
|
|
66037
66056
|
}
|
|
@@ -66079,7 +66098,12 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
|
|
|
66079
66098
|
context.registerCallbackTask(method.connectId, preWarmCallbackTask);
|
|
66080
66099
|
}
|
|
66081
66100
|
const pollingId = pollingManager.start(connectId);
|
|
66082
|
-
|
|
66101
|
+
const env = DataManager.getSettings('env');
|
|
66102
|
+
const connect = () => ensureConnected(context, method, connectId, pollingId, method.abortSignal);
|
|
66103
|
+
device =
|
|
66104
|
+
DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env)
|
|
66105
|
+
? yield requestQueue.waitForTask(task, () => context.methodSynchronize(connect, 'webusb-discovery'))
|
|
66106
|
+
: yield connect();
|
|
66083
66107
|
if ((_e = method.abortSignal) === null || _e === void 0 ? void 0 : _e.aborted) {
|
|
66084
66108
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
|
|
66085
66109
|
}
|
|
@@ -66667,6 +66691,15 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
|
|
|
66667
66691
|
if (error.errorCode === hdShared.HardwareErrorCode.TransportNotConfigured) {
|
|
66668
66692
|
yield TransportManager.configure();
|
|
66669
66693
|
}
|
|
66694
|
+
else {
|
|
66695
|
+
const env = DataManager.getSettings('env');
|
|
66696
|
+
if (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env)) {
|
|
66697
|
+
if (timer)
|
|
66698
|
+
clearTimeout(timer);
|
|
66699
|
+
reject(error);
|
|
66700
|
+
return;
|
|
66701
|
+
}
|
|
66702
|
+
}
|
|
66670
66703
|
}
|
|
66671
66704
|
if (abort()) {
|
|
66672
66705
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.2-alpha.
|
|
3
|
+
"version": "1.2.2-alpha.113",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.2-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.2-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.113",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.2-alpha.113",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
47
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "32601b82b280b9ec97161cb4206a15cf9cd72881"
|
|
50
50
|
}
|
package/src/api/SearchDevices.ts
CHANGED
|
@@ -20,12 +20,16 @@ export default class SearchDevices extends BaseMethod {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async run() {
|
|
23
|
-
|
|
23
|
+
const env = DataManager.getSettings('env');
|
|
24
|
+
const useCachedWebUsbDevices =
|
|
25
|
+
(env === 'webusb' || env === 'desktop-webusb') &&
|
|
26
|
+
(this.context?.requestQueue.getRequestTasksId().length ?? 0) > 0;
|
|
27
|
+
// Core serializes WebUSB discovery with connection setup. A registered
|
|
28
|
+
// business request owns the connection, including its initialization phase.
|
|
29
|
+
if (!useCachedWebUsbDevices) await TransportManager.configure();
|
|
24
30
|
const deviceDiff = await this.connector?.enumerate();
|
|
25
31
|
const devicesDescriptor = deviceDiff?.descriptors ?? [];
|
|
26
32
|
|
|
27
|
-
const env = DataManager.getSettings('env');
|
|
28
|
-
|
|
29
33
|
/**
|
|
30
34
|
* No need to call features during Bluetooth scaning
|
|
31
35
|
* to avoid device pairing
|
|
@@ -56,6 +60,13 @@ export default class SearchDevices extends BaseMethod {
|
|
|
56
60
|
return devices;
|
|
57
61
|
}
|
|
58
62
|
|
|
63
|
+
if (useCachedWebUsbDevices) {
|
|
64
|
+
return devicesDescriptor.flatMap(descriptor => {
|
|
65
|
+
const device = DevicePool.getDeviceByPath(descriptor.path);
|
|
66
|
+
return device?.features ? [device.toMessageObject()] : [];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
59
70
|
const deviceList = [];
|
|
60
71
|
for (const descriptor of devicesDescriptor) {
|
|
61
72
|
try {
|
package/src/core/index.ts
CHANGED
|
@@ -84,7 +84,7 @@ import type { BaseMethod } from '../api/BaseMethod';
|
|
|
84
84
|
|
|
85
85
|
const Log = getLogger(LoggerNames.Core);
|
|
86
86
|
const PRE_INITIALIZE_TTL_MS = 60 * 1000;
|
|
87
|
-
const PRE_PENDING_CALL_TIMEOUT_MS =
|
|
87
|
+
const PRE_PENDING_CALL_TIMEOUT_MS = 5 * 1000;
|
|
88
88
|
const PRO2_USB_SIGNING_COOLDOWN_MS = 1000;
|
|
89
89
|
|
|
90
90
|
// Dedup/coalesce state for "pre-warm signal" methods (isPreWarmSignal),
|
|
@@ -183,6 +183,7 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
|
|
|
183
183
|
}
|
|
184
184
|
};
|
|
185
185
|
method.setContext?.(context);
|
|
186
|
+
method.context = context;
|
|
186
187
|
|
|
187
188
|
method.requestContext = createRequestContext(method.responseID, method.name, {
|
|
188
189
|
sdkInstanceId: context.sdkInstanceId,
|
|
@@ -203,7 +204,12 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
|
|
|
203
204
|
if (!method.useDevice) {
|
|
204
205
|
updateMethodRequestContext(method, { status: 'running' });
|
|
205
206
|
try {
|
|
206
|
-
const
|
|
207
|
+
const env = DataManager.getSettings('env');
|
|
208
|
+
const response =
|
|
209
|
+
method.name === 'searchDevices' &&
|
|
210
|
+
(DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env))
|
|
211
|
+
? await context.methodSynchronize(() => method.run(), 'webusb-discovery')
|
|
212
|
+
: await method.run();
|
|
207
213
|
completeMethodRequestContext(method);
|
|
208
214
|
return createResponseMessage(method.responseID, true, response);
|
|
209
215
|
} catch (error) {
|
|
@@ -315,25 +321,25 @@ const waitForPendingPromise = async (
|
|
|
315
321
|
if (pendingPromise) {
|
|
316
322
|
Log.debug('pre pending call promise before call method, wait for it');
|
|
317
323
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
324
|
+
let timedOut = false;
|
|
318
325
|
try {
|
|
319
326
|
await Promise.race([
|
|
320
327
|
pendingPromise,
|
|
321
|
-
new Promise<void>(
|
|
328
|
+
new Promise<void>(resolve => {
|
|
322
329
|
timer = setTimeout(() => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
HardwareErrorCode.DeviceBusy,
|
|
326
|
-
'Previous device cancellation is still draining'
|
|
327
|
-
)
|
|
328
|
-
);
|
|
330
|
+
timedOut = true;
|
|
331
|
+
resolve();
|
|
329
332
|
}, PRE_PENDING_CALL_TIMEOUT_MS);
|
|
330
333
|
}),
|
|
331
334
|
]);
|
|
332
|
-
// A deadline is not evidence that old I/O is safe to reuse. Keep the
|
|
333
|
-
// barrier on failure; a later call may proceed only after cleanup settles.
|
|
334
|
-
removePrePendingCallPromise?.(connectId, pendingPromise);
|
|
335
335
|
} finally {
|
|
336
336
|
if (timer) clearTimeout(timer);
|
|
337
|
+
// Match the legacy behavior: a stuck cleanup must not permanently poison
|
|
338
|
+
// this connectId. The next request will reacquire the device if needed.
|
|
339
|
+
removePrePendingCallPromise?.(connectId, pendingPromise);
|
|
340
|
+
}
|
|
341
|
+
if (timedOut) {
|
|
342
|
+
Log.warn('pre pending call promise timed out before call method', { connectId });
|
|
337
343
|
}
|
|
338
344
|
Log.debug('pre pending call promise before call method done');
|
|
339
345
|
}
|
|
@@ -411,7 +417,17 @@ const onCallDevice = async (
|
|
|
411
417
|
* Polling to ensure successful connection
|
|
412
418
|
*/
|
|
413
419
|
const pollingId = pollingManager.start(connectId);
|
|
414
|
-
|
|
420
|
+
const env = DataManager.getSettings('env');
|
|
421
|
+
const connect = () =>
|
|
422
|
+
ensureConnected(context, method, connectId, pollingId, method.abortSignal);
|
|
423
|
+
// Discovery may acquire USB endpoints. Finish it before initializing a public
|
|
424
|
+
// request; once registered, that request makes discovery use cached state only.
|
|
425
|
+
device =
|
|
426
|
+
DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env)
|
|
427
|
+
? await requestQueue.waitForTask(task, () =>
|
|
428
|
+
context.methodSynchronize(connect, 'webusb-discovery')
|
|
429
|
+
)
|
|
430
|
+
: await connect();
|
|
415
431
|
if (method.abortSignal?.aborted) {
|
|
416
432
|
throw ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled);
|
|
417
433
|
}
|
|
@@ -1255,6 +1271,15 @@ const ensureConnected = async (
|
|
|
1255
1271
|
}
|
|
1256
1272
|
if (error.errorCode === HardwareErrorCode.TransportNotConfigured) {
|
|
1257
1273
|
await TransportManager.configure();
|
|
1274
|
+
} else {
|
|
1275
|
+
const env = DataManager.getSettings('env');
|
|
1276
|
+
if (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env)) {
|
|
1277
|
+
// Enumeration succeeded far enough to attempt initialization. Do not
|
|
1278
|
+
// replace its failure with a lookup against the now-empty DeviceList.
|
|
1279
|
+
if (timer) clearTimeout(timer);
|
|
1280
|
+
reject(error);
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1258
1283
|
}
|
|
1259
1284
|
}
|
|
1260
1285
|
|