You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Linux 6.6.87.2-microsoft-standard-WSL2 x86_64 x86_64
What steps can reproduce the bug?
Bun does not export markAsUncloneable from node:worker_threads, even though the Bun reference docs claim the API is supported (the docs appear to be auto-generated from Node's type declarations).
Minimal repro — the API itself is missing:
$ bun -e 'console.log(typeof require("node:worker_threads").markAsUncloneable)'
undefined
Real-world repro via undici 8.1.0, which is where this actually bites users. undici 8.0.3 removed its runtime feature probe for markAsUncloneable (nodejs/undici#4968) and 8.1.0's lib/web/webidl/index.js now calls require("node:worker_threads").markAsUncloneable unconditionally. Any undici constructor that goes through webidl.util.markAsUncloneable(this) — CacheStorage, Response, Request, Headers, FormData, WebSocket, EventSource — throws at module-load time:
mkdir /tmp/bun-uncloneable-repro &&cd /tmp/bun-uncloneable-repro
bun init -y
bun add undici@^8.1.0
bun -e 'require("undici/lib/web/cache/cachestorage.js"); new (require("undici")).CacheStorage'
Actual output:
TypeError: webidl.util.markAsUncloneable is not a function
markAsUncloneable(obj) returns undefined. It is a no-op for primitives (including null / undefined) and for ArrayBuffer / SharedArrayBuffer / Buffer-like objects (per the Node docs).
For any other object, subsequent attempts to clone it via structuredClone(obj), MessagePort.postMessage(obj), new Worker(..., { workerData: obj }), or BroadcastChannel.postMessage(obj) throw a DOMException with name === "DataCloneError".
The marking is irreversible.
The object stays usable locally (property access, JSON.stringify, etc. work normally).
undici 8.0.3+ loads and instantiates CacheStorage / Response / Request / Headers / FormData / WebSocket / EventSource without throwing.
$ bun -e 'console.log(typeof require("node:worker_threads").markAsUncloneable)'
undefined
$ bun -e 'require("undici/lib/web/cache/cachestorage.js"); new (require("undici")).CacheStorage'
error: webidl.util.markAsUncloneable is not a function
at <anonymous> (.../node_modules/undici/lib/web/webidl/index.js:…)
Every undici 8.0.3+ surface that passes this through webidl.util.markAsUncloneable fails to construct: CacheStorage, Response, Request, Headers, FormData, WebSocket, EventSource. This cascades into any Next.js / Vitest / jsdom / cheerio app running on Bun.
I have a PR ready that implements this and will reference this issue: tagging with a JSC private-name identifier and hooking CloneSerializer::dumpIfTerminal in SerializedScriptValue.cpp so structuredClone, MessagePort.postMessage, WorkerworkerData, and BroadcastChannel.postMessage all throw DataCloneError for marked objects. ArrayBuffer / SharedArrayBuffer / Buffer-like values remain a no-op per spec.
What version of Bun is running?
1.3.12+700fc117a
What platform is your computer?
Linux 6.6.87.2-microsoft-standard-WSL2 x86_64 x86_64
What steps can reproduce the bug?
Bun does not export
markAsUncloneablefromnode:worker_threads, even though the Bun reference docs claim the API is supported (the docs appear to be auto-generated from Node's type declarations).Minimal repro — the API itself is missing:
$ bun -e 'console.log(typeof require("node:worker_threads").markAsUncloneable)' undefinedReal-world repro via
undici8.1.0, which is where this actually bites users.undici8.0.3 removed its runtime feature probe formarkAsUncloneable(nodejs/undici#4968) and 8.1.0'slib/web/webidl/index.jsnow callsrequire("node:worker_threads").markAsUncloneableunconditionally. Anyundiciconstructor that goes throughwebidl.util.markAsUncloneable(this)—CacheStorage,Response,Request,Headers,FormData,WebSocket,EventSource— throws at module-load time:Actual output:
Spec: https://nodejs.org/api/worker_threads.html#workermarkasuncloneableobject
What is the expected behavior?
Matching Node.js ≥ v21:
typeof require("node:worker_threads").markAsUncloneable === "function".markAsUncloneable(obj)returnsundefined. It is a no-op for primitives (includingnull/undefined) and forArrayBuffer/SharedArrayBuffer/ Buffer-like objects (per the Node docs).structuredClone(obj),MessagePort.postMessage(obj),new Worker(..., { workerData: obj }), orBroadcastChannel.postMessage(obj)throw aDOMExceptionwithname === "DataCloneError".JSON.stringify, etc. work normally).undici8.0.3+ loads and instantiatesCacheStorage/Response/Request/Headers/FormData/WebSocket/EventSourcewithout throwing.Node reference:
What do you see instead?
Every
undici8.0.3+ surface that passesthisthroughwebidl.util.markAsUncloneablefails to construct:CacheStorage,Response,Request,Headers,FormData,WebSocket,EventSource. This cascades into any Next.js / Vitest / jsdom / cheerio app running on Bun.Additional information
markAsUncloneableas supported (https://bun.com/reference/node/worker_threads/markAsUncloneable) but the runtime does not export it. The docs look auto-generated from Node's.d.ts.worker_threads.markAsUntransferable(currently athrowNotImplementedstub).markAsUncloneablein v21.0.0. Spec: https://nodejs.org/api/worker_threads.html#workermarkasuncloneableobject.CloneSerializer::dumpIfTerminalinSerializedScriptValue.cppsostructuredClone,MessagePort.postMessage,WorkerworkerData, andBroadcastChannel.postMessageall throwDataCloneErrorfor marked objects.ArrayBuffer/SharedArrayBuffer/ Buffer-like values remain a no-op per spec.worker_threads(Worker&worker_threadsstability tracking issue #15964) — this fix is intentionally scoped to justmarkAsUncloneableand does not touch those.