(channel, ...args)
| 255 | dialog.appendChild(titleEl); |
| 256 | dialog.appendChild(messageEl); |
| 257 | dialog.appendChild(buttonRow); |
| 258 | |
| 259 | const styleTag = document.createElement('style'); |
| 260 | styleTag.textContent = ` |
| 261 | #${dialogId}::backdrop { |
| 262 | background: rgba(0, 0, 0, 0.5); |
| 263 | } |
| 264 | `; |
| 265 | |
| 266 | document.body.appendChild(styleTag); |
| 267 | document.body.appendChild(dialog); |
| 268 | dialog.showModal(); |
| 269 | }); |
| 270 | } |
| 271 | |
| 272 | function connect() { |
| 273 | try { |
| 274 | // Avoid stacking sockets: concurrent makeIpcCall used to overwrite `ws` while CONNECTING, |
| 275 | // which produced "connected" logs with readyState 0 and spurious "connection failed" errors. |
| 276 | if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) { |
| 277 | return; |
| 278 | } |
| 279 | if (connectInFlight) { |
| 280 | return; |
| 281 | } |
| 282 | connectInFlight = true; |
| 283 | console.log('[Bridge] Attempting WebSocket connection to:', wsUrl); |
| 284 | ws = new WebSocket(wsUrl); |
| 285 | const socket = ws; |
| 286 | |
| 287 | socket.onopen = () => { |
| 288 | if (ws !== socket) { |
| 289 | // Stale socket; a newer connect() replaced us. |
| 290 | try { socket.close(); } catch (e) { /* ignore */ } |
| 291 | return; |
| 292 | } |
| 293 | markConnected(socket); |
| 294 | }; |
| 295 | |
| 296 | socket.onmessage = (event) => { |
| 297 | if (BRIDGE_DEBUG) { |
| 298 | console.log('[Bridge] Received WebSocket message:', String(event.data).substring(0, 200)); |
| 299 | } |
| 300 | try { |
| 301 | const data = JSON.parse(event.data); |
| 302 | |
| 303 | if (data.type === 'result') { |
| 304 | const pending = pendingRequests.get(data.id); |
| 305 | if (pending) { |
no test coverage detected