mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 13:51:47 +00:00
Compare commits
6 Commits
claude/fix
...
claude/gc-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb20d4b269 | ||
|
|
e3c0fa384f | ||
|
|
f638fd93d4 | ||
|
|
edb7ba6332 | ||
|
|
802fae5093 | ||
|
|
2666848d5d |
@@ -1086,6 +1086,11 @@ pub fn serve(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.J
|
||||
if (route_list_object != .zero) {
|
||||
ServerType.js.routeListSetCached(obj, globalObject, route_list_object);
|
||||
}
|
||||
if (config.websocket_js_context != .zero) {
|
||||
ServerType.js.websocketServerContextSetCached(obj, globalObject, config.websocket_js_context);
|
||||
// Now that it's stored on the server, we can unprotect it
|
||||
config.websocket_js_context.unprotect();
|
||||
}
|
||||
server.js_value.setStrong(obj, globalObject);
|
||||
|
||||
if (config.allow_hot) {
|
||||
|
||||
@@ -87,7 +87,7 @@ function generate(name) {
|
||||
finalize: true,
|
||||
construct: true,
|
||||
noConstructor: true,
|
||||
values: ["routeList"],
|
||||
values: ["routeList", "websocketServerContext"],
|
||||
});
|
||||
}
|
||||
export default [
|
||||
@@ -320,7 +320,7 @@ export default [
|
||||
finalize: true,
|
||||
construct: true,
|
||||
klass: {},
|
||||
values: ["socket"],
|
||||
values: ["socket", "websocketServerContext"],
|
||||
}),
|
||||
|
||||
define({
|
||||
|
||||
@@ -4,6 +4,7 @@ const ctxLog = Output.scoped(.RequestContext, .visible);
|
||||
pub const WebSocketServerContext = @import("./server/WebSocketServerContext.zig");
|
||||
pub const HTTPStatusText = @import("./server/HTTPStatusText.zig");
|
||||
pub const HTMLBundle = @import("./server/HTMLBundle.zig");
|
||||
const JSWebSocketServerContext = @import("../bindings/JSWebSocketServerContext.zig").JSWebSocketServerContext;
|
||||
|
||||
pub fn writeStatus(comptime ssl: bool, resp_ptr: ?*uws.NewApp(ssl).Response, status: u16) void {
|
||||
if (resp_ptr) |resp| {
|
||||
@@ -989,7 +990,8 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
upgrader.request_weakref.deref();
|
||||
|
||||
data_value.ensureStillAlive();
|
||||
const ws = ServerWebSocket.init(&this.config.websocket.?.handler, data_value, signal);
|
||||
const ws_ctx = JSWebSocketServerContext.fromJS(this.config.websocket_js_context) orelse unreachable;
|
||||
const ws = ServerWebSocket.init(ws_ctx, data_value, signal);
|
||||
data_value.ensureStillAlive();
|
||||
|
||||
var sec_websocket_protocol_str = sec_websocket_protocol.toSlice(bun.default_allocator);
|
||||
@@ -1038,12 +1040,21 @@ pub fn NewServer(protocol_enum: enum { http, https }, development_kind: enum { d
|
||||
if (new_config.websocket) |*ws| {
|
||||
ws.handler.flags.ssl = ssl_enabled;
|
||||
if (ws.handler.onMessage != .zero or ws.handler.onOpen != .zero) {
|
||||
if (this.config.websocket) |old_ws| {
|
||||
old_ws.unprotect();
|
||||
// Update the existing JSWebSocketServerContext with new callbacks
|
||||
if (JSWebSocketServerContext.fromJS(new_config.websocket_js_context)) |ws_ctx| {
|
||||
ws_ctx.setSSL(ssl_enabled);
|
||||
ws_ctx.setOnOpen(globalThis, ws.handler.onOpen);
|
||||
ws_ctx.setOnMessage(globalThis, ws.handler.onMessage);
|
||||
ws_ctx.setOnClose(globalThis, ws.handler.onClose);
|
||||
ws_ctx.setOnDrain(globalThis, ws.handler.onDrain);
|
||||
ws_ctx.setOnError(globalThis, ws.handler.onError);
|
||||
ws_ctx.setOnPing(globalThis, ws.handler.onPing);
|
||||
ws_ctx.setOnPong(globalThis, ws.handler.onPong);
|
||||
}
|
||||
|
||||
ws.globalObject = globalThis;
|
||||
this.config.websocket = ws.*;
|
||||
this.config.websocket_js_context = new_config.websocket_js_context;
|
||||
} // we don't remove it
|
||||
}
|
||||
|
||||
@@ -3115,7 +3126,7 @@ pub const AnyServer = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn webSocketHandler(this: AnyServer) ?*WebSocketServerContext.Handler {
|
||||
pub fn webSocketHandler(this: AnyServer) ?*JSWebSocketServerContext {
|
||||
const server_config: *ServerConfig = switch (this.ptr.tag()) {
|
||||
Ptr.case(HTTPServer) => &this.ptr.as(HTTPServer).config,
|
||||
Ptr.case(HTTPSServer) => &this.ptr.as(HTTPSServer).config,
|
||||
@@ -3124,7 +3135,7 @@ pub const AnyServer = struct {
|
||||
else => bun.unreachablePanic("Invalid pointer tag", .{}),
|
||||
};
|
||||
if (server_config.websocket == null) return null;
|
||||
return &server_config.websocket.?.handler;
|
||||
return JSWebSocketServerContext.fromJS(server_config.websocket_js_context);
|
||||
}
|
||||
|
||||
pub fn onRequest(
|
||||
|
||||
@@ -47,6 +47,7 @@ onRequest: jsc.JSValue = jsc.JSValue.zero,
|
||||
onNodeHTTPRequest: jsc.JSValue = jsc.JSValue.zero,
|
||||
|
||||
websocket: ?WebSocketServerContext = null,
|
||||
websocket_js_context: jsc.JSValue = jsc.JSValue.zero,
|
||||
|
||||
inspector: bool = false,
|
||||
reuse_port: bool = false,
|
||||
@@ -744,7 +745,9 @@ pub fn fromJS(
|
||||
}
|
||||
|
||||
errdefer if (args.ssl_config) |*conf| conf.deinit();
|
||||
args.websocket = try WebSocketServerContext.onCreate(global, websocket_object);
|
||||
const ws_result = try WebSocketServerContext.onCreate(global, websocket_object);
|
||||
args.websocket = ws_result.context;
|
||||
args.websocket_js_context = ws_result.js_context;
|
||||
}
|
||||
if (global.hasException()) return error.JSError;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const ServerWebSocket = @This();
|
||||
|
||||
#handler: *WebSocketServer.Handler,
|
||||
#websocket_context: *JSWebSocketServerContext,
|
||||
#this_value: jsc.JSRef = .empty(),
|
||||
#flags: Flags = .{},
|
||||
#signal: ?*bun.webcore.AbortSignal = null,
|
||||
@@ -36,12 +36,13 @@ pub const fromJSDirect = js.fromJSDirect;
|
||||
|
||||
const new = bun.TrivialNew(ServerWebSocket);
|
||||
|
||||
/// Initialize a ServerWebSocket with the given handler, data value, and signal.
|
||||
/// Initialize a ServerWebSocket with the given websocket context, data value, and signal.
|
||||
/// The signal will not be ref'd inside the ServerWebSocket init function, but will unref itself when the ServerWebSocket is destroyed.
|
||||
pub fn init(handler: *WebSocketServer.Handler, data_value: jsc.JSValue, signal: ?*bun.webcore.AbortSignal) *ServerWebSocket {
|
||||
const globalObject = handler.globalObject;
|
||||
pub fn init(websocket_context: *JSWebSocketServerContext, data_value: jsc.JSValue, signal: ?*bun.webcore.AbortSignal) *ServerWebSocket {
|
||||
const vm = websocket_context.getVM();
|
||||
const globalObject = vm.global;
|
||||
const this = ServerWebSocket.new(.{
|
||||
.#handler = handler,
|
||||
.#websocket_context = websocket_context,
|
||||
.#signal = signal,
|
||||
});
|
||||
// Get a strong ref and downgrade when terminating/close and GC will be able to collect the newly created value
|
||||
@@ -67,11 +68,13 @@ pub fn onOpen(this: *ServerWebSocket, ws: uws.AnyWebSocket) void {
|
||||
this.#flags.closed = false;
|
||||
this.#flags.ssl = ws == .ssl;
|
||||
|
||||
var handler = this.#handler;
|
||||
const vm = this.#handler.vm;
|
||||
handler.active_connections +|= 1;
|
||||
const globalObject = handler.globalObject;
|
||||
const onOpenHandler = handler.onOpen;
|
||||
const ctx = this.#websocket_context;
|
||||
bun.Output.printErrorln("DEBUG onOpen: ctx ptr={*}", .{ctx});
|
||||
const vm = ctx.getVM();
|
||||
ctx.incrementActiveConnections();
|
||||
const globalObject = vm.global;
|
||||
const onOpenHandler = ctx.getOnOpen();
|
||||
bun.Output.printErrorln("DEBUG onOpen: isEmpty={}", .{onOpenHandler.isEmptyOrUndefinedOrNull()});
|
||||
if (vm.isShuttingDown()) {
|
||||
log("onOpen called after script execution", .{});
|
||||
ws.close();
|
||||
@@ -81,6 +84,7 @@ pub fn onOpen(this: *ServerWebSocket, ws: uws.AnyWebSocket) void {
|
||||
this.#flags.opened = false;
|
||||
|
||||
if (onOpenHandler.isEmptyOrUndefinedOrNull()) {
|
||||
bun.Output.printErrorln("DEBUG onOpen: EARLY RETURN - handler is null!", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -108,11 +112,11 @@ pub fn onOpen(this: *ServerWebSocket, ws: uws.AnyWebSocket) void {
|
||||
// we don't want any event handlers to fire after this for anything other than error()
|
||||
// https://github.com/oven-sh/bun/issues/1480
|
||||
this.websocket().close();
|
||||
handler.active_connections -|= 1;
|
||||
ctx.decrementActiveConnections();
|
||||
this_value.unprotect();
|
||||
}
|
||||
|
||||
handler.runErrorCallback(vm, globalObject, err_value);
|
||||
runErrorCallback(ctx, vm, globalObject, err_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +130,12 @@ pub fn onMessage(
|
||||
@intFromEnum(opcode),
|
||||
message,
|
||||
});
|
||||
const onMessageHandler = this.#handler.onMessage;
|
||||
const ctx = this.#websocket_context;
|
||||
const onMessageHandler = ctx.getOnMessage();
|
||||
if (onMessageHandler.isEmptyOrUndefinedOrNull()) return;
|
||||
var globalObject = this.#handler.globalObject;
|
||||
const vm = ctx.getVM();
|
||||
const globalObject = vm.global;
|
||||
// This is the start of a task.
|
||||
const vm = this.#handler.vm;
|
||||
if (vm.isShuttingDown()) {
|
||||
log("onMessage called after script execution", .{});
|
||||
ws.close();
|
||||
@@ -162,7 +167,7 @@ pub fn onMessage(
|
||||
if (result.isEmptyOrUndefinedOrNull()) return;
|
||||
|
||||
if (result.toError()) |err_value| {
|
||||
this.#handler.runErrorCallback(vm, globalObject, err_value);
|
||||
runErrorCallback(ctx, vm, globalObject, err_value);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -185,18 +190,19 @@ pub inline fn isClosed(this: *const ServerWebSocket) bool {
|
||||
pub fn onDrain(this: *ServerWebSocket, _: uws.AnyWebSocket) void {
|
||||
log("onDrain", .{});
|
||||
|
||||
const handler = this.#handler;
|
||||
const vm = handler.vm;
|
||||
const ctx = this.#websocket_context;
|
||||
const vm = ctx.getVM();
|
||||
if (this.isClosed() or vm.isShuttingDown())
|
||||
return;
|
||||
|
||||
if (handler.onDrain != .zero) {
|
||||
const globalObject = handler.globalObject;
|
||||
const onDrainHandler = ctx.getOnDrain();
|
||||
if (onDrainHandler != .zero) {
|
||||
const globalObject = vm.global;
|
||||
|
||||
var corker = Corker{
|
||||
.args = &[_]jsc.JSValue{this.#this_value.tryGet() orelse .js_undefined},
|
||||
.globalObject = globalObject,
|
||||
.callback = handler.onDrain,
|
||||
.callback = onDrainHandler,
|
||||
};
|
||||
const loop = vm.eventLoop();
|
||||
loop.enter();
|
||||
@@ -205,7 +211,7 @@ pub fn onDrain(this: *ServerWebSocket, _: uws.AnyWebSocket) void {
|
||||
const result = corker.result;
|
||||
|
||||
if (result.toError()) |err_value| {
|
||||
handler.runErrorCallback(vm, globalObject, err_value);
|
||||
runErrorCallback(ctx, vm, globalObject, err_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -232,11 +238,11 @@ fn binaryToJS(this: *const ServerWebSocket, globalThis: *jsc.JSGlobalObject, dat
|
||||
pub fn onPing(this: *ServerWebSocket, _: uws.AnyWebSocket, data: []const u8) void {
|
||||
log("onPing: {s}", .{data});
|
||||
|
||||
const handler = this.#handler;
|
||||
var cb = handler.onPing;
|
||||
const vm = handler.vm;
|
||||
const ctx = this.#websocket_context;
|
||||
const vm = ctx.getVM();
|
||||
var cb = ctx.getOnPing();
|
||||
if (cb.isEmptyOrUndefinedOrNull() or vm.isShuttingDown()) return;
|
||||
const globalThis = handler.globalObject;
|
||||
const globalThis = vm.global;
|
||||
|
||||
// This is the start of a task.
|
||||
const loop = vm.eventLoop();
|
||||
@@ -250,19 +256,19 @@ pub fn onPing(this: *ServerWebSocket, _: uws.AnyWebSocket, data: []const u8) voi
|
||||
) catch |e| {
|
||||
const err = globalThis.takeException(e);
|
||||
log("onPing error", .{});
|
||||
handler.runErrorCallback(vm, globalThis, err);
|
||||
runErrorCallback(ctx, vm, globalThis, err);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn onPong(this: *ServerWebSocket, _: uws.AnyWebSocket, data: []const u8) void {
|
||||
log("onPong: {s}", .{data});
|
||||
|
||||
const handler = this.#handler;
|
||||
var cb = handler.onPong;
|
||||
const ctx = this.#websocket_context;
|
||||
const vm = ctx.getVM();
|
||||
var cb = ctx.getOnPong();
|
||||
if (cb.isEmptyOrUndefinedOrNull()) return;
|
||||
|
||||
const globalThis = handler.globalObject;
|
||||
const vm = handler.vm;
|
||||
const globalThis = vm.global;
|
||||
|
||||
if (vm.isShuttingDown()) return;
|
||||
|
||||
@@ -278,19 +284,19 @@ pub fn onPong(this: *ServerWebSocket, _: uws.AnyWebSocket, data: []const u8) voi
|
||||
) catch |e| {
|
||||
const err = globalThis.takeException(e);
|
||||
log("onPong error", .{});
|
||||
handler.runErrorCallback(vm, globalThis, err);
|
||||
runErrorCallback(ctx, vm, globalThis, err);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn onClose(this: *ServerWebSocket, _: uws.AnyWebSocket, code: i32, message: []const u8) void {
|
||||
log("onClose", .{});
|
||||
// TODO: Can this called inside finalize?
|
||||
var handler = this.#handler;
|
||||
const ctx = this.#websocket_context;
|
||||
const was_closed = this.isClosed();
|
||||
this.#flags.closed = true;
|
||||
defer {
|
||||
if (!was_closed) {
|
||||
handler.active_connections -|= 1;
|
||||
ctx.decrementActiveConnections();
|
||||
}
|
||||
}
|
||||
const signal = this.#signal;
|
||||
@@ -307,13 +313,14 @@ pub fn onClose(this: *ServerWebSocket, _: uws.AnyWebSocket, code: i32, message:
|
||||
}
|
||||
}
|
||||
|
||||
const vm = handler.vm;
|
||||
const vm = ctx.getVM();
|
||||
if (vm.isShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!handler.onClose.isEmptyOrUndefinedOrNull()) {
|
||||
const globalObject = handler.globalObject;
|
||||
const onCloseHandler = ctx.getOnClose();
|
||||
if (!onCloseHandler.isEmptyOrUndefinedOrNull()) {
|
||||
const globalObject = vm.global;
|
||||
const loop = vm.eventLoop();
|
||||
|
||||
loop.enter();
|
||||
@@ -321,31 +328,33 @@ pub fn onClose(this: *ServerWebSocket, _: uws.AnyWebSocket, code: i32, message:
|
||||
|
||||
if (signal) |sig| {
|
||||
if (!sig.aborted()) {
|
||||
sig.signal(handler.globalObject, .ConnectionClosed);
|
||||
sig.signal(globalObject, .ConnectionClosed);
|
||||
}
|
||||
}
|
||||
|
||||
const message_js = bun.String.createUTF8ForJS(globalObject, message) catch |e| {
|
||||
const err = globalObject.takeException(e);
|
||||
log("onClose error (message) {}", .{this.#this_value.isNotEmpty()});
|
||||
handler.runErrorCallback(vm, globalObject, err);
|
||||
runErrorCallback(ctx, vm, globalObject, err);
|
||||
return;
|
||||
};
|
||||
|
||||
_ = handler.onClose.call(globalObject, .js_undefined, &[_]jsc.JSValue{ this.#this_value.tryGet() orelse .js_undefined, JSValue.jsNumber(code), message_js }) catch |e| {
|
||||
_ = onCloseHandler.call(globalObject, .js_undefined, &[_]jsc.JSValue{ this.#this_value.tryGet() orelse .js_undefined, JSValue.jsNumber(code), message_js }) catch |e| {
|
||||
const err = globalObject.takeException(e);
|
||||
log("onClose error {}", .{this.#this_value.isNotEmpty()});
|
||||
handler.runErrorCallback(vm, globalObject, err);
|
||||
runErrorCallback(ctx, vm, globalObject, err);
|
||||
return;
|
||||
};
|
||||
} else if (signal) |sig| {
|
||||
const loop = vm.eventLoop();
|
||||
const vm2 = ctx.getVM();
|
||||
const globalObject = vm2.global;
|
||||
const loop = vm2.eventLoop();
|
||||
|
||||
loop.enter();
|
||||
defer loop.exit();
|
||||
|
||||
if (!sig.aborted()) {
|
||||
sig.signal(handler.globalObject, .ConnectionClosed);
|
||||
sig.signal(globalObject, .ConnectionClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,13 +390,13 @@ pub fn publish(
|
||||
return globalThis.throw("publish requires at least 1 argument", .{});
|
||||
}
|
||||
|
||||
const app = this.#handler.app orelse {
|
||||
const ctx = this.#websocket_context;
|
||||
const app = ctx.getApp() orelse {
|
||||
log("publish() closed", .{});
|
||||
return JSValue.jsNumber(0);
|
||||
};
|
||||
const flags = this.#handler.flags;
|
||||
const ssl = flags.ssl;
|
||||
const publish_to_self = flags.publish_to_self;
|
||||
const ssl = ctx.getSSL();
|
||||
const publish_to_self = ctx.getPublishToSelf();
|
||||
|
||||
const topic_value = args.ptr[0];
|
||||
const message_value = args.ptr[1];
|
||||
@@ -465,13 +474,13 @@ pub fn publishText(
|
||||
return globalThis.throw("publish requires at least 1 argument", .{});
|
||||
}
|
||||
|
||||
const app = this.#handler.app orelse {
|
||||
const ctx = this.#websocket_context;
|
||||
const app = ctx.getApp() orelse {
|
||||
log("publish() closed", .{});
|
||||
return JSValue.jsNumber(0);
|
||||
};
|
||||
const flags = this.#handler.flags;
|
||||
const ssl = flags.ssl;
|
||||
const publish_to_self = flags.publish_to_self;
|
||||
const ssl = ctx.getSSL();
|
||||
const publish_to_self = ctx.getPublishToSelf();
|
||||
|
||||
const topic_value = args.ptr[0];
|
||||
const message_value = args.ptr[1];
|
||||
@@ -528,13 +537,13 @@ pub fn publishBinary(
|
||||
return globalThis.throw("publishBinary requires at least 1 argument", .{});
|
||||
}
|
||||
|
||||
const app = this.#handler.app orelse {
|
||||
const ctx = this.#websocket_context;
|
||||
const app = ctx.getApp() orelse {
|
||||
log("publish() closed", .{});
|
||||
return JSValue.jsNumber(0);
|
||||
};
|
||||
const flags = this.#handler.flags;
|
||||
const ssl = flags.ssl;
|
||||
const publish_to_self = flags.publish_to_self;
|
||||
const ssl = ctx.getSSL();
|
||||
const publish_to_self = ctx.getPublishToSelf();
|
||||
const topic_value = args.ptr[0];
|
||||
const message_value = args.ptr[1];
|
||||
const compress_value = args.ptr[2];
|
||||
@@ -583,13 +592,13 @@ pub fn publishBinaryWithoutTypeChecks(
|
||||
topic_str: *jsc.JSString,
|
||||
array: *jsc.JSUint8Array,
|
||||
) bun.JSError!jsc.JSValue {
|
||||
const app = this.#handler.app orelse {
|
||||
const ctx = this.#websocket_context;
|
||||
const app = ctx.getApp() orelse {
|
||||
log("publish() closed", .{});
|
||||
return JSValue.jsNumber(0);
|
||||
};
|
||||
const flags = this.#handler.flags;
|
||||
const ssl = flags.ssl;
|
||||
const publish_to_self = flags.publish_to_self;
|
||||
const ssl = ctx.getSSL();
|
||||
const publish_to_self = ctx.getPublishToSelf();
|
||||
|
||||
var topic_slice = topic_str.toSlice(globalThis, bun.default_allocator);
|
||||
defer topic_slice.deinit();
|
||||
@@ -622,13 +631,13 @@ pub fn publishTextWithoutTypeChecks(
|
||||
topic_str: *jsc.JSString,
|
||||
str: *jsc.JSString,
|
||||
) bun.JSError!jsc.JSValue {
|
||||
const app = this.#handler.app orelse {
|
||||
const ctx = this.#websocket_context;
|
||||
const app = ctx.getApp() orelse {
|
||||
log("publish() closed", .{});
|
||||
return JSValue.jsNumber(0);
|
||||
};
|
||||
const flags = this.#handler.flags;
|
||||
const ssl = flags.ssl;
|
||||
const publish_to_self = flags.publish_to_self;
|
||||
const ssl = ctx.getSSL();
|
||||
const publish_to_self = ctx.getPublishToSelf();
|
||||
|
||||
var topic_slice = topic_str.toSlice(globalThis, bun.default_allocator);
|
||||
defer topic_slice.deinit();
|
||||
@@ -1254,6 +1263,17 @@ pub fn getRemoteAddress(
|
||||
return bun.String.createUTF8ForJS(globalThis, text);
|
||||
}
|
||||
|
||||
fn runErrorCallback(ctx: *JSWebSocketServerContext, vm: *jsc.VirtualMachine, globalObject: *jsc.JSGlobalObject, error_value: jsc.JSValue) void {
|
||||
const onError = ctx.getOnError();
|
||||
if (!onError.isEmptyOrUndefinedOrNull()) {
|
||||
_ = onError.call(globalObject, .js_undefined, &.{error_value}) catch |err|
|
||||
globalObject.reportActiveExceptionAsUnhandled(err);
|
||||
return;
|
||||
}
|
||||
|
||||
_ = vm.uncaughtException(globalObject, error_value, false);
|
||||
}
|
||||
|
||||
const Corker = struct {
|
||||
args: []const JSValue = &.{},
|
||||
globalObject: *jsc.JSGlobalObject,
|
||||
@@ -1284,3 +1304,4 @@ const jsc = bun.jsc;
|
||||
const JSGlobalObject = jsc.JSGlobalObject;
|
||||
const JSValue = jsc.JSValue;
|
||||
const ZigString = jsc.ZigString;
|
||||
const JSWebSocketServerContext = @import("../../bindings/JSWebSocketServerContext.zig").JSWebSocketServerContext;
|
||||
|
||||
@@ -79,30 +79,6 @@ pub const Handler = struct {
|
||||
|
||||
return globalObject.throwInvalidArguments("WebSocketServerContext expects a message handler", .{});
|
||||
}
|
||||
|
||||
pub fn protect(this: Handler) void {
|
||||
this.onOpen.protect();
|
||||
this.onMessage.protect();
|
||||
this.onClose.protect();
|
||||
this.onDrain.protect();
|
||||
this.onError.protect();
|
||||
this.onPing.protect();
|
||||
this.onPong.protect();
|
||||
}
|
||||
|
||||
pub fn unprotect(this: Handler) void {
|
||||
if (this.vm.isShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onOpen.unprotect();
|
||||
this.onMessage.unprotect();
|
||||
this.onClose.unprotect();
|
||||
this.onDrain.unprotect();
|
||||
this.onError.unprotect();
|
||||
this.onPing.unprotect();
|
||||
this.onPong.unprotect();
|
||||
}
|
||||
};
|
||||
|
||||
pub fn toBehavior(this: WebSocketServerContext) uws.WebSocketBehavior {
|
||||
@@ -118,13 +94,6 @@ pub fn toBehavior(this: WebSocketServerContext) uws.WebSocketBehavior {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn protect(this: WebSocketServerContext) void {
|
||||
this.handler.protect();
|
||||
}
|
||||
pub fn unprotect(this: WebSocketServerContext) void {
|
||||
this.handler.unprotect();
|
||||
}
|
||||
|
||||
const CompressTable = bun.ComptimeStringMap(i32, .{
|
||||
.{ "disable", 0 },
|
||||
.{ "shared", uws.SHARED_COMPRESSOR },
|
||||
@@ -153,9 +122,10 @@ const DecompressTable = bun.ComptimeStringMap(i32, .{
|
||||
.{ "256KB", uws.DEDICATED_COMPRESSOR_256KB },
|
||||
});
|
||||
|
||||
pub fn onCreate(globalObject: *jsc.JSGlobalObject, object: JSValue) bun.JSError!WebSocketServerContext {
|
||||
pub fn onCreate(globalObject: *jsc.JSGlobalObject, object: JSValue) bun.JSError!struct { context: WebSocketServerContext, js_context: jsc.JSValue } {
|
||||
var server = WebSocketServerContext{};
|
||||
server.handler = try Handler.fromJS(globalObject, object);
|
||||
server.globalObject = globalObject;
|
||||
|
||||
if (try object.get(globalObject, "perMessageDeflate")) |per_message_deflate| {
|
||||
getter: {
|
||||
@@ -265,8 +235,27 @@ pub fn onCreate(globalObject: *jsc.JSGlobalObject, object: JSValue) bun.JSError!
|
||||
}
|
||||
}
|
||||
|
||||
server.protect();
|
||||
return server;
|
||||
// Create the GC-managed JSWebSocketServerContext object with all callbacks and settings
|
||||
const js_context = JSWebSocketServerContext.create(
|
||||
globalObject,
|
||||
server.handler.onOpen,
|
||||
server.handler.onMessage,
|
||||
server.handler.onClose,
|
||||
server.handler.onDrain,
|
||||
server.handler.onError,
|
||||
server.handler.onPing,
|
||||
server.handler.onPong,
|
||||
.zero, // server - will be set later when the server is created
|
||||
server.handler.app,
|
||||
server.handler.vm,
|
||||
false, // ssl - will be set later
|
||||
server.handler.flags.publish_to_self,
|
||||
);
|
||||
|
||||
// Protect the context from GC until it's stored on the server object
|
||||
js_context.protect();
|
||||
|
||||
return .{ .context = server, .js_context = js_context };
|
||||
}
|
||||
|
||||
const bun = @import("bun");
|
||||
@@ -278,3 +267,4 @@ const JSGlobalObject = jsc.JSGlobalObject;
|
||||
const JSValue = jsc.JSValue;
|
||||
const VirtualMachine = jsc.VirtualMachine;
|
||||
const ZigString = jsc.ZigString;
|
||||
const JSWebSocketServerContext = @import("../../bindings/JSWebSocketServerContext.zig").JSWebSocketServerContext;
|
||||
|
||||
372
src/bun.js/bindings/JSWebSocketServerContext.cpp
Normal file
372
src/bun.js/bindings/JSWebSocketServerContext.cpp
Normal file
@@ -0,0 +1,372 @@
|
||||
#include "root.h"
|
||||
#include <JavaScriptCore/JSCell.h>
|
||||
#include <JavaScriptCore/JSInternalFieldObjectImplInlines.h>
|
||||
#include <JavaScriptCore/ObjectConstructor.h>
|
||||
#include "ZigGlobalObject.h"
|
||||
#include <JavaScriptCore/Structure.h>
|
||||
#include "ZigGeneratedClasses.h"
|
||||
#include "JSWebSocketServerContext.h"
|
||||
|
||||
namespace Bun {
|
||||
using namespace JSC;
|
||||
using namespace WebCore;
|
||||
|
||||
/**
|
||||
JSWebSocketServerContext holds all the callbacks used by WebSocket handlers in Bun.serve()
|
||||
|
||||
Instead of manually managing protect()/unprotect() calls, we use JSInternalFieldObjectImpl
|
||||
to make the callbacks GC-managed. The GC will automatically track these references.
|
||||
|
||||
Internal fields (GC-tracked):
|
||||
0: onOpen
|
||||
1: onMessage
|
||||
2: onClose
|
||||
3: onDrain
|
||||
4: onError
|
||||
5: onPing
|
||||
6: onPong
|
||||
7: server (the server instance)
|
||||
|
||||
C++ members (not GC-tracked):
|
||||
- app (uWS app pointer)
|
||||
- vm (VirtualMachine pointer)
|
||||
- flags (ssl, publish_to_self)
|
||||
- active_connections (connection counter)
|
||||
*/
|
||||
class JSWebSocketServerContext final : public JSC::JSInternalFieldObjectImpl<8> {
|
||||
public:
|
||||
using Base = JSC::JSInternalFieldObjectImpl<8>;
|
||||
|
||||
static constexpr unsigned StructureFlags = Base::StructureFlags;
|
||||
|
||||
static constexpr uint8_t onOpenFieldIndex = 0;
|
||||
static constexpr uint8_t onMessageFieldIndex = 1;
|
||||
static constexpr uint8_t onCloseFieldIndex = 2;
|
||||
static constexpr uint8_t onDrainFieldIndex = 3;
|
||||
static constexpr uint8_t onErrorFieldIndex = 4;
|
||||
static constexpr uint8_t onPingFieldIndex = 5;
|
||||
static constexpr uint8_t onPongFieldIndex = 6;
|
||||
static constexpr uint8_t serverFieldIndex = 7;
|
||||
|
||||
struct Flags {
|
||||
bool ssl = false;
|
||||
bool publish_to_self = false;
|
||||
};
|
||||
|
||||
void* app = nullptr;
|
||||
void* vm = nullptr;
|
||||
Flags flags = {};
|
||||
size_t active_connections = 0;
|
||||
|
||||
static JSWebSocketServerContext* create(
|
||||
JSC::VM& vm,
|
||||
JSC::Structure* structure,
|
||||
JSValue onOpen,
|
||||
JSValue onMessage,
|
||||
JSValue onClose,
|
||||
JSValue onDrain,
|
||||
JSValue onError,
|
||||
JSValue onPing,
|
||||
JSValue onPong,
|
||||
JSValue server,
|
||||
void* app,
|
||||
void* vmPtr,
|
||||
bool ssl,
|
||||
bool publishToSelf)
|
||||
{
|
||||
auto* context = new (NotNull, JSC::allocateCell<JSWebSocketServerContext>(vm))
|
||||
JSWebSocketServerContext(vm, structure, onOpen, onMessage, onClose, onDrain, onError, onPing, onPong, server);
|
||||
context->finishCreation(vm);
|
||||
context->app = app;
|
||||
context->vm = vmPtr;
|
||||
context->flags.ssl = ssl;
|
||||
context->flags.publish_to_self = publishToSelf;
|
||||
context->active_connections = 0;
|
||||
return context;
|
||||
}
|
||||
|
||||
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
|
||||
{
|
||||
return JSC::Structure::create(vm, globalObject, globalObject->nullPrototype(), JSC::TypeInfo(JSC::InternalFieldTupleType, StructureFlags), info());
|
||||
}
|
||||
|
||||
static void destroy(JSCell* cell)
|
||||
{
|
||||
static_cast<JSWebSocketServerContext*>(cell)->~JSWebSocketServerContext();
|
||||
}
|
||||
|
||||
~JSWebSocketServerContext() = default;
|
||||
|
||||
template<typename, JSC::SubspaceAccess mode>
|
||||
static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
|
||||
{
|
||||
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
|
||||
return nullptr;
|
||||
return WebCore::subspaceForImpl<JSWebSocketServerContext, WebCore::UseCustomHeapCellType::No>(
|
||||
vm,
|
||||
[](auto& spaces) { return spaces.m_clientSubspaceForJSWebSocketServerContext.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSWebSocketServerContext = std::forward<decltype(space)>(space); },
|
||||
[](auto& spaces) { return spaces.m_subspaceForJSWebSocketServerContext.get(); },
|
||||
[](auto& spaces, auto&& space) { spaces.m_subspaceForJSWebSocketServerContext = std::forward<decltype(space)>(space); });
|
||||
}
|
||||
|
||||
DECLARE_INFO;
|
||||
DECLARE_VISIT_CHILDREN;
|
||||
|
||||
// Getters for each callback
|
||||
JSValue onOpen() const { return Base::internalField(onOpenFieldIndex).get(); }
|
||||
JSValue onMessage() const { return Base::internalField(onMessageFieldIndex).get(); }
|
||||
JSValue onClose() const { return Base::internalField(onCloseFieldIndex).get(); }
|
||||
JSValue onDrain() const { return Base::internalField(onDrainFieldIndex).get(); }
|
||||
JSValue onError() const { return Base::internalField(onErrorFieldIndex).get(); }
|
||||
JSValue onPing() const { return Base::internalField(onPingFieldIndex).get(); }
|
||||
JSValue onPong() const { return Base::internalField(onPongFieldIndex).get(); }
|
||||
JSValue server() const { return Base::internalField(serverFieldIndex).get(); }
|
||||
|
||||
// Setters for each callback
|
||||
void setOnOpen(JSC::VM& vm, JSValue value) { Base::internalField(onOpenFieldIndex).set(vm, this, value); }
|
||||
void setOnMessage(JSC::VM& vm, JSValue value) { Base::internalField(onMessageFieldIndex).set(vm, this, value); }
|
||||
void setOnClose(JSC::VM& vm, JSValue value) { Base::internalField(onCloseFieldIndex).set(vm, this, value); }
|
||||
void setOnDrain(JSC::VM& vm, JSValue value) { Base::internalField(onDrainFieldIndex).set(vm, this, value); }
|
||||
void setOnError(JSC::VM& vm, JSValue value) { Base::internalField(onErrorFieldIndex).set(vm, this, value); }
|
||||
void setOnPing(JSC::VM& vm, JSValue value) { Base::internalField(onPingFieldIndex).set(vm, this, value); }
|
||||
void setOnPong(JSC::VM& vm, JSValue value) { Base::internalField(onPongFieldIndex).set(vm, this, value); }
|
||||
void setServer(JSC::VM& vm, JSValue value) { Base::internalField(serverFieldIndex).set(vm, this, value); }
|
||||
|
||||
// Getters/setters for C++ members
|
||||
void* getApp() const { return app; }
|
||||
void setApp(void* value) { app = value; }
|
||||
void* getVM() const { return vm; }
|
||||
void setVM(void* value) { vm = value; }
|
||||
Flags getFlags() const { return flags; }
|
||||
void setFlags(Flags value) { flags = value; }
|
||||
size_t getActiveConnections() const { return active_connections; }
|
||||
void setActiveConnections(size_t value) { active_connections = value; }
|
||||
void incrementActiveConnections() { active_connections++; }
|
||||
void decrementActiveConnections() { if (active_connections > 0) active_connections--; }
|
||||
|
||||
private:
|
||||
JSWebSocketServerContext(JSC::VM& vm, JSC::Structure* structure,
|
||||
JSValue onOpen, JSValue onMessage, JSValue onClose,
|
||||
JSValue onDrain, JSValue onError, JSValue onPing,
|
||||
JSValue onPong, JSValue server)
|
||||
: Base(vm, structure)
|
||||
{
|
||||
// Initialize internal fields with the provided callbacks
|
||||
Base::internalField(onOpenFieldIndex).setWithoutWriteBarrier(onOpen);
|
||||
Base::internalField(onMessageFieldIndex).setWithoutWriteBarrier(onMessage);
|
||||
Base::internalField(onCloseFieldIndex).setWithoutWriteBarrier(onClose);
|
||||
Base::internalField(onDrainFieldIndex).setWithoutWriteBarrier(onDrain);
|
||||
Base::internalField(onErrorFieldIndex).setWithoutWriteBarrier(onError);
|
||||
Base::internalField(onPingFieldIndex).setWithoutWriteBarrier(onPing);
|
||||
Base::internalField(onPongFieldIndex).setWithoutWriteBarrier(onPong);
|
||||
Base::internalField(serverFieldIndex).setWithoutWriteBarrier(server);
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM& vm)
|
||||
{
|
||||
Base::finishCreation(vm);
|
||||
}
|
||||
};
|
||||
|
||||
const JSC::ClassInfo JSWebSocketServerContext::s_info = { "JSWebSocketServerContext"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSWebSocketServerContext) };
|
||||
|
||||
template<typename Visitor>
|
||||
void JSWebSocketServerContext::visitChildrenImpl(JSCell* cell, Visitor& visitor)
|
||||
{
|
||||
JSWebSocketServerContext* thisObject = jsCast<JSWebSocketServerContext*>(cell);
|
||||
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
|
||||
Base::visitChildren(thisObject, visitor);
|
||||
}
|
||||
|
||||
DEFINE_VISIT_CHILDREN(JSWebSocketServerContext);
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__create(
|
||||
Zig::GlobalObject* globalObject,
|
||||
JSC::EncodedJSValue onOpen,
|
||||
JSC::EncodedJSValue onMessage,
|
||||
JSC::EncodedJSValue onClose,
|
||||
JSC::EncodedJSValue onDrain,
|
||||
JSC::EncodedJSValue onError,
|
||||
JSC::EncodedJSValue onPing,
|
||||
JSC::EncodedJSValue onPong,
|
||||
JSC::EncodedJSValue server,
|
||||
void* app,
|
||||
void* vmPtr,
|
||||
bool ssl,
|
||||
bool publishToSelf)
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto* structure = globalObject->m_JSWebSocketServerContextStructure.get(globalObject);
|
||||
auto* context = JSWebSocketServerContext::create(
|
||||
vm, structure,
|
||||
JSValue::decode(onOpen),
|
||||
JSValue::decode(onMessage),
|
||||
JSValue::decode(onClose),
|
||||
JSValue::decode(onDrain),
|
||||
JSValue::decode(onError),
|
||||
JSValue::decode(onPing),
|
||||
JSValue::decode(onPong),
|
||||
JSValue::decode(server),
|
||||
app, vmPtr, ssl, publishToSelf);
|
||||
return JSValue::encode(context);
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnOpen(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnOpen(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnMessage(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnMessage(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnClose(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnClose(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnDrain(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnDrain(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnError(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnError(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnPing(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnPing(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setOnPong(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setOnPong(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setServer(JSWebSocketServerContext* context, Zig::GlobalObject* globalObject, JSC::EncodedJSValue value)
|
||||
{
|
||||
context->setServer(globalObject->vm(), JSValue::decode(value));
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnOpen(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onOpen());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnMessage(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onMessage());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnClose(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onClose());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnDrain(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onDrain());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnError(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onError());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnPing(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onPing());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getOnPong(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->onPong());
|
||||
}
|
||||
|
||||
extern "C" JSC::EncodedJSValue Bun__JSWebSocketServerContext__getServer(JSWebSocketServerContext* context)
|
||||
{
|
||||
return JSValue::encode(context->server());
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setApp(JSWebSocketServerContext* context, void* app)
|
||||
{
|
||||
context->setApp(app);
|
||||
}
|
||||
|
||||
extern "C" void* Bun__JSWebSocketServerContext__getApp(JSWebSocketServerContext* context)
|
||||
{
|
||||
return context->getApp();
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setVM(JSWebSocketServerContext* context, void* vm)
|
||||
{
|
||||
context->setVM(vm);
|
||||
}
|
||||
|
||||
extern "C" void* Bun__JSWebSocketServerContext__getVM(JSWebSocketServerContext* context)
|
||||
{
|
||||
return context->getVM();
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setSSL(JSWebSocketServerContext* context, bool ssl)
|
||||
{
|
||||
auto flags = context->getFlags();
|
||||
flags.ssl = ssl;
|
||||
context->setFlags(flags);
|
||||
}
|
||||
|
||||
extern "C" bool Bun__JSWebSocketServerContext__getSSL(JSWebSocketServerContext* context)
|
||||
{
|
||||
return context->getFlags().ssl;
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__setPublishToSelf(JSWebSocketServerContext* context, bool publish_to_self)
|
||||
{
|
||||
auto flags = context->getFlags();
|
||||
flags.publish_to_self = publish_to_self;
|
||||
context->setFlags(flags);
|
||||
}
|
||||
|
||||
extern "C" bool Bun__JSWebSocketServerContext__getPublishToSelf(JSWebSocketServerContext* context)
|
||||
{
|
||||
return context->getFlags().publish_to_self;
|
||||
}
|
||||
|
||||
extern "C" size_t Bun__JSWebSocketServerContext__getActiveConnections(JSWebSocketServerContext* context)
|
||||
{
|
||||
return context->getActiveConnections();
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__incrementActiveConnections(JSWebSocketServerContext* context)
|
||||
{
|
||||
context->incrementActiveConnections();
|
||||
}
|
||||
|
||||
extern "C" void Bun__JSWebSocketServerContext__decrementActiveConnections(JSWebSocketServerContext* context)
|
||||
{
|
||||
context->decrementActiveConnections();
|
||||
}
|
||||
|
||||
extern "C" JSWebSocketServerContext* Bun__JSWebSocketServerContext__fromJS(JSC::EncodedJSValue value)
|
||||
{
|
||||
JSValue jsValue = JSValue::decode(value);
|
||||
if (!jsValue.isCell())
|
||||
return nullptr;
|
||||
|
||||
JSCell* cell = jsValue.asCell();
|
||||
if (cell->type() != JSC::InternalFieldTupleType)
|
||||
return nullptr;
|
||||
|
||||
return jsCast<JSWebSocketServerContext*>(cell);
|
||||
}
|
||||
|
||||
Structure* createJSWebSocketServerContextStructure(JSC::VM& vm, Zig::GlobalObject* globalObject)
|
||||
{
|
||||
return JSWebSocketServerContext::createStructure(vm, globalObject);
|
||||
}
|
||||
|
||||
} // namespace Bun
|
||||
5
src/bun.js/bindings/JSWebSocketServerContext.h
Normal file
5
src/bun.js/bindings/JSWebSocketServerContext.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace Bun {
|
||||
JSC::Structure* createJSWebSocketServerContextStructure(JSC::VM&, Zig::GlobalObject*);
|
||||
}
|
||||
192
src/bun.js/bindings/JSWebSocketServerContext.zig
Normal file
192
src/bun.js/bindings/JSWebSocketServerContext.zig
Normal file
@@ -0,0 +1,192 @@
|
||||
const bun = @import("bun");
|
||||
const jsc = bun.jsc;
|
||||
|
||||
pub const JSWebSocketServerContext = opaque {
|
||||
pub fn create(
|
||||
globalObject: *jsc.JSGlobalObject,
|
||||
onOpen: jsc.JSValue,
|
||||
onMessage: jsc.JSValue,
|
||||
onClose: jsc.JSValue,
|
||||
onDrain: jsc.JSValue,
|
||||
onError: jsc.JSValue,
|
||||
onPing: jsc.JSValue,
|
||||
onPong: jsc.JSValue,
|
||||
server: jsc.JSValue,
|
||||
app: ?*anyopaque,
|
||||
vm: *jsc.VirtualMachine,
|
||||
ssl: bool,
|
||||
publishToSelf: bool,
|
||||
) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__create(
|
||||
globalObject,
|
||||
onOpen,
|
||||
onMessage,
|
||||
onClose,
|
||||
onDrain,
|
||||
onError,
|
||||
onPing,
|
||||
onPong,
|
||||
server,
|
||||
app,
|
||||
vm,
|
||||
ssl,
|
||||
publishToSelf,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn fromJS(value: jsc.JSValue) ?*JSWebSocketServerContext {
|
||||
return Bun__JSWebSocketServerContext__fromJS(value);
|
||||
}
|
||||
|
||||
pub fn setOnOpen(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnOpen(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setOnMessage(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnMessage(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setOnClose(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnClose(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setOnDrain(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnDrain(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setOnError(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnError(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setOnPing(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnPing(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setOnPong(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setOnPong(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn setServer(this: *JSWebSocketServerContext, globalObject: *jsc.JSGlobalObject, value: jsc.JSValue) void {
|
||||
Bun__JSWebSocketServerContext__setServer(this, globalObject, value);
|
||||
}
|
||||
|
||||
pub fn getOnOpen(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnOpen(this);
|
||||
}
|
||||
|
||||
pub fn getOnMessage(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnMessage(this);
|
||||
}
|
||||
|
||||
pub fn getOnClose(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnClose(this);
|
||||
}
|
||||
|
||||
pub fn getOnDrain(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnDrain(this);
|
||||
}
|
||||
|
||||
pub fn getOnError(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnError(this);
|
||||
}
|
||||
|
||||
pub fn getOnPing(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnPing(this);
|
||||
}
|
||||
|
||||
pub fn getOnPong(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getOnPong(this);
|
||||
}
|
||||
|
||||
pub fn getServer(this: *JSWebSocketServerContext) jsc.JSValue {
|
||||
return Bun__JSWebSocketServerContext__getServer(this);
|
||||
}
|
||||
|
||||
pub fn setApp(this: *JSWebSocketServerContext, app: ?*anyopaque) void {
|
||||
Bun__JSWebSocketServerContext__setApp(this, app);
|
||||
}
|
||||
|
||||
pub fn getApp(this: *JSWebSocketServerContext) ?*anyopaque {
|
||||
return Bun__JSWebSocketServerContext__getApp(this);
|
||||
}
|
||||
|
||||
pub fn setVM(this: *JSWebSocketServerContext, vm: *jsc.VirtualMachine) void {
|
||||
Bun__JSWebSocketServerContext__setVM(this, vm);
|
||||
}
|
||||
|
||||
pub fn getVM(this: *JSWebSocketServerContext) *jsc.VirtualMachine {
|
||||
return @ptrCast(@alignCast(Bun__JSWebSocketServerContext__getVM(this)));
|
||||
}
|
||||
|
||||
pub fn setSSL(this: *JSWebSocketServerContext, ssl: bool) void {
|
||||
Bun__JSWebSocketServerContext__setSSL(this, ssl);
|
||||
}
|
||||
|
||||
pub fn getSSL(this: *JSWebSocketServerContext) bool {
|
||||
return Bun__JSWebSocketServerContext__getSSL(this);
|
||||
}
|
||||
|
||||
pub fn setPublishToSelf(this: *JSWebSocketServerContext, publish_to_self: bool) void {
|
||||
Bun__JSWebSocketServerContext__setPublishToSelf(this, publish_to_self);
|
||||
}
|
||||
|
||||
pub fn getPublishToSelf(this: *JSWebSocketServerContext) bool {
|
||||
return Bun__JSWebSocketServerContext__getPublishToSelf(this);
|
||||
}
|
||||
|
||||
pub fn getActiveConnections(this: *JSWebSocketServerContext) usize {
|
||||
return Bun__JSWebSocketServerContext__getActiveConnections(this);
|
||||
}
|
||||
|
||||
pub fn incrementActiveConnections(this: *JSWebSocketServerContext) void {
|
||||
Bun__JSWebSocketServerContext__incrementActiveConnections(this);
|
||||
}
|
||||
|
||||
pub fn decrementActiveConnections(this: *JSWebSocketServerContext) void {
|
||||
Bun__JSWebSocketServerContext__decrementActiveConnections(this);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" fn Bun__JSWebSocketServerContext__create(
|
||||
*jsc.JSGlobalObject,
|
||||
jsc.JSValue, // onOpen
|
||||
jsc.JSValue, // onMessage
|
||||
jsc.JSValue, // onClose
|
||||
jsc.JSValue, // onDrain
|
||||
jsc.JSValue, // onError
|
||||
jsc.JSValue, // onPing
|
||||
jsc.JSValue, // onPong
|
||||
jsc.JSValue, // server
|
||||
?*anyopaque, // app
|
||||
*jsc.VirtualMachine, // vm
|
||||
bool, // ssl
|
||||
bool, // publishToSelf
|
||||
) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__fromJS(jsc.JSValue) ?*JSWebSocketServerContext;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnOpen(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnMessage(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnClose(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnDrain(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnError(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnPing(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setOnPong(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setServer(*JSWebSocketServerContext, *jsc.JSGlobalObject, jsc.JSValue) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnOpen(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnMessage(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnClose(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnDrain(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnError(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnPing(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getOnPong(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getServer(*JSWebSocketServerContext) jsc.JSValue;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setApp(*JSWebSocketServerContext, ?*anyopaque) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getApp(*JSWebSocketServerContext) ?*anyopaque;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setVM(*JSWebSocketServerContext, *jsc.VirtualMachine) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getVM(*JSWebSocketServerContext) *anyopaque;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setSSL(*JSWebSocketServerContext, bool) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getSSL(*JSWebSocketServerContext) bool;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__setPublishToSelf(*JSWebSocketServerContext, bool) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getPublishToSelf(*JSWebSocketServerContext) bool;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__getActiveConnections(*JSWebSocketServerContext) usize;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__incrementActiveConnections(*JSWebSocketServerContext) void;
|
||||
extern "C" fn Bun__JSWebSocketServerContext__decrementActiveConnections(*JSWebSocketServerContext) void;
|
||||
@@ -194,6 +194,7 @@
|
||||
#include <mutex>
|
||||
#include "JSBunRequest.h"
|
||||
#include "ServerRouteList.h"
|
||||
#include "JSWebSocketServerContext.h"
|
||||
|
||||
#if ENABLE(REMOTE_INSPECTOR)
|
||||
#include "JavaScriptCore/RemoteInspectorServer.h"
|
||||
@@ -2047,6 +2048,11 @@ void GlobalObject::finishCreation(VM& vm)
|
||||
init.set(Bun::createServerRouteListStructure(init.vm, static_cast<Zig::GlobalObject*>(init.owner)));
|
||||
});
|
||||
|
||||
m_JSWebSocketServerContextStructure.initLater(
|
||||
[](const JSC::LazyProperty<JSC::JSGlobalObject, Structure>::Initializer& init) {
|
||||
init.set(Bun::createJSWebSocketServerContextStructure(init.vm, static_cast<Zig::GlobalObject*>(init.owner)));
|
||||
});
|
||||
|
||||
m_JSBunRequestParamsPrototype.initLater(
|
||||
[](const JSC::LazyProperty<JSC::JSGlobalObject, JSObject>::Initializer& init) {
|
||||
init.set(Bun::createJSBunRequestParamsPrototype(init.vm, static_cast<Zig::GlobalObject*>(init.owner)));
|
||||
|
||||
@@ -620,6 +620,7 @@ public:
|
||||
V(public, LazyPropertyOfGlobalObject<Bun::Process>, m_processObject) \
|
||||
V(public, LazyPropertyOfGlobalObject<CustomGetterSetter>, m_lazyStackCustomGetterSetter) \
|
||||
V(public, LazyPropertyOfGlobalObject<Structure>, m_ServerRouteListStructure) \
|
||||
V(public, LazyPropertyOfGlobalObject<Structure>, m_JSWebSocketServerContextStructure) \
|
||||
V(public, LazyPropertyOfGlobalObject<Structure>, m_JSBunRequestStructure) \
|
||||
V(public, LazyPropertyOfGlobalObject<JSObject>, m_JSBunRequestParamsPrototype) \
|
||||
\
|
||||
|
||||
@@ -946,6 +946,7 @@ public:
|
||||
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSPublicKeyObject;
|
||||
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSPrivateKeyObject;
|
||||
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForServerRouteList;
|
||||
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForJSWebSocketServerContext;
|
||||
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBunRequest;
|
||||
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForBakeResponse;
|
||||
|
||||
|
||||
@@ -941,6 +941,7 @@ public:
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForJSHmac;
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForJSHash;
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForServerRouteList;
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForJSWebSocketServerContext;
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForBunRequest;
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForBakeResponse;
|
||||
std::unique_ptr<IsoSubspace> m_subspaceForJSDiffieHellman;
|
||||
|
||||
Reference in New Issue
Block a user