diff --git a/packages/util/src/serializableObject.ts b/packages/util/src/serializableObject.ts index 17c15d50b9f..64d133388a9 100644 --- a/packages/util/src/serializableObject.ts +++ b/packages/util/src/serializableObject.ts @@ -44,6 +44,18 @@ const hasInnerError = (error: unknown): error is { innerError: unknown } => const innerErrorHasData = (innerError: unknown): innerError is { data: unknown } => typeof innerError === 'object' && innerError !== null && 'data' in innerError; +const isNativeNonSerializableType = (obj: unknown): boolean => { + if (typeof obj === 'undefined' || typeof obj === 'bigint') return true; + if (typeof obj === 'object' && obj !== null) { + if (obj instanceof Date) return true; + if (obj instanceof Error) return true; + if (obj instanceof Map) return true; + if (obj instanceof Set) return true; + if (ArrayBuffer.isView(obj)) return true; + } + return false; +}; + export const toSerializableObject = (obj: unknown, options: ToSerializableObjectOptions = {}): unknown => { if (PLAIN_TYPES.has(typeof obj)) return obj; const { transformationTypeKey = defaultTransformationTypeKey, serializeKey = defaultTransformKey } = options; @@ -110,7 +122,9 @@ export const toSerializableObject = (obj: unknown, options: ToSerializableObject }; const fromSerializableObjectUnknown = (obj: unknown, options: FromSerializableObjectOptions = {}): unknown => { - if (PLAIN_TYPES.has(typeof obj)) return obj; + if (PLAIN_TYPES.has(typeof obj)) return obj; // no-op for plain types + if (isNativeNonSerializableType(obj)) return obj; // no-op for native types + if (typeof obj === 'object') { if (obj === null) return null; if (Array.isArray(obj)) { diff --git a/packages/util/test/serializableObject.test.ts b/packages/util/test/serializableObject.test.ts index bf912d96fa6..c9cd5d7e343 100644 --- a/packages/util/test/serializableObject.test.ts +++ b/packages/util/test/serializableObject.test.ts @@ -111,5 +111,19 @@ describe('serializableObject', () => { const obj = [{ a: [{ b: 1, c: '2' }] }, 3]; expect(fromSerializableObject(obj)).toEqual(obj); }); + + it('returns the identical object when input is already serialized', () => { + const obj = { + bigint: 123n, + buffer: new Uint8Array(Buffer.from('data')), + date: new Date(), + error: new Error('error obj'), + map: new Map([['key', 1n]]), + nullVal: null, + set: new Set(['item1', 1n]), + undefinedVal: undefined + }; + expect(fromSerializableObject(obj)).toEqual(obj); + }); }); });