Skip to content

fix(engine): wave 2 node:fs, stream/string_decoder, and child_process semantics (v0.10.10) - #66

Merged
siktec-lab merged 1 commit into
mainfrom
fix/wave-2-v0.10.10
Nov 11, 2026
Merged

siktec-lab merged 1 commit into
mainfrom
fix/wave-2-v0.10.10

Conversation

@siktec-lab

Copy link
Copy Markdown
Collaborator

Summary — Wave 2 (v0.10.10): node:fs, node:stream / node:string_decoder, and node:child_process Semantics

Closes #50
Closes #51
Closes #56

1. node:fs & node:fs/promises (#50)

  • POSIX Error Codes (err.code, err.errno, err.syscall, err.path): Throws/rejects with standard ENOENT, EEXIST, EISDIR, ENOTDIR, ENOTEMPTY, and EBADF error objects across readFileSync, statSync, lstatSync, unlinkSync, rmdirSync, readdirSync, renameSync, copyFileSync, openSync, and node:fs/promises equivalents, while keeping OCap FsReadDenied / FsWriteDenied violations uncatchable by guest try / catch.
  • statSync / lstatSync { throwIfNoEntry: false }: Returns undefined when { throwIfNoEntry: false } is passed for missing paths.
  • Default Buffer Return on readFileSync / fsp.readFile: Returns a Buffer when no encoding is specified (and decoded string when utf8 or { encoding } is passed).
  • Write Flags & utimesSync: Supports { flag: a | wx | ... } on writeFileSync/fsp.writeFile, and persists utimesSync / fsp.utimes mtime updates in BOA_VFS_MTIMES.
  • Recursive readdirSync: Supports { recursive: true } and { recursive: true, withFileTypes: true } with Dirent name / parentPath semantics.
  • File Descriptor Table (openSync, readSync, writeSync, fstatSync, ftruncateSync, closeSync, fsp.open): Implements full in-memory VFS file descriptors and FileHandle methods.

2. node:stream, node:string_decoder, and Web ReadableStream (#51)

  • Multi-Byte StringDecoder & Readable.setEncoding: Buffers incomplete multi-byte UTF-8 (2/3/4-byte sequences), UTF-16LE (odd byte & surrogate pairs), and Base64 (3-byte quantum) sequences across .write() calls and flushes on .end(), with a zero-copy __slice_text_decode fast path.
  • Writable Backpressure & 'drain': Tracks writableLength against writableHighWaterMark, returns false from .write() when full, and emits 'drain' when buffered writes complete.
  • Web ReadableStream Async Iteration & Readable.toWeb: Implements ReadableStream.prototype[Symbol.asyncIterator] and .values(), and queues pending reader.read() / Response.text() waiters on async push streams.

3. node:child_process (#56)

  • Shell Execution (exec, execSync, { shell: true }): Executes shell command chains (&&, ||, ;), pipelines (|), and exit codes (exit N -> err.status = N) under Ring-1 OCap ExecCap verification.
  • spawn stdin Piping: Buffers and delivers cp.stdin.write() / cp.stdin.end() binary and UTF-8 payloads to child processes via inputBase64.
  • ENOENT Handling: spawnSync returns { status: null, error } with error.code = ENOENT, and spawn emits 'error' with err.code = ENOENT.

Verification & Benchmarks

  • Workspace Test Suite: 190 passed; 0 failed (slice-cas: 21, slice-cli: 40, slice-engine: 109, slice-io: 6, slice-sandbox: 14).
  • 1,000-Tenant microvm-bench: 1.30 µs min / 1.40 µs P50 / 1.60 µs P99 cold-start, 1.87 ms 1,000-tenant swarm, 4.0 KB per-tenant footprint, 11.97 MB total process RSS.
  • Criterion microbench: Added slice_engine::vfs_and_streams (vfs_fd_open_read_write_and_recursive_readdir at ~307 µs, string_decoder_multibyte_and_writable_hwm at ~513 µs).

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