@@ -41,6 +41,13 @@ def enable(debuggerGlobalObject = pm.eval("debuggerGlobal")):
4141 logger.apply(logger, args.map(makeDebuggeeValue))
4242 }
4343
44+ function printSource (frame, location) {
45+ const src = frame.script.source.text
46+ const line = src.split('\\ n').slice(location.lineNumber-1, location.lineNumber).join('\\ n')
47+ print(line)
48+ print(" ".repeat(location.columnNumber) + "^") // indicate column position
49+ }
50+
4451 function getCommandInputs () {
4552 const input = debuggerInput("(pmdb) > ") // blocking
4653 const [_, command, rest] = input.match(/\\ s*(\\ w+)?(?:\\ s+(.*))?/)
@@ -57,6 +64,31 @@ def enable(debuggerGlobalObject = pm.eval("debuggerGlobal")):
5764 blockingLoop: while (true) {
5865 const { command, rest } = getCommandInputs() // blocking
5966 switch (command) {
67+ case "b":
68+ case "break": {
69+ // Set breakpoint on specific line number
70+ const lineNum = Number(rest)
71+ if (!lineNum) {
72+ print(`"break <lineNumber>" command requires a valid line number argument.`)
73+ continue blockingLoop;
74+ }
75+
76+ // find the bytecode offset for possible breakpoint location
77+ const bp = frame.script.getPossibleBreakpoints({ line: lineNum })[0]
78+ if (!bp) {
79+ print(`No possible breakpoint location found on line ${lineNum}`)
80+ continue blockingLoop;
81+ }
82+
83+ // add handler
84+ frame.script.setBreakpoint(bp.offset, (frame) => enterDebuggerLoop(frame))
85+
86+ // print breakpoint info
87+ print(`Breakpoint set on line ${bp.lineNumber} column ${bp.columnNumber+1} in "${frame.script.url}" :`)
88+ printSource(frame, bp)
89+
90+ continue blockingLoop;
91+ }
6092 case "c":
6193 case "cont":
6294 // Continue execution until next breakpoint or `debugger` statement
@@ -76,10 +108,7 @@ def enable(debuggerGlobalObject = pm.eval("debuggerGlobal")):
76108 case "l":
77109 case "line": {
78110 // Print current line
79- const src = frame.script.source.text
80- const line = src.split('\\ n').slice(metadata.lineNumber-1, metadata.lineNumber).join('\\ n')
81- print(line)
82- print(" ".repeat(metadata.columnNumber) + "^") // indicate column position
111+ printSource(frame, metadata)
83112 continue blockingLoop;
84113 }
85114 case "p":
@@ -107,6 +136,7 @@ def enable(debuggerGlobalObject = pm.eval("debuggerGlobal")):
107136 // XXX: keep this in sync with the actual implementation
108137 print([
109138 "List of commands:",
139+ "• b <lineNumber>/break <lineNumber>: Set breakpoint on specific line",
110140 "• c/cont: Continue execution until next breakpoint or debugger statement",
111141 "• n/next: Step next",
112142 "• bt/backtrace: Print backtrace of current execution frame",
0 commit comments