Commitaee36189Recorded6 May 2026Repositorysigil-websocket

Add WASM WebSocket bridge branch

Message

Add sigil-wasm-net as a dependency and make the connection module select a browser/WASM path with cond-expand. The WASM branch imports (sigil wasm net) and opens browser WebSocket handles while preserving the existing TCP/TLS implementation for native builds.

Verification: XDGCACHEHOME=/tmp/sigil-cache SIGIL_FEATURES=wasm /home/daviwil/Projects/Code/sigil/sigil/build/dev/bin/sigil -L /home/daviwil/Projects/Code/sigil/sigil/build/web/lib -L /home/daviwil/Projects/Code/sigil/sigil-websocket/src eval '(import (sigil websocket connection)) (display "ok") (newline)'; native eval tests 9/9 and 14/14.

Changed
 dev-redirects.sgl                  |   3 +++
 package.sgl                        |   1 +
 src/sigil/websocket/connection.sgl | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------
 3 files changed, 82 insertions(+), 45 deletions(-)
Diff
dev-redirects.sglmodified
@@ -1,6 +1,9 @@
1
;; Development redirects — point dependencies at local sibling checkouts.
2
(redirects
3
repos: (list
+4
(for-repo
+5
url: "codeberg:sigil/sigil"
+6
use: (from-path dir: "../sigil"))
7
(for-repo
8
url: "codeberg:sigil/sigil-lang"
9
use: (from-path dir: "../sigil-lang"))
package.sglmodified
@@ -29,6 +29,7 @@
29
30
dependencies: (list
31
(from-git url: "codeberg:sigil/sigil" package: "sigil-stdlib" version: "^0.15")
+32
(from-git url: "codeberg:sigil/sigil" package: "sigil-wasm-net" version: "^0.15")
33
(from-git url: "codeberg:sigil/sigil-socket" version: "^0.14.0")
34
(from-git url: "codeberg:sigil/sigil-tls" version: "^0.14.1")
35
(from-git url: "codeberg:sigil/sigil-crypto" version: "^0.15.0"))
src/sigil/websocket/connection.sglmodified
@@ -13,6 +13,10 @@
13
(sigil crypto)
14
(sigil async)
15
(sigil websocket frame))
+16
(cond-expand
+17
(wasm
+18
(import (sigil wasm net)))
+19
(else))
20
21
(export
22
;; Connection record
@@ -197,9 +201,13 @@
201
202
;;; Write to socket (handles both TCP and TLS)
203
(define (conn-write sock data)
200
(if (tls-connection? sock)
201
(tls-write sock data)
202
(socket-write sock data)))
+204
(cond-expand
+205
(wasm
+206
(wasm-websocket-send sock data))
+207
(else
+208
(if (tls-connection? sock)
+209
(tls-write sock data)
+210
(socket-write sock data)))))
211
212
;;; Read from socket (handles both TCP and TLS).
213
;;;
@@ -210,21 +218,33 @@
218
;;; particular). TLS still goes through `tls-read` which handles
219
;;; raw bytes natively.
220
(define (conn-read sock max-bytes)
213
(if (tls-connection? sock)
214
(tls-read sock max-bytes)
215
(socket-read-bytevector sock max-bytes)))
+221
(cond-expand
+222
(wasm
+223
(wasm-websocket-receive sock))
+224
(else
+225
(if (tls-connection? sock)
+226
(tls-read sock max-bytes)
+227
(socket-read-bytevector sock max-bytes)))))
228
229
;;; Close socket (handles both TCP and TLS)
230
(define (conn-close sock)
219
(if (tls-connection? sock)
220
(tls-close sock)
221
(socket-close sock)))
+231
(cond-expand
+232
(wasm
+233
(wasm-websocket-close sock 1000 ""))
+234
(else
+235
(if (tls-connection? sock)
+236
(tls-close sock)
+237
(socket-close sock)))))
238
239
;;; Set socket to non-blocking mode (handles both TCP and TLS)
240
(define (conn-set-non-blocking! sock enable)
225
(if (tls-connection? sock)
226
(tls-set-non-blocking! sock enable)
227
(socket-set-non-blocking! sock enable)))
+241
(cond-expand
+242
(wasm
+243
#t)
+244
(else
+245
(if (tls-connection? sock)
+246
(tls-set-non-blocking! sock enable)
+247
(socket-set-non-blocking! sock enable)))))
248
249
;; ============================================================
250
;; Public API
@@ -238,39 +258,52 @@
258
(let ((parsed (parse-ws-url url)))
259
(if (not parsed)
260
#f
241
(let* ((scheme (car parsed))
242
(host (cadr parsed))
243
(port (caddr parsed))
244
(path (cadddr parsed))
245
;; Connect using TLS for wss://
246
(socket (if (string=? scheme "wss")
247
(tls-connect host port)
248
(tcp-connect host port))))
249
(if (not socket)
250
#f
251
(let* ((conn (ws-connection
252
socket: socket
253
state: 'connecting
254
url: url
255
host: host
256
buffer: (make-bytevector 0)
257
fragments: '()))
258
(key (generate-ws-key))
259
(expected-accept (calculate-accept-key key))
260
(request (build-handshake-request host path key)))
261
;; Send handshake request
262
(conn-write socket request)
263
;; Validate response
264
(if (validate-handshake conn expected-accept)
265
(begin
266
(set-ws-connection-state! conn 'open)
267
;; Set to non-blocking for async I/O when in scheduler
268
(when (current-scheduler)
269
(conn-set-non-blocking! socket #t))
270
conn)
271
(begin
272
(conn-close socket)
273
#f))))))))
+261
(cond-expand
+262
(wasm
+263
(let* ((host (cadr parsed))
+264
(socket (wasm-websocket-open url "")))
+265
(and socket
+266
(ws-connection
+267
socket: socket
+268
state: 'open
+269
url: url
+270
host: host
+271
buffer: (make-bytevector 0)
+272
fragments: '()))))
+273
(else
+274
(let* ((scheme (car parsed))
+275
(host (cadr parsed))
+276
(port (caddr parsed))
+277
(path (cadddr parsed))
+278
;; Connect using TLS for wss://
+279
(socket (if (string=? scheme "wss")
+280
(tls-connect host port)
+281
(tcp-connect host port))))
+282
(if (not socket)
+283
#f
+284
(let* ((conn (ws-connection
+285
socket: socket
+286
state: 'connecting
+287
url: url
+288
host: host
+289
buffer: (make-bytevector 0)
+290
fragments: '()))
+291
(key (generate-ws-key))
+292
(expected-accept (calculate-accept-key key))
+293
(request (build-handshake-request host path key)))
+294
;; Send handshake request
+295
(conn-write socket request)
+296
;; Validate response
+297
(if (validate-handshake conn expected-accept)
+298
(begin
+299
(set-ws-connection-state! conn 'open)
+300
;; Set to non-blocking for async I/O when in scheduler
+301
(when (current-scheduler)
+302
(conn-set-non-blocking! socket #t))
+303
conn)
+304
(begin
+305
(conn-close socket)
+306
#f))))))))))
307
308
;;; Check if connection is open
309
(define (ws-connected? conn)