From 08222eda715f250e6c4238690a3381503694e402 Mon Sep 17 00:00:00 2001 From: Alistair Smith Date: Thu, 28 Nov 2024 04:47:23 +0000 Subject: [PATCH] fix: Connect with 1 socket to new env var but still work with js debug terminal (#15458) --- packages/bun-vscode/src/features/debug.ts | 2 + .../src/features/diagnostics/diagnostics.ts | 57 ++++++++----------- packages/bun-vscode/src/global-state.ts | 2 +- src/bun.js/javascript.zig | 25 ++++---- 4 files changed, 42 insertions(+), 44 deletions(-) diff --git a/packages/bun-vscode/src/features/debug.ts b/packages/bun-vscode/src/features/debug.ts index ee7c2ca91fa0b1..19b91cc476509c 100644 --- a/packages/bun-vscode/src/features/debug.ts +++ b/packages/bun-vscode/src/features/debug.ts @@ -120,6 +120,7 @@ async function injectDebugTerminal(terminal: vscode.Terminal): Promise { ...env, "BUN_INSPECT": `${adapter.url}?${query}`, "BUN_INSPECT_NOTIFY": signal.url, + BUN_INSPECT_CONNECT_TO: "", }, }); @@ -351,6 +352,7 @@ class TerminalDebugSession extends FileDebugSession { env: { "BUN_INSPECT": `${this.adapter.url}?wait=1`, "BUN_INSPECT_NOTIFY": this.signal.url, + BUN_INSPECT_CONNECT_TO: "", }, isTransient: true, iconPath: new vscode.ThemeIcon("debug-console"), diff --git a/packages/bun-vscode/src/features/diagnostics/diagnostics.ts b/packages/bun-vscode/src/features/diagnostics/diagnostics.ts index a63b8ce705258e..cacc9f0bf0174f 100644 --- a/packages/bun-vscode/src/features/diagnostics/diagnostics.ts +++ b/packages/bun-vscode/src/features/diagnostics/diagnostics.ts @@ -1,16 +1,16 @@ import * as fs from "node:fs/promises"; +import { Socket } from "node:net"; import * as os from "node:os"; import { inspect } from "node:util"; import * as vscode from "vscode"; import { getAvailablePort, - getRandomId, + NodeSocketDebugAdapter, TCPSocketSignal, UnixSignal, - WebSocketDebugAdapter, } from "../../../../bun-debug-adapter-protocol"; import type { JSC } from "../../../../bun-inspector-protocol"; -import { createGlobalStateGenerationFn, typedGlobalState } from "../../global-state"; +import { typedGlobalState } from "../../global-state"; const output = vscode.window.createOutputChannel("Bun - Diagnostics"); @@ -70,15 +70,14 @@ class BunDiagnosticsManager { private readonly editorState: EditorStateManager; private readonly signal: UnixSignal | TCPSocketSignal; private readonly context: vscode.ExtensionContext; - public readonly inspectUrl: string; - public get notifyUrl() { + public get signalUrl() { return this.signal.url; } private static async getOrRecreateSignal(context: vscode.ExtensionContext) { const globalState = typedGlobalState(context.globalState); - const existing = globalState.get("BUN_INSPECT_NOTIFY"); + const existing = globalState.get("BUN_INSPECT_CONNECT_TO"); const isWin = os.platform() === "win32"; @@ -102,7 +101,7 @@ class BunDiagnosticsManager { if (isWin) { const port = await getAvailablePort(); - await globalState.update("BUN_INSPECT_NOTIFY", { + await globalState.update("BUN_INSPECT_CONNECT_TO", { type: "tcp", port, }); @@ -113,7 +112,7 @@ class BunDiagnosticsManager { } else { const signal = new UnixSignal(); - await globalState.update("BUN_INSPECT_NOTIFY", { + await globalState.update("BUN_INSPECT_CONNECT_TO", { type: "unix", url: signal.url, }); @@ -124,30 +123,29 @@ class BunDiagnosticsManager { } } - private static getOrCreateOldVersionInspectURL = createGlobalStateGenerationFn( - "DIAGNOSTICS_BUN_INSPECT", - async () => { - const url = - process.platform === "win32" - ? `ws://127.0.0.1:${await getAvailablePort()}/${getRandomId()}` - : `ws+unix://${os.tmpdir()}/${getRandomId()}.sock`; + // private static getOrCreateOldVersionInspectURL = createGlobalStateGenerationFn( + // "DIAGNOSTICS_BUN_INSPECT", + // async () => { + // const url = + // process.platform === "win32" + // ? `ws://127.0.0.1:${await getAvailablePort()}/${getRandomId()}` + // : `ws+unix://${os.tmpdir()}/${getRandomId()}.sock`; - return url; - }, - ); + // return url; + // }, + // ); public static async initialize(context: vscode.ExtensionContext) { const signal = await BunDiagnosticsManager.getOrRecreateSignal(context); - const oldVersionInspectURL = await BunDiagnosticsManager.getOrCreateOldVersionInspectURL(context.globalState); - return new BunDiagnosticsManager(context, signal, oldVersionInspectURL); + return new BunDiagnosticsManager(context, signal); } /** * Called when Bun pings BUN_INSPECT_NOTIFY (indicating a program has started). */ - private async handleSocketConnection() { - const debugAdapter = new WebSocketDebugAdapter(this.inspectUrl); + private async handleSocketConnection(socket: Socket) { + const debugAdapter = new NodeSocketDebugAdapter(socket); this.editorState.clearAll("A new socket connected"); @@ -246,15 +244,10 @@ class BunDiagnosticsManager { }); } - private constructor( - context: vscode.ExtensionContext, - signal: UnixSignal | TCPSocketSignal, - oldVersionInspectURL: string, - ) { + private constructor(context: vscode.ExtensionContext, signal: UnixSignal | TCPSocketSignal) { this.editorState = new EditorStateManager(); this.signal = signal; this.context = context; - this.inspectUrl = oldVersionInspectURL; this.context.subscriptions.push( // on did type @@ -263,9 +256,7 @@ class BunDiagnosticsManager { }), ); - this.signal.on("Signal.received", () => { - this.handleSocketConnection(); - }); + this.signal.on("Signal.Socket.connect", this.handleSocketConnection.bind(this)); } } @@ -274,12 +265,12 @@ const description = new vscode.MarkdownString( ); export async function registerDiagnosticsSocket(context: vscode.ExtensionContext) { + context.environmentVariableCollection.clear(); context.environmentVariableCollection.description = description; const manager = await BunDiagnosticsManager.initialize(context); - context.environmentVariableCollection.replace("BUN_INSPECT_NOTIFY", manager.notifyUrl); - context.environmentVariableCollection.replace("BUN_INSPECT", `${manager.inspectUrl}?report=1?wait=1`); // Intentionally invalid query params + context.environmentVariableCollection.replace("BUN_INSPECT_CONNECT_TO", manager.signalUrl); context.subscriptions.push(manager); } diff --git a/packages/bun-vscode/src/global-state.ts b/packages/bun-vscode/src/global-state.ts index 87bda9659bb796..9ee8f170b5da1d 100644 --- a/packages/bun-vscode/src/global-state.ts +++ b/packages/bun-vscode/src/global-state.ts @@ -3,7 +3,7 @@ import { ExtensionContext } from "vscode"; export const GLOBAL_STATE_VERSION = 1; export type GlobalStateTypes = { - BUN_INSPECT_NOTIFY: + BUN_INSPECT_CONNECT_TO: | { type: "tcp"; port: number; diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 2dd1346042d6d9..7c0d15ab8d75b7 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -2005,21 +2005,16 @@ pub const VirtualMachine = struct { if (bun.getenvZ("HYPERFINE_RANDOMIZED_ENVIRONMENT_OFFSET") != null) { return; } - const notify = bun.getenvZ("BUN_INSPECT_NOTIFY") orelse ""; + const unix = bun.getenvZ("BUN_INSPECT") orelse ""; + const notify = bun.getenvZ("BUN_INSPECT_NOTIFY") orelse ""; + const connect_to = bun.getenvZ("BUN_INSPECT_CONNECT_TO") orelse ""; const set_breakpoint_on_first_line = unix.len > 0 and strings.endsWith(unix, "?break=1"); // If we should set a breakpoint on the first line - const wait_for_debugger = unix.len > 0 and strings.endsWith(unix, "?wait=1"); // If we should wait (either 30ms if report is passed, forever otherwise) for the debugger to connect - const report = unix.len > 0 and strings.includes(unix, "?report=1"); // If either `break=1` or `wait=1` are specified, passing this will make the wait be 30ms and act like it's reporting to clients like the VSCode extension - - // NOTE: - // It's possible (and likely!) that the unix url will end like `?report=1?wait=1`. - // This is done because we needed to support the BUN_INSPECT url in versions of bun before we introduced `report=1` mode. - // Report mode is used for the VSCode extension (and other clients), it just tells bun to timeout connecting quickly rather - // than waiting forever. + const wait_for_debugger = unix.len > 0 and strings.endsWith(unix, "?wait=1"); // If we should wait for the debugger to connect before starting the event loop const wait_for_connection: Debugger.Wait = switch (set_breakpoint_on_first_line or wait_for_debugger) { - true => if (report) .shortly else .forever, + true => if (notify.len > 0 or connect_to.len > 0) .shortly else .forever, false => .off, }; @@ -2040,6 +2035,16 @@ pub const VirtualMachine = struct { .set_breakpoint_on_first_line = set_breakpoint_on_first_line, .mode = .connect, }; + } else if (connect_to.len > 0) { + // This works in the vscode debug terminal because that relies on unix or notify being set, which they + // are in the debug terminal. This branch doesn't reach + this.debugger = Debugger{ + .path_or_port = null, + .from_environment_variable = connect_to, + .wait_for_connection = wait_for_connection, + .set_breakpoint_on_first_line = set_breakpoint_on_first_line, + .mode = .connect, + }; } }, .enable => {