diff --git a/packages/bun-types/serve.d.ts b/packages/bun-types/serve.d.ts index 78b0eea3d4..2558bb5944 100644 --- a/packages/bun-types/serve.d.ts +++ b/packages/bun-types/serve.d.ts @@ -1082,6 +1082,15 @@ declare module "bun" { */ readonly hostname: string | undefined; + /** + * The protocol the server is listening on. + * + * - "http" for normal servers + * - "https" when TLS is enabled + * - null for unix sockets or when unavailable + */ + readonly protocol: "http" | "https" | null; + /** * Is the server running in development mode? * diff --git a/src/bun.js/api/FFIObject.zig b/src/bun.js/api/FFIObject.zig index f7e2b0a3b8..956900a7d9 100644 --- a/src/bun.js/api/FFIObject.zig +++ b/src/bun.js/api/FFIObject.zig @@ -16,11 +16,22 @@ pub const dom_call = DOMCall("FFI", @This(), "ptr", DOMEffect.forRead(.TypedArra pub fn toJS(globalObject: *jsc.JSGlobalObject) jsc.JSValue { const object = jsc.JSValue.createEmptyObject(globalObject, comptime std.meta.fieldNames(@TypeOf(fields)).len + 2); inline for (comptime std.meta.fieldNames(@TypeOf(fields))) |field| { - object.put( - globalObject, - comptime ZigString.static(field), - jsc.JSFunction.create(globalObject, field, @field(fields, field), 1, .{}), - ); + if (comptime bun.strings.eqlComptime(field, "CString")) { + // CString needs to be callable as a constructor for backward compatibility. + // Pass the same function as the constructor so `new CString(ptr)` works. + const func = jsc.toJSHostFn(@field(fields, field)); + object.put( + globalObject, + comptime ZigString.static(field), + jsc.JSFunction.create(globalObject, field, func, 1, .{ .constructor = func }), + ); + } else { + object.put( + globalObject, + comptime ZigString.static(field), + jsc.JSFunction.create(globalObject, field, @field(fields, field), 1, .{}), + ); + } } dom_call.put(globalObject, object); diff --git a/test/regression/issue/25231.test.ts b/test/regression/issue/25231.test.ts new file mode 100644 index 0000000000..0afabca005 --- /dev/null +++ b/test/regression/issue/25231.test.ts @@ -0,0 +1,32 @@ +// https://github.com/oven-sh/bun/issues/25231 +// Bun.FFI.CString should be callable as a constructor (new CString(ptr)) + +import { expect, test } from "bun:test"; + +test("Bun.FFI.CString is callable with new", () => { + const { CString, ptr } = Bun.FFI; + + // Create a buffer with a null-terminated string + const buf = Buffer.from("hello\0"); + const ptrValue = ptr(buf); + + // CString should be callable with new + const result = new CString(ptrValue, 0, 5); + + // The result should be the string "hello" + expect(String(result)).toBe("hello"); +}); + +test("Bun.FFI.CString can be called without new", () => { + const { CString, ptr } = Bun.FFI; + + // Create a buffer with a null-terminated string + const buf = Buffer.from("hello\0"); + const ptrValue = ptr(buf); + + // CString should also be callable without new + const result = CString(ptrValue, 0, 5); + + // The result should be the string "hello" + expect(result).toBe("hello"); +});