diff options
Diffstat (limited to 'src/bun.js/api')
-rw-r--r-- | src/bun.js/api/bun.zig | 21 | ||||
-rw-r--r-- | src/bun.js/api/bun/socket.zig | 71 | ||||
-rw-r--r-- | src/bun.js/api/server.zig | 130 |
3 files changed, 150 insertions, 72 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index e9b760de5..32bd0a9ec 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -942,7 +942,17 @@ fn doResolve( return null; } - return doResolveWithArgs(ctx, specifier.getZigString(ctx.ptr()), from.getZigString(ctx.ptr()), exception, false); + var is_esm = true; + if (args.nextEat()) |next| { + if (next.isBoolean()) { + is_esm = next.toBoolean(); + } else { + JSC.throwInvalidArguments("esm must be a boolean", .{}, ctx, exception); + return null; + } + } + + return doResolveWithArgs(ctx, specifier.getZigString(ctx.ptr()), from.getZigString(ctx.ptr()), exception, is_esm, false); } fn doResolveWithArgs( @@ -950,6 +960,7 @@ fn doResolveWithArgs( specifier: ZigString, from: ZigString, exception: js.ExceptionRef, + is_esm: bool, comptime is_file_path: bool, ) ?JSC.JSValue { var errorable: ErrorableZigString = undefined; @@ -960,6 +971,7 @@ fn doResolveWithArgs( ctx.ptr(), specifier, from, + is_esm, ); } else { VirtualMachine.resolveForAPI( @@ -967,6 +979,7 @@ fn doResolveWithArgs( ctx.ptr(), specifier, from, + is_esm, ); } @@ -1010,10 +1023,11 @@ export fn Bun__resolve( global: *JSGlobalObject, specifier: JSValue, source: JSValue, + is_esm: bool, ) JSC.JSValue { var exception_ = [1]JSC.JSValueRef{null}; var exception = &exception_; - const value = doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, true) orelse { + const value = doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, is_esm, true) orelse { return JSC.JSPromise.rejectedPromiseValue(global, JSC.JSValue.fromRef(exception[0])); }; return JSC.JSPromise.resolvedPromiseValue(global, value); @@ -1023,10 +1037,11 @@ export fn Bun__resolveSync( global: *JSGlobalObject, specifier: JSValue, source: JSValue, + is_esm: bool, ) JSC.JSValue { var exception_ = [1]JSC.JSValueRef{null}; var exception = &exception_; - return doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, true) orelse { + return doResolveWithArgs(global, specifier.getZigString(global), source.getZigString(global), exception, is_esm, true) orelse { return JSC.JSValue.fromRef(exception[0]); }; } diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index f4dcfb01c..911dc9e89 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -232,38 +232,65 @@ pub const SocketConfig = struct { } } - if (opts.getTruthy(globalObject, "hostname")) |hostname| { - if (hostname.isEmptyOrUndefinedOrNull() or !hostname.isString()) { - exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a string", .{}, globalObject).asObjectRef(); - return null; - } + hostname_or_unix: { + if (opts.getTruthy(globalObject, "unix")) |unix_socket| { + if (!unix_socket.isString()) { + exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a string", .{}, globalObject).asObjectRef(); + return null; + } - const port_value = opts.get(globalObject, "port") orelse JSValue.zero; - if (port_value.isEmptyOrUndefinedOrNull() or !port_value.isNumber() or port_value.toInt64() > std.math.maxInt(u16) or port_value.toInt64() < 0) { - exception.* = JSC.toInvalidArguments("Expected \"port\" to be a number between 0 and 65535", .{}, globalObject).asObjectRef(); - return null; - } + hostname_or_unix = unix_socket.getZigString(globalObject).toSlice(bun.default_allocator); - hostname_or_unix = hostname.getZigString(globalObject).toSlice(bun.default_allocator); - port = port_value.toU16(); + if (strings.hasPrefixComptime(hostname_or_unix.slice(), "file://") or strings.hasPrefixComptime(hostname_or_unix.slice(), "unix://") or strings.hasPrefixComptime(hostname_or_unix.slice(), "sock://")) { + hostname_or_unix.ptr += 7; + hostname_or_unix.len -|= 7; + } - if (hostname_or_unix.len == 0) { - exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a non-empty string", .{}, globalObject).asObjectRef(); - return null; - } - } else if (opts.getTruthy(globalObject, "unix")) |unix_socket| { - if (unix_socket.isEmptyOrUndefinedOrNull() or !unix_socket.isString()) { - exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a string", .{}, globalObject).asObjectRef(); - return null; + if (hostname_or_unix.len > 0) { + break :hostname_or_unix; + } } - hostname_or_unix = unix_socket.getZigString(globalObject).toSlice(bun.default_allocator); + if (opts.getTruthy(globalObject, "hostname")) |hostname| { + if (!hostname.isString()) { + exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a string", .{}, globalObject).asObjectRef(); + return null; + } + + var port_value = opts.get(globalObject, "port") orelse JSValue.zero; + hostname_or_unix = hostname.getZigString(globalObject).toSlice(bun.default_allocator); + + if (port_value.isEmptyOrUndefinedOrNull() and hostname_or_unix.len > 0) { + const parsed_url = bun.URL.parse(hostname_or_unix.slice()); + if (parsed_url.getPort()) |port_num| { + port_value = JSValue.jsNumber(port_num); + hostname_or_unix.ptr = parsed_url.hostname.ptr; + hostname_or_unix.len = @truncate(u32, parsed_url.hostname.len); + } + } + + if (port_value.isEmptyOrUndefinedOrNull() or !port_value.isNumber() or port_value.toInt64() > std.math.maxInt(u16) or port_value.toInt64() < 0) { + exception.* = JSC.toInvalidArguments("Expected \"port\" to be a number between 0 and 65535", .{}, globalObject).asObjectRef(); + return null; + } + + port = port_value.toU16(); + + if (hostname_or_unix.len == 0) { + exception.* = JSC.toInvalidArguments("Expected \"hostname\" to be a non-empty string", .{}, globalObject).asObjectRef(); + return null; + } + + if (hostname_or_unix.len > 0) { + break :hostname_or_unix; + } + } if (hostname_or_unix.len == 0) { exception.* = JSC.toInvalidArguments("Expected \"unix\" to be a non-empty string", .{}, globalObject).asObjectRef(); return null; } - } else { + exception.* = JSC.toInvalidArguments("Expected either \"hostname\" or \"unix\"", .{}, globalObject).asObjectRef(); return null; } diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index f47ee9fc0..137d164f0 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -2135,8 +2135,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp const result = JSC.C.JSObjectCallAsFunctionReturnValue(this.server.globalThis, this.server.config.onError.asObjectRef(), this.server.thisObject.asObjectRef(), 1, &args); if (!result.isEmptyOrUndefinedOrNull()) { - if (result.isError() or result.isAggregateError(this.server.globalThis)) { - this.finishRunningErrorHandler(result, status); + if (result.toError()) |err| { + this.finishRunningErrorHandler(err, status); return; } else if (result.as(Response)) |response| { this.render(response); @@ -2514,7 +2514,10 @@ pub const WebSocketServer = struct { active_connections: usize = 0, /// used by publish() - ssl: bool = false, + flags: packed struct(u2) { + ssl: bool = false, + publish_to_self: bool = true, + } = .{}, pub fn fromJS(globalObject: *JSC.JSGlobalObject, object: JSC.JSValue) ?Handler { var handler = Handler{ .globalObject = globalObject }; @@ -2752,6 +2755,17 @@ pub const WebSocketServer = struct { } } + if (object.get(globalObject, "publishToSelf")) |value| { + if (!value.isUndefinedOrNull()) { + if (!value.isBoolean()) { + globalObject.throwInvalidArguments("websocket expects publishToSelf to be a boolean", .{}); + return null; + } + + server.handler.flags.publish_to_self = value.toBoolean(); + } + } + server.protect(); return server; } @@ -3025,7 +3039,9 @@ pub const ServerWebSocket = struct { log("publish() closed", .{}); return JSValue.jsNumber(0); }; - const ssl = this.handler.ssl; + const flags = this.handler.flags; + const ssl = flags.ssl; + const publish_to_self = flags.publish_to_self; const topic_value = args.ptr[0]; const message_value = args.ptr[1]; @@ -3051,16 +3067,23 @@ pub const ServerWebSocket = struct { return .zero; } - if (message_value.asArrayBuffer(globalThis)) |buffer| { + if (message_value.asArrayBuffer(globalThis)) |array_buffer| { + const buffer = array_buffer.slice(); + if (buffer.len == 0) { globalThis.throw("publish requires a non-empty message", .{}); return .zero; } + const result = if (!publish_to_self) + this.websocket.publish(topic_slice.slice(), buffer, .binary, compress) + else + uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .binary, compress); + return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent - @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer.slice(), .binary, compress))) * @intCast(i32, @truncate(u31, buffer.len)), + if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0), ); } @@ -3072,10 +3095,16 @@ pub const ServerWebSocket = struct { } const buffer = string_slice.slice(); + + const result = if (!publish_to_self) + this.websocket.publish(topic_slice.slice(), buffer, .text, compress) + else + uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress); + return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent - @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress))) * @intCast(i32, @truncate(u31, buffer.len)), + if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0), ); } @@ -3099,7 +3128,9 @@ pub const ServerWebSocket = struct { log("publish() closed", .{}); return JSValue.jsNumber(0); }; - const ssl = this.handler.ssl; + const flags = this.handler.flags; + const ssl = flags.ssl; + const publish_to_self = flags.publish_to_self; const topic_value = args.ptr[0]; const message_value = args.ptr[1]; @@ -3132,10 +3163,16 @@ pub const ServerWebSocket = struct { } const buffer = string_slice.slice(); + + const result = if (!publish_to_self) + this.websocket.publish(topic_slice.slice(), buffer, .text, compress) + else + uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress); + return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent - @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress))) * @intCast(i32, @truncate(u31, buffer.len)), + if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0), ); } @@ -3156,7 +3193,9 @@ pub const ServerWebSocket = struct { log("publish() closed", .{}); return JSValue.jsNumber(0); }; - const ssl = this.handler.ssl; + const flags = this.handler.flags; + const ssl = flags.ssl; + const publish_to_self = flags.publish_to_self; const topic_value = args.ptr[0]; const message_value = args.ptr[1]; const compress_value = args.ptr[2]; @@ -3180,19 +3219,25 @@ pub const ServerWebSocket = struct { globalThis.throw("publishBinary requires a non-empty message", .{}); return .zero; } - const buffer = message_value.asArrayBuffer(globalThis) orelse { + const array_buffer = message_value.asArrayBuffer(globalThis) orelse { globalThis.throw("publishBinary expects an ArrayBufferView", .{}); return .zero; }; + const buffer = array_buffer.slice(); if (buffer.len == 0) { return JSC.JSValue.jsNumber(0); } + const result = if (!publish_to_self) + this.websocket.publish(topic_slice.slice(), buffer, .binary, compress) + else + uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .binary, compress); + return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent - @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer.slice(), .binary, compress))) * @intCast(i32, @truncate(u31, buffer.len)), + if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0), ); } @@ -3200,13 +3245,15 @@ pub const ServerWebSocket = struct { this: *ServerWebSocket, globalThis: *JSC.JSGlobalObject, topic_str: *JSC.JSString, - buffer: *JSC.JSUint8Array, + array: *JSC.JSUint8Array, ) callconv(.C) JSC.JSValue { var app = this.handler.app orelse { log("publish() closed", .{}); return JSValue.jsNumber(0); }; - const ssl = this.handler.ssl; + const flags = this.handler.flags; + const ssl = flags.ssl; + const publish_to_self = flags.publish_to_self; var topic_slice = topic_str.toSlice(globalThis, bun.default_allocator); defer topic_slice.deinit(); @@ -3217,30 +3264,20 @@ pub const ServerWebSocket = struct { const compress = true; - const slice = buffer.slice(); - if (slice.len == 0) { + const buffer = array.slice(); + if (buffer.len == 0) { return JSC.JSValue.jsNumber(0); } + const result = if (!publish_to_self) + this.websocket.publish(topic_slice.slice(), buffer, .binary, compress) + else + uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .binary, compress); + return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent - @as( - i32, - @boolToInt( - uws.AnyWebSocket.publishWithOptions( - ssl, - app, - topic_slice.slice(), - slice, - .binary, - compress, - ), - ), - ) * @intCast( - i32, - @truncate(u31, slice.len), - ), + if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0), ); } @@ -3254,7 +3291,9 @@ pub const ServerWebSocket = struct { log("publish() closed", .{}); return JSValue.jsNumber(0); }; - const ssl = this.handler.ssl; + const flags = this.handler.flags; + const ssl = flags.ssl; + const publish_to_self = flags.publish_to_self; var topic_slice = topic_str.toSlice(globalThis, bun.default_allocator); defer topic_slice.deinit(); @@ -3266,24 +3305,21 @@ pub const ServerWebSocket = struct { const compress = true; const slice = str.toSlice(globalThis, bun.default_allocator); - if (slice.len == 0) { + defer slice.deinit(); + const buffer = slice.slice(); + + if (buffer.len == 0) { return JSC.JSValue.jsNumber(0); } + const result = if (!publish_to_self) + this.websocket.publish(topic_slice.slice(), buffer, .text, compress) + else + uws.AnyWebSocket.publishWithOptions(ssl, app, topic_slice.slice(), buffer, .text, compress); return JSValue.jsNumber( // if 0, return 0 // else return number of bytes sent - @as(i32, @boolToInt(uws.AnyWebSocket.publishWithOptions( - ssl, - app, - topic_slice.slice(), - slice.slice(), - .text, - compress, - ))) * @intCast( - i32, - @truncate(u31, slice.len), - ), + if (result) @intCast(i32, @truncate(u31, buffer.len)) else @as(i32, 0), ); } @@ -4107,7 +4143,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { } if (new_config.websocket) |*ws| { - ws.handler.ssl = ssl_enabled; + 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(); @@ -4671,7 +4707,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { if (this.config.websocket) |*websocket| { websocket.globalObject = this.globalThis; websocket.handler.app = this.app; - websocket.handler.ssl = ssl_enabled; + websocket.handler.flags.ssl = ssl_enabled; this.app.ws( "/*", this, |