ServerWebSocket: send Blob bytes instead of "[object Blob]"
What
ServerWebSocket.send(blob), ws.publish(topic, blob), ws.sendBinary(blob), ws.publishBinary(topic, blob), ws.ping(blob), ws.pong(blob), and server.publish(topic, blob) now send the Blob's bytes as a binary frame, matching the client-side WebSocket.send(blob) and npm ws.
Previously:
send/publishfell through toToStringand shipped the literal text"[object Blob]"(return code 13), silently corrupting data.sendBinary/publishBinary/ping/pongrejected Blobs with a TypeError.
So passing the same Blob to the client WebSocket.send, the server ws.send, and ws.sendBinary produced three different results.
Repro
const server = Bun.serve({
port: 0,
fetch: (req, s) => (s.upgrade(req) ? undefined : new Response("no")),
websocket: { open(ws) { globalThis.sws = ws; ws.subscribe("t"); }, message() {} },
});
const c = new WebSocket(`ws://127.0.0.1:${server.port}/`);
c.binaryType = "arraybuffer";
c.onmessage = e =>
console.log("client got:", typeof e.data === "string" ? JSON.stringify(e.data) : new Uint8Array(e.data));
c.onopen = () => {
const blob = new Blob([new Uint8Array([1, 2, 3, 4])]);
console.log("ws.send(blob) rc =", sws.send(blob)); // before: 13, after: 4
console.log("server.publish rc =", server.publish("t", blob)); // before: 13, after: 4
};
// before: client got: "[object Blob]" "[object Blob]"
// after: client got: Uint8Array [1,2,3,4] Uint8Array [1,2,3,4]
Cause
send() / publish() check message_value.as_array_buffer() and on miss fall straight through to message_value.to_js_string(), which is the JS ToString coercion. Blobs (and every other object) become "[object Blob]".
Fix
Insert a value.as_class_ref::<Blob>() check between the ArrayBuffer check and the string coercion at all seven sites, sending blob.shared_view() as Opcode::Binary. A shared blob_payload() helper does the detection and rejects file/S3-backed blobs (Bun.file(), Bun.s3()) with a TypeError that points at await blob.bytes(), since these send paths are synchronous and return a byte count so async I/O cannot happen there.
sendBinary / publishBinary error messages now say "Blob or BufferSource" instead of "an ArrayBufferView".
Type definitions and the websockets doc page are updated to include Blob in the unions.
Notes
Non-Blob objects passed to send / publish still coerce via ToString (e.g. ws.send(42) sends "42"). Tightening that to a TypeError the way npm ws does would be a separate behavior change.
no test proof · iteration 0 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/bun/websocket/websocket-server.test.ts