Repository navigation
Implement globalThis.structuredClone #39713
Description
Activity
- addedfeature requestIssues requesting new Node.js features.Issues requesting new Node.js features.
on Aug 9, 2021 YES PLEASE!
Reacted by Yahor Siarheyenka, Benjamin Gruenbaum, Steven, EviSONG, MCQ, Jonas Kuche and Matthias Kleine- addedhelp 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.
on Aug 11, 2021 Would love to give this a shot! I have some time this week I can get an initial PR up 🚀
Reacted by Michaël Zasso and Anna HenningsenDoing some pre investigation for this feature, I found this existing
structuredClonemethod inlib/internal/util.jsLines 456 to 469 in 33f9b7f
function structuredClone(value) { const { DefaultSerializer, DefaultDeserializer, } = require('v8'); const ser = new DefaultSerializer(); ser._getDataCloneError = hideStackFrames((message) => lazyDOMException(message, 'DataCloneError')); ser.writeValue(value); const serialized = ser.releaseBuffer(); const des = new DefaultDeserializer(serialized); return des.readValue(); } Should I look to modify this?
It seems to only be used in
lib/internal/perf/usertiming.jsnode/lib/internal/perf/usertiming.js
Line 73 in 33f9b7f
structuredClone(detail) :
Additionally, two implementation questions for StructuredSerializeWithTransfer function:
- How do i check for
internal slots? - How do I
throw a "DataCloneError" DOMException?
For each transferable of transferList:
If transferable has neither an [[ArrayBufferData]] internal slot nor a [[Detached]] internal slot, then throw a "DataCloneError" DOMException.
If transferable has an [[ArrayBufferData]] internal slot and ! IsSharedArrayBuffer(transferable) is true, then throw a "DataCloneError" DOMException.
If memory[transferable] exists, then throw a "DataCloneError" DOMException.
- How do i check for
/cc @addaleax ... she could likely provide a lot more detail and context on these bits than anyone else.
@Ethan-Arrowood Yeah, so … for a bit of context, the serialization/deserialization API in the
v8module has been around for quite a while, and predates the addition ofSharedArrayBuffers,MessagePorts and Worker Threads.Because the two APIs are used a bit differently, they have diverged a bit; in particular,
MessagePortis the API where most of the transfer/clone functionality for host objects has been implemented, whereas thev8module one is a bit more limited when it comes to that.Specifically, the
v8module API always encodes into a binary serialization; this also means that, for host objects (i.e. those with internal slots), thev8module API does not know how to serialize transferable Node.js API objects properly (e.g.FileHandleorMessagePort) because they have internal state that might just not be representable as binary data. It also misses support for things likeSharedArrayBuffers altogether.I think a drop-in
structuredClonefor Node.js could be:{ const { MessageChannel, receiveMessageOnPort } = require('worker_threads'); const channel = new MessageChannel(); channel.unref(); globalThis.structuredClone = function structuredClone(value, transfer) { channel.port1.postMessage(value, transfer); return receiveMessageOnPort(channel.port2).message; }: }
I think that would actually do well enough in terms of performance and correctness to be added as an initial implementation. It’s obviously not ideal to create two internal
MessagePortobjects here, but adjusting thev8module’s API would take quite some time and effort, I assume.Reacted by snek and barretronAlso, as for the questions above:
- How do i check for
internal slots?
Generally speaking, that’s done through the
InternalFieldCount()method in the V8 API, but in the V8ValueSerializerAPI, it’sWriteHostObject()that lets us override behavior for these objects.- How do I
throw a "DataCloneError" DOMException?
I think the straightforward answer here is
ThrowDataCloneException()fromnode_messaging.cc?Also, feel free to reach out in some other way if you’d want to have a synchronous conversation about this in some way 🙂
- How do i check for
Thank you @addaleax ! I'll give your solution a shot for now, and then go from there. There appears to be some WPT tests for the new spec; hopefully, those will let us know if things are working or not 😁
Reacted by Anna Henningsen and Ruben BridgewaterFound something about
receiveMessageOnPortWill this be back ported to v16? #40756
- added a commit that references this issue
on May 22, 2026
See whatwg/html#3414