Skip to content

Commit

Permalink
fix: Connect with 1 socket to new env var but still work with js debu…
Browse files Browse the repository at this point in the history
…g terminal (#15458)
  • Loading branch information
alii authored Nov 28, 2024
1 parent 6f8c595 commit 08222ed
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 44 deletions.
2 changes: 2 additions & 0 deletions packages/bun-vscode/src/features/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ async function injectDebugTerminal(terminal: vscode.Terminal): Promise<void> {
...env,
"BUN_INSPECT": `${adapter.url}?${query}`,
"BUN_INSPECT_NOTIFY": signal.url,
BUN_INSPECT_CONNECT_TO: "",
},
});

Expand Down Expand Up @@ -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"),
Expand Down
57 changes: 24 additions & 33 deletions packages/bun-vscode/src/features/diagnostics/diagnostics.ts
Original file line number Diff line number Diff line change
@@ -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");

Expand Down Expand Up @@ -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";

Expand All @@ -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,
});
Expand All @@ -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,
});
Expand All @@ -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");

Expand Down Expand Up @@ -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
Expand All @@ -263,9 +256,7 @@ class BunDiagnosticsManager {
}),
);

this.signal.on("Signal.received", () => {
this.handleSocketConnection();
});
this.signal.on("Signal.Socket.connect", this.handleSocketConnection.bind(this));
}
}

Expand All @@ -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);
}
2 changes: 1 addition & 1 deletion packages/bun-vscode/src/global-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 15 additions & 10 deletions src/bun.js/javascript.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand All @@ -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 => {
Expand Down

0 comments on commit 08222ed

Please sign in to comment.