From 2d215672712650729dc29ae55b4141c9bd9548ed Mon Sep 17 00:00:00 2001 From: Ashcon Partovi Date: Mon, 15 Jan 2024 17:00:29 -0800 Subject: [PATCH] Update debugger things (#8180) * T * Update Debug Adapter Protocol * Update JSC and V8 debugger protocols * Update inspector-frontend * Fix empty keys not being printed in `console.log` * Add `bun --inspect` tests and fix edge cases * bun install --exact --- .vscode/settings.json | 3 +- packages/bun-debug-adapter-protocol/bun.lockb | Bin 2323 -> 2323 bytes .../src/protocol/index.d.ts | 15 +- .../src/protocol/protocol.json | 12 +- .../{ => scripts}/build.ts | 4 +- .../src/protocol/jsc/index.d.ts | 4 + .../src/protocol/jsc/protocol.json | 9 +- .../src/protocol/v8/index.d.ts | 430 +++++++++++++-- .../src/protocol/v8/protocol.json | 502 ++++++++++++++++-- .../test/inspector/worker.js | 1 + src/bun.js/bindings/bindings.cpp | 4 - src/js/internal/debugger.ts | 44 +- test/bun.lockb | Bin 290701 -> 291026 bytes test/cli/inspect/inspect.test.ts | 259 +++++++++ test/cli/inspect/inspectee.js | 3 + test/cli/watch/watch.test.ts | 33 ++ test/harness.ts | 9 +- test/js/web/console/console-log.expected.txt | 3 + test/js/web/console/console-log.js | 2 + test/package.json | 1 + 20 files changed, 1234 insertions(+), 104 deletions(-) rename packages/bun-inspector-frontend/{ => scripts}/build.ts (96%) create mode 100644 packages/bun-inspector-protocol/test/inspector/worker.js create mode 100644 test/cli/inspect/inspect.test.ts create mode 100644 test/cli/inspect/inspectee.js create mode 100644 test/cli/watch/watch.test.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index d2b1a679c5..43a86eafe4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -226,5 +226,6 @@ "C_Cpp.errorSquiggles": "enabled", "eslint.workingDirectories": ["packages/bun-types"], "typescript.tsdk": "node_modules/typescript/lib", - "cmake.configureOnOpen": false + "cmake.configureOnOpen": false, + "git.ignoreLimitWarning": true } diff --git a/packages/bun-debug-adapter-protocol/bun.lockb b/packages/bun-debug-adapter-protocol/bun.lockb index 53d889ee4a4033f9a544b960f58945b6afce59a4..b63aa6d889cbfcf07318fe58c38935b67b1ed04d 100755 GIT binary patch delta 63 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

Wl=jobp~ZKgPVs#(ddv!qg^3Q3%BG` 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 { + inspectee = spawn({ + cwd: import.meta.dir, + cmd: [bunExe(), ...args, "inspectee.js"], + env: bunEnv, + stdout: "ignore", + stderr: "pipe", + }); + + let url: URL | undefined; + let stderr = ""; + const decoder = new TextDecoder(); + for await (const chunk of inspectee.stderr as ReadableStream) { + stderr += decoder.decode(chunk); + for (const line of stderr.split("\n")) { + try { + url = new URL(line); + } catch { + // Ignore + } + if (url?.protocol.includes("ws")) { + break; + } + } + if (stderr.includes("Listening:")) { + break; + } + } + + if (!url) { + process.stderr.write(stderr); + throw new Error("Unable to find listening URL"); + } + + const { protocol, hostname, port, pathname } = url; + expect({ + protocol, + hostname, + port, + pathname, + }).toMatchObject(expected); + + const webSocket = new WebSocket(url); + expect( + new Promise((resolve, reject) => { + webSocket.addEventListener("open", () => resolve()); + webSocket.addEventListener("error", cause => reject(new Error("WebSocket error", { cause }))); + webSocket.addEventListener("close", cause => reject(new Error("WebSocket closed", { cause }))); + }), + ).resolves.toBeUndefined(); + + webSocket.send(JSON.stringify({ id: 1, method: "Runtime.evaluate", params: { expression: "1 + 1" } })); + expect( + new Promise(resolve => { + webSocket.addEventListener("message", ({ data }) => { + resolve(JSON.parse(data.toString())); + }); + }), + ).resolves.toMatchObject({ + id: 1, + result: { + result: { + type: "number", + value: 2, + }, + }, + }); + + webSocket.close(); + }); +} + +afterEach(() => { + inspectee?.kill(); +}); diff --git a/test/cli/inspect/inspectee.js b/test/cli/inspect/inspectee.js new file mode 100644 index 0000000000..e2d1f60984 --- /dev/null +++ b/test/cli/inspect/inspectee.js @@ -0,0 +1,3 @@ +console.log("Hello"); + +setTimeout(() => {}, 30_000); diff --git a/test/cli/watch/watch.test.ts b/test/cli/watch/watch.test.ts new file mode 100644 index 0000000000..fc4d65a1da --- /dev/null +++ b/test/cli/watch/watch.test.ts @@ -0,0 +1,33 @@ +import { describe, test, expect, afterEach } from "bun:test"; +import type { Subprocess } from "bun"; +import { spawn } from "bun"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; +import { mkdtempSync, writeFileSync } from "node:fs"; +import { bunExe, bunEnv } from "harness"; + +let watchee: Subprocess; + +describe("bun --watch", () => { + const cwd = mkdtempSync(join(tmpdir(), "bun-test-")); + const path = join(cwd, "watchee.js"); + + const updateFile = (i: number) => { + writeFileSync(path, `console.log(${i});`); + }; + + test("should watch files", async () => { + watchee = spawn({ + cwd, + cmd: [bunExe(), "--watch", "watchee.js"], + env: bunEnv, + stdout: "inherit", + stderr: "inherit", + }); + await Bun.sleep(2000); + }); +}); + +afterEach(() => { + watchee?.kill(); +}); diff --git a/test/harness.ts b/test/harness.ts index 2e2c64eeaf..f3aae8154f 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -1,6 +1,7 @@ -import { gc as bunGC, stdout, unsafe, which } from "bun"; +import { gc as bunGC, unsafe, which } from "bun"; import { expect } from "bun:test"; -export const bunEnv: any = { + +export const bunEnv: NodeJS.ProcessEnv = { ...process.env, GITHUB_ACTIONS: "false", BUN_DEBUG_QUIET_LOGS: "1", @@ -174,6 +175,10 @@ export function fakeNodeRun(dir: string, file: string | string[], env?: Record