Repository navigation
fix(realtime): send typed array broadcast payloads as binary - #2772
Abhishek-B-R wants to merge 1 commit into
Conversation
The binary serializer only treated an ArrayBuffer payload as binary. A
Uint8Array, Node.js Buffer or DataView went down the JSON path, so the
bytes were sent as {"0":1,"1":4} with the JSON encoding flag and
subscribers received an object instead of an ArrayBuffer. httpSend()
already sends any ArrayBufferView as application/octet-stream.
Encode ArrayBufferView payloads with the binary encoding, copying only
the bytes the view covers so a Buffer from the pool does not leak its
neighbours.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Summary
Priority: ➖ Normal Change: Bug fix Merge Risk: ⚪ Minimal · up to
|
🔍 Description
What changed?
The realtime serializer now sends a broadcast payload as binary when it is any
ArrayBufferView(Uint8Array, Node.jsBuffer,DataView, other typed arrays), not only when it is a plainArrayBuffer. Only the bytes the view covers are copied, so a view into a larger buffer (a pooledBuffer, orsubarray()) sends just its own bytes.Why was this change needed?
channel.send({ type: 'broadcast', event, payload: new Uint8Array([1, 4]) })over the WebSocket goes down the JSON path, because_binaryEncodeUserBroadcastPushonly checks forArrayBuffer.JSON.stringifyturns the typed array into an object, so the frame carries{"0":1,"1":4}with the JSON encoding flag and every subscriber receives{ '0': 1, '1': 4 }instead of anArrayBuffer.httpSend()already treatsArrayBuffer.isView(payload)as binary and sends it asapplication/octet-stream, so the same payload worked over REST and broke over the socket. Libraries that hand you aUint8Array(Yjs updates, protobuf encoders,TextEncoder) hit this directly.📸 Screenshots/Examples
Encoding the same message with
new Uint8Array([1, 4])as the payload:Before (encoding byte
0x01= JSON):After (encoding byte
0x00= binary), identical to what anArrayBufferpayload produces:Tests added in
test/serializer.test.ts: aUint8Arraypayload, asubarray()view into a larger buffer (checks only the viewed bytes are sent), and aDataView. All three fail on master and pass with the change.What I ran in
packages/core/realtime-js:npx vitest run: 26 files, 478 passed, 1 skippedtsc -p tsconfig.jsonandtsc -p tsconfig.module.json: cleanprettier --checkon both changed files: clean🔄 Breaking changes
Plain
ArrayBufferand JSON payloads encode byte for byte the same as before.📋 Checklist
<type>(<scope>): <description>pnpm nx formatto ensure consistent code formatting📝 Additional notes
The deprecated implicit REST fallback inside
send()(used when the socket can't push) still JSON-encodes the payload, including a plainArrayBuffer. I left that alone since it is slated for removal andhttpSend()is the supported REST path.