aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Ashcon Partovi <ashcon@partovi.net> 2023-08-29 23:44:39 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-29 23:44:39 -0700
commitf2553d24543d72a777ba60213473332809866cb2 (patch)
tree61faac4292dbdf1b4d0543e33d3f5d2c792825c5 /src
parentc028b206bce3f9b5c3cba7899c6bf34856efe43f (diff)
downloadbun-f2553d24543d72a777ba60213473332809866cb2.tar.gz
bun-f2553d24543d72a777ba60213473332809866cb2.tar.zst
bun-f2553d24543d72a777ba60213473332809866cb2.zip
More support for DAP (#4380)
* Fix reconnect with --watch * Support setVariable * Support setExpression * Support watch variables * Conditional and hit breakpoints * Support exceptionInfo * Support goto and gotoTargets * Support completions * Support both a URL and UNIX inspector at the same time * Fix url * WIP, add timeouts to figure out issue * Fix messages being dropped from debugger.ts * Progress * Fix breakpoints and ref-event-loop * More fixes * Fix exit * Make hovers better * Fix --hot
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/bindings/BunDebugger.cpp11
-rw-r--r--src/bun.js/javascript.zig47
-rw-r--r--src/cli.zig9
-rw-r--r--src/js/internal/debugger.ts580
-rw-r--r--src/js/out/InternalModuleRegistryConstants.h6
5 files changed, 337 insertions, 316 deletions
diff --git a/src/bun.js/bindings/BunDebugger.cpp b/src/bun.js/bindings/BunDebugger.cpp
index 440a5125b..f4a5f535a 100644
--- a/src/bun.js/bindings/BunDebugger.cpp
+++ b/src/bun.js/bindings/BunDebugger.cpp
@@ -109,7 +109,7 @@ public:
globalObject->setInspectable(true);
auto& inspector = globalObject->inspectorDebuggable();
inspector.setInspectable(true);
- globalObject->inspectorController().connectFrontend(*connection, true, waitingForConnection);
+ globalObject->inspectorController().connectFrontend(*connection, true, false); // waitingForConnection
Inspector::JSGlobalObjectDebugger* debugger = reinterpret_cast<Inspector::JSGlobalObjectDebugger*>(globalObject->debugger());
if (debugger) {
@@ -482,7 +482,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionCreateConnection, (JSGlobalObject * globalObj
return JSValue::encode(JSBunInspectorConnection::create(vm, JSBunInspectorConnection::createStructure(vm, globalObject, globalObject->objectPrototype()), connection));
}
-extern "C" BunString Bun__startJSDebuggerThread(Zig::GlobalObject* debuggerGlobalObject, ScriptExecutionContextIdentifier scriptId, BunString* portOrPathString)
+extern "C" void Bun__startJSDebuggerThread(Zig::GlobalObject* debuggerGlobalObject, ScriptExecutionContextIdentifier scriptId, BunString* portOrPathString)
{
if (!debuggerScriptExecutionContext)
debuggerScriptExecutionContext = debuggerGlobalObject->scriptExecutionContext();
@@ -498,12 +498,7 @@ extern "C" BunString Bun__startJSDebuggerThread(Zig::GlobalObject* debuggerGloba
arguments.append(JSFunction::create(vm, debuggerGlobalObject, 1, String("send"_s), jsFunctionSend, ImplementationVisibility::Public));
arguments.append(JSFunction::create(vm, debuggerGlobalObject, 0, String("disconnect"_s), jsFunctionDisconnect, ImplementationVisibility::Public));
- JSValue serverURLValue = JSC::call(debuggerGlobalObject, debuggerDefaultFn, arguments, "Bun__initJSDebuggerThread - debuggerDefaultFn"_s);
-
- if (serverURLValue.isUndefinedOrNull())
- return BunStringEmpty;
-
- return Bun::toStringRef(debuggerGlobalObject, serverURLValue);
+ JSC::call(debuggerGlobalObject, debuggerDefaultFn, arguments, "Bun__initJSDebuggerThread - debuggerDefaultFn"_s);
}
enum class AsyncCallTypeUint8 : uint8_t {
diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig
index 90a3bbc66..32cf04346 100644
--- a/src/bun.js/javascript.zig
+++ b/src/bun.js/javascript.zig
@@ -502,6 +502,7 @@ pub const VirtualMachine = struct {
worker: ?*JSC.WebWorker = null,
debugger: ?Debugger = null,
+ has_started_debugger: bool = false,
pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSC.JSGlobalObject, JSC.JSValue) void;
@@ -794,7 +795,8 @@ pub const VirtualMachine = struct {
pub var has_created_debugger: bool = false;
pub const Debugger = struct {
- path_or_port: []const u8 = "",
+ path_or_port: ?[]const u8 = null,
+ unix: []const u8 = "",
script_execution_context_id: u32 = 0,
next_debugger_id: u64 = 1,
poll_ref: JSC.PollRef = .{},
@@ -805,8 +807,7 @@ pub const VirtualMachine = struct {
extern "C" fn Bun__createJSDebugger(*JSC.JSGlobalObject) u32;
extern "C" fn Bun__ensureDebugger(u32, bool) void;
- extern "C" fn Bun__startJSDebuggerThread(*JSC.JSGlobalObject, u32, *bun.String) bun.String;
- var has_started_debugger_thread: bool = false;
+ extern "C" fn Bun__startJSDebuggerThread(*JSC.JSGlobalObject, u32, *bun.String) void;
var futex_atomic: std.atomic.Atomic(u32) = undefined;
pub fn create(this: *VirtualMachine, globalObject: *JSGlobalObject) !void {
@@ -816,8 +817,8 @@ pub const VirtualMachine = struct {
has_created_debugger = true;
var debugger = &this.debugger.?;
debugger.script_execution_context_id = Bun__createJSDebugger(globalObject);
- if (!has_started_debugger_thread) {
- has_started_debugger_thread = true;
+ if (!this.has_started_debugger) {
+ this.has_started_debugger = true;
futex_atomic = std.atomic.Atomic(u32).init(0);
var thread = try std.Thread.spawn(.{}, startJSDebuggerThread, .{this});
thread.detach();
@@ -865,8 +866,6 @@ pub const VirtualMachine = struct {
vm.global.vm().holdAPILock(other_vm, @ptrCast(&start));
}
- pub export var Bun__debugger_server_url: bun.String = undefined;
-
pub export fn Debugger__didConnect() void {
var this = VirtualMachine.get();
std.debug.assert(this.debugger.?.wait_for_connection);
@@ -878,9 +877,17 @@ pub const VirtualMachine = struct {
JSC.markBinding(@src());
var this = VirtualMachine.get();
- var str = bun.String.create(other_vm.debugger.?.path_or_port);
- Bun__debugger_server_url = Bun__startJSDebuggerThread(this.global, other_vm.debugger.?.script_execution_context_id, &str);
- Bun__debugger_server_url.toThreadSafe();
+ var debugger = other_vm.debugger.?;
+
+ if (debugger.unix.len > 0) {
+ var url = bun.String.create(debugger.unix);
+ Bun__startJSDebuggerThread(this.global, debugger.script_execution_context_id, &url);
+ }
+
+ if (debugger.path_or_port) |path_or_port| {
+ var url = bun.String.create(path_or_port);
+ Bun__startJSDebuggerThread(this.global, debugger.script_execution_context_id, &url);
+ }
this.global.handleRejectedPromises();
@@ -1189,13 +1196,27 @@ pub const VirtualMachine = struct {
}
fn configureDebugger(this: *VirtualMachine, debugger: bun.CLI.Command.Debugger) void {
+ var unix = bun.getenvZ("BUN_INSPECT") orelse "";
+ var set_breakpoint_on_first_line = unix.len > 0 and strings.endsWith(unix, "?break=1");
+ var wait_for_connection = set_breakpoint_on_first_line or (unix.len > 0 and strings.endsWith(unix, "?wait=1"));
+
switch (debugger) {
- .unspecified => {},
+ .unspecified => {
+ if (unix.len > 0) {
+ this.debugger = Debugger{
+ .path_or_port = null,
+ .unix = unix,
+ .wait_for_connection = wait_for_connection,
+ .set_breakpoint_on_first_line = set_breakpoint_on_first_line,
+ };
+ }
+ },
.enable => {
this.debugger = Debugger{
.path_or_port = debugger.enable.path_or_port,
- .wait_for_connection = debugger.enable.wait_for_connection,
- .set_breakpoint_on_first_line = debugger.enable.set_breakpoint_on_first_line,
+ .unix = unix,
+ .wait_for_connection = wait_for_connection or debugger.enable.wait_for_connection,
+ .set_breakpoint_on_first_line = set_breakpoint_on_first_line or debugger.enable.set_breakpoint_on_first_line,
};
},
}
diff --git a/src/cli.zig b/src/cli.zig
index 68ae7e4c2..c68297baa 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -543,15 +543,6 @@ pub const Arguments = struct {
.wait_for_connection = true,
.set_breakpoint_on_first_line = true,
} };
- } else if (bun.getenvZ("BUN_INSPECT")) |inspect_value| {
- ctx.runtime_options.debugger = if (inspect_value.len == 0 or inspect_value[0] == '0')
- Command.Debugger{ .unspecified = {} }
- else
- Command.Debugger{ .enable = .{
- .path_or_port = inspect_value[1..],
- .wait_for_connection = inspect_value[0] == '1' or inspect_value[0] == '2',
- .set_breakpoint_on_first_line = inspect_value[0] == '2',
- } };
}
}
diff --git a/src/js/internal/debugger.ts b/src/js/internal/debugger.ts
index 2e76b2c7c..cd6f8f516 100644
--- a/src/js/internal/debugger.ts
+++ b/src/js/internal/debugger.ts
@@ -1,309 +1,322 @@
-import type * as BunType from "bun";
-
-// We want to avoid dealing with creating a prototype for the inspector class
-let sendFn_, disconnectFn_;
-const colors = Bun.enableANSIColors && process.env.NO_COLOR !== "1";
-
-var debuggerCounter = 1;
-class DebuggerWithMessageQueue {
- debugger?: Debugger = undefined;
- messageQueue: string[] = [];
- count: number = debuggerCounter++;
+import type { Server as WebSocketServer, WebSocketHandler, ServerWebSocket, SocketHandler, Socket } from "bun";
+
+export default function (
+ executionContextId: string,
+ url: string,
+ createBackend: (
+ executionContextId: string,
+ refEventLoop: boolean,
+ receive: (...messages: string[]) => void,
+ ) => unknown,
+ send: (message: string) => void,
+ close: () => void,
+): void {
+ let debug: Debugger | undefined;
+ try {
+ debug = new Debugger(executionContextId, url, createBackend, send, close);
+ } catch (error) {
+ exit("Failed to start inspector:\n", error);
+ }
- send(msg: string) {
- sendFn_.call(this.debugger, msg);
+ const { protocol, href, host, pathname } = debug.url;
+ if (!protocol.includes("unix")) {
+ console.log(dim("--------------------- Bun Inspector ---------------------"), reset());
+ console.log(`Listening:\n ${dim(href)}`);
+ if (protocol.includes("ws")) {
+ console.log(`Inspect in browser:\n ${link(`https://debug.bun.sh/#${host}${pathname}`)}`);
+ }
+ console.log(dim("--------------------- Bun Inspector ---------------------"), reset());
}
- disconnect() {
- disconnectFn_.call(this.debugger);
- this.messageQueue.length = 0;
+ const unix = process.env["BUN_INSPECT_NOTIFY"];
+ if (unix) {
+ const { protocol, pathname } = parseUrl(unix);
+ if (protocol === "unix:") {
+ notify(pathname);
+ }
}
}
-let defaultPort = 6499;
+class Debugger {
+ #url: URL;
+ #createBackend: (refEventLoop: boolean, receive: (...messages: string[]) => void) => Writer;
+
+ constructor(
+ executionContextId: string,
+ url: string,
+ createBackend: (
+ executionContextId: string,
+ refEventLoop: boolean,
+ receive: (...messages: string[]) => void,
+ ) => unknown,
+ send: (message: string) => void,
+ close: () => void,
+ ) {
+ this.#url = parseUrl(url);
+ this.#createBackend = (refEventLoop, receive) => {
+ const backend = createBackend(executionContextId, refEventLoop, receive);
+ return {
+ write: message => {
+ send.call(backend, message);
+ return true;
+ },
+ close: () => close.call(backend),
+ };
+ };
+ this.#listen();
+ }
-let generatedPath: string = "";
-function generatePath() {
- if (!generatedPath) {
- generatedPath = "/" + Math.random().toString(36).slice(2);
+ get url(): URL {
+ return this.#url;
}
- return generatedPath;
-}
+ #listen(): void {
+ const { protocol, hostname, port, pathname } = this.#url;
+
+ if (protocol === "ws:" || protocol === "ws+tcp:") {
+ const server = Bun.serve({
+ hostname,
+ port,
+ fetch: this.#fetch.bind(this),
+ websocket: this.#websocket,
+ });
+ this.#url.hostname = server.hostname;
+ this.#url.port = `${server.port}`;
+ return;
+ }
-function terminalLink(url) {
- if (colors) {
- // bold + hyperlink + reset
- return "\x1b[1m\x1b]8;;" + url + "\x1b\\" + url + "\x1b]8;;\x1b\\" + "\x1b[22m";
- }
+ if (protocol === "ws+unix:") {
+ Bun.serve({
+ unix: pathname,
+ fetch: this.#fetch.bind(this),
+ websocket: this.#websocket,
+ });
+ return;
+ }
- return url;
-}
+ throw new TypeError(`Unsupported protocol: '${protocol}' (expected 'ws:', 'ws+unix:', or 'unix:')`);
+ }
-function dim(text) {
- if (colors) {
- return "\x1b[2m" + text + "\x1b[22m";
+ get #websocket(): WebSocketHandler<Connection> {
+ return {
+ idleTimeout: 0,
+ closeOnBackpressureLimit: false,
+ open: ws => this.#open(ws, webSocketWriter(ws)),
+ message: (ws, message) => {
+ if (typeof message === "string") {
+ this.#message(ws, message);
+ } else {
+ this.#error(ws, new Error(`Unexpected binary message: ${message.toString()}`));
+ }
+ },
+ drain: ws => this.#drain(ws),
+ close: ws => this.#close(ws),
+ };
}
- return text;
-}
+ #fetch(request: Request, server: WebSocketServer): Response | undefined {
+ const { method, url, headers } = request;
+ const { pathname } = new URL(url);
-class WebSocketListener {
- server: BunType.Server;
- url: string = "";
- createInspectorConnection;
- scriptExecutionContextId: number = 0;
- activeConnections: Set<BunType.ServerWebSocket<DebuggerWithMessageQueue>> = new Set();
-
- constructor(scriptExecutionContextId: number = 0, url: string, createInspectorConnection) {
- this.scriptExecutionContextId = scriptExecutionContextId;
- this.createInspectorConnection = createInspectorConnection;
- this.server = this.start(url);
- }
+ if (method !== "GET") {
+ return new Response(null, {
+ status: 405, // Method Not Allowed
+ });
+ }
- start(url: string): BunType.Server {
- let defaultHostname = "localhost";
- let usingDefaultPort = false;
- let isUnix = false;
-
- if (url.startsWith("ws+unix://")) {
- isUnix = true;
- url = url.slice(10);
- } else if (/^[0-9]*$/.test(url)) {
- url = "ws://" + defaultHostname + ":" + url + generatePath();
- } else if (!url || url.startsWith("/")) {
- url = "ws://" + defaultHostname + ":" + defaultPort + generatePath();
- usingDefaultPort = true;
- } else if (url.includes(":") && !url.includes("://")) {
- try {
- const insertSlash = !url.includes("/");
- url = new URL("ws://" + url).href;
- if (insertSlash) {
- url += generatePath().slice(1);
- }
- } catch (e) {
- console.error("[Inspector]", "Failed to parse url", '"' + url + '"');
- process.exit(1);
- }
+ switch (pathname) {
+ case "/json/version":
+ return Response.json(versionInfo());
+ case "/json":
+ case "/json/list":
+ // TODO?
}
- if (!isUnix) {
- try {
- var { hostname, port, pathname } = new URL(url);
- this.url = pathname.toLowerCase();
- } catch (e) {
- console.error("[Inspector]", "Failed to parse url", '"' + url + '"');
- process.exit(1);
- }
+ if (!this.#url.protocol.includes("unix") && this.#url.pathname !== pathname) {
+ return new Response(null, {
+ status: 404, // Not Found
+ });
}
- const serveOptions: BunType.WebSocketServeOptions<DebuggerWithMessageQueue> = {
- ...(isUnix ? { unix: url } : { hostname }),
- development: false,
-
- // @ts-ignore
- reusePort: false,
-
- websocket: {
- idleTimeout: 0,
- open: socket => {
- var connection = new DebuggerWithMessageQueue();
- // @ts-expect-error
- const shouldRefEventLoop = !!socket.data?.shouldRefEventLoop;
-
- socket.data = connection;
- this.activeConnections.add(socket);
- connection.debugger = this.createInspectorConnection(
- this.scriptExecutionContextId,
- shouldRefEventLoop,
- (...msgs: string[]) => {
- if (socket.readyState > 1) {
- connection.disconnect();
- return;
- }
-
- if (connection.messageQueue.length > 0) {
- connection.messageQueue.push(...msgs);
- return;
- }
-
- for (let i = 0; i < msgs.length; i++) {
- if (!socket.sendText(msgs[i])) {
- if (socket.readyState < 2) {
- connection.messageQueue.push(...msgs.slice(i));
- }
- return;
- }
- }
- },
- );
-
- if (!isUnix) {
- console.log(
- "[Inspector]",
- "Connection #" + connection.count + " opened",
- "(" +
- new Intl.DateTimeFormat(undefined, {
- "timeStyle": "long",
- "dateStyle": "short",
- }).format(new Date()) +
- ")",
- );
- }
- },
- drain: socket => {
- const queue = socket.data.messageQueue;
- for (let i = 0; i < queue.length; i++) {
- if (!socket.sendText(queue[i])) {
- socket.data.messageQueue = queue.slice(i);
- return;
- }
- }
- queue.length = 0;
- },
- message: (socket, message) => {
- if (typeof message !== "string") {
- console.warn("[Inspector]", "Received non-string message");
- return;
- }
- socket.data.send(message as string);
- },
- close: socket => {
- socket.data.disconnect();
- if (!isUnix) {
- console.log(
- "[Inspector]",
- "Connection #" + socket.data.count + " closed",
- "(" +
- new Intl.DateTimeFormat(undefined, {
- "timeStyle": "long",
- "dateStyle": "short",
- }).format(new Date()) +
- ")",
- );
- }
- this.activeConnections.delete(socket);
+ const data: Connection = {
+ refEventLoop: headers.get("Ref-Event-Loop") === "0",
+ };
+
+ if (!server.upgrade(request, { data })) {
+ return new Response(null, {
+ status: 426, // Upgrade Required
+ headers: {
+ "Upgrade": "websocket",
},
- },
- fetch: (req, server) => {
- let { pathname } = new URL(req.url);
- pathname = pathname.toLowerCase();
-
- if (pathname === "/json/version") {
- return Response.json({
- "Browser": navigator.userAgent,
- "WebKit-Version": process.versions.webkit,
- "Bun-Version": Bun.version,
- "Bun-Revision": Bun.revision,
- });
- }
+ });
+ }
+ }
- if (!this.url || pathname === this.url) {
- const refHeader = req.headers.get("Ref-Event-Loop");
- if (
- server.upgrade(req, {
- data: {
- shouldRefEventLoop: !!refHeader && refHeader !== "0",
- },
- })
- ) {
- return new Response();
- }
+ get #socket(): SocketHandler<Connection> {
+ return {
+ open: socket => this.#open(socket, socketWriter(socket)),
+ data: (socket, message) => this.#message(socket, message.toString()),
+ drain: socket => this.#drain(socket),
+ close: socket => this.#close(socket),
+ error: (socket, error) => this.#error(socket, error),
+ connectError: (_, error) => exit("Failed to start inspector:\n", error),
+ };
+ }
- return new Response("WebSocket expected", {
- status: 400,
- });
- }
+ #open(connection: ConnectionOwner, writer: Writer): void {
+ const { data } = connection;
+ const { refEventLoop } = data;
- return new Response("Not found", {
- status: 404,
- });
- },
- };
+ const client = bufferedWriter(writer);
+ const backend = this.#createBackend(refEventLoop, (...messages: string[]) => {
+ for (const message of messages) {
+ client.write(message);
+ }
+ });
- if (port === "") {
- port = defaultPort + "";
- }
+ data.client = client;
+ data.backend = backend;
+ }
- let portNumber = Number(port);
- var server, lastError;
-
- if (usingDefaultPort) {
- for (let tries = 0; tries < 10 && !server; tries++) {
- try {
- lastError = undefined;
- server = Bun.serve<DebuggerWithMessageQueue>({
- ...serveOptions,
- port: portNumber++,
- });
- if (isUnix) {
- notify();
- }
- } catch (e) {
- lastError = e;
- }
+ #message(connection: ConnectionOwner, message: string): void {
+ const { data } = connection;
+ const { backend } = data;
+ backend?.write(message);
+ }
+
+ #drain(connection: ConnectionOwner): void {
+ const { data } = connection;
+ const { client } = data;
+ client?.drain?.();
+ }
+
+ #close(connection: ConnectionOwner): void {
+ const { data } = connection;
+ const { backend } = data;
+ backend?.close();
+ }
+
+ #error(connection: ConnectionOwner, error: Error): void {
+ const { data } = connection;
+ const { backend } = data;
+ console.error(error);
+ backend?.close();
+ }
+}
+
+function versionInfo(): unknown {
+ return {
+ "Protocol-Version": "1.3",
+ "Browser": "Bun",
+ // @ts-ignore: Missing types for `navigator`
+ "User-Agent": navigator.userAgent,
+ "WebKit-Version": process.versions.webkit,
+ "Bun-Version": Bun.version,
+ "Bun-Revision": Bun.revision,
+ };
+}
+
+function webSocketWriter(ws: ServerWebSocket<unknown>): Writer {
+ return {
+ write: message => !!ws.sendText(message),
+ close: () => ws.close(),
+ };
+}
+
+function socketWriter(socket: Socket<unknown>): Writer {
+ return {
+ write: message => !!socket.write(message),
+ close: () => socket.end(),
+ };
+}
+
+function bufferedWriter(writer: Writer): Writer {
+ let draining = false;
+ let pendingMessages: string[] = [];
+
+ return {
+ write: message => {
+ if (draining || !writer.write(message)) {
+ pendingMessages.push(message);
}
- } else {
+ return true;
+ },
+ drain: () => {
+ draining = true;
try {
- server = Bun.serve<DebuggerWithMessageQueue>({
- ...serveOptions,
- port: portNumber,
- });
- if (isUnix) {
- notify();
+ for (let i = 0; i < pendingMessages.length; i++) {
+ if (!writer.write(pendingMessages[i])) {
+ pendingMessages = pendingMessages.slice(i);
+ return;
+ }
}
- } catch (e) {
- lastError = e;
+ } finally {
+ draining = false;
}
- }
+ },
+ close: () => {
+ writer.close();
+ pendingMessages.length = 0;
+ },
+ };
+}
- if (!server) {
- console.error("[Inspector]", "Failed to start server");
- if (lastError) console.error(lastError);
- process.exit(1);
- }
+const defaultHostname = "localhost";
+const defaultPort = 6499;
- let textToWrite = "";
- function writeToConsole(text) {
- textToWrite += text;
- }
- function flushToConsole() {
- console.write(textToWrite);
+function parseUrl(url: string): URL {
+ try {
+ if (!url) {
+ return new URL(randomId(), `ws://${defaultHostname}:${defaultPort}/`);
+ } else if (url.startsWith("/")) {
+ return new URL(url, `ws://${defaultHostname}:${defaultPort}/`);
+ } else if (/^[a-z+]+:\/\//i.test(url)) {
+ return new URL(url);
+ } else if (/^\d+$/.test(url)) {
+ return new URL(randomId(), `ws://${defaultHostname}:${url}/`);
+ } else if (!url.includes("/") && url.includes(":")) {
+ return new URL(randomId(), `ws://${url}/`);
+ } else if (!url.includes(":")) {
+ const [hostname, pathname] = url.split("/", 2);
+ return new URL(`ws://${hostname}:${defaultPort}/${pathname}`);
+ } else {
+ return new URL(randomId(), `ws://${url}`);
}
+ } catch {
+ throw new TypeError(`Invalid hostname or URL: '${url}'`);
+ }
+}
- if (!this.url) {
- return server;
- }
+function randomId() {
+ return Math.random().toString(36).slice(2);
+}
- // yellow foreground
- writeToConsole(dim(`------------------ Bun Inspector ------------------` + "\n"));
- if (colors) {
- // reset background
- writeToConsole("\x1b[49m");
- }
+const { enableANSIColors } = Bun;
- writeToConsole(
- "Listening at:\n " +
- `ws://${hostname}:${server.port}${this.url}` +
- "\n\n" +
- "Inspect in browser:\n " +
- terminalLink(new URL(`https://debug.bun.sh#${server.hostname}:${server.port}${this.url}`).href) +
- "\n",
- );
- writeToConsole(dim(`------------------ Bun Inspector ------------------` + "\n"));
- flushToConsole();
-
- return server;
+function dim(string: string): string {
+ if (enableANSIColors) {
+ return `\x1b[2m${string}\x1b[22m`;
}
+ return string;
}
-function notify(): void {
- const unix = process.env["BUN_INSPECT_NOTIFY"];
- if (!unix || !unix.startsWith("unix://")) {
- return;
+function link(url: string): string {
+ if (enableANSIColors) {
+ return `\x1b[1m\x1b]8;;${url}\x1b\\${url}\x1b]8;;\x1b\\\x1b[22m`;
+ }
+ return url;
+}
+
+function reset(): string {
+ if (enableANSIColors) {
+ return "\x1b[49m";
}
+ return "";
+}
+
+function notify(unix: string): void {
Bun.connect({
- unix: unix.slice(7),
+ unix,
socket: {
open: socket => {
socket.end("1");
@@ -311,26 +324,27 @@ function notify(): void {
data: () => {}, // required or it errors
},
}).finally(() => {
- // Do nothing
+ // Best-effort
});
}
-interface Debugger {
- send(msg: string): void;
- disconnect(): void;
+function exit(...args: unknown[]): never {
+ console.error(...args);
+ process.exit(1);
}
-var listener: WebSocketListener;
-
-export default function start(debuggerId, hostOrPort, createInspectorConnection, sendFn, disconnectFn) {
- try {
- sendFn_ = sendFn;
- disconnectFn_ = disconnectFn;
- globalThis.listener = listener ||= new WebSocketListener(debuggerId, hostOrPort, createInspectorConnection);
- } catch (e) {
- console.error("Bun Inspector threw an exception\n", e);
- process.exit(1);
- }
-
- return `http://${listener.server.hostname}:${listener.server.port}${listener.url}`;
-}
+type ConnectionOwner = {
+ data: Connection;
+};
+
+type Connection = {
+ refEventLoop: boolean;
+ client?: Writer;
+ backend?: Writer;
+};
+
+type Writer = {
+ write: (message: string) => boolean;
+ drain?: () => void;
+ close: () => void;
+};
diff --git a/src/js/out/InternalModuleRegistryConstants.h b/src/js/out/InternalModuleRegistryConstants.h
index 31d51538f..66a8f169d 100644
--- a/src/js/out/InternalModuleRegistryConstants.h
+++ b/src/js/out/InternalModuleRegistryConstants.h
@@ -14,7 +14,7 @@ static constexpr ASCIILiteral BunSqliteCode = "(function (){\"use strict\";// sr
//
//
-static constexpr ASCIILiteral InternalDebuggerCode = "(function (){\"use strict\";// src/js/out/tmp/internal/debugger.ts\nvar generatePath = function() {\n if (!generatedPath)\n generatedPath = \"/\" + Math.random().toString(36).slice(2);\n return generatedPath;\n}, terminalLink = function(url) {\n if (colors)\n return \"\\x1B[1m\\x1B]8;;\" + url + \"\\x1B\\\\\" + url + \"\\x1B]8;;\\x1B\\\\\" + \"\\x1B[22m\";\n return url;\n}, dim = function(text) {\n if (colors)\n return \"\\x1B[2m\" + text + \"\\x1B[22m\";\n return text;\n}, notify = function() {\n const unix = process.env.BUN_INSPECT_NOTIFY;\n if (!unix || !unix.startsWith(\"unix://\"))\n return;\n Bun.connect({\n unix: unix.slice(7),\n socket: {\n open: (socket) => {\n socket.end(\"1\");\n },\n data: () => {\n }\n }\n }).finally(() => {\n });\n}, $, sendFn_, disconnectFn_, colors = Bun.enableANSIColors && process.env.NO_COLOR !== \"1\", debuggerCounter = 1;\n\nclass DebuggerWithMessageQueue {\n debugger = void 0;\n messageQueue = [];\n count = debuggerCounter++;\n send(msg) {\n sendFn_.call(this.debugger, msg);\n }\n disconnect() {\n disconnectFn_.call(this.debugger), this.messageQueue.length = 0;\n }\n}\nvar defaultPort = 6499, generatedPath = \"\";\n\nclass WebSocketListener {\n server;\n url = \"\";\n createInspectorConnection;\n scriptExecutionContextId = 0;\n activeConnections = new Set;\n constructor(scriptExecutionContextId = 0, url, createInspectorConnection) {\n this.scriptExecutionContextId = scriptExecutionContextId, this.createInspectorConnection = createInspectorConnection, this.server = this.start(url);\n }\n start(url) {\n let defaultHostname = \"localhost\", usingDefaultPort = !1, isUnix = !1;\n if (url.startsWith(\"ws+unix://\"))\n isUnix = !0, url = url.slice(10);\n else if (/^[0-9]*$/.test(url))\n url = \"ws://\" + defaultHostname + \":\" + url + generatePath();\n else if (!url || url.startsWith(\"/\"))\n url = \"ws://\" + defaultHostname + \":\" + defaultPort + generatePath(), usingDefaultPort = !0;\n else if (url.includes(\":\") && !url.includes(\"://\"))\n try {\n const insertSlash = !url.includes(\"/\");\n if (url = new URL(\"ws://\" + url).href, insertSlash)\n url += generatePath().slice(1);\n } catch (e) {\n console.error(\"[Inspector]\", \"Failed to parse url\", '\"' + url + '\"'), process.exit(1);\n }\n if (!isUnix)\n try {\n var { hostname, port, pathname } = new URL(url);\n this.url = pathname.toLowerCase();\n } catch (e) {\n console.error(\"[Inspector]\", \"Failed to parse url\", '\"' + url + '\"'), process.exit(1);\n }\n const serveOptions = {\n ...isUnix \? { unix: url } : { hostname },\n development: !1,\n reusePort: !1,\n websocket: {\n idleTimeout: 0,\n open: (socket) => {\n var connection = new DebuggerWithMessageQueue;\n const shouldRefEventLoop = !!socket.data\?.shouldRefEventLoop;\n if (socket.data = connection, this.activeConnections.add(socket), connection.debugger = this.createInspectorConnection(this.scriptExecutionContextId, shouldRefEventLoop, (...msgs) => {\n if (socket.readyState > 1) {\n connection.disconnect();\n return;\n }\n if (connection.messageQueue.length > 0) {\n connection.messageQueue.push(...msgs);\n return;\n }\n for (let i = 0;i < msgs.length; i++)\n if (!socket.sendText(msgs[i])) {\n if (socket.readyState < 2)\n connection.messageQueue.push(...msgs.slice(i));\n return;\n }\n }), !isUnix)\n console.log(\"[Inspector]\", \"Connection #\" + connection.count + \" opened\", \"(\" + new Intl.DateTimeFormat(void 0, {\n timeStyle: \"long\",\n dateStyle: \"short\"\n }).format(new Date) + \")\");\n },\n drain: (socket) => {\n const queue = socket.data.messageQueue;\n for (let i = 0;i < queue.length; i++)\n if (!socket.sendText(queue[i])) {\n socket.data.messageQueue = queue.slice(i);\n return;\n }\n queue.length = 0;\n },\n message: (socket, message) => {\n if (typeof message !== \"string\") {\n console.warn(\"[Inspector]\", \"Received non-string message\");\n return;\n }\n socket.data.send(message);\n },\n close: (socket) => {\n if (socket.data.disconnect(), !isUnix)\n console.log(\"[Inspector]\", \"Connection #\" + socket.data.count + \" closed\", \"(\" + new Intl.DateTimeFormat(void 0, {\n timeStyle: \"long\",\n dateStyle: \"short\"\n }).format(new Date) + \")\");\n this.activeConnections.delete(socket);\n }\n },\n fetch: (req, server2) => {\n let { pathname: pathname2 } = new URL(req.url);\n if (pathname2 = pathname2.toLowerCase(), pathname2 === \"/json/version\")\n return Response.json({\n Browser: navigator.userAgent,\n \"WebKit-Version\": process.versions.webkit,\n \"Bun-Version\": Bun.version,\n \"Bun-Revision\": Bun.revision\n });\n if (!this.url || pathname2 === this.url) {\n const refHeader = req.headers.get(\"Ref-Event-Loop\");\n if (server2.upgrade(req, {\n data: {\n shouldRefEventLoop: !!refHeader && refHeader !== \"0\"\n }\n }))\n return new Response;\n return new Response(\"WebSocket expected\", {\n status: 400\n });\n }\n return new Response(\"Not found\", {\n status: 404\n });\n }\n };\n if (port === \"\")\n port = defaultPort + \"\";\n let portNumber = Number(port);\n var server, lastError;\n if (usingDefaultPort)\n for (let tries = 0;tries < 10 && !server; tries++)\n try {\n if (lastError = void 0, server = Bun.serve({\n ...serveOptions,\n port: portNumber++\n }), isUnix)\n notify();\n } catch (e) {\n lastError = e;\n }\n else\n try {\n if (server = Bun.serve({\n ...serveOptions,\n port: portNumber\n }), isUnix)\n notify();\n } catch (e) {\n lastError = e;\n }\n if (!server) {\n if (console.error(\"[Inspector]\", \"Failed to start server\"), lastError)\n console.error(lastError);\n process.exit(1);\n }\n let textToWrite = \"\";\n function writeToConsole(text) {\n textToWrite += text;\n }\n function flushToConsole() {\n console.write(textToWrite);\n }\n if (!this.url)\n return server;\n if (writeToConsole(dim(\"------------------ Bun Inspector ------------------\\n\")), colors)\n writeToConsole(\"\\x1B[49m\");\n return writeToConsole(\"Listening at:\\n \" + `ws://${hostname}:${server.port}${this.url}` + \"\\n\\nInspect in browser:\\n \" + terminalLink(new URL(`https://debug.bun.sh#${server.hostname}:${server.port}${this.url}`).href) + \"\\n\"), writeToConsole(dim(\"------------------ Bun Inspector ------------------\\n\")), flushToConsole(), server;\n }\n}\nvar listener;\n$ = function start(debuggerId, hostOrPort, createInspectorConnection, sendFn, disconnectFn) {\n try {\n sendFn_ = sendFn, disconnectFn_ = disconnectFn, globalThis.listener = listener ||= new WebSocketListener(debuggerId, hostOrPort, createInspectorConnection);\n } catch (e) {\n console.error(\"Bun Inspector threw an exception\\n\", e), process.exit(1);\n }\n return `http://${listener.server.hostname}:${listener.server.port}${listener.url}`;\n};\nreturn $})\n"_s;
+static constexpr ASCIILiteral InternalDebuggerCode = "(function (){\"use strict\";// src/js/out/tmp/internal/debugger.ts\nvar versionInfo = function() {\n return {\n \"Protocol-Version\": \"1.3\",\n Browser: \"Bun\",\n \"User-Agent\": navigator.userAgent,\n \"WebKit-Version\": process.versions.webkit,\n \"Bun-Version\": Bun.version,\n \"Bun-Revision\": Bun.revision\n };\n}, webSocketWriter = function(ws) {\n return {\n write: (message) => !!ws.sendText(message),\n close: () => ws.close()\n };\n}, socketWriter = function(socket) {\n return {\n write: (message) => !!socket.write(message),\n close: () => socket.end()\n };\n}, bufferedWriter = function(writer) {\n let draining = !1, pendingMessages = [];\n return {\n write: (message) => {\n if (draining || !writer.write(message))\n pendingMessages.push(message);\n return !0;\n },\n drain: () => {\n draining = !0;\n try {\n for (let i = 0;i < pendingMessages.length; i++)\n if (!writer.write(pendingMessages[i])) {\n pendingMessages = pendingMessages.slice(i);\n return;\n }\n } finally {\n draining = !1;\n }\n },\n close: () => {\n writer.close(), pendingMessages.length = 0;\n }\n };\n}, parseUrl = function(url) {\n try {\n if (!url)\n return new URL(randomId(), `ws://${defaultHostname}:${defaultPort}/`);\n else if (url.startsWith(\"/\"))\n return new URL(url, `ws://${defaultHostname}:${defaultPort}/`);\n else if (/^[a-z+]+:\\/\\//i.test(url))\n return new URL(url);\n else if (/^\\d+$/.test(url))\n return new URL(randomId(), `ws://${defaultHostname}:${url}/`);\n else if (!url.includes(\"/\") && url.includes(\":\"))\n return new URL(randomId(), `ws://${url}/`);\n else if (!url.includes(\":\")) {\n const [hostname, pathname] = url.split(\"/\", 2);\n return new URL(`ws://${hostname}:${defaultPort}/${pathname}`);\n } else\n return new URL(randomId(), `ws://${url}`);\n } catch {\n @throwTypeError(`Invalid hostname or URL: '${url}'`);\n }\n}, randomId = function() {\n return Math.random().toString(36).slice(2);\n}, dim = function(string) {\n if (enableANSIColors)\n return `\\x1B[2m${string}\\x1B[22m`;\n return string;\n}, link = function(url) {\n if (enableANSIColors)\n return `\\x1B[1m\\x1B]8;;${url}\\x1B\\\\${url}\\x1B]8;;\\x1B\\\\\\x1B[22m`;\n return url;\n}, reset = function() {\n if (enableANSIColors)\n return \"\\x1B[49m\";\n return \"\";\n}, notify = function(unix) {\n Bun.connect({\n unix,\n socket: {\n open: (socket) => {\n socket.end(\"1\");\n },\n data: () => {\n }\n }\n }).finally(() => {\n });\n}, exit = function(...args) {\n console.error(...args), process.exit(1);\n}, $;\n$ = function(executionContextId, url, createBackend, send, close) {\n let debug;\n try {\n debug = new Debugger(executionContextId, url, createBackend, send, close);\n } catch (error) {\n exit(\"Failed to start inspector:\\n\", error);\n }\n const { protocol, href, host, pathname } = debug.url;\n if (!protocol.includes(\"unix\")) {\n if (console.log(dim(\"--------------------- Bun Inspector ---------------------\"), reset()), console.log(`Listening:\\n ${dim(href)}`), protocol.includes(\"ws\"))\n console.log(`Inspect in browser:\\n ${link(`https://debug.bun.sh/#${host}${pathname}`)}`);\n console.log(dim(\"--------------------- Bun Inspector ---------------------\"), reset());\n }\n const unix = process.env.BUN_INSPECT_NOTIFY;\n if (unix) {\n const { protocol: protocol2, pathname: pathname2 } = parseUrl(unix);\n if (protocol2 === \"unix:\")\n notify(pathname2);\n }\n};\n\nclass Debugger {\n #url;\n #createBackend;\n constructor(executionContextId, url, createBackend, send, close) {\n this.#url = parseUrl(url), this.#createBackend = (refEventLoop, receive) => {\n const backend = createBackend(executionContextId, refEventLoop, receive);\n return {\n write: (message) => {\n return send.call(backend, message), !0;\n },\n close: () => close.call(backend)\n };\n }, this.#listen();\n }\n get url() {\n return this.#url;\n }\n #listen() {\n const { protocol, hostname, port, pathname } = this.#url;\n if (protocol === \"ws:\" || protocol === \"ws+tcp:\") {\n const server = Bun.serve({\n hostname,\n port,\n fetch: this.#fetch.bind(this),\n websocket: this.#websocket\n });\n this.#url.hostname = server.hostname, this.#url.port = `${server.port}`;\n return;\n }\n if (protocol === \"ws+unix:\") {\n Bun.serve({\n unix: pathname,\n fetch: this.#fetch.bind(this),\n websocket: this.#websocket\n });\n return;\n }\n @throwTypeError(`Unsupported protocol: '${protocol}' (expected 'ws:', 'ws+unix:', or 'unix:')`);\n }\n get #websocket() {\n return {\n idleTimeout: 0,\n closeOnBackpressureLimit: !1,\n open: (ws) => this.#open(ws, webSocketWriter(ws)),\n message: (ws, message) => {\n if (typeof message === \"string\")\n this.#message(ws, message);\n else\n this.#error(ws, new Error(`Unexpected binary message: ${message.toString()}`));\n },\n drain: (ws) => this.#drain(ws),\n close: (ws) => this.#close(ws)\n };\n }\n #fetch(request, server) {\n const { method, url, headers } = request, { pathname } = new URL(url);\n if (method !== \"GET\")\n return new Response(null, {\n status: 405\n });\n switch (pathname) {\n case \"/json/version\":\n return Response.json(versionInfo());\n case \"/json\":\n case \"/json/list\":\n }\n if (!this.#url.protocol.includes(\"unix\") && this.#url.pathname !== pathname)\n return new Response(null, {\n status: 404\n });\n const data = {\n refEventLoop: headers.get(\"Ref-Event-Loop\") === \"0\"\n };\n if (!server.upgrade(request, { data }))\n return new Response(null, {\n status: 426,\n headers: {\n Upgrade: \"websocket\"\n }\n });\n }\n get #socket() {\n return {\n open: (socket) => this.#open(socket, socketWriter(socket)),\n data: (socket, message) => this.#message(socket, message.toString()),\n drain: (socket) => this.#drain(socket),\n close: (socket) => this.#close(socket),\n error: (socket, error) => this.#error(socket, error),\n connectError: (_, error) => exit(\"Failed to start inspector:\\n\", error)\n };\n }\n #open(connection, writer) {\n const { data } = connection, { refEventLoop } = data, client = bufferedWriter(writer), backend = this.#createBackend(refEventLoop, (...messages) => {\n for (let message of messages)\n client.write(message);\n });\n data.client = client, data.backend = backend;\n }\n #message(connection, message) {\n const { data } = connection, { backend } = data;\n backend\?.write(message);\n }\n #drain(connection) {\n const { data } = connection, { client } = data;\n client\?.drain\?.();\n }\n #close(connection) {\n const { data } = connection, { backend } = data;\n backend\?.close();\n }\n #error(connection, error) {\n const { data } = connection, { backend } = data;\n console.error(error), backend\?.close();\n }\n}\nvar defaultHostname = \"localhost\", defaultPort = 6499, { enableANSIColors } = Bun;\nreturn $})\n"_s;
//
//
@@ -247,7 +247,7 @@ static constexpr ASCIILiteral BunSqliteCode = "(function (){\"use strict\";// sr
//
//
-static constexpr ASCIILiteral InternalDebuggerCode = "(function (){\"use strict\";// src/js/out/tmp/internal/debugger.ts\nvar generatePath = function() {\n if (!generatedPath)\n generatedPath = \"/\" + Math.random().toString(36).slice(2);\n return generatedPath;\n}, terminalLink = function(url) {\n if (colors)\n return \"\\x1B[1m\\x1B]8;;\" + url + \"\\x1B\\\\\" + url + \"\\x1B]8;;\\x1B\\\\\" + \"\\x1B[22m\";\n return url;\n}, dim = function(text) {\n if (colors)\n return \"\\x1B[2m\" + text + \"\\x1B[22m\";\n return text;\n}, notify = function() {\n const unix = process.env.BUN_INSPECT_NOTIFY;\n if (!unix || !unix.startsWith(\"unix://\"))\n return;\n Bun.connect({\n unix: unix.slice(7),\n socket: {\n open: (socket) => {\n socket.end(\"1\");\n },\n data: () => {\n }\n }\n }).finally(() => {\n });\n}, $, sendFn_, disconnectFn_, colors = Bun.enableANSIColors && process.env.NO_COLOR !== \"1\", debuggerCounter = 1;\n\nclass DebuggerWithMessageQueue {\n debugger = void 0;\n messageQueue = [];\n count = debuggerCounter++;\n send(msg) {\n sendFn_.call(this.debugger, msg);\n }\n disconnect() {\n disconnectFn_.call(this.debugger), this.messageQueue.length = 0;\n }\n}\nvar defaultPort = 6499, generatedPath = \"\";\n\nclass WebSocketListener {\n server;\n url = \"\";\n createInspectorConnection;\n scriptExecutionContextId = 0;\n activeConnections = new Set;\n constructor(scriptExecutionContextId = 0, url, createInspectorConnection) {\n this.scriptExecutionContextId = scriptExecutionContextId, this.createInspectorConnection = createInspectorConnection, this.server = this.start(url);\n }\n start(url) {\n let defaultHostname = \"localhost\", usingDefaultPort = !1, isUnix = !1;\n if (url.startsWith(\"ws+unix://\"))\n isUnix = !0, url = url.slice(10);\n else if (/^[0-9]*$/.test(url))\n url = \"ws://\" + defaultHostname + \":\" + url + generatePath();\n else if (!url || url.startsWith(\"/\"))\n url = \"ws://\" + defaultHostname + \":\" + defaultPort + generatePath(), usingDefaultPort = !0;\n else if (url.includes(\":\") && !url.includes(\"://\"))\n try {\n const insertSlash = !url.includes(\"/\");\n if (url = new URL(\"ws://\" + url).href, insertSlash)\n url += generatePath().slice(1);\n } catch (e) {\n console.error(\"[Inspector]\", \"Failed to parse url\", '\"' + url + '\"'), process.exit(1);\n }\n if (!isUnix)\n try {\n var { hostname, port, pathname } = new URL(url);\n this.url = pathname.toLowerCase();\n } catch (e) {\n console.error(\"[Inspector]\", \"Failed to parse url\", '\"' + url + '\"'), process.exit(1);\n }\n const serveOptions = {\n ...isUnix \? { unix: url } : { hostname },\n development: !1,\n reusePort: !1,\n websocket: {\n idleTimeout: 0,\n open: (socket) => {\n var connection = new DebuggerWithMessageQueue;\n const shouldRefEventLoop = !!socket.data\?.shouldRefEventLoop;\n if (socket.data = connection, this.activeConnections.add(socket), connection.debugger = this.createInspectorConnection(this.scriptExecutionContextId, shouldRefEventLoop, (...msgs) => {\n if (socket.readyState > 1) {\n connection.disconnect();\n return;\n }\n if (connection.messageQueue.length > 0) {\n connection.messageQueue.push(...msgs);\n return;\n }\n for (let i = 0;i < msgs.length; i++)\n if (!socket.sendText(msgs[i])) {\n if (socket.readyState < 2)\n connection.messageQueue.push(...msgs.slice(i));\n return;\n }\n }), !isUnix)\n console.log(\"[Inspector]\", \"Connection #\" + connection.count + \" opened\", \"(\" + new Intl.DateTimeFormat(void 0, {\n timeStyle: \"long\",\n dateStyle: \"short\"\n }).format(new Date) + \")\");\n },\n drain: (socket) => {\n const queue = socket.data.messageQueue;\n for (let i = 0;i < queue.length; i++)\n if (!socket.sendText(queue[i])) {\n socket.data.messageQueue = queue.slice(i);\n return;\n }\n queue.length = 0;\n },\n message: (socket, message) => {\n if (typeof message !== \"string\") {\n console.warn(\"[Inspector]\", \"Received non-string message\");\n return;\n }\n socket.data.send(message);\n },\n close: (socket) => {\n if (socket.data.disconnect(), !isUnix)\n console.log(\"[Inspector]\", \"Connection #\" + socket.data.count + \" closed\", \"(\" + new Intl.DateTimeFormat(void 0, {\n timeStyle: \"long\",\n dateStyle: \"short\"\n }).format(new Date) + \")\");\n this.activeConnections.delete(socket);\n }\n },\n fetch: (req, server2) => {\n let { pathname: pathname2 } = new URL(req.url);\n if (pathname2 = pathname2.toLowerCase(), pathname2 === \"/json/version\")\n return Response.json({\n Browser: navigator.userAgent,\n \"WebKit-Version\": process.versions.webkit,\n \"Bun-Version\": Bun.version,\n \"Bun-Revision\": Bun.revision\n });\n if (!this.url || pathname2 === this.url) {\n const refHeader = req.headers.get(\"Ref-Event-Loop\");\n if (server2.upgrade(req, {\n data: {\n shouldRefEventLoop: !!refHeader && refHeader !== \"0\"\n }\n }))\n return new Response;\n return new Response(\"WebSocket expected\", {\n status: 400\n });\n }\n return new Response(\"Not found\", {\n status: 404\n });\n }\n };\n if (port === \"\")\n port = defaultPort + \"\";\n let portNumber = Number(port);\n var server, lastError;\n if (usingDefaultPort)\n for (let tries = 0;tries < 10 && !server; tries++)\n try {\n if (lastError = void 0, server = Bun.serve({\n ...serveOptions,\n port: portNumber++\n }), isUnix)\n notify();\n } catch (e) {\n lastError = e;\n }\n else\n try {\n if (server = Bun.serve({\n ...serveOptions,\n port: portNumber\n }), isUnix)\n notify();\n } catch (e) {\n lastError = e;\n }\n if (!server) {\n if (console.error(\"[Inspector]\", \"Failed to start server\"), lastError)\n console.error(lastError);\n process.exit(1);\n }\n let textToWrite = \"\";\n function writeToConsole(text) {\n textToWrite += text;\n }\n function flushToConsole() {\n console.write(textToWrite);\n }\n if (!this.url)\n return server;\n if (writeToConsole(dim(\"------------------ Bun Inspector ------------------\\n\")), colors)\n writeToConsole(\"\\x1B[49m\");\n return writeToConsole(\"Listening at:\\n \" + `ws://${hostname}:${server.port}${this.url}` + \"\\n\\nInspect in browser:\\n \" + terminalLink(new URL(`https://debug.bun.sh#${server.hostname}:${server.port}${this.url}`).href) + \"\\n\"), writeToConsole(dim(\"------------------ Bun Inspector ------------------\\n\")), flushToConsole(), server;\n }\n}\nvar listener;\n$ = function start(debuggerId, hostOrPort, createInspectorConnection, sendFn, disconnectFn) {\n try {\n sendFn_ = sendFn, disconnectFn_ = disconnectFn, globalThis.listener = listener ||= new WebSocketListener(debuggerId, hostOrPort, createInspectorConnection);\n } catch (e) {\n console.error(\"Bun Inspector threw an exception\\n\", e), process.exit(1);\n }\n return `http://${listener.server.hostname}:${listener.server.port}${listener.url}`;\n};\nreturn $})\n"_s;
+static constexpr ASCIILiteral InternalDebuggerCode = "(function (){\"use strict\";// src/js/out/tmp/internal/debugger.ts\nvar versionInfo = function() {\n return {\n \"Protocol-Version\": \"1.3\",\n Browser: \"Bun\",\n \"User-Agent\": navigator.userAgent,\n \"WebKit-Version\": process.versions.webkit,\n \"Bun-Version\": Bun.version,\n \"Bun-Revision\": Bun.revision\n };\n}, webSocketWriter = function(ws) {\n return {\n write: (message) => !!ws.sendText(message),\n close: () => ws.close()\n };\n}, socketWriter = function(socket) {\n return {\n write: (message) => !!socket.write(message),\n close: () => socket.end()\n };\n}, bufferedWriter = function(writer) {\n let draining = !1, pendingMessages = [];\n return {\n write: (message) => {\n if (draining || !writer.write(message))\n pendingMessages.push(message);\n return !0;\n },\n drain: () => {\n draining = !0;\n try {\n for (let i = 0;i < pendingMessages.length; i++)\n if (!writer.write(pendingMessages[i])) {\n pendingMessages = pendingMessages.slice(i);\n return;\n }\n } finally {\n draining = !1;\n }\n },\n close: () => {\n writer.close(), pendingMessages.length = 0;\n }\n };\n}, parseUrl = function(url) {\n try {\n if (!url)\n return new URL(randomId(), `ws://${defaultHostname}:${defaultPort}/`);\n else if (url.startsWith(\"/\"))\n return new URL(url, `ws://${defaultHostname}:${defaultPort}/`);\n else if (/^[a-z+]+:\\/\\//i.test(url))\n return new URL(url);\n else if (/^\\d+$/.test(url))\n return new URL(randomId(), `ws://${defaultHostname}:${url}/`);\n else if (!url.includes(\"/\") && url.includes(\":\"))\n return new URL(randomId(), `ws://${url}/`);\n else if (!url.includes(\":\")) {\n const [hostname, pathname] = url.split(\"/\", 2);\n return new URL(`ws://${hostname}:${defaultPort}/${pathname}`);\n } else\n return new URL(randomId(), `ws://${url}`);\n } catch {\n @throwTypeError(`Invalid hostname or URL: '${url}'`);\n }\n}, randomId = function() {\n return Math.random().toString(36).slice(2);\n}, dim = function(string) {\n if (enableANSIColors)\n return `\\x1B[2m${string}\\x1B[22m`;\n return string;\n}, link = function(url) {\n if (enableANSIColors)\n return `\\x1B[1m\\x1B]8;;${url}\\x1B\\\\${url}\\x1B]8;;\\x1B\\\\\\x1B[22m`;\n return url;\n}, reset = function() {\n if (enableANSIColors)\n return \"\\x1B[49m\";\n return \"\";\n}, notify = function(unix) {\n Bun.connect({\n unix,\n socket: {\n open: (socket) => {\n socket.end(\"1\");\n },\n data: () => {\n }\n }\n }).finally(() => {\n });\n}, exit = function(...args) {\n console.error(...args), process.exit(1);\n}, $;\n$ = function(executionContextId, url, createBackend, send, close) {\n let debug;\n try {\n debug = new Debugger(executionContextId, url, createBackend, send, close);\n } catch (error) {\n exit(\"Failed to start inspector:\\n\", error);\n }\n const { protocol, href, host, pathname } = debug.url;\n if (!protocol.includes(\"unix\")) {\n if (console.log(dim(\"--------------------- Bun Inspector ---------------------\"), reset()), console.log(`Listening:\\n ${dim(href)}`), protocol.includes(\"ws\"))\n console.log(`Inspect in browser:\\n ${link(`https://debug.bun.sh/#${host}${pathname}`)}`);\n console.log(dim(\"--------------------- Bun Inspector ---------------------\"), reset());\n }\n const unix = process.env.BUN_INSPECT_NOTIFY;\n if (unix) {\n const { protocol: protocol2, pathname: pathname2 } = parseUrl(unix);\n if (protocol2 === \"unix:\")\n notify(pathname2);\n }\n};\n\nclass Debugger {\n #url;\n #createBackend;\n constructor(executionContextId, url, createBackend, send, close) {\n this.#url = parseUrl(url), this.#createBackend = (refEventLoop, receive) => {\n const backend = createBackend(executionContextId, refEventLoop, receive);\n return {\n write: (message) => {\n return send.call(backend, message), !0;\n },\n close: () => close.call(backend)\n };\n }, this.#listen();\n }\n get url() {\n return this.#url;\n }\n #listen() {\n const { protocol, hostname, port, pathname } = this.#url;\n if (protocol === \"ws:\" || protocol === \"ws+tcp:\") {\n const server = Bun.serve({\n hostname,\n port,\n fetch: this.#fetch.bind(this),\n websocket: this.#websocket\n });\n this.#url.hostname = server.hostname, this.#url.port = `${server.port}`;\n return;\n }\n if (protocol === \"ws+unix:\") {\n Bun.serve({\n unix: pathname,\n fetch: this.#fetch.bind(this),\n websocket: this.#websocket\n });\n return;\n }\n @throwTypeError(`Unsupported protocol: '${protocol}' (expected 'ws:', 'ws+unix:', or 'unix:')`);\n }\n get #websocket() {\n return {\n idleTimeout: 0,\n closeOnBackpressureLimit: !1,\n open: (ws) => this.#open(ws, webSocketWriter(ws)),\n message: (ws, message) => {\n if (typeof message === \"string\")\n this.#message(ws, message);\n else\n this.#error(ws, new Error(`Unexpected binary message: ${message.toString()}`));\n },\n drain: (ws) => this.#drain(ws),\n close: (ws) => this.#close(ws)\n };\n }\n #fetch(request, server) {\n const { method, url, headers } = request, { pathname } = new URL(url);\n if (method !== \"GET\")\n return new Response(null, {\n status: 405\n });\n switch (pathname) {\n case \"/json/version\":\n return Response.json(versionInfo());\n case \"/json\":\n case \"/json/list\":\n }\n if (!this.#url.protocol.includes(\"unix\") && this.#url.pathname !== pathname)\n return new Response(null, {\n status: 404\n });\n const data = {\n refEventLoop: headers.get(\"Ref-Event-Loop\") === \"0\"\n };\n if (!server.upgrade(request, { data }))\n return new Response(null, {\n status: 426,\n headers: {\n Upgrade: \"websocket\"\n }\n });\n }\n get #socket() {\n return {\n open: (socket) => this.#open(socket, socketWriter(socket)),\n data: (socket, message) => this.#message(socket, message.toString()),\n drain: (socket) => this.#drain(socket),\n close: (socket) => this.#close(socket),\n error: (socket, error) => this.#error(socket, error),\n connectError: (_, error) => exit(\"Failed to start inspector:\\n\", error)\n };\n }\n #open(connection, writer) {\n const { data } = connection, { refEventLoop } = data, client = bufferedWriter(writer), backend = this.#createBackend(refEventLoop, (...messages) => {\n for (let message of messages)\n client.write(message);\n });\n data.client = client, data.backend = backend;\n }\n #message(connection, message) {\n const { data } = connection, { backend } = data;\n backend\?.write(message);\n }\n #drain(connection) {\n const { data } = connection, { client } = data;\n client\?.drain\?.();\n }\n #close(connection) {\n const { data } = connection, { backend } = data;\n backend\?.close();\n }\n #error(connection, error) {\n const { data } = connection, { backend } = data;\n console.error(error), backend\?.close();\n }\n}\nvar defaultHostname = \"localhost\", defaultPort = 6499, { enableANSIColors } = Bun;\nreturn $})\n"_s;
//
//
@@ -481,7 +481,7 @@ static constexpr ASCIILiteral BunSqliteCode = "(function (){\"use strict\";// sr
//
//
-static constexpr ASCIILiteral InternalDebuggerCode = "(function (){\"use strict\";// src/js/out/tmp/internal/debugger.ts\nvar generatePath = function() {\n if (!generatedPath)\n generatedPath = \"/\" + Math.random().toString(36).slice(2);\n return generatedPath;\n}, terminalLink = function(url) {\n if (colors)\n return \"\\x1B[1m\\x1B]8;;\" + url + \"\\x1B\\\\\" + url + \"\\x1B]8;;\\x1B\\\\\" + \"\\x1B[22m\";\n return url;\n}, dim = function(text) {\n if (colors)\n return \"\\x1B[2m\" + text + \"\\x1B[22m\";\n return text;\n}, notify = function() {\n const unix = process.env.BUN_INSPECT_NOTIFY;\n if (!unix || !unix.startsWith(\"unix://\"))\n return;\n Bun.connect({\n unix: unix.slice(7),\n socket: {\n open: (socket) => {\n socket.end(\"1\");\n },\n data: () => {\n }\n }\n }).finally(() => {\n });\n}, $, sendFn_, disconnectFn_, colors = Bun.enableANSIColors && process.env.NO_COLOR !== \"1\", debuggerCounter = 1;\n\nclass DebuggerWithMessageQueue {\n debugger = void 0;\n messageQueue = [];\n count = debuggerCounter++;\n send(msg) {\n sendFn_.call(this.debugger, msg);\n }\n disconnect() {\n disconnectFn_.call(this.debugger), this.messageQueue.length = 0;\n }\n}\nvar defaultPort = 6499, generatedPath = \"\";\n\nclass WebSocketListener {\n server;\n url = \"\";\n createInspectorConnection;\n scriptExecutionContextId = 0;\n activeConnections = new Set;\n constructor(scriptExecutionContextId = 0, url, createInspectorConnection) {\n this.scriptExecutionContextId = scriptExecutionContextId, this.createInspectorConnection = createInspectorConnection, this.server = this.start(url);\n }\n start(url) {\n let defaultHostname = \"localhost\", usingDefaultPort = !1, isUnix = !1;\n if (url.startsWith(\"ws+unix://\"))\n isUnix = !0, url = url.slice(10);\n else if (/^[0-9]*$/.test(url))\n url = \"ws://\" + defaultHostname + \":\" + url + generatePath();\n else if (!url || url.startsWith(\"/\"))\n url = \"ws://\" + defaultHostname + \":\" + defaultPort + generatePath(), usingDefaultPort = !0;\n else if (url.includes(\":\") && !url.includes(\"://\"))\n try {\n const insertSlash = !url.includes(\"/\");\n if (url = new URL(\"ws://\" + url).href, insertSlash)\n url += generatePath().slice(1);\n } catch (e) {\n console.error(\"[Inspector]\", \"Failed to parse url\", '\"' + url + '\"'), process.exit(1);\n }\n if (!isUnix)\n try {\n var { hostname, port, pathname } = new URL(url);\n this.url = pathname.toLowerCase();\n } catch (e) {\n console.error(\"[Inspector]\", \"Failed to parse url\", '\"' + url + '\"'), process.exit(1);\n }\n const serveOptions = {\n ...isUnix \? { unix: url } : { hostname },\n development: !1,\n reusePort: !1,\n websocket: {\n idleTimeout: 0,\n open: (socket) => {\n var connection = new DebuggerWithMessageQueue;\n const shouldRefEventLoop = !!socket.data\?.shouldRefEventLoop;\n if (socket.data = connection, this.activeConnections.add(socket), connection.debugger = this.createInspectorConnection(this.scriptExecutionContextId, shouldRefEventLoop, (...msgs) => {\n if (socket.readyState > 1) {\n connection.disconnect();\n return;\n }\n if (connection.messageQueue.length > 0) {\n connection.messageQueue.push(...msgs);\n return;\n }\n for (let i = 0;i < msgs.length; i++)\n if (!socket.sendText(msgs[i])) {\n if (socket.readyState < 2)\n connection.messageQueue.push(...msgs.slice(i));\n return;\n }\n }), !isUnix)\n console.log(\"[Inspector]\", \"Connection #\" + connection.count + \" opened\", \"(\" + new Intl.DateTimeFormat(void 0, {\n timeStyle: \"long\",\n dateStyle: \"short\"\n }).format(new Date) + \")\");\n },\n drain: (socket) => {\n const queue = socket.data.messageQueue;\n for (let i = 0;i < queue.length; i++)\n if (!socket.sendText(queue[i])) {\n socket.data.messageQueue = queue.slice(i);\n return;\n }\n queue.length = 0;\n },\n message: (socket, message) => {\n if (typeof message !== \"string\") {\n console.warn(\"[Inspector]\", \"Received non-string message\");\n return;\n }\n socket.data.send(message);\n },\n close: (socket) => {\n if (socket.data.disconnect(), !isUnix)\n console.log(\"[Inspector]\", \"Connection #\" + socket.data.count + \" closed\", \"(\" + new Intl.DateTimeFormat(void 0, {\n timeStyle: \"long\",\n dateStyle: \"short\"\n }).format(new Date) + \")\");\n this.activeConnections.delete(socket);\n }\n },\n fetch: (req, server2) => {\n let { pathname: pathname2 } = new URL(req.url);\n if (pathname2 = pathname2.toLowerCase(), pathname2 === \"/json/version\")\n return Response.json({\n Browser: navigator.userAgent,\n \"WebKit-Version\": process.versions.webkit,\n \"Bun-Version\": Bun.version,\n \"Bun-Revision\": Bun.revision\n });\n if (!this.url || pathname2 === this.url) {\n const refHeader = req.headers.get(\"Ref-Event-Loop\");\n if (server2.upgrade(req, {\n data: {\n shouldRefEventLoop: !!refHeader && refHeader !== \"0\"\n }\n }))\n return new Response;\n return new Response(\"WebSocket expected\", {\n status: 400\n });\n }\n return new Response(\"Not found\", {\n status: 404\n });\n }\n };\n if (port === \"\")\n port = defaultPort + \"\";\n let portNumber = Number(port);\n var server, lastError;\n if (usingDefaultPort)\n for (let tries = 0;tries < 10 && !server; tries++)\n try {\n if (lastError = void 0, server = Bun.serve({\n ...serveOptions,\n port: portNumber++\n }), isUnix)\n notify();\n } catch (e) {\n lastError = e;\n }\n else\n try {\n if (server = Bun.serve({\n ...serveOptions,\n port: portNumber\n }), isUnix)\n notify();\n } catch (e) {\n lastError = e;\n }\n if (!server) {\n if (console.error(\"[Inspector]\", \"Failed to start server\"), lastError)\n console.error(lastError);\n process.exit(1);\n }\n let textToWrite = \"\";\n function writeToConsole(text) {\n textToWrite += text;\n }\n function flushToConsole() {\n console.write(textToWrite);\n }\n if (!this.url)\n return server;\n if (writeToConsole(dim(\"------------------ Bun Inspector ------------------\\n\")), colors)\n writeToConsole(\"\\x1B[49m\");\n return writeToConsole(\"Listening at:\\n \" + `ws://${hostname}:${server.port}${this.url}` + \"\\n\\nInspect in browser:\\n \" + terminalLink(new URL(`https://debug.bun.sh#${server.hostname}:${server.port}${this.url}`).href) + \"\\n\"), writeToConsole(dim(\"------------------ Bun Inspector ------------------\\n\")), flushToConsole(), server;\n }\n}\nvar listener;\n$ = function start(debuggerId, hostOrPort, createInspectorConnection, sendFn, disconnectFn) {\n try {\n sendFn_ = sendFn, disconnectFn_ = disconnectFn, globalThis.listener = listener ||= new WebSocketListener(debuggerId, hostOrPort, createInspectorConnection);\n } catch (e) {\n console.error(\"Bun Inspector threw an exception\\n\", e), process.exit(1);\n }\n return `http://${listener.server.hostname}:${listener.server.port}${listener.url}`;\n};\nreturn $})\n"_s;
+static constexpr ASCIILiteral InternalDebuggerCode = "(function (){\"use strict\";// src/js/out/tmp/internal/debugger.ts\nvar versionInfo = function() {\n return {\n \"Protocol-Version\": \"1.3\",\n Browser: \"Bun\",\n \"User-Agent\": navigator.userAgent,\n \"WebKit-Version\": process.versions.webkit,\n \"Bun-Version\": Bun.version,\n \"Bun-Revision\": Bun.revision\n };\n}, webSocketWriter = function(ws) {\n return {\n write: (message) => !!ws.sendText(message),\n close: () => ws.close()\n };\n}, socketWriter = function(socket) {\n return {\n write: (message) => !!socket.write(message),\n close: () => socket.end()\n };\n}, bufferedWriter = function(writer) {\n let draining = !1, pendingMessages = [];\n return {\n write: (message) => {\n if (draining || !writer.write(message))\n pendingMessages.push(message);\n return !0;\n },\n drain: () => {\n draining = !0;\n try {\n for (let i = 0;i < pendingMessages.length; i++)\n if (!writer.write(pendingMessages[i])) {\n pendingMessages = pendingMessages.slice(i);\n return;\n }\n } finally {\n draining = !1;\n }\n },\n close: () => {\n writer.close(), pendingMessages.length = 0;\n }\n };\n}, parseUrl = function(url) {\n try {\n if (!url)\n return new URL(randomId(), `ws://${defaultHostname}:${defaultPort}/`);\n else if (url.startsWith(\"/\"))\n return new URL(url, `ws://${defaultHostname}:${defaultPort}/`);\n else if (/^[a-z+]+:\\/\\//i.test(url))\n return new URL(url);\n else if (/^\\d+$/.test(url))\n return new URL(randomId(), `ws://${defaultHostname}:${url}/`);\n else if (!url.includes(\"/\") && url.includes(\":\"))\n return new URL(randomId(), `ws://${url}/`);\n else if (!url.includes(\":\")) {\n const [hostname, pathname] = url.split(\"/\", 2);\n return new URL(`ws://${hostname}:${defaultPort}/${pathname}`);\n } else\n return new URL(randomId(), `ws://${url}`);\n } catch {\n @throwTypeError(`Invalid hostname or URL: '${url}'`);\n }\n}, randomId = function() {\n return Math.random().toString(36).slice(2);\n}, dim = function(string) {\n if (enableANSIColors)\n return `\\x1B[2m${string}\\x1B[22m`;\n return string;\n}, link = function(url) {\n if (enableANSIColors)\n return `\\x1B[1m\\x1B]8;;${url}\\x1B\\\\${url}\\x1B]8;;\\x1B\\\\\\x1B[22m`;\n return url;\n}, reset = function() {\n if (enableANSIColors)\n return \"\\x1B[49m\";\n return \"\";\n}, notify = function(unix) {\n Bun.connect({\n unix,\n socket: {\n open: (socket) => {\n socket.end(\"1\");\n },\n data: () => {\n }\n }\n }).finally(() => {\n });\n}, exit = function(...args) {\n console.error(...args), process.exit(1);\n}, $;\n$ = function(executionContextId, url, createBackend, send, close) {\n let debug;\n try {\n debug = new Debugger(executionContextId, url, createBackend, send, close);\n } catch (error) {\n exit(\"Failed to start inspector:\\n\", error);\n }\n const { protocol, href, host, pathname } = debug.url;\n if (!protocol.includes(\"unix\")) {\n if (console.log(dim(\"--------------------- Bun Inspector ---------------------\"), reset()), console.log(`Listening:\\n ${dim(href)}`), protocol.includes(\"ws\"))\n console.log(`Inspect in browser:\\n ${link(`https://debug.bun.sh/#${host}${pathname}`)}`);\n console.log(dim(\"--------------------- Bun Inspector ---------------------\"), reset());\n }\n const unix = process.env.BUN_INSPECT_NOTIFY;\n if (unix) {\n const { protocol: protocol2, pathname: pathname2 } = parseUrl(unix);\n if (protocol2 === \"unix:\")\n notify(pathname2);\n }\n};\n\nclass Debugger {\n #url;\n #createBackend;\n constructor(executionContextId, url, createBackend, send, close) {\n this.#url = parseUrl(url), this.#createBackend = (refEventLoop, receive) => {\n const backend = createBackend(executionContextId, refEventLoop, receive);\n return {\n write: (message) => {\n return send.call(backend, message), !0;\n },\n close: () => close.call(backend)\n };\n }, this.#listen();\n }\n get url() {\n return this.#url;\n }\n #listen() {\n const { protocol, hostname, port, pathname } = this.#url;\n if (protocol === \"ws:\" || protocol === \"ws+tcp:\") {\n const server = Bun.serve({\n hostname,\n port,\n fetch: this.#fetch.bind(this),\n websocket: this.#websocket\n });\n this.#url.hostname = server.hostname, this.#url.port = `${server.port}`;\n return;\n }\n if (protocol === \"ws+unix:\") {\n Bun.serve({\n unix: pathname,\n fetch: this.#fetch.bind(this),\n websocket: this.#websocket\n });\n return;\n }\n @throwTypeError(`Unsupported protocol: '${protocol}' (expected 'ws:', 'ws+unix:', or 'unix:')`);\n }\n get #websocket() {\n return {\n idleTimeout: 0,\n closeOnBackpressureLimit: !1,\n open: (ws) => this.#open(ws, webSocketWriter(ws)),\n message: (ws, message) => {\n if (typeof message === \"string\")\n this.#message(ws, message);\n else\n this.#error(ws, new Error(`Unexpected binary message: ${message.toString()}`));\n },\n drain: (ws) => this.#drain(ws),\n close: (ws) => this.#close(ws)\n };\n }\n #fetch(request, server) {\n const { method, url, headers } = request, { pathname } = new URL(url);\n if (method !== \"GET\")\n return new Response(null, {\n status: 405\n });\n switch (pathname) {\n case \"/json/version\":\n return Response.json(versionInfo());\n case \"/json\":\n case \"/json/list\":\n }\n if (!this.#url.protocol.includes(\"unix\") && this.#url.pathname !== pathname)\n return new Response(null, {\n status: 404\n });\n const data = {\n refEventLoop: headers.get(\"Ref-Event-Loop\") === \"0\"\n };\n if (!server.upgrade(request, { data }))\n return new Response(null, {\n status: 426,\n headers: {\n Upgrade: \"websocket\"\n }\n });\n }\n get #socket() {\n return {\n open: (socket) => this.#open(socket, socketWriter(socket)),\n data: (socket, message) => this.#message(socket, message.toString()),\n drain: (socket) => this.#drain(socket),\n close: (socket) => this.#close(socket),\n error: (socket, error) => this.#error(socket, error),\n connectError: (_, error) => exit(\"Failed to start inspector:\\n\", error)\n };\n }\n #open(connection, writer) {\n const { data } = connection, { refEventLoop } = data, client = bufferedWriter(writer), backend = this.#createBackend(refEventLoop, (...messages) => {\n for (let message of messages)\n client.write(message);\n });\n data.client = client, data.backend = backend;\n }\n #message(connection, message) {\n const { data } = connection, { backend } = data;\n backend\?.write(message);\n }\n #drain(connection) {\n const { data } = connection, { client } = data;\n client\?.drain\?.();\n }\n #close(connection) {\n const { data } = connection, { backend } = data;\n backend\?.close();\n }\n #error(connection, error) {\n const { data } = connection, { backend } = data;\n console.error(error), backend\?.close();\n }\n}\nvar defaultHostname = \"localhost\", defaultPort = 6499, { enableANSIColors } = Bun;\nreturn $})\n"_s;
//
//