V8 15.2 bumps the value-serializer wire format from version 15 to 16 (buffer lengths become 64-bit varints). Every current Node line (22–26, with LTS support into 2028) writes and reads at most version 15; Node won't cross over until Node 27.
That leaves embedders that exchange V8-serialized data with Node processes unable to span the bump: rusty_v8 ≥ v152 writes bytes no shipping Node can read, and a binary on an older rusty_v8 won't read what Node 27 writes. No single binary can support both sides of the bump, because the written version is hardcoded to kLatestVersion.
This will also bite Deno's own node:v8 compat: once the V8 roll passes 15.2, serialize() output stops being readable by any current Node, breaking cross-runtime caches, queues, and files written on one runtime and read on the other.
Upstream V8 has no API for this. workerd has carried a small patch since 2022 — patches/v8/0002-Allow-manually-setting-ValueSerializer-format-versio.patch (with 0001-…ValueDeserializer… as the read-side companion). It's ~40 lines of mechanism: a version_ field on the serializer, SetWriteVersion(uint32_t) clamped to a supported range, the header writing the pinned version, and the few version-dependent encodings gated on it. Cloudflare uses it to pin Durable Object storage to version 15. An upstream V8 API was discussed around nodejs/node#42192 but never filed.
Would you take this into denoland/v8, with a ValueSerializer::set_write_version() binding exposed in rusty_v8?
Happy to send the PR if the approach is acceptable.
V8 15.2 bumps the value-serializer wire format from version 15 to 16 (buffer lengths become 64-bit varints). Every current Node line (22–26, with LTS support into 2028) writes and reads at most version 15; Node won't cross over until Node 27.
That leaves embedders that exchange V8-serialized data with Node processes unable to span the bump: rusty_v8 ≥ v152 writes bytes no shipping Node can read, and a binary on an older rusty_v8 won't read what Node 27 writes. No single binary can support both sides of the bump, because the written version is hardcoded to
kLatestVersion.This will also bite Deno's own
node:v8compat: once the V8 roll passes 15.2,serialize()output stops being readable by any current Node, breaking cross-runtime caches, queues, and files written on one runtime and read on the other.Upstream V8 has no API for this. workerd has carried a small patch since 2022 —
patches/v8/0002-Allow-manually-setting-ValueSerializer-format-versio.patch(with0001-…ValueDeserializer…as the read-side companion). It's ~40 lines of mechanism: aversion_field on the serializer,SetWriteVersion(uint32_t)clamped to a supported range, the header writing the pinned version, and the few version-dependent encodings gated on it. Cloudflare uses it to pin Durable Object storage to version 15. An upstream V8 API was discussed around nodejs/node#42192 but never filed.Would you take this into denoland/v8, with a
ValueSerializer::set_write_version()binding exposed in rusty_v8?Happy to send the PR if the approach is acceptable.