From f593d42e5b47723cdf13a9b441b040d2166898f6 Mon Sep 17 00:00:00 2001 From: Rafael Zendron Date: Wed, 17 Jun 2026 12:27:38 -0300 Subject: [PATCH] fix: isJSONSerializable returns true for null Fixes #571 The bug was on line 22 where it checked `t === null`, but typeof never returns "null" (typeof null === "object"). This caused: 1. Dead code: t === null was always false 2. isJSONSerializable(null) threw TypeError accessing null.buffer 3. null was incorrectly identified as not JSON serializable Fixed by: - Adding explicit null check before typeof comparison - Removing t === null from typeof checks (impossible condition) Tests: - Added comprehensive unit tests for isJSONSerializable - All tests pass including null, undefined, primitives, and edge cases --- src/utils.ts | 5 +++- test/isjsonserializable.test.ts | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/isjsonserializable.test.ts diff --git a/src/utils.ts b/src/utils.ts index a773431b..2e79fc7a 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") { diff --git a/test/isjsonserializable.test.ts b/test/isjsonserializable.test.ts new file mode 100644 index 00000000..be088544 --- /dev/null +++ b/test/isjsonserializable.test.ts @@ -0,0 +1,51 @@ +import { describe, it, expect } from "vitest"; +import { isJSONSerializable } from "../src/utils.ts"; + +describe("isJSONSerializable", () => { + it("returns true for null", () => { + expect(isJSONSerializable(null)).toBe(true); + }); + + it("returns false for undefined", () => { + expect(isJSONSerializable(undefined)).toBe(false); + }); + + it("returns true for strings", () => { + expect(isJSONSerializable("hello")).toBe(true); + }); + + it("returns true for numbers", () => { + expect(isJSONSerializable(42)).toBe(true); + expect(isJSONSerializable(0)).toBe(true); + expect(isJSONSerializable(-1)).toBe(true); + expect(isJSONSerializable(3.14)).toBe(true); + }); + + it("returns true for booleans", () => { + expect(isJSONSerializable(true)).toBe(true); + expect(isJSONSerializable(false)).toBe(true); + }); + + it("returns true for arrays", () => { + expect(isJSONSerializable([])).toBe(true); + expect(isJSONSerializable([1, 2, 3])).toBe(true); + expect(isJSONSerializable([null, undefined])).toBe(true); + }); + + it("returns true for plain objects", () => { + expect(isJSONSerializable({})).toBe(true); + expect(isJSONSerializable({ a: 1 })).toBe(true); + }); + + it("returns false for buffers", () => { + expect(isJSONSerializable(new ArrayBuffer(8))).toBe(false); + }); + + it("returns false for FormData", () => { + expect(isJSONSerializable(new FormData())).toBe(false); + }); + + it("returns false for URLSearchParams", () => { + expect(isJSONSerializable(new URLSearchParams())).toBe(false); + }); +}); \ No newline at end of file