Skip to content

add net module: tcp sockets via libuv (prereq for pure-ts postgres driver)#585

Open
cs01 wants to merge 3 commits intomainfrom
feat/net-module-tcp
Open

add net module: tcp sockets via libuv (prereq for pure-ts postgres driver)#585
cs01 wants to merge 3 commits intomainfrom
feat/net-module-tcp

Conversation

@cs01
Copy link
Copy Markdown
Owner

@cs01 cs01 commented Apr 20, 2026

Summary

Adds a net module exposing raw TCP sockets via libuv. Prerequisite for a pure-TypeScript Postgres driver (and any future protocol implementation — Redis, MongoDB, etc).

Built by an agent in worktree isolation off origin/main. Smoke test passes on macOS arm64.

What's in it

  • c_bridges/net-bridge.c (401 LOC) — libuv-backed TCP bridge: cs_net_connect, cs_socket_write/end/destroy, cs_socket_poll/wait, event kind/data/len/consume accessors. GC-aware, no trampolines.
  • lib/net.ts (225 LOC) — Socket class with on('connect' | 'data' | 'error' | 'close', cb), write(buf: Buffer), end(), destroy(), removeDataListener(cb). Exposes createConnection(host, port).
  • Build + CI wiring:
    • scripts/build-vendor.sh — builds net-bridge.o after child-process-spawn
    • src/compiler.ts + src/native-compiler-lib.tsusesNet detection (scans declaredExternFunctions for cs_net_* prefix, mirrors usesPostgres), conditional linking of net-bridge.o + -luv
    • .github/workflows/ci.ymlnet-bridge.o added to release tarball packaging + verify-lib-contents list
  • tests/fixtures/net/tcp-echo.ts — smoke test: createConnectioncs_net_connect → libuv connect → isOpen() / destroy() round-trip. Follows the // @test-passed fixture pattern.

Chad-subset friction points discovered

All documented in the "Known limits" block at the top of lib/net.ts. Four of these are real codegen bugs worth filing as separate issues:

  1. Function arrays unsupportedArray<(x: string) => void> emits "function-pointer arrays not yet supported". Forced a single-listener-per-event shape instead of the usual array-of-listeners pattern.
  2. Arrow-literal in class ctor body: codegen emits store i8* __lambda_N missing the @ sigil; clang rejects the IR. Worked around with a module-level _netNoopCb reference.
  3. Closures capture by value — outer-scope let flags mutated inside listeners aren't visible outside. Test had to signal via stdout sentinels instead of a captured flag.
  4. arr[i](args) call pattern — parser rejects as "Unsupported call expression: ElementAccessExpression".
  5. let x: Type; then later-assign — method resolution on x breaks ("Method 'on' on 'x' is not supported"). Worked around by inlining the createConnection call.
  6. NULL char* across the FFI boundary doesn't reliably compare === "". Dropped the throw-on-fail; callers use isOpen() instead.

Test plan

  • bash scripts/build-vendor.sh builds c_bridges/net-bridge.o
  • npm run build typechecks lib/net.ts
  • tests/fixtures/net/tcp-echo.ts compiles + runs + emits TEST_PASSED
  • CI green on Linux (build-linux-glibc) and macOS (build-macos)
  • verify-cross-compiled-binary finds net-bridge.o in the release tarball

Follow-ups (separate PRs)

…/end/destroy, on connect/data/error/close events). prereq for pure-ts postgres driver. smoke test passes (connect-refused path).
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 20, 2026

Benchmark Results (Linux x86-64)

Benchmark C ChadScript Go Node Place
Cold Start 0.9ms 0.8ms 1.2ms 26.7ms 🥇
Fibonacci 0.816s 0.763s 1.563s 3.160s 🥇
Hash Map Lookup 0.090s 0.063s 0.089s 0.112s 🥇
Binary Trees 1.348s 1.274s 2.703s 1.151s 🥈
File I/O 0.116s 0.090s 0.086s 0.200s 🥈
JSON Parse/Stringify 0.035s 0.051s 0.176s 0.132s 🥈
N-Body Simulation 1.666s 2.121s 2.210s 2.435s 🥈
Regex Match 0.016s 0.005s 0.022s 0.004s 🥈
SQLite 0.051s 0.365s 0.493s 0.415s 🥈
Monte Carlo Pi 0.389s 0.410s 0.405s 2.253s 🥉
Quicksort 0.215s 0.246s 0.213s 0.262s 🥉
Sieve of Eratosthenes 0.015s 0.027s 0.018s 0.039s 🥉
String Manipulation 0.008s 0.018s 0.017s 0.038s 🥉
Matrix Multiply 0.525s 1.000s 0.632s 0.369s #4

CLI Tool Benchmarks

Benchmark ChadScript grep node xxd Place
Hex Dump 0.560s 0.973s 0.131s 🥈
Recursive Grep 0.019s 0.010s 0.101s 🥈

cs01 added 2 commits April 20, 2026 09:47
… was failing because chad build couldn't resolve the chadscript/net import since registerStdlib call was missing. one-line fix in src/chad-native.ts.
… socket class + createConnection so user code + ide gets typechecked (was missing from the initial net-module commit, paired with the registerStdlib fix).
@cs01
Copy link
Copy Markdown
Owner Author

cs01 commented Apr 20, 2026

CI is blocked on a main-branch regression, not on this PR's code.

Bisected: #597 — the checkMissingReturns pass false-positives on transformExpression when chad-native.ts has 8+ registerStdlib calls. This PR adds the 8th (net.ts), tripping the regression for the first time. Introduced in #583.

Repro is deterministic: reduce registerStdlib calls in chad-native.ts to 7 → compile succeeds. Any 8th (regardless of content/order/key) → fails with transformExpression does not return.

Options:

I lean option 1. Pausing on pushing more commits to this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant