ReviewOS

zig-utils/zig-js

ABI: exact SystemError error-instance boundaries

#295
Closed chris opened this 9 days ago ·
9 days ago

Parent: #140 Tracked by: #134, #163, #164

Implement the two pinned SystemError__* error-construction exports as one coherent boundary. The declarations are byte-identical in the pinned Home SystemError.zig (revision 7ed99c02) and the Bun core inventory; the pinned Bun C++ bridge in bindings.cpp builds an ordinary Error with DontDelete system fields, and an ERR_SYSTEM_ERROR info-object shape used by node:os.

Acceptance

  • Pin the exact 160-byte extern SystemError layout: errno: c_int, six 24-byte BunString fields in declaration order (code, message, path, syscall, hostname, dest), and fd: c_int with the minInt(c_int) no-descriptor sentinel.
  • Implement SystemError__toErrorInstance: ordinary Error with the exact message, optional code/path/dest/syscall/hostname string fields only when their tag is non-empty, fd only when non-negative, and unconditional errno, all with DontDelete (writable, enumerable, non-configurable) attributes; conversion failures on optional fields are cleared and skipped exactly like the pinned scope.clearException() paths.
  • Implement SystemError__toErrorInstanceWithInfoObject: Error named SystemError with non-enumerable code = "ERR_SYSTEM_ERROR", message "A system error occurred: {syscall} returned {code} ({message})", a plain info object carrying code/message/syscall/errno, and DontDelete info/syscall/errno on the error itself.
  • Cover empty/minimal and fully populated structs, lone errno, negative/zero/positive fd, Latin-1/UTF-16 BunString fields, sibling realms, pending-exception preservation, and descriptor attribute checks in the generated compile-link-runtime fixture.
  • Mark both exports implemented in the Home and Bun inventories with zero unclassified entries, and update the README/private-ABI counts and evidence.

Design constraint

These bridges construct plain data properties only; they must not consult mutable userland prototypes, run user code, or replace an already-pending VM exception.

Evidence

Completed on main in runtime commit 8874cb1e with README/private-ABI evidence in 26003992.

  • The pinned layout is compile-time locked (160 bytes, exact field offsets) beside the existing BunString/StringBuilder assertions.
  • SystemError__toErrorInstance installs fields in the pinned order (code, path, dest, fd, syscall, hostname, errno), materializes an own empty message exactly like JSC, and skips optional fields whose conversion fails; fd appears only when non-negative.
  • SystemError__toErrorInstanceWithInfoObject converts each BunString once and shares the exact value between the error and its plain info object; empty tags become installed empty strings, matching the unconditional pinned putDirect calls.
  • Focused fixture coverage: fully populated and minimal structs, lone errno, fd boundaries (minInt/0/positive), Latin-1 and UTF-16 (astral + lone-surrogate) fields, key insertion order, every descriptor attribute, null-struct rejection without a replacement exception, pending-exception preservation for both bridges, and sibling-realm prototype/field identity.
  • Generated Home consumer: 280/280 symbols linked; runtime matrix passed.
  • Home inventory: 278/431 implemented, 153 pending, zero unclassified.
  • Bun core inventory: 270/421 implemented, 151 pending, zero unclassified.
  • Public/private export audit: 117 public functions complete, 286 classified private profile exports.
  • Full unit suite from a clean tree at 894d22a5 plus this slice (compiler 0.17.0-dev.1413+addc3c3b8): 1094 passed, 0 skipped, 0 leaked, with one pre-existing failure in gc.test.Object fits the 128-byte GC slab and cold sidecar fits 256 bytes from the in-flight GC/WASM work on main at the time (src/gc.zig/src/value.zig are untouched by this slice).
  • The committed 1,540-sample benchmark matrix remains current because these construction-only bridges are outside its workloads.

Sign in to comment on this issue.