From c320e5bb7e691b93e0578e7e2304fef31a4f6a4d Mon Sep 17 00:00:00 2001 From: Swaraj Jakanoor <169044732+swaraj792725@users.noreply.github.com> Date: Sun, 27 Sep 2026 10:58:55 +0530 Subject: [PATCH] fix(utils): handle null and check instanceof safely in isJSONSerializable --- src/utils.ts | 21 ++++++++++++++------- test/index.test.ts | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 3bc0dbf5..bad34223 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -18,26 +18,33 @@ export function isJSONSerializable(value: any): boolean { if (value === undefined) { return false; } + if (value === null) { + return true; + } const t = typeof value; - if (t === "string" || t === "number" || t === "boolean" || t === null) { + if (t === "string" || t === "number" || t === "boolean") { return true; } if (t !== "object") { - return false; // bigint, function, symbol, undefined + return false; // bigint, function, symbol } if (Array.isArray(value)) { return true; } - if (value.buffer) { - return false; - } // `FormData` and `URLSearchParams` shouldn't have a `toJSON` method, // but Bun adds it, which is non-standard. - if (value instanceof FormData || value instanceof URLSearchParams) { + if ( + (typeof FormData !== "undefined" && value instanceof FormData) || + (typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams) + ) { + return false; + } + if (value.buffer) { return false; } return ( - (value.constructor && value.constructor.name === "Object") || + !value.constructor || + value.constructor.name === "Object" || typeof value.toJSON === "function" ); } diff --git a/test/index.test.ts b/test/index.test.ts index 5ac20b07..671efebf 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -525,3 +525,24 @@ describe("ofetch", () => { }); }); }); + +describe("isJSONSerializable", () => { + it("handles primitives and null safely", async () => { + const { isJSONSerializable } = await import("../src/utils.ts"); + // eslint-disable-next-line unicorn/no-null + expect(isJSONSerializable(null)).toBe(true); + expect(isJSONSerializable(undefined)).toBe(false); + expect(isJSONSerializable("hello")).toBe(true); + expect(isJSONSerializable(123)).toBe(true); + expect(isJSONSerializable(true)).toBe(true); + expect(isJSONSerializable(Symbol("test"))).toBe(false); + }); + + it("handles objects and special types", async () => { + const { isJSONSerializable } = await import("../src/utils.ts"); + expect(isJSONSerializable({ foo: "bar" })).toBe(true); + expect(isJSONSerializable(Object.create(null))).toBe(true); + expect(isJSONSerializable(new FormData())).toBe(false); + expect(isJSONSerializable(new URLSearchParams())).toBe(false); + }); +});