mirror of
https://github.com/oven-sh/bun
synced 2026-02-13 20:39:05 +00:00
More fixes for dap
This commit is contained in:
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
export type * from "./protocol";
|
||||
export * from "./debugger/adapter";
|
||||
export type * from "./src/protocol";
|
||||
export * from "./src/debugger/adapter";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "bun-debug-adapter-protocol",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"semver": "^7.5.4",
|
||||
"ws": "^8.13.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Protocol, Type } from "../protocol/schema.d.ts";
|
||||
import type { Protocol, Type } from "../src/protocol/schema";
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { spawnSync } from "node:child_process";
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type { DAP } from "..";
|
||||
// @ts-ignore: FIXME - there is something wrong with the types
|
||||
import type { JSC, InspectorListener } from "../../bun-inspector-protocol";
|
||||
import { WebSocketInspector } from "../../bun-inspector-protocol";
|
||||
import type { DAP } from "../protocol";
|
||||
// @ts-ignore
|
||||
import type { JSC, InspectorListener, WebSocketInspectorOptions } from "../../../bun-inspector-protocol";
|
||||
import { WebSocketInspector, remoteObjectToString } from "../../../bun-inspector-protocol/index";
|
||||
import type { ChildProcess } from "node:child_process";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import capabilities from "./capabilities";
|
||||
import { Location, SourceMap } from "./sourcemap";
|
||||
import { remoteObjectToString } from "./preview";
|
||||
import { compare, parse } from "semver";
|
||||
|
||||
type InitializeRequest = DAP.InitializeRequest & {
|
||||
@@ -71,23 +70,28 @@ type Variable = DAP.Variable & {
|
||||
};
|
||||
|
||||
type IDebugAdapter = {
|
||||
[E in keyof DAP.EventMap]?: (event: DAP.EventMap[E]) => void;
|
||||
[E in keyof DAP.EventMap]?: (event: DAP.EventMap[E]) => void | Promise<void>;
|
||||
} & {
|
||||
[R in keyof DAP.RequestMap]?: (
|
||||
request: DAP.RequestMap[R],
|
||||
) => void | DAP.ResponseMap[R] | Promise<void | DAP.ResponseMap[R]>;
|
||||
) => void | DAP.ResponseMap[R] | Promise<DAP.ResponseMap[R]> | Promise<void>;
|
||||
};
|
||||
|
||||
export type DebugAdapterOptions = {
|
||||
sendToAdapter(message: DAP.Request | DAP.Response | DAP.Event): Promise<void>;
|
||||
export type DebugAdapterOptions = WebSocketInspectorOptions & {
|
||||
send(message: DAP.Request | DAP.Response | DAP.Event): Promise<void>;
|
||||
stdout?(message: string): void;
|
||||
stderr?(message: string): void;
|
||||
};
|
||||
|
||||
// This adapter only support single-threaded debugging,
|
||||
// which means that there is only one thread at a time.
|
||||
const threadId = 1;
|
||||
|
||||
// @ts-ignore
|
||||
export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
#sendToAdapter: DebugAdapterOptions["sendToAdapter"];
|
||||
#sendToAdapter: DebugAdapterOptions["send"];
|
||||
#stdout?: DebugAdapterOptions["stdout"];
|
||||
#stderr?: DebugAdapterOptions["stderr"];
|
||||
#inspector: WebSocketInspector;
|
||||
#sourceId: number;
|
||||
#pendingSources: Map<string, ((source: Source) => void)[]>;
|
||||
@@ -105,9 +109,12 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
#terminated?: boolean;
|
||||
#url?: URL;
|
||||
|
||||
constructor({ sendToAdapter }: DebugAdapterOptions) {
|
||||
this.#inspector = new WebSocketInspector({ listener: this });
|
||||
this.#sendToAdapter = sendToAdapter;
|
||||
constructor({ send, stdout, stderr, ...options }: DebugAdapterOptions) {
|
||||
// @ts-ignore
|
||||
this.#inspector = new WebSocketInspector({ ...options, listener: this });
|
||||
this.#stdout = stdout;
|
||||
this.#stderr = stderr;
|
||||
this.#sendToAdapter = send;
|
||||
this.#sourceId = 1;
|
||||
this.#pendingSources = new Map();
|
||||
this.#sources = new Map();
|
||||
@@ -247,16 +254,27 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
throw new Error("Program must be a JavaScript or TypeScript file.");
|
||||
}
|
||||
|
||||
const argz = ["--inspect-wait=0", ...args];
|
||||
const finalArgs = ["--inspect-wait=0", ...args];
|
||||
if (watch) {
|
||||
argz.push(watch === "hot" ? "--hot" : "--watch");
|
||||
finalArgs.push(watch === "hot" ? "--hot" : "--watch");
|
||||
}
|
||||
console.log(argz);
|
||||
|
||||
const subprocess = spawn(runtime, [...argz, program], {
|
||||
const finalEnv = inheritEnv
|
||||
? {
|
||||
...process.env,
|
||||
...env,
|
||||
}
|
||||
: {
|
||||
...env,
|
||||
};
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/571
|
||||
finalEnv["NO_COLOR"] = "1";
|
||||
|
||||
const subprocess = spawn(runtime, [...finalArgs, program], {
|
||||
stdio: ["ignore", "pipe", "pipe", "pipe"],
|
||||
cwd,
|
||||
env: inheritEnv ? { ...process.env, ...env } : env,
|
||||
env: finalEnv,
|
||||
});
|
||||
|
||||
subprocess.on("spawn", () => {
|
||||
@@ -278,8 +296,10 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
|
||||
const stdout: string[] = [];
|
||||
subprocess.stdout!.on("data", data => {
|
||||
const text = data.toString();
|
||||
this.#stdout?.(text);
|
||||
|
||||
if (!this.#url) {
|
||||
const text = data.toString();
|
||||
stdout.push(text);
|
||||
const url = (this.#url = parseUrlMaybe(text));
|
||||
this.#inspector.start(url);
|
||||
@@ -290,8 +310,11 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
|
||||
const stderr: string[] = [];
|
||||
subprocess.stderr!.on("data", data => {
|
||||
const text = data.toString();
|
||||
this.#stderr?.(text);
|
||||
|
||||
if (!this.#url) {
|
||||
stderr.push(data.toString());
|
||||
stderr.push(text);
|
||||
} else if (stderr.length) {
|
||||
stderr.length = 0;
|
||||
}
|
||||
@@ -468,20 +491,20 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
if (!numberIsValid(line)) {
|
||||
return 0;
|
||||
}
|
||||
if (this.#initialized?.linesStartAt1) {
|
||||
return line - 1;
|
||||
if (!this.#initialized?.linesStartAt1) {
|
||||
return line;
|
||||
}
|
||||
return line;
|
||||
return line - 1;
|
||||
}
|
||||
|
||||
#columnTo0BasedColumn(column?: number): number {
|
||||
if (!numberIsValid(column)) {
|
||||
return 0;
|
||||
}
|
||||
if (this.#initialized?.columnsStartAt1) {
|
||||
return column - 1;
|
||||
if (!this.#initialized?.columnsStartAt1) {
|
||||
return column;
|
||||
}
|
||||
return column;
|
||||
return column - 1;
|
||||
}
|
||||
|
||||
#originalLocation(
|
||||
@@ -505,17 +528,17 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
}
|
||||
|
||||
#lineFrom0BasedLine(line?: number): number {
|
||||
if (this.#initialized?.linesStartAt1) {
|
||||
return numberIsValid(line) ? line + 1 : 1;
|
||||
if (!this.#initialized?.linesStartAt1) {
|
||||
return numberIsValid(line) ? line : 0;
|
||||
}
|
||||
return numberIsValid(line) ? line : 0;
|
||||
return numberIsValid(line) ? line + 1 : 1;
|
||||
}
|
||||
|
||||
#columnFrom0BasedColumn(column?: number): number {
|
||||
if (this.#initialized?.columnsStartAt1) {
|
||||
return numberIsValid(column) ? column + 1 : 1;
|
||||
if (!this.#initialized?.columnsStartAt1) {
|
||||
return numberIsValid(column) ? column : 0;
|
||||
}
|
||||
return numberIsValid(column) ? column : 0;
|
||||
return numberIsValid(column) ? column + 1 : 1;
|
||||
}
|
||||
|
||||
async setBreakpoints(request: DAP.SetBreakpointsRequest): Promise<DAP.SetBreakpointsResponse> {
|
||||
@@ -942,8 +965,7 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
|
||||
const variables = parameters.map((parameter, i) => {
|
||||
const variable = this.#addVariable(parameter, { name: `${i}` });
|
||||
|
||||
const { value } = variable;
|
||||
output += value + " ";
|
||||
output += remoteObjectToString(parameter, true) + " ";
|
||||
|
||||
return variable;
|
||||
});
|
||||
@@ -1681,8 +1703,6 @@ function consoleLevelToAnsiColor(level: JSC.Console.ConsoleMessage["level"]): st
|
||||
return "\u001b[33m";
|
||||
case "error":
|
||||
return "\u001b[31m";
|
||||
case "debug":
|
||||
return "\u001b[36m";
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { DAP } from "..";
|
||||
import type { DAP } from "../protocol";
|
||||
|
||||
const capabilities: DAP.Capabilities = {
|
||||
/**
|
||||
@@ -52,6 +52,7 @@ class ActualSourceMap implements SourceMap {
|
||||
|
||||
generatedLocation(request: LocationRequest): Location {
|
||||
const { line, column, url } = request;
|
||||
|
||||
let lineRange: LineRange;
|
||||
try {
|
||||
const source = this.#getSource(url);
|
||||
@@ -68,6 +69,7 @@ class ActualSourceMap implements SourceMap {
|
||||
message: unknownToError(error),
|
||||
};
|
||||
}
|
||||
|
||||
if (!locationIsValid(lineRange)) {
|
||||
return {
|
||||
line: lineToLine(line),
|
||||
@@ -75,6 +77,7 @@ class ActualSourceMap implements SourceMap {
|
||||
verified: false,
|
||||
};
|
||||
}
|
||||
|
||||
const { line: gline, column: gcolumn } = lineRange;
|
||||
return {
|
||||
line: lineToLine(gline),
|
||||
@@ -85,6 +88,7 @@ class ActualSourceMap implements SourceMap {
|
||||
|
||||
originalLocation(request: LocationRequest): Location {
|
||||
const { line, column } = request;
|
||||
|
||||
let mappedPosition: MappedPosition;
|
||||
try {
|
||||
mappedPosition = this.#sourceMap.originalPositionFor({
|
||||
@@ -99,6 +103,7 @@ class ActualSourceMap implements SourceMap {
|
||||
message: unknownToError(error),
|
||||
};
|
||||
}
|
||||
|
||||
if (!locationIsValid(mappedPosition)) {
|
||||
return {
|
||||
line: lineToLine(line),
|
||||
@@ -106,6 +111,7 @@ class ActualSourceMap implements SourceMap {
|
||||
verified: false,
|
||||
};
|
||||
}
|
||||
|
||||
const { line: oline, column: ocolumn } = mappedPosition;
|
||||
return {
|
||||
line: lineTo0BasedLine(oline),
|
||||
3761
packages/bun-debug-adapter-protocol/src/protocol/protocol.json
Normal file
3761
packages/bun-debug-adapter-protocol/src/protocol/protocol.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,7 @@
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"inlineSourceMap": true,
|
||||
"allowJs": true,
|
||||
"types": ["bun-types"],
|
||||
"outDir": "dist",
|
||||
},
|
||||
"include": [".", "../bun-types/index.d.ts", "../bun-inspector-protocol/index"]
|
||||
"include": ["src", "scripts", "../bun-types/index.d.ts", "../bun-inspector-protocol/src"]
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,3 +1,4 @@
|
||||
export type * from "./protocol";
|
||||
export type * from "./inspector";
|
||||
export * from "./inspector/websocket";
|
||||
export type * from "./src/protocol";
|
||||
export type * from "./src/inspector";
|
||||
export * from "./src/util/preview";
|
||||
export * from "./src/inspector/websocket";
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export default {
|
||||
fetch(request) {
|
||||
console.log(request);
|
||||
debugger;
|
||||
return new Response();
|
||||
},
|
||||
};
|
||||
@@ -1,83 +0,0 @@
|
||||
import { afterAll, beforeAll, mock, test, expect } from "bun:test";
|
||||
import type { JSC } from "..";
|
||||
import type { InspectorListener } from ".";
|
||||
import { WebSocketInspector } from "./websocket";
|
||||
import { sleep, spawn } from "bun";
|
||||
|
||||
let inspectee: any;
|
||||
let url: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const { pathname } = new URL("fixtures/inspectee.js", import.meta.url);
|
||||
inspectee = spawn({
|
||||
cmd: [process.argv0, "--inspect", pathname],
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
url = await new Promise(async resolve => {
|
||||
for await (const chunk of inspectee.stdout) {
|
||||
const text = new TextDecoder().decode(chunk);
|
||||
const match = /(wss?:\/\/.*:[0-9]+\/.*)/.exec(text);
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
const [_, url] = match;
|
||||
resolve(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
inspectee?.kill();
|
||||
});
|
||||
|
||||
test(
|
||||
"WebSocketInspector",
|
||||
async () => {
|
||||
const listener: InspectorListener = {
|
||||
["Inspector.connected"]: mock((...args) => {
|
||||
expect(args).toBeEmpty();
|
||||
}),
|
||||
["Inspector.disconnected"]: mock((error?: Error) => {
|
||||
expect(error).toBeUndefined();
|
||||
}),
|
||||
["Debugger.scriptParsed"]: mock((event: JSC.Debugger.ScriptParsedEvent) => {
|
||||
expect(event).toMatchObject({
|
||||
endColumn: expect.any(Number),
|
||||
endLine: expect.any(Number),
|
||||
isContentScript: expect.any(Boolean),
|
||||
module: expect.any(Boolean),
|
||||
scriptId: expect.any(String),
|
||||
startColumn: expect.any(Number),
|
||||
startLine: expect.any(Number),
|
||||
url: expect.any(String),
|
||||
});
|
||||
}),
|
||||
};
|
||||
const inspector = new WebSocketInspector({
|
||||
url,
|
||||
listener,
|
||||
});
|
||||
inspector.start();
|
||||
inspector.send("Runtime.enable");
|
||||
inspector.send("Debugger.enable");
|
||||
//expect(inspector.send("Runtime.enable")).resolves.toBeEmpty();
|
||||
//expect(inspector.send("Debugger.enable")).resolves.toBeEmpty();
|
||||
expect(inspector.send("Runtime.evaluate", { expression: "1 + 1" })).resolves.toMatchObject({
|
||||
result: {
|
||||
type: "number",
|
||||
value: 2,
|
||||
description: "2",
|
||||
},
|
||||
wasThrown: false,
|
||||
});
|
||||
expect(listener["Inspector.connected"]).toHaveBeenCalled();
|
||||
expect(listener["Debugger.scriptParsed"]).toHaveBeenCalled();
|
||||
inspector.close();
|
||||
expect(inspector.closed).toBeTrue();
|
||||
expect(listener["Inspector.disconnected"]).toHaveBeenCalled();
|
||||
},
|
||||
{
|
||||
timeout: 100000,
|
||||
},
|
||||
);
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Protocol, Domain, Property } from "../protocol/schema";
|
||||
import type { Protocol, Domain, Property } from "../src/protocol/schema";
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { spawnSync } from "node:child_process";
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { Inspector, InspectorListener } from ".";
|
||||
import { JSC } from "..";
|
||||
import type { JSC } from "../protocol";
|
||||
import { WebSocket } from "ws";
|
||||
|
||||
export type WebSocketInspectorOptions = {
|
||||
url?: string | URL;
|
||||
listener?: InspectorListener;
|
||||
logger?: (...messages: unknown[]) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -17,13 +18,15 @@ export class WebSocketInspector implements Inspector {
|
||||
#pendingRequests: Map<number, (result: unknown) => void>;
|
||||
#pendingMessages: string[];
|
||||
#listener: InspectorListener;
|
||||
#log: (...messages: unknown[]) => void;
|
||||
|
||||
constructor({ url, listener }: WebSocketInspectorOptions) {
|
||||
constructor({ url, listener, logger }: WebSocketInspectorOptions) {
|
||||
this.#url = url ? new URL(url) : undefined;
|
||||
this.#listener = listener ?? {};
|
||||
this.#requestId = 1;
|
||||
this.#pendingRequests = new Map();
|
||||
this.#pendingMessages = [];
|
||||
this.#listener = listener ?? {};
|
||||
this.#log = logger ?? (() => {});
|
||||
}
|
||||
|
||||
start(url?: string | URL): void {
|
||||
@@ -40,9 +43,10 @@ export class WebSocketInspector implements Inspector {
|
||||
return;
|
||||
}
|
||||
this.#webSocket?.close();
|
||||
|
||||
let webSocket: WebSocket;
|
||||
try {
|
||||
console.log("[jsc] connecting", this.#url.href);
|
||||
this.#log("connecting:", this.#url.href);
|
||||
webSocket = new WebSocket(this.#url, {
|
||||
headers: {
|
||||
"Ref-Event-Loop": "0",
|
||||
@@ -52,35 +56,44 @@ export class WebSocketInspector implements Inspector {
|
||||
this.#close(unknownToError(error));
|
||||
return;
|
||||
}
|
||||
|
||||
webSocket.addEventListener("open", () => {
|
||||
console.log("[jsc] connected");
|
||||
this.#log("connected");
|
||||
|
||||
for (const message of this.#pendingMessages) {
|
||||
this.#send(message);
|
||||
}
|
||||
|
||||
this.#pendingMessages.length = 0;
|
||||
this.#listener["Inspector.connected"]?.();
|
||||
});
|
||||
|
||||
webSocket.addEventListener("message", ({ data }) => {
|
||||
if (typeof data === "string") {
|
||||
this.accept(data);
|
||||
}
|
||||
});
|
||||
|
||||
webSocket.addEventListener("error", event => {
|
||||
console.log("[jsc] error", event);
|
||||
this.#log("error:", event);
|
||||
this.#close(unknownToError(event));
|
||||
});
|
||||
|
||||
webSocket.addEventListener("unexpected-response", () => {
|
||||
console.log("[jsc] unexpected-response");
|
||||
this.#log("unexpected-response");
|
||||
this.#close(new Error("WebSocket upgrade failed"));
|
||||
});
|
||||
|
||||
webSocket.addEventListener("close", ({ code, reason }) => {
|
||||
console.log("[jsc] closed", code, reason);
|
||||
this.#log("closed:", code, reason);
|
||||
|
||||
if (code === 1001) {
|
||||
this.#close();
|
||||
} else {
|
||||
this.#close(new Error(`WebSocket closed: ${code} ${reason}`.trimEnd()));
|
||||
}
|
||||
});
|
||||
|
||||
this.#webSocket = webSocket;
|
||||
}
|
||||
|
||||
@@ -90,7 +103,9 @@ export class WebSocketInspector implements Inspector {
|
||||
): Promise<JSC.ResponseMap[M]> {
|
||||
const id = this.#requestId++;
|
||||
const request = { id, method, params };
|
||||
console.log("[jsc] -->", request);
|
||||
|
||||
this.#log("-->", request);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const done = (result: any) => {
|
||||
this.#pendingRequests.delete(id);
|
||||
@@ -100,6 +115,7 @@ export class WebSocketInspector implements Inspector {
|
||||
resolve(result);
|
||||
}
|
||||
};
|
||||
|
||||
this.#pendingRequests.set(id, done);
|
||||
this.#send(JSON.stringify(request));
|
||||
});
|
||||
@@ -113,6 +129,7 @@ export class WebSocketInspector implements Inspector {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.#pendingMessages.includes(message)) {
|
||||
this.#pendingMessages.push(message);
|
||||
}
|
||||
@@ -123,35 +140,37 @@ export class WebSocketInspector implements Inspector {
|
||||
try {
|
||||
event = JSON.parse(message);
|
||||
} catch (error) {
|
||||
console.error("Failed to parse message:", message);
|
||||
this.#log("Failed to parse message:", message);
|
||||
return;
|
||||
}
|
||||
console.log("[jsc] <--", event);
|
||||
if ("id" in event) {
|
||||
const { id } = event;
|
||||
const resolve = this.#pendingRequests.get(id);
|
||||
if (!resolve) {
|
||||
console.error(`Failed to accept response for unknown ID ${id}:`, event);
|
||||
return;
|
||||
}
|
||||
this.#pendingRequests.delete(id);
|
||||
if ("error" in event) {
|
||||
const { error } = event;
|
||||
const { message } = error;
|
||||
resolve(new Error(message));
|
||||
} else {
|
||||
const { result } = event;
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
|
||||
this.#log("<--", event);
|
||||
|
||||
if (!("id" in event)) {
|
||||
const { method, params } = event;
|
||||
try {
|
||||
// @ts-ignore
|
||||
this.#listener[method]?.(params);
|
||||
this.#listener[method]?.(params as any);
|
||||
} catch (error) {
|
||||
console.error(`Failed to accept ${method} event:`, error);
|
||||
return;
|
||||
this.#log(`Failed to accept ${method} event:`, error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const { id } = event;
|
||||
const resolve = this.#pendingRequests.get(id);
|
||||
if (!resolve) {
|
||||
this.#log("Failed to accept response with unknown ID:", id);
|
||||
return;
|
||||
}
|
||||
|
||||
this.#pendingRequests.delete(id);
|
||||
if ("error" in event) {
|
||||
const { error } = event;
|
||||
const { message } = error;
|
||||
resolve(new Error(message));
|
||||
} else {
|
||||
const { result } = event;
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,12 +178,14 @@ export class WebSocketInspector implements Inspector {
|
||||
if (!this.#webSocket) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { readyState } = this.#webSocket;
|
||||
switch (readyState) {
|
||||
case WebSocket.CLOSED:
|
||||
case WebSocket.CLOSING:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
17428
packages/bun-inspector-protocol/src/protocol/v8/index.d.ts
vendored
Normal file
17428
packages/bun-inspector-protocol/src/protocol/v8/index.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
14136
packages/bun-inspector-protocol/src/protocol/v8/protocol.json
Normal file
14136
packages/bun-inspector-protocol/src/protocol/v8/protocol.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
import type { JSC } from "../../bun-inspector-protocol";
|
||||
import type { JSC } from "../protocol";
|
||||
|
||||
export function remoteObjectToString(remoteObject: JSC.Runtime.RemoteObject): string {
|
||||
export function remoteObjectToString(remoteObject: JSC.Runtime.RemoteObject, topLevel?: boolean): string {
|
||||
const { type, subtype, value, description, className, preview } = remoteObject;
|
||||
switch (type) {
|
||||
case "undefined":
|
||||
@@ -9,6 +9,9 @@ export function remoteObjectToString(remoteObject: JSC.Runtime.RemoteObject): st
|
||||
case "number":
|
||||
return description ?? JSON.stringify(value);
|
||||
case "string":
|
||||
if (topLevel) {
|
||||
return String(value ?? description);
|
||||
}
|
||||
return JSON.stringify(value ?? description);
|
||||
case "symbol":
|
||||
case "bigint":
|
||||
@@ -1,9 +1,8 @@
|
||||
import { beforeAll, afterAll, test, expect } from "bun:test";
|
||||
import type { JSC } from "../../bun-inspector-protocol";
|
||||
import { WebSocketInspector } from "../../bun-inspector-protocol";
|
||||
import type { PipedSubprocess } from "bun";
|
||||
import { spawn } from "bun";
|
||||
import { remoteObjectToString } from "./preview";
|
||||
import type { JSC } from "../..";
|
||||
import { WebSocketInspector, remoteObjectToString } from "../..";
|
||||
|
||||
let subprocess: PipedSubprocess | undefined;
|
||||
let objects: JSC.Runtime.RemoteObject[] = [];
|
||||
@@ -11,7 +10,7 @@ let objects: JSC.Runtime.RemoteObject[] = [];
|
||||
beforeAll(async () => {
|
||||
subprocess = spawn({
|
||||
cwd: import.meta.dir,
|
||||
cmd: [process.argv0, "--inspect-wait=0", "fixtures/preview.js"],
|
||||
cmd: [process.argv0, "--inspect-wait=0", "preview.js"],
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
stdin: "pipe",
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext"],
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "nodenext",
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"moduleDetection": "force",
|
||||
"strict": true,
|
||||
"downlevelIteration": true,
|
||||
@@ -13,7 +13,6 @@
|
||||
"inlineSourceMap": true,
|
||||
"allowJs": true,
|
||||
"outDir": "dist",
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [".", "../bun-types/index.d.ts"]
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug Bun",
|
||||
"program": "${file}",
|
||||
"watch": "hot"
|
||||
"watch": true
|
||||
},
|
||||
{
|
||||
"type": "bun",
|
||||
|
||||
@@ -4,7 +4,7 @@ export default {
|
||||
const coolThing: CoolThing = new SuperCoolThing();
|
||||
coolThing.doCoolThing();
|
||||
debugger;
|
||||
return new Response("HELLO WORLD");
|
||||
return new Response("HELLO WHAT!");
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -115,13 +115,27 @@ function isJavaScript(languageId: string): boolean {
|
||||
|
||||
export class VSCodeAdapter extends DebugSession {
|
||||
#adapter: DebugAdapter;
|
||||
#console: vscode.OutputChannel;
|
||||
#dap: vscode.OutputChannel;
|
||||
#jsc: vscode.OutputChannel;
|
||||
|
||||
constructor(session: vscode.DebugSession) {
|
||||
super();
|
||||
this.#dap = vscode.window.createOutputChannel("Debug Adapter Protocol");
|
||||
const output = (this.#console = vscode.window.createOutputChannel("Console (Bun)"));
|
||||
this.#dap = vscode.window.createOutputChannel("Debug Adapter Protocol (Bun)");
|
||||
const jsc = (this.#jsc = vscode.window.createOutputChannel("JavaScript Inspector (Bun)"));
|
||||
this.#adapter = new DebugAdapter({
|
||||
sendToAdapter: this.sendMessage.bind(this),
|
||||
send: this.sendMessage.bind(this),
|
||||
logger(...messages) {
|
||||
console.log("[jsc]", ...messages);
|
||||
jsc.appendLine(messages.map(v => (typeof v === "object" ? JSON.stringify(v) : v)).join(" "));
|
||||
},
|
||||
stdout(message) {
|
||||
output.append(message);
|
||||
},
|
||||
stderr(message) {
|
||||
output.append(message);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,6 +162,8 @@ export class VSCodeAdapter extends DebugSession {
|
||||
|
||||
dispose() {
|
||||
this.#adapter.close();
|
||||
this.#console.dispose();
|
||||
this.#dap.dispose();
|
||||
this.#jsc.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user