More improvements to debugger support (#4345)

* More fixes for dap

* More changes

* More changes 2

* More fixes

* Fix debugger.ts

* Bun Terminal
This commit is contained in:
Ashcon Partovi
2023-08-26 02:34:25 -07:00
committed by GitHub
parent 910daeff27
commit 2a9e967fd1
60 changed files with 36014 additions and 552 deletions

View File

@@ -1,143 +0,0 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
exports[`remoteObjectToString 1`] = `"undefined"`;
exports[`remoteObjectToString 2`] = `"null"`;
exports[`remoteObjectToString 3`] = `"true"`;
exports[`remoteObjectToString 4`] = `"false"`;
exports[`remoteObjectToString 5`] = `"0"`;
exports[`remoteObjectToString 6`] = `"1"`;
exports[`remoteObjectToString 7`] = `"3.141592653589793"`;
exports[`remoteObjectToString 8`] = `"-2.718281828459045"`;
exports[`remoteObjectToString 9`] = `"NaN"`;
exports[`remoteObjectToString 10`] = `"Infinity"`;
exports[`remoteObjectToString 11`] = `"-Infinity"`;
exports[`remoteObjectToString 12`] = `"0n"`;
exports[`remoteObjectToString 13`] = `"1n"`;
exports[`remoteObjectToString 14`] = `"10000000000000n"`;
exports[`remoteObjectToString 15`] = `"-10000000000000n"`;
exports[`remoteObjectToString 16`] = `""""`;
exports[`remoteObjectToString 17`] = `"" ""`;
exports[`remoteObjectToString 18`] = `""Hello""`;
exports[`remoteObjectToString 19`] = `""Hello World""`;
exports[`remoteObjectToString 20`] = `"Array(0)"`;
exports[`remoteObjectToString 21`] = `"Array(3) [1, 2, 3]"`;
exports[`remoteObjectToString 22`] = `"Array(4) ["a", 1, null, undefined]"`;
exports[`remoteObjectToString 23`] = `"Array(2) [1, Array]"`;
exports[`remoteObjectToString 24`] = `"Array(1) [Array]"`;
exports[`remoteObjectToString 25`] = `"{}"`;
exports[`remoteObjectToString 26`] = `"{a: 1}"`;
exports[`remoteObjectToString 27`] = `"{a: 1, b: 2, c: 3}"`;
exports[`remoteObjectToString 28`] = `"{a: Object}"`;
exports[`remoteObjectToString 29`] = `
"ƒ() {
}"
`;
exports[`remoteObjectToString 30`] = `
"ƒ namedFunction() {
}"
`;
exports[`remoteObjectToString 31`] = `
"class {
}"
`;
exports[`remoteObjectToString 32`] = `
"class namedClass {
}"
`;
exports[`remoteObjectToString 33`] = `
"class namedClass {
a() {
}
b = 1;
c = [
null,
undefined,
"a",
{
a: 1,
b: 2,
c: 3
}
];
}"
`;
exports[`remoteObjectToString 34`] = `"Wed Dec 31 1969 16:00:00 GMT-0800 (Pacific Standard Time)"`;
exports[`remoteObjectToString 35`] = `"Invalid Date"`;
exports[`remoteObjectToString 36`] = `"/(?:)/"`;
exports[`remoteObjectToString 37`] = `"/abc/"`;
exports[`remoteObjectToString 38`] = `"/abc/g"`;
exports[`remoteObjectToString 39`] = `"/abc/"`;
exports[`remoteObjectToString 40`] = `"Set(0)"`;
exports[`remoteObjectToString 41`] = `"Set(3) [1, 2, 3]"`;
exports[`remoteObjectToString 42`] = `"WeakSet(0)"`;
exports[`remoteObjectToString 43`] = `"WeakSet(3) [{a: 1}, {b: 2}, {c: 3}]"`;
exports[`remoteObjectToString 44`] = `"Map(0)"`;
exports[`remoteObjectToString 45`] = `"Map(3) {"a" => 1, "b" => 2, "c" => 3}"`;
exports[`remoteObjectToString 46`] = `"WeakMap(0)"`;
exports[`remoteObjectToString 47`] = `"WeakMap(3) {{a: 1} => 1, {b: 2} => 2, {c: 3} => 3}"`;
exports[`remoteObjectToString 48`] = `"Symbol()"`;
exports[`remoteObjectToString 49`] = `"Symbol(namedSymbol)"`;
exports[`remoteObjectToString 50`] = `"Error"`;
exports[`remoteObjectToString 51`] = `"TypeError: This is a TypeError"`;
exports[`remoteObjectToString 52`] = `"Headers {append: ƒ, delete: ƒ, get: ƒ, getAll: ƒ, has: ƒ, …}"`;
exports[`remoteObjectToString 53`] = `"Headers {a: "1", append: ƒ, b: "2", delete: ƒ, get: ƒ, …}"`;
exports[`remoteObjectToString 54`] = `"Request {arrayBuffer: ƒ, blob: ƒ, body: null, bodyUsed: false, cache: "default", …}"`;
exports[`remoteObjectToString 55`] = `"Request {arrayBuffer: ƒ, blob: ƒ, body: ReadableStream, bodyUsed: false, cache: "default", …}"`;
exports[`remoteObjectToString 56`] = `"Response {arrayBuffer: ƒ, blob: ƒ, body: null, bodyUsed: false, clone: ƒ, …}"`;
exports[`remoteObjectToString 57`] = `"Response {arrayBuffer: ƒ, blob: ƒ, body: ReadableStream, bodyUsed: false, clone: ƒ, …}"`;

View File

@@ -1,99 +0,0 @@
console.log(
undefined,
null,
true,
false,
0,
1,
Math.PI,
-Math.E,
NaN,
Infinity,
-Infinity,
BigInt(0),
BigInt(1),
BigInt("10000000000000"),
BigInt("-10000000000000"),
"",
" ",
"Hello",
"Hello World",
[],
[1, 2, 3],
["a", 1, null, undefined],
[1, [2, [3, [4, [5, [6, [7, [8, [9, [10]]]]]]]]]],
[[[[[]]]]],
{},
{ a: 1 },
{ a: 1, b: 2, c: 3 },
{ a: { b: { c: { d: { e: { f: { g: { h: { i: { j: 10 } } } } } } } } } },
function () {},
function namedFunction() {},
class {},
class namedClass {},
class namedClass {
a() {}
b = 1;
c = [
null,
undefined,
"a",
{
a: 1,
b: 2,
c: 3,
},
];
},
new Date(0),
new Date(NaN),
new RegExp(),
new RegExp("abc"),
new RegExp("abc", "g"),
/abc/,
new Set(),
new Set([1, 2, 3]),
new WeakSet(),
new WeakSet([{ a: 1 }, { b: 2 }, { c: 3 }]),
new Map(),
new Map([
["a", 1],
["b", 2],
["c", 3],
]),
new WeakMap(),
new WeakMap([
[{ a: 1 }, 1],
[{ b: 2 }, 2],
[{ c: 3 }, 3],
]),
Symbol(),
Symbol("namedSymbol"),
new Error(),
new TypeError("This is a TypeError"),
//"a".repeat(10000),
//["a"].fill("a", 0, 10000),
new Headers(),
new Headers({
a: "1",
b: "2",
}),
new Request("https://example.com/"),
new Request("https://example.com/", {
method: "POST",
headers: {
a: "1",
b: "2",
},
body: '{"example":true}',
}),
new Response(),
new Response('{"example":true}', {
status: 200,
statusText: "OK",
headers: {
a: "1",
b: "2",
},
}),
);

View File

@@ -1,62 +0,0 @@
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";
let subprocess: PipedSubprocess | undefined;
let objects: JSC.Runtime.RemoteObject[] = [];
beforeAll(async () => {
subprocess = spawn({
cwd: import.meta.dir,
cmd: [process.argv0, "--inspect-wait=0", "fixtures/preview.js"],
stdout: "pipe",
stderr: "pipe",
stdin: "pipe",
});
const decoder = new TextDecoder();
let url: URL;
for await (const chunk of subprocess!.stdout) {
const text = decoder.decode(chunk);
if (text.includes("ws://")) {
url = new URL(/(ws:\/\/.*)/.exec(text)![0]);
break;
}
}
objects = await new Promise((resolve, reject) => {
const inspector = new WebSocketInspector({
url,
listener: {
["Inspector.connected"]: () => {
inspector.send("Inspector.enable");
inspector.send("Runtime.enable");
inspector.send("Console.enable");
inspector.send("Debugger.enable");
inspector.send("Debugger.resume");
inspector.send("Inspector.initialized");
},
["Inspector.disconnected"]: error => {
reject(error);
},
["Console.messageAdded"]: ({ message }) => {
const { parameters } = message;
resolve(parameters!);
inspector.close();
},
},
});
inspector.start();
});
});
afterAll(() => {
subprocess?.kill();
});
test("remoteObjectToString", () => {
for (const object of objects) {
expect(remoteObjectToString(object)).toMatchSnapshot();
}
});

View File

@@ -1,110 +0,0 @@
import type { JSC } from "../../bun-inspector-protocol";
export function remoteObjectToString(remoteObject: JSC.Runtime.RemoteObject): string {
const { type, subtype, value, description, className, preview } = remoteObject;
switch (type) {
case "undefined":
return "undefined";
case "boolean":
case "number":
return description ?? JSON.stringify(value);
case "string":
return JSON.stringify(value ?? description);
case "symbol":
case "bigint":
return description!;
case "function":
return description!.replace("function", "ƒ") || "ƒ";
}
switch (subtype) {
case "null":
return "null";
case "regexp":
case "date":
case "error":
return description!;
}
if (preview) {
return objectPreviewToString(preview);
}
if (className) {
return className;
}
return description || "Object";
}
export function objectPreviewToString(objectPreview: JSC.Runtime.ObjectPreview): string {
const { type, subtype, entries, properties, overflow, description, size } = objectPreview;
if (type !== "object") {
return remoteObjectToString(objectPreview);
}
let items: string[];
if (entries) {
items = entries.map(entryPreviewToString).sort();
} else if (properties) {
if (isIndexed(subtype)) {
items = properties.map(indexedPropertyPreviewToString).sort();
} else {
items = properties.map(namedPropertyPreviewToString).sort();
}
} else {
items = ["…"];
}
if (overflow) {
items.push("…");
}
let label: string;
if (description === "Object") {
label = "";
} else if (size === undefined) {
label = description!;
} else {
label = `${description}(${size})`;
}
if (!items.length) {
return label || "{}";
}
if (label) {
label += " ";
}
if (isIndexed(subtype)) {
return `${label}[${items.join(", ")}]`;
}
return `${label}{${items.join(", ")}}`;
}
function propertyPreviewToString(propertyPreview: JSC.Runtime.PropertyPreview): string {
const { type, value, ...preview } = propertyPreview;
if (type === "accessor") {
return "ƒ";
}
return remoteObjectToString({ ...preview, type, description: value });
}
function entryPreviewToString(entryPreview: JSC.Runtime.EntryPreview): string {
const { key, value } = entryPreview;
if (key) {
return `${objectPreviewToString(key)} => ${objectPreviewToString(value)}`;
}
return objectPreviewToString(value);
}
function namedPropertyPreviewToString(propertyPreview: JSC.Runtime.PropertyPreview): string {
const { name, valuePreview } = propertyPreview;
if (valuePreview) {
return `${name}: ${objectPreviewToString(valuePreview)}`;
}
return `${name}: ${propertyPreviewToString(propertyPreview)}`;
}
function indexedPropertyPreviewToString(propertyPreview: JSC.Runtime.PropertyPreview): string {
const { valuePreview } = propertyPreview;
if (valuePreview) {
return objectPreviewToString(valuePreview);
}
return propertyPreviewToString(propertyPreview);
}
function isIndexed(type?: JSC.Runtime.RemoteObject["subtype"]): boolean {
return type === "array" || type === "set" || type === "weakset";
}

View File

@@ -1,2 +1,2 @@
export type * from "./protocol";
export * from "./debugger/adapter";
export type * from "./src/protocol";
export * from "./src/debugger/adapter";

View File

@@ -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"
}
}

