cdpwave-debugging
Bilingual developer knowledge base with 1000+ code recipes, design patterns, architecture guides, and reusable documentation templates. Built with Astro, Tailwind CSS, and Pagefind.
Install / Use
npx skills add MathiasPaulenko/stack-practices-webInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Content & MediaSupported Platforms
Skill content
View source on GitHubname: CDPWave Debugging version: 1.0.0 author: Mathias Paulenko Echeverz description: "Advanced debugging with cdpwave. Breakpoints, step debugging, CPU profiling, heap snapshots, code coverage, DOM debugger." tags: [debugging, breakpoints, profiling, heap-snapshot] trigger: When the user asks about debugging with cdpwave, needs breakpoints or step debugging, wants CPU profiling, needs heap snapshots, wants code coverage, or needs DOM debugger.
CDPWave Debugging
Description
Advanced debugging with cdpwave — set breakpoints, step through JavaScript, capture CPU profiles, take heap snapshots, measure code coverage, and use the DOM debugger for event-level debugging.
When to Invoke
- Setting breakpoints and step debugging JavaScript
- Capturing and analyzing CPU profiles
- Taking heap snapshots for memory leak detection
- Measuring JS and CSS code coverage
- Setting DOM and event breakpoints
- Debugging JavaScript execution in automated tests
Prerequisites
pip install cdpwave- Chrome or Edge launched with
--remote-debugging-port=9222 - Basic familiarity with cdpwave (see
cdpwave-testingskill) - Python 3.11+ with
asyncio
Debugger Domain
The CDP Debugger domain provides full step-debugging capabilities over the DevTools Protocol.
Setting breakpoints
debug_set_breakpoint
Set a breakpoint by URL, function, or script:
import asyncio
from cdpwave import CDPSession
async def set_breakpoint():
session = await CDPSession.connect("ws://localhost:9222")
# Enable the Debugger domain
await session.Debugger.enable()
# Set breakpoint by URL and line number
result = await session.Debugger.set_breakpoint_by_url(
url="https://example.com/app.js",
line_number=42,
column_number=0
)
breakpoint_id = result["breakpointId"]
# Set breakpoint by function name
result = await session.Debugger.set_breakpoint_by_function(
function_name="handleClick"
)
# Set breakpoint by script ID and line
result = await session.Debugger.set_breakpoint(
location={
"scriptId": "script123",
"lineNumber": 10,
"columnNumber": 0
}
)
await session.close()
Conditional breakpoints
await session.Debugger.set_breakpoint_by_url(
url="https://example.com/app.js",
line_number=42,
condition="x > 100"
)
Logpoints (breakpoints that log without pausing)
await session.Debugger.set_breakpoint_by_url(
url="https://example.com/app.js",
line_number=42,
condition="console.log('hit line 42, x=', x); false"
)
Pausing and resuming
debug_pause
Pause JavaScript execution:
await session.Debugger.pause()
debug_resume
Resume execution after a pause:
await session.Debugger.resume()
Step debugging
| Method | Description |
|--------|-------------|
| Debugger.step_over | Step over the next function call |
| Debugger.step_into | Step into the next function call |
| Debugger.step_out | Step out of the current function |
| Debugger.resume | Resume execution until next breakpoint |
async def step_debug(session):
# Wait for pause event
paused = await session.Debugger.wait_for_pause()
print(f"Paused at: {paused['callFrames'][0]['url']}")
print(f"Line: {paused['callFrames'][0]['location']['lineNumber']}")
# Step over
await session.Debugger.step_over()
paused = await session.Debugger.wait_for_pause()
# Step into
await session.Debugger.step_into()
paused = await session.Debugger.wait_for_pause()
# Step out
await session.Debugger.step_out()
paused = await session.Debugger.wait_for_pause()
# Resume
await session.Debugger.resume()
Removing breakpoints
# Remove a specific breakpoint
await session.Debugger.remove_breakpoint(breakpoint_id=breakpoint_id)
# Remove all breakpoints
await session.Debugger.set_skip_all_breakpoints(skip=True)
Call frames and scope
When paused, inspect call frames and scope chains:
async def inspect_pause(session):
paused = await session.Debugger.wait_for_pause()
for frame in paused["callFrames"]:
print(f"Function: {frame['functionName']}")
print(f"URL: {frame['url']}")
print(f"Line: {frame['location']['lineNumber']}")
for scope in frame["scopeChain"]:
print(f" Scope: {scope['type']}") # global, local, closure, catch, block, script, with
obj = await session.Runtime.get_properties(
object_id=scope["object"]["objectId"],
own_properties=True
)
for prop in obj["result"]:
print(f" {prop['name']} = {prop.get('value', {}).get('value', 'N/A')}")
HeapProfiler Domain
Capture heap snapshots for memory leak detection and analysis.
Taking a heap snapshot
async def heap_snapshot(session):
await session.HeapProfiler.enable()
# Capture heap snapshot
snapshot_data = []
async for event in session.HeapProfiler.take_heap_snapshot():
snapshot_data.append(event)
# Save snapshot
with open("heap.heapsnapshot", "w") as f:
json.dump(snapshot_data, f)
Heap sampling
async def heap_sampling(session):
await session.HeapProfiler.enable()
# Start sampling
await session.HeapProfiler.start_sampling()
# ... run page interactions ...
# Stop sampling and get results
profile = await session.HeapProfiler.stop_sampling()
with open("heap-sampling.json", "w") as f:
json.dump(profile, f)
Tracking heap object allocations
async def track_allocations(session):
await session.HeapProfiler.enable()
# Start tracking
await session.HeapProfiler.start_tracking_heap_objects()
# ... run page interactions ...
# Stop tracking and get snapshot
await session.HeapProfiler.stop_tracking_heap_objects()
# Get tracked objects
objects = await session.HeapProfiler.get_heap_object_id()
Heap snapshot analysis
import json
def analyze_heap(snapshot_path):
with open(snapshot_path) as f:
snapshot = json.load(f)
nodes = snapshot["nodes"]
strings = snapshot["strings"]
# Count nodes by type
type_counts = {}
for i in range(0, len(nodes), 7):
type_idx = nodes[i]
type_name = strings[type_idx]
type_counts[type_name] = type_counts.get(type_name, 0) + 1
for type_name, count in sorted(type_counts.items(), key=lambda x: -x[1]):
print(f"{type_name}: {count}")
Profiler Domain
Capture CPU profiles to identify performance bottlenecks.
CPU profiling
async def cpu_profile(session):
await session.Profiler.enable()
# Start profiling
await session.Profiler.start()
# ... run page interactions ...
# Stop profiling and get profile
profile = await session.Profiler.stop()
with open("cpu-profile.json", "w") as f:
json.dump(profile, f)
Profiling with precision
async def precise_profile(session):
await session.Profiler.enable()
# Set sampling interval (default is 1000us = 1ms)
await session.Profiler.set_sampling_interval(interval=100) # 100us = 0.1ms
await session.Profiler.start()
# ... run interactions ...
profile = await session.Profiler.stop()
CPU profile analysis
import json
def analyze_cpu_profile(profile_path):
with open(profile_path) as f:
profile = json.load(f)
nodes = profile["profile"]["nodes"]
samples = profile["profile"]["samples"]
time_deltas = profile["profile"]["timeDeltas"]
# Find hot functions (most samples)
sample_counts = {}
for sample in samples:
sample_counts[sample] = sample_counts.get(sample, 0) + 1
# Map node IDs to function names
node_map = {n["id"]: n for n in nodes}
for node_id, count in sorted(sample_counts.items(), key=lambda x: -x[1])[:10]:
node = node_map[node_id]
func = node["callFrame"]["functionName"] or "(anonymous)"
url = node["callFrame"]["url"]
line = node["callFrame"]["lineNumber"]
print(f"{func} at {url}:{line} — {count} samples")
DOMDebugger Domain
Set breakpoints on DOM events and DOM modifications.
Event breakpoints
async def event_breakpoints(session):
await session.DOMDebugger.enable()
# Break on all click events
await session.DOMDebugger.set_event_breakpoint(
event_name="click"
)
# Break on XHR load
await session.DOMDebugger.set_event_breakpoint(
event_name="load",
target_name="XMLHttpRequest"
)
# Break on specific event
await session.DOMDebugger.set_event_breakpoint(
event_name="submit"
)
DOM breakpoints
async def dom_breakpoints(session):
await session.DOMDebugger.enable()
# Get a DOM node first
document = await session.DOM.get_document()
node_id = document["root"]["children"][1]["children"][0]["nodeId"]
# Break on subtree modification
await session.DOMDebugger.set_dom_breakpoint(
node_id=node_id,
type="subtree-modified" # subtree-modified, attribute-modified, node-removed
)
# Break on attribute modification
await session.DOMDebugger.set_dom_breakpoint(
node_id=node_id,
type="attribute-modified"
)
# Break on node removal
await session.DOMDebugger.set_dom_breakpoint(
node_id=node_id,
type="node-removed"
)
Removing DOM breakpoints
# Remove specific DOM breakpoint
await session.DOMDebugger.remove_dom_breakpoint(
node_id=node_id,
type="subtree-modified"
)
# Remove event breakpoint
await session.DOMDebugger.remove_event_breakpoint(
event_name="click"
)
Code Coverage
Measure JS and CSS code coverage to find unused code.
JS coverage
async def js_coverage(session):
await session.Profiler.enable()
await session.Profiler.start_precise_coverage(
call_count=True,
detailed=True
)
# ... run page interactions ...
# Get coverage results
result = await session.Profiler.take_precise_coverage()
for script in result["result"]:
url = script["url"]
functions = script["functions"]
for func in functions:
func_name = func["functionName"] or "(anonymous)"
for range in func["ranges"]:
start = range["startOffset"]
end = range["endOffset"]
count = range["count"]
if count == 0:
print(f"UNUSED: {func_name} in {url} [{start}:{end}]")
await session.Profiler.stop_precise_coverage()
CSS coverage
async def css_coverage(session):
await session.CSS.enable()
await session.CSS.start_rule_usage_tracking()
# ... run page interactions ...
# Get coverage results
result = await session.CSS.stop_rule_usage_tracking()
for rule in result["ruleUsage"]:
style_sheet_id = rule["styleSheetId"]
start = rule["startOffset"]
end = rule["endOffset"]
used = rule["used"]
if not used:
print(f"UNUSED CSS: sheet={style_sheet_id} [{start}:{end}]")
Combined Debug Session
A complete debug session combining breakpoints, profiling, and heap analysis:
import asyncio
import json
from cdpwave import CDPSession
async def debug_session():
session = await CDPSession.connect("ws://localhost:9222")
# Enable all required domains
await session.Debugger.enable()
await session.Profiler.enable()
await session.HeapProfiler.enable()
# Set breakpoint
bp = await session.Debugger.set_breakpoint_by_url(
url="https://example.com/app.js",
line_number=42,
con
Truncated for display — read the full file on GitHub.
Related Skills
momen-cursurrules-prompt-file
40.6kCursor rules for building custom frontends with Momen.app as headless BaaS with GraphQL API, actionflows, AI agents, and Stripe integration.
semiotic-react-dataviz-cursorrules-prompt-file
40.6kCursor rules for Semiotic data visualization library with 30+ chart types, MCP server, and AI-assisted chart generation.
siyuan
45.9kAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作
guizang-ppt-skill
24.5kAI-agent Skill for generating polished HTML slide decks: editorial magazine and Swiss layouts, image prompts, social covers, and a WebGL/low-power presentation runtime.
Security Score
Audited on Invalid Date
