Immutable ArrayBuffer's are almost here. Are we ready?Β #66346
Copy link
Copy link
Open
Labels
help wantedIssues that need assistance from volunteers or PRs that need help to proceed.Issues that need assistance from volunteers or PRs that need help to proceed.never-staleIssues and PRs exempt from automated stale handling.Issues and PRs exempt from automated stale handling.v8 engineIssues and PRs related to the V8 dependency.Issues and PRs related to the V8 dependency.
Description
Every API that receives an ArrayBuffer needs to be updated to correctly handle immutable ArrayBuffers. It looks like we still have a fair number that do not handle them correctly. We need a comprehensive audit and update.
/cc @panva
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
help wantedIssues that need assistance from volunteers or PRs that need help to proceed.Issues that need assistance from volunteers or PRs that need help to proceed.never-staleIssues and PRs exempt from automated stale handling.Issues and PRs exempt from automated stale handling.v8 engineIssues and PRs related to the V8 dependency.Issues and PRs related to the V8 dependency.
Activity
panva commentedon Sep 27, 2026
Some issues to look at and chip down on in #66350. Most likely not exhaustive.
Hakaou commentedon Oct 21, 2026
Hi @jasnell, I was a little bit curious regarding the serialization part of this audit.
I reproduced on 26.4 with
--js-immutable-arraybufferand readmainat ce9d650.v8.serialize()/v8.deserialize()and theadvancedIPC codec keep a bare immutableArrayBufferimmutable, but any view over one comes back mutable.structuredClone,MessageChannelandWorkerkeep it. #66350 already lists this. As far as I can tell the host-object record written by_writeHostObjectandnode_ipc_serdes.cccarries nothing about the backing store.What I have in mind is to keep the documented
DefaultSerializercontract where only the referenced range is stored and let V8 carry that range as a buffer for immutable views only.The invariants are the exact range, Buffers staying Buffers and the encoding of mutable views remaining byte-for-byte unchanged. I verified them in a userland prototype on 26.4. The
ipc_serdesreader can follow withReadValue(). The writer needs a way to build an immutable copy of a range from C++. V8's public API does not offer it yet. Sonode:v8first and IPC as a follow-up.On compatibility, Node 25.0.0 accepts today's encoding of an immutable view as a mutable view and rejects the new record. Would this record shape be acceptable for immutable views, including rejection by older readers? Or would you prefer a different compatibility strategy?
Details and measurements
In the prototype on 26.4, 15/15 mutable values are byte-identical to
v8.serialize(). A 6-byte view of a 36-byte immutable buffer serializes to 16 bytes with none of the surrounding bytes. Today it is 11 bytes and mutable on read. Mixed messages, repeated references and cycles round-trip. Zeroing the transport buffer after reading leaves the immutable view intact.I could also test two more cases that come with the change. A mutable view read from an immutable transport buffer comes out mutable instead of aliasing the transport. An unknown type index throws an explicit error instead of a
TypeErroronundefined.With Node 25.0.0 reading messages written by 26.4, a bare immutable
ArrayBufferfails withUnable to deserialize cloned data. A view in the current encoding is read and writable. The new record fails withReadRawBytes() failed. The closest precedents are the BigInt64Array #43571 and Float16Array #55996 index additions. Those added new types rather than re-encoding a view older readers already accept.v8: keep immutable ArrayBuffer views immutable
v8: keep immutable ArrayBuffer views immutable
v8: keep immutable ArrayBuffer views immutable
Hakaou commentedon Oct 22, 2026
I opened a draft in #66936. It differs from what I had in mind at first. A view over part of an immutable ArrayBuffer now throws instead of being copied. The PR description explains why.
v8: keep immutable ArrayBuffer views immutable
crypto: reject immutable random fill buffers
crypto: reject immutable random fill buffers