OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 "use strict"; | 5 "use strict"; |
6 | 6 |
7 // If true, prints all messages sent and received by inspector. | 7 // If true, prints all messages sent and received by inspector. |
8 const printProtocolMessages = false; | 8 const printProtocolMessages = false; |
9 | 9 |
10 // The active wrapper instance. | 10 // The active wrapper instance. |
(...skipping 27 matching lines...) Expand all Loading... |
38 AsyncTaskEvent: 7 | 38 AsyncTaskEvent: 7 |
39 }; | 39 }; |
40 | 40 |
41 // The different types of steps. | 41 // The different types of steps. |
42 this.StepAction = { StepOut: 0, | 42 this.StepAction = { StepOut: 0, |
43 StepNext: 1, | 43 StepNext: 1, |
44 StepIn: 2, | 44 StepIn: 2, |
45 StepFrame: 3, | 45 StepFrame: 3, |
46 }; | 46 }; |
47 | 47 |
| 48 // The different types of scripts matching enum ScriptType in objects.h. |
| 49 this.ScriptType = { Native: 0, |
| 50 Extension: 1, |
| 51 Normal: 2, |
| 52 Wasm: 3}; |
| 53 |
48 // A copy of the scope types from runtime-debug.cc. | 54 // A copy of the scope types from runtime-debug.cc. |
49 // NOTE: these constants should be backward-compatible, so | 55 // NOTE: these constants should be backward-compatible, so |
50 // add new ones to the end of this list. | 56 // add new ones to the end of this list. |
51 this.ScopeType = { Global: 0, | 57 this.ScopeType = { Global: 0, |
52 Local: 1, | 58 Local: 1, |
53 With: 2, | 59 With: 2, |
54 Closure: 3, | 60 Closure: 3, |
55 Catch: 4, | 61 Catch: 4, |
56 Block: 5, | 62 Block: 5, |
57 Script: 6, | 63 Script: 6, |
(...skipping 13 matching lines...) Expand all Loading... |
71 }; | 77 }; |
72 | 78 |
73 // The different script break point types. | 79 // The different script break point types. |
74 this.ScriptBreakPointType = { ScriptId: 0, | 80 this.ScriptBreakPointType = { ScriptId: 0, |
75 ScriptName: 1, | 81 ScriptName: 1, |
76 ScriptRegExp: 2 }; | 82 ScriptRegExp: 2 }; |
77 | 83 |
78 // Store the current script id so we can skip corresponding break events. | 84 // Store the current script id so we can skip corresponding break events. |
79 this.thisScriptId = %FunctionGetScriptId(receive); | 85 this.thisScriptId = %FunctionGetScriptId(receive); |
80 | 86 |
| 87 // Stores all set breakpoints. |
| 88 this.breakpoints = new Set(); |
| 89 |
81 // Register as the active wrapper. | 90 // Register as the active wrapper. |
82 assertTrue(activeWrapper === undefined); | 91 assertTrue(activeWrapper === undefined); |
83 activeWrapper = this; | 92 activeWrapper = this; |
84 } | 93 } |
85 | 94 |
86 enable() { this.sendMessageForMethodChecked("Debugger.enable"); } | 95 enable() { this.sendMessageForMethodChecked("Debugger.enable"); } |
87 disable() { this.sendMessageForMethodChecked("Debugger.disable"); } | 96 disable() { this.sendMessageForMethodChecked("Debugger.disable"); } |
88 | 97 |
89 setListener(listener) { this.listener = listener; } | 98 setListener(listener) { this.listener = listener; } |
90 | 99 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 setBreakPoint(func, opt_line, opt_column, opt_condition) { | 138 setBreakPoint(func, opt_line, opt_column, opt_condition) { |
130 assertTrue(%IsFunction(func)); | 139 assertTrue(%IsFunction(func)); |
131 assertFalse(%FunctionIsAPIFunction(func)); | 140 assertFalse(%FunctionIsAPIFunction(func)); |
132 | 141 |
133 const scriptid = %FunctionGetScriptId(func); | 142 const scriptid = %FunctionGetScriptId(func); |
134 assertTrue(scriptid != -1); | 143 assertTrue(scriptid != -1); |
135 | 144 |
136 const offset = %FunctionGetScriptSourcePosition(func); | 145 const offset = %FunctionGetScriptSourcePosition(func); |
137 const loc = | 146 const loc = |
138 %ScriptLocationFromLine2(scriptid, opt_line, opt_column, offset); | 147 %ScriptLocationFromLine2(scriptid, opt_line, opt_column, offset); |
139 | 148 return this.setBreakPointAtLocation(scriptid, loc, opt_condition); |
140 const params = { location : | |
141 { scriptId : scriptid.toString(), | |
142 lineNumber : loc.line, | |
143 columnNumber : loc.column, | |
144 }}; | |
145 if (!!opt_condition) { | |
146 params.condition = opt_condition; | |
147 } | |
148 | |
149 const {msgid, msg} = this.createMessage("Debugger.setBreakpoint", params); | |
150 this.sendMessage(msg); | |
151 | |
152 const reply = this.takeReplyChecked(msgid); | |
153 assertTrue(reply.result !== undefined); | |
154 const breakid = reply.result.breakpointId; | |
155 assertTrue(breakid !== undefined); | |
156 | |
157 return breakid; | |
158 } | 149 } |
159 | 150 |
160 setScriptBreakPoint(type, scriptid, opt_line, opt_column, opt_condition) { | 151 setScriptBreakPoint(type, scriptid, opt_line, opt_column, opt_condition) { |
161 // Only sets by script id are supported for now. | 152 // Only sets by script id are supported for now. |
162 assertEquals(this.ScriptBreakPointType.ScriptId, type); | 153 assertEquals(this.ScriptBreakPointType.ScriptId, type); |
163 return this.setScriptBreakPointById(scriptid, opt_line, opt_column, | 154 return this.setScriptBreakPointById(scriptid, opt_line, opt_column, |
164 opt_condition); | 155 opt_condition); |
165 } | 156 } |
166 | 157 |
167 setScriptBreakPointById(scriptid, opt_line, opt_column, opt_condition) { | 158 setScriptBreakPointById(scriptid, opt_line, opt_column, opt_condition) { |
168 const loc = %ScriptLocationFromLine2(scriptid, opt_line, opt_column, 0); | 159 const loc = %ScriptLocationFromLine2(scriptid, opt_line, opt_column, 0); |
169 | 160 return this.setBreakPointAtLocation(scriptid, loc, opt_condition); |
170 const params = { location : | |
171 { scriptId : scriptid.toString(), | |
172 lineNumber : loc.line, | |
173 columnNumber : loc.column, | |
174 }}; | |
175 if (!!opt_condition) { | |
176 params.condition = opt_condition; | |
177 } | |
178 | |
179 const {msgid, msg} = this.createMessage("Debugger.setBreakpoint", params); | |
180 this.sendMessage(msg); | |
181 | |
182 const reply = this.takeReplyChecked(msgid); | |
183 assertTrue(reply.result !== undefined); | |
184 const breakid = reply.result.breakpointId; | |
185 assertTrue(breakid !== undefined); | |
186 | |
187 return breakid; | |
188 } | 161 } |
189 | 162 |
190 clearBreakPoint(breakid) { | 163 clearBreakPoint(breakid) { |
| 164 assertTrue(this.breakpoints.has(breakid)); |
191 const {msgid, msg} = this.createMessage( | 165 const {msgid, msg} = this.createMessage( |
192 "Debugger.removeBreakpoint", { breakpointId : breakid }); | 166 "Debugger.removeBreakpoint", { breakpointId : breakid }); |
193 this.sendMessage(msg); | 167 this.sendMessage(msg); |
194 this.takeReplyChecked(msgid); | 168 this.takeReplyChecked(msgid); |
| 169 this.breakpoints.delete(breakid); |
| 170 } |
| 171 |
| 172 clearAllBreakPoints() { |
| 173 for (let breakid of this.breakpoints) { |
| 174 this.clearBreakPoint(breakid); |
| 175 } |
| 176 this.breakpoints.clear(); |
195 } | 177 } |
196 | 178 |
197 showBreakPoints(f, opt_position_alignment) { | 179 showBreakPoints(f, opt_position_alignment) { |
198 if (!%IsFunction(f)) throw new Error("Not passed a Function"); | 180 if (!%IsFunction(f)) throw new Error("Not passed a Function"); |
199 | 181 |
200 const source = %FunctionGetSourceCode(f); | 182 const source = %FunctionGetSourceCode(f); |
201 const offset = %FunctionGetScriptSourcePosition(f); | 183 const offset = %FunctionGetScriptSourcePosition(f); |
202 const position_alignment = opt_position_alignment === undefined | 184 const position_alignment = opt_position_alignment === undefined |
203 ? this.BreakPositionAlignment.Statement : opt_position_alignment; | 185 ? this.BreakPositionAlignment.Statement : opt_position_alignment; |
204 const locations = %GetBreakLocations(f, position_alignment); | 186 const locations = %GetBreakLocations(f, position_alignment); |
(...skipping 24 matching lines...) Expand all Loading... |
229 { setValue : (enabled) => this.setBreakPointsActive(enabled) } | 211 { setValue : (enabled) => this.setBreakPointsActive(enabled) } |
230 }; | 212 }; |
231 } | 213 } |
232 | 214 |
233 scripts() { | 215 scripts() { |
234 // Collect all scripts in the heap. | 216 // Collect all scripts in the heap. |
235 return %DebugGetLoadedScripts(); | 217 return %DebugGetLoadedScripts(); |
236 } | 218 } |
237 | 219 |
238 // Returns a Script object. If the parameter is a function the return value | 220 // Returns a Script object. If the parameter is a function the return value |
239 // is the script in which the function is defined. If the parameter is a strin
g | 221 // is the script in which the function is defined. If the parameter is a |
240 // the return value is the script for which the script name has that string | 222 // string the return value is the script for which the script name has that |
241 // value. If it is a regexp and there is a unique script whose name matches | 223 // string value. If it is a regexp and there is a unique script whose name |
242 // we return that, otherwise undefined. | 224 // matches we return that, otherwise undefined. |
243 findScript(func_or_script_name) { | 225 findScript(func_or_script_name) { |
244 if (%IsFunction(func_or_script_name)) { | 226 if (%IsFunction(func_or_script_name)) { |
245 return %FunctionGetScript(func_or_script_name); | 227 return %FunctionGetScript(func_or_script_name); |
246 } else if (%IsRegExp(func_or_script_name)) { | 228 } else if (%IsRegExp(func_or_script_name)) { |
247 var scripts = this.scripts(); | 229 var scripts = this.scripts(); |
248 var last_result = null; | 230 var last_result = null; |
249 var result_count = 0; | 231 var result_count = 0; |
250 for (var i in scripts) { | 232 for (var i in scripts) { |
251 var script = scripts[i]; | 233 var script = scripts[i]; |
252 if (func_or_script_name.test(script.name)) { | 234 if (func_or_script_name.test(script.name)) { |
253 last_result = script; | 235 last_result = script; |
254 result_count++; | 236 result_count++; |
255 } | 237 } |
256 } | 238 } |
257 // Return the unique script matching the regexp. If there are more | 239 // Return the unique script matching the regexp. If there are more |
258 // than one we don't return a value since there is no good way to | 240 // than one we don't return a value since there is no good way to |
259 // decide which one to return. Returning a "random" one, say the | 241 // decide which one to return. Returning a "random" one, say the |
260 // first, would introduce nondeterminism (or something close to it) | 242 // first, would introduce nondeterminism (or something close to it) |
261 // because the order is the heap iteration order. | 243 // because the order is the heap iteration order. |
262 if (result_count == 1) { | 244 if (result_count == 1) { |
263 return last_result; | 245 return last_result; |
264 } else { | 246 } else { |
265 return undefined; | 247 return undefined; |
266 } | 248 } |
267 } else { | 249 } else { |
268 return %GetScript(func_or_script_name); | 250 return %GetScript(func_or_script_name); |
269 } | 251 } |
270 } | 252 } |
271 | 253 |
| 254 // Returns the script source. If the parameter is a function the return value |
| 255 // is the script source for the script in which the function is defined. If th
e |
| 256 // parameter is a string the return value is the script for which the script |
| 257 // name has that string value. |
| 258 scriptSource(func_or_script_name) { |
| 259 return this.findScript(func_or_script_name).source; |
| 260 }; |
| 261 |
272 sourcePosition(f) { | 262 sourcePosition(f) { |
273 if (!%IsFunction(f)) throw new Error("Not passed a Function"); | 263 if (!%IsFunction(f)) throw new Error("Not passed a Function"); |
274 return %FunctionGetScriptSourcePosition(f); | 264 return %FunctionGetScriptSourcePosition(f); |
275 }; | 265 }; |
276 | 266 |
| 267 // Returns the character position in a script based on a line number and an |
| 268 // optional position within that line. |
| 269 findScriptSourcePosition(script, opt_line, opt_column) { |
| 270 var location = %ScriptLocationFromLine(script, opt_line, opt_column, 0); |
| 271 return location ? location.position : null; |
| 272 }; |
| 273 |
| 274 findFunctionSourceLocation(func, opt_line, opt_column) { |
| 275 var script = %FunctionGetScript(func); |
| 276 var script_offset = %FunctionGetScriptSourcePosition(func); |
| 277 return %ScriptLocationFromLine(script, opt_line, opt_column, script_offset); |
| 278 } |
| 279 |
277 setBreakPointsActive(enabled) { | 280 setBreakPointsActive(enabled) { |
278 const {msgid, msg} = this.createMessage( | 281 const {msgid, msg} = this.createMessage( |
279 "Debugger.setBreakpointsActive", { active : enabled }); | 282 "Debugger.setBreakpointsActive", { active : enabled }); |
280 this.sendMessage(msg); | 283 this.sendMessage(msg); |
281 this.takeReplyChecked(msgid); | 284 this.takeReplyChecked(msgid); |
282 } | 285 } |
283 | 286 |
284 get LiveEdit() { | 287 get LiveEdit() { |
285 return %GetLiveEditAPIObject(); | 288 return %GetLiveEditAPIObject(); |
286 } | 289 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 this.takeReplyChecked(msgid); | 326 this.takeReplyChecked(msgid); |
324 } | 327 } |
325 | 328 |
326 takeReplyChecked(msgid) { | 329 takeReplyChecked(msgid) { |
327 const reply = this.receivedMessages.get(msgid); | 330 const reply = this.receivedMessages.get(msgid); |
328 assertTrue(reply !== undefined); | 331 assertTrue(reply !== undefined); |
329 this.receivedMessages.delete(msgid); | 332 this.receivedMessages.delete(msgid); |
330 return reply; | 333 return reply; |
331 } | 334 } |
332 | 335 |
| 336 setBreakPointAtLocation(scriptid, loc, opt_condition) { |
| 337 const params = { location : |
| 338 { scriptId : scriptid.toString(), |
| 339 lineNumber : loc.line, |
| 340 columnNumber : loc.column, |
| 341 }, |
| 342 condition : opt_condition, |
| 343 }; |
| 344 |
| 345 const {msgid, msg} = this.createMessage("Debugger.setBreakpoint", params); |
| 346 this.sendMessage(msg); |
| 347 |
| 348 const reply = this.takeReplyChecked(msgid); |
| 349 assertTrue(reply.result !== undefined); |
| 350 const breakid = reply.result.breakpointId; |
| 351 assertTrue(breakid !== undefined); |
| 352 |
| 353 this.breakpoints.add(breakid); |
| 354 |
| 355 return breakid; |
| 356 } |
| 357 |
333 execStatePrepareStep(action) { | 358 execStatePrepareStep(action) { |
334 switch(action) { | 359 switch(action) { |
335 case this.StepAction.StepOut: this.stepOut(); break; | 360 case this.StepAction.StepOut: this.stepOut(); break; |
336 case this.StepAction.StepNext: this.stepOver(); break; | 361 case this.StepAction.StepNext: this.stepOver(); break; |
337 case this.StepAction.StepIn: this.stepInto(); break; | 362 case this.StepAction.StepIn: this.stepInto(); break; |
338 default: %AbortJS("Unsupported StepAction"); break; | 363 default: %AbortJS("Unsupported StepAction"); break; |
339 } | 364 } |
340 } | 365 } |
341 | 366 |
342 execStateScopeType(type) { | 367 execStateScopeType(type) { |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 debug.instance = new DebugWrapper(); | 712 debug.instance = new DebugWrapper(); |
688 debug.instance.enable(); | 713 debug.instance.enable(); |
689 } | 714 } |
690 return debug.instance; | 715 return debug.instance; |
691 }}); | 716 }}); |
692 | 717 |
693 Object.defineProperty(debug, 'ScopeType', { get: function() { | 718 Object.defineProperty(debug, 'ScopeType', { get: function() { |
694 const instance = debug.Debug; | 719 const instance = debug.Debug; |
695 return instance.ScopeType; | 720 return instance.ScopeType; |
696 }}); | 721 }}); |
OLD | NEW |