From 2dd0215108df0300584371adc4ce2b654095d469 Mon Sep 17 00:00:00 2001 From: landuoduo Date: Tue, 7 Jul 2026 11:57:03 +0800 Subject: [PATCH] fix: treat null as JSON-serializable in isJSONSerializable typeof null is "object", so the t === null branch was dead code (t is always a string). isJSONSerializable(null) fell through to value.buffer and threw "Cannot read properties of null". null is JSON-serializable, so check value === null and return true instead. Resolves #571 --- src/utils.ts | 2 +- test/index.test.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index a773431b..eca6b351 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -19,7 +19,7 @@ export function isJSONSerializable(value: any): boolean { return false; } const t = typeof value; - if (t === "string" || t === "number" || t === "boolean" || t === null) { + if (value === null || t === "string" || t === "number" || t === "boolean") { return true; } if (t !== "object") { diff --git a/test/index.test.ts b/test/index.test.ts index 5ac20b07..7c54d608 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -10,6 +10,7 @@ import { import { Readable } from "node:stream"; import { H3, HTTPError, readBody, serve } from "h3"; import { $fetch } from "../src/index.ts"; +import { isJSONSerializable } from "../src/utils.ts"; describe("ofetch", () => { let listener: ReturnType; @@ -525,3 +526,24 @@ describe("ofetch", () => { }); }); }); + +describe("isJSONSerializable", () => { + it("treats null as serializable without throwing", () => { + // `typeof null` is "object", so the old `t === null` check was dead code + // and execution fell through to `value.buffer`, throwing on null. + // eslint-disable-next-line unicorn/no-null + const value = null; + expect(() => isJSONSerializable(value)).not.toThrow(); + expect(isJSONSerializable(value)).toBe(true); + }); + + it("classifies common values", () => { + expect(isJSONSerializable(undefined)).toBe(false); + expect(isJSONSerializable("str")).toBe(true); + expect(isJSONSerializable(1)).toBe(true); + expect(isJSONSerializable({ a: 1 })).toBe(true); + expect(isJSONSerializable([1, 2])).toBe(true); + expect(isJSONSerializable(new Uint8Array())).toBe(false); + expect(isJSONSerializable(() => {})).toBe(false); + }); +});