Skip to content

A RegExp handed to a compilePackages package loses its prototype: z.string().regex() dies with 'test is not a function' #8905

Description

@proggeramlug

perry 0.5.1220, macOS arm64, zod ^4.0.0 in perry.compilePackages + perry.allow.compilePackages.

RegExp.prototype.test works perfectly in user code. But a RegExp passed into a compiled package and called there is missing it.

Repro

import { z } from "zod";

function main(): void {
  // Plain user code: all fine.
  const re = /^a+$/;
  console.log("user .test      :", re.test("aaa"));          // true
  console.log("typeof re.test  :", typeof re.test);          // "function"
  console.log("via fn / obj    :", ((r: RegExp) => r.test("aaa"))(re), ({ r: re }).r.test("aaa"));

  // The same regex handed to zod:
  console.log(z.string().regex(/^[A-Za-z0-9_-]{12}$/).safeParse("abcdefgh1234"));
}
main();
user .test      : true
typeof re.test  : function
via fn / obj    : true true
TypeError: test is not a function

Node runs the last line fine ({ success: true, … }).

z.string().datetime() fails identically, which fits — zod validates ISO strings with an internal regex.

Probably related, possibly the same root cause

Two other things in the same build look like values crossing the package boundary arriving partially materialised:

  • #8904 — the zod namespace object has no own enumerable properties (Object.keys(z).length === 0 vs 238 on Node) and z.coerce / z.iso are undefined, while z.object and z.string work.
  • ZodObject.partial() throws Error: Invalid element at key "id": expected a Zod schema — i.e. zod rejects the schemas in its own .shape when it re-reads them. Reading .shape from the outside is fine: Object.keys(schema.shape) returns ["id","n"] and schema.shape.id.optional() works.

So the pattern looks like: an object is usable across the boundary for direct member reads that the compiler saw statically, but loses its prototype and its own-property table. Filing separately because the symptom is distinct enough to bisect on its own; close as duplicate if it is one fix.

Impact

This is the whole input-validation layer of a REST API. z.string().regex() guards id shapes and z.string().email() guards addresses; both raise TypeError instead of returning a validation failure, so the process throws on the first malformed request rather than answering 400.

Environment

  • perry 0.5.1220 (current latest release), macOS arm64
  • compiled with PERRY_NO_AUTO_OPTIMIZE=1 (prebuilt stdlib)

Activity

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