Detailed per-module status for Home's node:* namespace. This is the
drill-down view; the at-a-glance row is in the
README parity status
section.
Status: The JS-callable bridge is live. A
require()(CommonJS) of thenode:*modules below works through Home's own JavaScriptCore realm — exercised today byhome evalandHOME_NATIVE_RUN=1 home run, NOT by delegating to systembun. 24 modules are JS-callable (🟡) as behavioral subsets, each unit-tested inpackages/runtime/src/jsc/node_modules.zig(+jsc/spawn_global.zigforchild_process). Several are backed by native Zig:node:zlib(std.compress.flate),node:cryptoHMAC/pbkdf2 (std.crypto),node:fs/child_process(std.process/ native fs).Scope caveat: 🟡 here means "callable through Home's realm as a useful subset", NOT "passes the Node test suite" (we don't run it yet) and NOT "wired into the bun-corpus gate" (that still routes through the separate bootstrap harness). The remaining 🔴 are server-side sockets and heavy runtime (
tls/http2/dgram/worker_threads/cluster/…); client networking (dns/net/http/https) is now 🟡 (client-only).
Legend:
- 🟢 Fully implemented — JS-callable today, passes its slice of the Node test suite at the rate noted.
- 🟡 Partially implemented — JS-callable (through Home's realm), with missing APIs / caveats noted inline.
- 🔴 Not implemented — no JS surface yet; Zig substrate may exist.
- ❌ Won't implement — explicitly out of scope (no Node-only
internals like
node:wasilegacy quirks).
🟡 JS-callable. ok/equal/notEqual/strictEqual/notStrictEqual,
deepEqual/deepStrictEqual/notDeepStrictEqual, throws/doesNotThrow,
rejects/doesNotReject, match/doesNotMatch, ifError, fail,
AssertionError (code ERR_ASSERTION), assert.strict. Missing: full
AssertionError diff formatting (the myers_diff.zig substrate isn't wired
to messages yet).
🔴 Not implemented.
🟡 JS-callable (Buffer extends Uint8Array, also a global). from
(utf8/hex/base64/base64url/latin1/array/ArrayBuffer/view), alloc/
allocUnsafe, isBuffer, byteLength, concat, compare (static +
instance), equals, toString (utf8/hex/base64/base64url/latin1/ascii),
toJSON, subarray (memory-sharing view), and read/write UInt8/Int8,
UInt16/Int16 LE+BE, UInt32/Int32 LE+BE, BigUInt64 LE/BE,
Float/Double LE. Missing: Blob, File, the full read/write variant
matrix, SlowBuffer, transcode. Zig substrate: node/buffer.zig.
🟡 JS-callable, mapped onto Home's native Bun.spawnSync:
spawnSync/execSync/execFileSync (Node result shapes) + exec/
execFile (async callback) + spawn (EventEmitter emitting stdout/stderr
data/end and exit/close). Caveat: eager — children run to
completion synchronously under the hood (no live streaming / interactive
stdin yet). fork/IPC not implemented.
🔴 Not implemented.
🟡 JS-callable — require("node:console") returns the realm's console
global (log/info/debug/error/warn/trace/dir).
🟡 JS-callable — POSIX/Darwin subset: O_* open flags, F_OK/R_OK/
W_OK/X_OK, S_IF* mode bits, SIG* signal numbers. Zig substrate:
packages/runtime/src/node/os_constants.zig.
🟡 JS-callable. createHash (sha256/sha512/sha1/md5), createHmac
(HMAC over native hash), pbkdf2/pbkdf2Sync (native std.crypto.pwhash,
sha1/256/512 — RFC 6070 verified), hkdf/hkdfSync (native
std.crypto.kdf.hkdf, sha256/512 — RFC 5869 verified), scrypt/scryptSync
(native std.crypto.pwhash.scrypt, N/r/p — RFC 7914 verified), randomBytes,
randomFillSync, randomInt, randomUUID (v4), timingSafeEqual,
getHashes. Missing: createCipheriv/createDecipheriv,
createSign/verify, KeyObject, X.509 — the OpenSSL/BoringSSL-backed
surfaces.
Zig substrate: node/crypto.zig.
🔴 Not implemented (needs UDP sockets).
🔴 Not implemented.
🔴 Not implemented (needs resolver bindings).
🟡 JS-callable. EventEmitter (on/once/off/emit/addListener/
prependListener/removeListener/removeAllListeners/listeners/
listenerCount/eventNames/setMaxListeners), events.once(emitter,name)
→ Promise, events.getEventListeners. Missing: events.on async iterator,
captureRejections, EventTarget interop. Zig substrate: node/events.zig.
🟡 JS-callable, backed by Home's native fs. Sync:
readFileSync/writeFileSync/existsSync/statSync/mkdirSync/
appendFileSync. Callback: readFile/writeFile. Streams:
createReadStream/createWriteStream (on node:stream),
readdirSync/readdir (+withFileTypes), unlinkSync/unlink,
renameSync/rename, rmSync/rmdirSync (recursive). fs.promises
(see below). Missing: copyFile/watch/open/readSync/writeSync,
full Stats instances, most async callback variants. Zig substrate:
node/fs.zig, Stat.zig,
StatFS.zig, dir_iterator.zig, fs_events.zig, node_fs_constant.zig,
time_like.zig.
🟡 JS-callable (require("node:fs/promises") or fs.promises):
readFile/writeFile/appendFile/mkdir/stat/access/readdir/
unlink/rm/rename. Missing: open/FileHandle/copyFile/cp/watch.
🔴 Not implemented (needs the socket/server stack).
🔴 Not implemented.
🔴 Not implemented.
🔴 Not implemented.
🔴 Not implemented (the realm exposes a CommonJS require global, but the
node:module API — createRequire/Module/builtinModules — is not).
🔴 Not implemented (needs TCP/IPC sockets). Zig substrate:
packages/runtime/src/node/node_net_binding.zig.
🟡 JS-callable. platform/arch/type/release/machine/version,
EOL, homedir/tmpdir/hostname, cpus/totalmem/freemem
(placeholder values), endianness, loadavg, uptime,
availableParallelism, networkInterfaces ({}), userInfo,
constants.signals, getPriority/setPriority, devNull. Several derive
from process/navigator rather than syscalls. Zig substrate:
node/os.zig, os_constants.zig.
🟡 JS-callable. Full POSIX surface (join/normalize/resolve/
dirname/basename/extname/isAbsolute/relative/parse/format/
sep/delimiter), plus path.posix/path.win32 namespaces,
path.matchesGlob, path.toNamespacedPath. Win32 is a backslash-aware
subset. (The verbatim Bun Zig port at node/path.zig is not yet the
backing impl — the current impl is the realm's JS port.)
🟡 JS-callable — { performance, PerformanceObserver (stub) }. Missing
PerformanceObserver actually observing, performance.mark/measure
entries.
🟡 JS-callable — require("node:process") returns the realm's process
global: argv, env, platform, arch, version/versions, pid,
cwd(), exit(), nextTick(), stdout/stderr .write. Missing:
EventEmitter surface, hrtime, memoryUsage/cpuUsage, signal handlers,
process.binding. Zig substrate: node/process.zig.
🔴 Not implemented.
🟡 JS-callable — parse/stringify/escape/unescape (duplicate keys
preserved as arrays). Zig substrate: node/querystring.zig.
🟡 JS-callable — createInterface({ input }) reads lines from a Readable
input, emitting line/close (CRLF-trimmed). question is a stub.
Missing: interactive/output mode, history, cursor control.
🔴 Not implemented.
🔴 Not implemented.
🟡 JS-callable, flowing-mode on EventEmitter: Readable (push/read/
resume/pause/pipe/Readable.from/[Symbol.asyncIterator]),
Writable, Transform, PassThrough, Duplex, and stream.finished/
stream.pipeline (callback). Missing: object-mode nuances, backpressure,
highWaterMark, cork/uncork, the web-streams bridge. Zig substrate:
node/stream.zig.
🔴 Not implemented.
🟡 JS-callable — stream.promises.pipeline / finished (also via
require("node:stream/promises")).
🔴 Not implemented (no WHATWG ReadableStream/WritableStream/
TransformStream yet).
🟡 JS-callable — StringDecoder with UTF-8 chunk-boundary handling
(buffers an incomplete trailing multibyte sequence between writes);
non-utf8 encodings fall back to whole-chunk Buffer.toString. Zig
substrate: node/string_decoder.zig.
🔴 Not implemented. Will land as part of home test (Phase 12.8).
🟡 JS-callable — setTimeout/clearTimeout/setInterval/clearInterval/
setImmediate/clearImmediate (re-exporting the realm's event-loop
timers) + timers.promises.setTimeout.
🟡 JS-callable — setTimeout(ms, value) → Promise (via
require("node:timers/promises")). Missing setInterval/setImmediate
async-iterator forms.
🔴 Not implemented (needs TLS sockets).
🔴 Not implemented.
🟡 JS-callable — isatty() (returns false for now), ReadStream/
WriteStream stubs. Missing real tty detection / window-size / raw mode.
Zig substrate: node/tty.zig, core/tty.zig.
🟡 JS-callable — URL/URLSearchParams (the realm's WHATWG globals),
fileURLToPath/pathToFileURL, format. Missing legacy url.parse/
resolve (the old Url object shape). Zig substrate: node/url.zig.
🟡 JS-callable — inspect, format, promisify, callbackify,
inherits, deprecate, isDeepStrictEqual, stripVTControlCharacters,
toUSVString, debuglog, TextEncoder/TextDecoder, parseArgs
(long/short/=value/clustered/boolean+string/multiple/defaults/
positionals/--), and types.* (isDate/isRegExp/isPromise/isMap/isSet/
isArrayBuffer/isTypedArray/isAsyncFunction/isNativeError/isAnyArrayBuffer).
Zig substrate: node/util.zig, util/parse_args_utils.zig, types.zig.
❌ Won't implement. Home runs on JavaScriptCore, not V8 — the serializer and heap-snapshot APIs are V8-specific and have no equivalent in JSC.
🟡 JS-callable — vm.runInThisContext(code) + vm.Script(code).runInThisContext()
evaluate in the realm's current global via JSC (JSEvaluateScript).
createContext/isContext present; runInNewContext/compileFunction throw
ENOSYS (no context isolation yet).
🔴 Not implemented.
🔴 Not implemented.
🟡 JS-callable, native (Zig std.compress.flate): gzipSync/
gunzipSync/deflateSync/inflateSync/deflateRawSync/inflateRawSync
- async (callback)
gzip/gunzip/deflate/inflate. Missing: brotli, streamingGzip/Gunziptransform classes, options (level/strategy).
🟡 JS-callable in the realm: process, Buffer, console, the timer
functions (setTimeout/setInterval/setImmediate + clearX),
queueMicrotask, fetch (data:/file:/http(s)), URL, URLSearchParams,
TextEncoder/TextDecoder, crypto (getRandomValues/randomUUID),
performance, structuredClone, atob/btoa, global/self. Missing:
WebSocket, the WHATWG *Stream family, navigator (intentionally absent
to prove non-delegation).
| Status | Count | % |
|---|---|---|
| 🟢 Fully implemented | 0 | 0% |
| 🟡 Partially implemented (JS-callable subset) | 36 | ~77% |
| 🔴 Not implemented | 10 | ~21% |
| ❌ Won't implement | 1 | ~2% |
🟡 modules (JS-callable via Home's realm — home eval /
HOME_NATIVE_RUN): assert, async_hooks, buffer, child_process,
console, constants, crypto, diagnostics_channel, dns, events,
fs, fs/promises, http, https, module, net, os, path,
perf_hooks, process, punycode, querystring, readline,
readline/promises, stream, stream/consumers, stream/promises,
stream/web, string_decoder, timers, timers/promises, tty,
url, util, vm, zlib.
Still 🔴 (the next frontier — server-side sockets + heavy runtime):
http2, tls, dgram, worker_threads, cluster, repl, wasi,
inspector, trace_events, test.
Honest caveats: (1) 🟡 = a useful subset callable through Home's own
JSC realm, not a full module nor Node-test-suite-verified — e.g. net/http
are client-only (real net.connect via std.Io.net; http/https
request/get over the realm's fetch), with createServer/duplex streaming
still parked on the event loop; (2) these are
not yet wired into the bun-corpus gate (which still routes through the
bootstrap text-rewrite harness), so they do not yet move the corpus
pass-count — that needs the loader/runtime convergence work tracked in
BUN_PARITY_PLAN.md.