Skip to content

codegen: String.prototype.split rejects 2-arg form (separator, limit) #567

Closed

Description

@proggeramlug

Repro

const s = "a=b=c=d";
const parts = s.split("=", 2);
console.log(parts[0]);
console.log(parts[1]);
console.log(parts.length);

bun main.ts → a / b / 2
perry main.ts → compile-time error:

perry-codegen: String.split expects 1 arg (delimiter), got 2

Spec

String.prototype.split(separator, limit) — the optional 2nd arg limits the number of returned substrings. Standard ES1+. Used widely.

Where this came from

Triaging #551 (s3-lite-client native compile). signing.ts:254 does:

const [key, val] = element.split("=", 2);

to split "key=value=with=equals" into ["key", "value=with=equals"] (or just ["key"] if no =). Without the limit, = characters inside the value get lost. This is the standard idiom for parsing query-string-style key/value pairs and it's a hard requirement for AWS SigV4 canonicalization.

Suggested implementation

String.prototype.split is currently lowered in crates/perry-codegen/src/lower_string_method.rs (or similar — search for the error message string). Extend the call site to accept a 2nd argument limit: number. Two reasonable shapes:

  1. Honor it precisely (per spec): split fully, then truncate the resulting array to limit entries.
  2. Honor a trimmed form: split until limit substrings are produced and stop scanning.

Either is fine for spec-conformance — [].split(sep, n) and bun/Node both implement option (1) since it's simpler and the result is identical.

For RegExp separators, behavior should match the string-separator path (since perry already supports regex .split(re) per other recent fixes).

Acceptance

The repro at the top prints a / b / 2 — matching Node/bun byte-for-byte.

Plus regression: "a,b,c".split(",", 0) → [], "a".split(",", 5) → ["a"], edge cases.

Refs #551

Activity

  1. proggeramlug commented on May 7, 2026

    @proggeramlug
    ContributorAuthor

    Codegen-side gap closed in v0.5.661 (commit 403b1d6) — String.split(s, limit) now compiles AND runs. Repro from the issue prints a / b / 2 matching Node; edge cases (limit=0, limit > parts, regex separator with limit) all match byte-for-byte.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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