Skip to content

stdlib: URLSearchParams.toString() returns "[object Object]" for every input shape #575

@proggeramlug

Description

@proggeramlug

Repro

console.log(JSON.stringify(new URLSearchParams({}).toString()));
console.log(JSON.stringify(new URLSearchParams({ a: "1", b: "2" }).toString()));
console.log(JSON.stringify(new URLSearchParams("a=1").toString()));

bun main.ts:

""
"a=1&b=2"
"a=1"

perry main.ts:

"[object Object]"
"[object Object]"
"[object Object]"

Every input shape — empty record, populated record, query string — produces "[object Object]" from .toString(). Looks like .toString() is falling through to Object.prototype.toString.

Note: per #561 / the related fetch.rs work, URLSearchParams.set(k, v) and .get(k) work in isolation. The bug is specifically .toString() (and likely the constructor's input parsing — even strings come back as "[object Object]").

Why this matters

Discovered while running @bradenmacdonald/s3-lite-client post #572/#573/#574 fix (#551). The package's buildRequestOptions does:

const queryAsString = typeof options.query === "object"
  ? new URLSearchParams(options.query).toString().replace("+", "%20")
  : options.query;

In a presigned-URL flow, queryAsString becomes "[object Object]" — which then gets injected verbatim into the URL path before AWS SigV4 canonicalization. The resulting presigned URL has a stray query parameter ?[object Object]=&... (visible in the issue's repro).

Beyond s3-lite, URLSearchParams is used by every HTTP client / form-encoder / redirect-URL builder in the JS ecosystem.

Acceptance

The repro at the top prints "" / "a=1&b=2" / "a=1" matching bun. Plus regressions:

  • Iterating: for (const [k, v] of params) yields the entries
  • params.has(k), params.delete(k), params.append(k, v) all working against the parsed form
  • URLSearchParams(URLSearchParams) copy-construct
  • Special chars: URLSearchParams({ a: "x y" }).toString()"a=x+y" (+ for space, not %20)

Refs #551

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions