aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/bun-debug-adapter-protocol/src/debugger/adapter.ts27
-rw-r--r--packages/bun-inspector-protocol/src/inspector/websocket.ts13
-rw-r--r--packages/bun-vscode/.gitignore1
-rw-r--r--packages/bun-vscode/example/example.test.ts4
-rw-r--r--packages/bun-vscode/src/features/debug.ts63
5 files changed, 79 insertions, 29 deletions
diff --git a/packages/bun-debug-adapter-protocol/src/debugger/adapter.ts b/packages/bun-debug-adapter-protocol/src/debugger/adapter.ts
index cd1b656a7..33555dbb0 100644
--- a/packages/bun-debug-adapter-protocol/src/debugger/adapter.ts
+++ b/packages/bun-debug-adapter-protocol/src/debugger/adapter.ts
@@ -109,7 +109,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
#initialized?: InitializeRequest;
#launched?: LaunchRequest;
#connected?: boolean;
- #terminated?: boolean;
constructor({ url, send, stdout, stderr, ...options }: DebugAdapterOptions) {
this.#url = new URL(url);
@@ -129,6 +128,10 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
this.#variables = [{ name: "", value: "", type: undefined, variablesReference: 0 }];
}
+ get inspector(): UnixWebSocketInspector {
+ return this.#inspector;
+ }
+
async accept(message: DAP.Request | DAP.Response | DAP.Event): Promise<void> {
const { type } = message;
@@ -414,7 +417,18 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
async #attach(request: AttachRequest): Promise<void> {
const { url } = request;
+ if (this.#url.href === url) {
+ this.#emit("output", {
+ category: "debug console",
+ output: "Debugger attached.\n",
+ });
+
+ this.configurationDone();
+ return;
+ }
+
if (await this.#start(url)) {
+ this.configurationDone();
return;
}
@@ -422,7 +436,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
}
terminate(): void {
- this.#terminated = true;
this.#process?.kill();
}
@@ -855,14 +868,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
output: "Debugger detached.\n",
});
- if (error && !this.#terminated) {
- const { message } = error;
- this.#emit("output", {
- category: "stderr",
- output: `${message}\n`,
- });
- }
-
this.#emit("terminated");
this.#reset();
}
@@ -1426,7 +1431,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
}
close(): void {
- this.#terminated = true;
this.#process?.kill();
this.#inspector.close();
this.#reset();
@@ -1444,7 +1448,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
this.#launched = undefined;
this.#initialized = undefined;
this.#connected = undefined;
- this.#terminated = undefined;
}
}
diff --git a/packages/bun-inspector-protocol/src/inspector/websocket.ts b/packages/bun-inspector-protocol/src/inspector/websocket.ts
index 4ba85df13..238d3b2b7 100644
--- a/packages/bun-inspector-protocol/src/inspector/websocket.ts
+++ b/packages/bun-inspector-protocol/src/inspector/websocket.ts
@@ -224,14 +224,19 @@ export class WebSocketInspector implements Inspector {
export class UnixWebSocketInspector extends WebSocketInspector {
#unix: string;
#server: Server;
- #ready: Promise<void>;
+ #ready: Promise<unknown>;
+ startDebugging?: () => void;
constructor(options: WebSocketInspectorOptions) {
super(options);
this.#unix = unixSocket();
this.#server = createServer();
this.#server.listen(this.#unix);
- this.#ready = this.#wait();
+ this.#ready = this.#wait().then(() => {
+ setTimeout(() => {
+ this.start().then(() => this.startDebugging?.());
+ }, 1);
+ });
}
get unix(): string {
@@ -240,16 +245,18 @@ export class UnixWebSocketInspector extends WebSocketInspector {
#wait(): Promise<void> {
return new Promise(resolve => {
+ console.log("waiting");
this.#server.once("connection", socket => {
+ console.log("received");
socket.once("data", resolve);
});
- setTimeout(resolve, 1000);
});
}
async start(url?: string | URL): Promise<boolean> {
await this.#ready;
try {
+ console.log("starting");
return await super.start(url);
} finally {
this.#ready = this.#wait();
diff --git a/packages/bun-vscode/.gitignore b/packages/bun-vscode/.gitignore
index 9db2648e4..cafc85cea 100644
--- a/packages/bun-vscode/.gitignore
+++ b/packages/bun-vscode/.gitignore
@@ -1,2 +1,3 @@
node_modules
extension
+example/.vscode
diff --git a/packages/bun-vscode/example/example.test.ts b/packages/bun-vscode/example/example.test.ts
index eb15eed39..a9da929eb 100644
--- a/packages/bun-vscode/example/example.test.ts
+++ b/packages/bun-vscode/example/example.test.ts
@@ -3,5 +3,9 @@ import { describe, test, expect } from "bun:test";
describe("example", () => {
test("it works", () => {
expect(1).toBe(1);
+ expect(1).not.toBe(2);
+ expect(() => {
+ throw new Error("error");
+ }).toThrow();
});
});
diff --git a/packages/bun-vscode/src/features/debug.ts b/packages/bun-vscode/src/features/debug.ts
index bbfadb62e..eae2b1c33 100644
--- a/packages/bun-vscode/src/features/debug.ts
+++ b/packages/bun-vscode/src/features/debug.ts
@@ -11,7 +11,7 @@ const debugConfiguration: vscode.DebugConfiguration = {
request: "launch",
name: "Debug Bun",
program: "${file}",
- watch: true,
+ watch: false,
};
const runConfiguration: vscode.DebugConfiguration = {
@@ -20,7 +20,7 @@ const runConfiguration: vscode.DebugConfiguration = {
name: "Run Bun",
program: "${file}",
debug: false,
- watch: true,
+ watch: false,
};
const attachConfiguration: vscode.DebugConfiguration = {
@@ -30,7 +30,8 @@ const attachConfiguration: vscode.DebugConfiguration = {
url: "ws://localhost:6499/",
};
-const channels: Record<string, vscode.OutputChannel> = {};
+let channels: Record<string, vscode.OutputChannel> = {};
+let terminal: TerminalDebugSession | undefined;
export default function (context: vscode.ExtensionContext, factory?: vscode.DebugAdapterDescriptorFactory) {
context.subscriptions.push(
@@ -50,10 +51,11 @@ export default function (context: vscode.ExtensionContext, factory?: vscode.Debu
(channels["dap"] = vscode.window.createOutputChannel("Debug Adapter Protocol (Bun)")),
(channels["jsc"] = vscode.window.createOutputChannel("JavaScript Inspector (Bun)")),
(channels["console"] = vscode.window.createOutputChannel("Console (Bun)")),
+ (terminal = new TerminalDebugSession()),
);
}
-function RunFileCommand(resource: vscode.Uri): void {
+function RunFileCommand(resource?: vscode.Uri): void {
const path = getCurrentPath(resource);
if (path) {
vscode.debug.startDebugging(undefined, {
@@ -64,7 +66,7 @@ function RunFileCommand(resource: vscode.Uri): void {
}
}
-function DebugFileCommand(resource: vscode.Uri): void {
+function DebugFileCommand(resource?: vscode.Uri): void {
const path = getCurrentPath(resource);
if (path) {
vscode.debug.startDebugging(undefined, {
@@ -105,19 +107,28 @@ class DebugConfigurationProvider implements vscode.DebugConfigurationProvider {
class InlineDebugAdapterFactory implements vscode.DebugAdapterDescriptorFactory {
createDebugAdapterDescriptor(session: vscode.DebugSession): ProviderResult<vscode.DebugAdapterDescriptor> {
- const adapter = new VSCodeAdapter(session);
+ const { configuration } = session;
+ const { request, url } = configuration;
+
+ if (request === "attach" && url === terminal?.url) {
+ return new vscode.DebugAdapterInlineImplementation(terminal);
+ }
+
+ const adapter = new FileDebugSession(session.id);
return new vscode.DebugAdapterInlineImplementation(adapter);
}
}
-export class VSCodeAdapter extends DebugSession {
- #adapter: DebugAdapter;
+class FileDebugSession extends DebugSession {
+ readonly url: string;
+ readonly adapter: DebugAdapter;
- constructor(session: vscode.DebugSession) {
+ constructor(sessionId?: string) {
super();
- const { id } = session;
- this.#adapter = new DebugAdapter({
- url: `ws+unix://${tmpdir()}/bun-vscode-${id}.sock`,
+ const uniqueId = sessionId ?? Math.random().toString(36).slice(2);
+ this.url = `ws+unix://${tmpdir()}/bun-vscode-${uniqueId}.sock`;
+ this.adapter = new DebugAdapter({
+ url: this.url,
send: this.sendMessage.bind(this),
logger(...messages) {
log("jsc", ...messages);
@@ -147,11 +158,35 @@ export class VSCodeAdapter extends DebugSession {
handleMessage(message: DAP.Event | DAP.Request | DAP.Response): void {
log("dap", "<--", message);
- this.#adapter.accept(message);
+ this.adapter.accept(message);
}
dispose() {
- this.#adapter.close();
+ this.adapter.close();
+ }
+}
+
+class TerminalDebugSession extends FileDebugSession {
+ readonly terminal: vscode.Terminal;
+
+ constructor() {
+ super();
+ this.terminal = vscode.window.createTerminal({
+ name: "Bun Terminal",
+ env: {
+ "BUN_INSPECT": `1${this.url}`,
+ "BUN_INSPECT_NOTIFY": `unix://${this.adapter.inspector.unix}`,
+ },
+ isTransient: true,
+ iconPath: new vscode.ThemeIcon("debug-console"),
+ });
+ this.terminal.show();
+ this.adapter.inspector.startDebugging = () => {
+ vscode.debug.startDebugging(undefined, {
+ ...attachConfiguration,
+ url: this.url,
+ });
+ };
}
}