|
1 const Cc = SpecialPowers.Cc; |
|
2 const Ci = SpecialPowers.Ci; |
|
3 const RETURN_CONTINUE = Ci.jsdIExecutionHook.RETURN_CONTINUE; |
|
4 const DebuggerService = Cc["@mozilla.org/js/jsd/debugger-service;1"]; |
|
5 |
|
6 var jsd = Cc['@mozilla.org/js/jsd/debugger-service;1'] |
|
7 .getService(Ci.jsdIDebuggerService); |
|
8 var jsdOnAtStart = false; |
|
9 |
|
10 function setupJSD(test) { |
|
11 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); |
|
12 jsdOnAtStart = jsd.isOn; |
|
13 if (jsdOnAtStart) { |
|
14 runTest(); |
|
15 } else { |
|
16 jsd.asyncOn({ onDebuggerActivated: function() { runTest(); } }); |
|
17 } |
|
18 } |
|
19 |
|
20 // Ugly workaround: when you turn the debugger on, it will only see scripts |
|
21 // compiled after that point. And it may be turned on asynchronously. So |
|
22 // we put the debugged code into a separate script that gets loaded after |
|
23 // the debugger is on. |
|
24 function loadScript(url, element) { |
|
25 var script = document.createElement('script'); |
|
26 script.type = 'text/javascript'; |
|
27 script.src = url; |
|
28 script.defer = false; |
|
29 element.appendChild(script); |
|
30 } |
|
31 |
|
32 function findScriptByFunction(name) { |
|
33 var script; |
|
34 jsd.enumerateScripts({ enumerateScript: |
|
35 function(script_) { |
|
36 if (script_.functionName === name) { |
|
37 script = script_; |
|
38 } |
|
39 } |
|
40 }); |
|
41 |
|
42 if (typeof(script) === "undefined") { |
|
43 throw("Cannot find function named '" + name + "'"); |
|
44 } |
|
45 |
|
46 return script; |
|
47 } |
|
48 |
|
49 // Pass in a JSD script |
|
50 function breakOnAllLines(script) { |
|
51 // Map each line to a PC, and collect that set of PCs (removing |
|
52 // duplicates.) |
|
53 var pcs = {}; |
|
54 for (i = 0; i < script.lineExtent; i++) { |
|
55 var jsdLine = script.baseLineNumber + i; |
|
56 var pc = script.lineToPc(jsdLine, Ci.jsdIScript.PCMAP_SOURCETEXT); |
|
57 pcs[pc] = 1; |
|
58 } |
|
59 |
|
60 // Set a breakpoint on each of those PCs. |
|
61 for (pc in pcs) { |
|
62 try { |
|
63 script.setBreakpoint(pc); |
|
64 } catch(e) { |
|
65 alert("Error setting breakpoint: " + e); |
|
66 } |
|
67 } |
|
68 } |
|
69 |
|
70 // Set a breakpoint on a script, where lineno is relative to the beginning |
|
71 // of the script (NOT the absolute line number within the file). |
|
72 function breakOnLine(script, lineno) { |
|
73 breakOnAbsoluteLine(script, script.baseLineNumber + lineno); |
|
74 } |
|
75 |
|
76 function breakOnAbsoluteLine(script, lineno) { |
|
77 var pc = script.lineToPc(lineno, Ci.jsdIScript.PCMAP_SOURCETEXT); |
|
78 script.setBreakpoint(pc); |
|
79 } |
|
80 |
|
81 function loadPage(page) { |
|
82 var url; |
|
83 if (page.match(/^\w+:/)) { |
|
84 // Full URI, so just use it |
|
85 url = page; |
|
86 } else { |
|
87 // Treat as relative to previous page |
|
88 url = document.location.href.replace(/\/[^\/]*$/, "/" + page); |
|
89 } |
|
90 |
|
91 dump("Switching to URL " + url + "\n"); |
|
92 |
|
93 gURLBar.value = url; |
|
94 gURLBar.handleCommand(); |
|
95 } |
|
96 |
|
97 function breakpointObserver(lines, interesting, callback) { |
|
98 jsd.breakpointHook = { onExecute: function(frame, type, rv) { |
|
99 breakpoints_hit.push(frame.line); |
|
100 if (frame.line in interesting) { |
|
101 return callback(frame, type, breakpoints_hit); |
|
102 } else { |
|
103 return RETURN_CONTINUE; |
|
104 } |
|
105 } }; |
|
106 } |
|
107 |
|
108 function dumpStack(frame, msg) { |
|
109 dump(msg + ":\n"); |
|
110 while(frame) { |
|
111 var callee = frame.callee; |
|
112 if (callee !== null) |
|
113 callee = callee.jsClassName; |
|
114 dump(" " + frame.script.fileName + ":" + frame.line + " func=" + frame.script.functionName + " ffunc=" + frame.functionName + " callee=" + callee + " pc=" + frame.pc + "\n"); |
|
115 frame = frame.callingFrame; |
|
116 } |
|
117 } |