Skip to content

String.prototype.replace(/.../g, fn) — replacer-fn return value is dropped (replaces with empty string) #833

Description

@proggeramlug

Surfaced by `test-files/test_gap_regexp_advanced.ts` running under the new feature-matrix runner (#801).

Repro

const result = \"hello world foo\".replace(
  /(\\w+)/g,
  (match: string) => match.charAt(0).toUpperCase() + match.slice(1)
);
console.log(result);

Expected (Node)

Hello World Foo

Actual (Perry v0.5.914)

  

(Two literal spaces — the whitespace between matches survives, but each matched word is replaced with an empty string instead of the replacer-function's return value.)

Narrowing

  • The same shape using `match` only (`(match) => match.toUpperCase()`) reproduces the same empty-replacement behavior.
  • Returning a hard-coded string from the replacer also returns empty:
    \"aXbXc\".replace(/X/g, () => \"Y\")
    TODO confirm — but the `offset` test case in the same file does work (`(_match, offset) => { withOffsets.push(offset); return "Y"; }` printed "5 8" correctly while the replacement string was dropped).

So the bug is specifically: the return value of the replacer function is not threaded back through into the output string.

Why this matters

`str.replace(re, fn)` is one of the most common JS idioms — every parser-lite, URL slugifier, syntax-highlighter, sanitizer uses it. With this bug they all silently produce empty/whitespace output.

Part of #793 (axis 1 — language/runtime semantics). Surfaced by #801.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions