Skip to content

buffer,fs: support immutable arraybuffers - #66379

Draft
avivkeller wants to merge 1 commit into
nodejs:mainfrom
avivkeller:fs-immutable-arraybuffer
Draft

avivkeller wants to merge 1 commit into
nodejs:mainfrom
avivkeller:fs-immutable-arraybuffer

Conversation

@avivkeller

Copy link
Copy Markdown
Member

Ref: #66346

Adds error-handling for immutable ArrayBuffers in the node:fs module + support for these ArrayBuffers in Node's Buffer.

cc @panva @jasnell

Note that %TypedArray%.prototype.set() rejects immutable ArrayBuffers, so I've updated the buffer implementation to use _copy instead.

Signed-off-by: avivkeller <me@aviv.sh>
@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. labels Sep 28, 2026
@panva

panva commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Might as well wait for #66350 to land before chipping away on #66346...

Comment thread src/node_buffer.cc
// NOLINTNEXTLINE(runtime/references)
FastApiCallbackOptions& options) {
TRACK_V8_FAST_API_CALL("buffer.isImmutable");
HandleScope scope(options.isolate);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this really need a handle scope?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not

@avivkeller
avivkeller marked this pull request as draft September 28, 2026 15:24
@avivkeller

Copy link
Copy Markdown
Member Author

Actually, _copy is significantly slower than %TypedArray%.prototype.set()... I'll backport c795f5948568 (which I didn't realize existed until just now) to allow use to continue using that impl.

@codecov

codecov Bot commented Sep 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.75000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.36%. Comparing base (191a3b2) to head (8f17a15).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
src/node_buffer.cc 66.66% 4 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #66379   +/-   ##
=======================================
  Coverage   90.35%   90.36%           
=======================================
  Files         792      792           
  Lines      275434   275492   +58     
  Branches    52780    52796   +16     
=======================================
+ Hits       248878   248947   +69     
+ Misses      16981    16964   -17     
- Partials     9575     9581    +6     
Files with missing lines Coverage Δ
lib/buffer.js 99.74% <100.00%> (+<0.01%) ⬆️
lib/fs.js 97.32% <100.00%> (+<0.01%) ⬆️
lib/internal/fs/promises.js 91.02% <100.00%> (+<0.01%) ⬆️
lib/internal/fs/utils.js 96.33% <100.00%> (+0.04%) ⬆️
lib/internal/validators.js 98.33% <100.00%> (+0.05%) ⬆️
src/node_buffer.cc 70.36% <66.66%> (-0.05%) ⬇️

... and 27 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/node_buffer.cc
Comment on lines +992 to +994
bool IsImmutableImpl(Local<Value> view) {
return view.As<ArrayBufferView>()->Buffer()->IsImmutable();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool IsImmutableImpl(Local<Value> view) {
return view.As<ArrayBufferView>()->Buffer()->IsImmutable();
}
bool IsImmutableImpl(Local<Value> value) {
Local<ArrayBufferView> abv = value.As<ArrayBufferView>();
if (!abv->HasBuffer()) {
return false;
}
return abv->Buffer()->IsImmutable();
}

Buffer() has side-effects if a typed array was created with on-heap storage.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should likely also at least DCHECK that view->IsArrayBufferView()

@jasnell jasnell Sep 29, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, given how this is used, I think you actually need a tri-state return.

For the IsImmutableImpl, return an std::optional<bool>.

std::nullopt if view is not an ArrayBufferView.

false if view is not immutable.

true if view is immutable.

Then at the callsites, std::nullopt should map to null

(that's a bit pedantic tho so I'll leave it up to you... at a minimum the DCHECK)

validateBuffer(buffer);
}

validateWritableBuffer(buffer);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bikeshed: I'd prefer validateMutableBuffer but non-blocking.

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

Labels

lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants