mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 09:35:59 -04:00
Merge pull request #2158 from lightpanda-io/websocket_tweaks
WS.close returns DOMException
This commit is contained in:
@@ -130,7 +130,7 @@ pub fn httpMaxResponseSize(self: *const Config) ?usize {
|
||||
|
||||
pub fn wsMaxConcurrent(self: *const Config) u8 {
|
||||
return switch (self.mode) {
|
||||
inline .serve, .fetch, .mcp => |opts| opts.common.ws_max_concurrent orelse 8,
|
||||
inline .serve, .fetch, .mcp => |opts| opts.common.ws_max_concurrent orelse 64,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -857,6 +857,18 @@ fn jsValueToTypedArray(comptime T: type, js_val: js.Value) !?[]T {
|
||||
return ptr[0..num_elements];
|
||||
}
|
||||
},
|
||||
f32 => {
|
||||
if (js_val.isFloat32Array()) {
|
||||
const ptr = @as([*]f32, @ptrCast(@alignCast(base)));
|
||||
return ptr[0..num_elements];
|
||||
}
|
||||
},
|
||||
f64 => {
|
||||
if (js_val.isFloat64Array()) {
|
||||
const ptr = @as([*]f64, @ptrCast(@alignCast(base)));
|
||||
return ptr[0..num_elements];
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return error.InvalidArgument;
|
||||
@@ -985,6 +997,12 @@ fn probeJsValueToZig(self: *const Local, comptime T: type, js_val: js.Value) !Pr
|
||||
i64 => if (js_val.isBigInt64Array()) {
|
||||
return .{ .ok = {} };
|
||||
},
|
||||
f32 => if (js_val.isFloat32Array()) {
|
||||
return .{ .ok = {} };
|
||||
},
|
||||
f64 => if (js_val.isFloat64Array()) {
|
||||
return .{ .ok = {} };
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return .{ .invalid = {} };
|
||||
|
||||
@@ -155,6 +155,14 @@ pub fn isBigInt64Array(self: Value) bool {
|
||||
return v8.v8__Value__IsBigInt64Array(self.handle);
|
||||
}
|
||||
|
||||
pub fn isFloat32Array(self: Value) bool {
|
||||
return v8.v8__Value__IsFloat32Array(self.handle);
|
||||
}
|
||||
|
||||
pub fn isFloat64Array(self: Value) bool {
|
||||
return v8.v8__Value__IsFloat64Array(self.handle);
|
||||
}
|
||||
|
||||
pub fn isPromise(self: Value) bool {
|
||||
return v8.v8__Value__IsPromise(self.handle);
|
||||
}
|
||||
|
||||
@@ -88,20 +88,6 @@ pub const BinaryType = enum {
|
||||
arraybuffer,
|
||||
};
|
||||
|
||||
fn isValidProtocol(protocol: []const u8) bool {
|
||||
if (protocol.len == 0) return false;
|
||||
for (protocol) |c| {
|
||||
// Control characters
|
||||
if (c <= 31 or c == 127) return false;
|
||||
// Separators per RFC 2616
|
||||
switch (c) {
|
||||
'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t' => return false,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn init(url: []const u8, protocols: [][]const u8, page: *Page) !*WebSocket {
|
||||
{
|
||||
if (url.len < 6) {
|
||||
@@ -196,6 +182,18 @@ pub fn deinit(self: *WebSocket, session: *Session) void {
|
||||
session.releaseArena(self._arena);
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *WebSocket, session: *Session) void {
|
||||
self._rc.release(self, session);
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *WebSocket) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
fn asEventTarget(self: *WebSocket) *EventTarget {
|
||||
return self._proto;
|
||||
}
|
||||
|
||||
// we're being aborted internally (e.g. page shutting down)
|
||||
pub fn kill(self: *WebSocket) void {
|
||||
self.cleanup();
|
||||
@@ -211,13 +209,15 @@ pub fn disconnected(self: *WebSocket, err_: ?anyerror) void {
|
||||
log.info(.websocket, "disconnected", .{ .url = self._url, .reason = "closed" });
|
||||
}
|
||||
|
||||
self.cleanup();
|
||||
defer self.cleanup();
|
||||
|
||||
// Use 1006 (abnormal closure) if connection wasn't cleanly closed
|
||||
const code = if (was_clean) self._close_code else 1006;
|
||||
const reason = if (was_clean) self._close_reason else "";
|
||||
|
||||
// Spec requires error event before close on abnormal closure
|
||||
// Spec requires error event before close on abnormal closure.
|
||||
// Dispatch events before cleanup since cleanup releases the ref count
|
||||
// which may free our event handler references.
|
||||
if (!was_clean) {
|
||||
self.dispatchErrorEvent() catch |err| {
|
||||
log.err(.websocket, "error event dispatch failed", .{ .err = err });
|
||||
@@ -239,18 +239,6 @@ fn cleanup(self: *WebSocket) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *WebSocket, session: *Session) void {
|
||||
self._rc.release(self, session);
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *WebSocket) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
fn asEventTarget(self: *WebSocket) *EventTarget {
|
||||
return self._proto;
|
||||
}
|
||||
|
||||
fn queueMessage(self: *WebSocket, msg: Message) !void {
|
||||
const was_empty = self._send_queue.items.len == 0;
|
||||
try self._send_queue.append(self._arena, msg);
|
||||
@@ -263,6 +251,20 @@ fn queueMessage(self: *WebSocket, msg: Message) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn isValidProtocol(protocol: []const u8) bool {
|
||||
if (protocol.len == 0) return false;
|
||||
for (protocol) |c| {
|
||||
// Control characters and non-ASCII
|
||||
if (c <= 31 or c >= 127) return false;
|
||||
// Separators per RFC 2616
|
||||
switch (c) {
|
||||
'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t' => return false,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// WebSocket send() accepts string, Blob, ArrayBuffer, or TypedArray
|
||||
const SendData = union(enum) {
|
||||
blob: *Blob,
|
||||
@@ -279,17 +281,16 @@ const BinaryData = union(enum) {
|
||||
uint32: []u32,
|
||||
int64: []i64,
|
||||
uint64: []u64,
|
||||
float32: []f32,
|
||||
float64: []f64,
|
||||
|
||||
fn asBuffer(self: BinaryData) []u8 {
|
||||
return switch (self) {
|
||||
.int8 => |b| @as([*]u8, @ptrCast(b.ptr))[0..b.len],
|
||||
.uint8 => |b| b,
|
||||
.int16 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 2],
|
||||
.uint16 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 2],
|
||||
.int32 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 4],
|
||||
.uint32 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 4],
|
||||
.int64 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 8],
|
||||
.uint64 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 8],
|
||||
inline .int16, .uint16 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 2],
|
||||
inline .int32, .uint32, .float32 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 4],
|
||||
inline .int64, .uint64, .float64 => |b| @as([*]u8, @ptrCast(b.ptr))[0 .. b.len * 8],
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -754,7 +755,7 @@ pub const JsApi = struct {
|
||||
pub const onclose = bridge.accessor(WebSocket.getOnClose, WebSocket.setOnClose, .{});
|
||||
|
||||
pub const send = bridge.function(WebSocket.send, .{ .dom_exception = true });
|
||||
pub const close = bridge.function(WebSocket.close, .{});
|
||||
pub const close = bridge.function(WebSocket.close, .{ .dom_exception = true });
|
||||
};
|
||||
|
||||
const testing = @import("../../../testing.zig");
|
||||
|
||||
Reference in New Issue
Block a user