Skip to content

fix(ext/web): make URL and URLSearchParams non-serializable - #35423

Merged
bartlomieju merged 2 commits into
mainfrom
fix/url-not-serializable
Jun 29, 2026
Merged

bartlomieju merged 2 commits into
mainfrom
fix/url-not-serializable

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

Per the WHATWG/HTML spec, URL is not [Serializable], so cloning it via
structuredClone() or sending it through postMessage() must throw a
DataCloneError, which is what browsers and Node both do. Deno instead
silently produced an empty object (instanceof URL is false, stringifies
to [object Object]) because URL is a plain JS class whose state lives
in symbol-keyed slots that V8's ValueSerializer drops.

Deno already has the machinery for this: markNotSerializable() in
13_message_port.js, backed by a kNotSerializable symbol, with the
clone/postMessage paths checking it and throwing the expected
DataCloneError. The platform types that already behave correctly
(Headers, Request, Response, and the stream types) all call it on
their prototype; URL and URLSearchParams simply never registered.
This marks both prototypes so they take the same path.

This covers the top-level case. A non-serializable value nested inside
another object still serializes to {}, which is a pre-existing,
separately-documented limitation that needs a custom V8 serializer
delegate to fully resolve.

Per the WHATWG/HTML spec, URL is not [Serializable], so cloning it via
structuredClone() or postMessage() must throw a DataCloneError, which is
what browsers and Node both do. Deno instead silently produced an empty
object because URL is a plain JS class whose state lives in symbol-keyed
slots that V8's ValueSerializer drops.

Deno already has machinery for this: markNotSerializable() in
13_message_port.js, used by Headers, Request, Response and the stream
types. URL and URLSearchParams simply never registered. Mark both
prototypes so they take the same DataCloneError path.
@bartlomieju
bartlomieju enabled auto-merge (squash) June 22, 2026 11:01
@bartlomieju
bartlomieju merged commit 4c2f662 into main Jun 29, 2026
136 checks passed
@bartlomieju
bartlomieju deleted the fix/url-not-serializable branch June 29, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant