aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-08-25 21:08:41 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-25 21:08:41 -0700
commitd98a93c3181426ea0565193303d3e63d3796231c (patch)
tree71a8d96bc4b75d902643ec877c03070cca8fcf45
parentf70bb2497b2406e89afec3ee8a36a3b10ef66334 (diff)
downloadbun-d98a93c3181426ea0565193303d3e63d3796231c.tar.gz
bun-d98a93c3181426ea0565193303d3e63d3796231c.tar.zst
bun-d98a93c3181426ea0565193303d3e63d3796231c.zip
Automatically hot reload Bun.serve() (#4344)
* Automatically hot reload Bun.serve() * Update doc * Update example --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r--docs/runtime/hot.md38
-rw-r--r--examples/bun-hot-websockets.js4
-rw-r--r--packages/bun-types/bun.d.ts24
-rw-r--r--src/bun.js/api/bun.zig60
-rw-r--r--src/bun.js/api/server.classes.ts4
-rw-r--r--src/bun.js/api/server.zig108
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp144
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.h4
-rw-r--r--src/bun.js/bindings/generated_classes.zig104
-rw-r--r--src/bun.js/javascript.zig8
-rw-r--r--src/bun.js/rare_data.zig62
11 files changed, 503 insertions, 57 deletions
diff --git a/docs/runtime/hot.md b/docs/runtime/hot.md
index 0797187de..7f0b04c28 100644
--- a/docs/runtime/hot.md
+++ b/docs/runtime/hot.md
@@ -102,55 +102,25 @@ Traditional file watchers like `nodemon` restart the entire process, so HTTP ser
Bun provides the following simplified API for implementing HTTP servers. Refer to [API > HTTP](/docs/api/http) for full details.
```ts#server.ts
-import {type Serve} from "bun";
+import {serve} from "bun";
globalThis.count ??= 0;
globalThis.count++;
-export default {
+serve({
fetch(req: Request) {
return new Response(`Reloaded ${globalThis.count} times`);
},
port: 3000,
-} satisfies Serve;
+});
```
The file above is simply exporting an object with a `fetch` handler defined. When this file is executed, Bun interprets this as an HTTP server and passes the exported object into `Bun.serve`.
-Unlike an explicit call to `Bun.serve`, the object-based syntax works out of the box with `bun --hot`. When you save the file, your HTTP server be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
+When you save the file, your HTTP server be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
{% image src="https://user-images.githubusercontent.com/709451/195477632-5fd8a73e-014d-4589-9ba2-e075ad9eb040.gif" alt="Bun vs Nodemon refresh speeds" caption="Bun on the left, Nodemon on the right." /%}
-For more fine-grained control, you can use the `Bun.serve` API directly and handle the server reloading manually.
-
-```ts#server.ts
-import type {Serve, Server} from "bun";
-
-// make TypeScript happy
-declare global {
- var count: number;
- var server: Server;
-}
-
-globalThis.count ??= 0;
-globalThis.count++;
-
-// define server parameters
-const serverOptions: Serve = {
- port: 3000,
- fetch(req) {
- return new Response(`Reloaded ${globalThis.count} times`);
- }
-};
-
-if (!globalThis.server) {
- globalThis.server = Bun.serve(serverOptions);
-} else {
- // reload server
- globalThis.server.reload(serverOptions);
-}
-```
-
{% callout %}
**Note** — In a future version of Bun, support for Vite's `import.meta.hot` is planned to enable better lifecycle management for hot reloading and to align with the ecosystem.
diff --git a/examples/bun-hot-websockets.js b/examples/bun-hot-websockets.js
index 7cdaf0f02..37d823a22 100644
--- a/examples/bun-hot-websockets.js
+++ b/examples/bun-hot-websockets.js
@@ -38,7 +38,7 @@ const styles = css`
}
`;
-export default {
+Bun.serve({
websocket: {
message(ws, msg) {
ws.send(styles);
@@ -86,4 +86,4 @@ export default {
},
);
},
-};
+});
diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts
index 76db42715..2df53a301 100644
--- a/packages/bun-types/bun.d.ts
+++ b/packages/bun-types/bun.d.ts
@@ -1820,6 +1820,21 @@ declare module "bun" {
this: Server,
request: Errorlike,
) => Response | Promise<Response> | undefined | void | Promise<undefined>;
+
+ /**
+ * Uniquely identify a server instance with an ID
+ *
+ * ### When bun is started with the `--hot` flag
+ *
+ * This string will be used to hot reload the server without interrupting
+ * pending requests or websockets. If not provided, a value will be
+ * generated. To disable hot reloading, set this value to `null`.
+ *
+ * ### When bun is not started with the `--hot` flag
+ *
+ * This string will currently do nothing. But in the future it could be useful for logs or metrics.
+ */
+ id?: string | null;
}
export type AnyFunction = (..._: any[]) => any;
@@ -2345,6 +2360,15 @@ declare module "bun" {
*
*/
readonly development: boolean;
+
+ /**
+ * An identifier of the server instance
+ *
+ * When bun is started with the `--hot` flag, this ID is used to hot reload the server without interrupting pending requests or websockets.
+ *
+ * When bun is not started with the `--hot` flag, this ID is currently unused.
+ */
+ readonly id: string;
}
/**
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index a9d7ed970..71b065993 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -2481,7 +2481,7 @@ pub fn serve(
callframe: *JSC.CallFrame,
) callconv(.C) JSC.JSValue {
const arguments = callframe.arguments(2).slice();
- const config: JSC.API.ServerConfig = brk: {
+ var config: JSC.API.ServerConfig = brk: {
var exception_ = [1]JSC.JSValueRef{null};
var exception = &exception_;
@@ -2497,6 +2497,40 @@ pub fn serve(
var exception_value: *JSC.JSValue = undefined;
+ if (config.allow_hot) {
+ if (globalObject.bunVM().hotMap()) |hot| {
+ if (config.id.len == 0) {
+ config.id = config.computeID(globalObject.allocator());
+ }
+
+ if (hot.getEntry(config.id)) |entry| {
+ switch (entry.tag()) {
+ @field(@TypeOf(entry.tag()), @typeName(JSC.API.HTTPServer)) => {
+ var server: *JSC.API.HTTPServer = entry.as(JSC.API.HTTPServer);
+ server.onReloadFromZig(&config, globalObject);
+ return server.thisObject;
+ },
+ @field(@TypeOf(entry.tag()), @typeName(JSC.API.DebugHTTPServer)) => {
+ var server: *JSC.API.DebugHTTPServer = entry.as(JSC.API.DebugHTTPServer);
+ server.onReloadFromZig(&config, globalObject);
+ return server.thisObject;
+ },
+ @field(@TypeOf(entry.tag()), @typeName(JSC.API.DebugHTTPSServer)) => {
+ var server: *JSC.API.DebugHTTPSServer = entry.as(JSC.API.DebugHTTPSServer);
+ server.onReloadFromZig(&config, globalObject);
+ return server.thisObject;
+ },
+ @field(@TypeOf(entry.tag()), @typeName(JSC.API.HTTPSServer)) => {
+ var server: *JSC.API.HTTPSServer = entry.as(JSC.API.HTTPSServer);
+ server.onReloadFromZig(&config, globalObject);
+ return server.thisObject;
+ },
+ else => {},
+ }
+ }
+ }
+ }
+
// Listen happens on the next tick!
// This is so we can return a Server object
if (config.ssl_config != null) {
@@ -2515,6 +2549,12 @@ pub fn serve(
obj.protect();
server.thisObject = obj;
+
+ if (config.allow_hot) {
+ if (globalObject.bunVM().hotMap()) |hot| {
+ hot.insert(config.id, server);
+ }
+ }
return obj;
} else {
var server = JSC.API.HTTPSServer.init(config, globalObject.ptr());
@@ -2530,6 +2570,12 @@ pub fn serve(
const obj = server.toJS(globalObject);
obj.protect();
server.thisObject = obj;
+
+ if (config.allow_hot) {
+ if (globalObject.bunVM().hotMap()) |hot| {
+ hot.insert(config.id, server);
+ }
+ }
return obj;
}
} else {
@@ -2547,6 +2593,12 @@ pub fn serve(
const obj = server.toJS(globalObject);
obj.protect();
server.thisObject = obj;
+
+ if (config.allow_hot) {
+ if (globalObject.bunVM().hotMap()) |hot| {
+ hot.insert(config.id, server);
+ }
+ }
return obj;
} else {
var server = JSC.API.HTTPServer.init(config, globalObject.ptr());
@@ -2563,6 +2615,12 @@ pub fn serve(
obj.protect();
server.thisObject = obj;
+
+ if (config.allow_hot) {
+ if (globalObject.bunVM().hotMap()) |hot| {
+ hot.insert(config.id, server);
+ }
+ }
return obj;
}
}
diff --git a/src/bun.js/api/server.classes.ts b/src/bun.js/api/server.classes.ts
index 7db8a3444..544f37ce6 100644
--- a/src/bun.js/api/server.classes.ts
+++ b/src/bun.js/api/server.classes.ts
@@ -27,6 +27,10 @@ function generate(name) {
port: {
getter: "getPort",
},
+ id: {
+ getter: "getId",
+ cache: true,
+ },
pendingRequests: {
getter: "getPendingRequests",
},
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 81a50a5a7..01f06ebf2 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -158,6 +158,36 @@ pub const ServerConfig = struct {
inspector: bool = false,
reuse_port: bool = false,
+ id: []const u8 = "",
+ allow_hot: bool = true,
+
+ pub fn computeID(this: *const ServerConfig, allocator: std.mem.Allocator) []const u8 {
+ var arraylist = std.ArrayList(u8).init(allocator);
+ var writer = arraylist.writer();
+
+ writer.writeAll("[http]-") catch {};
+ switch (this.address) {
+ .tcp => {
+ if (this.address.tcp.hostname) |host| {
+ writer.print("tcp:{s}:{d}", .{
+ bun.sliceTo(host, 0),
+ this.address.tcp.port,
+ }) catch {};
+ } else {
+ writer.print("tcp:localhost:{d}", .{
+ this.address.tcp.port,
+ }) catch {};
+ }
+ },
+ .unix => {
+ writer.print("unix:{s}", .{
+ bun.sliceTo(this.address.unix, 0),
+ }) catch {};
+ },
+ }
+
+ return arraylist.items;
+ }
pub const SSLConfig = struct {
server_name: [*c]const u8 = null,
@@ -794,6 +824,23 @@ pub const ServerConfig = struct {
}
}
+ if (arg.get(global, "id")) |id| {
+ if (id.isUndefinedOrNull()) {
+ args.allow_hot = false;
+ } else {
+ const id_str = id.toSlice(
+ global,
+ bun.default_allocator,
+ );
+
+ if (id_str.len > 0) {
+ args.id = (id_str.cloneIfNeeded(bun.default_allocator) catch unreachable).slice();
+ } else {
+ args.allow_hot = false;
+ }
+ }
+ }
+
if (arg.get(global, "development")) |dev| {
args.development = dev.coerce(bool, global);
args.reuse_port = !args.development;
@@ -4867,26 +4914,8 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
return JSC.jsBoolean(true);
}
- pub fn onReload(
- this: *ThisServer,
- globalThis: *JSC.JSGlobalObject,
- callframe: *JSC.CallFrame,
- ) callconv(.C) JSC.JSValue {
- const arguments = callframe.arguments(1).slice();
- if (arguments.len < 1) {
- globalThis.throwNotEnoughArguments("reload", 1, 0);
- return .zero;
- }
-
- var args_slice = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments);
- defer args_slice.deinit();
- var exception_ref = [_]JSC.C.JSValueRef{null};
- var exception: JSC.C.ExceptionRef = &exception_ref;
- var new_config = ServerConfig.fromJS(globalThis, &args_slice, exception);
- if (exception.* != null) {
- globalThis.throwValue(exception_ref[0].?.value());
- return .zero;
- }
+ pub fn onReloadFromZig(this: *ThisServer, new_config: *ServerConfig, globalThis: *JSC.JSGlobalObject) void {
+ httplog("onReload", .{});
// only reload those two
if (this.config.onRequest != new_config.onRequest) {
@@ -4915,6 +4944,30 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
this.config.websocket = ws.*;
} // we don't remove it
}
+ }
+
+ pub fn onReload(
+ this: *ThisServer,
+ globalThis: *JSC.JSGlobalObject,
+ callframe: *JSC.CallFrame,
+ ) callconv(.C) JSC.JSValue {
+ const arguments = callframe.arguments(1).slice();
+ if (arguments.len < 1) {
+ globalThis.throwNotEnoughArguments("reload", 1, 0);
+ return .zero;
+ }
+
+ var args_slice = JSC.Node.ArgumentsSlice.init(globalThis.bunVM(), arguments);
+ defer args_slice.deinit();
+ var exception_ref = [_]JSC.C.JSValueRef{null};
+ var exception: JSC.C.ExceptionRef = &exception_ref;
+ var new_config = ServerConfig.fromJS(globalThis, &args_slice, exception);
+ if (exception.* != null) {
+ globalThis.throwValue(exception_ref[0].?.value());
+ return .zero;
+ }
+
+ this.onReloadFromZig(&new_config, globalThis);
return this.thisObject;
}
@@ -5066,6 +5119,15 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
return JSC.JSValue.jsNumber(listener.getLocalPort());
}
+ pub fn getId(
+ this: *ThisServer,
+ globalThis: *JSC.JSGlobalObject,
+ ) callconv(.C) JSC.JSValue {
+ var str = bun.String.create(this.config.id);
+ defer str.deref();
+ return str.toJS(globalThis);
+ }
+
pub fn getPendingRequests(
this: *ThisServer,
_: *JSC.JSGlobalObject,
@@ -5170,6 +5232,12 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
}
pub fn stop(this: *ThisServer, abrupt: bool) void {
+ if (this.config.allow_hot and this.config.id.len > 0) {
+ if (this.globalThis.bunVM().hotMap()) |hot| {
+ hot.remove(this.config.id);
+ }
+ }
+
this.stopListening(abrupt);
this.deinitIfWeCan();
}
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp
index 0ab7a1b5d..497408632 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.cpp
+++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp
@@ -4176,6 +4176,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPSServerPrototype__fetchCallback);
extern "C" JSC::EncodedJSValue DebugHTTPSServerPrototype__getHostname(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(DebugHTTPSServerPrototype__hostnameGetterWrap);
+extern "C" JSC::EncodedJSValue DebugHTTPSServerPrototype__getId(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(DebugHTTPSServerPrototype__idGetterWrap);
+
extern "C" JSC::EncodedJSValue DebugHTTPSServerPrototype__getPendingRequests(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(DebugHTTPSServerPrototype__pendingRequestsGetterWrap);
@@ -4206,6 +4209,7 @@ static const HashTableValue JSDebugHTTPSServerPrototypeTableValues[] = {
{ "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__developmentGetterWrap, 0 } },
{ "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPSServerPrototype__fetchCallback, 1 } },
{ "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__hostnameGetterWrap, 0 } },
+ { "id"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__idGetterWrap, 0 } },
{ "pendingRequests"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__pendingRequestsGetterWrap, 0 } },
{ "pendingWebSockets"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__pendingWebSocketsGetterWrap, 0 } },
{ "port"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPSServerPrototype__portGetterWrap, 0 } },
@@ -4301,6 +4305,37 @@ extern "C" EncodedJSValue DebugHTTPSServerPrototype__hostnameGetCachedValue(JSC:
return JSValue::encode(thisObject->m_hostname.get());
}
+JSC_DEFINE_CUSTOM_GETTER(DebugHTTPSServerPrototype__idGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSDebugHTTPSServer* thisObject = jsCast<JSDebugHTTPSServer*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ if (JSValue cachedValue = thisObject->m_id.get())
+ return JSValue::encode(cachedValue);
+
+ JSC::JSValue result = JSC::JSValue::decode(
+ DebugHTTPSServerPrototype__getId(thisObject->wrapped(), globalObject));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ thisObject->m_id.set(vm, thisObject, result);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+}
+
+extern "C" void DebugHTTPSServerPrototype__idSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value)
+{
+ auto& vm = globalObject->vm();
+ auto* thisObject = jsCast<JSDebugHTTPSServer*>(JSValue::decode(thisValue));
+ thisObject->m_id.set(vm, thisObject, JSValue::decode(value));
+}
+
+extern "C" EncodedJSValue DebugHTTPSServerPrototype__idGetCachedValue(JSC::EncodedJSValue thisValue)
+{
+ auto* thisObject = jsCast<JSDebugHTTPSServer*>(JSValue::decode(thisValue));
+ return JSValue::encode(thisObject->m_id.get());
+}
+
JSC_DEFINE_CUSTOM_GETTER(DebugHTTPSServerPrototype__pendingRequestsGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = lexicalGlobalObject->vm();
@@ -4564,6 +4599,7 @@ void JSDebugHTTPSServer::visitAdditionalChildren(Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
visitor.append(thisObject->m_hostname);
+ visitor.append(thisObject->m_id);
}
DEFINE_VISIT_ADDITIONAL_CHILDREN(JSDebugHTTPSServer);
@@ -4622,6 +4658,9 @@ JSC_DECLARE_HOST_FUNCTION(DebugHTTPServerPrototype__fetchCallback);
extern "C" JSC::EncodedJSValue DebugHTTPServerPrototype__getHostname(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(DebugHTTPServerPrototype__hostnameGetterWrap);
+extern "C" JSC::EncodedJSValue DebugHTTPServerPrototype__getId(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(DebugHTTPServerPrototype__idGetterWrap);
+
extern "C" JSC::EncodedJSValue DebugHTTPServerPrototype__getPendingRequests(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(DebugHTTPServerPrototype__pendingRequestsGetterWrap);
@@ -4652,6 +4691,7 @@ static const HashTableValue JSDebugHTTPServerPrototypeTableValues[] = {
{ "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__developmentGetterWrap, 0 } },
{ "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, DebugHTTPServerPrototype__fetchCallback, 1 } },
{ "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__hostnameGetterWrap, 0 } },
+ { "id"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__idGetterWrap, 0 } },
{ "pendingRequests"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__pendingRequestsGetterWrap, 0 } },
{ "pendingWebSockets"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__pendingWebSocketsGetterWrap, 0 } },
{ "port"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, DebugHTTPServerPrototype__portGetterWrap, 0 } },
@@ -4747,6 +4787,37 @@ extern "C" EncodedJSValue DebugHTTPServerPrototype__hostnameGetCachedValue(JSC::
return JSValue::encode(thisObject->m_hostname.get());
}
+JSC_DEFINE_CUSTOM_GETTER(DebugHTTPServerPrototype__idGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSDebugHTTPServer* thisObject = jsCast<JSDebugHTTPServer*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ if (JSValue cachedValue = thisObject->m_id.get())
+ return JSValue::encode(cachedValue);
+
+ JSC::JSValue result = JSC::JSValue::decode(
+ DebugHTTPServerPrototype__getId(thisObject->wrapped(), globalObject));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ thisObject->m_id.set(vm, thisObject, result);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+}
+
+extern "C" void DebugHTTPServerPrototype__idSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value)
+{
+ auto& vm = globalObject->vm();
+ auto* thisObject = jsCast<JSDebugHTTPServer*>(JSValue::decode(thisValue));
+ thisObject->m_id.set(vm, thisObject, JSValue::decode(value));
+}
+
+extern "C" EncodedJSValue DebugHTTPServerPrototype__idGetCachedValue(JSC::EncodedJSValue thisValue)
+{
+ auto* thisObject = jsCast<JSDebugHTTPServer*>(JSValue::decode(thisValue));
+ return JSValue::encode(thisObject->m_id.get());
+}
+
JSC_DEFINE_CUSTOM_GETTER(DebugHTTPServerPrototype__pendingRequestsGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = lexicalGlobalObject->vm();
@@ -5010,6 +5081,7 @@ void JSDebugHTTPServer::visitAdditionalChildren(Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
visitor.append(thisObject->m_hostname);
+ visitor.append(thisObject->m_id);
}
DEFINE_VISIT_ADDITIONAL_CHILDREN(JSDebugHTTPServer);
@@ -11359,6 +11431,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPSServerPrototype__fetchCallback);
extern "C" JSC::EncodedJSValue HTTPSServerPrototype__getHostname(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(HTTPSServerPrototype__hostnameGetterWrap);
+extern "C" JSC::EncodedJSValue HTTPSServerPrototype__getId(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(HTTPSServerPrototype__idGetterWrap);
+
extern "C" JSC::EncodedJSValue HTTPSServerPrototype__getPendingRequests(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(HTTPSServerPrototype__pendingRequestsGetterWrap);
@@ -11389,6 +11464,7 @@ static const HashTableValue JSHTTPSServerPrototypeTableValues[] = {
{ "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__developmentGetterWrap, 0 } },
{ "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPSServerPrototype__fetchCallback, 1 } },
{ "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__hostnameGetterWrap, 0 } },
+ { "id"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__idGetterWrap, 0 } },
{ "pendingRequests"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__pendingRequestsGetterWrap, 0 } },
{ "pendingWebSockets"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__pendingWebSocketsGetterWrap, 0 } },
{ "port"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPSServerPrototype__portGetterWrap, 0 } },
@@ -11484,6 +11560,37 @@ extern "C" EncodedJSValue HTTPSServerPrototype__hostnameGetCachedValue(JSC::Enco
return JSValue::encode(thisObject->m_hostname.get());
}
+JSC_DEFINE_CUSTOM_GETTER(HTTPSServerPrototype__idGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSHTTPSServer* thisObject = jsCast<JSHTTPSServer*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ if (JSValue cachedValue = thisObject->m_id.get())
+ return JSValue::encode(cachedValue);
+
+ JSC::JSValue result = JSC::JSValue::decode(
+ HTTPSServerPrototype__getId(thisObject->wrapped(), globalObject));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ thisObject->m_id.set(vm, thisObject, result);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+}
+
+extern "C" void HTTPSServerPrototype__idSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value)
+{
+ auto& vm = globalObject->vm();
+ auto* thisObject = jsCast<JSHTTPSServer*>(JSValue::decode(thisValue));
+ thisObject->m_id.set(vm, thisObject, JSValue::decode(value));
+}
+
+extern "C" EncodedJSValue HTTPSServerPrototype__idGetCachedValue(JSC::EncodedJSValue thisValue)
+{
+ auto* thisObject = jsCast<JSHTTPSServer*>(JSValue::decode(thisValue));
+ return JSValue::encode(thisObject->m_id.get());
+}
+
JSC_DEFINE_CUSTOM_GETTER(HTTPSServerPrototype__pendingRequestsGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = lexicalGlobalObject->vm();
@@ -11747,6 +11854,7 @@ void JSHTTPSServer::visitAdditionalChildren(Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
visitor.append(thisObject->m_hostname);
+ visitor.append(thisObject->m_id);
}
DEFINE_VISIT_ADDITIONAL_CHILDREN(JSHTTPSServer);
@@ -11805,6 +11913,9 @@ JSC_DECLARE_HOST_FUNCTION(HTTPServerPrototype__fetchCallback);
extern "C" JSC::EncodedJSValue HTTPServerPrototype__getHostname(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(HTTPServerPrototype__hostnameGetterWrap);
+extern "C" JSC::EncodedJSValue HTTPServerPrototype__getId(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
+JSC_DECLARE_CUSTOM_GETTER(HTTPServerPrototype__idGetterWrap);
+
extern "C" JSC::EncodedJSValue HTTPServerPrototype__getPendingRequests(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);
JSC_DECLARE_CUSTOM_GETTER(HTTPServerPrototype__pendingRequestsGetterWrap);
@@ -11835,6 +11946,7 @@ static const HashTableValue JSHTTPServerPrototypeTableValues[] = {
{ "development"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__developmentGetterWrap, 0 } },
{ "fetch"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, HTTPServerPrototype__fetchCallback, 1 } },
{ "hostname"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__hostnameGetterWrap, 0 } },
+ { "id"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__idGetterWrap, 0 } },
{ "pendingRequests"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__pendingRequestsGetterWrap, 0 } },
{ "pendingWebSockets"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__pendingWebSocketsGetterWrap, 0 } },
{ "port"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, HTTPServerPrototype__portGetterWrap, 0 } },
@@ -11930,6 +12042,37 @@ extern "C" EncodedJSValue HTTPServerPrototype__hostnameGetCachedValue(JSC::Encod
return JSValue::encode(thisObject->m_hostname.get());
}
+JSC_DEFINE_CUSTOM_GETTER(HTTPServerPrototype__idGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
+{
+ auto& vm = lexicalGlobalObject->vm();
+ Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ JSHTTPServer* thisObject = jsCast<JSHTTPServer*>(JSValue::decode(thisValue));
+ JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
+
+ if (JSValue cachedValue = thisObject->m_id.get())
+ return JSValue::encode(cachedValue);
+
+ JSC::JSValue result = JSC::JSValue::decode(
+ HTTPServerPrototype__getId(thisObject->wrapped(), globalObject));
+ RETURN_IF_EXCEPTION(throwScope, {});
+ thisObject->m_id.set(vm, thisObject, result);
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
+}
+
+extern "C" void HTTPServerPrototype__idSetCachedValue(JSC::EncodedJSValue thisValue, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value)
+{
+ auto& vm = globalObject->vm();
+ auto* thisObject = jsCast<JSHTTPServer*>(JSValue::decode(thisValue));
+ thisObject->m_id.set(vm, thisObject, JSValue::decode(value));
+}
+
+extern "C" EncodedJSValue HTTPServerPrototype__idGetCachedValue(JSC::EncodedJSValue thisValue)
+{
+ auto* thisObject = jsCast<JSHTTPServer*>(JSValue::decode(thisValue));
+ return JSValue::encode(thisObject->m_id.get());
+}
+
JSC_DEFINE_CUSTOM_GETTER(HTTPServerPrototype__pendingRequestsGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))
{
auto& vm = lexicalGlobalObject->vm();
@@ -12193,6 +12336,7 @@ void JSHTTPServer::visitAdditionalChildren(Visitor& visitor)
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
visitor.append(thisObject->m_hostname);
+ visitor.append(thisObject->m_id);
}
DEFINE_VISIT_ADDITIONAL_CHILDREN(JSHTTPServer);
diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h
index b8b694068..e0b10ff55 100644
--- a/src/bun.js/bindings/ZigGeneratedClasses.h
+++ b/src/bun.js/bindings/ZigGeneratedClasses.h
@@ -511,6 +511,7 @@ public:
DECLARE_VISIT_OUTPUT_CONSTRAINTS;
mutable JSC::WriteBarrier<JSC::Unknown> m_hostname;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_id;
};
class JSDebugHTTPServer final : public JSC::JSDestructibleObject {
@@ -567,6 +568,7 @@ public:
DECLARE_VISIT_OUTPUT_CONSTRAINTS;
mutable JSC::WriteBarrier<JSC::Unknown> m_hostname;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_id;
};
class JSDirent final : public JSC::JSDestructibleObject {
@@ -1415,6 +1417,7 @@ public:
DECLARE_VISIT_OUTPUT_CONSTRAINTS;
mutable JSC::WriteBarrier<JSC::Unknown> m_hostname;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_id;
};
class JSHTTPServer final : public JSC::JSDestructibleObject {
@@ -1471,6 +1474,7 @@ public:
DECLARE_VISIT_OUTPUT_CONSTRAINTS;
mutable JSC::WriteBarrier<JSC::Unknown> m_hostname;
+ mutable JSC::WriteBarrier<JSC::Unknown> m_id;
};
class JSListener final : public JSC::JSDestructibleObject {
diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig
index e98b8f973..116947c24 100644
--- a/src/bun.js/bindings/generated_classes.zig
+++ b/src/bun.js/bindings/generated_classes.zig
@@ -1242,6 +1242,28 @@ pub const JSDebugHTTPSServer = struct {
return result;
}
+ extern fn DebugHTTPSServerPrototype__idSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void;
+
+ extern fn DebugHTTPSServerPrototype__idGetCachedValue(JSC.JSValue) JSC.JSValue;
+
+ /// `DebugHTTPSServer.id` setter
+ /// This value will be visited by the garbage collector.
+ pub fn idSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ DebugHTTPSServerPrototype__idSetCachedValue(thisValue, globalObject, value);
+ }
+
+ /// `DebugHTTPSServer.id` getter
+ /// This value will be visited by the garbage collector.
+ pub fn idGetCached(thisValue: JSC.JSValue) ?JSC.JSValue {
+ JSC.markBinding(@src());
+ const result = DebugHTTPSServerPrototype__idGetCachedValue(thisValue);
+ if (result == .zero)
+ return null;
+
+ return result;
+ }
+
/// Create a new instance of DebugHTTPSServer
pub fn toJS(this: *DebugHTTPSServer, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
JSC.markBinding(@src());
@@ -1286,6 +1308,9 @@ pub const JSDebugHTTPSServer = struct {
if (@TypeOf(DebugHTTPSServer.getHostname) != GetterType)
@compileLog("Expected DebugHTTPSServer.getHostname to be a getter");
+ if (@TypeOf(DebugHTTPSServer.getId) != GetterType)
+ @compileLog("Expected DebugHTTPSServer.getId to be a getter");
+
if (@TypeOf(DebugHTTPSServer.getPendingRequests) != GetterType)
@compileLog("Expected DebugHTTPSServer.getPendingRequests to be a getter");
@@ -1315,6 +1340,7 @@ pub const JSDebugHTTPSServer = struct {
@export(DebugHTTPSServer.finalize, .{ .name = "DebugHTTPSServerClass__finalize" });
@export(DebugHTTPSServer.getDevelopment, .{ .name = "DebugHTTPSServerPrototype__getDevelopment" });
@export(DebugHTTPSServer.getHostname, .{ .name = "DebugHTTPSServerPrototype__getHostname" });
+ @export(DebugHTTPSServer.getId, .{ .name = "DebugHTTPSServerPrototype__getId" });
@export(DebugHTTPSServer.getPendingRequests, .{ .name = "DebugHTTPSServerPrototype__getPendingRequests" });
@export(DebugHTTPSServer.getPendingWebSockets, .{ .name = "DebugHTTPSServerPrototype__getPendingWebSockets" });
@export(DebugHTTPSServer.getPort, .{ .name = "DebugHTTPSServerPrototype__getPort" });
@@ -1359,6 +1385,28 @@ pub const JSDebugHTTPServer = struct {
return result;
}
+ extern fn DebugHTTPServerPrototype__idSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void;
+
+ extern fn DebugHTTPServerPrototype__idGetCachedValue(JSC.JSValue) JSC.JSValue;
+
+ /// `DebugHTTPServer.id` setter
+ /// This value will be visited by the garbage collector.
+ pub fn idSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ DebugHTTPServerPrototype__idSetCachedValue(thisValue, globalObject, value);
+ }
+
+ /// `DebugHTTPServer.id` getter
+ /// This value will be visited by the garbage collector.
+ pub fn idGetCached(thisValue: JSC.JSValue) ?JSC.JSValue {
+ JSC.markBinding(@src());
+ const result = DebugHTTPServerPrototype__idGetCachedValue(thisValue);
+ if (result == .zero)
+ return null;
+
+ return result;
+ }
+
/// Create a new instance of DebugHTTPServer
pub fn toJS(this: *DebugHTTPServer, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
JSC.markBinding(@src());
@@ -1403,6 +1451,9 @@ pub const JSDebugHTTPServer = struct {
if (@TypeOf(DebugHTTPServer.getHostname) != GetterType)
@compileLog("Expected DebugHTTPServer.getHostname to be a getter");
+ if (@TypeOf(DebugHTTPServer.getId) != GetterType)
+ @compileLog("Expected DebugHTTPServer.getId to be a getter");
+
if (@TypeOf(DebugHTTPServer.getPendingRequests) != GetterType)
@compileLog("Expected DebugHTTPServer.getPendingRequests to be a getter");
@@ -1432,6 +1483,7 @@ pub const JSDebugHTTPServer = struct {
@export(DebugHTTPServer.finalize, .{ .name = "DebugHTTPServerClass__finalize" });
@export(DebugHTTPServer.getDevelopment, .{ .name = "DebugHTTPServerPrototype__getDevelopment" });
@export(DebugHTTPServer.getHostname, .{ .name = "DebugHTTPServerPrototype__getHostname" });
+ @export(DebugHTTPServer.getId, .{ .name = "DebugHTTPServerPrototype__getId" });
@export(DebugHTTPServer.getPendingRequests, .{ .name = "DebugHTTPServerPrototype__getPendingRequests" });
@export(DebugHTTPServer.getPendingWebSockets, .{ .name = "DebugHTTPServerPrototype__getPendingWebSockets" });
@export(DebugHTTPServer.getPort, .{ .name = "DebugHTTPServerPrototype__getPort" });
@@ -3059,6 +3111,28 @@ pub const JSHTTPSServer = struct {
return result;
}
+ extern fn HTTPSServerPrototype__idSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void;
+
+ extern fn HTTPSServerPrototype__idGetCachedValue(JSC.JSValue) JSC.JSValue;
+
+ /// `HTTPSServer.id` setter
+ /// This value will be visited by the garbage collector.
+ pub fn idSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ HTTPSServerPrototype__idSetCachedValue(thisValue, globalObject, value);
+ }
+
+ /// `HTTPSServer.id` getter
+ /// This value will be visited by the garbage collector.
+ pub fn idGetCached(thisValue: JSC.JSValue) ?JSC.JSValue {
+ JSC.markBinding(@src());
+ const result = HTTPSServerPrototype__idGetCachedValue(thisValue);
+ if (result == .zero)
+ return null;
+
+ return result;
+ }
+
/// Create a new instance of HTTPSServer
pub fn toJS(this: *HTTPSServer, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
JSC.markBinding(@src());
@@ -3103,6 +3177,9 @@ pub const JSHTTPSServer = struct {
if (@TypeOf(HTTPSServer.getHostname) != GetterType)
@compileLog("Expected HTTPSServer.getHostname to be a getter");
+ if (@TypeOf(HTTPSServer.getId) != GetterType)
+ @compileLog("Expected HTTPSServer.getId to be a getter");
+
if (@TypeOf(HTTPSServer.getPendingRequests) != GetterType)
@compileLog("Expected HTTPSServer.getPendingRequests to be a getter");
@@ -3132,6 +3209,7 @@ pub const JSHTTPSServer = struct {
@export(HTTPSServer.finalize, .{ .name = "HTTPSServerClass__finalize" });
@export(HTTPSServer.getDevelopment, .{ .name = "HTTPSServerPrototype__getDevelopment" });
@export(HTTPSServer.getHostname, .{ .name = "HTTPSServerPrototype__getHostname" });
+ @export(HTTPSServer.getId, .{ .name = "HTTPSServerPrototype__getId" });
@export(HTTPSServer.getPendingRequests, .{ .name = "HTTPSServerPrototype__getPendingRequests" });
@export(HTTPSServer.getPendingWebSockets, .{ .name = "HTTPSServerPrototype__getPendingWebSockets" });
@export(HTTPSServer.getPort, .{ .name = "HTTPSServerPrototype__getPort" });
@@ -3176,6 +3254,28 @@ pub const JSHTTPServer = struct {
return result;
}
+ extern fn HTTPServerPrototype__idSetCachedValue(JSC.JSValue, *JSC.JSGlobalObject, JSC.JSValue) void;
+
+ extern fn HTTPServerPrototype__idGetCachedValue(JSC.JSValue) JSC.JSValue;
+
+ /// `HTTPServer.id` setter
+ /// This value will be visited by the garbage collector.
+ pub fn idSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
+ HTTPServerPrototype__idSetCachedValue(thisValue, globalObject, value);
+ }
+
+ /// `HTTPServer.id` getter
+ /// This value will be visited by the garbage collector.
+ pub fn idGetCached(thisValue: JSC.JSValue) ?JSC.JSValue {
+ JSC.markBinding(@src());
+ const result = HTTPServerPrototype__idGetCachedValue(thisValue);
+ if (result == .zero)
+ return null;
+
+ return result;
+ }
+
/// Create a new instance of HTTPServer
pub fn toJS(this: *HTTPServer, globalObject: *JSC.JSGlobalObject) JSC.JSValue {
JSC.markBinding(@src());
@@ -3220,6 +3320,9 @@ pub const JSHTTPServer = struct {
if (@TypeOf(HTTPServer.getHostname) != GetterType)
@compileLog("Expected HTTPServer.getHostname to be a getter");
+ if (@TypeOf(HTTPServer.getId) != GetterType)
+ @compileLog("Expected HTTPServer.getId to be a getter");
+
if (@TypeOf(HTTPServer.getPendingRequests) != GetterType)
@compileLog("Expected HTTPServer.getPendingRequests to be a getter");
@@ -3249,6 +3352,7 @@ pub const JSHTTPServer = struct {
@export(HTTPServer.finalize, .{ .name = "HTTPServerClass__finalize" });
@export(HTTPServer.getDevelopment, .{ .name = "HTTPServerPrototype__getDevelopment" });
@export(HTTPServer.getHostname, .{ .name = "HTTPServerPrototype__getHostname" });
+ @export(HTTPServer.getId, .{ .name = "HTTPServerPrototype__getId" });
@export(HTTPServer.getPendingRequests, .{ .name = "HTTPServerPrototype__getPendingRequests" });
@export(HTTPServer.getPendingWebSockets, .{ .name = "HTTPServerPrototype__getPendingWebSockets" });
@export(HTTPServer.getPort, .{ .name = "HTTPServerPrototype__getPort" });
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 01f6383af..fc2bd7a05 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -766,6 +766,14 @@ pub const VirtualMachine = struct {
return debugger.next_debugger_id;
}
+ pub fn hotMap(this: *VirtualMachine) ?*JSC.RareData.HotMap {
+ if (this.hot_reload != .hot) {
+ return null;
+ }
+
+ return this.rareData().hotMap(this.allocator);
+ }
+
pub var has_created_debugger: bool = false;
pub const Debugger = struct {
diff --git a/src/bun.js/rare_data.zig b/src/bun.js/rare_data.zig
index 216b56eda..ab9cc9ea4 100644
--- a/src/bun.js/rare_data.zig
+++ b/src/bun.js/rare_data.zig
@@ -19,6 +19,8 @@ stdout_store: ?*Blob.Store = null,
entropy_cache: ?*EntropyCache = null,
+hot_map: ?HotMap = null,
+
// TODO: make this per JSGlobalObject instead of global
// This does not handle ShadowRealm correctly!
tail_cleanup_hook: ?*CleanupHook = null,
@@ -30,6 +32,14 @@ global_dns_data: ?*JSC.DNS.GlobalData = null,
mime_types: ?bun.HTTP.MimeType.Map = null,
+pub fn hotMap(this: *RareData, allocator: std.mem.Allocator) *HotMap {
+ if (this.hot_map == null) {
+ this.hot_map = HotMap.init(allocator);
+ }
+
+ return &this.hot_map.?;
+}
+
pub fn mimeTypeFromString(this: *RareData, allocator: std.mem.Allocator, str: []const u8) ?bun.HTTP.MimeType {
if (this.mime_types == null) {
this.mime_types = bun.HTTP.MimeType.createHashTable(
@@ -40,6 +50,58 @@ pub fn mimeTypeFromString(this: *RareData, allocator: std.mem.Allocator, str: []
return this.mime_types.?.get(str);
}
+pub const HotMap = struct {
+ _map: bun.StringArrayHashMap(Entry),
+
+ const HTTPServer = JSC.API.HTTPServer;
+ const HTTPSServer = JSC.API.HTTPSServer;
+ const DebugHTTPServer = JSC.API.DebugHTTPServer;
+ const DebugHTTPSServer = JSC.API.DebugHTTPSServer;
+ const TCPSocket = JSC.API.TCPSocket;
+ const TLSSocket = JSC.API.TLSSocket;
+ const Listener = JSC.API.Listener;
+ const Entry = bun.TaggedPointerUnion(.{
+ HTTPServer,
+ HTTPSServer,
+ DebugHTTPServer,
+ DebugHTTPSServer,
+ TCPSocket,
+ TLSSocket,
+ Listener,
+ });
+
+ pub fn init(allocator: std.mem.Allocator) HotMap {
+ return .{
+ ._map = bun.StringArrayHashMap(Entry).init(allocator),
+ };
+ }
+
+ pub fn get(this: *HotMap, key: []const u8, comptime Type: type) ?*Type {
+ var entry = this._map.get(key) orelse return null;
+ return entry.get(Type);
+ }
+
+ pub fn getEntry(this: *HotMap, key: []const u8) ?Entry {
+ return this._map.get(key) orelse return null;
+ }
+
+ pub fn insert(this: *HotMap, key: []const u8, ptr: anytype) void {
+ var entry = this._map.getOrPut(key) catch @panic("Out of memory");
+ if (entry.found_existing) {
+ @panic("HotMap already contains key");
+ }
+
+ entry.key_ptr.* = this._map.allocator.dupe(u8, key) catch @panic("Out of memory");
+ entry.value_ptr.* = Entry.init(ptr);
+ }
+
+ pub fn remove(this: *HotMap, key: []const u8) void {
+ var entry = this._map.getEntry(key) orelse return;
+ bun.default_allocator.free(entry.key_ptr.*);
+ _ = this._map.orderedRemove(key);
+ }
+};
+
pub fn filePolls(this: *RareData, vm: *JSC.VirtualMachine) *JSC.FilePoll.HiveArray {
return this.file_polls_ orelse {
this.file_polls_ = vm.allocator.create(JSC.FilePoll.HiveArray) catch unreachable;