Skip to content

fix(ext/node): reject non-ArrayBufferView data in fs.writeFileSync#33406

Merged
bartlomieju merged 1 commit into
denoland:mainfrom
nathanwhitbot:fix/node-compat-iter7
Apr 24, 2026
Merged

fix(ext/node): reject non-ArrayBufferView data in fs.writeFileSync#33406
bartlomieju merged 1 commit into
denoland:mainfrom
nathanwhitbot:fix/node-compat-iter7

Conversation

@nathanwhitbot

Copy link
Copy Markdown
Contributor

Summary

  • Node's fs.writeFileSync only accepts string or ArrayBufferView for data. Non-ArrayBufferView input is routed through validateStringAfterArrayBufferView, which throws ERR_INVALID_ARG_TYPE (see lib/fs.js writeFileSync). Only the async Promise variant at lib/internal/fs/promises.js branches on isCustomIterable to support iterables.
  • Deno's sync path was applying the iterable check as well, so fs.appendFileSync(path, []) silently wrote zero bytes instead of throwing. Drop the iterable short-circuit for the sync path only; fs.writeFile / fsPromises.writeFile are unchanged.
  • Enables parallel/test-fs-append-file-sync.js in the node compat suite.

Test plan

  • cargo test --test node_compat -- test-fs-append-file-sync.js passes
  • Sibling sync tests still pass: test-fs-buffertype-writesync, test-fs-writev-sync
  • test-fs-write-stream.js still fails in local runs on upstream/main as well — pre-existing flake, not caused by this change

🤖 Generated with Claude Code

Node's fs.writeFileSync only accepts string or ArrayBufferView data
(see lib/fs.js): non-ArrayBufferView data is routed through
validateStringAfterArrayBufferView, which throws ERR_INVALID_ARG_TYPE.
The async Promise variant (lib/internal/fs/promises.js) additionally
accepts custom iterables via isCustomIterable, but the sync version
does not.

Deno's writeFileSync applied the iterable check, so
fs.appendFileSync(path, []) silently wrote zero bytes instead of
throwing. Drop the iterable short-circuit for the sync path — the
async writeFile / fsPromises.writeFile paths are unchanged.

Enables parallel/test-fs-append-file-sync.js in the node compat suite.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@nathanwhitbot

Copy link
Copy Markdown
Contributor Author

Reviewed — correct and well-targeted. Verified against Node source:

  • lib/fs.js:2386 (writeFileSync): if (!isArrayBufferView(data)) { validateStringAfterArrayBufferView(data, 'data'); data = Buffer.from(...) } — no iterable check. Matches the PR.
  • lib/internal/fs/promises.js:1888 (fsPromises.writeFile): if (!isArrayBufferView(data) && !isCustomIterable(data)) — this is the only path that allows iterables, as the PR description says.

Two observations, both out of scope for this PR but worth a follow-up:

  1. Same bug exists in Deno's callback fs.writeFile at ext/node/polyfills/fs.ts:2565 — it also has if (!ArrayBufferIsView(data) && !_isCustomIterable(data)). Node's callback fs.writeFile at lib/fs.js:2348 uses the same pattern as sync (no iterable support), so fs.writeFile(path, [], cb) should also throw ERR_INVALID_ARG_TYPE but currently silently succeeds. Easy to fix in a sibling PR.

  2. Dead code after this change: with writeFileSync now guaranteeing data is an ArrayBufferView before calling _writeAllSync, the iterable branch at fs.ts:2691-2713 is unreachable (it's only reached from the sync path). Not worth blocking this PR but could be cleaned up.

Test plan looks reasonable — test-fs-append-file-sync.js gets enabled, and you've verified sibling sync tests still pass. No concerns on correctness, safety, performance, or Node conformance for the change as written.

@nathanwhitbot

Copy link
Copy Markdown
Contributor Author

CI failure on `test node_compat debug windows-x86_64` is the same Windows flake we've seen elsewhere this stack (also hit on #33401 and #33404): `parallel/test-child-process-exec-kill-throws.js` — the test asserts `child.killed === true` but occasionally observes `false` on Windows runners (job 72824560998). No relationship to this PR's fs.writeFileSync change. Needs a rerun.

@bartlomieju
bartlomieju enabled auto-merge (squash) April 24, 2026 06:08
@bartlomieju
bartlomieju merged commit bbd5865 into denoland:main Apr 24, 2026
220 of 222 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants