simpler debugger class

This commit is contained in:
Tommy D. Rossi
2025-12-25 21:23:09 +01:00
parent ccffd9477d
commit aed319be9e
2 changed files with 3 additions and 117 deletions
+2 -116
View File
@@ -7,12 +7,6 @@ export interface BreakpointInfo {
line: number line: number
} }
export interface ConsoleEntry {
type: string
message: string
timestamp: number
}
export interface LocationInfo { export interface LocationInfo {
url: string url: string
lineNumber: number lineNumber: number
@@ -28,7 +22,6 @@ export interface LocationInfo {
export interface EvaluateResult { export interface EvaluateResult {
value: unknown value: unknown
consoleOutput: string[]
} }
export interface VariablesResult { export interface VariablesResult {
@@ -62,7 +55,6 @@ export class Debugger {
private paused = false private paused = false
private currentCallFrames: Protocol.Debugger.CallFrame[] = [] private currentCallFrames: Protocol.Debugger.CallFrame[] = []
private breakpoints = new Map<string, BreakpointInfo>() private breakpoints = new Map<string, BreakpointInfo>()
private consoleOutput: ConsoleEntry[] = []
private scripts = new Map<string, ScriptInfo>() private scripts = new Map<string, ScriptInfo>()
/** /**
@@ -101,33 +93,6 @@ export class Debugger {
}) })
} }
}) })
this.cdp.on('Runtime.consoleAPICalled', (params) => {
const message = params.args
.map((arg) => {
if (arg.type === 'string' || arg.type === 'number' || arg.type === 'boolean') {
return String(arg.value)
}
if (arg.type === 'object') {
if (arg.value) {
return JSON.stringify(arg.value, null, 2)
}
return arg.description || `[${arg.subtype || arg.type}]`
}
return JSON.stringify(arg)
})
.join(' ')
this.consoleOutput.push({
type: params.type,
message,
timestamp: Date.now(),
})
if (this.consoleOutput.length > 100) {
this.consoleOutput.shift()
}
})
} }
/** /**
@@ -149,57 +114,6 @@ export class Debugger {
this.debuggerEnabled = true this.debuggerEnabled = true
} }
/**
* Executes JavaScript code in the debugged process.
* Code is wrapped in try-catch and promises are awaited.
*
* @param options - Execution options
* @param options.code - JavaScript code to execute
* @returns The result value and any console output generated
*
* @example
* ```ts
* const result = await dbg.executeCode({ code: 'Object.keys(require.cache).length' })
* console.log(result.value) // 42
* console.log(result.consoleOutput) // ['[log] some message']
* ```
*/
async executeCode({ code }: { code: string }): Promise<EvaluateResult> {
await this.enable()
const consoleStartIndex = this.consoleOutput.length
const wrappedCode = `
try {
${code}
} catch (e) {
e;
}
`
const response = await this.cdp.send('Runtime.evaluate', {
expression: wrappedCode,
objectGroup: 'console',
includeCommandLineAPI: true,
silent: false,
returnByValue: true,
generatePreview: true,
awaitPromise: true,
})
await new Promise((resolve) => {
setTimeout(resolve, 200)
})
const consoleOutputs = this.consoleOutput.slice(consoleStartIndex)
const value = await this.processRemoteObject(response.result)
return {
value,
consoleOutput: consoleOutputs.map((o) => `[${o.type}] ${o.message}`),
}
}
/** /**
* Sets a breakpoint at a specified file and line number. * Sets a breakpoint at a specified file and line number.
* The file path is automatically converted to a file:// URL if needed. * The file path is automatically converted to a file:// URL if needed.
@@ -345,7 +259,7 @@ export class Debugger {
* *
* @param options - Options * @param options - Options
* @param options.expression - JavaScript expression to evaluate * @param options.expression - JavaScript expression to evaluate
* @returns The result value and any console output generated * @returns The result value
* *
* @example * @example
* ```ts * ```ts
@@ -360,8 +274,6 @@ export class Debugger {
async evaluate({ expression }: { expression: string }): Promise<EvaluateResult> { async evaluate({ expression }: { expression: string }): Promise<EvaluateResult> {
await this.enable() await this.enable()
const consoleStartIndex = this.consoleOutput.length
const wrappedExpression = ` const wrappedExpression = `
try { try {
${expression} ${expression}
@@ -395,17 +307,9 @@ export class Debugger {
}) })
} }
await new Promise((resolve) => {
setTimeout(resolve, 200)
})
const consoleOutputs = this.consoleOutput.slice(consoleStartIndex)
const value = await this.processRemoteObject(response.result) const value = await this.processRemoteObject(response.result)
return { return { value }
value,
consoleOutput: consoleOutputs.map((o) => `[${o.type}] ${o.message}`),
}
} }
/** /**
@@ -547,24 +451,6 @@ export class Debugger {
await this.cdp.send('Debugger.resume') await this.cdp.send('Debugger.resume')
} }
/**
* Gets the most recent console output captured from the debugged process.
* Console output is captured automatically via Runtime.consoleAPICalled events.
*
* @param options - Options
* @param options.limit - Maximum number of entries to return (default: 20)
* @returns Array of console entries with type, message, and timestamp
*
* @example
* ```ts
* const logs = dbg.getConsoleOutput({ limit: 10 })
* // [{ type: 'log', message: 'Hello world', timestamp: 1234567890 }]
* ```
*/
getConsoleOutput({ limit = 20 }: { limit?: number } = {}): ConsoleEntry[] {
return this.consoleOutput.slice(-limit)
}
/** /**
* Returns whether the debugger is currently paused at a breakpoint. * Returns whether the debugger is currently paused at a breakpoint.
* *
+1 -1
View File
@@ -97,7 +97,7 @@ you have access to some functions in addition to playwright methods:
- Example: `const cdp = await getCDPSession({ page }); const metrics = await cdp.send('Page.getLayoutMetrics');` - Example: `const cdp = await getCDPSession({ page }); const metrics = await cdp.send('Page.getLayoutMetrics');`
- `createDebugger({ cdp })`: creates a Debugger instance for setting breakpoints, stepping, and inspecting variables. Works with browser JS or Node.js (--inspect). - `createDebugger({ cdp })`: creates a Debugger instance for setting breakpoints, stepping, and inspecting variables. Works with browser JS or Node.js (--inspect).
- `cdp`: a CDPSession from `getCDPSession` - `cdp`: a CDPSession from `getCDPSession`
- Methods: `enable()`, `setBreakpoint({ file, line })`, `deleteBreakpoint({ breakpointId })`, `listBreakpoints()`, `listScripts({ search? })`, `evaluate({ expression })`, `executeCode({ code })`, `inspectVariables({ scope? })`, `getLocation()`, `stepOver()`, `stepInto()`, `stepOut()`, `resume()`, `getConsoleOutput({ limit? })`, `isPaused()` - Methods: `enable()`, `setBreakpoint({ file, line })`, `deleteBreakpoint({ breakpointId })`, `listBreakpoints()`, `listScripts({ search? })`, `evaluate({ expression })`, `inspectVariables({ scope? })`, `getLocation()`, `stepOver()`, `stepInto()`, `stepOut()`, `resume()`, `isPaused()`
- Example: - Example:
```js ```js
const cdp = await getCDPSession({ page }); const dbg = createDebugger({ cdp }); await dbg.enable(); const cdp = await getCDPSession({ page }); const dbg = createDebugger({ cdp }); await dbg.enable();