Repository navigation
fix(fs): match Node read and write argument defaults - #80
Merged
Merged
Conversation
Normalize each overload before native I/O, preserving signed read-length coercion, FileHandle defaults, validation order, bigint positions, and exact diagnostics. Adapts the independent write-argument handling from oven-sh#37647, with credit to robobun. Enable the existing explicit-undefined regression and cover sibling overloads.
This was referenced Oct 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fs.readSync(fd, buffer, undefined, undefined, undefined)threw anERR_OUT_OF_RANGENaN-length error. Node coerces that positional length to zero. Bun also stopped parsing buffer writes at an undefined offset, silently ignoring later length and position arguments.Normalize the public overloads before native I/O. Synchronous/callback reads retain Node's signed 32-bit length coercion;
FileHandle.readretains its distinct nullish-length default. Validate positions even for zero-byte reads and preserve exact range/type errors and their delivery order. Writes consume each argument independently and preserve the string overload's UTF-8 fallback. Native backing-store and bounds checks remain in place. The existing expected-failure test for explicit undefined lengths is now enabled.Upstream research found oven-sh/bun#37647, whose write-slot/default behavior is adapted here in the JavaScript normalization layer. Thanks @robobun! Closed #29017 covers only part of zero-length position validation; no complete read-default fix was found. The complete change is proposed upstream in oven-sh/bun#44476, with an upstream-base Darwin build and oracle proof.
Validation: Node 24.21.0 oracle covering 1,227 argument shapes; every one of the 1,217 non-crashing Node outcomes matches exactly, including codes, messages, byte counts, written bytes and callback/rejection channels. Ten malformed FileHandle length inputs abort Node itself; Bun retains recoverable behavior. Regression groups fail on fork
13311cf83e. All 25 filesystem test files pass through the repository's official runner. All 20 selected ported Node read/write tests pass under Node 24 and patched Bun after restoring the empty-buffer test's exact Node diagnostics. Scoped P2 review, lint, built-in TypeScript checking and formatting pass.OpenClaw consumer comparison is pinned to
8d756e9c009b2: Node passes 271 wrapper tests;13311cf83epasses 269 and fails the capsule readSync case plus an independent retained-allocation receipt race. Patched Bun passes 270 wrapper tests and retains only the independent receipt race; the readSync failure is gone. An earlier loaded-run pnpm startup timeout passed on the exact-runtime replay. All 11 additional consumer files pass on Node, baseline Bun and patched Bun (216 tests on each), covering staging, source capsules, process snapshots, call logs, browser auth, heap snapshots and artifact copying. Both Linux x64 and Darwin arm64 CI passed on final heada88111a1843a26a95f53931459128b556a32571a(run 37077526599). Squash-merged as8d3a4d8ab287dd7136c79136c5cc29aa2eb95f04; the fetched main tree matches the qualified source tree.