blob: 19209d4b95d900d3d61cc17cc735d6ac3cd45391 [file] [log] [blame]
ulan@chromium.org967e2702012-02-28 09:49:15 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Default number of frames to include in the response to backtrace request.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000029var kDefaultBacktraceLength = 10;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000031var Debug = {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032
33// Regular expression to skip "crud" at the beginning of a source line which is
34// not really code. Currently the regular expression matches whitespace and
35// comments.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000036var sourceLineBeginningSkip = /^(?:\s*(?:\/\*.*?\*\/)*)*/;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38// Debug events which can occour in the V8 JavaScript engine. These originate
39// from the API include file debug.h.
40Debug.DebugEvent = { Break: 1,
41 Exception: 2,
42 NewFunction: 3,
43 BeforeCompile: 4,
kasperl@chromium.org71affb52009-05-26 05:44:31 +000044 AfterCompile: 5,
45 ScriptCollected: 6 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
47// Types of exceptions that can be broken upon.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000048Debug.ExceptionBreak = { Caught : 0,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049 Uncaught: 1 };
50
51// The different types of steps.
52Debug.StepAction = { StepOut: 0,
53 StepNext: 1,
54 StepIn: 2,
55 StepMin: 3,
56 StepInMin: 4 };
57
58// The different types of scripts matching enum ScriptType in objects.h.
59Debug.ScriptType = { Native: 0,
60 Extension: 1,
61 Normal: 2 };
62
ager@chromium.orge2902be2009-06-08 12:21:35 +000063// The different types of script compilations matching enum
64// Script::CompilationType in objects.h.
65Debug.ScriptCompilationType = { Host: 0,
66 Eval: 1,
67 JSON: 2 };
68
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000069// The different script break point types.
70Debug.ScriptBreakPointType = { ScriptId: 0,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +000071 ScriptName: 1,
72 ScriptRegExp: 2 };
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000073
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +000074// The different types of breakpoint position alignments.
75// Must match BreakPositionAlignment in debug.h.
76Debug.BreakPositionAlignment = {
77 Statement: 0,
78 BreakPosition: 1
79};
80
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000081function ScriptTypeFlag(type) {
82 return (1 << type);
83}
84
85// Globals.
86var next_response_seq = 0;
87var next_break_point_number = 1;
88var break_points = [];
89var script_break_points = [];
whesse@chromium.orge90029b2010-08-02 11:52:17 +000090var debugger_flags = {
91 breakPointsActive: {
92 value: true,
93 getValue: function() { return this.value; },
94 setValue: function(value) {
95 this.value = !!value;
96 %SetDisableBreak(!this.value);
97 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000098 },
99 breakOnCaughtException: {
100 getValue: function() { return Debug.isBreakOnException(); },
101 setValue: function(value) {
102 if (value) {
103 Debug.setBreakOnException();
104 } else {
105 Debug.clearBreakOnException();
106 }
107 }
108 },
109 breakOnUncaughtException: {
110 getValue: function() { return Debug.isBreakOnUncaughtException(); },
111 setValue: function(value) {
112 if (value) {
113 Debug.setBreakOnUncaughtException();
114 } else {
115 Debug.clearBreakOnUncaughtException();
116 }
117 }
118 },
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000119};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120
121
122// Create a new break point object and add it to the list of break points.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000123function MakeBreakPoint(source_position, opt_script_break_point) {
124 var break_point = new BreakPoint(source_position, opt_script_break_point);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000125 break_points.push(break_point);
126 return break_point;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000127}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128
129
130// Object representing a break point.
131// NOTE: This object does not have a reference to the function having break
132// point as this would cause function not to be garbage collected when it is
133// not used any more. We do not want break points to keep functions alive.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000134function BreakPoint(source_position, opt_script_break_point) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135 this.source_position_ = source_position;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136 if (opt_script_break_point) {
137 this.script_break_point_ = opt_script_break_point;
138 } else {
139 this.number_ = next_break_point_number++;
140 }
141 this.hit_count_ = 0;
142 this.active_ = true;
143 this.condition_ = null;
144 this.ignoreCount_ = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000145}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000146
147
148BreakPoint.prototype.number = function() {
149 return this.number_;
150};
151
152
153BreakPoint.prototype.func = function() {
154 return this.func_;
155};
156
157
158BreakPoint.prototype.source_position = function() {
159 return this.source_position_;
160};
161
162
163BreakPoint.prototype.hit_count = function() {
164 return this.hit_count_;
165};
166
167
168BreakPoint.prototype.active = function() {
169 if (this.script_break_point()) {
170 return this.script_break_point().active();
171 }
172 return this.active_;
173};
174
175
176BreakPoint.prototype.condition = function() {
177 if (this.script_break_point() && this.script_break_point().condition()) {
178 return this.script_break_point().condition();
179 }
180 return this.condition_;
181};
182
183
184BreakPoint.prototype.ignoreCount = function() {
185 return this.ignoreCount_;
186};
187
188
189BreakPoint.prototype.script_break_point = function() {
190 return this.script_break_point_;
191};
192
193
194BreakPoint.prototype.enable = function() {
195 this.active_ = true;
196};
197
198
199BreakPoint.prototype.disable = function() {
200 this.active_ = false;
201};
202
203
204BreakPoint.prototype.setCondition = function(condition) {
205 this.condition_ = condition;
206};
207
208
209BreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
210 this.ignoreCount_ = ignoreCount;
211};
212
213
214BreakPoint.prototype.isTriggered = function(exec_state) {
215 // Break point not active - not triggered.
216 if (!this.active()) return false;
217
218 // Check for conditional break point.
219 if (this.condition()) {
220 // If break point has condition try to evaluate it in the top frame.
221 try {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000222 var mirror = exec_state.frame(0).evaluate(this.condition());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223 // If no sensible mirror or non true value break point not triggered.
224 if (!(mirror instanceof ValueMirror) || !%ToBoolean(mirror.value_)) {
225 return false;
226 }
227 } catch (e) {
228 // Exception evaluating condition counts as not triggered.
229 return false;
230 }
231 }
232
233 // Update the hit count.
234 this.hit_count_++;
235 if (this.script_break_point_) {
236 this.script_break_point_.hit_count_++;
237 }
238
239 // If the break point has an ignore count it is not triggered.
240 if (this.ignoreCount_ > 0) {
241 this.ignoreCount_--;
242 return false;
243 }
244
245 // Break point triggered.
246 return true;
247};
248
249
250// Function called from the runtime when a break point is hit. Returns true if
251// the break point is triggered and supposed to break execution.
252function IsBreakPointTriggered(break_id, break_point) {
253 return break_point.isTriggered(MakeExecutionState(break_id));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000254}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000255
256
257// Object representing a script break point. The script is referenced by its
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000258// script name or script id and the break point is represented as line and
259// column.
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000260function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000261 opt_groupId, opt_position_alignment) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000262 this.type_ = type;
263 if (type == Debug.ScriptBreakPointType.ScriptId) {
264 this.script_id_ = script_id_or_name;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000265 } else if (type == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000266 this.script_name_ = script_id_or_name;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000267 } else if (type == Debug.ScriptBreakPointType.ScriptRegExp) {
268 this.script_regexp_object_ = new RegExp(script_id_or_name);
269 } else {
270 throw new Error("Unexpected breakpoint type " + type);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000271 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000272 this.line_ = opt_line || 0;
273 this.column_ = opt_column;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000274 this.groupId_ = opt_groupId;
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000275 this.position_alignment_ = IS_UNDEFINED(opt_position_alignment)
276 ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277 this.hit_count_ = 0;
278 this.active_ = true;
279 this.condition_ = null;
280 this.ignoreCount_ = 0;
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000281 this.break_points_ = [];
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000282}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000283
284
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000285//Creates a clone of script breakpoint that is linked to another script.
286ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
287 var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000288 other_script.id, this.line_, this.column_, this.groupId_,
289 this.position_alignment_);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000290 copy.number_ = next_break_point_number++;
291 script_break_points.push(copy);
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000292
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000293 copy.hit_count_ = this.hit_count_;
294 copy.active_ = this.active_;
295 copy.condition_ = this.condition_;
296 copy.ignoreCount_ = this.ignoreCount_;
297 return copy;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000298};
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000299
300
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000301ScriptBreakPoint.prototype.number = function() {
302 return this.number_;
303};
304
305
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000306ScriptBreakPoint.prototype.groupId = function() {
307 return this.groupId_;
308};
309
310
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000311ScriptBreakPoint.prototype.type = function() {
312 return this.type_;
313};
314
315
316ScriptBreakPoint.prototype.script_id = function() {
317 return this.script_id_;
318};
319
320
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321ScriptBreakPoint.prototype.script_name = function() {
322 return this.script_name_;
323};
324
325
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000326ScriptBreakPoint.prototype.script_regexp_object = function() {
327 return this.script_regexp_object_;
328};
329
330
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000331ScriptBreakPoint.prototype.line = function() {
332 return this.line_;
333};
334
335
336ScriptBreakPoint.prototype.column = function() {
337 return this.column_;
338};
339
340
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000341ScriptBreakPoint.prototype.actual_locations = function() {
342 var locations = [];
343 for (var i = 0; i < this.break_points_.length; i++) {
344 locations.push(this.break_points_[i].actual_location);
345 }
346 return locations;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000347};
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000348
349
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000350ScriptBreakPoint.prototype.update_positions = function(line, column) {
351 this.line_ = line;
352 this.column_ = column;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000353};
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000354
355
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000356ScriptBreakPoint.prototype.hit_count = function() {
357 return this.hit_count_;
358};
359
360
361ScriptBreakPoint.prototype.active = function() {
362 return this.active_;
363};
364
365
366ScriptBreakPoint.prototype.condition = function() {
367 return this.condition_;
368};
369
370
371ScriptBreakPoint.prototype.ignoreCount = function() {
372 return this.ignoreCount_;
373};
374
375
376ScriptBreakPoint.prototype.enable = function() {
377 this.active_ = true;
378};
379
380
381ScriptBreakPoint.prototype.disable = function() {
382 this.active_ = false;
383};
384
385
386ScriptBreakPoint.prototype.setCondition = function(condition) {
387 this.condition_ = condition;
388};
389
390
391ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
392 this.ignoreCount_ = ignoreCount;
393
394 // Set ignore count on all break points created from this script break point.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000395 for (var i = 0; i < this.break_points_.length; i++) {
396 this.break_points_[i].setIgnoreCount(ignoreCount);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397 }
398};
399
400
401// Check whether a script matches this script break point. Currently this is
402// only based on script name.
403ScriptBreakPoint.prototype.matchesScript = function(script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000404 if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
405 return this.script_id_ == script.id;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000406 } else {
407 // We might want to account columns here as well.
408 if (!(script.line_offset <= this.line_ &&
409 this.line_ < script.line_offset + script.lineCount())) {
410 return false;
411 }
412 if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
413 return this.script_name_ == script.nameOrSourceURL();
414 } else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
415 return this.script_regexp_object_.test(script.nameOrSourceURL());
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000416 } else {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000417 throw new Error("Unexpected breakpoint type " + this.type_);
418 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000419 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420};
421
422
423// Set the script break point in a script.
424ScriptBreakPoint.prototype.set = function (script) {
425 var column = this.column();
426 var line = this.line();
427 // If the column is undefined the break is on the line. To help locate the
428 // first piece of breakable code on the line try to find the column on the
429 // line which contains some source.
430 if (IS_UNDEFINED(column)) {
431 var source_line = script.sourceLine(this.line());
432
433 // Allocate array for caching the columns where the actual source starts.
434 if (!script.sourceColumnStart_) {
435 script.sourceColumnStart_ = new Array(script.lineCount());
436 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000437
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000438 // Fill cache if needed and get column where the actual source starts.
439 if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
440 script.sourceColumnStart_[line] =
441 source_line.match(sourceLineBeginningSkip)[0].length;
442 }
443 column = script.sourceColumnStart_[line];
444 }
445
446 // Convert the line and column into an absolute position within the script.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000447 var position = Debug.findScriptSourcePosition(script, this.line(), column);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000448
ager@chromium.org8bb60582008-12-11 12:02:20 +0000449 // If the position is not found in the script (the script might be shorter
450 // than it used to be) just ignore it.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000451 if (position === null) return;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000452
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000453 // Create a break point object and set the break point.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000454 break_point = MakeBreakPoint(position, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455 break_point.setIgnoreCount(this.ignoreCount());
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000456 var actual_position = %SetScriptBreakPoint(script, position,
457 this.position_alignment_,
458 break_point);
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000459 if (IS_UNDEFINED(actual_position)) {
460 actual_position = position;
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000461 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000462 var actual_location = script.locationFromPosition(actual_position, true);
463 break_point.actual_location = { line: actual_location.line,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000464 column: actual_location.column,
465 script_id: script.id };
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000466 this.break_points_.push(break_point);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467 return break_point;
468};
469
470
471// Clear all the break points created from this script break point
472ScriptBreakPoint.prototype.clear = function () {
473 var remaining_break_points = [];
474 for (var i = 0; i < break_points.length; i++) {
475 if (break_points[i].script_break_point() &&
476 break_points[i].script_break_point() === this) {
477 %ClearBreakPoint(break_points[i]);
478 } else {
479 remaining_break_points.push(break_points[i]);
480 }
481 }
482 break_points = remaining_break_points;
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000483 this.break_points_ = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484};
485
486
487// Function called from runtime when a new script is compiled to set any script
488// break points set in this script.
489function UpdateScriptBreakPoints(script) {
490 for (var i = 0; i < script_break_points.length; i++) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000491 var break_point = script_break_points[i];
ulan@chromium.org967e2702012-02-28 09:49:15 +0000492 if ((break_point.type() == Debug.ScriptBreakPointType.ScriptName ||
493 break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) &&
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000494 break_point.matchesScript(script)) {
495 break_point.set(script);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496 }
497 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000498}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499
500
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000501function GetScriptBreakPoints(script) {
502 var result = [];
503 for (var i = 0; i < script_break_points.length; i++) {
504 if (script_break_points[i].matchesScript(script)) {
505 result.push(script_break_points[i]);
506 }
507 }
508 return result;
509}
510
511
iposva@chromium.org245aa852009-02-10 00:49:54 +0000512Debug.setListener = function(listener, opt_data) {
513 if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
514 throw new Error('Parameters have wrong types.');
515 }
516 %SetDebugEventListener(listener, opt_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517};
518
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000520Debug.breakExecution = function(f) {
mads.s.ager31e71382008-08-13 09:32:07 +0000521 %Break();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522};
523
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000524Debug.breakLocations = function(f, opt_position_aligment) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000526 var position_aligment = IS_UNDEFINED(opt_position_aligment)
527 ? Debug.BreakPositionAlignment.Statement : opt_position_aligment;
528 return %GetBreakLocations(f, position_aligment);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529};
530
531// Returns a Script object. If the parameter is a function the return value
532// is the script in which the function is defined. If the parameter is a string
533// the return value is the script for which the script name has that string
mads.s.agercbaa0602008-08-14 13:41:48 +0000534// value. If it is a regexp and there is a unique script whose name matches
535// we return that, otherwise undefined.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000536Debug.findScript = function(func_or_script_name) {
537 if (IS_FUNCTION(func_or_script_name)) {
538 return %FunctionGetScript(func_or_script_name);
mads.s.agercbaa0602008-08-14 13:41:48 +0000539 } else if (IS_REGEXP(func_or_script_name)) {
540 var scripts = Debug.scripts();
541 var last_result = null;
542 var result_count = 0;
543 for (var i in scripts) {
544 var script = scripts[i];
545 if (func_or_script_name.test(script.name)) {
546 last_result = script;
547 result_count++;
548 }
549 }
550 // Return the unique script matching the regexp. If there are more
551 // than one we don't return a value since there is no good way to
552 // decide which one to return. Returning a "random" one, say the
553 // first, would introduce nondeterminism (or something close to it)
554 // because the order is the heap iteration order.
555 if (result_count == 1) {
556 return last_result;
557 } else {
558 return undefined;
559 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560 } else {
561 return %GetScript(func_or_script_name);
562 }
563};
564
565// Returns the script source. If the parameter is a function the return value
566// is the script source for the script in which the function is defined. If the
567// parameter is a string the return value is the script for which the script
568// name has that string value.
569Debug.scriptSource = function(func_or_script_name) {
570 return this.findScript(func_or_script_name).source;
571};
572
573Debug.source = function(f) {
574 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
575 return %FunctionGetSourceCode(f);
576};
577
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000578Debug.disassemble = function(f) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000580 return %DebugDisassembleFunction(f);
581};
582
583Debug.disassembleConstructor = function(f) {
584 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
585 return %DebugDisassembleConstructor(f);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586};
587
ager@chromium.org357bf652010-04-12 11:30:10 +0000588Debug.ExecuteInDebugContext = function(f, without_debugger) {
589 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
590 return %ExecuteInDebugContext(f, !!without_debugger);
591};
592
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000593Debug.sourcePosition = function(f) {
594 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
595 return %FunctionGetScriptSourcePosition(f);
596};
597
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000598
599Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600 var script = %FunctionGetScript(func);
601 var script_offset = %FunctionGetScriptSourcePosition(func);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000602 return script.locationFromLine(opt_line, opt_column, script_offset);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000603};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000604
605
606// Returns the character position in a script based on a line number and an
607// optional position within that line.
608Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000609 var location = script.locationFromLine(opt_line, opt_column);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000610 return location ? location.position : null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000611};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612
613
614Debug.findBreakPoint = function(break_point_number, remove) {
615 var break_point;
616 for (var i = 0; i < break_points.length; i++) {
617 if (break_points[i].number() == break_point_number) {
618 break_point = break_points[i];
619 // Remove the break point from the list if requested.
620 if (remove) {
621 break_points.splice(i, 1);
622 }
623 break;
624 }
625 }
626 if (break_point) {
627 return break_point;
628 } else {
629 return this.findScriptBreakPoint(break_point_number, remove);
630 }
631};
632
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000633Debug.findBreakPointActualLocations = function(break_point_number) {
634 for (var i = 0; i < script_break_points.length; i++) {
635 if (script_break_points[i].number() == break_point_number) {
636 return script_break_points[i].actual_locations();
637 }
638 }
639 for (var i = 0; i < break_points.length; i++) {
640 if (break_points[i].number() == break_point_number) {
641 return [break_points[i].actual_location];
642 }
643 }
644 return [];
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000645};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000646
647Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
648 if (!IS_FUNCTION(func)) throw new Error('Parameters have wrong types.');
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000649 // Break points in API functions are not supported.
650 if (%FunctionIsAPIFunction(func)) {
651 throw new Error('Cannot set break point in native code.');
652 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000653 // Find source position relative to start of the function
654 var break_position =
655 this.findFunctionSourceLocation(func, opt_line, opt_column).position;
656 var source_position = break_position - this.sourcePosition(func);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000657 // Find the script for the function.
658 var script = %FunctionGetScript(func);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000659 // Break in builtin JavaScript code is not supported.
660 if (script.type == Debug.ScriptType.Native) {
661 throw new Error('Cannot set break point in native code.');
662 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000663 // If the script for the function has a name convert this to a script break
664 // point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000665 if (script && script.id) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000666 // Adjust the source position to be script relative.
667 source_position += %FunctionGetScriptSourcePosition(func);
668 // Find line and column for the position in the script and set a script
669 // break point from that.
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000670 var location = script.locationFromPosition(source_position, false);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000671 return this.setScriptBreakPointById(script.id,
672 location.line, location.column,
673 opt_condition);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 } else {
675 // Set a break point directly on the function.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000676 var break_point = MakeBreakPoint(source_position);
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000677 var actual_position =
678 %SetFunctionBreakPoint(func, source_position, break_point);
679 actual_position += this.sourcePosition(func);
680 var actual_location = script.locationFromPosition(actual_position, true);
681 break_point.actual_location = { line: actual_location.line,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000682 column: actual_location.column,
683 script_id: script.id };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684 break_point.setCondition(opt_condition);
685 return break_point.number();
686 }
687};
688
689
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000690Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000691 condition, enabled,
692 opt_position_alignment)
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000693{
694 break_point = MakeBreakPoint(position);
695 break_point.setCondition(condition);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000696 if (!enabled) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000697 break_point.disable();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000698 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000699 var scripts = this.scripts();
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000700 var position_alignment = IS_UNDEFINED(opt_position_alignment)
701 ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000702 for (var i = 0; i < scripts.length; i++) {
703 if (script_id == scripts[i].id) {
704 break_point.actual_position = %SetScriptBreakPoint(scripts[i], position,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000705 position_alignment, break_point);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000706 break;
707 }
708 }
709 return break_point;
710};
711
712
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713Debug.enableBreakPoint = function(break_point_number) {
714 var break_point = this.findBreakPoint(break_point_number, false);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000715 // Only enable if the breakpoint hasn't been deleted:
716 if (break_point) {
717 break_point.enable();
718 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000719};
720
721
722Debug.disableBreakPoint = function(break_point_number) {
723 var break_point = this.findBreakPoint(break_point_number, false);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000724 // Only enable if the breakpoint hasn't been deleted:
725 if (break_point) {
726 break_point.disable();
727 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728};
729
730
731Debug.changeBreakPointCondition = function(break_point_number, condition) {
732 var break_point = this.findBreakPoint(break_point_number, false);
733 break_point.setCondition(condition);
734};
735
736
737Debug.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
738 if (ignoreCount < 0) {
739 throw new Error('Invalid argument');
740 }
741 var break_point = this.findBreakPoint(break_point_number, false);
742 break_point.setIgnoreCount(ignoreCount);
743};
744
745
746Debug.clearBreakPoint = function(break_point_number) {
747 var break_point = this.findBreakPoint(break_point_number, true);
748 if (break_point) {
749 return %ClearBreakPoint(break_point);
750 } else {
751 break_point = this.findScriptBreakPoint(break_point_number, true);
752 if (!break_point) {
753 throw new Error('Invalid breakpoint');
754 }
755 }
756};
757
758
759Debug.clearAllBreakPoints = function() {
760 for (var i = 0; i < break_points.length; i++) {
761 break_point = break_points[i];
762 %ClearBreakPoint(break_point);
763 }
764 break_points = [];
765};
766
767
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000768Debug.disableAllBreakPoints = function() {
769 // Disable all user defined breakpoints:
770 for (var i = 1; i < next_break_point_number; i++) {
771 Debug.disableBreakPoint(i);
772 }
773 // Disable all exception breakpoints:
774 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
775 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
776};
777
778
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000779Debug.findScriptBreakPoint = function(break_point_number, remove) {
780 var script_break_point;
781 for (var i = 0; i < script_break_points.length; i++) {
782 if (script_break_points[i].number() == break_point_number) {
783 script_break_point = script_break_points[i];
784 // Remove the break point from the list if requested.
785 if (remove) {
786 script_break_point.clear();
787 script_break_points.splice(i,1);
788 }
789 break;
790 }
791 }
792 return script_break_point;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000793};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794
795
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000796// Sets a breakpoint in a script identified through id or name at the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000797// specified source line and column within that line.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000798Debug.setScriptBreakPoint = function(type, script_id_or_name,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000799 opt_line, opt_column, opt_condition,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000800 opt_groupId, opt_position_alignment) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000801 // Create script break point object.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000802 var script_break_point =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000803 new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000804 opt_groupId, opt_position_alignment);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805
806 // Assign number to the new script break point and add it.
807 script_break_point.number_ = next_break_point_number++;
808 script_break_point.setCondition(opt_condition);
809 script_break_points.push(script_break_point);
810
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000811 // Run through all scripts to see if this script break point matches any
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812 // loaded scripts.
813 var scripts = this.scripts();
814 for (var i = 0; i < scripts.length; i++) {
815 if (script_break_point.matchesScript(scripts[i])) {
816 script_break_point.set(scripts[i]);
817 }
818 }
819
820 return script_break_point.number();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000821};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000822
823
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000824Debug.setScriptBreakPointById = function(script_id,
825 opt_line, opt_column,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000826 opt_condition, opt_groupId,
827 opt_position_alignment) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000828 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
829 script_id, opt_line, opt_column,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000830 opt_condition, opt_groupId,
831 opt_position_alignment);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000832};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000833
834
835Debug.setScriptBreakPointByName = function(script_name,
836 opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000837 opt_condition, opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000838 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
839 script_name, opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000840 opt_condition, opt_groupId);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000841};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000842
843
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000844Debug.setScriptBreakPointByRegExp = function(script_regexp,
845 opt_line, opt_column,
846 opt_condition, opt_groupId) {
847 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptRegExp,
848 script_regexp, opt_line, opt_column,
849 opt_condition, opt_groupId);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000850};
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000851
852
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000853Debug.enableScriptBreakPoint = function(break_point_number) {
854 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
855 script_break_point.enable();
856};
857
858
859Debug.disableScriptBreakPoint = function(break_point_number) {
860 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
861 script_break_point.disable();
862};
863
864
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000865Debug.changeScriptBreakPointCondition = function(
866 break_point_number, condition) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
868 script_break_point.setCondition(condition);
869};
870
871
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000872Debug.changeScriptBreakPointIgnoreCount = function(
873 break_point_number, ignoreCount) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874 if (ignoreCount < 0) {
875 throw new Error('Invalid argument');
876 }
877 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
878 script_break_point.setIgnoreCount(ignoreCount);
879};
880
881
882Debug.scriptBreakPoints = function() {
883 return script_break_points;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000884};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000885
886
887Debug.clearStepping = function() {
mads.s.ager31e71382008-08-13 09:32:07 +0000888 %ClearStepping();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000889};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890
891Debug.setBreakOnException = function() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000892 return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893};
894
895Debug.clearBreakOnException = function() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000896 return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
897};
898
899Debug.isBreakOnException = function() {
900 return !!%IsBreakOnException(Debug.ExceptionBreak.Caught);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000901};
902
903Debug.setBreakOnUncaughtException = function() {
904 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
905};
906
907Debug.clearBreakOnUncaughtException = function() {
908 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
909};
910
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000911Debug.isBreakOnUncaughtException = function() {
912 return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
913};
914
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000915Debug.showBreakPoints = function(f, full, opt_position_alignment) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
917 var source = full ? this.scriptSource(f) : this.source(f);
918 var offset = full ? this.sourcePosition(f) : 0;
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000919 var locations = this.breakLocations(f, opt_position_alignment);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000920 if (!locations) return source;
921 locations.sort(function(x, y) { return x - y; });
922 var result = "";
923 var prev_pos = 0;
924 var pos;
925 for (var i = 0; i < locations.length; i++) {
926 pos = locations[i] - offset;
927 result += source.slice(prev_pos, pos);
928 result += "[B" + i + "]";
929 prev_pos = pos;
930 }
931 pos = source.length;
932 result += source.substring(prev_pos, pos);
933 return result;
934};
935
936
937// Get all the scripts currently loaded. Locating all the scripts is based on
938// scanning the heap.
939Debug.scripts = function() {
940 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +0000941 return %DebugGetLoadedScripts();
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000942};
943
944
945Debug.debuggerFlags = function() {
946 return debugger_flags;
947};
948
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000949Debug.MakeMirror = MakeMirror;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000950
951function MakeExecutionState(break_id) {
952 return new ExecutionState(break_id);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000953}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000954
955function ExecutionState(break_id) {
956 this.break_id = break_id;
957 this.selected_frame = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000958}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000959
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000960ExecutionState.prototype.prepareStep = function(opt_action, opt_count,
961 opt_callframe) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000962 var action = Debug.StepAction.StepIn;
963 if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
964 var count = opt_count ? %ToNumber(opt_count) : 1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000965 var callFrameId = 0;
966 if (!IS_UNDEFINED(opt_callframe)) {
967 callFrameId = opt_callframe.details_.frameId();
968 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000969
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000970 return %PrepareStep(this.break_id, action, count, callFrameId);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000971};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000972
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000973ExecutionState.prototype.evaluateGlobal = function(source, disable_break,
974 opt_additional_context) {
975 return MakeMirror(%DebugEvaluateGlobal(this.break_id, source,
976 Boolean(disable_break),
977 opt_additional_context));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000978};
979
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000980ExecutionState.prototype.frameCount = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000981 return %GetFrameCount(this.break_id);
982};
983
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000984ExecutionState.prototype.threadCount = function() {
985 return %GetThreadCount(this.break_id);
986};
987
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000988ExecutionState.prototype.frame = function(opt_index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000989 // If no index supplied return the selected frame.
990 if (opt_index == null) opt_index = this.selected_frame;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000991 if (opt_index < 0 || opt_index >= this.frameCount()) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000992 throw new Error('Illegal frame index.');
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000993 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000994 return new FrameMirror(this.break_id, opt_index);
995};
996
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000997ExecutionState.prototype.setSelectedFrame = function(index) {
998 var i = %ToNumber(index);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000999 if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001000 this.selected_frame = i;
1001};
1002
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001003ExecutionState.prototype.selectedFrame = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001004 return this.selected_frame;
1005};
1006
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001007ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) {
1008 return new DebugCommandProcessor(this, opt_is_running);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001009};
1010
1011
1012function MakeBreakEvent(exec_state, break_points_hit) {
1013 return new BreakEvent(exec_state, break_points_hit);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001014}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001015
1016
1017function BreakEvent(exec_state, break_points_hit) {
1018 this.exec_state_ = exec_state;
1019 this.break_points_hit_ = break_points_hit;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001020}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001021
1022
ager@chromium.org8bb60582008-12-11 12:02:20 +00001023BreakEvent.prototype.executionState = function() {
1024 return this.exec_state_;
1025};
1026
1027
1028BreakEvent.prototype.eventType = function() {
1029 return Debug.DebugEvent.Break;
1030};
1031
1032
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001033BreakEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001034 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001035};
1036
1037
1038BreakEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001039 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001040};
1041
1042
1043BreakEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001044 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045};
1046
1047
1048BreakEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001049 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001050};
1051
1052
1053BreakEvent.prototype.breakPointsHit = function() {
1054 return this.break_points_hit_;
1055};
1056
1057
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058BreakEvent.prototype.toJSONProtocol = function() {
1059 var o = { seq: next_response_seq++,
1060 type: "event",
1061 event: "break",
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001062 body: { invocationText: this.exec_state_.frame(0).invocationText(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001063 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001064 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001065
1066 // Add script related information to the event if available.
1067 var script = this.func().script();
1068 if (script) {
1069 o.body.sourceLine = this.sourceLine(),
1070 o.body.sourceColumn = this.sourceColumn(),
1071 o.body.sourceLineText = this.sourceLineText(),
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001072 o.body.script = MakeScriptObject_(script, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001073 }
1074
1075 // Add an Array of break points hit if any.
1076 if (this.breakPointsHit()) {
1077 o.body.breakpoints = [];
1078 for (var i = 0; i < this.breakPointsHit().length; i++) {
1079 // Find the break point number. For break points originating from a
1080 // script break point supply the script break point number.
1081 var breakpoint = this.breakPointsHit()[i];
1082 var script_break_point = breakpoint.script_break_point();
1083 var number;
1084 if (script_break_point) {
1085 number = script_break_point.number();
1086 } else {
1087 number = breakpoint.number();
1088 }
1089 o.body.breakpoints.push(number);
1090 }
1091 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001092 return JSON.stringify(ObjectToProtocolObject_(o));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001093};
1094
1095
1096function MakeExceptionEvent(exec_state, exception, uncaught) {
1097 return new ExceptionEvent(exec_state, exception, uncaught);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001098}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001099
ager@chromium.org8bb60582008-12-11 12:02:20 +00001100
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101function ExceptionEvent(exec_state, exception, uncaught) {
1102 this.exec_state_ = exec_state;
1103 this.exception_ = exception;
1104 this.uncaught_ = uncaught;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001105}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106
ager@chromium.org8bb60582008-12-11 12:02:20 +00001107
1108ExceptionEvent.prototype.executionState = function() {
1109 return this.exec_state_;
1110};
1111
1112
1113ExceptionEvent.prototype.eventType = function() {
1114 return Debug.DebugEvent.Exception;
1115};
1116
1117
1118ExceptionEvent.prototype.exception = function() {
1119 return this.exception_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001120};
ager@chromium.org8bb60582008-12-11 12:02:20 +00001121
1122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123ExceptionEvent.prototype.uncaught = function() {
1124 return this.uncaught_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001125};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001126
ager@chromium.org8bb60582008-12-11 12:02:20 +00001127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001128ExceptionEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001129 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130};
1131
1132
1133ExceptionEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001134 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135};
1136
1137
1138ExceptionEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001139 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140};
1141
1142
1143ExceptionEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001144 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001145};
1146
1147
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001148ExceptionEvent.prototype.toJSONProtocol = function() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001149 var o = new ProtocolMessage();
1150 o.event = "exception";
1151 o.body = { uncaught: this.uncaught_,
1152 exception: MakeMirror(this.exception_)
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001153 };
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001154
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001155 // Exceptions might happen whithout any JavaScript frames.
1156 if (this.exec_state_.frameCount() > 0) {
1157 o.body.sourceLine = this.sourceLine();
1158 o.body.sourceColumn = this.sourceColumn();
1159 o.body.sourceLineText = this.sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001160
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001161 // Add script information to the event if available.
1162 var script = this.func().script();
1163 if (script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001164 o.body.script = MakeScriptObject_(script, false);
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001165 }
1166 } else {
1167 o.body.sourceLine = -1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001168 }
1169
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001170 return o.toJSONProtocol();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001171};
1172
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001173
iposva@chromium.org245aa852009-02-10 00:49:54 +00001174function MakeCompileEvent(exec_state, script, before) {
1175 return new CompileEvent(exec_state, script, before);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001176}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001178
iposva@chromium.org245aa852009-02-10 00:49:54 +00001179function CompileEvent(exec_state, script, before) {
1180 this.exec_state_ = exec_state;
1181 this.script_ = MakeMirror(script);
1182 this.before_ = before;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001183}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001184
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001185
iposva@chromium.org245aa852009-02-10 00:49:54 +00001186CompileEvent.prototype.executionState = function() {
1187 return this.exec_state_;
1188};
1189
1190
ager@chromium.org8bb60582008-12-11 12:02:20 +00001191CompileEvent.prototype.eventType = function() {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001192 if (this.before_) {
1193 return Debug.DebugEvent.BeforeCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001194 } else {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001195 return Debug.DebugEvent.AfterCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001196 }
1197};
1198
1199
iposva@chromium.org245aa852009-02-10 00:49:54 +00001200CompileEvent.prototype.script = function() {
1201 return this.script_;
1202};
1203
1204
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001205CompileEvent.prototype.toJSONProtocol = function() {
1206 var o = new ProtocolMessage();
ager@chromium.org5ec48922009-05-05 07:25:34 +00001207 o.running = true;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001208 if (this.before_) {
1209 o.event = "beforeCompile";
1210 } else {
1211 o.event = "afterCompile";
1212 }
1213 o.body = {};
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001214 o.body.script = this.script_;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001215
1216 return o.toJSONProtocol();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001217};
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001218
1219
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001220function MakeNewFunctionEvent(func) {
1221 return new NewFunctionEvent(func);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001222}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001224
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001225function NewFunctionEvent(func) {
1226 this.func = func;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001227}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001228
ager@chromium.org8bb60582008-12-11 12:02:20 +00001229
1230NewFunctionEvent.prototype.eventType = function() {
1231 return Debug.DebugEvent.NewFunction;
1232};
1233
1234
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001235NewFunctionEvent.prototype.name = function() {
1236 return this.func.name;
1237};
1238
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240NewFunctionEvent.prototype.setBreakPoint = function(p) {
1241 Debug.setBreakPoint(this.func, p || 0);
1242};
1243
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001244
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001245function MakeScriptCollectedEvent(exec_state, id) {
1246 return new ScriptCollectedEvent(exec_state, id);
1247}
1248
1249
1250function ScriptCollectedEvent(exec_state, id) {
1251 this.exec_state_ = exec_state;
1252 this.id_ = id;
1253}
1254
1255
1256ScriptCollectedEvent.prototype.id = function() {
1257 return this.id_;
1258};
1259
1260
1261ScriptCollectedEvent.prototype.executionState = function() {
1262 return this.exec_state_;
1263};
1264
1265
1266ScriptCollectedEvent.prototype.toJSONProtocol = function() {
1267 var o = new ProtocolMessage();
1268 o.running = true;
1269 o.event = "scriptCollected";
1270 o.body = {};
1271 o.body.script = { id: this.id() };
1272 return o.toJSONProtocol();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001273};
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001274
1275
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001276function MakeScriptObject_(script, include_source) {
1277 var o = { id: script.id(),
1278 name: script.name(),
1279 lineOffset: script.lineOffset(),
1280 columnOffset: script.columnOffset(),
1281 lineCount: script.lineCount(),
1282 };
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001283 if (!IS_UNDEFINED(script.data())) {
1284 o.data = script.data();
1285 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001286 if (include_source) {
1287 o.source = script.source();
1288 }
1289 return o;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001290}
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001291
1292
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001293function DebugCommandProcessor(exec_state, opt_is_running) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294 this.exec_state_ = exec_state;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001295 this.running_ = opt_is_running || false;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001296}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297
1298
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001299DebugCommandProcessor.prototype.processDebugRequest = function (request) {
1300 return this.processDebugJSONRequest(request);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001301};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001302
1303
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001304function ProtocolMessage(request) {
1305 // Update sequence number.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001306 this.seq = next_response_seq++;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001307
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001308 if (request) {
1309 // If message is based on a request this is a response. Fill the initial
1310 // response from the request.
1311 this.type = 'response';
1312 this.request_seq = request.seq;
1313 this.command = request.command;
1314 } else {
1315 // If message is not based on a request it is a dabugger generated event.
1316 this.type = 'event';
1317 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001318 this.success = true;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001319 // Handler may set this field to control debugger state.
1320 this.running = undefined;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001321}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001322
1323
ager@chromium.org9085a012009-05-11 19:22:57 +00001324ProtocolMessage.prototype.setOption = function(name, value) {
1325 if (!this.options_) {
1326 this.options_ = {};
1327 }
1328 this.options_[name] = value;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001329};
ager@chromium.org9085a012009-05-11 19:22:57 +00001330
1331
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001332ProtocolMessage.prototype.failed = function(message, opt_details) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001333 this.success = false;
1334 this.message = message;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001335 if (IS_OBJECT(opt_details)) {
1336 this.error_details = opt_details;
1337 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001338};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001339
1340
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001341ProtocolMessage.prototype.toJSONProtocol = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001342 // Encode the protocol header.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001343 var json = {};
1344 json.seq= this.seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001345 if (this.request_seq) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001346 json.request_seq = this.request_seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001347 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001348 json.type = this.type;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001349 if (this.event) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001350 json.event = this.event;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001351 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001352 if (this.command) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001353 json.command = this.command;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354 }
1355 if (this.success) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001356 json.success = this.success;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001357 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001358 json.success = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359 }
1360 if (this.body) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361 // Encode the body part.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001362 var bodyJson;
ager@chromium.org9085a012009-05-11 19:22:57 +00001363 var serializer = MakeMirrorSerializer(true, this.options_);
ager@chromium.org32912102009-01-16 10:38:43 +00001364 if (this.body instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001365 bodyJson = serializer.serializeValue(this.body);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001366 } else if (this.body instanceof Array) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001367 bodyJson = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001368 for (var i = 0; i < this.body.length; i++) {
ager@chromium.org32912102009-01-16 10:38:43 +00001369 if (this.body[i] instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001370 bodyJson.push(serializer.serializeValue(this.body[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001371 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001372 bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001373 }
1374 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001375 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001376 bodyJson = ObjectToProtocolObject_(this.body, serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001377 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001378 json.body = bodyJson;
1379 json.refs = serializer.serializeReferencedObjects();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380 }
1381 if (this.message) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001382 json.message = this.message;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001383 }
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001384 if (this.error_details) {
1385 json.error_details = this.error_details;
1386 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001387 json.running = this.running;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001388 return JSON.stringify(json);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001389};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001390
1391
1392DebugCommandProcessor.prototype.createResponse = function(request) {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001393 return new ProtocolMessage(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394};
1395
1396
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001397DebugCommandProcessor.prototype.processDebugJSONRequest = function(
1398 json_request) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001399 var request; // Current request.
1400 var response; // Generated response.
1401 try {
1402 try {
1403 // Convert the JSON string to an object.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001404 request = JSON.parse(json_request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405
1406 // Create an initial response.
1407 response = this.createResponse(request);
1408
1409 if (!request.type) {
1410 throw new Error('Type not specified');
1411 }
1412
1413 if (request.type != 'request') {
1414 throw new Error("Illegal type '" + request.type + "' in request");
1415 }
1416
1417 if (!request.command) {
1418 throw new Error('Command not specified');
1419 }
1420
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001421 if (request.arguments) {
1422 var args = request.arguments;
1423 // TODO(yurys): remove request.arguments.compactFormat check once
1424 // ChromeDevTools are switched to 'inlineRefs'
1425 if (args.inlineRefs || args.compactFormat) {
1426 response.setOption('inlineRefs', true);
1427 }
1428 if (!IS_UNDEFINED(args.maxStringLength)) {
1429 response.setOption('maxStringLength', args.maxStringLength);
1430 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001431 }
1432
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433 if (request.command == 'continue') {
1434 this.continueRequest_(request, response);
1435 } else if (request.command == 'break') {
1436 this.breakRequest_(request, response);
1437 } else if (request.command == 'setbreakpoint') {
1438 this.setBreakPointRequest_(request, response);
1439 } else if (request.command == 'changebreakpoint') {
1440 this.changeBreakPointRequest_(request, response);
1441 } else if (request.command == 'clearbreakpoint') {
1442 this.clearBreakPointRequest_(request, response);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001443 } else if (request.command == 'clearbreakpointgroup') {
1444 this.clearBreakPointGroupRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001445 } else if (request.command == 'disconnect') {
1446 this.disconnectRequest_(request, response);
1447 } else if (request.command == 'setexceptionbreak') {
1448 this.setExceptionBreakRequest_(request, response);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001449 } else if (request.command == 'listbreakpoints') {
1450 this.listBreakpointsRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001451 } else if (request.command == 'backtrace') {
1452 this.backtraceRequest_(request, response);
1453 } else if (request.command == 'frame') {
1454 this.frameRequest_(request, response);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001455 } else if (request.command == 'scopes') {
1456 this.scopesRequest_(request, response);
1457 } else if (request.command == 'scope') {
1458 this.scopeRequest_(request, response);
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001459 } else if (request.command == 'setVariableValue') {
1460 this.setVariableValueRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461 } else if (request.command == 'evaluate') {
1462 this.evaluateRequest_(request, response);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001463 } else if (request.command == 'lookup') {
1464 this.lookupRequest_(request, response);
iposva@chromium.org245aa852009-02-10 00:49:54 +00001465 } else if (request.command == 'references') {
1466 this.referencesRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001467 } else if (request.command == 'source') {
1468 this.sourceRequest_(request, response);
1469 } else if (request.command == 'scripts') {
1470 this.scriptsRequest_(request, response);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001471 } else if (request.command == 'threads') {
1472 this.threadsRequest_(request, response);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001473 } else if (request.command == 'suspend') {
1474 this.suspendRequest_(request, response);
ager@chromium.org3811b432009-10-28 14:53:37 +00001475 } else if (request.command == 'version') {
1476 this.versionRequest_(request, response);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001477 } else if (request.command == 'changelive') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001478 this.changeLiveRequest_(request, response);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001479 } else if (request.command == 'restartframe') {
1480 this.restartFrameRequest_(request, response);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001481 } else if (request.command == 'flags') {
1482 this.debuggerFlagsRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001483 } else if (request.command == 'v8flags') {
1484 this.v8FlagsRequest_(request, response);
1485
1486 // GC tools:
1487 } else if (request.command == 'gc') {
1488 this.gcRequest_(request, response);
1489
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001490 } else {
1491 throw new Error('Unknown command "' + request.command + '" in request');
1492 }
1493 } catch (e) {
1494 // If there is no response object created one (without command).
1495 if (!response) {
1496 response = this.createResponse();
1497 }
1498 response.success = false;
1499 response.message = %ToString(e);
1500 }
1501
1502 // Return the response as a JSON encoded string.
1503 try {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001504 if (!IS_UNDEFINED(response.running)) {
1505 // Response controls running state.
1506 this.running_ = response.running;
1507 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00001508 response.running = this.running_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001509 return response.toJSONProtocol();
1510 } catch (e) {
1511 // Failed to generate response - return generic error.
1512 return '{"seq":' + response.seq + ',' +
1513 '"request_seq":' + request.seq + ',' +
1514 '"type":"response",' +
1515 '"success":false,' +
1516 '"message":"Internal error: ' + %ToString(e) + '"}';
1517 }
1518 } catch (e) {
1519 // Failed in one of the catch blocks above - most generic error.
1520 return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
1521 }
1522};
1523
1524
1525DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
1526 // Check for arguments for continue.
1527 if (request.arguments) {
1528 var count = 1;
1529 var action = Debug.StepAction.StepIn;
1530
1531 // Pull out arguments.
1532 var stepaction = request.arguments.stepaction;
1533 var stepcount = request.arguments.stepcount;
1534
1535 // Get the stepcount argument if any.
1536 if (stepcount) {
1537 count = %ToNumber(stepcount);
1538 if (count < 0) {
1539 throw new Error('Invalid stepcount argument "' + stepcount + '".');
1540 }
1541 }
1542
1543 // Get the stepaction argument.
1544 if (stepaction) {
1545 if (stepaction == 'in') {
1546 action = Debug.StepAction.StepIn;
1547 } else if (stepaction == 'min') {
1548 action = Debug.StepAction.StepMin;
1549 } else if (stepaction == 'next') {
1550 action = Debug.StepAction.StepNext;
1551 } else if (stepaction == 'out') {
1552 action = Debug.StepAction.StepOut;
1553 } else {
1554 throw new Error('Invalid stepaction argument "' + stepaction + '".');
1555 }
1556 }
1557
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001558 // Set up the VM for stepping.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559 this.exec_state_.prepareStep(action, count);
1560 }
1561
1562 // VM should be running after executing this request.
1563 response.running = true;
1564};
1565
1566
1567DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
1568 // Ignore as break command does not do anything when broken.
1569};
1570
1571
1572DebugCommandProcessor.prototype.setBreakPointRequest_ =
1573 function(request, response) {
1574 // Check for legal request.
1575 if (!request.arguments) {
1576 response.failed('Missing arguments');
1577 return;
1578 }
1579
1580 // Pull out arguments.
1581 var type = request.arguments.type;
1582 var target = request.arguments.target;
1583 var line = request.arguments.line;
1584 var column = request.arguments.column;
1585 var enabled = IS_UNDEFINED(request.arguments.enabled) ?
1586 true : request.arguments.enabled;
1587 var condition = request.arguments.condition;
1588 var ignoreCount = request.arguments.ignoreCount;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001589 var groupId = request.arguments.groupId;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001590
1591 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001592 if (!type || IS_UNDEFINED(target)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001593 response.failed('Missing argument "type" or "target"');
1594 return;
1595 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001596
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001597 // Either function or script break point.
1598 var break_point_number;
1599 if (type == 'function') {
1600 // Handle function break point.
1601 if (!IS_STRING(target)) {
1602 response.failed('Argument "target" is not a string value');
1603 return;
1604 }
1605 var f;
1606 try {
1607 // Find the function through a global evaluate.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001608 f = this.exec_state_.evaluateGlobal(target).value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001609 } catch (e) {
1610 response.failed('Error: "' + %ToString(e) +
1611 '" evaluating "' + target + '"');
1612 return;
1613 }
1614 if (!IS_FUNCTION(f)) {
1615 response.failed('"' + target + '" does not evaluate to a function');
1616 return;
1617 }
1618
1619 // Set function break point.
1620 break_point_number = Debug.setBreakPoint(f, line, column, condition);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001621 } else if (type == 'handle') {
1622 // Find the object pointed by the specified handle.
1623 var handle = parseInt(target, 10);
1624 var mirror = LookupMirror(handle);
1625 if (!mirror) {
1626 return response.failed('Object #' + handle + '# not found');
1627 }
1628 if (!mirror.isFunction()) {
1629 return response.failed('Object #' + handle + '# is not a function');
1630 }
1631
1632 // Set function break point.
1633 break_point_number = Debug.setBreakPoint(mirror.value(),
1634 line, column, condition);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001635 } else if (type == 'script') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001636 // set script break point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001637 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001638 Debug.setScriptBreakPointByName(target, line, column, condition,
1639 groupId);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001640 } else if (type == 'scriptId') {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001641 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001642 Debug.setScriptBreakPointById(target, line, column, condition, groupId);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001643 } else if (type == 'scriptRegExp') {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001644 break_point_number =
1645 Debug.setScriptBreakPointByRegExp(target, line, column, condition,
1646 groupId);
1647 } else {
1648 response.failed('Illegal type "' + type + '"');
1649 return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001650 }
1651
1652 // Set additional break point properties.
1653 var break_point = Debug.findBreakPoint(break_point_number);
1654 if (ignoreCount) {
1655 Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
1656 }
1657 if (!enabled) {
1658 Debug.disableBreakPoint(break_point_number);
1659 }
1660
1661 // Add the break point number to the response.
1662 response.body = { type: type,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001663 breakpoint: break_point_number };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664
1665 // Add break point information to the response.
1666 if (break_point instanceof ScriptBreakPoint) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001667 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1668 response.body.type = 'scriptId';
1669 response.body.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001670 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001671 response.body.type = 'scriptName';
1672 response.body.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001673 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1674 response.body.type = 'scriptRegExp';
1675 response.body.script_regexp = break_point.script_regexp_object().source;
1676 } else {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001677 throw new Error("Internal error: Unexpected breakpoint type: " +
1678 break_point.type());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001679 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001680 response.body.line = break_point.line();
1681 response.body.column = break_point.column();
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001682 response.body.actual_locations = break_point.actual_locations();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001683 } else {
1684 response.body.type = 'function';
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001685 response.body.actual_locations = [break_point.actual_location];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001686 }
1687};
1688
1689
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001690DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(
1691 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001692 // Check for legal request.
1693 if (!request.arguments) {
1694 response.failed('Missing arguments');
1695 return;
1696 }
1697
1698 // Pull out arguments.
1699 var break_point = %ToNumber(request.arguments.breakpoint);
1700 var enabled = request.arguments.enabled;
1701 var condition = request.arguments.condition;
1702 var ignoreCount = request.arguments.ignoreCount;
1703
1704 // Check for legal arguments.
1705 if (!break_point) {
1706 response.failed('Missing argument "breakpoint"');
1707 return;
1708 }
1709
1710 // Change enabled state if supplied.
1711 if (!IS_UNDEFINED(enabled)) {
1712 if (enabled) {
1713 Debug.enableBreakPoint(break_point);
1714 } else {
1715 Debug.disableBreakPoint(break_point);
1716 }
1717 }
1718
1719 // Change condition if supplied
1720 if (!IS_UNDEFINED(condition)) {
1721 Debug.changeBreakPointCondition(break_point, condition);
1722 }
1723
1724 // Change ignore count if supplied
1725 if (!IS_UNDEFINED(ignoreCount)) {
1726 Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
1727 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001728};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001729
1730
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001731DebugCommandProcessor.prototype.clearBreakPointGroupRequest_ = function(
1732 request, response) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001733 // Check for legal request.
1734 if (!request.arguments) {
1735 response.failed('Missing arguments');
1736 return;
1737 }
1738
1739 // Pull out arguments.
1740 var group_id = request.arguments.groupId;
1741
1742 // Check for legal arguments.
1743 if (!group_id) {
1744 response.failed('Missing argument "groupId"');
1745 return;
1746 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001747
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001748 var cleared_break_points = [];
1749 var new_script_break_points = [];
1750 for (var i = 0; i < script_break_points.length; i++) {
1751 var next_break_point = script_break_points[i];
1752 if (next_break_point.groupId() == group_id) {
1753 cleared_break_points.push(next_break_point.number());
1754 next_break_point.clear();
1755 } else {
1756 new_script_break_points.push(next_break_point);
1757 }
1758 }
1759 script_break_points = new_script_break_points;
1760
1761 // Add the cleared break point numbers to the response.
1762 response.body = { breakpoints: cleared_break_points };
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001763};
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001764
1765
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001766DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(
1767 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001768 // Check for legal request.
1769 if (!request.arguments) {
1770 response.failed('Missing arguments');
1771 return;
1772 }
1773
1774 // Pull out arguments.
1775 var break_point = %ToNumber(request.arguments.breakpoint);
1776
1777 // Check for legal arguments.
1778 if (!break_point) {
1779 response.failed('Missing argument "breakpoint"');
1780 return;
1781 }
1782
1783 // Clear break point.
1784 Debug.clearBreakPoint(break_point);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001785
1786 // Add the cleared break point number to the response.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001787 response.body = { breakpoint: break_point };
1788};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001789
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001790
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001791DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(
1792 request, response) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001793 var array = [];
1794 for (var i = 0; i < script_break_points.length; i++) {
1795 var break_point = script_break_points[i];
1796
1797 var description = {
1798 number: break_point.number(),
1799 line: break_point.line(),
1800 column: break_point.column(),
1801 groupId: break_point.groupId(),
1802 hit_count: break_point.hit_count(),
1803 active: break_point.active(),
1804 condition: break_point.condition(),
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001805 ignoreCount: break_point.ignoreCount(),
1806 actual_locations: break_point.actual_locations()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001807 };
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001808
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001809 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1810 description.type = 'scriptId';
1811 description.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001812 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001813 description.type = 'scriptName';
1814 description.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001815 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1816 description.type = 'scriptRegExp';
1817 description.script_regexp = break_point.script_regexp_object().source;
1818 } else {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001819 throw new Error("Internal error: Unexpected breakpoint type: " +
1820 break_point.type());
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001821 }
1822 array.push(description);
1823 }
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001824
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001825 response.body = {
1826 breakpoints: array,
1827 breakOnExceptions: Debug.isBreakOnException(),
1828 breakOnUncaughtExceptions: Debug.isBreakOnUncaughtException()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001829 };
1830};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001831
1832
1833DebugCommandProcessor.prototype.disconnectRequest_ =
1834 function(request, response) {
1835 Debug.disableAllBreakPoints();
1836 this.continueRequest_(request, response);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001837};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001838
1839
1840DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
1841 function(request, response) {
1842 // Check for legal request.
1843 if (!request.arguments) {
1844 response.failed('Missing arguments');
1845 return;
1846 }
1847
1848 // Pull out and check the 'type' argument:
1849 var type = request.arguments.type;
1850 if (!type) {
1851 response.failed('Missing argument "type"');
1852 return;
1853 }
1854
1855 // Initialize the default value of enable:
1856 var enabled;
1857 if (type == 'all') {
1858 enabled = !Debug.isBreakOnException();
1859 } else if (type == 'uncaught') {
1860 enabled = !Debug.isBreakOnUncaughtException();
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001861 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001862
1863 // Pull out and check the 'enabled' argument if present:
1864 if (!IS_UNDEFINED(request.arguments.enabled)) {
1865 enabled = request.arguments.enabled;
1866 if ((enabled != true) && (enabled != false)) {
1867 response.failed('Illegal value for "enabled":"' + enabled + '"');
1868 }
1869 }
1870
1871 // Now set the exception break state:
1872 if (type == 'all') {
1873 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, enabled);
1874 } else if (type == 'uncaught') {
1875 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, enabled);
1876 } else {
1877 response.failed('Unknown "type":"' + type + '"');
1878 }
1879
1880 // Add the cleared break point number to the response.
1881 response.body = { 'type': type, 'enabled': enabled };
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001882};
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001883
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001884
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001885DebugCommandProcessor.prototype.backtraceRequest_ = function(
1886 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001887 // Get the number of frames.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001888 var total_frames = this.exec_state_.frameCount();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001889
ager@chromium.org8bb60582008-12-11 12:02:20 +00001890 // Create simple response if there are no frames.
1891 if (total_frames == 0) {
1892 response.body = {
1893 totalFrames: total_frames
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001894 };
ager@chromium.org8bb60582008-12-11 12:02:20 +00001895 return;
1896 }
1897
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001898 // Default frame range to include in backtrace.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001899 var from_index = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001900 var to_index = kDefaultBacktraceLength;
1901
1902 // Get the range from the arguments.
1903 if (request.arguments) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001904 if (request.arguments.fromFrame) {
1905 from_index = request.arguments.fromFrame;
1906 }
1907 if (request.arguments.toFrame) {
1908 to_index = request.arguments.toFrame;
1909 }
1910 if (request.arguments.bottom) {
1911 var tmp_index = total_frames - from_index;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001912 from_index = total_frames - to_index;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001913 to_index = tmp_index;
1914 }
1915 if (from_index < 0 || to_index < 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001916 return response.failed('Invalid frame number');
1917 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001918 }
1919
1920 // Adjust the index.
1921 to_index = Math.min(total_frames, to_index);
1922
1923 if (to_index <= from_index) {
1924 var error = 'Invalid frame range';
1925 return response.failed(error);
1926 }
1927
1928 // Create the response body.
1929 var frames = [];
1930 for (var i = from_index; i < to_index; i++) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001931 frames.push(this.exec_state_.frame(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001932 }
1933 response.body = {
1934 fromFrame: from_index,
1935 toFrame: to_index,
1936 totalFrames: total_frames,
1937 frames: frames
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001938 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001939};
1940
1941
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001943 // No frames no source.
1944 if (this.exec_state_.frameCount() == 0) {
1945 return response.failed('No frames');
1946 }
1947
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001948 // With no arguments just keep the selected frame.
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001949 if (request.arguments) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001950 var index = request.arguments.number;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001951 if (index < 0 || this.exec_state_.frameCount() <= index) {
1952 return response.failed('Invalid frame number');
1953 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001954
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001955 this.exec_state_.setSelectedFrame(request.arguments.number);
1956 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001957 response.body = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001958};
1959
1960
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001961DebugCommandProcessor.prototype.resolveFrameFromScopeDescription_ =
1962 function(scope_description) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001963 // Get the frame for which the scope or scopes are requested.
1964 // With no frameNumber argument use the currently selected frame.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001965 if (scope_description && !IS_UNDEFINED(scope_description.frameNumber)) {
1966 frame_index = scope_description.frameNumber;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001967 if (frame_index < 0 || this.exec_state_.frameCount() <= frame_index) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001968 throw new Error('Invalid frame number');
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001969 }
1970 return this.exec_state_.frame(frame_index);
1971 } else {
1972 return this.exec_state_.frame();
1973 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001974};
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001975
1976
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001977// Gets scope host object from request. It is either a function
1978// ('functionHandle' argument must be specified) or a stack frame
1979// ('frameNumber' may be specified and the current frame is taken by default).
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001980DebugCommandProcessor.prototype.resolveScopeHolder_ =
1981 function(scope_description) {
1982 if (scope_description && "functionHandle" in scope_description) {
1983 if (!IS_NUMBER(scope_description.functionHandle)) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001984 throw new Error('Function handle must be a number');
1985 }
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001986 var function_mirror = LookupMirror(scope_description.functionHandle);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001987 if (!function_mirror) {
1988 throw new Error('Failed to find function object by handle');
1989 }
1990 if (!function_mirror.isFunction()) {
1991 throw new Error('Value of non-function type is found by handle');
1992 }
1993 return function_mirror;
1994 } else {
1995 // No frames no scopes.
1996 if (this.exec_state_.frameCount() == 0) {
1997 throw new Error('No scopes');
1998 }
1999
2000 // Get the frame for which the scopes are requested.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002001 var frame = this.resolveFrameFromScopeDescription_(scope_description);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002002 return frame;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002003 }
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002004}
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002005
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00002006
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002007DebugCommandProcessor.prototype.scopesRequest_ = function(request, response) {
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002008 var scope_holder = this.resolveScopeHolder_(request.arguments);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002009
2010 // Fill all scopes for this frame or function.
2011 var total_scopes = scope_holder.scopeCount();
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002012 var scopes = [];
2013 for (var i = 0; i < total_scopes; i++) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002014 scopes.push(scope_holder.scope(i));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002015 }
2016 response.body = {
2017 fromScope: 0,
2018 toScope: total_scopes,
2019 totalScopes: total_scopes,
2020 scopes: scopes
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002021 };
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002022};
2023
2024
2025DebugCommandProcessor.prototype.scopeRequest_ = function(request, response) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002026 // Get the frame or function for which the scope is requested.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002027 var scope_holder = this.resolveScopeHolder_(request.arguments);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002028
2029 // With no scope argument just return top scope.
2030 var scope_index = 0;
2031 if (request.arguments && !IS_UNDEFINED(request.arguments.number)) {
2032 scope_index = %ToNumber(request.arguments.number);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002033 if (scope_index < 0 || scope_holder.scopeCount() <= scope_index) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002034 return response.failed('Invalid scope number');
2035 }
2036 }
2037
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002038 response.body = scope_holder.scope(scope_index);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002039};
2040
2041
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002042// Reads value from protocol description. Description may be in form of type
2043// (for singletons), raw value (primitive types supported in JSON),
2044// string value description plus type (for primitive values) or handle id.
2045// Returns raw value or throws exception.
2046DebugCommandProcessor.resolveValue_ = function(value_description) {
2047 if ("handle" in value_description) {
2048 var value_mirror = LookupMirror(value_description.handle);
2049 if (!value_mirror) {
2050 throw new Error("Failed to resolve value by handle, ' #" +
2051 mapping.handle + "# not found");
2052 }
2053 return value_mirror.value();
2054 } else if ("stringDescription" in value_description) {
2055 if (value_description.type == BOOLEAN_TYPE) {
2056 return Boolean(value_description.stringDescription);
2057 } else if (value_description.type == NUMBER_TYPE) {
2058 return Number(value_description.stringDescription);
2059 } if (value_description.type == STRING_TYPE) {
2060 return String(value_description.stringDescription);
2061 } else {
2062 throw new Error("Unknown type");
2063 }
2064 } else if ("value" in value_description) {
2065 return value_description.value;
2066 } else if (value_description.type == UNDEFINED_TYPE) {
2067 return void 0;
2068 } else if (value_description.type == NULL_TYPE) {
2069 return null;
2070 } else {
2071 throw new Error("Failed to parse value description");
2072 }
2073};
2074
2075
2076DebugCommandProcessor.prototype.setVariableValueRequest_ =
2077 function(request, response) {
2078 if (!request.arguments) {
2079 response.failed('Missing arguments');
2080 return;
2081 }
2082
2083 if (IS_UNDEFINED(request.arguments.name)) {
2084 response.failed('Missing variable name');
2085 }
2086 var variable_name = request.arguments.name;
2087
2088 var scope_description = request.arguments.scope;
2089
2090 // Get the frame or function for which the scope is requested.
2091 var scope_holder = this.resolveScopeHolder_(scope_description);
2092
2093 if (IS_UNDEFINED(scope_description.number)) {
2094 response.failed('Missing scope number');
2095 }
2096 var scope_index = %ToNumber(scope_description.number);
2097
2098 var scope = scope_holder.scope(scope_index);
2099
2100 var new_value =
2101 DebugCommandProcessor.resolveValue_(request.arguments.newValue);
2102
2103 scope.setVariableValue(variable_name, new_value);
2104
2105 var new_value_mirror = MakeMirror(new_value);
2106
2107 response.body = {
2108 newValue: new_value_mirror
2109 };
2110};
2111
2112
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002113DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
2114 if (!request.arguments) {
2115 return response.failed('Missing arguments');
2116 }
2117
2118 // Pull out arguments.
2119 var expression = request.arguments.expression;
2120 var frame = request.arguments.frame;
2121 var global = request.arguments.global;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002122 var disable_break = request.arguments.disable_break;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002123 var additional_context = request.arguments.additional_context;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002124
2125 // The expression argument could be an integer so we convert it to a
2126 // string.
2127 try {
2128 expression = String(expression);
2129 } catch(e) {
2130 return response.failed('Failed to convert expression argument to string');
2131 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002132
2133 // Check for legal arguments.
2134 if (!IS_UNDEFINED(frame) && global) {
2135 return response.failed('Arguments "frame" and "global" are exclusive');
2136 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002137
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002138 var additional_context_object;
2139 if (additional_context) {
2140 additional_context_object = {};
2141 for (var i = 0; i < additional_context.length; i++) {
2142 var mapping = additional_context[i];
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002143
2144 if (!IS_STRING(mapping.name)) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002145 return response.failed("Context element #" + i +
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002146 " doesn't contain name:string property");
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002147 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002148
2149 var raw_value = DebugCommandProcessor.resolveValue_(mapping);
2150 additional_context_object[mapping.name] = raw_value;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002151 }
2152 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002153
2154 // Global evaluate.
2155 if (global) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002156 // Evaluate in the native context.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002157 response.body = this.exec_state_.evaluateGlobal(
2158 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002159 return;
2160 }
2161
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002162 // Default value for disable_break is true.
2163 if (IS_UNDEFINED(disable_break)) {
2164 disable_break = true;
2165 }
2166
ager@chromium.org381abbb2009-02-25 13:23:22 +00002167 // No frames no evaluate in frame.
2168 if (this.exec_state_.frameCount() == 0) {
2169 return response.failed('No frames');
2170 }
2171
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002172 // Check whether a frame was specified.
2173 if (!IS_UNDEFINED(frame)) {
2174 var frame_number = %ToNumber(frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002175 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002176 return response.failed('Invalid frame "' + frame + '"');
2177 }
2178 // Evaluate in the specified frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002179 response.body = this.exec_state_.frame(frame_number).evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002180 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002181 return;
2182 } else {
2183 // Evaluate in the selected frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002184 response.body = this.exec_state_.frame().evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002185 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002186 return;
2187 }
2188};
2189
2190
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002191DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
2192 if (!request.arguments) {
2193 return response.failed('Missing arguments');
2194 }
2195
2196 // Pull out arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002197 var handles = request.arguments.handles;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002198
2199 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002200 if (IS_UNDEFINED(handles)) {
2201 return response.failed('Argument "handles" missing');
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002202 }
2203
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002204 // Set 'includeSource' option for script lookup.
2205 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2206 includeSource = %ToBoolean(request.arguments.includeSource);
2207 response.setOption('includeSource', includeSource);
2208 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00002209
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002210 // Lookup handles.
2211 var mirrors = {};
2212 for (var i = 0; i < handles.length; i++) {
2213 var handle = handles[i];
2214 var mirror = LookupMirror(handle);
2215 if (!mirror) {
2216 return response.failed('Object #' + handle + '# not found');
2217 }
2218 mirrors[handle] = mirror;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002219 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002220 response.body = mirrors;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002221};
2222
2223
iposva@chromium.org245aa852009-02-10 00:49:54 +00002224DebugCommandProcessor.prototype.referencesRequest_ =
2225 function(request, response) {
2226 if (!request.arguments) {
2227 return response.failed('Missing arguments');
2228 }
2229
2230 // Pull out arguments.
2231 var type = request.arguments.type;
2232 var handle = request.arguments.handle;
2233
2234 // Check for legal arguments.
2235 if (IS_UNDEFINED(type)) {
2236 return response.failed('Argument "type" missing');
2237 }
2238 if (IS_UNDEFINED(handle)) {
2239 return response.failed('Argument "handle" missing');
2240 }
2241 if (type != 'referencedBy' && type != 'constructedBy') {
2242 return response.failed('Invalid type "' + type + '"');
2243 }
2244
2245 // Lookup handle and return objects with references the object.
2246 var mirror = LookupMirror(handle);
2247 if (mirror) {
2248 if (type == 'referencedBy') {
2249 response.body = mirror.referencedBy();
2250 } else {
2251 response.body = mirror.constructedBy();
2252 }
2253 } else {
2254 return response.failed('Object #' + handle + '# not found');
2255 }
2256};
2257
2258
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002259DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00002260 // No frames no source.
2261 if (this.exec_state_.frameCount() == 0) {
2262 return response.failed('No source');
2263 }
2264
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002265 var from_line;
2266 var to_line;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002267 var frame = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002268 if (request.arguments) {
2269 // Pull out arguments.
2270 from_line = request.arguments.fromLine;
2271 to_line = request.arguments.toLine;
2272
2273 if (!IS_UNDEFINED(request.arguments.frame)) {
2274 var frame_number = %ToNumber(request.arguments.frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002275 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002276 return response.failed('Invalid frame "' + frame + '"');
2277 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002278 frame = this.exec_state_.frame(frame_number);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002279 }
2280 }
2281
2282 // Get the script selected.
2283 var script = frame.func().script();
2284 if (!script) {
2285 return response.failed('No source');
2286 }
2287
2288 // Get the source slice and fill it into the response.
2289 var slice = script.sourceSlice(from_line, to_line);
2290 if (!slice) {
2291 return response.failed('Invalid line interval');
2292 }
2293 response.body = {};
2294 response.body.source = slice.sourceText();
2295 response.body.fromLine = slice.from_line;
2296 response.body.toLine = slice.to_line;
2297 response.body.fromPosition = slice.from_position;
2298 response.body.toPosition = slice.to_position;
2299 response.body.totalLines = script.lineCount();
2300};
2301
2302
2303DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
2304 var types = ScriptTypeFlag(Debug.ScriptType.Normal);
ager@chromium.org41826e72009-03-30 13:30:57 +00002305 var includeSource = false;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002306 var idsToInclude = null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002307 if (request.arguments) {
2308 // Pull out arguments.
2309 if (!IS_UNDEFINED(request.arguments.types)) {
2310 types = %ToNumber(request.arguments.types);
2311 if (isNaN(types) || types < 0) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002312 return response.failed('Invalid types "' +
2313 request.arguments.types + '"');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002314 }
2315 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002316
ager@chromium.org41826e72009-03-30 13:30:57 +00002317 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2318 includeSource = %ToBoolean(request.arguments.includeSource);
ager@chromium.org9085a012009-05-11 19:22:57 +00002319 response.setOption('includeSource', includeSource);
ager@chromium.org41826e72009-03-30 13:30:57 +00002320 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002321
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002322 if (IS_ARRAY(request.arguments.ids)) {
2323 idsToInclude = {};
2324 var ids = request.arguments.ids;
2325 for (var i = 0; i < ids.length; i++) {
2326 idsToInclude[ids[i]] = true;
2327 }
2328 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002329
2330 var filterStr = null;
2331 var filterNum = null;
2332 if (!IS_UNDEFINED(request.arguments.filter)) {
2333 var num = %ToNumber(request.arguments.filter);
2334 if (!isNaN(num)) {
2335 filterNum = num;
2336 }
2337 filterStr = request.arguments.filter;
2338 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002339 }
2340
2341 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +00002342 var scripts = %DebugGetLoadedScripts();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002343
2344 response.body = [];
2345
2346 for (var i = 0; i < scripts.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002347 if (idsToInclude && !idsToInclude[scripts[i].id]) {
2348 continue;
2349 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002350 if (filterStr || filterNum) {
2351 var script = scripts[i];
2352 var found = false;
2353 if (filterNum && !found) {
2354 if (script.id && script.id === filterNum) {
2355 found = true;
2356 }
2357 }
2358 if (filterStr && !found) {
2359 if (script.name && script.name.indexOf(filterStr) >= 0) {
2360 found = true;
2361 }
2362 }
2363 if (!found) continue;
2364 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002365 if (types & ScriptTypeFlag(scripts[i].type)) {
ager@chromium.org9085a012009-05-11 19:22:57 +00002366 response.body.push(MakeMirror(scripts[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002367 }
2368 }
2369};
2370
2371
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002372DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
2373 // Get the number of threads.
2374 var total_threads = this.exec_state_.threadCount();
2375
2376 // Get information for all threads.
2377 var threads = [];
2378 for (var i = 0; i < total_threads; i++) {
2379 var details = %GetThreadDetails(this.exec_state_.break_id, i);
2380 var thread_info = { current: details[0],
2381 id: details[1]
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002382 };
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002383 threads.push(thread_info);
2384 }
2385
2386 // Create the response body.
2387 response.body = {
2388 totalThreads: total_threads,
2389 threads: threads
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002390 };
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002391};
2392
2393
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002394DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002395 response.running = false;
2396};
2397
2398
ager@chromium.org3811b432009-10-28 14:53:37 +00002399DebugCommandProcessor.prototype.versionRequest_ = function(request, response) {
2400 response.body = {
2401 V8Version: %GetV8Version()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002402 };
ager@chromium.org3811b432009-10-28 14:53:37 +00002403};
2404
2405
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002406DebugCommandProcessor.prototype.changeLiveRequest_ = function(
2407 request, response) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002408 if (!request.arguments) {
2409 return response.failed('Missing arguments');
2410 }
2411 var script_id = request.arguments.script_id;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002412 var preview_only = !!request.arguments.preview_only;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002413
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002414 var scripts = %DebugGetLoadedScripts();
2415
2416 var the_script = null;
2417 for (var i = 0; i < scripts.length; i++) {
2418 if (scripts[i].id == script_id) {
2419 the_script = scripts[i];
2420 }
2421 }
2422 if (!the_script) {
2423 response.failed('Script not found');
2424 return;
2425 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002426
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002427 var change_log = new Array();
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002428
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002429 if (!IS_STRING(request.arguments.new_source)) {
2430 throw "new_source argument expected";
lrn@chromium.org25156de2010-04-06 13:10:27 +00002431 }
2432
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002433 var new_source = request.arguments.new_source;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002434
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002435 var result_description;
2436 try {
2437 result_description = Debug.LiveEdit.SetScriptSource(the_script,
2438 new_source, preview_only, change_log);
2439 } catch (e) {
2440 if (e instanceof Debug.LiveEdit.Failure && "details" in e) {
2441 response.failed(e.message, e.details);
2442 return;
2443 }
2444 throw e;
2445 }
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002446 response.body = {change_log: change_log, result: result_description};
vegorov@chromium.org42841962010-10-18 11:18:59 +00002447
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002448 if (!preview_only && !this.running_ && result_description.stack_modified) {
2449 response.body.stepin_recommended = true;
2450 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002451};
2452
2453
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002454DebugCommandProcessor.prototype.restartFrameRequest_ = function(
2455 request, response) {
2456 if (!request.arguments) {
2457 return response.failed('Missing arguments');
2458 }
2459 var frame = request.arguments.frame;
2460
2461 // No frames to evaluate in frame.
2462 if (this.exec_state_.frameCount() == 0) {
2463 return response.failed('No frames');
2464 }
2465
2466 var frame_mirror;
2467 // Check whether a frame was specified.
2468 if (!IS_UNDEFINED(frame)) {
2469 var frame_number = %ToNumber(frame);
2470 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
2471 return response.failed('Invalid frame "' + frame + '"');
2472 }
2473 // Restart specified frame.
2474 frame_mirror = this.exec_state_.frame(frame_number);
2475 } else {
2476 // Restart selected frame.
2477 frame_mirror = this.exec_state_.frame();
2478 }
2479
2480 var result_description = Debug.LiveEdit.RestartFrame(frame_mirror);
2481 response.body = {result: result_description};
2482};
2483
2484
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002485DebugCommandProcessor.prototype.debuggerFlagsRequest_ = function(request,
2486 response) {
2487 // Check for legal request.
2488 if (!request.arguments) {
2489 response.failed('Missing arguments');
2490 return;
2491 }
2492
2493 // Pull out arguments.
2494 var flags = request.arguments.flags;
2495
2496 response.body = { flags: [] };
2497 if (!IS_UNDEFINED(flags)) {
2498 for (var i = 0; i < flags.length; i++) {
2499 var name = flags[i].name;
2500 var debugger_flag = debugger_flags[name];
2501 if (!debugger_flag) {
2502 continue;
2503 }
2504 if ('value' in flags[i]) {
2505 debugger_flag.setValue(flags[i].value);
2506 }
2507 response.body.flags.push({ name: name, value: debugger_flag.getValue() });
2508 }
2509 } else {
2510 for (var name in debugger_flags) {
2511 var value = debugger_flags[name].getValue();
2512 response.body.flags.push({ name: name, value: value });
2513 }
2514 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002515};
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002516
2517
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002518DebugCommandProcessor.prototype.v8FlagsRequest_ = function(request, response) {
2519 var flags = request.arguments.flags;
2520 if (!flags) flags = '';
2521 %SetFlags(flags);
2522};
2523
2524
2525DebugCommandProcessor.prototype.gcRequest_ = function(request, response) {
2526 var type = request.arguments.type;
2527 if (!type) type = 'all';
2528
2529 var before = %GetHeapUsage();
2530 %CollectGarbage(type);
2531 var after = %GetHeapUsage();
2532
2533 response.body = { "before": before, "after": after };
2534};
2535
2536
iposva@chromium.org245aa852009-02-10 00:49:54 +00002537// Check whether the previously processed command caused the VM to become
2538// running.
2539DebugCommandProcessor.prototype.isRunning = function() {
2540 return this.running_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002541};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002542
2543
2544DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
mads.s.ager31e71382008-08-13 09:32:07 +00002545 return %SystemBreak();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002546};
2547
2548
2549function NumberToHex8Str(n) {
2550 var r = "";
2551 for (var i = 0; i < 8; ++i) {
2552 var c = hexCharArray[n & 0x0F]; // hexCharArray is defined in uri.js
2553 r = c + r;
2554 n = n >>> 4;
2555 }
2556 return r;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002557}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002558
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002559
2560/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002561 * Convert an Object to its debugger protocol representation. The representation
2562 * may be serilized to a JSON object using JSON.stringify().
2563 * This implementation simply runs through all string property names, converts
2564 * each property value to a protocol value and adds the property to the result
2565 * object. For type "object" the function will be called recursively. Note that
2566 * circular structures will cause infinite recursion.
2567 * @param {Object} object The object to format as protocol object.
ager@chromium.org32912102009-01-16 10:38:43 +00002568 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2569 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002570 * @return {Object} Protocol object value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002571 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002572function ObjectToProtocolObject_(object, mirror_serializer) {
2573 var content = {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002574 for (var key in object) {
2575 // Only consider string keys.
2576 if (typeof key == 'string') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002577 // Format the value based on its type.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002578 var property_value_json = ValueToProtocolValue_(object[key],
2579 mirror_serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002580 // Add the property if relevant.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002581 if (!IS_UNDEFINED(property_value_json)) {
2582 content[key] = property_value_json;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002583 }
2584 }
2585 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002586
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002587 return content;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002588}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002589
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002590
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002591/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002592 * Convert an array to its debugger protocol representation. It will convert
2593 * each array element to a protocol value.
2594 * @param {Array} array The array to format as protocol array.
ager@chromium.org32912102009-01-16 10:38:43 +00002595 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2596 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002597 * @return {Array} Protocol array value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002598 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002599function ArrayToProtocolArray_(array, mirror_serializer) {
2600 var json = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002601 for (var i = 0; i < array.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002602 json.push(ValueToProtocolValue_(array[i], mirror_serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002603 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002604 return json;
2605}
2606
2607
2608/**
lrn@chromium.org25156de2010-04-06 13:10:27 +00002609 * Convert a value to its debugger protocol representation.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002610 * @param {*} value The value to format as protocol value.
2611 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2612 * mirror objects are encountered.
2613 * @return {*} Protocol value.
2614 */
2615function ValueToProtocolValue_(value, mirror_serializer) {
2616 // Format the value based on its type.
2617 var json;
2618 switch (typeof value) {
2619 case 'object':
2620 if (value instanceof Mirror) {
2621 json = mirror_serializer.serializeValue(value);
2622 } else if (IS_ARRAY(value)){
2623 json = ArrayToProtocolArray_(value, mirror_serializer);
2624 } else {
2625 json = ObjectToProtocolObject_(value, mirror_serializer);
2626 }
2627 break;
2628
2629 case 'boolean':
2630 case 'string':
2631 case 'number':
2632 json = value;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002633 break;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002634
2635 default:
2636 json = null;
2637 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002638 return json;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002639}
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002640
2641Debug.TestApi = {
2642 CommandProcessorResolveValue: DebugCommandProcessor.resolveValue_
2643};