zod 4.5.0 → 4.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -115,8 +115,6 @@ await schema.parseAsync("hello");
115
115
 
116
116
  ### AOT compilation
117
117
 
118
- **Canary only** — compilation has not shipped in a stable release yet. Install with `npm install zod@canary`.
119
-
120
118
  For hot validation paths, `z.compile(schema)` returns a schema clone with an ahead-of-time compiled fast path. Valid inputs take the compiled path; invalid inputs fall back to the regular parser so error reporting stays identical.
121
119
 
122
120
  Across a 55-schema benchmark the median speedup is **2.4x**, and it scales with how much work the schema does per parse: a large array of objects is ~9x, a 20-key object ~9x, a nested object ~4.5x, while a bare `z.string()` gains nothing — compilation removes per-node dispatch and allocation, and a single `typeof` has none to remove.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Colin McDonnell <zod@colinhacks.com>",
@@ -305,7 +305,7 @@ export const ZodType: core.$constructor<ZodType> = /*@__PURE__*/ core.$construct
305
305
  },
306
306
  // `spa` is an alias: same function object as `safeParseAsync`, as before.
307
307
  get spa(): ZodType["safeParseAsync"] {
308
- return this.safeParseAsync;
308
+ return this?.safeParseAsync;
309
309
  },
310
310
  set spa(value: ZodType["safeParseAsync"]) {
311
311
  util.own(this, "spa", value);
@@ -334,11 +334,8 @@ export const ZodType: core.$constructor<ZodType> = /*@__PURE__*/ core.$construct
334
334
  async safeDecodeAsync(data, params) {
335
335
  return parse.safeDecodeAsync(this, data, params);
336
336
  },
337
- get toJSONSchema(): ZodType["toJSONSchema"] {
338
- return util.own(this, "toJSONSchema", createToJSONSchemaMethod(this, {}));
339
- },
340
- set toJSONSchema(value: ZodType["toJSONSchema"]) {
341
- util.own(this, "toJSONSchema", value);
337
+ toJSONSchema(params) {
338
+ return createToJSONSchemaMethod(this, {})(params);
342
339
  },
343
340
  // Reads through to the registry on every access, so it must not cache.
344
341
  get description(): string | undefined {
@@ -1,4 +1,4 @@
1
- import { expect, test } from "vitest";
1
+ import { expect, test, vi } from "vitest";
2
2
  import * as z from "zod/v4";
3
3
 
4
4
  /**
@@ -195,3 +195,27 @@ test("broad sweep: detaching builder methods does not throw or produce a corrupt
195
195
 
196
196
  expect(broken).toEqual([]);
197
197
  });
198
+
199
+ test("vi.spyOn wraps a prototype method that was never read", () => {
200
+ const schema = z.object({ a: z.string() });
201
+ const spy = vi.spyOn(schema, "safeParse").mockReturnValue({ success: true, data: { a: "mocked" } });
202
+
203
+ expect(schema.safeParse({})).toEqual({ success: true, data: { a: "mocked" } });
204
+ expect(spy).toHaveBeenCalledOnce();
205
+
206
+ spy.mockRestore();
207
+ expect(schema.safeParse({ a: "x" })).toEqual({ success: true, data: { a: "x" } });
208
+ expect(schema.safeParse({}).success).toBe(false);
209
+
210
+ const json = vi.spyOn(schema, "toJSONSchema").mockReturnValue({ type: "null" } as any);
211
+ expect(schema.toJSONSchema()).toEqual({ type: "null" });
212
+ json.mockRestore();
213
+ expect(schema.toJSONSchema().type).toBe("object");
214
+ });
215
+
216
+ test("a getter member answers a bare read without a receiver", () => {
217
+ const schema = z.string();
218
+ const get = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(schema), "spa")!.get!;
219
+ expect(get.call(undefined)).toBeUndefined();
220
+ expect(schema.spa).toBe(schema.safeParseAsync);
221
+ });
@@ -1093,7 +1093,8 @@ function defineBound(proto: object, key: string, fn: AnyFunc): void {
1093
1093
  Object.defineProperty(proto, key, {
1094
1094
  configurable: true,
1095
1095
  get(this: any) {
1096
- return own(this, key, fn.bind(this));
1096
+ // vitest's spyOn calls a prototype getter bare to find the function it wraps, so a nullish receiver answers the raw method
1097
+ return this == null ? fn : own(this, key, fn.bind(this));
1097
1098
  },
1098
1099
  set(this: any, value: unknown) {
1099
1100
  own(this, key, value);
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 5,
4
- patch: 0 as number,
4
+ patch: 2 as number,
5
5
  } as const;
@@ -270,7 +270,7 @@ exports.ZodType = core.$constructor("ZodType", (inst, def) => {
270
270
  },
271
271
  // `spa` is an alias: same function object as `safeParseAsync`, as before.
272
272
  get spa() {
273
- return this.safeParseAsync;
273
+ return this?.safeParseAsync;
274
274
  },
275
275
  set spa(value) {
276
276
  index_js_1.util.own(this, "spa", value);
@@ -299,11 +299,8 @@ exports.ZodType = core.$constructor("ZodType", (inst, def) => {
299
299
  async safeDecodeAsync(data, params) {
300
300
  return parse.safeDecodeAsync(this, data, params);
301
301
  },
302
- get toJSONSchema() {
303
- return index_js_1.util.own(this, "toJSONSchema", (0, to_json_schema_js_1.createToJSONSchemaMethod)(this, {}));
304
- },
305
- set toJSONSchema(value) {
306
- index_js_1.util.own(this, "toJSONSchema", value);
302
+ toJSONSchema(params) {
303
+ return (0, to_json_schema_js_1.createToJSONSchemaMethod)(this, {})(params);
307
304
  },
308
305
  // Reads through to the registry on every access, so it must not cache.
309
306
  get description() {
@@ -144,7 +144,7 @@ export const ZodType = /*@__PURE__*/ core.$constructor("ZodType", (inst, def) =>
144
144
  },
145
145
  // `spa` is an alias: same function object as `safeParseAsync`, as before.
146
146
  get spa() {
147
- return this.safeParseAsync;
147
+ return this?.safeParseAsync;
148
148
  },
149
149
  set spa(value) {
150
150
  util.own(this, "spa", value);
@@ -173,11 +173,8 @@ export const ZodType = /*@__PURE__*/ core.$constructor("ZodType", (inst, def) =>
173
173
  async safeDecodeAsync(data, params) {
174
174
  return parse.safeDecodeAsync(this, data, params);
175
175
  },
176
- get toJSONSchema() {
177
- return util.own(this, "toJSONSchema", createToJSONSchemaMethod(this, {}));
178
- },
179
- set toJSONSchema(value) {
180
- util.own(this, "toJSONSchema", value);
176
+ toJSONSchema(params) {
177
+ return createToJSONSchemaMethod(this, {})(params);
181
178
  },
182
179
  // Reads through to the registry on every access, so it must not cache.
183
180
  get description() {
package/v4/core/util.cjs CHANGED
@@ -813,7 +813,8 @@ function defineBound(proto, key, fn) {
813
813
  Object.defineProperty(proto, key, {
814
814
  configurable: true,
815
815
  get() {
816
- return own(this, key, fn.bind(this));
816
+ // vitest's spyOn calls a prototype getter bare to find the function it wraps, so a nullish receiver answers the raw method
817
+ return this == null ? fn : own(this, key, fn.bind(this));
817
818
  },
818
819
  set(value) {
819
820
  own(this, key, value);
package/v4/core/util.js CHANGED
@@ -744,7 +744,8 @@ function defineBound(proto, key, fn) {
744
744
  Object.defineProperty(proto, key, {
745
745
  configurable: true,
746
746
  get() {
747
- return own(this, key, fn.bind(this));
747
+ // vitest's spyOn calls a prototype getter bare to find the function it wraps, so a nullish receiver answers the raw method
748
+ return this == null ? fn : own(this, key, fn.bind(this));
748
749
  },
749
750
  set(value) {
750
751
  own(this, key, value);
@@ -4,5 +4,5 @@ exports.version = void 0;
4
4
  exports.version = {
5
5
  major: 4,
6
6
  minor: 5,
7
- patch: 0,
7
+ patch: 2,
8
8
  };
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 5,
4
- patch: 0,
4
+ patch: 2,
5
5
  };