Debugger Domain
The Debugger domain provides methods for JavaScript debugging including breakpoints, stepping, and inspecting execution state.
Import
const cdp = @import("cdp");
const Debugger = cdp.Debugger;Initialization
var session = try browser.newPage();
var debugger_domain = Debugger.init(session);
_ = try debugger_domain.enable();Methods
enable
Enable the debugger domain. Returns the debugger protocol version.
pub fn enable(self: *Debugger) !i64Example:
var dbg = cdp.Debugger.init(session);
const version = try dbg.enable();
std.debug.print("Debugger version: {}\n", .{version});disable
Disable the debugger domain.
pub fn disable(self: *Debugger) !voidpause
Pause JavaScript execution immediately.
pub fn pause(self: *Debugger) !voidresume
Resume JavaScript execution after being paused.
pub fn @"resume"(self: *Debugger) !voidTIP
The method is named @"resume" because resume is a reserved keyword in Zig.
stepOver
Step over the next statement (doesn't enter function calls).
pub fn stepOver(self: *Debugger) !voidstepInto
Step into a function call.
pub fn stepInto(self: *Debugger) !voidstepOut
Step out of the current function.
pub fn stepOut(self: *Debugger) !voidsetBreakpointByUrl
Set a breakpoint by URL. Can match multiple scripts.
pub fn setBreakpointByUrl(
self: *Debugger,
allocator: Allocator,
line_number: i64,
url: ?[]const u8,
url_regex: ?[]const u8,
script_hash: ?[]const u8,
column_number: ?i64,
condition: ?[]const u8,
) !BreakpointResultParameters:
| Parameter | Description |
|---|---|
line_number | Line number (0-based internally, but typically 1-based in source) |
url | Script URL to match |
url_regex | Regex pattern to match URLs |
script_hash | Script content hash |
column_number | Column number for the breakpoint |
condition | JavaScript expression - breakpoint only triggers when true |
Returns:
pub const BreakpointResult = struct {
breakpoint_id: []const u8,
locations: []Location,
};Example:
var dbg = cdp.Debugger.init(session);
_ = try dbg.enable();
const result = try dbg.setBreakpointByUrl(
allocator,
10, // line 10
"http://localhost:9000/app.js", // url
null, // url_regex
null, // script_hash
null, // column_number
"count > 5", // condition
);
defer {
allocator.free(result.breakpoint_id);
for (result.locations) |*loc| loc.deinit(allocator);
allocator.free(result.locations);
}
std.debug.print("Breakpoint ID: {s}\n", .{result.breakpoint_id});setBreakpoint
Set a breakpoint at a specific location (requires script ID).
pub fn setBreakpoint(
self: *Debugger,
allocator: Allocator,
location: Location,
condition: ?[]const u8,
) !struct { breakpoint_id: BreakpointId, actual_location: Location }removeBreakpoint
Remove a breakpoint by its ID.
pub fn removeBreakpoint(self: *Debugger, breakpoint_id: []const u8) !voidExample:
try dbg.removeBreakpoint("1:10:0:http://localhost:9000/app.js");setPauseOnExceptions
Configure when to pause on exceptions.
pub fn setPauseOnExceptions(self: *Debugger, state: PauseOnExceptionsState) !voidExample:
var dbg = cdp.Debugger.init(session);
_ = try dbg.enable();
try dbg.setPauseOnExceptions(.uncaught);getScriptSource
Get the source code of a script by its ID.
pub fn getScriptSource(
self: *Debugger,
allocator: Allocator,
script_id: []const u8,
) ![]const u8setBreakpointsActive
Enable or disable all breakpoints globally.
pub fn setBreakpointsActive(self: *Debugger, active: bool) !voidcontinueToLocation
Continue execution until reaching a specific location.
pub fn continueToLocation(
self: *Debugger,
location: Location,
target_call_frames: ?[]const u8,
) !voidsetAsyncCallStackDepth
Set the depth of async call stacks to capture.
pub fn setAsyncCallStackDepth(self: *Debugger, max_depth: i64) !voidsetBlackboxPatterns
Set URL patterns for scripts to skip during debugging.
pub fn setBlackboxPatterns(self: *Debugger, patterns: []const []const u8) !voidExample:
// Skip node_modules and vendor scripts
try dbg.setBlackboxPatterns(&.{
".*node_modules.*",
".*vendor.*",
});Types
Location
pub const Location = struct {
script_id: []const u8,
line_number: i64,
column_number: ?i64 = null,
pub fn deinit(self: *Location, allocator: Allocator) void;
};PauseOnExceptionsState
pub const PauseOnExceptionsState = enum {
none, // Don't pause on exceptions
uncaught, // Pause on uncaught exceptions only
all, // Pause on all exceptions
};PausedReason
pub const PausedReason = enum {
ambiguous,
assert,
csp_violation,
debug_command,
dom,
event_listener,
exception,
instrumentation,
oom,
other,
promise_rejection,
xhr,
step,
};ScopeType
pub const ScopeType = enum {
global,
local,
with,
closure,
catch_scope,
block,
script,
eval,
module,
wasm_expression_stack,
};Events
The debugger domain emits these events (received via CDP event handling):
| Event | Description |
|---|---|
paused | Execution paused (breakpoint, exception, etc.) |
resumed | Execution resumed |
scriptParsed | A script was parsed |
breakpointResolved | A breakpoint was resolved to a location |
Complete Example
const std = @import("std");
const cdp = @import("cdp");
pub fn debugSession(session: *cdp.Session, allocator: std.mem.Allocator) !void {
var dbg = cdp.Debugger.init(session);
// Enable the debugger
_ = try dbg.enable();
// Pause on uncaught exceptions
try dbg.setPauseOnExceptions(.uncaught);
// Set a conditional breakpoint
const bp = try dbg.setBreakpointByUrl(
allocator,
25, // line number
"http://localhost:9000/app.js", // url
null, null, null, // url_regex, script_hash, column
"user.isAdmin", // condition
);
defer {
allocator.free(bp.breakpoint_id);
for (bp.locations) |*loc| loc.deinit(allocator);
allocator.free(bp.locations);
}
std.debug.print("Breakpoint set: {s}\n", .{bp.breakpoint_id});
// Skip vendor scripts
try dbg.setBlackboxPatterns(&.{".*vendor.*", ".*jquery.*"});
// When paused, step through code
// (In practice, you'd wait for paused event)
try dbg.stepOver();
try dbg.stepOver();
try dbg.@"resume"();
// Clean up
try dbg.removeBreakpoint(bp.breakpoint_id);
try dbg.disable();
}