Repository navigation
structuredClone: throw DataCloneError for a detached ArrayBuffer - #32799
Conversation
Serializing a detached ArrayBuffer through structuredClone, postMessage, or
bun:jsc's serialize threw a plain TypeError ("Unable to deserialize data.").
Per the HTML structured serialize algorithm it must be a DataCloneError
DOMException, and Node, Chrome, Firefox, and Safari all agree.
The detached check in CloneSerializer::dumpIfTerminal set
SerializationReturnCode::ValidationError, which maps to TypeError. Upstream
WebKit uses DataCloneError at this site; Bun's 2023 port of the file predates
that change. Set DataCloneError instead.
Detached ArrayBuffers reached through a typed array or DataView already took
the isOutOfBounds path and threw DataCloneError, as did a detached buffer in
the transfer list; only the direct ArrayBuffer reference was wrong.
|
Warning Review limit reached
More reviews will be available in 11 minutes and 55 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
|
Updated 7:50 PM PT - Jun 26th, 2026
❌ @robobun, your commit cf36dcf has some failures in 🧪 To try this PR locally: bunx bun-pr 32799That installs a local version of the PR into your bun-32799 --bun |
There was a problem hiding this comment.
LGTM — one-line enum swap aligning the detached-ArrayBuffer error with the HTML spec and upstream WebKit, with a focused regression test.
Extended reasoning...
Overview
This PR changes a single enum value in CloneSerializer::dumpIfTerminal (src/jsc/bindings/webcore/SerializedScriptValue.cpp): when a detached ArrayBuffer is encountered during serialization, it now sets SerializationReturnCode::DataCloneError instead of ValidationError. I confirmed in maybeThrowExceptionIfSerializationFailed that DataCloneError maps to throwDataCloneError (a DOMException with name === "DataCloneError") while ValidationError mapped to a generic TypeError. A regression test in test/js/web/workers/structured-clone.test.ts exercises bare, object-wrapped, array-wrapped, and Map-wrapped detached buffers and asserts the exception class, name, and code.
Security risks
None. This only changes which exception subclass is thrown on an existing error path; no new data is exposed, no auth/crypto/permission logic is touched, and the serialization wire format is unchanged.
Level of scrutiny
Low. The functional change is literally one identifier on one line, plus a comment citing the relevant WHATWG spec step. The PR description correctly notes that upstream WebKit, Node, Chrome, Firefox, and Safari all throw DataCloneError here, so this is a straightforward spec/compat alignment rather than a design decision. The new test sits inside the existing structuredClone-only transferables block and follows the established style of adjacent tests.
Other factors
No bugs were flagged by the bug-hunting system, there are no outstanding human review comments, and the PR author already verified locally that the full structured-clone.test.ts suite passes (162 pass, 0 fail). The change is self-contained and easy to revert if anything unexpected surfaces in CI.
|
CI status on this PR (build 65217, now complete): the diff is green everywhere it is exercised, and every red lane is unrelated to it. I am not going to push retrigger commits, so here is the breakdown for whoever looks at the checks. Exercising this diff (all green)
Red lanes (5 jobs, none touched by this diff)
The change is a one-line enum swap in |
The previous commit accidentally picked up the detached-ArrayBuffer hunk that already landed on main as #32799. This PR does not change SerializedScriptValue.cpp.
Summary
Serializing a graph that contains a detached
ArrayBufferthrew a plainTypeErrorinstead of a"DataCloneError"DOMException. The HTML structured serialize algorithm requiresDataCloneErrorhere, and Node, Chrome, Firefox, and Safari all throw it. Code that branches onDataCloneError(the standard "unclonable value" signal, e.g. retry-without-transfer fallbacks) takes the wrong branch on Bun.Reproduction
Before the fix:
Cause
The detached check in
CloneSerializer::dumpIfTerminalsetSerializationReturnCode::ValidationError, whichmaybeThrowExceptionIfSerializationFailedmaps to aTypeError:Upstream WebKit uses
DataCloneErrorat this exact site. Bun's port ofSerializedScriptValue.cpp(#3637, 2023) predates that upstream change and kept the old code.Fix
Set
SerializationReturnCode::DataCloneErrorinstead. One line; no wire format change.This covers every entry point that shares the serializer:
structuredClone,Worker/MessagePortpostMessage,bun:jscserialize, andnode:v8serialize.Detached ArrayBuffers reached through a typed array or
DataViewalready threwDataCloneError(they hit theisOutOfBoundscheck first), as did a detached buffer passed in the transfer list; only a direct reference to a detachedArrayBufferin the serialized graph was wrong.Not changed: a
MessagePortthat appears in the graph but not in the transfer list still throwsTypeError. That path also usesValidationError, but it matches current upstream WebKit, so it is out of scope here.Verification
The new test in
test/js/web/workers/structured-clone.test.tsserializes a detachedArrayBufferbare, inside an object, inside an array, and inside aMap, and asserts the thrown value is aDOMExceptionnamedDataCloneErrorwithcode === DOMException.DATA_CLONE_ERR.Before (unfixed) and after