v0.2.0
0.2.0 (2026-05-01)
gjsify v0.2.0 is the most comprehensive release to date and marks a major milestone on the road to full Node.js compatibility on GJS.
The @gjsify/fs module is now nearly complete: four consecutive PRs landed cp, opendir, glob, watchFile, statfs, utimes, lchown, FileHandle, and an AsyncIterableIterator-based fs.promises.watch() stream. The WebSocket server implementation is equally complete — with verifyClient, handleProtocols, noServer/handleUpgrade, permessage-deflate, and full Autobahn testsuite coverage. socket.io now runs 20/20 tests on GJS, a direct result of root-cause fixes across events, fetch, http, and stream.
New additions include: MCP support (Model Context Protocol) with server, client, and Streamable HTTP examples; the first phases of ts-for-gir integration, making @ts-for-gir/cli run fully on GJS for the first time; a new framework pillar with @gjsify/adw-app; GstHTMLVideoElement for GStreamer-backed video playback; and Playwright-based browser tests for Web/DOM packages.
On the performance side, per-frame GC allocations in the WebGL stack and the Excalibur demo have been significantly reduced.
Features
- @gjsify/fetch + integration: axios integration suite + double-decompression fix (#54) (a09bf9b)
- @gjsify/fs: add fs.promises.watch() as AsyncIterableIterator (#51) (f2ef61d)
- @gjsify/fs: add watchFile/unwatchFile and statfsSync/statfs/promises.statfs (#52) (5fe86ed)
- @gjsify/fs: complete fs — utimes/lutimes/lchown/lchmod, all fd-ops, FileHandle stubs (#53) (2908669)
- @gjsify/fs: implement cp, Dir/opendir, and globSync/glob/promises.glob (#50) (4975f89)
- @gjsify/v8: promote Stub → Partial with real heap stats and V8 wire-format serdes (#54) (e9e92fe)
- deps: add @gjsify/crypto workspace dependency (8f03007)
- example/cli-axios-http-client: rewrite around jsonplaceholder.typicode.com (real HTTPS) (ce9a512)
- examples: add MCP server and client examples (61336ef)
- examples: add SQLite todo store cross-validated on GJS and Node.js (6803555)
- examples: socket.io ping-pong + chat-server examples + fix zlib TS errors (26d9553)
- framework: new packages/framework pillar + @gjsify/adw-app (252386a)
- http-soup-bridge: new Vala bridge package wrapping Soup.Server (eea4862)
- http2: implement Soup 3.0-backed compat + session API (Phase 1) (a271401)
- http2: update yarn.lock with new @girs dependencies for compatibility (e4a31ce)
- integration/mcp: add Streamable HTTP transport tests (73dd84b)
- integration/ts-for-gir: @ts-for-gir/cli@4.0.0-rc.8 on GJS via async-safe @gjsify/process.exit (#58) (24414f3)
- integration/ts-for-gir: Phase 1 — @gi.ts/parser on GJS (#55) (f26a61f)
- integration/ts-for-gir: Phase 4a — non-interactive @ts-for-gir/cli on Node + supporting infra (#57) (7973f3d)
- integration/ts-for-gir: Phases 2+3 — @ts-for-gir/lib type system + generator pipeline on GJS (#56) (066e431)
- integration: add MCP TypeScript SDK integration tests (757697c)
- integration: socket.io 20/20 on GJS + 3 root-cause fixes in events/fetch/http/stream (97dcc7f)
- integration: webtorrent integration test pillar + 3 root-cause fixes (b571b53)
- node/ws: drop-in @gjsify/ws wrapper over Soup WebsocketConnection (b11304c)
- socket.io-examples: enable WebSocket transport + add READMEs (706de51)
- socket.io: port socket.spec.ts + namespaces.spec.ts; fix WebSocket-only transport (83f2db5)
- tests-integration,websocket: Autobahn Testsuite pillar + /register subpath (221db35)
- tests-integration: enable Autobahn 9.* performance suite (720ed04)
- tests/browser: add browser tests for dom-elements and canvas2d-core (7a843f4)
- tests/browser: add Playwright browser test infrastructure for Web/DOM packages (5506b60)
- tests: add streamx integration test suite (155 Node + 156 GJS tests) (a975669)
- video: GstHTMLVideoElement + VideoBridge controls + two new examples (#24) (82e32b5), closes #0 #1 #2 #18
- websocket,tests-integration: permessage-deflate + Autobahn baseline expansion (74487bc), closes #30
- websocket: implement headers, origin, handshakeTimeout client options (a2bb775)
- ws,net,http: WebSocket server Phase 3 — noServer+handleUpgrade+'headers' event (93f4980)
- ws: implement createWebSocketStream + update docs (09249a3)
- ws: WebSocket server hooks Phase 2 — verifyClient, handleProtocols, { server } mode (a11a041)
Bug Fixes
- @gjsify/unit: add browserSignalDone — 13/13 browser tests green (#48) (0a81e1f)
- child_process: add ensureMainLoop() to spawn/exec/execFile — fix GJS-from-GJS subprocess deadlock (Phase 5) (#59) (2f04633)
- child_process: spawn() sets child.stdout/stderr as GioInputStreamReadable (#49) (8b3feac)
- ci: upgrade riscv64 base image to ubuntu:26.04 (9484cf3)
- dgram: reject mismatched-family sends with EINVAL before hitting Gio (280bbfa)
- esbuild-plugin-gjsify: add resolveDir to __dirname onLoad result (eec66e9)
- esbuild-plugin-gjsify: fix random-access-file 'not a directory' build error (5105dfa)
- esbuild-plugin-gjsify: inject __dirname/__filename for CJS node_modules (d2471c0)
- esbuild-plugin-gjsify: use build.resolve for random-access-file redirect (79e3009)
- example/cli-axios-http-client: explicit process.exit(0) so GJS returns to shell (d1a8b45)
- examples/mcp: fix net-mcp-server session handling (eb235f8)
- examples/mcp: fix TS2339 union type in cli-mcp-client (55c2eb4)
- examples/mcp: hold McpServer per session and use explicit resource path (05b66cb)
- examples: chat-server use CDN for socket.io client, serveClient: false (eed71a3)
- fetch,url,webrtc,webaudio: XHR responseType + URL.createObjectURL at the source (unblocks Excalibur showcase audio) (604f6fa)
- fetch: xhr.ts pass headersInit record directly, remove unused Headers import (0557244)
- fs,stream: serialize concurrent I/O to clear GIO_ERROR_PENDING (2ad9471)
- fs: convert ReadStream and FileHandle to async Gio I/O (c74c34a)
- fs: use _construct() for async ReadStream file open; add regression tests (e75fab7)
- globals: inject timer override into bundles via auto-globals (0a4af05)
- http-soup-bridge: hand-written ambient types instead of @girs/ (4f42cc8)
- http-soup-bridge: throw GLib.Error from listen() so JS gets EADDRINUSE (fc73142), closes #44
- http,net,fetch: make HTTP server lifecycle GJS-GC-safe and Hono-compatible (ff4959f)
- http2: use npm version ranges for @girs/* deps (not workspace:^) (60c5055)
- http: map Gio listen errors to EADDRINUSE + default start to GJS (8374b34)
- http: restore broad upgrade-intercept condition, keep req.socket before block (4675156)
- integration/mcp: fix API signatures and GJS URL normalization (d94324f)
- integration/mcp: fix TS2339 union type access on resource contents (28edde7)
- net-ws-server: correct subprotocol to chat.v1, fix build:public idempotency (4e29eb3)
- net: yield to GLib idle between socket reads to prevent GTK freeze (03f9389)
- process: revert nextTick to microtask semantics (cc953c7)
- remove surplus null arg from GLib.timeout_add calls in excalibur tests (496fa78)
- remove surplus null user_data arg from GLib.timeout_add/idle_add calls (ba8aa76)
- replace (globalThis as any).X with direct imports in impl code (40f7ea1)
- stream,fetch: implement Readable.toWeb/fromWeb + fix fetch Content-Type (6f422c6)
- stream: drain write buffer synchronously when _write completes sync (b7f6d5b)
- stream: preserve FIFO write order across drain emit re-entry (d85eff4), closes #0
- stream: store _err on destroy(), fix finished() for already-destroyed streams (9cb6c42)
- tests/browser: exclude test.browser.mts from tsc in dom packages (91156f1)
- tests/browser: pass DOMMatrix2DInit with 2D-only props to setTransform (4ca4d35)
- utils,process: route nextTick through GLib idle to unfreeze GTK window (9f077ca)
- utils: batch nextTick bursts to keep GTK input events dispatching (c9febdc)
- utils: point GJS crash hint at GitHub issues, not internal STATUS.md (4c7dbca)
- utils: print G_DEBUG advisory at GJS HTTP startup; document MainContext race (de5cd8d)
- web-streams: use queueMicrotask instead of nextTick for pipeTo scheduling (fec7abb)
- webgl: cast TypedArray to number[] for @girs/gwebgl-0.1 compat (509b6f1)
- webgl: remove stale dom/webgl/prebuilds after move to framework/ (dba474d)
- webrtc-native,webgl: remove build:meson from default build script (8f74ca2)
- websocket: make perMessageDeflate opt-in to fix unit test regressions (dbdf236)
- websocket: preserve NUL bytes in text-frame sends (0b548bf)
- websocket: set max_incoming_payload_size to 100 MB + refresh Autobahn baselines (cf1fd74)
- ws,net-ws-server: remove double 'connection' emit in handleUpgrade path (c5c12e0)
- ws: replace @gjsify/http import type with local structural interface (a4157a9)
- yarn: add workspace reference for @gjsify/buffer (9cfdea3)
Performance Improvements
- excalibur-jelly-jumper: add performance profiling + GJS vs browser comparison (a5bd29d)
- excalibur-jelly-jumper: finalize GJS config after A/B tests (6cf9eb1)
- excalibur-jelly-jumper: fix HUD visibility + reduce physics cascade (5e1a55d)
- excalibur-jelly-jumper: improve comparison script hints based on real data (5ad2b62)
- excalibur-jelly-jumper: reduce per-frame GC allocations (0415007)
- excalibur-jelly-jumper: tie [PERF] logging to F1 toggle (ca6877d)
- excalibur-jelly-jumper: use black HUD text (green bg) (312c5cc)
- webgl,excalibur-jelly-jumper: final allocation fixes (9a78eaa)
- webgl,webaudio: eliminate per-frame GLib.Source + defer audio pipeline teardown (d66a44f)
- webgl: eliminate Vala GLenum[] conversion loops + cache VariantType (0ee028a)