blob: 36b624e5749df3b4f60807529f7f585aca023b72 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 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.
29const kDefaultBacktraceLength = 10;
30
31const Debug = {};
32
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.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000036const 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000074function ScriptTypeFlag(type) {
75 return (1 << type);
76}
77
78// Globals.
79var next_response_seq = 0;
80var next_break_point_number = 1;
81var break_points = [];
82var script_break_points = [];
whesse@chromium.orge90029b2010-08-02 11:52:17 +000083var debugger_flags = {
84 breakPointsActive: {
85 value: true,
86 getValue: function() { return this.value; },
87 setValue: function(value) {
88 this.value = !!value;
89 %SetDisableBreak(!this.value);
90 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000091 },
92 breakOnCaughtException: {
93 getValue: function() { return Debug.isBreakOnException(); },
94 setValue: function(value) {
95 if (value) {
96 Debug.setBreakOnException();
97 } else {
98 Debug.clearBreakOnException();
99 }
100 }
101 },
102 breakOnUncaughtException: {
103 getValue: function() { return Debug.isBreakOnUncaughtException(); },
104 setValue: function(value) {
105 if (value) {
106 Debug.setBreakOnUncaughtException();
107 } else {
108 Debug.clearBreakOnUncaughtException();
109 }
110 }
111 },
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000112};
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000113var lol_is_enabled = %HasLOLEnabled();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114
115
116// Create a new break point object and add it to the list of break points.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000117function MakeBreakPoint(source_position, opt_script_break_point) {
118 var break_point = new BreakPoint(source_position, opt_script_break_point);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119 break_points.push(break_point);
120 return break_point;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000121}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122
123
124// Object representing a break point.
125// NOTE: This object does not have a reference to the function having break
126// point as this would cause function not to be garbage collected when it is
127// not used any more. We do not want break points to keep functions alive.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000128function BreakPoint(source_position, opt_script_break_point) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129 this.source_position_ = source_position;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130 if (opt_script_break_point) {
131 this.script_break_point_ = opt_script_break_point;
132 } else {
133 this.number_ = next_break_point_number++;
134 }
135 this.hit_count_ = 0;
136 this.active_ = true;
137 this.condition_ = null;
138 this.ignoreCount_ = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000139}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140
141
142BreakPoint.prototype.number = function() {
143 return this.number_;
144};
145
146
147BreakPoint.prototype.func = function() {
148 return this.func_;
149};
150
151
152BreakPoint.prototype.source_position = function() {
153 return this.source_position_;
154};
155
156
157BreakPoint.prototype.hit_count = function() {
158 return this.hit_count_;
159};
160
161
162BreakPoint.prototype.active = function() {
163 if (this.script_break_point()) {
164 return this.script_break_point().active();
165 }
166 return this.active_;
167};
168
169
170BreakPoint.prototype.condition = function() {
171 if (this.script_break_point() && this.script_break_point().condition()) {
172 return this.script_break_point().condition();
173 }
174 return this.condition_;
175};
176
177
178BreakPoint.prototype.ignoreCount = function() {
179 return this.ignoreCount_;
180};
181
182
183BreakPoint.prototype.script_break_point = function() {
184 return this.script_break_point_;
185};
186
187
188BreakPoint.prototype.enable = function() {
189 this.active_ = true;
190};
191
192
193BreakPoint.prototype.disable = function() {
194 this.active_ = false;
195};
196
197
198BreakPoint.prototype.setCondition = function(condition) {
199 this.condition_ = condition;
200};
201
202
203BreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
204 this.ignoreCount_ = ignoreCount;
205};
206
207
208BreakPoint.prototype.isTriggered = function(exec_state) {
209 // Break point not active - not triggered.
210 if (!this.active()) return false;
211
212 // Check for conditional break point.
213 if (this.condition()) {
214 // If break point has condition try to evaluate it in the top frame.
215 try {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000216 var mirror = exec_state.frame(0).evaluate(this.condition());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217 // If no sensible mirror or non true value break point not triggered.
218 if (!(mirror instanceof ValueMirror) || !%ToBoolean(mirror.value_)) {
219 return false;
220 }
221 } catch (e) {
222 // Exception evaluating condition counts as not triggered.
223 return false;
224 }
225 }
226
227 // Update the hit count.
228 this.hit_count_++;
229 if (this.script_break_point_) {
230 this.script_break_point_.hit_count_++;
231 }
232
233 // If the break point has an ignore count it is not triggered.
234 if (this.ignoreCount_ > 0) {
235 this.ignoreCount_--;
236 return false;
237 }
238
239 // Break point triggered.
240 return true;
241};
242
243
244// Function called from the runtime when a break point is hit. Returns true if
245// the break point is triggered and supposed to break execution.
246function IsBreakPointTriggered(break_id, break_point) {
247 return break_point.isTriggered(MakeExecutionState(break_id));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000248}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249
250
251// Object representing a script break point. The script is referenced by its
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000252// script name or script id and the break point is represented as line and
253// column.
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000254function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
255 opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000256 this.type_ = type;
257 if (type == Debug.ScriptBreakPointType.ScriptId) {
258 this.script_id_ = script_id_or_name;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000259 } else if (type == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000260 this.script_name_ = script_id_or_name;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000261 } else if (type == Debug.ScriptBreakPointType.ScriptRegExp) {
262 this.script_regexp_object_ = new RegExp(script_id_or_name);
263 } else {
264 throw new Error("Unexpected breakpoint type " + type);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000265 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000266 this.line_ = opt_line || 0;
267 this.column_ = opt_column;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000268 this.groupId_ = opt_groupId;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269 this.hit_count_ = 0;
270 this.active_ = true;
271 this.condition_ = null;
272 this.ignoreCount_ = 0;
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000273 this.break_points_ = [];
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000274}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275
276
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000277//Creates a clone of script breakpoint that is linked to another script.
278ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
279 var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
280 other_script.id, this.line_, this.column_, this.groupId_);
281 copy.number_ = next_break_point_number++;
282 script_break_points.push(copy);
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000283
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000284 copy.hit_count_ = this.hit_count_;
285 copy.active_ = this.active_;
286 copy.condition_ = this.condition_;
287 copy.ignoreCount_ = this.ignoreCount_;
288 return copy;
289}
290
291
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292ScriptBreakPoint.prototype.number = function() {
293 return this.number_;
294};
295
296
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000297ScriptBreakPoint.prototype.groupId = function() {
298 return this.groupId_;
299};
300
301
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000302ScriptBreakPoint.prototype.type = function() {
303 return this.type_;
304};
305
306
307ScriptBreakPoint.prototype.script_id = function() {
308 return this.script_id_;
309};
310
311
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312ScriptBreakPoint.prototype.script_name = function() {
313 return this.script_name_;
314};
315
316
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000317ScriptBreakPoint.prototype.script_regexp_object = function() {
318 return this.script_regexp_object_;
319};
320
321
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322ScriptBreakPoint.prototype.line = function() {
323 return this.line_;
324};
325
326
327ScriptBreakPoint.prototype.column = function() {
328 return this.column_;
329};
330
331
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000332ScriptBreakPoint.prototype.actual_locations = function() {
333 var locations = [];
334 for (var i = 0; i < this.break_points_.length; i++) {
335 locations.push(this.break_points_[i].actual_location);
336 }
337 return locations;
338}
339
340
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000341ScriptBreakPoint.prototype.update_positions = function(line, column) {
342 this.line_ = line;
343 this.column_ = column;
344}
345
346
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347ScriptBreakPoint.prototype.hit_count = function() {
348 return this.hit_count_;
349};
350
351
352ScriptBreakPoint.prototype.active = function() {
353 return this.active_;
354};
355
356
357ScriptBreakPoint.prototype.condition = function() {
358 return this.condition_;
359};
360
361
362ScriptBreakPoint.prototype.ignoreCount = function() {
363 return this.ignoreCount_;
364};
365
366
367ScriptBreakPoint.prototype.enable = function() {
368 this.active_ = true;
369};
370
371
372ScriptBreakPoint.prototype.disable = function() {
373 this.active_ = false;
374};
375
376
377ScriptBreakPoint.prototype.setCondition = function(condition) {
378 this.condition_ = condition;
379};
380
381
382ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
383 this.ignoreCount_ = ignoreCount;
384
385 // Set ignore count on all break points created from this script break point.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000386 for (var i = 0; i < this.break_points_.length; i++) {
387 this.break_points_[i].setIgnoreCount(ignoreCount);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388 }
389};
390
391
392// Check whether a script matches this script break point. Currently this is
393// only based on script name.
394ScriptBreakPoint.prototype.matchesScript = function(script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000395 if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
396 return this.script_id_ == script.id;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000397 } else {
398 // We might want to account columns here as well.
399 if (!(script.line_offset <= this.line_ &&
400 this.line_ < script.line_offset + script.lineCount())) {
401 return false;
402 }
403 if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
404 return this.script_name_ == script.nameOrSourceURL();
405 } else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
406 return this.script_regexp_object_.test(script.nameOrSourceURL());
407 } else {
408 throw new Error("Unexpected breakpoint type " + this.type_);
409 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000410 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000411};
412
413
414// Set the script break point in a script.
415ScriptBreakPoint.prototype.set = function (script) {
416 var column = this.column();
417 var line = this.line();
418 // If the column is undefined the break is on the line. To help locate the
419 // first piece of breakable code on the line try to find the column on the
420 // line which contains some source.
421 if (IS_UNDEFINED(column)) {
422 var source_line = script.sourceLine(this.line());
423
424 // Allocate array for caching the columns where the actual source starts.
425 if (!script.sourceColumnStart_) {
426 script.sourceColumnStart_ = new Array(script.lineCount());
427 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000428
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429 // Fill cache if needed and get column where the actual source starts.
430 if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
431 script.sourceColumnStart_[line] =
432 source_line.match(sourceLineBeginningSkip)[0].length;
433 }
434 column = script.sourceColumnStart_[line];
435 }
436
437 // Convert the line and column into an absolute position within the script.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000438 var position = Debug.findScriptSourcePosition(script, this.line(), column);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000439
ager@chromium.org8bb60582008-12-11 12:02:20 +0000440 // If the position is not found in the script (the script might be shorter
441 // than it used to be) just ignore it.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000442 if (position === null) return;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444 // Create a break point object and set the break point.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000445 break_point = MakeBreakPoint(position, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000446 break_point.setIgnoreCount(this.ignoreCount());
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000447 var actual_position = %SetScriptBreakPoint(script, position, break_point);
448 if (IS_UNDEFINED(actual_position)) {
449 actual_position = position;
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000450 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000451 var actual_location = script.locationFromPosition(actual_position, true);
452 break_point.actual_location = { line: actual_location.line,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000453 column: actual_location.column,
454 script_id: script.id };
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000455 this.break_points_.push(break_point);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456 return break_point;
457};
458
459
460// Clear all the break points created from this script break point
461ScriptBreakPoint.prototype.clear = function () {
462 var remaining_break_points = [];
463 for (var i = 0; i < break_points.length; i++) {
464 if (break_points[i].script_break_point() &&
465 break_points[i].script_break_point() === this) {
466 %ClearBreakPoint(break_points[i]);
467 } else {
468 remaining_break_points.push(break_points[i]);
469 }
470 }
471 break_points = remaining_break_points;
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000472 this.break_points_ = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473};
474
475
476// Function called from runtime when a new script is compiled to set any script
477// break points set in this script.
478function UpdateScriptBreakPoints(script) {
479 for (var i = 0; i < script_break_points.length; i++) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000480 if (script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptName &&
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000481 script_break_points[i].matchesScript(script)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482 script_break_points[i].set(script);
483 }
484 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000485}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000486
487
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000488function GetScriptBreakPoints(script) {
489 var result = [];
490 for (var i = 0; i < script_break_points.length; i++) {
491 if (script_break_points[i].matchesScript(script)) {
492 result.push(script_break_points[i]);
493 }
494 }
495 return result;
496}
497
498
iposva@chromium.org245aa852009-02-10 00:49:54 +0000499Debug.setListener = function(listener, opt_data) {
500 if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
501 throw new Error('Parameters have wrong types.');
502 }
503 %SetDebugEventListener(listener, opt_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504};
505
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000506
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000507Debug.breakExecution = function(f) {
mads.s.ager31e71382008-08-13 09:32:07 +0000508 %Break();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509};
510
511Debug.breakLocations = function(f) {
512 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
513 return %GetBreakLocations(f);
514};
515
516// Returns a Script object. If the parameter is a function the return value
517// is the script in which the function is defined. If the parameter is a string
518// the return value is the script for which the script name has that string
mads.s.agercbaa0602008-08-14 13:41:48 +0000519// value. If it is a regexp and there is a unique script whose name matches
520// we return that, otherwise undefined.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521Debug.findScript = function(func_or_script_name) {
522 if (IS_FUNCTION(func_or_script_name)) {
523 return %FunctionGetScript(func_or_script_name);
mads.s.agercbaa0602008-08-14 13:41:48 +0000524 } else if (IS_REGEXP(func_or_script_name)) {
525 var scripts = Debug.scripts();
526 var last_result = null;
527 var result_count = 0;
528 for (var i in scripts) {
529 var script = scripts[i];
530 if (func_or_script_name.test(script.name)) {
531 last_result = script;
532 result_count++;
533 }
534 }
535 // Return the unique script matching the regexp. If there are more
536 // than one we don't return a value since there is no good way to
537 // decide which one to return. Returning a "random" one, say the
538 // first, would introduce nondeterminism (or something close to it)
539 // because the order is the heap iteration order.
540 if (result_count == 1) {
541 return last_result;
542 } else {
543 return undefined;
544 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545 } else {
546 return %GetScript(func_or_script_name);
547 }
548};
549
550// Returns the script source. If the parameter is a function the return value
551// is the script source for the script in which the function is defined. If the
552// parameter is a string the return value is the script for which the script
553// name has that string value.
554Debug.scriptSource = function(func_or_script_name) {
555 return this.findScript(func_or_script_name).source;
556};
557
558Debug.source = function(f) {
559 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
560 return %FunctionGetSourceCode(f);
561};
562
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000563Debug.disassemble = function(f) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000565 return %DebugDisassembleFunction(f);
566};
567
568Debug.disassembleConstructor = function(f) {
569 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
570 return %DebugDisassembleConstructor(f);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000571};
572
ager@chromium.org357bf652010-04-12 11:30:10 +0000573Debug.ExecuteInDebugContext = function(f, without_debugger) {
574 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
575 return %ExecuteInDebugContext(f, !!without_debugger);
576};
577
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000578Debug.sourcePosition = function(f) {
579 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
580 return %FunctionGetScriptSourcePosition(f);
581};
582
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000583
584Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585 var script = %FunctionGetScript(func);
586 var script_offset = %FunctionGetScriptSourcePosition(func);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000587 return script.locationFromLine(opt_line, opt_column, script_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588}
589
590
591// Returns the character position in a script based on a line number and an
592// optional position within that line.
593Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000594 var location = script.locationFromLine(opt_line, opt_column);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000595 return location ? location.position : null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596}
597
598
599Debug.findBreakPoint = function(break_point_number, remove) {
600 var break_point;
601 for (var i = 0; i < break_points.length; i++) {
602 if (break_points[i].number() == break_point_number) {
603 break_point = break_points[i];
604 // Remove the break point from the list if requested.
605 if (remove) {
606 break_points.splice(i, 1);
607 }
608 break;
609 }
610 }
611 if (break_point) {
612 return break_point;
613 } else {
614 return this.findScriptBreakPoint(break_point_number, remove);
615 }
616};
617
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000618Debug.findBreakPointActualLocations = function(break_point_number) {
619 for (var i = 0; i < script_break_points.length; i++) {
620 if (script_break_points[i].number() == break_point_number) {
621 return script_break_points[i].actual_locations();
622 }
623 }
624 for (var i = 0; i < break_points.length; i++) {
625 if (break_points[i].number() == break_point_number) {
626 return [break_points[i].actual_location];
627 }
628 }
629 return [];
630}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631
632Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
633 if (!IS_FUNCTION(func)) throw new Error('Parameters have wrong types.');
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000634 // Break points in API functions are not supported.
635 if (%FunctionIsAPIFunction(func)) {
636 throw new Error('Cannot set break point in native code.');
637 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000638 // Find source position relative to start of the function
639 var break_position =
640 this.findFunctionSourceLocation(func, opt_line, opt_column).position;
641 var source_position = break_position - this.sourcePosition(func);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000642 // Find the script for the function.
643 var script = %FunctionGetScript(func);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000644 // Break in builtin JavaScript code is not supported.
645 if (script.type == Debug.ScriptType.Native) {
646 throw new Error('Cannot set break point in native code.');
647 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000648 // If the script for the function has a name convert this to a script break
649 // point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000650 if (script && script.id) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000651 // Adjust the source position to be script relative.
652 source_position += %FunctionGetScriptSourcePosition(func);
653 // Find line and column for the position in the script and set a script
654 // break point from that.
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000655 var location = script.locationFromPosition(source_position, false);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000656 return this.setScriptBreakPointById(script.id,
657 location.line, location.column,
658 opt_condition);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000659 } else {
660 // Set a break point directly on the function.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000661 var break_point = MakeBreakPoint(source_position);
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000662 var actual_position =
663 %SetFunctionBreakPoint(func, source_position, break_point);
664 actual_position += this.sourcePosition(func);
665 var actual_location = script.locationFromPosition(actual_position, true);
666 break_point.actual_location = { line: actual_location.line,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000667 column: actual_location.column,
668 script_id: script.id };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000669 break_point.setCondition(opt_condition);
670 return break_point.number();
671 }
672};
673
674
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000675Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
676 condition, enabled)
677{
678 break_point = MakeBreakPoint(position);
679 break_point.setCondition(condition);
680 if (!enabled)
681 break_point.disable();
682 var scripts = this.scripts();
683 for (var i = 0; i < scripts.length; i++) {
684 if (script_id == scripts[i].id) {
685 break_point.actual_position = %SetScriptBreakPoint(scripts[i], position,
686 break_point);
687 break;
688 }
689 }
690 return break_point;
691};
692
693
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000694Debug.enableBreakPoint = function(break_point_number) {
695 var break_point = this.findBreakPoint(break_point_number, false);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000696 // Only enable if the breakpoint hasn't been deleted:
697 if (break_point) {
698 break_point.enable();
699 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000700};
701
702
703Debug.disableBreakPoint = function(break_point_number) {
704 var break_point = this.findBreakPoint(break_point_number, false);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000705 // Only enable if the breakpoint hasn't been deleted:
706 if (break_point) {
707 break_point.disable();
708 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709};
710
711
712Debug.changeBreakPointCondition = function(break_point_number, condition) {
713 var break_point = this.findBreakPoint(break_point_number, false);
714 break_point.setCondition(condition);
715};
716
717
718Debug.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
719 if (ignoreCount < 0) {
720 throw new Error('Invalid argument');
721 }
722 var break_point = this.findBreakPoint(break_point_number, false);
723 break_point.setIgnoreCount(ignoreCount);
724};
725
726
727Debug.clearBreakPoint = function(break_point_number) {
728 var break_point = this.findBreakPoint(break_point_number, true);
729 if (break_point) {
730 return %ClearBreakPoint(break_point);
731 } else {
732 break_point = this.findScriptBreakPoint(break_point_number, true);
733 if (!break_point) {
734 throw new Error('Invalid breakpoint');
735 }
736 }
737};
738
739
740Debug.clearAllBreakPoints = function() {
741 for (var i = 0; i < break_points.length; i++) {
742 break_point = break_points[i];
743 %ClearBreakPoint(break_point);
744 }
745 break_points = [];
746};
747
748
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000749Debug.disableAllBreakPoints = function() {
750 // Disable all user defined breakpoints:
751 for (var i = 1; i < next_break_point_number; i++) {
752 Debug.disableBreakPoint(i);
753 }
754 // Disable all exception breakpoints:
755 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
756 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
757};
758
759
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760Debug.findScriptBreakPoint = function(break_point_number, remove) {
761 var script_break_point;
762 for (var i = 0; i < script_break_points.length; i++) {
763 if (script_break_points[i].number() == break_point_number) {
764 script_break_point = script_break_points[i];
765 // Remove the break point from the list if requested.
766 if (remove) {
767 script_break_point.clear();
768 script_break_points.splice(i,1);
769 }
770 break;
771 }
772 }
773 return script_break_point;
774}
775
776
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000777// Sets a breakpoint in a script identified through id or name at the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778// specified source line and column within that line.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000779Debug.setScriptBreakPoint = function(type, script_id_or_name,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000780 opt_line, opt_column, opt_condition,
781 opt_groupId) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000782 // Create script break point object.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000783 var script_break_point =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000784 new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
785 opt_groupId);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000786
787 // Assign number to the new script break point and add it.
788 script_break_point.number_ = next_break_point_number++;
789 script_break_point.setCondition(opt_condition);
790 script_break_points.push(script_break_point);
791
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000792 // Run through all scripts to see if this script break point matches any
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793 // loaded scripts.
794 var scripts = this.scripts();
795 for (var i = 0; i < scripts.length; i++) {
796 if (script_break_point.matchesScript(scripts[i])) {
797 script_break_point.set(scripts[i]);
798 }
799 }
800
801 return script_break_point.number();
802}
803
804
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000805Debug.setScriptBreakPointById = function(script_id,
806 opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000807 opt_condition, opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000808 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
809 script_id, opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000810 opt_condition, opt_groupId);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000811}
812
813
814Debug.setScriptBreakPointByName = function(script_name,
815 opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000816 opt_condition, opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000817 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
818 script_name, opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000819 opt_condition, opt_groupId);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000820}
821
822
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000823Debug.setScriptBreakPointByRegExp = function(script_regexp,
824 opt_line, opt_column,
825 opt_condition, opt_groupId) {
826 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptRegExp,
827 script_regexp, opt_line, opt_column,
828 opt_condition, opt_groupId);
829}
830
831
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832Debug.enableScriptBreakPoint = function(break_point_number) {
833 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
834 script_break_point.enable();
835};
836
837
838Debug.disableScriptBreakPoint = function(break_point_number) {
839 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
840 script_break_point.disable();
841};
842
843
844Debug.changeScriptBreakPointCondition = function(break_point_number, condition) {
845 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
846 script_break_point.setCondition(condition);
847};
848
849
850Debug.changeScriptBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
851 if (ignoreCount < 0) {
852 throw new Error('Invalid argument');
853 }
854 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
855 script_break_point.setIgnoreCount(ignoreCount);
856};
857
858
859Debug.scriptBreakPoints = function() {
860 return script_break_points;
861}
862
863
864Debug.clearStepping = function() {
mads.s.ager31e71382008-08-13 09:32:07 +0000865 %ClearStepping();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866}
867
868Debug.setBreakOnException = function() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000869 return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870};
871
872Debug.clearBreakOnException = function() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000873 return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
874};
875
876Debug.isBreakOnException = function() {
877 return !!%IsBreakOnException(Debug.ExceptionBreak.Caught);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878};
879
880Debug.setBreakOnUncaughtException = function() {
881 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
882};
883
884Debug.clearBreakOnUncaughtException = function() {
885 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
886};
887
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000888Debug.isBreakOnUncaughtException = function() {
889 return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
890};
891
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892Debug.showBreakPoints = function(f, full) {
893 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
894 var source = full ? this.scriptSource(f) : this.source(f);
895 var offset = full ? this.sourcePosition(f) : 0;
896 var locations = this.breakLocations(f);
897 if (!locations) return source;
898 locations.sort(function(x, y) { return x - y; });
899 var result = "";
900 var prev_pos = 0;
901 var pos;
902 for (var i = 0; i < locations.length; i++) {
903 pos = locations[i] - offset;
904 result += source.slice(prev_pos, pos);
905 result += "[B" + i + "]";
906 prev_pos = pos;
907 }
908 pos = source.length;
909 result += source.substring(prev_pos, pos);
910 return result;
911};
912
913
914// Get all the scripts currently loaded. Locating all the scripts is based on
915// scanning the heap.
916Debug.scripts = function() {
917 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +0000918 return %DebugGetLoadedScripts();
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000919};
920
921
922Debug.debuggerFlags = function() {
923 return debugger_flags;
924};
925
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000926Debug.MakeMirror = MakeMirror;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000927
928function MakeExecutionState(break_id) {
929 return new ExecutionState(break_id);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000930}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000931
932function ExecutionState(break_id) {
933 this.break_id = break_id;
934 this.selected_frame = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000935}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000936
937ExecutionState.prototype.prepareStep = function(opt_action, opt_count) {
938 var action = Debug.StepAction.StepIn;
939 if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
940 var count = opt_count ? %ToNumber(opt_count) : 1;
941
942 return %PrepareStep(this.break_id, action, count);
943}
944
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000945ExecutionState.prototype.evaluateGlobal = function(source, disable_break,
946 opt_additional_context) {
947 return MakeMirror(%DebugEvaluateGlobal(this.break_id, source,
948 Boolean(disable_break),
949 opt_additional_context));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000950};
951
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000952ExecutionState.prototype.frameCount = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000953 return %GetFrameCount(this.break_id);
954};
955
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000956ExecutionState.prototype.threadCount = function() {
957 return %GetThreadCount(this.break_id);
958};
959
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000960ExecutionState.prototype.frame = function(opt_index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000961 // If no index supplied return the selected frame.
962 if (opt_index == null) opt_index = this.selected_frame;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000963 if (opt_index < 0 || opt_index >= this.frameCount())
964 throw new Error('Illegal frame index.');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000965 return new FrameMirror(this.break_id, opt_index);
966};
967
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000968ExecutionState.prototype.setSelectedFrame = function(index) {
969 var i = %ToNumber(index);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000970 if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000971 this.selected_frame = i;
972};
973
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000974ExecutionState.prototype.selectedFrame = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000975 return this.selected_frame;
976};
977
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000978ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) {
979 return new DebugCommandProcessor(this, opt_is_running);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000980};
981
982
983function MakeBreakEvent(exec_state, break_points_hit) {
984 return new BreakEvent(exec_state, break_points_hit);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000985}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000986
987
988function BreakEvent(exec_state, break_points_hit) {
989 this.exec_state_ = exec_state;
990 this.break_points_hit_ = break_points_hit;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000991}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000992
993
ager@chromium.org8bb60582008-12-11 12:02:20 +0000994BreakEvent.prototype.executionState = function() {
995 return this.exec_state_;
996};
997
998
999BreakEvent.prototype.eventType = function() {
1000 return Debug.DebugEvent.Break;
1001};
1002
1003
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001004BreakEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001005 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001006};
1007
1008
1009BreakEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001010 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001011};
1012
1013
1014BreakEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001015 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001016};
1017
1018
1019BreakEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001020 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001021};
1022
1023
1024BreakEvent.prototype.breakPointsHit = function() {
1025 return this.break_points_hit_;
1026};
1027
1028
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001029BreakEvent.prototype.toJSONProtocol = function() {
1030 var o = { seq: next_response_seq++,
1031 type: "event",
1032 event: "break",
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001033 body: { invocationText: this.exec_state_.frame(0).invocationText(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001035 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001036
1037 // Add script related information to the event if available.
1038 var script = this.func().script();
1039 if (script) {
1040 o.body.sourceLine = this.sourceLine(),
1041 o.body.sourceColumn = this.sourceColumn(),
1042 o.body.sourceLineText = this.sourceLineText(),
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001043 o.body.script = MakeScriptObject_(script, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001044 }
1045
1046 // Add an Array of break points hit if any.
1047 if (this.breakPointsHit()) {
1048 o.body.breakpoints = [];
1049 for (var i = 0; i < this.breakPointsHit().length; i++) {
1050 // Find the break point number. For break points originating from a
1051 // script break point supply the script break point number.
1052 var breakpoint = this.breakPointsHit()[i];
1053 var script_break_point = breakpoint.script_break_point();
1054 var number;
1055 if (script_break_point) {
1056 number = script_break_point.number();
1057 } else {
1058 number = breakpoint.number();
1059 }
1060 o.body.breakpoints.push(number);
1061 }
1062 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001063 return JSON.stringify(ObjectToProtocolObject_(o));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001064};
1065
1066
1067function MakeExceptionEvent(exec_state, exception, uncaught) {
1068 return new ExceptionEvent(exec_state, exception, uncaught);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001069}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001070
ager@chromium.org8bb60582008-12-11 12:02:20 +00001071
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001072function ExceptionEvent(exec_state, exception, uncaught) {
1073 this.exec_state_ = exec_state;
1074 this.exception_ = exception;
1075 this.uncaught_ = uncaught;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001076}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001077
ager@chromium.org8bb60582008-12-11 12:02:20 +00001078
1079ExceptionEvent.prototype.executionState = function() {
1080 return this.exec_state_;
1081};
1082
1083
1084ExceptionEvent.prototype.eventType = function() {
1085 return Debug.DebugEvent.Exception;
1086};
1087
1088
1089ExceptionEvent.prototype.exception = function() {
1090 return this.exception_;
1091}
1092
1093
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094ExceptionEvent.prototype.uncaught = function() {
1095 return this.uncaught_;
1096}
1097
ager@chromium.org8bb60582008-12-11 12:02:20 +00001098
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001099ExceptionEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001100 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101};
1102
1103
1104ExceptionEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001105 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106};
1107
1108
1109ExceptionEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001110 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001111};
1112
1113
1114ExceptionEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001115 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001116};
1117
1118
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001119ExceptionEvent.prototype.toJSONProtocol = function() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001120 var o = new ProtocolMessage();
1121 o.event = "exception";
1122 o.body = { uncaught: this.uncaught_,
1123 exception: MakeMirror(this.exception_)
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001124 };
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001125
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001126 // Exceptions might happen whithout any JavaScript frames.
1127 if (this.exec_state_.frameCount() > 0) {
1128 o.body.sourceLine = this.sourceLine();
1129 o.body.sourceColumn = this.sourceColumn();
1130 o.body.sourceLineText = this.sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001131
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001132 // Add script information to the event if available.
1133 var script = this.func().script();
1134 if (script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001135 o.body.script = MakeScriptObject_(script, false);
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001136 }
1137 } else {
1138 o.body.sourceLine = -1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001139 }
1140
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001141 return o.toJSONProtocol();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001142};
1143
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001144
iposva@chromium.org245aa852009-02-10 00:49:54 +00001145function MakeCompileEvent(exec_state, script, before) {
1146 return new CompileEvent(exec_state, script, before);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001147}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001148
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001149
iposva@chromium.org245aa852009-02-10 00:49:54 +00001150function CompileEvent(exec_state, script, before) {
1151 this.exec_state_ = exec_state;
1152 this.script_ = MakeMirror(script);
1153 this.before_ = before;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001154}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001155
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001156
iposva@chromium.org245aa852009-02-10 00:49:54 +00001157CompileEvent.prototype.executionState = function() {
1158 return this.exec_state_;
1159};
1160
1161
ager@chromium.org8bb60582008-12-11 12:02:20 +00001162CompileEvent.prototype.eventType = function() {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001163 if (this.before_) {
1164 return Debug.DebugEvent.BeforeCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001165 } else {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001166 return Debug.DebugEvent.AfterCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001167 }
1168};
1169
1170
iposva@chromium.org245aa852009-02-10 00:49:54 +00001171CompileEvent.prototype.script = function() {
1172 return this.script_;
1173};
1174
1175
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001176CompileEvent.prototype.toJSONProtocol = function() {
1177 var o = new ProtocolMessage();
ager@chromium.org5ec48922009-05-05 07:25:34 +00001178 o.running = true;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001179 if (this.before_) {
1180 o.event = "beforeCompile";
1181 } else {
1182 o.event = "afterCompile";
1183 }
1184 o.body = {};
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001185 o.body.script = this.script_;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001186
1187 return o.toJSONProtocol();
1188}
1189
1190
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001191function MakeNewFunctionEvent(func) {
1192 return new NewFunctionEvent(func);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001193}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001194
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001195
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001196function NewFunctionEvent(func) {
1197 this.func = func;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001198}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001199
ager@chromium.org8bb60582008-12-11 12:02:20 +00001200
1201NewFunctionEvent.prototype.eventType = function() {
1202 return Debug.DebugEvent.NewFunction;
1203};
1204
1205
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001206NewFunctionEvent.prototype.name = function() {
1207 return this.func.name;
1208};
1209
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001210
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001211NewFunctionEvent.prototype.setBreakPoint = function(p) {
1212 Debug.setBreakPoint(this.func, p || 0);
1213};
1214
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001215
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001216function MakeScriptCollectedEvent(exec_state, id) {
1217 return new ScriptCollectedEvent(exec_state, id);
1218}
1219
1220
1221function ScriptCollectedEvent(exec_state, id) {
1222 this.exec_state_ = exec_state;
1223 this.id_ = id;
1224}
1225
1226
1227ScriptCollectedEvent.prototype.id = function() {
1228 return this.id_;
1229};
1230
1231
1232ScriptCollectedEvent.prototype.executionState = function() {
1233 return this.exec_state_;
1234};
1235
1236
1237ScriptCollectedEvent.prototype.toJSONProtocol = function() {
1238 var o = new ProtocolMessage();
1239 o.running = true;
1240 o.event = "scriptCollected";
1241 o.body = {};
1242 o.body.script = { id: this.id() };
1243 return o.toJSONProtocol();
1244}
1245
1246
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001247function MakeScriptObject_(script, include_source) {
1248 var o = { id: script.id(),
1249 name: script.name(),
1250 lineOffset: script.lineOffset(),
1251 columnOffset: script.columnOffset(),
1252 lineCount: script.lineCount(),
1253 };
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001254 if (!IS_UNDEFINED(script.data())) {
1255 o.data = script.data();
1256 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001257 if (include_source) {
1258 o.source = script.source();
1259 }
1260 return o;
1261};
1262
1263
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001264function DebugCommandProcessor(exec_state, opt_is_running) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001265 this.exec_state_ = exec_state;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001266 this.running_ = opt_is_running || false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001267};
1268
1269
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001270DebugCommandProcessor.prototype.processDebugRequest = function (request) {
1271 return this.processDebugJSONRequest(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272}
1273
1274
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001275function ProtocolMessage(request) {
1276 // Update sequence number.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277 this.seq = next_response_seq++;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001278
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001279 if (request) {
1280 // If message is based on a request this is a response. Fill the initial
1281 // response from the request.
1282 this.type = 'response';
1283 this.request_seq = request.seq;
1284 this.command = request.command;
1285 } else {
1286 // If message is not based on a request it is a dabugger generated event.
1287 this.type = 'event';
1288 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001289 this.success = true;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001290 // Handler may set this field to control debugger state.
1291 this.running = undefined;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001292}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001293
1294
ager@chromium.org9085a012009-05-11 19:22:57 +00001295ProtocolMessage.prototype.setOption = function(name, value) {
1296 if (!this.options_) {
1297 this.options_ = {};
1298 }
1299 this.options_[name] = value;
1300}
1301
1302
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001303ProtocolMessage.prototype.failed = function(message) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001304 this.success = false;
1305 this.message = message;
1306}
1307
1308
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001309ProtocolMessage.prototype.toJSONProtocol = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001310 // Encode the protocol header.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001311 var json = {};
1312 json.seq= this.seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001313 if (this.request_seq) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001314 json.request_seq = this.request_seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001316 json.type = this.type;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001317 if (this.event) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001318 json.event = this.event;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001319 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320 if (this.command) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001321 json.command = this.command;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001322 }
1323 if (this.success) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001324 json.success = this.success;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001325 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001326 json.success = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001327 }
1328 if (this.body) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329 // Encode the body part.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001330 var bodyJson;
ager@chromium.org9085a012009-05-11 19:22:57 +00001331 var serializer = MakeMirrorSerializer(true, this.options_);
ager@chromium.org32912102009-01-16 10:38:43 +00001332 if (this.body instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001333 bodyJson = serializer.serializeValue(this.body);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001334 } else if (this.body instanceof Array) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001335 bodyJson = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001336 for (var i = 0; i < this.body.length; i++) {
ager@chromium.org32912102009-01-16 10:38:43 +00001337 if (this.body[i] instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001338 bodyJson.push(serializer.serializeValue(this.body[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001339 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001340 bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001341 }
1342 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001343 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001344 bodyJson = ObjectToProtocolObject_(this.body, serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001345 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001346 json.body = bodyJson;
1347 json.refs = serializer.serializeReferencedObjects();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001348 }
1349 if (this.message) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001350 json.message = this.message;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001351 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001352 json.running = this.running;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001353 return JSON.stringify(json);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354}
1355
1356
1357DebugCommandProcessor.prototype.createResponse = function(request) {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001358 return new ProtocolMessage(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359};
1360
1361
iposva@chromium.org245aa852009-02-10 00:49:54 +00001362DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001363 var request; // Current request.
1364 var response; // Generated response.
1365 try {
1366 try {
1367 // Convert the JSON string to an object.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001368 request = JSON.parse(json_request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001369
1370 // Create an initial response.
1371 response = this.createResponse(request);
1372
1373 if (!request.type) {
1374 throw new Error('Type not specified');
1375 }
1376
1377 if (request.type != 'request') {
1378 throw new Error("Illegal type '" + request.type + "' in request");
1379 }
1380
1381 if (!request.command) {
1382 throw new Error('Command not specified');
1383 }
1384
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001385 if (request.arguments) {
1386 var args = request.arguments;
1387 // TODO(yurys): remove request.arguments.compactFormat check once
1388 // ChromeDevTools are switched to 'inlineRefs'
1389 if (args.inlineRefs || args.compactFormat) {
1390 response.setOption('inlineRefs', true);
1391 }
1392 if (!IS_UNDEFINED(args.maxStringLength)) {
1393 response.setOption('maxStringLength', args.maxStringLength);
1394 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001395 }
1396
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001397 if (request.command == 'continue') {
1398 this.continueRequest_(request, response);
1399 } else if (request.command == 'break') {
1400 this.breakRequest_(request, response);
1401 } else if (request.command == 'setbreakpoint') {
1402 this.setBreakPointRequest_(request, response);
1403 } else if (request.command == 'changebreakpoint') {
1404 this.changeBreakPointRequest_(request, response);
1405 } else if (request.command == 'clearbreakpoint') {
1406 this.clearBreakPointRequest_(request, response);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001407 } else if (request.command == 'clearbreakpointgroup') {
1408 this.clearBreakPointGroupRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001409 } else if (request.command == 'disconnect') {
1410 this.disconnectRequest_(request, response);
1411 } else if (request.command == 'setexceptionbreak') {
1412 this.setExceptionBreakRequest_(request, response);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001413 } else if (request.command == 'listbreakpoints') {
1414 this.listBreakpointsRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001415 } else if (request.command == 'backtrace') {
1416 this.backtraceRequest_(request, response);
1417 } else if (request.command == 'frame') {
1418 this.frameRequest_(request, response);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001419 } else if (request.command == 'scopes') {
1420 this.scopesRequest_(request, response);
1421 } else if (request.command == 'scope') {
1422 this.scopeRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423 } else if (request.command == 'evaluate') {
1424 this.evaluateRequest_(request, response);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001425 } else if (lol_is_enabled && request.command == 'getobj') {
1426 this.getobjRequest_(request, response);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001427 } else if (request.command == 'lookup') {
1428 this.lookupRequest_(request, response);
iposva@chromium.org245aa852009-02-10 00:49:54 +00001429 } else if (request.command == 'references') {
1430 this.referencesRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001431 } else if (request.command == 'source') {
1432 this.sourceRequest_(request, response);
1433 } else if (request.command == 'scripts') {
1434 this.scriptsRequest_(request, response);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001435 } else if (request.command == 'threads') {
1436 this.threadsRequest_(request, response);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001437 } else if (request.command == 'suspend') {
1438 this.suspendRequest_(request, response);
ager@chromium.org3811b432009-10-28 14:53:37 +00001439 } else if (request.command == 'version') {
1440 this.versionRequest_(request, response);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001441 } else if (request.command == 'profile') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001442 this.profileRequest_(request, response);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001443 } else if (request.command == 'changelive') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001444 this.changeLiveRequest_(request, response);
1445 } else if (request.command == 'flags') {
1446 this.debuggerFlagsRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001447 } else if (request.command == 'v8flags') {
1448 this.v8FlagsRequest_(request, response);
1449
1450 // GC tools:
1451 } else if (request.command == 'gc') {
1452 this.gcRequest_(request, response);
1453
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001454 // LiveObjectList tools:
1455 } else if (lol_is_enabled && request.command == 'lol-capture') {
1456 this.lolCaptureRequest_(request, response);
1457 } else if (lol_is_enabled && request.command == 'lol-delete') {
1458 this.lolDeleteRequest_(request, response);
1459 } else if (lol_is_enabled && request.command == 'lol-diff') {
1460 this.lolDiffRequest_(request, response);
1461 } else if (lol_is_enabled && request.command == 'lol-getid') {
1462 this.lolGetIdRequest_(request, response);
1463 } else if (lol_is_enabled && request.command == 'lol-info') {
1464 this.lolInfoRequest_(request, response);
1465 } else if (lol_is_enabled && request.command == 'lol-reset') {
1466 this.lolResetRequest_(request, response);
1467 } else if (lol_is_enabled && request.command == 'lol-retainers') {
1468 this.lolRetainersRequest_(request, response);
1469 } else if (lol_is_enabled && request.command == 'lol-path') {
1470 this.lolPathRequest_(request, response);
1471 } else if (lol_is_enabled && request.command == 'lol-print') {
1472 this.lolPrintRequest_(request, response);
1473 } else if (lol_is_enabled && request.command == 'lol-stats') {
1474 this.lolStatsRequest_(request, response);
1475
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001476 } else {
1477 throw new Error('Unknown command "' + request.command + '" in request');
1478 }
1479 } catch (e) {
1480 // If there is no response object created one (without command).
1481 if (!response) {
1482 response = this.createResponse();
1483 }
1484 response.success = false;
1485 response.message = %ToString(e);
1486 }
1487
1488 // Return the response as a JSON encoded string.
1489 try {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001490 if (!IS_UNDEFINED(response.running)) {
1491 // Response controls running state.
1492 this.running_ = response.running;
1493 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00001494 response.running = this.running_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001495 return response.toJSONProtocol();
1496 } catch (e) {
1497 // Failed to generate response - return generic error.
1498 return '{"seq":' + response.seq + ',' +
1499 '"request_seq":' + request.seq + ',' +
1500 '"type":"response",' +
1501 '"success":false,' +
1502 '"message":"Internal error: ' + %ToString(e) + '"}';
1503 }
1504 } catch (e) {
1505 // Failed in one of the catch blocks above - most generic error.
1506 return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
1507 }
1508};
1509
1510
1511DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
1512 // Check for arguments for continue.
1513 if (request.arguments) {
1514 var count = 1;
1515 var action = Debug.StepAction.StepIn;
1516
1517 // Pull out arguments.
1518 var stepaction = request.arguments.stepaction;
1519 var stepcount = request.arguments.stepcount;
1520
1521 // Get the stepcount argument if any.
1522 if (stepcount) {
1523 count = %ToNumber(stepcount);
1524 if (count < 0) {
1525 throw new Error('Invalid stepcount argument "' + stepcount + '".');
1526 }
1527 }
1528
1529 // Get the stepaction argument.
1530 if (stepaction) {
1531 if (stepaction == 'in') {
1532 action = Debug.StepAction.StepIn;
1533 } else if (stepaction == 'min') {
1534 action = Debug.StepAction.StepMin;
1535 } else if (stepaction == 'next') {
1536 action = Debug.StepAction.StepNext;
1537 } else if (stepaction == 'out') {
1538 action = Debug.StepAction.StepOut;
1539 } else {
1540 throw new Error('Invalid stepaction argument "' + stepaction + '".');
1541 }
1542 }
1543
1544 // Setup the VM for stepping.
1545 this.exec_state_.prepareStep(action, count);
1546 }
1547
1548 // VM should be running after executing this request.
1549 response.running = true;
1550};
1551
1552
1553DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
1554 // Ignore as break command does not do anything when broken.
1555};
1556
1557
1558DebugCommandProcessor.prototype.setBreakPointRequest_ =
1559 function(request, response) {
1560 // Check for legal request.
1561 if (!request.arguments) {
1562 response.failed('Missing arguments');
1563 return;
1564 }
1565
1566 // Pull out arguments.
1567 var type = request.arguments.type;
1568 var target = request.arguments.target;
1569 var line = request.arguments.line;
1570 var column = request.arguments.column;
1571 var enabled = IS_UNDEFINED(request.arguments.enabled) ?
1572 true : request.arguments.enabled;
1573 var condition = request.arguments.condition;
1574 var ignoreCount = request.arguments.ignoreCount;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001575 var groupId = request.arguments.groupId;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001576
1577 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001578 if (!type || IS_UNDEFINED(target)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579 response.failed('Missing argument "type" or "target"');
1580 return;
1581 }
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001582
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583 // Either function or script break point.
1584 var break_point_number;
1585 if (type == 'function') {
1586 // Handle function break point.
1587 if (!IS_STRING(target)) {
1588 response.failed('Argument "target" is not a string value');
1589 return;
1590 }
1591 var f;
1592 try {
1593 // Find the function through a global evaluate.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001594 f = this.exec_state_.evaluateGlobal(target).value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001595 } catch (e) {
1596 response.failed('Error: "' + %ToString(e) +
1597 '" evaluating "' + target + '"');
1598 return;
1599 }
1600 if (!IS_FUNCTION(f)) {
1601 response.failed('"' + target + '" does not evaluate to a function');
1602 return;
1603 }
1604
1605 // Set function break point.
1606 break_point_number = Debug.setBreakPoint(f, line, column, condition);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001607 } else if (type == 'handle') {
1608 // Find the object pointed by the specified handle.
1609 var handle = parseInt(target, 10);
1610 var mirror = LookupMirror(handle);
1611 if (!mirror) {
1612 return response.failed('Object #' + handle + '# not found');
1613 }
1614 if (!mirror.isFunction()) {
1615 return response.failed('Object #' + handle + '# is not a function');
1616 }
1617
1618 // Set function break point.
1619 break_point_number = Debug.setBreakPoint(mirror.value(),
1620 line, column, condition);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001621 } else if (type == 'script') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001622 // set script break point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001623 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001624 Debug.setScriptBreakPointByName(target, line, column, condition,
1625 groupId);
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001626 } else if (type == 'scriptId') {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001627 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001628 Debug.setScriptBreakPointById(target, line, column, condition, groupId);
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001629 } else if (type == 'scriptRegExp') {
1630 break_point_number =
1631 Debug.setScriptBreakPointByRegExp(target, line, column, condition,
1632 groupId);
1633 } else {
1634 response.failed('Illegal type "' + type + '"');
1635 return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001636 }
1637
1638 // Set additional break point properties.
1639 var break_point = Debug.findBreakPoint(break_point_number);
1640 if (ignoreCount) {
1641 Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
1642 }
1643 if (!enabled) {
1644 Debug.disableBreakPoint(break_point_number);
1645 }
1646
1647 // Add the break point number to the response.
1648 response.body = { type: type,
1649 breakpoint: break_point_number }
1650
1651 // Add break point information to the response.
1652 if (break_point instanceof ScriptBreakPoint) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001653 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1654 response.body.type = 'scriptId';
1655 response.body.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001656 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001657 response.body.type = 'scriptName';
1658 response.body.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001659 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1660 response.body.type = 'scriptRegExp';
1661 response.body.script_regexp = break_point.script_regexp_object().source;
1662 } else {
1663 throw new Error("Internal error: Unexpected breakpoint type: " + break_point.type());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001664 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001665 response.body.line = break_point.line();
1666 response.body.column = break_point.column();
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001667 response.body.actual_locations = break_point.actual_locations();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668 } else {
1669 response.body.type = 'function';
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001670 response.body.actual_locations = [break_point.actual_location];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001671 }
1672};
1673
1674
1675DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(request, response) {
1676 // Check for legal request.
1677 if (!request.arguments) {
1678 response.failed('Missing arguments');
1679 return;
1680 }
1681
1682 // Pull out arguments.
1683 var break_point = %ToNumber(request.arguments.breakpoint);
1684 var enabled = request.arguments.enabled;
1685 var condition = request.arguments.condition;
1686 var ignoreCount = request.arguments.ignoreCount;
1687
1688 // Check for legal arguments.
1689 if (!break_point) {
1690 response.failed('Missing argument "breakpoint"');
1691 return;
1692 }
1693
1694 // Change enabled state if supplied.
1695 if (!IS_UNDEFINED(enabled)) {
1696 if (enabled) {
1697 Debug.enableBreakPoint(break_point);
1698 } else {
1699 Debug.disableBreakPoint(break_point);
1700 }
1701 }
1702
1703 // Change condition if supplied
1704 if (!IS_UNDEFINED(condition)) {
1705 Debug.changeBreakPointCondition(break_point, condition);
1706 }
1707
1708 // Change ignore count if supplied
1709 if (!IS_UNDEFINED(ignoreCount)) {
1710 Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
1711 }
1712}
1713
1714
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001715DebugCommandProcessor.prototype.clearBreakPointGroupRequest_ = function(request, response) {
1716 // Check for legal request.
1717 if (!request.arguments) {
1718 response.failed('Missing arguments');
1719 return;
1720 }
1721
1722 // Pull out arguments.
1723 var group_id = request.arguments.groupId;
1724
1725 // Check for legal arguments.
1726 if (!group_id) {
1727 response.failed('Missing argument "groupId"');
1728 return;
1729 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001730
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001731 var cleared_break_points = [];
1732 var new_script_break_points = [];
1733 for (var i = 0; i < script_break_points.length; i++) {
1734 var next_break_point = script_break_points[i];
1735 if (next_break_point.groupId() == group_id) {
1736 cleared_break_points.push(next_break_point.number());
1737 next_break_point.clear();
1738 } else {
1739 new_script_break_points.push(next_break_point);
1740 }
1741 }
1742 script_break_points = new_script_break_points;
1743
1744 // Add the cleared break point numbers to the response.
1745 response.body = { breakpoints: cleared_break_points };
1746}
1747
1748
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(request, response) {
1750 // Check for legal request.
1751 if (!request.arguments) {
1752 response.failed('Missing arguments');
1753 return;
1754 }
1755
1756 // Pull out arguments.
1757 var break_point = %ToNumber(request.arguments.breakpoint);
1758
1759 // Check for legal arguments.
1760 if (!break_point) {
1761 response.failed('Missing argument "breakpoint"');
1762 return;
1763 }
1764
1765 // Clear break point.
1766 Debug.clearBreakPoint(break_point);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001767
1768 // Add the cleared break point number to the response.
1769 response.body = { breakpoint: break_point }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001770}
1771
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001772
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001773DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(request, response) {
1774 var array = [];
1775 for (var i = 0; i < script_break_points.length; i++) {
1776 var break_point = script_break_points[i];
1777
1778 var description = {
1779 number: break_point.number(),
1780 line: break_point.line(),
1781 column: break_point.column(),
1782 groupId: break_point.groupId(),
1783 hit_count: break_point.hit_count(),
1784 active: break_point.active(),
1785 condition: break_point.condition(),
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001786 ignoreCount: break_point.ignoreCount(),
1787 actual_locations: break_point.actual_locations()
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001788 }
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001789
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001790 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1791 description.type = 'scriptId';
1792 description.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001793 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001794 description.type = 'scriptName';
1795 description.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001796 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1797 description.type = 'scriptRegExp';
1798 description.script_regexp = break_point.script_regexp_object().source;
1799 } else {
1800 throw new Error("Internal error: Unexpected breakpoint type: " + break_point.type());
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001801 }
1802 array.push(description);
1803 }
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001804
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001805 response.body = {
1806 breakpoints: array,
1807 breakOnExceptions: Debug.isBreakOnException(),
1808 breakOnUncaughtExceptions: Debug.isBreakOnUncaughtException()
1809 }
1810}
1811
1812
1813DebugCommandProcessor.prototype.disconnectRequest_ =
1814 function(request, response) {
1815 Debug.disableAllBreakPoints();
1816 this.continueRequest_(request, response);
1817}
1818
1819
1820DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
1821 function(request, response) {
1822 // Check for legal request.
1823 if (!request.arguments) {
1824 response.failed('Missing arguments');
1825 return;
1826 }
1827
1828 // Pull out and check the 'type' argument:
1829 var type = request.arguments.type;
1830 if (!type) {
1831 response.failed('Missing argument "type"');
1832 return;
1833 }
1834
1835 // Initialize the default value of enable:
1836 var enabled;
1837 if (type == 'all') {
1838 enabled = !Debug.isBreakOnException();
1839 } else if (type == 'uncaught') {
1840 enabled = !Debug.isBreakOnUncaughtException();
1841 }
1842
1843 // Pull out and check the 'enabled' argument if present:
1844 if (!IS_UNDEFINED(request.arguments.enabled)) {
1845 enabled = request.arguments.enabled;
1846 if ((enabled != true) && (enabled != false)) {
1847 response.failed('Illegal value for "enabled":"' + enabled + '"');
1848 }
1849 }
1850
1851 // Now set the exception break state:
1852 if (type == 'all') {
1853 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, enabled);
1854 } else if (type == 'uncaught') {
1855 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, enabled);
1856 } else {
1857 response.failed('Unknown "type":"' + type + '"');
1858 }
1859
1860 // Add the cleared break point number to the response.
1861 response.body = { 'type': type, 'enabled': enabled };
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001862}
1863
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001864
1865DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) {
1866 // Get the number of frames.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001867 var total_frames = this.exec_state_.frameCount();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001868
ager@chromium.org8bb60582008-12-11 12:02:20 +00001869 // Create simple response if there are no frames.
1870 if (total_frames == 0) {
1871 response.body = {
1872 totalFrames: total_frames
1873 }
1874 return;
1875 }
1876
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001877 // Default frame range to include in backtrace.
1878 var from_index = 0
1879 var to_index = kDefaultBacktraceLength;
1880
1881 // Get the range from the arguments.
1882 if (request.arguments) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001883 if (request.arguments.fromFrame) {
1884 from_index = request.arguments.fromFrame;
1885 }
1886 if (request.arguments.toFrame) {
1887 to_index = request.arguments.toFrame;
1888 }
1889 if (request.arguments.bottom) {
1890 var tmp_index = total_frames - from_index;
1891 from_index = total_frames - to_index
1892 to_index = tmp_index;
1893 }
1894 if (from_index < 0 || to_index < 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001895 return response.failed('Invalid frame number');
1896 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001897 }
1898
1899 // Adjust the index.
1900 to_index = Math.min(total_frames, to_index);
1901
1902 if (to_index <= from_index) {
1903 var error = 'Invalid frame range';
1904 return response.failed(error);
1905 }
1906
1907 // Create the response body.
1908 var frames = [];
1909 for (var i = from_index; i < to_index; i++) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001910 frames.push(this.exec_state_.frame(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001911 }
1912 response.body = {
1913 fromFrame: from_index,
1914 toFrame: to_index,
1915 totalFrames: total_frames,
1916 frames: frames
1917 }
1918};
1919
1920
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001921DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001922 // No frames no source.
1923 if (this.exec_state_.frameCount() == 0) {
1924 return response.failed('No frames');
1925 }
1926
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001927 // With no arguments just keep the selected frame.
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001928 if (request.arguments) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001929 var index = request.arguments.number;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001930 if (index < 0 || this.exec_state_.frameCount() <= index) {
1931 return response.failed('Invalid frame number');
1932 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001933
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001934 this.exec_state_.setSelectedFrame(request.arguments.number);
1935 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001936 response.body = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001937};
1938
1939
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001940DebugCommandProcessor.prototype.frameForScopeRequest_ = function(request) {
1941 // Get the frame for which the scope or scopes are requested. With no frameNumber
1942 // argument use the currently selected frame.
1943 if (request.arguments && !IS_UNDEFINED(request.arguments.frameNumber)) {
1944 frame_index = request.arguments.frameNumber;
1945 if (frame_index < 0 || this.exec_state_.frameCount() <= frame_index) {
1946 return response.failed('Invalid frame number');
1947 }
1948 return this.exec_state_.frame(frame_index);
1949 } else {
1950 return this.exec_state_.frame();
1951 }
1952}
1953
1954
1955DebugCommandProcessor.prototype.scopesRequest_ = function(request, response) {
1956 // No frames no scopes.
1957 if (this.exec_state_.frameCount() == 0) {
1958 return response.failed('No scopes');
1959 }
1960
1961 // Get the frame for which the scopes are requested.
1962 var frame = this.frameForScopeRequest_(request);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001963
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001964 // Fill all scopes for this frame.
1965 var total_scopes = frame.scopeCount();
1966 var scopes = [];
1967 for (var i = 0; i < total_scopes; i++) {
1968 scopes.push(frame.scope(i));
1969 }
1970 response.body = {
1971 fromScope: 0,
1972 toScope: total_scopes,
1973 totalScopes: total_scopes,
1974 scopes: scopes
1975 }
1976};
1977
1978
1979DebugCommandProcessor.prototype.scopeRequest_ = function(request, response) {
1980 // No frames no scopes.
1981 if (this.exec_state_.frameCount() == 0) {
1982 return response.failed('No scopes');
1983 }
1984
1985 // Get the frame for which the scope is requested.
1986 var frame = this.frameForScopeRequest_(request);
1987
1988 // With no scope argument just return top scope.
1989 var scope_index = 0;
1990 if (request.arguments && !IS_UNDEFINED(request.arguments.number)) {
1991 scope_index = %ToNumber(request.arguments.number);
1992 if (scope_index < 0 || frame.scopeCount() <= scope_index) {
1993 return response.failed('Invalid scope number');
1994 }
1995 }
1996
1997 response.body = frame.scope(scope_index);
1998};
1999
2000
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002001DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
2002 if (!request.arguments) {
2003 return response.failed('Missing arguments');
2004 }
2005
2006 // Pull out arguments.
2007 var expression = request.arguments.expression;
2008 var frame = request.arguments.frame;
2009 var global = request.arguments.global;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002010 var disable_break = request.arguments.disable_break;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002011 var additional_context = request.arguments.additional_context;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002012
2013 // The expression argument could be an integer so we convert it to a
2014 // string.
2015 try {
2016 expression = String(expression);
2017 } catch(e) {
2018 return response.failed('Failed to convert expression argument to string');
2019 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002020
2021 // Check for legal arguments.
2022 if (!IS_UNDEFINED(frame) && global) {
2023 return response.failed('Arguments "frame" and "global" are exclusive');
2024 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002025
2026 var additional_context_object;
2027 if (additional_context) {
2028 additional_context_object = {};
2029 for (var i = 0; i < additional_context.length; i++) {
2030 var mapping = additional_context[i];
2031 if (!IS_STRING(mapping.name) || !IS_NUMBER(mapping.handle)) {
2032 return response.failed("Context element #" + i +
2033 " must contain name:string and handle:number");
2034 }
2035 var context_value_mirror = LookupMirror(mapping.handle);
2036 if (!context_value_mirror) {
2037 return response.failed("Context object '" + mapping.name +
2038 "' #" + mapping.handle + "# not found");
2039 }
2040 additional_context_object[mapping.name] = context_value_mirror.value();
2041 }
2042 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002043
2044 // Global evaluate.
2045 if (global) {
2046 // Evaluate in the global context.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002047 response.body = this.exec_state_.evaluateGlobal(
2048 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002049 return;
2050 }
2051
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002052 // Default value for disable_break is true.
2053 if (IS_UNDEFINED(disable_break)) {
2054 disable_break = true;
2055 }
2056
ager@chromium.org381abbb2009-02-25 13:23:22 +00002057 // No frames no evaluate in frame.
2058 if (this.exec_state_.frameCount() == 0) {
2059 return response.failed('No frames');
2060 }
2061
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002062 // Check whether a frame was specified.
2063 if (!IS_UNDEFINED(frame)) {
2064 var frame_number = %ToNumber(frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002065 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002066 return response.failed('Invalid frame "' + frame + '"');
2067 }
2068 // Evaluate in the specified frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002069 response.body = this.exec_state_.frame(frame_number).evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002070 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002071 return;
2072 } else {
2073 // Evaluate in the selected frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002074 response.body = this.exec_state_.frame().evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002075 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002076 return;
2077 }
2078};
2079
2080
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00002081DebugCommandProcessor.prototype.getobjRequest_ = function(request, response) {
2082 if (!request.arguments) {
2083 return response.failed('Missing arguments');
2084 }
2085
2086 // Pull out arguments.
2087 var obj_id = request.arguments.obj_id;
2088
2089 // Check for legal arguments.
2090 if (IS_UNDEFINED(obj_id)) {
2091 return response.failed('Argument "obj_id" missing');
2092 }
2093
2094 // Dump the object.
2095 response.body = MakeMirror(%GetLOLObj(obj_id));
2096};
2097
2098
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002099DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
2100 if (!request.arguments) {
2101 return response.failed('Missing arguments');
2102 }
2103
2104 // Pull out arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002105 var handles = request.arguments.handles;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002106
2107 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002108 if (IS_UNDEFINED(handles)) {
2109 return response.failed('Argument "handles" missing');
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002110 }
2111
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002112 // Set 'includeSource' option for script lookup.
2113 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2114 includeSource = %ToBoolean(request.arguments.includeSource);
2115 response.setOption('includeSource', includeSource);
2116 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00002117
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002118 // Lookup handles.
2119 var mirrors = {};
2120 for (var i = 0; i < handles.length; i++) {
2121 var handle = handles[i];
2122 var mirror = LookupMirror(handle);
2123 if (!mirror) {
2124 return response.failed('Object #' + handle + '# not found');
2125 }
2126 mirrors[handle] = mirror;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002127 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002128 response.body = mirrors;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002129};
2130
2131
iposva@chromium.org245aa852009-02-10 00:49:54 +00002132DebugCommandProcessor.prototype.referencesRequest_ =
2133 function(request, response) {
2134 if (!request.arguments) {
2135 return response.failed('Missing arguments');
2136 }
2137
2138 // Pull out arguments.
2139 var type = request.arguments.type;
2140 var handle = request.arguments.handle;
2141
2142 // Check for legal arguments.
2143 if (IS_UNDEFINED(type)) {
2144 return response.failed('Argument "type" missing');
2145 }
2146 if (IS_UNDEFINED(handle)) {
2147 return response.failed('Argument "handle" missing');
2148 }
2149 if (type != 'referencedBy' && type != 'constructedBy') {
2150 return response.failed('Invalid type "' + type + '"');
2151 }
2152
2153 // Lookup handle and return objects with references the object.
2154 var mirror = LookupMirror(handle);
2155 if (mirror) {
2156 if (type == 'referencedBy') {
2157 response.body = mirror.referencedBy();
2158 } else {
2159 response.body = mirror.constructedBy();
2160 }
2161 } else {
2162 return response.failed('Object #' + handle + '# not found');
2163 }
2164};
2165
2166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002167DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00002168 // No frames no source.
2169 if (this.exec_state_.frameCount() == 0) {
2170 return response.failed('No source');
2171 }
2172
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002173 var from_line;
2174 var to_line;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002175 var frame = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002176 if (request.arguments) {
2177 // Pull out arguments.
2178 from_line = request.arguments.fromLine;
2179 to_line = request.arguments.toLine;
2180
2181 if (!IS_UNDEFINED(request.arguments.frame)) {
2182 var frame_number = %ToNumber(request.arguments.frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002183 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002184 return response.failed('Invalid frame "' + frame + '"');
2185 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002186 frame = this.exec_state_.frame(frame_number);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002187 }
2188 }
2189
2190 // Get the script selected.
2191 var script = frame.func().script();
2192 if (!script) {
2193 return response.failed('No source');
2194 }
2195
2196 // Get the source slice and fill it into the response.
2197 var slice = script.sourceSlice(from_line, to_line);
2198 if (!slice) {
2199 return response.failed('Invalid line interval');
2200 }
2201 response.body = {};
2202 response.body.source = slice.sourceText();
2203 response.body.fromLine = slice.from_line;
2204 response.body.toLine = slice.to_line;
2205 response.body.fromPosition = slice.from_position;
2206 response.body.toPosition = slice.to_position;
2207 response.body.totalLines = script.lineCount();
2208};
2209
2210
2211DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
2212 var types = ScriptTypeFlag(Debug.ScriptType.Normal);
ager@chromium.org41826e72009-03-30 13:30:57 +00002213 var includeSource = false;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002214 var idsToInclude = null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002215 if (request.arguments) {
2216 // Pull out arguments.
2217 if (!IS_UNDEFINED(request.arguments.types)) {
2218 types = %ToNumber(request.arguments.types);
2219 if (isNaN(types) || types < 0) {
2220 return response.failed('Invalid types "' + request.arguments.types + '"');
2221 }
2222 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002223
ager@chromium.org41826e72009-03-30 13:30:57 +00002224 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2225 includeSource = %ToBoolean(request.arguments.includeSource);
ager@chromium.org9085a012009-05-11 19:22:57 +00002226 response.setOption('includeSource', includeSource);
ager@chromium.org41826e72009-03-30 13:30:57 +00002227 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002228
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002229 if (IS_ARRAY(request.arguments.ids)) {
2230 idsToInclude = {};
2231 var ids = request.arguments.ids;
2232 for (var i = 0; i < ids.length; i++) {
2233 idsToInclude[ids[i]] = true;
2234 }
2235 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002236
2237 var filterStr = null;
2238 var filterNum = null;
2239 if (!IS_UNDEFINED(request.arguments.filter)) {
2240 var num = %ToNumber(request.arguments.filter);
2241 if (!isNaN(num)) {
2242 filterNum = num;
2243 }
2244 filterStr = request.arguments.filter;
2245 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002246 }
2247
2248 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +00002249 var scripts = %DebugGetLoadedScripts();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002250
2251 response.body = [];
2252
2253 for (var i = 0; i < scripts.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002254 if (idsToInclude && !idsToInclude[scripts[i].id]) {
2255 continue;
2256 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002257 if (filterStr || filterNum) {
2258 var script = scripts[i];
2259 var found = false;
2260 if (filterNum && !found) {
2261 if (script.id && script.id === filterNum) {
2262 found = true;
2263 }
2264 }
2265 if (filterStr && !found) {
2266 if (script.name && script.name.indexOf(filterStr) >= 0) {
2267 found = true;
2268 }
2269 }
2270 if (!found) continue;
2271 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002272 if (types & ScriptTypeFlag(scripts[i].type)) {
ager@chromium.org9085a012009-05-11 19:22:57 +00002273 response.body.push(MakeMirror(scripts[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002274 }
2275 }
2276};
2277
2278
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002279DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
2280 // Get the number of threads.
2281 var total_threads = this.exec_state_.threadCount();
2282
2283 // Get information for all threads.
2284 var threads = [];
2285 for (var i = 0; i < total_threads; i++) {
2286 var details = %GetThreadDetails(this.exec_state_.break_id, i);
2287 var thread_info = { current: details[0],
2288 id: details[1]
2289 }
2290 threads.push(thread_info);
2291 }
2292
2293 // Create the response body.
2294 response.body = {
2295 totalThreads: total_threads,
2296 threads: threads
2297 }
2298};
2299
2300
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002301DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002302 response.running = false;
2303};
2304
2305
ager@chromium.org3811b432009-10-28 14:53:37 +00002306DebugCommandProcessor.prototype.versionRequest_ = function(request, response) {
2307 response.body = {
2308 V8Version: %GetV8Version()
2309 }
2310};
2311
2312
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002313DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002314 if (request.arguments.command == 'resume') {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002315 %ProfilerResume();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002316 } else if (request.arguments.command == 'pause') {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002317 %ProfilerPause();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002318 } else {
2319 return response.failed('Unknown command');
2320 }
2321 response.body = {};
2322};
2323
2324
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002325DebugCommandProcessor.prototype.changeLiveRequest_ = function(request, response) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002326 if (!Debug.LiveEdit) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002327 return response.failed('LiveEdit feature is not supported');
2328 }
2329 if (!request.arguments) {
2330 return response.failed('Missing arguments');
2331 }
2332 var script_id = request.arguments.script_id;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002333 var preview_only = !!request.arguments.preview_only;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002334
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002335 var scripts = %DebugGetLoadedScripts();
2336
2337 var the_script = null;
2338 for (var i = 0; i < scripts.length; i++) {
2339 if (scripts[i].id == script_id) {
2340 the_script = scripts[i];
2341 }
2342 }
2343 if (!the_script) {
2344 response.failed('Script not found');
2345 return;
2346 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002347
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002348 var change_log = new Array();
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002349
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002350 if (!IS_STRING(request.arguments.new_source)) {
2351 throw "new_source argument expected";
lrn@chromium.org25156de2010-04-06 13:10:27 +00002352 }
2353
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002354 var new_source = request.arguments.new_source;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002355
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002356 var result_description = Debug.LiveEdit.SetScriptSource(the_script,
2357 new_source, preview_only, change_log);
2358 response.body = {change_log: change_log, result: result_description};
vegorov@chromium.org42841962010-10-18 11:18:59 +00002359
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002360 if (!preview_only && !this.running_ && result_description.stack_modified) {
2361 response.body.stepin_recommended = true;
2362 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002363};
2364
2365
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002366DebugCommandProcessor.prototype.debuggerFlagsRequest_ = function(request,
2367 response) {
2368 // Check for legal request.
2369 if (!request.arguments) {
2370 response.failed('Missing arguments');
2371 return;
2372 }
2373
2374 // Pull out arguments.
2375 var flags = request.arguments.flags;
2376
2377 response.body = { flags: [] };
2378 if (!IS_UNDEFINED(flags)) {
2379 for (var i = 0; i < flags.length; i++) {
2380 var name = flags[i].name;
2381 var debugger_flag = debugger_flags[name];
2382 if (!debugger_flag) {
2383 continue;
2384 }
2385 if ('value' in flags[i]) {
2386 debugger_flag.setValue(flags[i].value);
2387 }
2388 response.body.flags.push({ name: name, value: debugger_flag.getValue() });
2389 }
2390 } else {
2391 for (var name in debugger_flags) {
2392 var value = debugger_flags[name].getValue();
2393 response.body.flags.push({ name: name, value: value });
2394 }
2395 }
2396}
2397
2398
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002399DebugCommandProcessor.prototype.v8FlagsRequest_ = function(request, response) {
2400 var flags = request.arguments.flags;
2401 if (!flags) flags = '';
2402 %SetFlags(flags);
2403};
2404
2405
2406DebugCommandProcessor.prototype.gcRequest_ = function(request, response) {
2407 var type = request.arguments.type;
2408 if (!type) type = 'all';
2409
2410 var before = %GetHeapUsage();
2411 %CollectGarbage(type);
2412 var after = %GetHeapUsage();
2413
2414 response.body = { "before": before, "after": after };
2415};
2416
2417
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00002418DebugCommandProcessor.prototype.lolCaptureRequest_ =
2419 function(request, response) {
2420 response.body = %CaptureLOL();
2421};
2422
2423
2424DebugCommandProcessor.prototype.lolDeleteRequest_ =
2425 function(request, response) {
2426 var id = request.arguments.id;
2427 var result = %DeleteLOL(id);
2428 if (result) {
2429 response.body = { id: id };
2430 } else {
2431 response.failed('Failed to delete: live object list ' + id + ' not found.');
2432 }
2433};
2434
2435
2436DebugCommandProcessor.prototype.lolDiffRequest_ = function(request, response) {
2437 var id1 = request.arguments.id1;
2438 var id2 = request.arguments.id2;
2439 var verbose = request.arguments.verbose;
2440 var filter = request.arguments.filter;
2441 if (verbose === true) {
2442 var start = request.arguments.start;
2443 var count = request.arguments.count;
2444 response.body = %DumpLOL(id1, id2, start, count, filter);
2445 } else {
2446 response.body = %SummarizeLOL(id1, id2, filter);
2447 }
2448};
2449
2450
2451DebugCommandProcessor.prototype.lolGetIdRequest_ = function(request, response) {
2452 var address = request.arguments.address;
2453 response.body = {};
2454 response.body.id = %GetLOLObjId(address);
2455};
2456
2457
2458DebugCommandProcessor.prototype.lolInfoRequest_ = function(request, response) {
2459 var start = request.arguments.start;
2460 var count = request.arguments.count;
2461 response.body = %InfoLOL(start, count);
2462};
2463
2464
2465DebugCommandProcessor.prototype.lolResetRequest_ = function(request, response) {
2466 %ResetLOL();
2467};
2468
2469
2470DebugCommandProcessor.prototype.lolRetainersRequest_ =
2471 function(request, response) {
2472 var id = request.arguments.id;
2473 var verbose = request.arguments.verbose;
2474 var start = request.arguments.start;
2475 var count = request.arguments.count;
2476 var filter = request.arguments.filter;
2477
2478 response.body = %GetLOLObjRetainers(id, Mirror.prototype, verbose,
2479 start, count, filter);
2480};
2481
2482
2483DebugCommandProcessor.prototype.lolPathRequest_ = function(request, response) {
2484 var id1 = request.arguments.id1;
2485 var id2 = request.arguments.id2;
2486 response.body = {};
2487 response.body.path = %GetLOLPath(id1, id2, Mirror.prototype);
2488};
2489
2490
2491DebugCommandProcessor.prototype.lolPrintRequest_ = function(request, response) {
2492 var id = request.arguments.id;
2493 response.body = {};
2494 response.body.dump = %PrintLOLObj(id);
2495};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002496
2497
iposva@chromium.org245aa852009-02-10 00:49:54 +00002498// Check whether the previously processed command caused the VM to become
2499// running.
2500DebugCommandProcessor.prototype.isRunning = function() {
2501 return this.running_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002502}
2503
2504
2505DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
mads.s.ager31e71382008-08-13 09:32:07 +00002506 return %SystemBreak();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002507};
2508
2509
2510function NumberToHex8Str(n) {
2511 var r = "";
2512 for (var i = 0; i < 8; ++i) {
2513 var c = hexCharArray[n & 0x0F]; // hexCharArray is defined in uri.js
2514 r = c + r;
2515 n = n >>> 4;
2516 }
2517 return r;
2518};
2519
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002520
2521/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002522 * Convert an Object to its debugger protocol representation. The representation
2523 * may be serilized to a JSON object using JSON.stringify().
2524 * This implementation simply runs through all string property names, converts
2525 * each property value to a protocol value and adds the property to the result
2526 * object. For type "object" the function will be called recursively. Note that
2527 * circular structures will cause infinite recursion.
2528 * @param {Object} object The object to format as protocol object.
ager@chromium.org32912102009-01-16 10:38:43 +00002529 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2530 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002531 * @return {Object} Protocol object value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002532 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002533function ObjectToProtocolObject_(object, mirror_serializer) {
2534 var content = {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002535 for (var key in object) {
2536 // Only consider string keys.
2537 if (typeof key == 'string') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002538 // Format the value based on its type.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002539 var property_value_json = ValueToProtocolValue_(object[key],
2540 mirror_serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002541 // Add the property if relevant.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002542 if (!IS_UNDEFINED(property_value_json)) {
2543 content[key] = property_value_json;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002544 }
2545 }
2546 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002547
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002548 return content;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002549}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002550
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002551
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002552/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002553 * Convert an array to its debugger protocol representation. It will convert
2554 * each array element to a protocol value.
2555 * @param {Array} array The array to format as protocol array.
ager@chromium.org32912102009-01-16 10:38:43 +00002556 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2557 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002558 * @return {Array} Protocol array value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002559 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002560function ArrayToProtocolArray_(array, mirror_serializer) {
2561 var json = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002562 for (var i = 0; i < array.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002563 json.push(ValueToProtocolValue_(array[i], mirror_serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002564 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002565 return json;
2566}
2567
2568
2569/**
lrn@chromium.org25156de2010-04-06 13:10:27 +00002570 * Convert a value to its debugger protocol representation.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002571 * @param {*} value The value to format as protocol value.
2572 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2573 * mirror objects are encountered.
2574 * @return {*} Protocol value.
2575 */
2576function ValueToProtocolValue_(value, mirror_serializer) {
2577 // Format the value based on its type.
2578 var json;
2579 switch (typeof value) {
2580 case 'object':
2581 if (value instanceof Mirror) {
2582 json = mirror_serializer.serializeValue(value);
2583 } else if (IS_ARRAY(value)){
2584 json = ArrayToProtocolArray_(value, mirror_serializer);
2585 } else {
2586 json = ObjectToProtocolObject_(value, mirror_serializer);
2587 }
2588 break;
2589
2590 case 'boolean':
2591 case 'string':
2592 case 'number':
2593 json = value;
2594 break
2595
2596 default:
2597 json = null;
2598 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002599 return json;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002600}