michael@0: const Cc = SpecialPowers.Cc; michael@0: const Ci = SpecialPowers.Ci; michael@0: const RETURN_CONTINUE = Ci.jsdIExecutionHook.RETURN_CONTINUE; michael@0: const DebuggerService = Cc["@mozilla.org/js/jsd/debugger-service;1"]; michael@0: michael@0: var jsd = Cc['@mozilla.org/js/jsd/debugger-service;1'] michael@0: .getService(Ci.jsdIDebuggerService); michael@0: var jsdOnAtStart = false; michael@0: michael@0: function setupJSD(test) { michael@0: netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); michael@0: jsdOnAtStart = jsd.isOn; michael@0: if (jsdOnAtStart) { michael@0: runTest(); michael@0: } else { michael@0: jsd.asyncOn({ onDebuggerActivated: function() { runTest(); } }); michael@0: } michael@0: } michael@0: michael@0: // Ugly workaround: when you turn the debugger on, it will only see scripts michael@0: // compiled after that point. And it may be turned on asynchronously. So michael@0: // we put the debugged code into a separate script that gets loaded after michael@0: // the debugger is on. michael@0: function loadScript(url, element) { michael@0: var script = document.createElement('script'); michael@0: script.type = 'text/javascript'; michael@0: script.src = url; michael@0: script.defer = false; michael@0: element.appendChild(script); michael@0: } michael@0: michael@0: function findScriptByFunction(name) { michael@0: var script; michael@0: jsd.enumerateScripts({ enumerateScript: michael@0: function(script_) { michael@0: if (script_.functionName === name) { michael@0: script = script_; michael@0: } michael@0: } michael@0: }); michael@0: michael@0: if (typeof(script) === "undefined") { michael@0: throw("Cannot find function named '" + name + "'"); michael@0: } michael@0: michael@0: return script; michael@0: } michael@0: michael@0: // Pass in a JSD script michael@0: function breakOnAllLines(script) { michael@0: // Map each line to a PC, and collect that set of PCs (removing michael@0: // duplicates.) michael@0: var pcs = {}; michael@0: for (i = 0; i < script.lineExtent; i++) { michael@0: var jsdLine = script.baseLineNumber + i; michael@0: var pc = script.lineToPc(jsdLine, Ci.jsdIScript.PCMAP_SOURCETEXT); michael@0: pcs[pc] = 1; michael@0: } michael@0: michael@0: // Set a breakpoint on each of those PCs. michael@0: for (pc in pcs) { michael@0: try { michael@0: script.setBreakpoint(pc); michael@0: } catch(e) { michael@0: alert("Error setting breakpoint: " + e); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // Set a breakpoint on a script, where lineno is relative to the beginning michael@0: // of the script (NOT the absolute line number within the file). michael@0: function breakOnLine(script, lineno) { michael@0: breakOnAbsoluteLine(script, script.baseLineNumber + lineno); michael@0: } michael@0: michael@0: function breakOnAbsoluteLine(script, lineno) { michael@0: var pc = script.lineToPc(lineno, Ci.jsdIScript.PCMAP_SOURCETEXT); michael@0: script.setBreakpoint(pc); michael@0: } michael@0: michael@0: function loadPage(page) { michael@0: var url; michael@0: if (page.match(/^\w+:/)) { michael@0: // Full URI, so just use it michael@0: url = page; michael@0: } else { michael@0: // Treat as relative to previous page michael@0: url = document.location.href.replace(/\/[^\/]*$/, "/" + page); michael@0: } michael@0: michael@0: dump("Switching to URL " + url + "\n"); michael@0: michael@0: gURLBar.value = url; michael@0: gURLBar.handleCommand(); michael@0: } michael@0: michael@0: function breakpointObserver(lines, interesting, callback) { michael@0: jsd.breakpointHook = { onExecute: function(frame, type, rv) { michael@0: breakpoints_hit.push(frame.line); michael@0: if (frame.line in interesting) { michael@0: return callback(frame, type, breakpoints_hit); michael@0: } else { michael@0: return RETURN_CONTINUE; michael@0: } michael@0: } }; michael@0: } michael@0: michael@0: function dumpStack(frame, msg) { michael@0: dump(msg + ":\n"); michael@0: while(frame) { michael@0: var callee = frame.callee; michael@0: if (callee !== null) michael@0: callee = callee.jsClassName; michael@0: dump(" " + frame.script.fileName + ":" + frame.line + " func=" + frame.script.functionName + " ffunc=" + frame.functionName + " callee=" + callee + " pc=" + frame.pc + "\n"); michael@0: frame = frame.callingFrame; michael@0: } michael@0: }