support 'blob' binaryType

This commit is contained in:
Karl Seguin
2026-04-02 10:45:02 +08:00
parent d05aa09c01
commit 5f4ae2fd8c
3 changed files with 51 additions and 3 deletions

View File

@@ -544,3 +544,43 @@
}); });
} }
</script> </script>
<script id=receive_binary_as_blob type=module>
{
const state = await testing.async();
let received = [];
let ws = new WebSocket('ws://127.0.0.1:9584/');
// binaryType defaults to 'blob'
ws.addEventListener('open', () => {
// Send binary data - server will echo with 0xEE marker
const data = new Uint8Array([1, 2, 3, 4, 5]);
ws.send(data);
});
ws.addEventListener('message', async (e) => {
// e.data should be a Blob
received.push(e.data instanceof Blob);
received.push(e.data.size);
// Read the Blob using FileReader
const reader = new FileReader();
reader.onload = () => {
const arr = new Uint8Array(reader.result);
received.push(arr[0]); // 0xEE marker
received.push(arr[1]); // Our first byte
ws.close();
};
reader.readAsArrayBuffer(e.data);
});
ws.addEventListener('close', () => {
state.resolve();
});
await state.done(() => {
testing.expectEqual([true, 6, 0xEE, 1], received);
});
}
</script>

View File

@@ -44,6 +44,7 @@ pub const Data = union(enum) {
value: js.Value.Temp, value: js.Value.Temp,
string: []const u8, string: []const u8,
arraybuffer: js.ArrayBuffer, arraybuffer: js.ArrayBuffer,
blob: *@import("../Blob.zig"),
}; };
const Options = Event.inheritOptions(MessageEvent, MessageEventOptions); const Options = Event.inheritOptions(MessageEvent, MessageEventOptions);
@@ -83,6 +84,7 @@ pub fn deinit(self: *MessageEvent, session: *Session) void {
if (self._data) |d| { if (self._data) |d| {
switch (d) { switch (d) {
.value => |js_val| js_val.release(), .value => |js_val| js_val.release(),
.blob => |blob| blob.releaseRef(session),
.string, .arraybuffer => {}, .string, .arraybuffer => {},
} }
} }

View File

@@ -410,13 +410,19 @@ fn dispatchOpenEvent(self: *WebSocket) !void {
} }
fn dispatchMessageEvent(self: *WebSocket, data: []const u8, frame_type: http.WsFrameType) !void { fn dispatchMessageEvent(self: *WebSocket, data: []const u8, frame_type: http.WsFrameType) !void {
std.debug.print("{any} {s}\n", .{ frame_type, data });
const page = self._page; const page = self._page;
const target = self.asEventTarget(); const target = self.asEventTarget();
if (page._event_manager.hasDirectListeners(target, "message", self._on_message)) { if (page._event_manager.hasDirectListeners(target, "message", self._on_message)) {
const msg_data: MessageEvent.Data = if (frame_type == .binary and self._binary_type == .arraybuffer) const msg_data: MessageEvent.Data = if (frame_type == .binary)
.{ .arraybuffer = .{ .values = data } } switch (self._binary_type) {
.arraybuffer => .{ .arraybuffer = .{ .values = data } },
.blob => blk: {
const blob = try Blob.init(&.{data}, .{}, page);
blob.acquireRef();
break :blk .{ .blob = blob };
},
}
else else
.{ .string = data }; .{ .string = data };