ReviewOS

home-lang/home

Native spawn: retain an owned snapshot of ArrayBuffer stdin

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

Follow-up to #66 and #499. Comparing the pinned current spawn/stdio.rs with Home exposes a missing ArrayBuffer-copy step: Rust copies the selected byte slice into a runtime-owned buffer before retaining it, while Home retains the caller's original ArrayBuffer/view in ArrayBuffer.Strong.

A native probe on published a21f735fc passes a 2 MiB Uint8Array filled with byte 65 as stdin, immediately fills the caller's view with byte 66, and has the child read stdin after 50 ms. The child receives all 2,097,152 bytes changed to 66. The native call returned successfully, but the queued input no longer reflects the bytes passed at spawn. Holding the JS wrapper also does not prevent the caller from transferring/detaching its underlying buffer.

Port the selected source's owned copy (including view offsets/lengths) and verify unchanged content after immediate mutation or transfer/detachment. Cover ArrayBuffer, typed/DataView slices and Node Buffer views without replacing the native process/writer path. Retain the unchanged upstream input-stream and spawn suites. Source pin: 4982b91e3702094330f3be3883354c52b8c01323.

This is separate from extra-stdio validation/rejected Blob cleanup (#499) and FilePoll deregistration (#501). Do not infer memory safety merely from keeping a Strong reference to a detachable ArrayBuffer.

9 days ago

Published ba2cf90dc on codex/runtime-port as Chris Breuer with no coauthors. Not merged into main.

The native stdio parser now copies the selected byte slice before retaining it. Strong references no longer leave the writer dependent on caller-mutated or detached ArrayBuffer storage. Successful Writable initialization moves the owned payload; later option/spawn errors release unconsumed Blob/ArrayBuffer inputs. Terminal stdio replacement also releases superseded payloads, but terminal execution remains unimplemented in #503.

Eight native scenarios pass: ArrayBuffer, Uint8Array, DataView and Buffer inputs, each with immediate mutation or transfer/detachment plus GC, using 2 MiB per scenario and checking all delivered bytes and exact length. Offset/length views are included. The pre-change snapshot probe delivered all 2,097,152 bytes mutated. Repeated rejected-input tests cover payload cleanup; the old binary retains roughly 160 MiB beyond warmup and fails the bound.

All 21 native files and the final 34-command main batch pass. The native core file passes three additional runs, including one with VM destruction. Complete unchanged spawn: 126 pass / 5484 assertions / 5 skips. Seven additional stdin files: 34 pass / 197 assertions / 3 TODOs excluded. Build and cached rebuild: 17/17. Related #499/#501 fixes are in this checkpoint; integration and non-Darwin validation remain open under #66.

9 days ago

Follow-up terminal coverage is published in 8157bde43, on codex/runtime-port and not merged into main. #503 now has real PTY creation/I/O rather than the skeleton.

The new native terminal regression includes 48 disposal and failed inline spawn cycles with alternating Blob/typed-array stdin overridden by terminal stdio. It verifies native ENOENT failures and exact descriptor recovery, alongside constructor descriptor-exhaustion cleanup and GC/lifetime controls. All 39 main regression commands and three additional terminal repeats pass on macOS, including a repeat with VM destruction at exit.

This validates the previously unreachable terminal replacement path; it does not establish all file-backed Blob ownership or other-platform correctness. #503 and #66 retain those broader completion limits.

9 days ago

Integration is now complete: ba2cf90dc is an ancestor of current main (972979e09).

A fresh JSC-enabled run of HOME_NATIVE_VM=1 ./zig-out/bin/home-debug tests/runtime/native-node-core-cli.test.mjs passes on the merged artifact. Its owned-input section retains all eight required cases: ArrayBuffer, Uint8Array, DataView, and Buffer, each with immediate mutation and transfer/detachment, exact 2 MiB length/content checks, view offsets, GC, and native child I/O.

The requested owned snapshot behavior is therefore implemented, integrated, and covered without delegating the child runtime to Bun. Cross-platform corpus verification remains part of #66 rather than keeping this implementation issue stale.

Sign in to comment on this issue.