View File

@@ -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";

View File

@@ -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 { UnixWebSocketInspector, 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 & {
@@ -21,6 +20,7 @@ type LaunchRequest = DAP.LaunchRequest & {
env?: Record<string, string>;
inheritEnv?: boolean;
watch?: boolean | "hot";
debug?: boolean;
};
type AttachRequest = DAP.AttachRequest & {
@@ -71,24 +71,31 @@ 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 & {
url: string | URL;
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"];
#inspector: WebSocketInspector;
#url: URL;
#sendToAdapter: DebugAdapterOptions["send"];
#stdout?: DebugAdapterOptions["stdout"];
#stderr?: DebugAdapterOptions["stderr"];
#inspector: UnixWebSocketInspector;
#sourceId: number;
#pendingSources: Map<string, ((source: Source) => void)[]>;
#sources: Map<string | number, Source>;
@@ -102,12 +109,14 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
#initialized?: InitializeRequest;
#launched?: LaunchRequest;
#connected?: boolean;
#terminated?: boolean;
#url?: URL;
constructor({ sendToAdapter }: DebugAdapterOptions) {
this.#inspector = new WebSocketInspector({ listener: this });
this.#sendToAdapter = sendToAdapter;
constructor({ url, send, stdout, stderr, ...options }: DebugAdapterOptions) {
this.#url = new URL(url);
// @ts-ignore
this.#inspector = new UnixWebSocketInspector({ ...options, url, listener: this });
this.#stdout = stdout;
this.#stderr = stderr;
this.#sendToAdapter = send;
this.#sourceId = 1;
this.#pendingSources = new Map();
this.#sources = new Map();
@@ -119,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;
@@ -140,7 +153,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
}
response = await this[command as keyof this](args);
} catch (error) {
console.error(error);
const { message } = unknownToError(error);
return this.#sendToAdapter({
type: "response",
@@ -238,7 +250,7 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
throw new Error("Another program is already running. Did you terminate the last session?");
}
const { program, runtime = "bun", args = [], cwd, env = {}, inheritEnv = true, watch = true } = request;
const { program, runtime = "bun", args = [], cwd, env = {}, inheritEnv = true, watch = false } = request;
if (!program) {
throw new Error("No program specified. Did you set the 'program' property in your launch.json?");
}
@@ -247,16 +259,39 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
throw new Error("Program must be a JavaScript or TypeScript file.");
}
const argz = ["--inspect-wait=0", ...args];
if (watch) {
argz.push(watch === "hot" ? "--hot" : "--watch");
const finalArgs = [...args];
const isTest = isTestJavaScript(program);
if (isTest) {
finalArgs.unshift("test");
}
console.log(argz);
const subprocess = spawn(runtime, [...argz, program], {
stdio: ["ignore", "pipe", "pipe", "pipe"],
if (watch) {
finalArgs.push(watch === "hot" ? "--hot" : "--watch");
}
const finalEnv = inheritEnv
? {
...process.env,
...env,
}
: {
...env,
};
finalEnv["BUN_INSPECT"] = `1${this.#url}`;
finalEnv["BUN_INSPECT_NOTIFY"] = `unix://${this.#inspector.unix}`;
if (isTest) {
finalEnv["FORCE_COLOR"] = "1";
} else {
// https://github.com/microsoft/vscode/issues/571
finalEnv["NO_COLOR"] = "1";
}
const subprocess = spawn(runtime, [...finalArgs, program], {
stdio: ["ignore", "pipe", "pipe"],
cwd,
env: inheritEnv ? { ...process.env, ...env } : env,
env: finalEnv,
});
subprocess.on("spawn", () => {
@@ -269,31 +304,40 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
});
});
subprocess.on("exit", code => {
subprocess.on("exit", (code, signal) => {
this.#emit("exited", {
exitCode: code ?? -1,
});
this.#process = undefined;
});
const stdout: string[] = [];
subprocess.stdout!.on("data", data => {
if (!this.#url) {
const text = data.toString();
stdout.push(text);
const url = (this.#url = parseUrlMaybe(text));
this.#inspector.start(url);
} else if (stdout.length) {
stdout.length = 0;
const text = data.toString();
this.#stdout?.(text);
if (isTest) {
this.#emit("output", {
category: "stdout",
output: text,
source: {
path: program,
},
});
}
});
const stderr: string[] = [];
subprocess.stderr!.on("data", data => {
if (!this.#url) {
stderr.push(data.toString());
} else if (stderr.length) {
stderr.length = 0;
const text = data.toString();
this.#stderr?.(text);
if (isTest) {
this.#emit("output", {
category: "stdout", // Not stderr, since VSCode will highlight it as red.
output: text,
source: {
path: program,
},
});
}
});
@@ -317,11 +361,7 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
throw new Error(`Program exited with code ${reason} before the debugger could attached.`);
}
for (let retries = 0; !this.#url && retries < 10; retries++) {
await new Promise(resolve => setTimeout(resolve, 100 * retries));
}
if (this.#url) {
if (await this.#start()) {
return;
}
@@ -334,42 +374,68 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
const { stdout: version } = spawnSync(runtime, ["--version"], { stdio: "pipe", encoding: "utf-8" });
if (parse(version, true) && compare("0.8.0", version, true)) {
throw new Error(
`Bun v${version.trim()} does not have debugger support. Please upgrade to v0.8 or later by running: \`bun upgrade\``,
);
}
for (const message of stderr) {
this.#emit("output", {
category: "stderr",
output: message,
source: {
path: program,
},
});
}
for (const message of stdout) {
this.#emit("output", {
category: "stdout",
output: message,
source: {
path: program,
},
});
const minVersion = "0.8.2";
if (parse(version, true) && compare(minVersion, version, true)) {
throw new Error(`This extension requires Bun v${minVersion} or later. Please upgrade by running: bun upgrade`);
}
throw new Error("Program started, but the debugger could not be attached.");
}
attach(request: AttachRequest): void {
async #start(url?: string | URL): Promise<boolean> {
if (url) {
this.#url = new URL(url);
}
for (let i = 0; i < 5; i++) {
const ok = await this.#inspector.start(url);
if (ok) {
return true;
}
await new Promise(resolve => setTimeout(resolve, 100 * i));
}
return false;
}
async attach(request: DAP.AttachRequest): Promise<void> {
try {
await this.#attach(request);
} catch (error) {
// Some clients, like VSCode, will show a system-level popup when a `launch` request fails.
// Instead, we want to show the error as a sidebar notification.
const { message } = unknownToError(error);
this.#emit("output", {
category: "stderr",
output: `Failed to start debugger.\n${message}`,
});
this.#emit("terminated");
}
}
async #attach(request: AttachRequest): Promise<void> {
const { url } = request;
this.#inspector.start(parseUrl(url));
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;
}
throw new Error("Failed to attach to program.");
}
terminate(): void {
this.#terminated = true;
this.#process?.kill();
}
@@ -468,20 +534,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 +571,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> {
@@ -788,9 +854,12 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
this.#emit("initialized");
}
["Inspector.disconnected"](error?: Error): void {
if (this.#connected && this.#process?.exitCode === null) {
this.#url = undefined;
async ["Inspector.disconnected"](error?: Error): Promise<void> {
if (this.#connected && this.#process?.exitCode === null && (await this.#start())) {
return;
}
if (!this.#connected) {
return;
}
@@ -799,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();
}
@@ -942,8 +1003,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;
});
@@ -1371,7 +1431,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
}
close(): void {
this.#terminated = true;
this.#process?.kill();
this.#inspector.close();
this.#reset();
@@ -1389,8 +1448,6 @@ export class DebugAdapter implements IDebugAdapter, InspectorListener {
this.#launched = undefined;
this.#initialized = undefined;
this.#connected = undefined;
this.#terminated = undefined;
this.#url = undefined;
}
}
@@ -1598,6 +1655,10 @@ function isJavaScript(path: string): boolean {
return /\.(c|m)?(j|t)sx?$/.test(path);
}
function isTestJavaScript(path: string): boolean {
return /\.(test|spec)\.(c|m)?(j|t)sx?$/.test(path);
}
function parseUrl(hostname?: string, port?: number): URL {
hostname ||= "localhost";
port ||= 6499;
@@ -1681,8 +1742,6 @@ function consoleLevelToAnsiColor(level: JSC.Console.ConsoleMessage["level"]): st
return "\u001b[33m";
case "error":
return "\u001b[31m";
case "debug":
return "\u001b[36m";
}
return undefined;
}

View File

@@ -1,4 +1,4 @@
import type { DAP } from "..";
import type { DAP } from "../protocol";
const capabilities: DAP.Capabilities = {
/**

View File

@@ -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),

File diff suppressed because it is too large Load Diff

View File

@@ -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"]
}