blob: 961f304edbcf837021fa6fd3a34ceb4b369eaa12 [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
iposva@chromium.org245aa852009-02-10 00:49:54 +000028// jsminify this file, js2c: jsmin
29
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030// Default number of frames to include in the response to backtrace request.
31const kDefaultBacktraceLength = 10;
32
33const Debug = {};
34
35// Regular expression to skip "crud" at the beginning of a source line which is
36// not really code. Currently the regular expression matches whitespace and
37// comments.
38const sourceLineBeginningSkip = /^(?:[ \v\h]*(?:\/\*.*?\*\/)*)*/;
39
40// Debug events which can occour in the V8 JavaScript engine. These originate
41// from the API include file debug.h.
42Debug.DebugEvent = { Break: 1,
43 Exception: 2,
44 NewFunction: 3,
45 BeforeCompile: 4,
46 AfterCompile: 5 };
47
48// Types of exceptions that can be broken upon.
49Debug.ExceptionBreak = { All : 0,
50 Uncaught: 1 };
51
52// The different types of steps.
53Debug.StepAction = { StepOut: 0,
54 StepNext: 1,
55 StepIn: 2,
56 StepMin: 3,
57 StepInMin: 4 };
58
59// The different types of scripts matching enum ScriptType in objects.h.
60Debug.ScriptType = { Native: 0,
61 Extension: 1,
62 Normal: 2 };
63
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000064// The different script break point types.
65Debug.ScriptBreakPointType = { ScriptId: 0,
66 ScriptName: 1 };
67
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068function ScriptTypeFlag(type) {
69 return (1 << type);
70}
71
72// Globals.
73var next_response_seq = 0;
74var next_break_point_number = 1;
75var break_points = [];
76var script_break_points = [];
77
78
79// Create a new break point object and add it to the list of break points.
80function MakeBreakPoint(source_position, opt_line, opt_column, opt_script_break_point) {
81 var break_point = new BreakPoint(source_position, opt_line, opt_column, opt_script_break_point);
82 break_points.push(break_point);
83 return break_point;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000084}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000085
86
87// Object representing a break point.
88// NOTE: This object does not have a reference to the function having break
89// point as this would cause function not to be garbage collected when it is
90// not used any more. We do not want break points to keep functions alive.
91function BreakPoint(source_position, opt_line, opt_column, opt_script_break_point) {
92 this.source_position_ = source_position;
93 this.source_line_ = opt_line;
94 this.source_column_ = opt_column;
95 if (opt_script_break_point) {
96 this.script_break_point_ = opt_script_break_point;
97 } else {
98 this.number_ = next_break_point_number++;
99 }
100 this.hit_count_ = 0;
101 this.active_ = true;
102 this.condition_ = null;
103 this.ignoreCount_ = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000104}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105
106
107BreakPoint.prototype.number = function() {
108 return this.number_;
109};
110
111
112BreakPoint.prototype.func = function() {
113 return this.func_;
114};
115
116
117BreakPoint.prototype.source_position = function() {
118 return this.source_position_;
119};
120
121
122BreakPoint.prototype.hit_count = function() {
123 return this.hit_count_;
124};
125
126
127BreakPoint.prototype.active = function() {
128 if (this.script_break_point()) {
129 return this.script_break_point().active();
130 }
131 return this.active_;
132};
133
134
135BreakPoint.prototype.condition = function() {
136 if (this.script_break_point() && this.script_break_point().condition()) {
137 return this.script_break_point().condition();
138 }
139 return this.condition_;
140};
141
142
143BreakPoint.prototype.ignoreCount = function() {
144 return this.ignoreCount_;
145};
146
147
148BreakPoint.prototype.script_break_point = function() {
149 return this.script_break_point_;
150};
151
152
153BreakPoint.prototype.enable = function() {
154 this.active_ = true;
155};
156
157
158BreakPoint.prototype.disable = function() {
159 this.active_ = false;
160};
161
162
163BreakPoint.prototype.setCondition = function(condition) {
164 this.condition_ = condition;
165};
166
167
168BreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
169 this.ignoreCount_ = ignoreCount;
170};
171
172
173BreakPoint.prototype.isTriggered = function(exec_state) {
174 // Break point not active - not triggered.
175 if (!this.active()) return false;
176
177 // Check for conditional break point.
178 if (this.condition()) {
179 // If break point has condition try to evaluate it in the top frame.
180 try {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000181 var mirror = exec_state.frame(0).evaluate(this.condition());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 // If no sensible mirror or non true value break point not triggered.
183 if (!(mirror instanceof ValueMirror) || !%ToBoolean(mirror.value_)) {
184 return false;
185 }
186 } catch (e) {
187 // Exception evaluating condition counts as not triggered.
188 return false;
189 }
190 }
191
192 // Update the hit count.
193 this.hit_count_++;
194 if (this.script_break_point_) {
195 this.script_break_point_.hit_count_++;
196 }
197
198 // If the break point has an ignore count it is not triggered.
199 if (this.ignoreCount_ > 0) {
200 this.ignoreCount_--;
201 return false;
202 }
203
204 // Break point triggered.
205 return true;
206};
207
208
209// Function called from the runtime when a break point is hit. Returns true if
210// the break point is triggered and supposed to break execution.
211function IsBreakPointTriggered(break_id, break_point) {
212 return break_point.isTriggered(MakeExecutionState(break_id));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000213}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214
215
216// Object representing a script break point. The script is referenced by its
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000217// script name or script id and the break point is represented as line and
218// column.
219function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column) {
220 this.type_ = type;
221 if (type == Debug.ScriptBreakPointType.ScriptId) {
222 this.script_id_ = script_id_or_name;
223 } else { // type == Debug.ScriptBreakPointType.ScriptName
224 this.script_name_ = script_id_or_name;
225 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226 this.line_ = opt_line || 0;
227 this.column_ = opt_column;
228 this.hit_count_ = 0;
229 this.active_ = true;
230 this.condition_ = null;
231 this.ignoreCount_ = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000232}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233
234
235ScriptBreakPoint.prototype.number = function() {
236 return this.number_;
237};
238
239
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000240ScriptBreakPoint.prototype.type = function() {
241 return this.type_;
242};
243
244
245ScriptBreakPoint.prototype.script_id = function() {
246 return this.script_id_;
247};
248
249
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250ScriptBreakPoint.prototype.script_name = function() {
251 return this.script_name_;
252};
253
254
255ScriptBreakPoint.prototype.line = function() {
256 return this.line_;
257};
258
259
260ScriptBreakPoint.prototype.column = function() {
261 return this.column_;
262};
263
264
265ScriptBreakPoint.prototype.hit_count = function() {
266 return this.hit_count_;
267};
268
269
270ScriptBreakPoint.prototype.active = function() {
271 return this.active_;
272};
273
274
275ScriptBreakPoint.prototype.condition = function() {
276 return this.condition_;
277};
278
279
280ScriptBreakPoint.prototype.ignoreCount = function() {
281 return this.ignoreCount_;
282};
283
284
285ScriptBreakPoint.prototype.enable = function() {
286 this.active_ = true;
287};
288
289
290ScriptBreakPoint.prototype.disable = function() {
291 this.active_ = false;
292};
293
294
295ScriptBreakPoint.prototype.setCondition = function(condition) {
296 this.condition_ = condition;
297};
298
299
300ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
301 this.ignoreCount_ = ignoreCount;
302
303 // Set ignore count on all break points created from this script break point.
304 for (var i = 0; i < break_points.length; i++) {
305 if (break_points[i].script_break_point() === this) {
306 break_points[i].setIgnoreCount(ignoreCount);
307 }
308 }
309};
310
311
312// Check whether a script matches this script break point. Currently this is
313// only based on script name.
314ScriptBreakPoint.prototype.matchesScript = function(script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000315 if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
316 return this.script_id_ == script.id;
317 } else { // this.type_ == Debug.ScriptBreakPointType.ScriptName
318 return this.script_name_ == script.name &&
319 script.line_offset <= this.line_ &&
320 this.line_ < script.line_offset + script.lineCount();
321 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322};
323
324
325// Set the script break point in a script.
326ScriptBreakPoint.prototype.set = function (script) {
327 var column = this.column();
328 var line = this.line();
329 // If the column is undefined the break is on the line. To help locate the
330 // first piece of breakable code on the line try to find the column on the
331 // line which contains some source.
332 if (IS_UNDEFINED(column)) {
333 var source_line = script.sourceLine(this.line());
334
335 // Allocate array for caching the columns where the actual source starts.
336 if (!script.sourceColumnStart_) {
337 script.sourceColumnStart_ = new Array(script.lineCount());
338 }
339
340 // Fill cache if needed and get column where the actual source starts.
341 if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
342 script.sourceColumnStart_[line] =
343 source_line.match(sourceLineBeginningSkip)[0].length;
344 }
345 column = script.sourceColumnStart_[line];
346 }
347
348 // Convert the line and column into an absolute position within the script.
349 var pos = Debug.findScriptSourcePosition(script, this.line(), column);
350
ager@chromium.org8bb60582008-12-11 12:02:20 +0000351 // If the position is not found in the script (the script might be shorter
352 // than it used to be) just ignore it.
353 if (pos === null) return;
354
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355 // Create a break point object and set the break point.
356 break_point = MakeBreakPoint(pos, this.line(), this.column(), this);
357 break_point.setIgnoreCount(this.ignoreCount());
358 %SetScriptBreakPoint(script, pos, break_point);
359
360 return break_point;
361};
362
363
364// Clear all the break points created from this script break point
365ScriptBreakPoint.prototype.clear = function () {
366 var remaining_break_points = [];
367 for (var i = 0; i < break_points.length; i++) {
368 if (break_points[i].script_break_point() &&
369 break_points[i].script_break_point() === this) {
370 %ClearBreakPoint(break_points[i]);
371 } else {
372 remaining_break_points.push(break_points[i]);
373 }
374 }
375 break_points = remaining_break_points;
376};
377
378
379// Function called from runtime when a new script is compiled to set any script
380// break points set in this script.
381function UpdateScriptBreakPoints(script) {
382 for (var i = 0; i < script_break_points.length; i++) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000383 if (script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptName &&
384 script_break_points[i].script_name() == script.name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000385 script_break_points[i].set(script);
386 }
387 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000388}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000389
390
iposva@chromium.org245aa852009-02-10 00:49:54 +0000391Debug.setListener = function(listener, opt_data) {
392 if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
393 throw new Error('Parameters have wrong types.');
394 }
395 %SetDebugEventListener(listener, opt_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396};
397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000399Debug.breakExecution = function(f) {
mads.s.ager31e71382008-08-13 09:32:07 +0000400 %Break();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401};
402
403Debug.breakLocations = function(f) {
404 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
405 return %GetBreakLocations(f);
406};
407
408// Returns a Script object. If the parameter is a function the return value
409// is the script in which the function is defined. If the parameter is a string
410// the return value is the script for which the script name has that string
mads.s.agercbaa0602008-08-14 13:41:48 +0000411// value. If it is a regexp and there is a unique script whose name matches
412// we return that, otherwise undefined.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413Debug.findScript = function(func_or_script_name) {
414 if (IS_FUNCTION(func_or_script_name)) {
415 return %FunctionGetScript(func_or_script_name);
mads.s.agercbaa0602008-08-14 13:41:48 +0000416 } else if (IS_REGEXP(func_or_script_name)) {
417 var scripts = Debug.scripts();
418 var last_result = null;
419 var result_count = 0;
420 for (var i in scripts) {
421 var script = scripts[i];
422 if (func_or_script_name.test(script.name)) {
423 last_result = script;
424 result_count++;
425 }
426 }
427 // Return the unique script matching the regexp. If there are more
428 // than one we don't return a value since there is no good way to
429 // decide which one to return. Returning a "random" one, say the
430 // first, would introduce nondeterminism (or something close to it)
431 // because the order is the heap iteration order.
432 if (result_count == 1) {
433 return last_result;
434 } else {
435 return undefined;
436 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000437 } else {
438 return %GetScript(func_or_script_name);
439 }
440};
441
442// Returns the script source. If the parameter is a function the return value
443// is the script source for the script in which the function is defined. If the
444// parameter is a string the return value is the script for which the script
445// name has that string value.
446Debug.scriptSource = function(func_or_script_name) {
447 return this.findScript(func_or_script_name).source;
448};
449
450Debug.source = function(f) {
451 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
452 return %FunctionGetSourceCode(f);
453};
454
455Debug.assembler = function(f) {
456 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
457 return %FunctionGetAssemblerCode(f);
458};
459
460Debug.sourcePosition = function(f) {
461 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
462 return %FunctionGetScriptSourcePosition(f);
463};
464
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000465
466Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467 var script = %FunctionGetScript(func);
468 var script_offset = %FunctionGetScriptSourcePosition(func);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000469 return script.locationFromLine(opt_line, opt_column, script_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000470}
471
472
473// Returns the character position in a script based on a line number and an
474// optional position within that line.
475Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000476 var location = script.locationFromLine(opt_line, opt_column);
477 return location ? location.position : null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000478}
479
480
481Debug.findBreakPoint = function(break_point_number, remove) {
482 var break_point;
483 for (var i = 0; i < break_points.length; i++) {
484 if (break_points[i].number() == break_point_number) {
485 break_point = break_points[i];
486 // Remove the break point from the list if requested.
487 if (remove) {
488 break_points.splice(i, 1);
489 }
490 break;
491 }
492 }
493 if (break_point) {
494 return break_point;
495 } else {
496 return this.findScriptBreakPoint(break_point_number, remove);
497 }
498};
499
500
501Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
502 if (!IS_FUNCTION(func)) throw new Error('Parameters have wrong types.');
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000503 // Break points in API functions are not supported.
504 if (%FunctionIsAPIFunction(func)) {
505 throw new Error('Cannot set break point in native code.');
506 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000507 // Find source position relative to start of the function
508 var break_position =
509 this.findFunctionSourceLocation(func, opt_line, opt_column).position;
510 var source_position = break_position - this.sourcePosition(func);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511 // Find the script for the function.
512 var script = %FunctionGetScript(func);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000513 // Break in builtin JavaScript code is not supported.
514 if (script.type == Debug.ScriptType.Native) {
515 throw new Error('Cannot set break point in native code.');
516 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517 // If the script for the function has a name convert this to a script break
518 // point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000519 if (script && script.id) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000520 // Adjust the source position to be script relative.
521 source_position += %FunctionGetScriptSourcePosition(func);
522 // Find line and column for the position in the script and set a script
523 // break point from that.
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000524 var location = script.locationFromPosition(source_position, false);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000525 return this.setScriptBreakPointById(script.id,
526 location.line, location.column,
527 opt_condition);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 } else {
529 // Set a break point directly on the function.
530 var break_point = MakeBreakPoint(source_position, opt_line, opt_column);
531 %SetFunctionBreakPoint(func, source_position, break_point);
532 break_point.setCondition(opt_condition);
533 return break_point.number();
534 }
535};
536
537
538Debug.enableBreakPoint = function(break_point_number) {
539 var break_point = this.findBreakPoint(break_point_number, false);
540 break_point.enable();
541};
542
543
544Debug.disableBreakPoint = function(break_point_number) {
545 var break_point = this.findBreakPoint(break_point_number, false);
546 break_point.disable();
547};
548
549
550Debug.changeBreakPointCondition = function(break_point_number, condition) {
551 var break_point = this.findBreakPoint(break_point_number, false);
552 break_point.setCondition(condition);
553};
554
555
556Debug.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
557 if (ignoreCount < 0) {
558 throw new Error('Invalid argument');
559 }
560 var break_point = this.findBreakPoint(break_point_number, false);
561 break_point.setIgnoreCount(ignoreCount);
562};
563
564
565Debug.clearBreakPoint = function(break_point_number) {
566 var break_point = this.findBreakPoint(break_point_number, true);
567 if (break_point) {
568 return %ClearBreakPoint(break_point);
569 } else {
570 break_point = this.findScriptBreakPoint(break_point_number, true);
571 if (!break_point) {
572 throw new Error('Invalid breakpoint');
573 }
574 }
575};
576
577
578Debug.clearAllBreakPoints = function() {
579 for (var i = 0; i < break_points.length; i++) {
580 break_point = break_points[i];
581 %ClearBreakPoint(break_point);
582 }
583 break_points = [];
584};
585
586
587Debug.findScriptBreakPoint = function(break_point_number, remove) {
588 var script_break_point;
589 for (var i = 0; i < script_break_points.length; i++) {
590 if (script_break_points[i].number() == break_point_number) {
591 script_break_point = script_break_points[i];
592 // Remove the break point from the list if requested.
593 if (remove) {
594 script_break_point.clear();
595 script_break_points.splice(i,1);
596 }
597 break;
598 }
599 }
600 return script_break_point;
601}
602
603
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000604// Sets a breakpoint in a script identified through id or name at the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605// specified source line and column within that line.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000606Debug.setScriptBreakPoint = function(type, script_id_or_name,
607 opt_line, opt_column, opt_condition) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000608 // Create script break point object.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000609 var script_break_point =
610 new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611
612 // Assign number to the new script break point and add it.
613 script_break_point.number_ = next_break_point_number++;
614 script_break_point.setCondition(opt_condition);
615 script_break_points.push(script_break_point);
616
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000617 // Run through all scripts to see if this script break point matches any
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618 // loaded scripts.
619 var scripts = this.scripts();
620 for (var i = 0; i < scripts.length; i++) {
621 if (script_break_point.matchesScript(scripts[i])) {
622 script_break_point.set(scripts[i]);
623 }
624 }
625
626 return script_break_point.number();
627}
628
629
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000630Debug.setScriptBreakPointById = function(script_id,
631 opt_line, opt_column,
632 opt_condition) {
633 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
634 script_id, opt_line, opt_column,
635 opt_condition)
636}
637
638
639Debug.setScriptBreakPointByName = function(script_name,
640 opt_line, opt_column,
641 opt_condition) {
642 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
643 script_name, opt_line, opt_column,
644 opt_condition)
645}
646
647
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000648Debug.enableScriptBreakPoint = function(break_point_number) {
649 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
650 script_break_point.enable();
651};
652
653
654Debug.disableScriptBreakPoint = function(break_point_number) {
655 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
656 script_break_point.disable();
657};
658
659
660Debug.changeScriptBreakPointCondition = function(break_point_number, condition) {
661 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
662 script_break_point.setCondition(condition);
663};
664
665
666Debug.changeScriptBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
667 if (ignoreCount < 0) {
668 throw new Error('Invalid argument');
669 }
670 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
671 script_break_point.setIgnoreCount(ignoreCount);
672};
673
674
675Debug.scriptBreakPoints = function() {
676 return script_break_points;
677}
678
679
680Debug.clearStepping = function() {
mads.s.ager31e71382008-08-13 09:32:07 +0000681 %ClearStepping();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000682}
683
684Debug.setBreakOnException = function() {
685 return %ChangeBreakOnException(Debug.ExceptionBreak.All, true);
686};
687
688Debug.clearBreakOnException = function() {
689 return %ChangeBreakOnException(Debug.ExceptionBreak.All, false);
690};
691
692Debug.setBreakOnUncaughtException = function() {
693 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
694};
695
696Debug.clearBreakOnUncaughtException = function() {
697 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
698};
699
700Debug.showBreakPoints = function(f, full) {
701 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
702 var source = full ? this.scriptSource(f) : this.source(f);
703 var offset = full ? this.sourcePosition(f) : 0;
704 var locations = this.breakLocations(f);
705 if (!locations) return source;
706 locations.sort(function(x, y) { return x - y; });
707 var result = "";
708 var prev_pos = 0;
709 var pos;
710 for (var i = 0; i < locations.length; i++) {
711 pos = locations[i] - offset;
712 result += source.slice(prev_pos, pos);
713 result += "[B" + i + "]";
714 prev_pos = pos;
715 }
716 pos = source.length;
717 result += source.substring(prev_pos, pos);
718 return result;
719};
720
721
722// Get all the scripts currently loaded. Locating all the scripts is based on
723// scanning the heap.
724Debug.scripts = function() {
725 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +0000726 return %DebugGetLoadedScripts();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000727}
728
729function MakeExecutionState(break_id) {
730 return new ExecutionState(break_id);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000731}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000732
733function ExecutionState(break_id) {
734 this.break_id = break_id;
735 this.selected_frame = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000736}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737
738ExecutionState.prototype.prepareStep = function(opt_action, opt_count) {
739 var action = Debug.StepAction.StepIn;
740 if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
741 var count = opt_count ? %ToNumber(opt_count) : 1;
742
743 return %PrepareStep(this.break_id, action, count);
744}
745
kasper.lundbd3ec4e2008-07-09 11:06:54 +0000746ExecutionState.prototype.evaluateGlobal = function(source, disable_break) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000747 return MakeMirror(
748 %DebugEvaluateGlobal(this.break_id, source, Boolean(disable_break)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000749};
750
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000751ExecutionState.prototype.frameCount = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752 return %GetFrameCount(this.break_id);
753};
754
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000755ExecutionState.prototype.threadCount = function() {
756 return %GetThreadCount(this.break_id);
757};
758
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000759ExecutionState.prototype.frame = function(opt_index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760 // If no index supplied return the selected frame.
761 if (opt_index == null) opt_index = this.selected_frame;
762 return new FrameMirror(this.break_id, opt_index);
763};
764
765ExecutionState.prototype.cframesValue = function(opt_from_index, opt_to_index) {
766 return %GetCFrames(this.break_id);
767};
768
769ExecutionState.prototype.setSelectedFrame = function(index) {
770 var i = %ToNumber(index);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000771 if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772 this.selected_frame = i;
773};
774
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000775ExecutionState.prototype.selectedFrame = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000776 return this.selected_frame;
777};
778
779ExecutionState.prototype.debugCommandProcessor = function(protocol) {
780 return new DebugCommandProcessor(this, protocol);
781};
782
783
784function MakeBreakEvent(exec_state, break_points_hit) {
785 return new BreakEvent(exec_state, break_points_hit);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000786}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787
788
789function BreakEvent(exec_state, break_points_hit) {
790 this.exec_state_ = exec_state;
791 this.break_points_hit_ = break_points_hit;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000792}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793
794
ager@chromium.org8bb60582008-12-11 12:02:20 +0000795BreakEvent.prototype.executionState = function() {
796 return this.exec_state_;
797};
798
799
800BreakEvent.prototype.eventType = function() {
801 return Debug.DebugEvent.Break;
802};
803
804
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805BreakEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000806 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000807};
808
809
810BreakEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000811 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812};
813
814
815BreakEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000816 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000817};
818
819
820BreakEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000821 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000822};
823
824
825BreakEvent.prototype.breakPointsHit = function() {
826 return this.break_points_hit_;
827};
828
829
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000830BreakEvent.prototype.toJSONProtocol = function() {
831 var o = { seq: next_response_seq++,
832 type: "event",
833 event: "break",
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000834 body: { invocationText: this.exec_state_.frame(0).invocationText(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835 }
836 }
837
838 // Add script related information to the event if available.
839 var script = this.func().script();
840 if (script) {
841 o.body.sourceLine = this.sourceLine(),
842 o.body.sourceColumn = this.sourceColumn(),
843 o.body.sourceLineText = this.sourceLineText(),
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000844 o.body.script = MakeScriptObject_(script, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000845 }
846
847 // Add an Array of break points hit if any.
848 if (this.breakPointsHit()) {
849 o.body.breakpoints = [];
850 for (var i = 0; i < this.breakPointsHit().length; i++) {
851 // Find the break point number. For break points originating from a
852 // script break point supply the script break point number.
853 var breakpoint = this.breakPointsHit()[i];
854 var script_break_point = breakpoint.script_break_point();
855 var number;
856 if (script_break_point) {
857 number = script_break_point.number();
858 } else {
859 number = breakpoint.number();
860 }
861 o.body.breakpoints.push(number);
862 }
863 }
864
865 return SimpleObjectToJSON_(o);
866};
867
868
869function MakeExceptionEvent(exec_state, exception, uncaught) {
870 return new ExceptionEvent(exec_state, exception, uncaught);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000871}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000872
ager@chromium.org8bb60582008-12-11 12:02:20 +0000873
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874function ExceptionEvent(exec_state, exception, uncaught) {
875 this.exec_state_ = exec_state;
876 this.exception_ = exception;
877 this.uncaught_ = uncaught;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000878}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879
ager@chromium.org8bb60582008-12-11 12:02:20 +0000880
881ExceptionEvent.prototype.executionState = function() {
882 return this.exec_state_;
883};
884
885
886ExceptionEvent.prototype.eventType = function() {
887 return Debug.DebugEvent.Exception;
888};
889
890
891ExceptionEvent.prototype.exception = function() {
892 return this.exception_;
893}
894
895
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896ExceptionEvent.prototype.uncaught = function() {
897 return this.uncaught_;
898}
899
ager@chromium.org8bb60582008-12-11 12:02:20 +0000900
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000901ExceptionEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000902 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000903};
904
905
906ExceptionEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000907 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000908};
909
910
911ExceptionEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000912 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000913};
914
915
916ExceptionEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000917 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918};
919
920
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921ExceptionEvent.prototype.toJSONProtocol = function() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000922 var o = new ProtocolMessage();
923 o.event = "exception";
924 o.body = { uncaught: this.uncaught_,
925 exception: MakeMirror(this.exception_)
926 }
927
928 // Exceptions might happen whithout any JavaScript frames.
929 if (this.exec_state_.frameCount() > 0) {
930 o.body.sourceLine = this.sourceLine();
931 o.body.sourceColumn = this.sourceColumn();
932 o.body.sourceLineText = this.sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000933
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000934 // Add script information to the event if available.
935 var script = this.func().script();
936 if (script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000937 o.body.script = MakeScriptObject_(script, false);
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000938 }
939 } else {
940 o.body.sourceLine = -1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000941 }
942
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000943 return o.toJSONProtocol();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000944};
945
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000946
iposva@chromium.org245aa852009-02-10 00:49:54 +0000947function MakeCompileEvent(exec_state, script, before) {
948 return new CompileEvent(exec_state, script, before);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000949}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000950
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000951
iposva@chromium.org245aa852009-02-10 00:49:54 +0000952function CompileEvent(exec_state, script, before) {
953 this.exec_state_ = exec_state;
954 this.script_ = MakeMirror(script);
955 this.before_ = before;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000956}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000957
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000958
iposva@chromium.org245aa852009-02-10 00:49:54 +0000959CompileEvent.prototype.executionState = function() {
960 return this.exec_state_;
961};
962
963
ager@chromium.org8bb60582008-12-11 12:02:20 +0000964CompileEvent.prototype.eventType = function() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000965 if (this.before_) {
966 return Debug.DebugEvent.BeforeCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +0000967 } else {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000968 return Debug.DebugEvent.AfterCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +0000969 }
970};
971
972
iposva@chromium.org245aa852009-02-10 00:49:54 +0000973CompileEvent.prototype.script = function() {
974 return this.script_;
975};
976
977
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000978CompileEvent.prototype.toJSONProtocol = function() {
979 var o = new ProtocolMessage();
980 if (this.before_) {
981 o.event = "beforeCompile";
982 } else {
983 o.event = "afterCompile";
984 }
985 o.body = {};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000986 o.body.script = MakeScriptObject_(this.script_, true);
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000987
988 return o.toJSONProtocol();
989}
990
991
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000992function MakeNewFunctionEvent(func) {
993 return new NewFunctionEvent(func);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000994}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000996
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000997function NewFunctionEvent(func) {
998 this.func = func;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000999}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001000
ager@chromium.org8bb60582008-12-11 12:02:20 +00001001
1002NewFunctionEvent.prototype.eventType = function() {
1003 return Debug.DebugEvent.NewFunction;
1004};
1005
1006
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001007NewFunctionEvent.prototype.name = function() {
1008 return this.func.name;
1009};
1010
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001011
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001012NewFunctionEvent.prototype.setBreakPoint = function(p) {
1013 Debug.setBreakPoint(this.func, p || 0);
1014};
1015
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001016
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001017function MakeScriptObject_(script, include_source) {
1018 var o = { id: script.id(),
1019 name: script.name(),
1020 lineOffset: script.lineOffset(),
1021 columnOffset: script.columnOffset(),
1022 lineCount: script.lineCount(),
1023 };
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001024 if (!IS_UNDEFINED(script.data())) {
1025 o.data = script.data();
1026 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001027 if (include_source) {
1028 o.source = script.source();
1029 }
1030 return o;
1031};
1032
1033
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034function DebugCommandProcessor(exec_state) {
1035 this.exec_state_ = exec_state;
iposva@chromium.org245aa852009-02-10 00:49:54 +00001036 this.running_ = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001037};
1038
1039
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001040DebugCommandProcessor.prototype.processDebugRequest = function (request) {
1041 return this.processDebugJSONRequest(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001042}
1043
1044
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001045function ProtocolMessage(request) {
1046 // Update sequence number.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001047 this.seq = next_response_seq++;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001048
1049 if (request) {
1050 // If message is based on a request this is a response. Fill the initial
1051 // response from the request.
1052 this.type = 'response';
1053 this.request_seq = request.seq;
1054 this.command = request.command;
1055 } else {
1056 // If message is not based on a request it is a dabugger generated event.
1057 this.type = 'event';
1058 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059 this.success = true;
1060 this.running = false;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001061}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001062
1063
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001064ProtocolMessage.prototype.failed = function(message) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001065 this.success = false;
1066 this.message = message;
1067}
1068
1069
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001070ProtocolMessage.prototype.toJSONProtocol = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071 // Encode the protocol header.
1072 var json = '{';
1073 json += '"seq":' + this.seq;
1074 if (this.request_seq) {
1075 json += ',"request_seq":' + this.request_seq;
1076 }
1077 json += ',"type":"' + this.type + '"';
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001078 if (this.event) {
1079 json += ',"event":' + StringToJSON_(this.event);
1080 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001081 if (this.command) {
1082 json += ',"command":' + StringToJSON_(this.command);
1083 }
1084 if (this.success) {
1085 json += ',"success":' + this.success;
1086 } else {
1087 json += ',"success":false';
1088 }
1089 if (this.body) {
1090 json += ',"body":';
1091 // Encode the body part.
ager@chromium.org32912102009-01-16 10:38:43 +00001092 var serializer = MakeMirrorSerializer(true);
1093 if (this.body instanceof Mirror) {
1094 json += serializer.serializeValue(this.body);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001095 } else if (this.body instanceof Array) {
1096 json += '[';
1097 for (var i = 0; i < this.body.length; i++) {
1098 if (i != 0) json += ',';
ager@chromium.org32912102009-01-16 10:38:43 +00001099 if (this.body[i] instanceof Mirror) {
1100 json += serializer.serializeValue(this.body[i]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101 } else {
ager@chromium.org32912102009-01-16 10:38:43 +00001102 json += SimpleObjectToJSON_(this.body[i], serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001103 }
1104 }
1105 json += ']';
1106 } else {
ager@chromium.org32912102009-01-16 10:38:43 +00001107 json += SimpleObjectToJSON_(this.body, serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001108 }
ager@chromium.org32912102009-01-16 10:38:43 +00001109 json += ',"refs":';
1110 json += serializer.serializeReferencedObjects();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001111 }
1112 if (this.message) {
1113 json += ',"message":' + StringToJSON_(this.message) ;
1114 }
1115 if (this.running) {
1116 json += ',"running":true';
1117 } else {
1118 json += ',"running":false';
1119 }
1120 json += '}';
1121 return json;
1122}
1123
1124
1125DebugCommandProcessor.prototype.createResponse = function(request) {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001126 return new ProtocolMessage(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001127};
1128
1129
iposva@chromium.org245aa852009-02-10 00:49:54 +00001130DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001131 var request; // Current request.
1132 var response; // Generated response.
1133 try {
1134 try {
1135 // Convert the JSON string to an object.
ager@chromium.org3a37e9b2009-04-27 09:26:21 +00001136 request = %CompileString('(' + json_request + ')', 0, false)();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001137
1138 // Create an initial response.
1139 response = this.createResponse(request);
1140
1141 if (!request.type) {
1142 throw new Error('Type not specified');
1143 }
1144
1145 if (request.type != 'request') {
1146 throw new Error("Illegal type '" + request.type + "' in request");
1147 }
1148
1149 if (!request.command) {
1150 throw new Error('Command not specified');
1151 }
1152
1153 if (request.command == 'continue') {
1154 this.continueRequest_(request, response);
1155 } else if (request.command == 'break') {
1156 this.breakRequest_(request, response);
1157 } else if (request.command == 'setbreakpoint') {
1158 this.setBreakPointRequest_(request, response);
1159 } else if (request.command == 'changebreakpoint') {
1160 this.changeBreakPointRequest_(request, response);
1161 } else if (request.command == 'clearbreakpoint') {
1162 this.clearBreakPointRequest_(request, response);
1163 } else if (request.command == 'backtrace') {
1164 this.backtraceRequest_(request, response);
1165 } else if (request.command == 'frame') {
1166 this.frameRequest_(request, response);
1167 } else if (request.command == 'evaluate') {
1168 this.evaluateRequest_(request, response);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001169 } else if (request.command == 'lookup') {
1170 this.lookupRequest_(request, response);
iposva@chromium.org245aa852009-02-10 00:49:54 +00001171 } else if (request.command == 'references') {
1172 this.referencesRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001173 } else if (request.command == 'source') {
1174 this.sourceRequest_(request, response);
1175 } else if (request.command == 'scripts') {
1176 this.scriptsRequest_(request, response);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001177 } else if (request.command == 'threads') {
1178 this.threadsRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001179 } else {
1180 throw new Error('Unknown command "' + request.command + '" in request');
1181 }
1182 } catch (e) {
1183 // If there is no response object created one (without command).
1184 if (!response) {
1185 response = this.createResponse();
1186 }
1187 response.success = false;
1188 response.message = %ToString(e);
1189 }
1190
1191 // Return the response as a JSON encoded string.
1192 try {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001193 this.running_ = response.running; // Store the running state.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001194 return response.toJSONProtocol();
1195 } catch (e) {
1196 // Failed to generate response - return generic error.
1197 return '{"seq":' + response.seq + ',' +
1198 '"request_seq":' + request.seq + ',' +
1199 '"type":"response",' +
1200 '"success":false,' +
1201 '"message":"Internal error: ' + %ToString(e) + '"}';
1202 }
1203 } catch (e) {
1204 // Failed in one of the catch blocks above - most generic error.
1205 return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
1206 }
1207};
1208
1209
1210DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
1211 // Check for arguments for continue.
1212 if (request.arguments) {
1213 var count = 1;
1214 var action = Debug.StepAction.StepIn;
1215
1216 // Pull out arguments.
1217 var stepaction = request.arguments.stepaction;
1218 var stepcount = request.arguments.stepcount;
1219
1220 // Get the stepcount argument if any.
1221 if (stepcount) {
1222 count = %ToNumber(stepcount);
1223 if (count < 0) {
1224 throw new Error('Invalid stepcount argument "' + stepcount + '".');
1225 }
1226 }
1227
1228 // Get the stepaction argument.
1229 if (stepaction) {
1230 if (stepaction == 'in') {
1231 action = Debug.StepAction.StepIn;
1232 } else if (stepaction == 'min') {
1233 action = Debug.StepAction.StepMin;
1234 } else if (stepaction == 'next') {
1235 action = Debug.StepAction.StepNext;
1236 } else if (stepaction == 'out') {
1237 action = Debug.StepAction.StepOut;
1238 } else {
1239 throw new Error('Invalid stepaction argument "' + stepaction + '".');
1240 }
1241 }
1242
1243 // Setup the VM for stepping.
1244 this.exec_state_.prepareStep(action, count);
1245 }
1246
1247 // VM should be running after executing this request.
1248 response.running = true;
1249};
1250
1251
1252DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
1253 // Ignore as break command does not do anything when broken.
1254};
1255
1256
1257DebugCommandProcessor.prototype.setBreakPointRequest_ =
1258 function(request, response) {
1259 // Check for legal request.
1260 if (!request.arguments) {
1261 response.failed('Missing arguments');
1262 return;
1263 }
1264
1265 // Pull out arguments.
1266 var type = request.arguments.type;
1267 var target = request.arguments.target;
1268 var line = request.arguments.line;
1269 var column = request.arguments.column;
1270 var enabled = IS_UNDEFINED(request.arguments.enabled) ?
1271 true : request.arguments.enabled;
1272 var condition = request.arguments.condition;
1273 var ignoreCount = request.arguments.ignoreCount;
1274
1275 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001276 if (!type || IS_UNDEFINED(target)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277 response.failed('Missing argument "type" or "target"');
1278 return;
1279 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001280 if (type != 'function' && type != 'handle' &&
1281 type != 'script' && type != 'scriptId') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282 response.failed('Illegal type "' + type + '"');
1283 return;
1284 }
1285
1286 // Either function or script break point.
1287 var break_point_number;
1288 if (type == 'function') {
1289 // Handle function break point.
1290 if (!IS_STRING(target)) {
1291 response.failed('Argument "target" is not a string value');
1292 return;
1293 }
1294 var f;
1295 try {
1296 // Find the function through a global evaluate.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001297 f = this.exec_state_.evaluateGlobal(target).value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001298 } catch (e) {
1299 response.failed('Error: "' + %ToString(e) +
1300 '" evaluating "' + target + '"');
1301 return;
1302 }
1303 if (!IS_FUNCTION(f)) {
1304 response.failed('"' + target + '" does not evaluate to a function');
1305 return;
1306 }
1307
1308 // Set function break point.
1309 break_point_number = Debug.setBreakPoint(f, line, column, condition);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001310 } else if (type == 'handle') {
1311 // Find the object pointed by the specified handle.
1312 var handle = parseInt(target, 10);
1313 var mirror = LookupMirror(handle);
1314 if (!mirror) {
1315 return response.failed('Object #' + handle + '# not found');
1316 }
1317 if (!mirror.isFunction()) {
1318 return response.failed('Object #' + handle + '# is not a function');
1319 }
1320
1321 // Set function break point.
1322 break_point_number = Debug.setBreakPoint(mirror.value(),
1323 line, column, condition);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001324 } else if (type == 'script') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001325 // set script break point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001326 break_point_number =
1327 Debug.setScriptBreakPointByName(target, line, column, condition);
1328 } else { // type == 'scriptId.
1329 break_point_number =
1330 Debug.setScriptBreakPointById(target, line, column, condition);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001331 }
1332
1333 // Set additional break point properties.
1334 var break_point = Debug.findBreakPoint(break_point_number);
1335 if (ignoreCount) {
1336 Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
1337 }
1338 if (!enabled) {
1339 Debug.disableBreakPoint(break_point_number);
1340 }
1341
1342 // Add the break point number to the response.
1343 response.body = { type: type,
1344 breakpoint: break_point_number }
1345
1346 // Add break point information to the response.
1347 if (break_point instanceof ScriptBreakPoint) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001348 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1349 response.body.type = 'scriptId';
1350 response.body.script_id = break_point.script_id();
1351 } else {
1352 response.body.type = 'scriptName';
1353 response.body.script_name = break_point.script_name();
1354 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001355 response.body.line = break_point.line();
1356 response.body.column = break_point.column();
1357 } else {
1358 response.body.type = 'function';
1359 }
1360};
1361
1362
1363DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(request, response) {
1364 // Check for legal request.
1365 if (!request.arguments) {
1366 response.failed('Missing arguments');
1367 return;
1368 }
1369
1370 // Pull out arguments.
1371 var break_point = %ToNumber(request.arguments.breakpoint);
1372 var enabled = request.arguments.enabled;
1373 var condition = request.arguments.condition;
1374 var ignoreCount = request.arguments.ignoreCount;
1375
1376 // Check for legal arguments.
1377 if (!break_point) {
1378 response.failed('Missing argument "breakpoint"');
1379 return;
1380 }
1381
1382 // Change enabled state if supplied.
1383 if (!IS_UNDEFINED(enabled)) {
1384 if (enabled) {
1385 Debug.enableBreakPoint(break_point);
1386 } else {
1387 Debug.disableBreakPoint(break_point);
1388 }
1389 }
1390
1391 // Change condition if supplied
1392 if (!IS_UNDEFINED(condition)) {
1393 Debug.changeBreakPointCondition(break_point, condition);
1394 }
1395
1396 // Change ignore count if supplied
1397 if (!IS_UNDEFINED(ignoreCount)) {
1398 Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
1399 }
1400}
1401
1402
1403DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(request, response) {
1404 // Check for legal request.
1405 if (!request.arguments) {
1406 response.failed('Missing arguments');
1407 return;
1408 }
1409
1410 // Pull out arguments.
1411 var break_point = %ToNumber(request.arguments.breakpoint);
1412
1413 // Check for legal arguments.
1414 if (!break_point) {
1415 response.failed('Missing argument "breakpoint"');
1416 return;
1417 }
1418
1419 // Clear break point.
1420 Debug.clearBreakPoint(break_point);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001421
1422 // Add the cleared break point number to the response.
1423 response.body = { breakpoint: break_point }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001424}
1425
1426
1427DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) {
1428 // Get the number of frames.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001429 var total_frames = this.exec_state_.frameCount();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001430
ager@chromium.org8bb60582008-12-11 12:02:20 +00001431 // Create simple response if there are no frames.
1432 if (total_frames == 0) {
1433 response.body = {
1434 totalFrames: total_frames
1435 }
1436 return;
1437 }
1438
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001439 // Default frame range to include in backtrace.
1440 var from_index = 0
1441 var to_index = kDefaultBacktraceLength;
1442
1443 // Get the range from the arguments.
1444 if (request.arguments) {
1445 from_index = request.arguments.fromFrame;
1446 if (from_index < 0) {
1447 return response.failed('Invalid frame number');
1448 }
1449 to_index = request.arguments.toFrame;
1450 if (to_index < 0) {
1451 return response.failed('Invalid frame number');
1452 }
1453 }
1454
1455 // Adjust the index.
1456 to_index = Math.min(total_frames, to_index);
1457
1458 if (to_index <= from_index) {
1459 var error = 'Invalid frame range';
1460 return response.failed(error);
1461 }
1462
1463 // Create the response body.
1464 var frames = [];
1465 for (var i = from_index; i < to_index; i++) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001466 frames.push(this.exec_state_.frame(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001467 }
1468 response.body = {
1469 fromFrame: from_index,
1470 toFrame: to_index,
1471 totalFrames: total_frames,
1472 frames: frames
1473 }
1474};
1475
1476
1477DebugCommandProcessor.prototype.backtracec = function(cmd, args) {
1478 return this.exec_state_.cframesValue();
1479};
1480
1481
1482DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001483 // No frames no source.
1484 if (this.exec_state_.frameCount() == 0) {
1485 return response.failed('No frames');
1486 }
1487
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001488 // With no arguments just keep the selected frame.
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001489 if (request.arguments) {
1490 index = request.arguments.number;
1491 if (index < 0 || this.exec_state_.frameCount() <= index) {
1492 return response.failed('Invalid frame number');
1493 }
1494
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001495 this.exec_state_.setSelectedFrame(request.arguments.number);
1496 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001497 response.body = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001498};
1499
1500
1501DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
1502 if (!request.arguments) {
1503 return response.failed('Missing arguments');
1504 }
1505
1506 // Pull out arguments.
1507 var expression = request.arguments.expression;
1508 var frame = request.arguments.frame;
1509 var global = request.arguments.global;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00001510 var disable_break = request.arguments.disable_break;
1511
1512 // The expression argument could be an integer so we convert it to a
1513 // string.
1514 try {
1515 expression = String(expression);
1516 } catch(e) {
1517 return response.failed('Failed to convert expression argument to string');
1518 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001519
1520 // Check for legal arguments.
1521 if (!IS_UNDEFINED(frame) && global) {
1522 return response.failed('Arguments "frame" and "global" are exclusive');
1523 }
1524
1525 // Global evaluate.
1526 if (global) {
1527 // Evaluate in the global context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001528 response.body =
1529 this.exec_state_.evaluateGlobal(expression), Boolean(disable_break);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001530 return;
1531 }
1532
kasper.lundbd3ec4e2008-07-09 11:06:54 +00001533 // Default value for disable_break is true.
1534 if (IS_UNDEFINED(disable_break)) {
1535 disable_break = true;
1536 }
1537
ager@chromium.org381abbb2009-02-25 13:23:22 +00001538 // No frames no evaluate in frame.
1539 if (this.exec_state_.frameCount() == 0) {
1540 return response.failed('No frames');
1541 }
1542
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543 // Check whether a frame was specified.
1544 if (!IS_UNDEFINED(frame)) {
1545 var frame_number = %ToNumber(frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001546 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001547 return response.failed('Invalid frame "' + frame + '"');
1548 }
1549 // Evaluate in the specified frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001550 response.body = this.exec_state_.frame(frame_number).evaluate(
kasper.lundbd3ec4e2008-07-09 11:06:54 +00001551 expression, Boolean(disable_break));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552 return;
1553 } else {
1554 // Evaluate in the selected frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001555 response.body = this.exec_state_.frame().evaluate(
kasper.lundbd3ec4e2008-07-09 11:06:54 +00001556 expression, Boolean(disable_break));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001557 return;
1558 }
1559};
1560
1561
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001562DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
1563 if (!request.arguments) {
1564 return response.failed('Missing arguments');
1565 }
1566
1567 // Pull out arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001568 var handles = request.arguments.handles;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001569
1570 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001571 if (IS_UNDEFINED(handles)) {
1572 return response.failed('Argument "handles" missing');
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001573 }
1574
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001575 // Lookup handles.
1576 var mirrors = {};
1577 for (var i = 0; i < handles.length; i++) {
1578 var handle = handles[i];
1579 var mirror = LookupMirror(handle);
1580 if (!mirror) {
1581 return response.failed('Object #' + handle + '# not found');
1582 }
1583 mirrors[handle] = mirror;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001584 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001585 response.body = mirrors;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001586};
1587
1588
iposva@chromium.org245aa852009-02-10 00:49:54 +00001589DebugCommandProcessor.prototype.referencesRequest_ =
1590 function(request, response) {
1591 if (!request.arguments) {
1592 return response.failed('Missing arguments');
1593 }
1594
1595 // Pull out arguments.
1596 var type = request.arguments.type;
1597 var handle = request.arguments.handle;
1598
1599 // Check for legal arguments.
1600 if (IS_UNDEFINED(type)) {
1601 return response.failed('Argument "type" missing');
1602 }
1603 if (IS_UNDEFINED(handle)) {
1604 return response.failed('Argument "handle" missing');
1605 }
1606 if (type != 'referencedBy' && type != 'constructedBy') {
1607 return response.failed('Invalid type "' + type + '"');
1608 }
1609
1610 // Lookup handle and return objects with references the object.
1611 var mirror = LookupMirror(handle);
1612 if (mirror) {
1613 if (type == 'referencedBy') {
1614 response.body = mirror.referencedBy();
1615 } else {
1616 response.body = mirror.constructedBy();
1617 }
1618 } else {
1619 return response.failed('Object #' + handle + '# not found');
1620 }
1621};
1622
1623
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001624DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001625 // No frames no source.
1626 if (this.exec_state_.frameCount() == 0) {
1627 return response.failed('No source');
1628 }
1629
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001630 var from_line;
1631 var to_line;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001632 var frame = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633 if (request.arguments) {
1634 // Pull out arguments.
1635 from_line = request.arguments.fromLine;
1636 to_line = request.arguments.toLine;
1637
1638 if (!IS_UNDEFINED(request.arguments.frame)) {
1639 var frame_number = %ToNumber(request.arguments.frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001640 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001641 return response.failed('Invalid frame "' + frame + '"');
1642 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001643 frame = this.exec_state_.frame(frame_number);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001644 }
1645 }
1646
1647 // Get the script selected.
1648 var script = frame.func().script();
1649 if (!script) {
1650 return response.failed('No source');
1651 }
1652
1653 // Get the source slice and fill it into the response.
1654 var slice = script.sourceSlice(from_line, to_line);
1655 if (!slice) {
1656 return response.failed('Invalid line interval');
1657 }
1658 response.body = {};
1659 response.body.source = slice.sourceText();
1660 response.body.fromLine = slice.from_line;
1661 response.body.toLine = slice.to_line;
1662 response.body.fromPosition = slice.from_position;
1663 response.body.toPosition = slice.to_position;
1664 response.body.totalLines = script.lineCount();
1665};
1666
1667
1668DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
1669 var types = ScriptTypeFlag(Debug.ScriptType.Normal);
ager@chromium.org41826e72009-03-30 13:30:57 +00001670 var includeSource = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001671 if (request.arguments) {
1672 // Pull out arguments.
1673 if (!IS_UNDEFINED(request.arguments.types)) {
1674 types = %ToNumber(request.arguments.types);
1675 if (isNaN(types) || types < 0) {
1676 return response.failed('Invalid types "' + request.arguments.types + '"');
1677 }
1678 }
ager@chromium.org41826e72009-03-30 13:30:57 +00001679
1680 if (!IS_UNDEFINED(request.arguments.includeSource)) {
1681 includeSource = %ToBoolean(request.arguments.includeSource);
1682 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001683 }
1684
1685 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +00001686 var scripts = %DebugGetLoadedScripts();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001687
1688 response.body = [];
1689
1690 for (var i = 0; i < scripts.length; i++) {
1691 if (types & ScriptTypeFlag(scripts[i].type)) {
1692 var script = {};
1693 if (scripts[i].name) {
1694 script.name = scripts[i].name;
1695 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001696 script.id = scripts[i].id;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001697 script.lineOffset = scripts[i].line_offset;
1698 script.columnOffset = scripts[i].column_offset;
1699 script.lineCount = scripts[i].lineCount();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001700 if (scripts[i].data) {
1701 script.data = scripts[i].data;
1702 }
ager@chromium.org41826e72009-03-30 13:30:57 +00001703 if (includeSource) {
1704 script.source = scripts[i].source;
1705 } else {
1706 script.sourceStart = scripts[i].source.substring(0, 80);
1707 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001708 script.sourceLength = scripts[i].source.length;
1709 script.type = scripts[i].type;
1710 response.body.push(script);
1711 }
1712 }
1713};
1714
1715
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001716DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
1717 // Get the number of threads.
1718 var total_threads = this.exec_state_.threadCount();
1719
1720 // Get information for all threads.
1721 var threads = [];
1722 for (var i = 0; i < total_threads; i++) {
1723 var details = %GetThreadDetails(this.exec_state_.break_id, i);
1724 var thread_info = { current: details[0],
1725 id: details[1]
1726 }
1727 threads.push(thread_info);
1728 }
1729
1730 // Create the response body.
1731 response.body = {
1732 totalThreads: total_threads,
1733 threads: threads
1734 }
1735};
1736
1737
iposva@chromium.org245aa852009-02-10 00:49:54 +00001738// Check whether the previously processed command caused the VM to become
1739// running.
1740DebugCommandProcessor.prototype.isRunning = function() {
1741 return this.running_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001742}
1743
1744
1745DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
mads.s.ager31e71382008-08-13 09:32:07 +00001746 return %SystemBreak();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001747};
1748
1749
1750function NumberToHex8Str(n) {
1751 var r = "";
1752 for (var i = 0; i < 8; ++i) {
1753 var c = hexCharArray[n & 0x0F]; // hexCharArray is defined in uri.js
1754 r = c + r;
1755 n = n >>> 4;
1756 }
1757 return r;
1758};
1759
1760DebugCommandProcessor.prototype.formatCFrames = function(cframes_value) {
1761 var result = "";
1762 if (cframes_value == null || cframes_value.length == 0) {
1763 result += "(stack empty)";
1764 } else {
1765 for (var i = 0; i < cframes_value.length; ++i) {
1766 if (i != 0) result += "\n";
1767 result += this.formatCFrame(cframes_value[i]);
1768 }
1769 }
1770 return result;
1771};
1772
1773
1774DebugCommandProcessor.prototype.formatCFrame = function(cframe_value) {
1775 var result = "";
1776 result += "0x" + NumberToHex8Str(cframe_value.address);
1777 if (!IS_UNDEFINED(cframe_value.text)) {
1778 result += " " + cframe_value.text;
1779 }
1780 return result;
1781}
1782
1783
1784/**
1785 * Convert an Object to its JSON representation (see http://www.json.org/).
1786 * This implementation simply runs through all string property names and adds
1787 * each property to the JSON representation for some predefined types. For type
1788 * "object" the function calls itself recursively unless the object has the
1789 * function property "toJSONProtocol" in which case that is used. This is not
1790 * a general implementation but sufficient for the debugger. Note that circular
1791 * structures will cause infinite recursion.
1792 * @param {Object} object The object to format as JSON
ager@chromium.org32912102009-01-16 10:38:43 +00001793 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
1794 * mirror objects are encountered.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001795 * @return {string} JSON formatted object value
1796 */
ager@chromium.org32912102009-01-16 10:38:43 +00001797function SimpleObjectToJSON_(object, mirror_serializer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001798 var content = [];
1799 for (var key in object) {
1800 // Only consider string keys.
1801 if (typeof key == 'string') {
1802 var property_value = object[key];
1803
1804 // Format the value based on its type.
1805 var property_value_json;
1806 switch (typeof property_value) {
1807 case 'object':
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001808 if (property_value instanceof Mirror) {
1809 property_value_json = mirror_serializer.serializeValue(property_value);
1810 } else if (typeof property_value.toJSONProtocol == 'function') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001811 property_value_json = property_value.toJSONProtocol(true)
1812 } else if (IS_ARRAY(property_value)){
ager@chromium.org32912102009-01-16 10:38:43 +00001813 property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001814 } else {
ager@chromium.org32912102009-01-16 10:38:43 +00001815 property_value_json = SimpleObjectToJSON_(property_value, mirror_serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001816 }
1817 break;
1818
1819 case 'boolean':
1820 property_value_json = BooleanToJSON_(property_value);
1821 break;
1822
1823 case 'number':
1824 property_value_json = NumberToJSON_(property_value);
1825 break;
1826
1827 case 'string':
1828 property_value_json = StringToJSON_(property_value);
1829 break;
1830
1831 default:
1832 property_value_json = null;
1833 }
1834
1835 // Add the property if relevant.
1836 if (property_value_json) {
1837 content.push(StringToJSON_(key) + ':' + property_value_json);
1838 }
1839 }
1840 }
1841
1842 // Make JSON object representation.
1843 return '{' + content.join(',') + '}';
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001844}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001845
1846/**
1847 * Convert an array to its JSON representation. This is a VERY simple
1848 * implementation just to support what is needed for the debugger.
ager@chromium.org32912102009-01-16 10:38:43 +00001849 * @param {Array} array The array to format as JSON
1850 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
1851 * mirror objects are encountered.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001852 * @return {string} JSON formatted array value
1853 */
ager@chromium.org32912102009-01-16 10:38:43 +00001854function SimpleArrayToJSON_(array, mirror_serializer) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001855 // Make JSON array representation.
1856 var json = '[';
1857 for (var i = 0; i < array.length; i++) {
1858 if (i != 0) {
1859 json += ',';
1860 }
1861 var elem = array[i];
ager@chromium.org32912102009-01-16 10:38:43 +00001862 if (elem instanceof Mirror) {
1863 json += mirror_serializer.serializeValue(elem);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001864 } else if (IS_OBJECT(elem)) {
1865 json += SimpleObjectToJSON_(elem);
1866 } else if (IS_BOOLEAN(elem)) {
1867 json += BooleanToJSON_(elem);
1868 } else if (IS_NUMBER(elem)) {
1869 json += NumberToJSON_(elem);
1870 } else if (IS_STRING(elem)) {
1871 json += StringToJSON_(elem);
1872 } else {
1873 json += elem;
1874 }
1875 }
1876 json += ']';
1877 return json;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001878}