Repository navigation
Add opt-in structuredClone - #3092
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lahma
force-pushed
the
webapi/structured-clone
branch
from
August 20, 2026 16:10
8514c34 to
0d5c742
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the opt-in web API series (#3079):
structuredClone(value, { transfer })behindWebApiFeatures.StructuredClone(inDefault). Usual rules: BCL only, net8+, opt-in, default engine unchanged.Implements HTML's StructuredSerializeWithTransfer/StructuredDeserializeWithTransfer (https://html.spec.whatwg.org/multipage/structured-data.html) fused into a single walk —
structuredClonehas one realm, so the memory map keys on source-object identity, and the fusion is argued unobservable in the class doc (identical traversal order → identical getter order; a mid-walk throw discards an unreachable clone; transfer still runs strictly after the walk).Covered: primitives; boxed Boolean/Number/String/BigInt; Date; RegExp (source+flags,
lastIndexstarts 0); ArrayBuffer incl. resizability, detached →DataCloneError; TypedArrays/DataView (two views over one buffer deserialize as two views over one cloned buffer — the memory map gives it for free); Map/Set; Array with holes preserved; Errors per the spec table (plusstackcarried, as both HTML and WebIDL say a UA "should");DOMException(it is WebIDL-[Serializable]); plain objects via own enumerable string keys read withGet(getters run, per spec); circular references. Symbols, functions, proxies and host-wrapped objects throwDataCloneError— the recognition is deliberately positive (only object shapes Jint can prove ordinary clone), so nothing ever silently loses data.transferaccepts ArrayBuffers, with the spec's duplicate/detached/non-transferable error order pinned.The walk is iterative, not recursive — there is no depth limit at all. The motivation is empirical: the same 100k-deep
{next:{next:…}}graph run through the engine's recursiveJSON.stringifykills the process with an uncatchable0xC00000FDstack overflow;structuredCloneof that graph (and equally deep array and Map chains) completes in milliseconds, and progress is charged against the engine's execution constraints so a huge clone stays interruptible by timeout/cancellation.94 tests including the deep-graph cases, transfer error ordering, realm-correct prototypes, and the public-surface pins. Verified: all-TFM build, both suites × both frameworks × both host-contract-verification configurations.
🤖 Generated with Claude Code