From 3d25f32a0c11334b2ccce07c029bd7aae2823daa Mon Sep 17 00:00:00 2001 From: Henry Kwon Date: Wed, 25 Mar 2026 18:29:48 -0400 Subject: [PATCH] fix: serialize undefined array elements as null --- .../standard/rpc-json-serializer.test.ts | 24 +++++++++++++++++++ .../adapters/standard/rpc-json-serializer.ts | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/client/src/adapters/standard/rpc-json-serializer.test.ts b/packages/client/src/adapters/standard/rpc-json-serializer.test.ts index 98979e450..cc77c8fca 100644 --- a/packages/client/src/adapters/standard/rpc-json-serializer.test.ts +++ b/packages/client/src/adapters/standard/rpc-json-serializer.test.ts @@ -136,6 +136,30 @@ describe.each([ }) }) +describe('standardRPCJsonSerializer: undefined in arrays produces JSON-safe output', () => { + const serializer = new StandardRPCJsonSerializer() + + it('serialize uses null as placeholder for undefined array elements', () => { + const [json] = serializer.serialize([undefined, 'a', undefined]) + expect(json).toEqual([null, 'a', null]) + }) + + it('round-trips undefined array elements through JSON.parse(JSON.stringify(...))', () => { + const [json, meta, maps, blobs] = serializer.serialize([undefined, 'a', undefined]) + const result = JSON.parse(JSON.stringify({ json, meta, maps })) + const deserialized = serializer.deserialize(result.json, result.meta, result.maps, (i: number) => blobs[i]!) + expect(deserialized).toEqual([undefined, 'a', undefined]) + }) + + it('round-trips nested undefined array elements (e.g. TanStack Query pageParams)', () => { + const data = { pageParams: [undefined, 'cursor_abc'], pages: [{ items: [1, 2] }] } + const [json, meta, maps, blobs] = serializer.serialize(data) + const result = JSON.parse(JSON.stringify({ json, meta, maps })) + const deserialized = serializer.deserialize(result.json, result.meta, result.maps, (i: number) => blobs[i]!) + expect(deserialized).toEqual(data) + }) +}) + describe('standardRPCJsonSerializer: custom serializers', () => { it('should throw when type is duplicated', () => { expect(() => { diff --git a/packages/client/src/adapters/standard/rpc-json-serializer.ts b/packages/client/src/adapters/standard/rpc-json-serializer.ts index 30f16bd50..c644b4d08 100644 --- a/packages/client/src/adapters/standard/rpc-json-serializer.ts +++ b/packages/client/src/adapters/standard/rpc-json-serializer.ts @@ -100,7 +100,7 @@ export class StandardRPCJsonSerializer { const json = data.map((v, i) => { if (v === undefined) { meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED, ...segments, i]) - return v + return null } return this.serialize(v, [...segments, i], meta, maps, blobs)[0]