fix: support ArrayBuffer serialization#358
Open
xianjianlf2 wants to merge 1 commit into
Open
Conversation
SuperJSON supports every TypedArray (Int8Array … BigInt64Array) and
DataView-adjacent binary types, but a plain `ArrayBuffer` was not handled
at all. Because it isn't a plain object, array, Map/Set, Error, or
registered class, it fell through untransformed: `stringify` emitted `{}`
and `parse` returned an empty plain object, silently losing all bytes and
the type.
Add an `ArrayBuffer` leaf transformer that serializes the buffer as an
array of byte values (JSON can't represent raw bytes) and reconstructs it
via `new Uint8Array(bytes).buffer`, mirroring the existing typed-array
convention.
| isArrayBuffer, | ||
| 'ArrayBuffer', | ||
| // Raw bytes aren't valid JSON, so they're stored as an array of byte values. | ||
| v => Array.from(new Uint8Array(v)), |
There was a problem hiding this comment.
Minor style inconsistency: the existing
typedArrayRule spreads its view with [...v] (line 256), while the new rule uses Array.from(new Uint8Array(v)). Both produce identical results, but using the spread form matches the established pattern in this file.
Suggested change
| v => Array.from(new Uint8Array(v)), | |
| v => [...new Uint8Array(v)], |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/transformer.ts
Line: 186
Comment:
Minor style inconsistency: the existing `typedArrayRule` spreads its view with `[...v]` (line 256), while the new rule uses `Array.from(new Uint8Array(v))`. Both produce identical results, but using the spread form matches the established pattern in this file.
```suggestion
v => [...new Uint8Array(v)],
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A plain
ArrayBuffercurrently round-trips to an empty object, silently losing all bytes and the type:SuperJSON already supports every
TypedArray(including the recently addedBigInt64Array/BigUint64Array, #353), but a bareArrayBufferisn't a plain object, array, Map/Set, Error, or registered class, so it falls through untransformed andJSON.stringifyreduces it to{}— with no error or warning.Changes
ArrayBufferleaf transformer insrc/transformer.ts(with anisArrayBufferguard insrc/is.ts), following the same convention as the existing typed-array support: the buffer is serialized as an array of byte values (JSON can't represent raw bytes) and reconstructed vianew Uint8Array(bytes).buffer.stringify & parsetest case covering a non-empty and an emptyArrayBuffer, asserting the serialized form, the annotation, and byte-exact reconstruction (+24 lines insrc/index.test.ts).ArrayBufferto the README support table.npm test(vitest): 7 files, 87 passed, 1 skipped (pre-existing), 1 todo.Greptile Summary
This PR adds native
ArrayBufferserialization support to SuperJSON by following the existing typed-array convention: the buffer is serialized as a plain JSON array of byte values and reconstructed vianew Uint8Array(bytes).buffer. Before this change, a bareArrayBufferwould silently serialize to{}, losing all data.src/is.ts/src/transformer.ts: AddsisArrayBufferguard and registers a newsimpleTransformationentry that convertsArrayBuffer ↔ number[]. The rule is correctly placed after all other simple rules and does not conflict with the existingisTypedArraycomposite rule (sinceArrayBuffer.isView(anArrayBuffer)isfalse).src/index.test.ts: Covers non-empty and emptyArrayBufferround-trips, verifying serialized form, annotation key, instance type, and byte-exact reconstruction.Confidence Score: 4/5
Safe to merge — the change is self-contained and the round-trip is byte-exact.
The implementation correctly follows the existing simple-transformation pattern, does not conflict with the TypedArray composite rule (since ArrayBuffer.isView returns false for a bare ArrayBuffer), and the test covers both empty and non-empty buffers with byte-exact assertions. One minor style inconsistency was noted but does not affect correctness.
No files require special attention.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant C as Caller participant SJ as SuperJSON participant T as transformer.ts participant IS as is.ts Note over C,IS: Serialization (stringify) C->>SJ: "stringify({ buf: ArrayBuffer })" SJ->>T: transformValue(ArrayBuffer) T->>IS: isArrayBuffer(value) IS-->>T: true T->>T: Array.from(new Uint8Array(buf)) T-->>SJ: "{ value: [1,2,3,4], type: ArrayBuffer }" SJ-->>C: json string with annotation Note over C,IS: Deserialization (parse) C->>SJ: parse(jsonString) SJ->>T: untransformValue([1,2,3,4], ArrayBuffer) T->>T: new Uint8Array([1,2,3,4]).buffer T-->>SJ: ArrayBuffer(4) SJ-->>C: "{ buf: ArrayBuffer }"%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant C as Caller participant SJ as SuperJSON participant T as transformer.ts participant IS as is.ts Note over C,IS: Serialization (stringify) C->>SJ: "stringify({ buf: ArrayBuffer })" SJ->>T: transformValue(ArrayBuffer) T->>IS: isArrayBuffer(value) IS-->>T: true T->>T: Array.from(new Uint8Array(buf)) T-->>SJ: "{ value: [1,2,3,4], type: ArrayBuffer }" SJ-->>C: json string with annotation Note over C,IS: Deserialization (parse) C->>SJ: parse(jsonString) SJ->>T: untransformValue([1,2,3,4], ArrayBuffer) T->>T: new Uint8Array([1,2,3,4]).buffer T-->>SJ: ArrayBuffer(4) SJ-->>C: "{ buf: ArrayBuffer }"Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix: preserve ArrayBuffer instead of sil..." | Re-trigger Greptile