blob: 88efbe212af13330561b60f0e3dff36fdf4e3e05 [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
960ExecutionState.prototype.prepareStep = function(opt_action, opt_count) {
961 var action = Debug.StepAction.StepIn;
962 if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
963 var count = opt_count ? %ToNumber(opt_count) : 1;
964
965 return %PrepareStep(this.break_id, action, count);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000966};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000967
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000968ExecutionState.prototype.evaluateGlobal = function(source, disable_break,
969 opt_additional_context) {
970 return MakeMirror(%DebugEvaluateGlobal(this.break_id, source,
971 Boolean(disable_break),
972 opt_additional_context));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973};
974
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000975ExecutionState.prototype.frameCount = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000976 return %GetFrameCount(this.break_id);
977};
978
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000979ExecutionState.prototype.threadCount = function() {
980 return %GetThreadCount(this.break_id);
981};
982
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000983ExecutionState.prototype.frame = function(opt_index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000984 // If no index supplied return the selected frame.
985 if (opt_index == null) opt_index = this.selected_frame;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000986 if (opt_index < 0 || opt_index >= this.frameCount()) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000987 throw new Error('Illegal frame index.');
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000988 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000989 return new FrameMirror(this.break_id, opt_index);
990};
991
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000992ExecutionState.prototype.setSelectedFrame = function(index) {
993 var i = %ToNumber(index);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000994 if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995 this.selected_frame = i;
996};
997
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000998ExecutionState.prototype.selectedFrame = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000999 return this.selected_frame;
1000};
1001
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001002ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) {
1003 return new DebugCommandProcessor(this, opt_is_running);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001004};
1005
1006
1007function MakeBreakEvent(exec_state, break_points_hit) {
1008 return new BreakEvent(exec_state, break_points_hit);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001009}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001010
1011
1012function BreakEvent(exec_state, break_points_hit) {
1013 this.exec_state_ = exec_state;
1014 this.break_points_hit_ = break_points_hit;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001015}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001016
1017
ager@chromium.org8bb60582008-12-11 12:02:20 +00001018BreakEvent.prototype.executionState = function() {
1019 return this.exec_state_;
1020};
1021
1022
1023BreakEvent.prototype.eventType = function() {
1024 return Debug.DebugEvent.Break;
1025};
1026
1027
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001028BreakEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001029 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001030};
1031
1032
1033BreakEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001034 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001035};
1036
1037
1038BreakEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001039 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001040};
1041
1042
1043BreakEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001044 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045};
1046
1047
1048BreakEvent.prototype.breakPointsHit = function() {
1049 return this.break_points_hit_;
1050};
1051
1052
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001053BreakEvent.prototype.toJSONProtocol = function() {
1054 var o = { seq: next_response_seq++,
1055 type: "event",
1056 event: "break",
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001057 body: { invocationText: this.exec_state_.frame(0).invocationText(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001059 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001060
1061 // Add script related information to the event if available.
1062 var script = this.func().script();
1063 if (script) {
1064 o.body.sourceLine = this.sourceLine(),
1065 o.body.sourceColumn = this.sourceColumn(),
1066 o.body.sourceLineText = this.sourceLineText(),
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001067 o.body.script = MakeScriptObject_(script, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001068 }
1069
1070 // Add an Array of break points hit if any.
1071 if (this.breakPointsHit()) {
1072 o.body.breakpoints = [];
1073 for (var i = 0; i < this.breakPointsHit().length; i++) {
1074 // Find the break point number. For break points originating from a
1075 // script break point supply the script break point number.
1076 var breakpoint = this.breakPointsHit()[i];
1077 var script_break_point = breakpoint.script_break_point();
1078 var number;
1079 if (script_break_point) {
1080 number = script_break_point.number();
1081 } else {
1082 number = breakpoint.number();
1083 }
1084 o.body.breakpoints.push(number);
1085 }
1086 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001087 return JSON.stringify(ObjectToProtocolObject_(o));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088};
1089
1090
1091function MakeExceptionEvent(exec_state, exception, uncaught) {
1092 return new ExceptionEvent(exec_state, exception, uncaught);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001093}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094
ager@chromium.org8bb60582008-12-11 12:02:20 +00001095
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001096function ExceptionEvent(exec_state, exception, uncaught) {
1097 this.exec_state_ = exec_state;
1098 this.exception_ = exception;
1099 this.uncaught_ = uncaught;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001100}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101
ager@chromium.org8bb60582008-12-11 12:02:20 +00001102
1103ExceptionEvent.prototype.executionState = function() {
1104 return this.exec_state_;
1105};
1106
1107
1108ExceptionEvent.prototype.eventType = function() {
1109 return Debug.DebugEvent.Exception;
1110};
1111
1112
1113ExceptionEvent.prototype.exception = function() {
1114 return this.exception_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001115};
ager@chromium.org8bb60582008-12-11 12:02:20 +00001116
1117
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001118ExceptionEvent.prototype.uncaught = function() {
1119 return this.uncaught_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001120};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121
ager@chromium.org8bb60582008-12-11 12:02:20 +00001122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123ExceptionEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001124 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001125};
1126
1127
1128ExceptionEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001129 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130};
1131
1132
1133ExceptionEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001134 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135};
1136
1137
1138ExceptionEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001139 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140};
1141
1142
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001143ExceptionEvent.prototype.toJSONProtocol = function() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001144 var o = new ProtocolMessage();
1145 o.event = "exception";
1146 o.body = { uncaught: this.uncaught_,
1147 exception: MakeMirror(this.exception_)
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001148 };
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001149
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001150 // Exceptions might happen whithout any JavaScript frames.
1151 if (this.exec_state_.frameCount() > 0) {
1152 o.body.sourceLine = this.sourceLine();
1153 o.body.sourceColumn = this.sourceColumn();
1154 o.body.sourceLineText = this.sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001155
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001156 // Add script information to the event if available.
1157 var script = this.func().script();
1158 if (script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001159 o.body.script = MakeScriptObject_(script, false);
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001160 }
1161 } else {
1162 o.body.sourceLine = -1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001163 }
1164
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001165 return o.toJSONProtocol();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001166};
1167
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001168
iposva@chromium.org245aa852009-02-10 00:49:54 +00001169function MakeCompileEvent(exec_state, script, before) {
1170 return new CompileEvent(exec_state, script, before);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001171}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001173
iposva@chromium.org245aa852009-02-10 00:49:54 +00001174function CompileEvent(exec_state, script, before) {
1175 this.exec_state_ = exec_state;
1176 this.script_ = MakeMirror(script);
1177 this.before_ = before;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001178}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001179
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001180
iposva@chromium.org245aa852009-02-10 00:49:54 +00001181CompileEvent.prototype.executionState = function() {
1182 return this.exec_state_;
1183};
1184
1185
ager@chromium.org8bb60582008-12-11 12:02:20 +00001186CompileEvent.prototype.eventType = function() {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001187 if (this.before_) {
1188 return Debug.DebugEvent.BeforeCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001189 } else {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001190 return Debug.DebugEvent.AfterCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001191 }
1192};
1193
1194
iposva@chromium.org245aa852009-02-10 00:49:54 +00001195CompileEvent.prototype.script = function() {
1196 return this.script_;
1197};
1198
1199
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001200CompileEvent.prototype.toJSONProtocol = function() {
1201 var o = new ProtocolMessage();
ager@chromium.org5ec48922009-05-05 07:25:34 +00001202 o.running = true;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001203 if (this.before_) {
1204 o.event = "beforeCompile";
1205 } else {
1206 o.event = "afterCompile";
1207 }
1208 o.body = {};
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001209 o.body.script = this.script_;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001210
1211 return o.toJSONProtocol();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001212};
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001213
1214
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001215function MakeNewFunctionEvent(func) {
1216 return new NewFunctionEvent(func);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001217}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001218
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001219
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001220function NewFunctionEvent(func) {
1221 this.func = func;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001222}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001223
ager@chromium.org8bb60582008-12-11 12:02:20 +00001224
1225NewFunctionEvent.prototype.eventType = function() {
1226 return Debug.DebugEvent.NewFunction;
1227};
1228
1229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001230NewFunctionEvent.prototype.name = function() {
1231 return this.func.name;
1232};
1233
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001234
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001235NewFunctionEvent.prototype.setBreakPoint = function(p) {
1236 Debug.setBreakPoint(this.func, p || 0);
1237};
1238
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001239
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001240function MakeScriptCollectedEvent(exec_state, id) {
1241 return new ScriptCollectedEvent(exec_state, id);
1242}
1243
1244
1245function ScriptCollectedEvent(exec_state, id) {
1246 this.exec_state_ = exec_state;
1247 this.id_ = id;
1248}
1249
1250
1251ScriptCollectedEvent.prototype.id = function() {
1252 return this.id_;
1253};
1254
1255
1256ScriptCollectedEvent.prototype.executionState = function() {
1257 return this.exec_state_;
1258};
1259
1260
1261ScriptCollectedEvent.prototype.toJSONProtocol = function() {
1262 var o = new ProtocolMessage();
1263 o.running = true;
1264 o.event = "scriptCollected";
1265 o.body = {};
1266 o.body.script = { id: this.id() };
1267 return o.toJSONProtocol();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001268};
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001269
1270
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001271function MakeScriptObject_(script, include_source) {
1272 var o = { id: script.id(),
1273 name: script.name(),
1274 lineOffset: script.lineOffset(),
1275 columnOffset: script.columnOffset(),
1276 lineCount: script.lineCount(),
1277 };
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001278 if (!IS_UNDEFINED(script.data())) {
1279 o.data = script.data();
1280 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001281 if (include_source) {
1282 o.source = script.source();
1283 }
1284 return o;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001285}
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001286
1287
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001288function DebugCommandProcessor(exec_state, opt_is_running) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001289 this.exec_state_ = exec_state;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001290 this.running_ = opt_is_running || false;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001291}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001292
1293
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001294DebugCommandProcessor.prototype.processDebugRequest = function (request) {
1295 return this.processDebugJSONRequest(request);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001296};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297
1298
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001299function ProtocolMessage(request) {
1300 // Update sequence number.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001301 this.seq = next_response_seq++;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001302
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001303 if (request) {
1304 // If message is based on a request this is a response. Fill the initial
1305 // response from the request.
1306 this.type = 'response';
1307 this.request_seq = request.seq;
1308 this.command = request.command;
1309 } else {
1310 // If message is not based on a request it is a dabugger generated event.
1311 this.type = 'event';
1312 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001313 this.success = true;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001314 // Handler may set this field to control debugger state.
1315 this.running = undefined;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001316}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001317
1318
ager@chromium.org9085a012009-05-11 19:22:57 +00001319ProtocolMessage.prototype.setOption = function(name, value) {
1320 if (!this.options_) {
1321 this.options_ = {};
1322 }
1323 this.options_[name] = value;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001324};
ager@chromium.org9085a012009-05-11 19:22:57 +00001325
1326
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001327ProtocolMessage.prototype.failed = function(message, opt_details) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001328 this.success = false;
1329 this.message = message;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001330 if (IS_OBJECT(opt_details)) {
1331 this.error_details = opt_details;
1332 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001333};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001334
1335
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001336ProtocolMessage.prototype.toJSONProtocol = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337 // Encode the protocol header.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001338 var json = {};
1339 json.seq= this.seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001340 if (this.request_seq) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001341 json.request_seq = this.request_seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001342 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001343 json.type = this.type;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001344 if (this.event) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001345 json.event = this.event;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001346 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001347 if (this.command) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001348 json.command = this.command;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001349 }
1350 if (this.success) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001351 json.success = this.success;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001352 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001353 json.success = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354 }
1355 if (this.body) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356 // Encode the body part.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001357 var bodyJson;
ager@chromium.org9085a012009-05-11 19:22:57 +00001358 var serializer = MakeMirrorSerializer(true, this.options_);
ager@chromium.org32912102009-01-16 10:38:43 +00001359 if (this.body instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001360 bodyJson = serializer.serializeValue(this.body);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361 } else if (this.body instanceof Array) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001362 bodyJson = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001363 for (var i = 0; i < this.body.length; i++) {
ager@chromium.org32912102009-01-16 10:38:43 +00001364 if (this.body[i] instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001365 bodyJson.push(serializer.serializeValue(this.body[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001366 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001367 bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001368 }
1369 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001370 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001371 bodyJson = ObjectToProtocolObject_(this.body, serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001372 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001373 json.body = bodyJson;
1374 json.refs = serializer.serializeReferencedObjects();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001375 }
1376 if (this.message) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001377 json.message = this.message;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001378 }
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001379 if (this.error_details) {
1380 json.error_details = this.error_details;
1381 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001382 json.running = this.running;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001383 return JSON.stringify(json);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001384};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001385
1386
1387DebugCommandProcessor.prototype.createResponse = function(request) {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001388 return new ProtocolMessage(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389};
1390
1391
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001392DebugCommandProcessor.prototype.processDebugJSONRequest = function(
1393 json_request) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394 var request; // Current request.
1395 var response; // Generated response.
1396 try {
1397 try {
1398 // Convert the JSON string to an object.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001399 request = JSON.parse(json_request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001400
1401 // Create an initial response.
1402 response = this.createResponse(request);
1403
1404 if (!request.type) {
1405 throw new Error('Type not specified');
1406 }
1407
1408 if (request.type != 'request') {
1409 throw new Error("Illegal type '" + request.type + "' in request");
1410 }
1411
1412 if (!request.command) {
1413 throw new Error('Command not specified');
1414 }
1415
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001416 if (request.arguments) {
1417 var args = request.arguments;
1418 // TODO(yurys): remove request.arguments.compactFormat check once
1419 // ChromeDevTools are switched to 'inlineRefs'
1420 if (args.inlineRefs || args.compactFormat) {
1421 response.setOption('inlineRefs', true);
1422 }
1423 if (!IS_UNDEFINED(args.maxStringLength)) {
1424 response.setOption('maxStringLength', args.maxStringLength);
1425 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001426 }
1427
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001428 if (request.command == 'continue') {
1429 this.continueRequest_(request, response);
1430 } else if (request.command == 'break') {
1431 this.breakRequest_(request, response);
1432 } else if (request.command == 'setbreakpoint') {
1433 this.setBreakPointRequest_(request, response);
1434 } else if (request.command == 'changebreakpoint') {
1435 this.changeBreakPointRequest_(request, response);
1436 } else if (request.command == 'clearbreakpoint') {
1437 this.clearBreakPointRequest_(request, response);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001438 } else if (request.command == 'clearbreakpointgroup') {
1439 this.clearBreakPointGroupRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001440 } else if (request.command == 'disconnect') {
1441 this.disconnectRequest_(request, response);
1442 } else if (request.command == 'setexceptionbreak') {
1443 this.setExceptionBreakRequest_(request, response);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001444 } else if (request.command == 'listbreakpoints') {
1445 this.listBreakpointsRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001446 } else if (request.command == 'backtrace') {
1447 this.backtraceRequest_(request, response);
1448 } else if (request.command == 'frame') {
1449 this.frameRequest_(request, response);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001450 } else if (request.command == 'scopes') {
1451 this.scopesRequest_(request, response);
1452 } else if (request.command == 'scope') {
1453 this.scopeRequest_(request, response);
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001454 } else if (request.command == 'setVariableValue') {
1455 this.setVariableValueRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456 } else if (request.command == 'evaluate') {
1457 this.evaluateRequest_(request, response);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001458 } else if (request.command == 'lookup') {
1459 this.lookupRequest_(request, response);
iposva@chromium.org245aa852009-02-10 00:49:54 +00001460 } else if (request.command == 'references') {
1461 this.referencesRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462 } else if (request.command == 'source') {
1463 this.sourceRequest_(request, response);
1464 } else if (request.command == 'scripts') {
1465 this.scriptsRequest_(request, response);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001466 } else if (request.command == 'threads') {
1467 this.threadsRequest_(request, response);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001468 } else if (request.command == 'suspend') {
1469 this.suspendRequest_(request, response);
ager@chromium.org3811b432009-10-28 14:53:37 +00001470 } else if (request.command == 'version') {
1471 this.versionRequest_(request, response);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001472 } else if (request.command == 'profile') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001473 this.profileRequest_(request, response);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001474 } else if (request.command == 'changelive') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001475 this.changeLiveRequest_(request, response);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001476 } else if (request.command == 'restartframe') {
1477 this.restartFrameRequest_(request, response);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001478 } else if (request.command == 'flags') {
1479 this.debuggerFlagsRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001480 } else if (request.command == 'v8flags') {
1481 this.v8FlagsRequest_(request, response);
1482
1483 // GC tools:
1484 } else if (request.command == 'gc') {
1485 this.gcRequest_(request, response);
1486
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001487 } else {
1488 throw new Error('Unknown command "' + request.command + '" in request');
1489 }
1490 } catch (e) {
1491 // If there is no response object created one (without command).
1492 if (!response) {
1493 response = this.createResponse();
1494 }
1495 response.success = false;
1496 response.message = %ToString(e);
1497 }
1498
1499 // Return the response as a JSON encoded string.
1500 try {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001501 if (!IS_UNDEFINED(response.running)) {
1502 // Response controls running state.
1503 this.running_ = response.running;
1504 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00001505 response.running = this.running_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001506 return response.toJSONProtocol();
1507 } catch (e) {
1508 // Failed to generate response - return generic error.
1509 return '{"seq":' + response.seq + ',' +
1510 '"request_seq":' + request.seq + ',' +
1511 '"type":"response",' +
1512 '"success":false,' +
1513 '"message":"Internal error: ' + %ToString(e) + '"}';
1514 }
1515 } catch (e) {
1516 // Failed in one of the catch blocks above - most generic error.
1517 return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
1518 }
1519};
1520
1521
1522DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
1523 // Check for arguments for continue.
1524 if (request.arguments) {
1525 var count = 1;
1526 var action = Debug.StepAction.StepIn;
1527
1528 // Pull out arguments.
1529 var stepaction = request.arguments.stepaction;
1530 var stepcount = request.arguments.stepcount;
1531
1532 // Get the stepcount argument if any.
1533 if (stepcount) {
1534 count = %ToNumber(stepcount);
1535 if (count < 0) {
1536 throw new Error('Invalid stepcount argument "' + stepcount + '".');
1537 }
1538 }
1539
1540 // Get the stepaction argument.
1541 if (stepaction) {
1542 if (stepaction == 'in') {
1543 action = Debug.StepAction.StepIn;
1544 } else if (stepaction == 'min') {
1545 action = Debug.StepAction.StepMin;
1546 } else if (stepaction == 'next') {
1547 action = Debug.StepAction.StepNext;
1548 } else if (stepaction == 'out') {
1549 action = Debug.StepAction.StepOut;
1550 } else {
1551 throw new Error('Invalid stepaction argument "' + stepaction + '".');
1552 }
1553 }
1554
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001555 // Set up the VM for stepping.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001556 this.exec_state_.prepareStep(action, count);
1557 }
1558
1559 // VM should be running after executing this request.
1560 response.running = true;
1561};
1562
1563
1564DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
1565 // Ignore as break command does not do anything when broken.
1566};
1567
1568
1569DebugCommandProcessor.prototype.setBreakPointRequest_ =
1570 function(request, response) {
1571 // Check for legal request.
1572 if (!request.arguments) {
1573 response.failed('Missing arguments');
1574 return;
1575 }
1576
1577 // Pull out arguments.
1578 var type = request.arguments.type;
1579 var target = request.arguments.target;
1580 var line = request.arguments.line;
1581 var column = request.arguments.column;
1582 var enabled = IS_UNDEFINED(request.arguments.enabled) ?
1583 true : request.arguments.enabled;
1584 var condition = request.arguments.condition;
1585 var ignoreCount = request.arguments.ignoreCount;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001586 var groupId = request.arguments.groupId;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001587
1588 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001589 if (!type || IS_UNDEFINED(target)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001590 response.failed('Missing argument "type" or "target"');
1591 return;
1592 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001593
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001594 // Either function or script break point.
1595 var break_point_number;
1596 if (type == 'function') {
1597 // Handle function break point.
1598 if (!IS_STRING(target)) {
1599 response.failed('Argument "target" is not a string value');
1600 return;
1601 }
1602 var f;
1603 try {
1604 // Find the function through a global evaluate.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001605 f = this.exec_state_.evaluateGlobal(target).value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001606 } catch (e) {
1607 response.failed('Error: "' + %ToString(e) +
1608 '" evaluating "' + target + '"');
1609 return;
1610 }
1611 if (!IS_FUNCTION(f)) {
1612 response.failed('"' + target + '" does not evaluate to a function');
1613 return;
1614 }
1615
1616 // Set function break point.
1617 break_point_number = Debug.setBreakPoint(f, line, column, condition);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001618 } else if (type == 'handle') {
1619 // Find the object pointed by the specified handle.
1620 var handle = parseInt(target, 10);
1621 var mirror = LookupMirror(handle);
1622 if (!mirror) {
1623 return response.failed('Object #' + handle + '# not found');
1624 }
1625 if (!mirror.isFunction()) {
1626 return response.failed('Object #' + handle + '# is not a function');
1627 }
1628
1629 // Set function break point.
1630 break_point_number = Debug.setBreakPoint(mirror.value(),
1631 line, column, condition);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001632 } else if (type == 'script') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633 // set script break point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001634 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001635 Debug.setScriptBreakPointByName(target, line, column, condition,
1636 groupId);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001637 } else if (type == 'scriptId') {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001638 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001639 Debug.setScriptBreakPointById(target, line, column, condition, groupId);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001640 } else if (type == 'scriptRegExp') {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001641 break_point_number =
1642 Debug.setScriptBreakPointByRegExp(target, line, column, condition,
1643 groupId);
1644 } else {
1645 response.failed('Illegal type "' + type + '"');
1646 return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001647 }
1648
1649 // Set additional break point properties.
1650 var break_point = Debug.findBreakPoint(break_point_number);
1651 if (ignoreCount) {
1652 Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
1653 }
1654 if (!enabled) {
1655 Debug.disableBreakPoint(break_point_number);
1656 }
1657
1658 // Add the break point number to the response.
1659 response.body = { type: type,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001660 breakpoint: break_point_number };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001661
1662 // Add break point information to the response.
1663 if (break_point instanceof ScriptBreakPoint) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001664 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1665 response.body.type = 'scriptId';
1666 response.body.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001667 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001668 response.body.type = 'scriptName';
1669 response.body.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001670 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1671 response.body.type = 'scriptRegExp';
1672 response.body.script_regexp = break_point.script_regexp_object().source;
1673 } else {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001674 throw new Error("Internal error: Unexpected breakpoint type: " +
1675 break_point.type());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001676 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001677 response.body.line = break_point.line();
1678 response.body.column = break_point.column();
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001679 response.body.actual_locations = break_point.actual_locations();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001680 } else {
1681 response.body.type = 'function';
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001682 response.body.actual_locations = [break_point.actual_location];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001683 }
1684};
1685
1686
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001687DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(
1688 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001689 // Check for legal request.
1690 if (!request.arguments) {
1691 response.failed('Missing arguments');
1692 return;
1693 }
1694
1695 // Pull out arguments.
1696 var break_point = %ToNumber(request.arguments.breakpoint);
1697 var enabled = request.arguments.enabled;
1698 var condition = request.arguments.condition;
1699 var ignoreCount = request.arguments.ignoreCount;
1700
1701 // Check for legal arguments.
1702 if (!break_point) {
1703 response.failed('Missing argument "breakpoint"');
1704 return;
1705 }
1706
1707 // Change enabled state if supplied.
1708 if (!IS_UNDEFINED(enabled)) {
1709 if (enabled) {
1710 Debug.enableBreakPoint(break_point);
1711 } else {
1712 Debug.disableBreakPoint(break_point);
1713 }
1714 }
1715
1716 // Change condition if supplied
1717 if (!IS_UNDEFINED(condition)) {
1718 Debug.changeBreakPointCondition(break_point, condition);
1719 }
1720
1721 // Change ignore count if supplied
1722 if (!IS_UNDEFINED(ignoreCount)) {
1723 Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
1724 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001725};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001726
1727
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001728DebugCommandProcessor.prototype.clearBreakPointGroupRequest_ = function(
1729 request, response) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001730 // Check for legal request.
1731 if (!request.arguments) {
1732 response.failed('Missing arguments');
1733 return;
1734 }
1735
1736 // Pull out arguments.
1737 var group_id = request.arguments.groupId;
1738
1739 // Check for legal arguments.
1740 if (!group_id) {
1741 response.failed('Missing argument "groupId"');
1742 return;
1743 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001744
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001745 var cleared_break_points = [];
1746 var new_script_break_points = [];
1747 for (var i = 0; i < script_break_points.length; i++) {
1748 var next_break_point = script_break_points[i];
1749 if (next_break_point.groupId() == group_id) {
1750 cleared_break_points.push(next_break_point.number());
1751 next_break_point.clear();
1752 } else {
1753 new_script_break_points.push(next_break_point);
1754 }
1755 }
1756 script_break_points = new_script_break_points;
1757
1758 // Add the cleared break point numbers to the response.
1759 response.body = { breakpoints: cleared_break_points };
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001760};
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001761
1762
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001763DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(
1764 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001765 // Check for legal request.
1766 if (!request.arguments) {
1767 response.failed('Missing arguments');
1768 return;
1769 }
1770
1771 // Pull out arguments.
1772 var break_point = %ToNumber(request.arguments.breakpoint);
1773
1774 // Check for legal arguments.
1775 if (!break_point) {
1776 response.failed('Missing argument "breakpoint"');
1777 return;
1778 }
1779
1780 // Clear break point.
1781 Debug.clearBreakPoint(break_point);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001782
1783 // Add the cleared break point number to the response.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001784 response.body = { breakpoint: break_point };
1785};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001786
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001787
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001788DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(
1789 request, response) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001790 var array = [];
1791 for (var i = 0; i < script_break_points.length; i++) {
1792 var break_point = script_break_points[i];
1793
1794 var description = {
1795 number: break_point.number(),
1796 line: break_point.line(),
1797 column: break_point.column(),
1798 groupId: break_point.groupId(),
1799 hit_count: break_point.hit_count(),
1800 active: break_point.active(),
1801 condition: break_point.condition(),
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001802 ignoreCount: break_point.ignoreCount(),
1803 actual_locations: break_point.actual_locations()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001804 };
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001805
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001806 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1807 description.type = 'scriptId';
1808 description.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001809 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001810 description.type = 'scriptName';
1811 description.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001812 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1813 description.type = 'scriptRegExp';
1814 description.script_regexp = break_point.script_regexp_object().source;
1815 } else {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001816 throw new Error("Internal error: Unexpected breakpoint type: " +
1817 break_point.type());
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001818 }
1819 array.push(description);
1820 }
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001821
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001822 response.body = {
1823 breakpoints: array,
1824 breakOnExceptions: Debug.isBreakOnException(),
1825 breakOnUncaughtExceptions: Debug.isBreakOnUncaughtException()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001826 };
1827};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001828
1829
1830DebugCommandProcessor.prototype.disconnectRequest_ =
1831 function(request, response) {
1832 Debug.disableAllBreakPoints();
1833 this.continueRequest_(request, response);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001834};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001835
1836
1837DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
1838 function(request, response) {
1839 // Check for legal request.
1840 if (!request.arguments) {
1841 response.failed('Missing arguments');
1842 return;
1843 }
1844
1845 // Pull out and check the 'type' argument:
1846 var type = request.arguments.type;
1847 if (!type) {
1848 response.failed('Missing argument "type"');
1849 return;
1850 }
1851
1852 // Initialize the default value of enable:
1853 var enabled;
1854 if (type == 'all') {
1855 enabled = !Debug.isBreakOnException();
1856 } else if (type == 'uncaught') {
1857 enabled = !Debug.isBreakOnUncaughtException();
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001858 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001859
1860 // Pull out and check the 'enabled' argument if present:
1861 if (!IS_UNDEFINED(request.arguments.enabled)) {
1862 enabled = request.arguments.enabled;
1863 if ((enabled != true) && (enabled != false)) {
1864 response.failed('Illegal value for "enabled":"' + enabled + '"');
1865 }
1866 }
1867
1868 // Now set the exception break state:
1869 if (type == 'all') {
1870 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, enabled);
1871 } else if (type == 'uncaught') {
1872 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, enabled);
1873 } else {
1874 response.failed('Unknown "type":"' + type + '"');
1875 }
1876
1877 // Add the cleared break point number to the response.
1878 response.body = { 'type': type, 'enabled': enabled };
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001879};
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001880
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001881
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001882DebugCommandProcessor.prototype.backtraceRequest_ = function(
1883 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001884 // Get the number of frames.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001885 var total_frames = this.exec_state_.frameCount();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001886
ager@chromium.org8bb60582008-12-11 12:02:20 +00001887 // Create simple response if there are no frames.
1888 if (total_frames == 0) {
1889 response.body = {
1890 totalFrames: total_frames
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001891 };
ager@chromium.org8bb60582008-12-11 12:02:20 +00001892 return;
1893 }
1894
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001895 // Default frame range to include in backtrace.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001896 var from_index = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001897 var to_index = kDefaultBacktraceLength;
1898
1899 // Get the range from the arguments.
1900 if (request.arguments) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001901 if (request.arguments.fromFrame) {
1902 from_index = request.arguments.fromFrame;
1903 }
1904 if (request.arguments.toFrame) {
1905 to_index = request.arguments.toFrame;
1906 }
1907 if (request.arguments.bottom) {
1908 var tmp_index = total_frames - from_index;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001909 from_index = total_frames - to_index;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001910 to_index = tmp_index;
1911 }
1912 if (from_index < 0 || to_index < 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001913 return response.failed('Invalid frame number');
1914 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001915 }
1916
1917 // Adjust the index.
1918 to_index = Math.min(total_frames, to_index);
1919
1920 if (to_index <= from_index) {
1921 var error = 'Invalid frame range';
1922 return response.failed(error);
1923 }
1924
1925 // Create the response body.
1926 var frames = [];
1927 for (var i = from_index; i < to_index; i++) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001928 frames.push(this.exec_state_.frame(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001929 }
1930 response.body = {
1931 fromFrame: from_index,
1932 toFrame: to_index,
1933 totalFrames: total_frames,
1934 frames: frames
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001935 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001936};
1937
1938
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001939DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001940 // No frames no source.
1941 if (this.exec_state_.frameCount() == 0) {
1942 return response.failed('No frames');
1943 }
1944
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001945 // With no arguments just keep the selected frame.
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001946 if (request.arguments) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001947 var index = request.arguments.number;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001948 if (index < 0 || this.exec_state_.frameCount() <= index) {
1949 return response.failed('Invalid frame number');
1950 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001951
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001952 this.exec_state_.setSelectedFrame(request.arguments.number);
1953 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001954 response.body = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001955};
1956
1957
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001958DebugCommandProcessor.prototype.resolveFrameFromScopeDescription_ =
1959 function(scope_description) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001960 // Get the frame for which the scope or scopes are requested.
1961 // With no frameNumber argument use the currently selected frame.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001962 if (scope_description && !IS_UNDEFINED(scope_description.frameNumber)) {
1963 frame_index = scope_description.frameNumber;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001964 if (frame_index < 0 || this.exec_state_.frameCount() <= frame_index) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001965 throw new Error('Invalid frame number');
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001966 }
1967 return this.exec_state_.frame(frame_index);
1968 } else {
1969 return this.exec_state_.frame();
1970 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001971};
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001972
1973
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001974// Gets scope host object from request. It is either a function
1975// ('functionHandle' argument must be specified) or a stack frame
1976// ('frameNumber' may be specified and the current frame is taken by default).
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001977DebugCommandProcessor.prototype.resolveScopeHolder_ =
1978 function(scope_description) {
1979 if (scope_description && "functionHandle" in scope_description) {
1980 if (!IS_NUMBER(scope_description.functionHandle)) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001981 throw new Error('Function handle must be a number');
1982 }
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001983 var function_mirror = LookupMirror(scope_description.functionHandle);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001984 if (!function_mirror) {
1985 throw new Error('Failed to find function object by handle');
1986 }
1987 if (!function_mirror.isFunction()) {
1988 throw new Error('Value of non-function type is found by handle');
1989 }
1990 return function_mirror;
1991 } else {
1992 // No frames no scopes.
1993 if (this.exec_state_.frameCount() == 0) {
1994 throw new Error('No scopes');
1995 }
1996
1997 // Get the frame for which the scopes are requested.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001998 var frame = this.resolveFrameFromScopeDescription_(scope_description);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001999 return frame;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002000 }
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002001}
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002002
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00002003
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002004DebugCommandProcessor.prototype.scopesRequest_ = function(request, response) {
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002005 var scope_holder = this.resolveScopeHolder_(request.arguments);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002006
2007 // Fill all scopes for this frame or function.
2008 var total_scopes = scope_holder.scopeCount();
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002009 var scopes = [];
2010 for (var i = 0; i < total_scopes; i++) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002011 scopes.push(scope_holder.scope(i));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002012 }
2013 response.body = {
2014 fromScope: 0,
2015 toScope: total_scopes,
2016 totalScopes: total_scopes,
2017 scopes: scopes
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002018 };
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002019};
2020
2021
2022DebugCommandProcessor.prototype.scopeRequest_ = function(request, response) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002023 // Get the frame or function for which the scope is requested.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002024 var scope_holder = this.resolveScopeHolder_(request.arguments);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002025
2026 // With no scope argument just return top scope.
2027 var scope_index = 0;
2028 if (request.arguments && !IS_UNDEFINED(request.arguments.number)) {
2029 scope_index = %ToNumber(request.arguments.number);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002030 if (scope_index < 0 || scope_holder.scopeCount() <= scope_index) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002031 return response.failed('Invalid scope number');
2032 }
2033 }
2034
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002035 response.body = scope_holder.scope(scope_index);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002036};
2037
2038
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002039// Reads value from protocol description. Description may be in form of type
2040// (for singletons), raw value (primitive types supported in JSON),
2041// string value description plus type (for primitive values) or handle id.
2042// Returns raw value or throws exception.
2043DebugCommandProcessor.resolveValue_ = function(value_description) {
2044 if ("handle" in value_description) {
2045 var value_mirror = LookupMirror(value_description.handle);
2046 if (!value_mirror) {
2047 throw new Error("Failed to resolve value by handle, ' #" +
2048 mapping.handle + "# not found");
2049 }
2050 return value_mirror.value();
2051 } else if ("stringDescription" in value_description) {
2052 if (value_description.type == BOOLEAN_TYPE) {
2053 return Boolean(value_description.stringDescription);
2054 } else if (value_description.type == NUMBER_TYPE) {
2055 return Number(value_description.stringDescription);
2056 } if (value_description.type == STRING_TYPE) {
2057 return String(value_description.stringDescription);
2058 } else {
2059 throw new Error("Unknown type");
2060 }
2061 } else if ("value" in value_description) {
2062 return value_description.value;
2063 } else if (value_description.type == UNDEFINED_TYPE) {
2064 return void 0;
2065 } else if (value_description.type == NULL_TYPE) {
2066 return null;
2067 } else {
2068 throw new Error("Failed to parse value description");
2069 }
2070};
2071
2072
2073DebugCommandProcessor.prototype.setVariableValueRequest_ =
2074 function(request, response) {
2075 if (!request.arguments) {
2076 response.failed('Missing arguments');
2077 return;
2078 }
2079
2080 if (IS_UNDEFINED(request.arguments.name)) {
2081 response.failed('Missing variable name');
2082 }
2083 var variable_name = request.arguments.name;
2084
2085 var scope_description = request.arguments.scope;
2086
2087 // Get the frame or function for which the scope is requested.
2088 var scope_holder = this.resolveScopeHolder_(scope_description);
2089
2090 if (IS_UNDEFINED(scope_description.number)) {
2091 response.failed('Missing scope number');
2092 }
2093 var scope_index = %ToNumber(scope_description.number);
2094
2095 var scope = scope_holder.scope(scope_index);
2096
2097 var new_value =
2098 DebugCommandProcessor.resolveValue_(request.arguments.newValue);
2099
2100 scope.setVariableValue(variable_name, new_value);
2101
2102 var new_value_mirror = MakeMirror(new_value);
2103
2104 response.body = {
2105 newValue: new_value_mirror
2106 };
2107};
2108
2109
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002110DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
2111 if (!request.arguments) {
2112 return response.failed('Missing arguments');
2113 }
2114
2115 // Pull out arguments.
2116 var expression = request.arguments.expression;
2117 var frame = request.arguments.frame;
2118 var global = request.arguments.global;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002119 var disable_break = request.arguments.disable_break;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002120 var additional_context = request.arguments.additional_context;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002121
2122 // The expression argument could be an integer so we convert it to a
2123 // string.
2124 try {
2125 expression = String(expression);
2126 } catch(e) {
2127 return response.failed('Failed to convert expression argument to string');
2128 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002129
2130 // Check for legal arguments.
2131 if (!IS_UNDEFINED(frame) && global) {
2132 return response.failed('Arguments "frame" and "global" are exclusive');
2133 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002134
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002135 var additional_context_object;
2136 if (additional_context) {
2137 additional_context_object = {};
2138 for (var i = 0; i < additional_context.length; i++) {
2139 var mapping = additional_context[i];
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002140
2141 if (!IS_STRING(mapping.name)) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002142 return response.failed("Context element #" + i +
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002143 " doesn't contain name:string property");
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002144 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002145
2146 var raw_value = DebugCommandProcessor.resolveValue_(mapping);
2147 additional_context_object[mapping.name] = raw_value;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002148 }
2149 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002150
2151 // Global evaluate.
2152 if (global) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002153 // Evaluate in the native context.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002154 response.body = this.exec_state_.evaluateGlobal(
2155 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002156 return;
2157 }
2158
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002159 // Default value for disable_break is true.
2160 if (IS_UNDEFINED(disable_break)) {
2161 disable_break = true;
2162 }
2163
ager@chromium.org381abbb2009-02-25 13:23:22 +00002164 // No frames no evaluate in frame.
2165 if (this.exec_state_.frameCount() == 0) {
2166 return response.failed('No frames');
2167 }
2168
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002169 // Check whether a frame was specified.
2170 if (!IS_UNDEFINED(frame)) {
2171 var frame_number = %ToNumber(frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002172 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002173 return response.failed('Invalid frame "' + frame + '"');
2174 }
2175 // Evaluate in the specified frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002176 response.body = this.exec_state_.frame(frame_number).evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002177 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002178 return;
2179 } else {
2180 // Evaluate in the selected frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002181 response.body = this.exec_state_.frame().evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002182 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002183 return;
2184 }
2185};
2186
2187
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002188DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
2189 if (!request.arguments) {
2190 return response.failed('Missing arguments');
2191 }
2192
2193 // Pull out arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002194 var handles = request.arguments.handles;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002195
2196 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002197 if (IS_UNDEFINED(handles)) {
2198 return response.failed('Argument "handles" missing');
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002199 }
2200
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002201 // Set 'includeSource' option for script lookup.
2202 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2203 includeSource = %ToBoolean(request.arguments.includeSource);
2204 response.setOption('includeSource', includeSource);
2205 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00002206
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002207 // Lookup handles.
2208 var mirrors = {};
2209 for (var i = 0; i < handles.length; i++) {
2210 var handle = handles[i];
2211 var mirror = LookupMirror(handle);
2212 if (!mirror) {
2213 return response.failed('Object #' + handle + '# not found');
2214 }
2215 mirrors[handle] = mirror;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002216 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002217 response.body = mirrors;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002218};
2219
2220
iposva@chromium.org245aa852009-02-10 00:49:54 +00002221DebugCommandProcessor.prototype.referencesRequest_ =
2222 function(request, response) {
2223 if (!request.arguments) {
2224 return response.failed('Missing arguments');
2225 }
2226
2227 // Pull out arguments.
2228 var type = request.arguments.type;
2229 var handle = request.arguments.handle;
2230
2231 // Check for legal arguments.
2232 if (IS_UNDEFINED(type)) {
2233 return response.failed('Argument "type" missing');
2234 }
2235 if (IS_UNDEFINED(handle)) {
2236 return response.failed('Argument "handle" missing');
2237 }
2238 if (type != 'referencedBy' && type != 'constructedBy') {
2239 return response.failed('Invalid type "' + type + '"');
2240 }
2241
2242 // Lookup handle and return objects with references the object.
2243 var mirror = LookupMirror(handle);
2244 if (mirror) {
2245 if (type == 'referencedBy') {
2246 response.body = mirror.referencedBy();
2247 } else {
2248 response.body = mirror.constructedBy();
2249 }
2250 } else {
2251 return response.failed('Object #' + handle + '# not found');
2252 }
2253};
2254
2255
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002256DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00002257 // No frames no source.
2258 if (this.exec_state_.frameCount() == 0) {
2259 return response.failed('No source');
2260 }
2261
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002262 var from_line;
2263 var to_line;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002264 var frame = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002265 if (request.arguments) {
2266 // Pull out arguments.
2267 from_line = request.arguments.fromLine;
2268 to_line = request.arguments.toLine;
2269
2270 if (!IS_UNDEFINED(request.arguments.frame)) {
2271 var frame_number = %ToNumber(request.arguments.frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002272 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002273 return response.failed('Invalid frame "' + frame + '"');
2274 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002275 frame = this.exec_state_.frame(frame_number);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002276 }
2277 }
2278
2279 // Get the script selected.
2280 var script = frame.func().script();
2281 if (!script) {
2282 return response.failed('No source');
2283 }
2284
2285 // Get the source slice and fill it into the response.
2286 var slice = script.sourceSlice(from_line, to_line);
2287 if (!slice) {
2288 return response.failed('Invalid line interval');
2289 }
2290 response.body = {};
2291 response.body.source = slice.sourceText();
2292 response.body.fromLine = slice.from_line;
2293 response.body.toLine = slice.to_line;
2294 response.body.fromPosition = slice.from_position;
2295 response.body.toPosition = slice.to_position;
2296 response.body.totalLines = script.lineCount();
2297};
2298
2299
2300DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
2301 var types = ScriptTypeFlag(Debug.ScriptType.Normal);
ager@chromium.org41826e72009-03-30 13:30:57 +00002302 var includeSource = false;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002303 var idsToInclude = null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002304 if (request.arguments) {
2305 // Pull out arguments.
2306 if (!IS_UNDEFINED(request.arguments.types)) {
2307 types = %ToNumber(request.arguments.types);
2308 if (isNaN(types) || types < 0) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002309 return response.failed('Invalid types "' +
2310 request.arguments.types + '"');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002311 }
2312 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002313
ager@chromium.org41826e72009-03-30 13:30:57 +00002314 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2315 includeSource = %ToBoolean(request.arguments.includeSource);
ager@chromium.org9085a012009-05-11 19:22:57 +00002316 response.setOption('includeSource', includeSource);
ager@chromium.org41826e72009-03-30 13:30:57 +00002317 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002318
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002319 if (IS_ARRAY(request.arguments.ids)) {
2320 idsToInclude = {};
2321 var ids = request.arguments.ids;
2322 for (var i = 0; i < ids.length; i++) {
2323 idsToInclude[ids[i]] = true;
2324 }
2325 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002326
2327 var filterStr = null;
2328 var filterNum = null;
2329 if (!IS_UNDEFINED(request.arguments.filter)) {
2330 var num = %ToNumber(request.arguments.filter);
2331 if (!isNaN(num)) {
2332 filterNum = num;
2333 }
2334 filterStr = request.arguments.filter;
2335 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002336 }
2337
2338 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +00002339 var scripts = %DebugGetLoadedScripts();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002340
2341 response.body = [];
2342
2343 for (var i = 0; i < scripts.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002344 if (idsToInclude && !idsToInclude[scripts[i].id]) {
2345 continue;
2346 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002347 if (filterStr || filterNum) {
2348 var script = scripts[i];
2349 var found = false;
2350 if (filterNum && !found) {
2351 if (script.id && script.id === filterNum) {
2352 found = true;
2353 }
2354 }
2355 if (filterStr && !found) {
2356 if (script.name && script.name.indexOf(filterStr) >= 0) {
2357 found = true;
2358 }
2359 }
2360 if (!found) continue;
2361 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002362 if (types & ScriptTypeFlag(scripts[i].type)) {
ager@chromium.org9085a012009-05-11 19:22:57 +00002363 response.body.push(MakeMirror(scripts[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002364 }
2365 }
2366};
2367
2368
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002369DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
2370 // Get the number of threads.
2371 var total_threads = this.exec_state_.threadCount();
2372
2373 // Get information for all threads.
2374 var threads = [];
2375 for (var i = 0; i < total_threads; i++) {
2376 var details = %GetThreadDetails(this.exec_state_.break_id, i);
2377 var thread_info = { current: details[0],
2378 id: details[1]
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002379 };
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002380 threads.push(thread_info);
2381 }
2382
2383 // Create the response body.
2384 response.body = {
2385 totalThreads: total_threads,
2386 threads: threads
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002387 };
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002388};
2389
2390
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002391DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002392 response.running = false;
2393};
2394
2395
ager@chromium.org3811b432009-10-28 14:53:37 +00002396DebugCommandProcessor.prototype.versionRequest_ = function(request, response) {
2397 response.body = {
2398 V8Version: %GetV8Version()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002399 };
ager@chromium.org3811b432009-10-28 14:53:37 +00002400};
2401
2402
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002403DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002404 if (request.arguments.command == 'resume') {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002405 %ProfilerResume();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002406 } else if (request.arguments.command == 'pause') {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002407 %ProfilerPause();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002408 } else {
2409 return response.failed('Unknown command');
2410 }
2411 response.body = {};
2412};
2413
2414
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002415DebugCommandProcessor.prototype.changeLiveRequest_ = function(
2416 request, response) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002417 if (!request.arguments) {
2418 return response.failed('Missing arguments');
2419 }
2420 var script_id = request.arguments.script_id;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002421 var preview_only = !!request.arguments.preview_only;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002422
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002423 var scripts = %DebugGetLoadedScripts();
2424
2425 var the_script = null;
2426 for (var i = 0; i < scripts.length; i++) {
2427 if (scripts[i].id == script_id) {
2428 the_script = scripts[i];
2429 }
2430 }
2431 if (!the_script) {
2432 response.failed('Script not found');
2433 return;
2434 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002435
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002436 var change_log = new Array();
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002437
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002438 if (!IS_STRING(request.arguments.new_source)) {
2439 throw "new_source argument expected";
lrn@chromium.org25156de2010-04-06 13:10:27 +00002440 }
2441
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002442 var new_source = request.arguments.new_source;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002443
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002444 var result_description;
2445 try {
2446 result_description = Debug.LiveEdit.SetScriptSource(the_script,
2447 new_source, preview_only, change_log);
2448 } catch (e) {
2449 if (e instanceof Debug.LiveEdit.Failure && "details" in e) {
2450 response.failed(e.message, e.details);
2451 return;
2452 }
2453 throw e;
2454 }
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002455 response.body = {change_log: change_log, result: result_description};
vegorov@chromium.org42841962010-10-18 11:18:59 +00002456
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002457 if (!preview_only && !this.running_ && result_description.stack_modified) {
2458 response.body.stepin_recommended = true;
2459 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002460};
2461
2462
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002463DebugCommandProcessor.prototype.restartFrameRequest_ = function(
2464 request, response) {
2465 if (!request.arguments) {
2466 return response.failed('Missing arguments');
2467 }
2468 var frame = request.arguments.frame;
2469
2470 // No frames to evaluate in frame.
2471 if (this.exec_state_.frameCount() == 0) {
2472 return response.failed('No frames');
2473 }
2474
2475 var frame_mirror;
2476 // Check whether a frame was specified.
2477 if (!IS_UNDEFINED(frame)) {
2478 var frame_number = %ToNumber(frame);
2479 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
2480 return response.failed('Invalid frame "' + frame + '"');
2481 }
2482 // Restart specified frame.
2483 frame_mirror = this.exec_state_.frame(frame_number);
2484 } else {
2485 // Restart selected frame.
2486 frame_mirror = this.exec_state_.frame();
2487 }
2488
2489 var result_description = Debug.LiveEdit.RestartFrame(frame_mirror);
2490 response.body = {result: result_description};
2491};
2492
2493
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002494DebugCommandProcessor.prototype.debuggerFlagsRequest_ = function(request,
2495 response) {
2496 // Check for legal request.
2497 if (!request.arguments) {
2498 response.failed('Missing arguments');
2499 return;
2500 }
2501
2502 // Pull out arguments.
2503 var flags = request.arguments.flags;
2504
2505 response.body = { flags: [] };
2506 if (!IS_UNDEFINED(flags)) {
2507 for (var i = 0; i < flags.length; i++) {
2508 var name = flags[i].name;
2509 var debugger_flag = debugger_flags[name];
2510 if (!debugger_flag) {
2511 continue;
2512 }
2513 if ('value' in flags[i]) {
2514 debugger_flag.setValue(flags[i].value);
2515 }
2516 response.body.flags.push({ name: name, value: debugger_flag.getValue() });
2517 }
2518 } else {
2519 for (var name in debugger_flags) {
2520 var value = debugger_flags[name].getValue();
2521 response.body.flags.push({ name: name, value: value });
2522 }
2523 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002524};
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002525
2526
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002527DebugCommandProcessor.prototype.v8FlagsRequest_ = function(request, response) {
2528 var flags = request.arguments.flags;
2529 if (!flags) flags = '';
2530 %SetFlags(flags);
2531};
2532
2533
2534DebugCommandProcessor.prototype.gcRequest_ = function(request, response) {
2535 var type = request.arguments.type;
2536 if (!type) type = 'all';
2537
2538 var before = %GetHeapUsage();
2539 %CollectGarbage(type);
2540 var after = %GetHeapUsage();
2541
2542 response.body = { "before": before, "after": after };
2543};
2544
2545
iposva@chromium.org245aa852009-02-10 00:49:54 +00002546// Check whether the previously processed command caused the VM to become
2547// running.
2548DebugCommandProcessor.prototype.isRunning = function() {
2549 return this.running_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002550};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002551
2552
2553DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
mads.s.ager31e71382008-08-13 09:32:07 +00002554 return %SystemBreak();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002555};
2556
2557
2558function NumberToHex8Str(n) {
2559 var r = "";
2560 for (var i = 0; i < 8; ++i) {
2561 var c = hexCharArray[n & 0x0F]; // hexCharArray is defined in uri.js
2562 r = c + r;
2563 n = n >>> 4;
2564 }
2565 return r;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002566}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002567
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002568
2569/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002570 * Convert an Object to its debugger protocol representation. The representation
2571 * may be serilized to a JSON object using JSON.stringify().
2572 * This implementation simply runs through all string property names, converts
2573 * each property value to a protocol value and adds the property to the result
2574 * object. For type "object" the function will be called recursively. Note that
2575 * circular structures will cause infinite recursion.
2576 * @param {Object} object The object to format as protocol object.
ager@chromium.org32912102009-01-16 10:38:43 +00002577 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2578 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002579 * @return {Object} Protocol object value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002580 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002581function ObjectToProtocolObject_(object, mirror_serializer) {
2582 var content = {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002583 for (var key in object) {
2584 // Only consider string keys.
2585 if (typeof key == 'string') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002586 // Format the value based on its type.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002587 var property_value_json = ValueToProtocolValue_(object[key],
2588 mirror_serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002589 // Add the property if relevant.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002590 if (!IS_UNDEFINED(property_value_json)) {
2591 content[key] = property_value_json;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002592 }
2593 }
2594 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002595
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002596 return content;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002597}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002598
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002599
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002600/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002601 * Convert an array to its debugger protocol representation. It will convert
2602 * each array element to a protocol value.
2603 * @param {Array} array The array to format as protocol array.
ager@chromium.org32912102009-01-16 10:38:43 +00002604 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2605 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002606 * @return {Array} Protocol array value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002607 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002608function ArrayToProtocolArray_(array, mirror_serializer) {
2609 var json = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002610 for (var i = 0; i < array.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002611 json.push(ValueToProtocolValue_(array[i], mirror_serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002612 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002613 return json;
2614}
2615
2616
2617/**
lrn@chromium.org25156de2010-04-06 13:10:27 +00002618 * Convert a value to its debugger protocol representation.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002619 * @param {*} value The value to format as protocol value.
2620 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2621 * mirror objects are encountered.
2622 * @return {*} Protocol value.
2623 */
2624function ValueToProtocolValue_(value, mirror_serializer) {
2625 // Format the value based on its type.
2626 var json;
2627 switch (typeof value) {
2628 case 'object':
2629 if (value instanceof Mirror) {
2630 json = mirror_serializer.serializeValue(value);
2631 } else if (IS_ARRAY(value)){
2632 json = ArrayToProtocolArray_(value, mirror_serializer);
2633 } else {
2634 json = ObjectToProtocolObject_(value, mirror_serializer);
2635 }
2636 break;
2637
2638 case 'boolean':
2639 case 'string':
2640 case 'number':
2641 json = value;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002642 break;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002643
2644 default:
2645 json = null;
2646 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002647 return json;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002648}
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002649
2650Debug.TestApi = {
2651 CommandProcessorResolveValue: DebugCommandProcessor.resolveValue_
2652};