From 913403bef41a4616c54aebd737fcbab186b5b8e2 Mon Sep 17 00:00:00 2001 From: loucadufault <40028187+loucadufault@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:54:00 +0000 Subject: [PATCH 1/3] handle error events on xkeys that can be emitted during the init process before the instance is exposed for listener registration --- packages/webhid/src/methods.ts | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/webhid/src/methods.ts b/packages/webhid/src/methods.ts index 7a8be47..b45b00e 100644 --- a/packages/webhid/src/methods.ts +++ b/packages/webhid/src/methods.ts @@ -69,13 +69,28 @@ export async function setupXkeysPanel(browserDevice: HIDDevice): Promise }) }) - // Wait for the device to initialize: - try { - await xkeys.init() - - return xkeys - } catch (e) { - await deviceWrap.close() - throw e - } + let alreadyRejected = false + return new Promise((resolve, reject) => { + const xkeysStopgapErrorHandler = (e: unknown) => { + if (alreadyRejected) { + console.error(`Xkeys: Error emitted after setup already rejected:`, e) + return + } + deviceWrap.close() + .then(() => reject()) + .catch(reject) + .finally(() => (alreadyRejected = true)) + } + // Handle all error events until the instance is returned + xkeys.on('error', xkeysStopgapErrorHandler) + + // Wait for the device to initialize: + xkeys.init() + .then(() => { + resolve(xkeys) + xkeys.removeListener('error', xkeysStopgapErrorHandler) + }) + .catch(reject) + .finally(() => (alreadyRejected = true)) + }) } From faa35ef7f50ee0b43b35c7dc84fd7d42ee7d943c Mon Sep 17 00:00:00 2001 From: loucadufault <40028187+loucadufault@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:16:06 +0000 Subject: [PATCH 2/3] style: lint --- packages/webhid/src/methods.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/webhid/src/methods.ts b/packages/webhid/src/methods.ts index b45b00e..a96d3e5 100644 --- a/packages/webhid/src/methods.ts +++ b/packages/webhid/src/methods.ts @@ -76,16 +76,18 @@ export async function setupXkeysPanel(browserDevice: HIDDevice): Promise console.error(`Xkeys: Error emitted after setup already rejected:`, e) return } - deviceWrap.close() + deviceWrap + .close() .then(() => reject()) .catch(reject) .finally(() => (alreadyRejected = true)) } - // Handle all error events until the instance is returned + // Handle all error events until the instance is returned xkeys.on('error', xkeysStopgapErrorHandler) - + // Wait for the device to initialize: - xkeys.init() + xkeys + .init() .then(() => { resolve(xkeys) xkeys.removeListener('error', xkeysStopgapErrorHandler) From 494f579985d1a3cc2cea982d4e2c07f1d198cfe4 Mon Sep 17 00:00:00 2001 From: loucadufault <40028187+loucadufault@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:44:26 +0000 Subject: [PATCH 3/3] revise implementation to simplify promise executor --- packages/webhid/src/methods.ts | 56 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/packages/webhid/src/methods.ts b/packages/webhid/src/methods.ts index a96d3e5..26a9d24 100644 --- a/packages/webhid/src/methods.ts +++ b/packages/webhid/src/methods.ts @@ -70,29 +70,37 @@ export async function setupXkeysPanel(browserDevice: HIDDevice): Promise }) let alreadyRejected = false - return new Promise((resolve, reject) => { - const xkeysStopgapErrorHandler = (e: unknown) => { - if (alreadyRejected) { - console.error(`Xkeys: Error emitted after setup already rejected:`, e) - return + try { + await new Promise((resolve, reject) => { + const markRejected = (e: unknown) => { + reject(e) + alreadyRejected = true } - deviceWrap - .close() - .then(() => reject()) - .catch(reject) - .finally(() => (alreadyRejected = true)) - } - // Handle all error events until the instance is returned - xkeys.on('error', xkeysStopgapErrorHandler) - - // Wait for the device to initialize: - xkeys - .init() - .then(() => { - resolve(xkeys) - xkeys.removeListener('error', xkeysStopgapErrorHandler) - }) - .catch(reject) - .finally(() => (alreadyRejected = true)) - }) + const xkeysStopgapErrorHandler = (e: unknown) => { + if (alreadyRejected) { + console.error(`Xkeys: Error emitted after setup already rejected:`, e) + return + } + + markRejected(e) + } + + // Handle all error events until the instance is returned + xkeys.on('error', xkeysStopgapErrorHandler) + + // Wait for the device to initialize: + xkeys + .init() + .then(() => { + resolve() + xkeys.removeListener('error', xkeysStopgapErrorHandler) + }) + .catch(markRejected) + }) + + return xkeys + } catch (e) { + await deviceWrap.close() + throw e + } }