Skip to content

Commit 8f425c3

Browse files
committed
Fix some sonar issues
1 parent b202a7a commit 8f425c3

File tree

3 files changed

+66
-66
lines changed

3 files changed

+66
-66
lines changed

src/js/port_handler.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ PortHandler.initialize = function () {
6363
// Use serial for all protocol events
6464
serial.addEventListener("addedDevice", (event) => {
6565
const detail = event.detail;
66-
const proto = (detail?.protocolType || "").toLowerCase();
66+
const protocol = (detail?.protocolType || "").toLowerCase();
6767

68-
if (detail?.path?.startsWith("bluetooth") || proto === "webbluetooth") {
68+
if (detail?.path?.startsWith("bluetooth") || protocol === "webbluetooth") {
6969
this.handleDeviceAdded(detail, "webbluetooth");
70-
} else if (proto === "tauriserial") {
70+
} else if (protocol === "tauriserial") {
7171
this.handleDeviceAdded(detail, "tauriserial");
7272
} else {
7373
this.handleDeviceAdded(detail, "webserial");
7474
}
75-
console.log(`${this.logHead} #### Device addition event received:`, event.detail, proto);
75+
console.log(`${this.logHead} #### Device addition event received:`, event.detail, protocol);
7676
});
7777

7878
serial.addEventListener("removedDevice", (event) => {
@@ -117,7 +117,7 @@ PortHandler.removedSerialDevice = function (device) {
117117

118118
// Get device path safely
119119
const devicePath = device?.path || (typeof device === "string" ? device : null);
120-
const proto = (device?.protocolType || "").toLowerCase();
120+
const protocol = (device?.protocolType || "").toLowerCase();
121121

122122
if (!devicePath) {
123123
console.warn(`${this.logHead} Device removal event missing path information`, device);
@@ -131,7 +131,7 @@ PortHandler.removedSerialDevice = function (device) {
131131
// Update the appropriate ports list based on the device type
132132
const updatePromise = devicePath.startsWith("bluetooth")
133133
? this.updateDeviceList("webbluetooth")
134-
: this.updateDeviceList(proto === "tauriserial" ? "tauriserial" : "webserial");
134+
: this.updateDeviceList(protocol === "tauriserial" ? "tauriserial" : "webserial");
135135

136136
const wasSelectedPort = this.portPicker.selectedPort === devicePath;
137137

src/js/protocols/TauriSerial.js

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,7 @@ function isBrokenPipeError(error) {
1111
return /broken pipe|EPIPE|os error 32|code:\s*32/i.test(s);
1212
}
1313

14-
/**
15-
* Async generator that polls the serial port for incoming data
16-
* Similar to streamAsyncIterable in WebSerial but uses polling instead of streams
17-
*/
18-
async function* pollSerialData(path, keepReadingFlag) {
19-
try {
20-
while (keepReadingFlag()) {
21-
try {
22-
// Non-blocking read with short timeout
23-
const result = await invoke("plugin:serialplugin|read_binary", {
24-
path,
25-
size: 256,
26-
timeout: 10,
27-
});
28-
29-
if (result && result.length > 0) {
30-
yield new Uint8Array(result);
31-
}
32-
33-
// Small delay between polls to avoid overwhelming the system
34-
await new Promise((resolve) => setTimeout(resolve, 5));
35-
} catch (error) {
36-
const msg = error?.message || (error?.toString ? error.toString() : "");
37-
// Timeout is expected when no data available
38-
if (msg && msg.toLowerCase().includes("no data received")) {
39-
// Continue polling
40-
await new Promise((resolve) => setTimeout(resolve, 5));
41-
continue;
42-
}
43-
if (isBrokenPipeError(msg)) {
44-
console.error(`${logHead} Fatal poll error (broken pipe) on ${path}:`, error);
45-
throw error;
46-
}
47-
console.warn(`${logHead} Poll error:`, error);
48-
// Continue polling
49-
await new Promise((resolve) => setTimeout(resolve, 5));
50-
}
51-
}
52-
} finally {
53-
console.log(`${logHead} Polling stopped for ${path}`);
54-
}
55-
}
14+
// Note: We avoid async generator + for-await-of to improve compatibility in some runtimes.
5615

5716
/**
5817
* TauriSerial protocol implementation using tauri-plugin-serialplugin
@@ -141,10 +100,10 @@ class TauriSerial extends EventTarget {
141100
let productId = undefined;
142101

143102
if (info.vid) {
144-
vendorId = typeof info.vid === "number" ? info.vid : parseInt(info.vid, 10);
103+
vendorId = typeof info.vid === "number" ? info.vid : Number.parseInt(info.vid, 10);
145104
}
146105
if (info.pid) {
147-
productId = typeof info.pid === "number" ? info.pid : parseInt(info.pid, 10);
106+
productId = typeof info.pid === "number" ? info.pid : Number.parseInt(info.pid, 10);
148107
}
149108

150109
return {
@@ -204,10 +163,10 @@ class TauriSerial extends EventTarget {
204163
let productId = undefined;
205164

206165
if (info.vid) {
207-
vendorId = typeof info.vid === "number" ? info.vid : parseInt(info.vid, 10);
166+
vendorId = typeof info.vid === "number" ? info.vid : Number.parseInt(info.vid, 10);
208167
}
209168
if (info.pid) {
210-
productId = typeof info.pid === "number" ? info.pid : parseInt(info.pid, 10);
169+
productId = typeof info.pid === "number" ? info.pid : Number.parseInt(info.pid, 10);
211170
}
212171

213172
return {
@@ -309,12 +268,41 @@ class TauriSerial extends EventTarget {
309268

310269
async readLoop() {
311270
try {
312-
for await (let value of pollSerialData(this.connectionId, () => this.reading)) {
313-
this.dispatchEvent(new CustomEvent("receive", { detail: value }));
271+
while (this.reading) {
272+
try {
273+
// Non-blocking read with short timeout
274+
const result = await invoke("plugin:serialplugin|read_binary", {
275+
path: this.connectionId,
276+
size: 256,
277+
timeout: 10,
278+
});
279+
280+
if (result && result.length > 0) {
281+
this.dispatchEvent(new CustomEvent("receive", { detail: new Uint8Array(result) }));
282+
}
283+
284+
// Small delay between polls to avoid overwhelming the system
285+
await new Promise((resolve) => setTimeout(resolve, 5));
286+
} catch (error) {
287+
const msg = error?.message || (error?.toString ? error.toString() : "");
288+
// Timeout is expected when no data available
289+
if (msg && msg.toLowerCase().includes("no data received")) {
290+
await new Promise((resolve) => setTimeout(resolve, 5));
291+
continue;
292+
}
293+
if (isBrokenPipeError(msg)) {
294+
console.error(`${logHead} Fatal poll error (broken pipe) on ${this.connectionId}:`, error);
295+
throw error;
296+
}
297+
console.warn(`${logHead} Poll error:`, error);
298+
await new Promise((resolve) => setTimeout(resolve, 5));
299+
}
314300
}
315301
} catch (error) {
316302
console.error(`${logHead} Error in read loop:`, error);
317303
this.handleFatalSerialError(error);
304+
} finally {
305+
console.log(`${logHead} Polling stopped for ${this.connectionId || "<no-port>"}`);
318306
}
319307
}
320308

src/js/serial.js

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,24 @@ class Serial extends EventTarget {
2626

2727
// Forward events from current protocols
2828
this._setupEventForwarding();
29+
}
2930

31+
/**
32+
* Perform any asynchronous initialization required by the Serial facade.
33+
* This keeps constructors synchronous and predictable.
34+
*/
35+
async init() {
3036
// Dynamically include the native Tauri serial adapter so web builds don't try to resolve it.
3137
if (isTauri) {
32-
import("./protocols/TauriSerial.js")
33-
.then(({ default: TauriSerial }) => {
34-
const inst = new TauriSerial();
35-
this._protocols.unshift({ name: "tauriserial", instance: inst });
36-
// Wire event forwarding for this late-added protocol
37-
this._setupEventForwardingFor("tauriserial", inst);
38-
})
39-
.catch((err) => {
40-
console.warn(`${this.logHead} Failed to load TauriSerial adapter:`, err);
41-
});
38+
try {
39+
const { default: TauriSerial } = await import("./protocols/TauriSerial.js");
40+
const inst = new TauriSerial();
41+
this._protocols.unshift({ name: "tauriserial", instance: inst });
42+
// Wire event forwarding for this late-added protocol
43+
this._setupEventForwardingFor("tauriserial", inst);
44+
} catch (err) {
45+
console.warn(`${this.logHead} Failed to load TauriSerial adapter:`, err);
46+
}
4247
}
4348
}
4449

@@ -58,7 +63,9 @@ class Serial extends EventTarget {
5863
instance,
5964
events = ["addedDevice", "removedDevice", "connect", "disconnect", "receive"],
6065
) {
61-
if (typeof instance?.addEventListener !== "function") return;
66+
if (typeof instance?.addEventListener !== "function") {
67+
return;
68+
}
6269
for (const eventType of events) {
6370
instance.addEventListener(eventType, (event) => {
6471
let newDetail;
@@ -105,7 +112,9 @@ class Serial extends EventTarget {
105112
}
106113
// Prefer Tauri plugin if present
107114
const tauriInst = this._protocols.find((p) => p.name === "tauriserial")?.instance;
108-
if (tauriInst) return tauriInst;
115+
if (tauriInst) {
116+
return tauriInst;
117+
}
109118
return this._protocols.find((p) => p.name === "webserial")?.instance;
110119
}
111120

@@ -236,3 +245,6 @@ class Serial extends EventTarget {
236245

237246
// Export a singleton instance
238247
export const serial = new Serial();
248+
// Kick off async initialization outside of the constructor.
249+
// Intentionally not awaited to avoid blocking module load.
250+
void serial.init();

0 commit comments

Comments
 (0)