diff --git a/src/utils.ts b/src/utils.ts index a773431b..ff7871a0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -18,8 +18,11 @@ 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") { @@ -28,14 +31,14 @@ export function isJSONSerializable(value: any): boolean { if (Array.isArray(value)) { return true; } - if (value.buffer) { - return false; - } // `FormData` and `URLSearchParams` should't have a `toJSON` method, // but Bun adds it, which is non-standard. if (value instanceof FormData || value instanceof URLSearchParams) { return false; } + if (value.buffer) { + return false; + } return ( (value.constructor && value.constructor.name === "Object") || typeof value.toJSON === "function" diff --git a/test/index.test.ts b/test/index.test.ts index 5ac20b07..c3f7a848 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -525,3 +525,25 @@ describe("ofetch", () => { }); }); }); + +describe("isJSONSerializable", () => { + let isJSONSerializable: (value: unknown) => boolean; + + beforeAll(async () => { + const utils = await import("../src/utils.ts"); + isJSONSerializable = utils.isJSONSerializable; + }); + + it("returns false for FormData and URLSearchParams before buffer checks", () => { + expect(isJSONSerializable(new FormData())).toBe(false); + expect(isJSONSerializable(new URLSearchParams())).toBe(false); + + const data = new FormData(); + data.append("foo", "bar"); + expect(isJSONSerializable(data)).toBe(false); + }); + + it("returns true for null without throwing", () => { + expect(isJSONSerializable(null)).toBe(true); // eslint-disable-line unicorn/no-null + }); +});