blob: 7787312ddc68ead51e24738a512d6affda2f4501 [file] [log] [blame]
ulan@chromium.org967e2702012-02-28 09:49:15 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Default number of frames to include in the response to backtrace request.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000029var kDefaultBacktraceLength = 10;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000031var Debug = {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032
33// Regular expression to skip "crud" at the beginning of a source line which is
34// not really code. Currently the regular expression matches whitespace and
35// comments.
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000036var sourceLineBeginningSkip = /^(?:\s*(?:\/\*.*?\*\/)*)*/;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38// Debug events which can occour in the V8 JavaScript engine. These originate
39// from the API include file debug.h.
40Debug.DebugEvent = { Break: 1,
41 Exception: 2,
42 NewFunction: 3,
43 BeforeCompile: 4,
kasperl@chromium.org71affb52009-05-26 05:44:31 +000044 AfterCompile: 5,
45 ScriptCollected: 6 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
47// Types of exceptions that can be broken upon.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000048Debug.ExceptionBreak = { Caught : 0,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049 Uncaught: 1 };
50
51// The different types of steps.
52Debug.StepAction = { StepOut: 0,
53 StepNext: 1,
54 StepIn: 2,
55 StepMin: 3,
56 StepInMin: 4 };
57
58// The different types of scripts matching enum ScriptType in objects.h.
59Debug.ScriptType = { Native: 0,
60 Extension: 1,
61 Normal: 2 };
62
ager@chromium.orge2902be2009-06-08 12:21:35 +000063// The different types of script compilations matching enum
64// Script::CompilationType in objects.h.
65Debug.ScriptCompilationType = { Host: 0,
66 Eval: 1,
67 JSON: 2 };
68
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000069// The different script break point types.
70Debug.ScriptBreakPointType = { ScriptId: 0,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +000071 ScriptName: 1,
72 ScriptRegExp: 2 };
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000073
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};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000113
114
115// Create a new break point object and add it to the list of break points.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000116function MakeBreakPoint(source_position, opt_script_break_point) {
117 var break_point = new BreakPoint(source_position, opt_script_break_point);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118 break_points.push(break_point);
119 return break_point;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000120}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000121
122
123// Object representing a break point.
124// NOTE: This object does not have a reference to the function having break
125// point as this would cause function not to be garbage collected when it is
126// not used any more. We do not want break points to keep functions alive.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000127function BreakPoint(source_position, opt_script_break_point) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 this.source_position_ = source_position;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129 if (opt_script_break_point) {
130 this.script_break_point_ = opt_script_break_point;
131 } else {
132 this.number_ = next_break_point_number++;
133 }
134 this.hit_count_ = 0;
135 this.active_ = true;
136 this.condition_ = null;
137 this.ignoreCount_ = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000138}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000139
140
141BreakPoint.prototype.number = function() {
142 return this.number_;
143};
144
145
146BreakPoint.prototype.func = function() {
147 return this.func_;
148};
149
150
151BreakPoint.prototype.source_position = function() {
152 return this.source_position_;
153};
154
155
156BreakPoint.prototype.hit_count = function() {
157 return this.hit_count_;
158};
159
160
161BreakPoint.prototype.active = function() {
162 if (this.script_break_point()) {
163 return this.script_break_point().active();
164 }
165 return this.active_;
166};
167
168
169BreakPoint.prototype.condition = function() {
170 if (this.script_break_point() && this.script_break_point().condition()) {
171 return this.script_break_point().condition();
172 }
173 return this.condition_;
174};
175
176
177BreakPoint.prototype.ignoreCount = function() {
178 return this.ignoreCount_;
179};
180
181
182BreakPoint.prototype.script_break_point = function() {
183 return this.script_break_point_;
184};
185
186
187BreakPoint.prototype.enable = function() {
188 this.active_ = true;
189};
190
191
192BreakPoint.prototype.disable = function() {
193 this.active_ = false;
194};
195
196
197BreakPoint.prototype.setCondition = function(condition) {
198 this.condition_ = condition;
199};
200
201
202BreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
203 this.ignoreCount_ = ignoreCount;
204};
205
206
207BreakPoint.prototype.isTriggered = function(exec_state) {
208 // Break point not active - not triggered.
209 if (!this.active()) return false;
210
211 // Check for conditional break point.
212 if (this.condition()) {
213 // If break point has condition try to evaluate it in the top frame.
214 try {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000215 var mirror = exec_state.frame(0).evaluate(this.condition());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 // If no sensible mirror or non true value break point not triggered.
217 if (!(mirror instanceof ValueMirror) || !%ToBoolean(mirror.value_)) {
218 return false;
219 }
220 } catch (e) {
221 // Exception evaluating condition counts as not triggered.
222 return false;
223 }
224 }
225
226 // Update the hit count.
227 this.hit_count_++;
228 if (this.script_break_point_) {
229 this.script_break_point_.hit_count_++;
230 }
231
232 // If the break point has an ignore count it is not triggered.
233 if (this.ignoreCount_ > 0) {
234 this.ignoreCount_--;
235 return false;
236 }
237
238 // Break point triggered.
239 return true;
240};
241
242
243// Function called from the runtime when a break point is hit. Returns true if
244// the break point is triggered and supposed to break execution.
245function IsBreakPointTriggered(break_id, break_point) {
246 return break_point.isTriggered(MakeExecutionState(break_id));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000247}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000248
249
250// Object representing a script break point. The script is referenced by its
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000251// script name or script id and the break point is represented as line and
252// column.
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000253function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
254 opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000255 this.type_ = type;
256 if (type == Debug.ScriptBreakPointType.ScriptId) {
257 this.script_id_ = script_id_or_name;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000258 } else if (type == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000259 this.script_name_ = script_id_or_name;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000260 } else if (type == Debug.ScriptBreakPointType.ScriptRegExp) {
261 this.script_regexp_object_ = new RegExp(script_id_or_name);
262 } else {
263 throw new Error("Unexpected breakpoint type " + type);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000264 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265 this.line_ = opt_line || 0;
266 this.column_ = opt_column;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000267 this.groupId_ = opt_groupId;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000268 this.hit_count_ = 0;
269 this.active_ = true;
270 this.condition_ = null;
271 this.ignoreCount_ = 0;
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000272 this.break_points_ = [];
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000273}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000274
275
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000276//Creates a clone of script breakpoint that is linked to another script.
277ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
278 var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
279 other_script.id, this.line_, this.column_, this.groupId_);
280 copy.number_ = next_break_point_number++;
281 script_break_points.push(copy);
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000282
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000283 copy.hit_count_ = this.hit_count_;
284 copy.active_ = this.active_;
285 copy.condition_ = this.condition_;
286 copy.ignoreCount_ = this.ignoreCount_;
287 return copy;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000288};
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000289
290
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291ScriptBreakPoint.prototype.number = function() {
292 return this.number_;
293};
294
295
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000296ScriptBreakPoint.prototype.groupId = function() {
297 return this.groupId_;
298};
299
300
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000301ScriptBreakPoint.prototype.type = function() {
302 return this.type_;
303};
304
305
306ScriptBreakPoint.prototype.script_id = function() {
307 return this.script_id_;
308};
309
310
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000311ScriptBreakPoint.prototype.script_name = function() {
312 return this.script_name_;
313};
314
315
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000316ScriptBreakPoint.prototype.script_regexp_object = function() {
317 return this.script_regexp_object_;
318};
319
320
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321ScriptBreakPoint.prototype.line = function() {
322 return this.line_;
323};
324
325
326ScriptBreakPoint.prototype.column = function() {
327 return this.column_;
328};
329
330
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000331ScriptBreakPoint.prototype.actual_locations = function() {
332 var locations = [];
333 for (var i = 0; i < this.break_points_.length; i++) {
334 locations.push(this.break_points_[i].actual_location);
335 }
336 return locations;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000337};
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000338
339
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000340ScriptBreakPoint.prototype.update_positions = function(line, column) {
341 this.line_ = line;
342 this.column_ = column;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000343};
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000344
345
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000346ScriptBreakPoint.prototype.hit_count = function() {
347 return this.hit_count_;
348};
349
350
351ScriptBreakPoint.prototype.active = function() {
352 return this.active_;
353};
354
355
356ScriptBreakPoint.prototype.condition = function() {
357 return this.condition_;
358};
359
360
361ScriptBreakPoint.prototype.ignoreCount = function() {
362 return this.ignoreCount_;
363};
364
365
366ScriptBreakPoint.prototype.enable = function() {
367 this.active_ = true;
368};
369
370
371ScriptBreakPoint.prototype.disable = function() {
372 this.active_ = false;
373};
374
375
376ScriptBreakPoint.prototype.setCondition = function(condition) {
377 this.condition_ = condition;
378};
379
380
381ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
382 this.ignoreCount_ = ignoreCount;
383
384 // Set ignore count on all break points created from this script break point.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000385 for (var i = 0; i < this.break_points_.length; i++) {
386 this.break_points_[i].setIgnoreCount(ignoreCount);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 }
388};
389
390
391// Check whether a script matches this script break point. Currently this is
392// only based on script name.
393ScriptBreakPoint.prototype.matchesScript = function(script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000394 if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
395 return this.script_id_ == script.id;
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000396 } else {
397 // We might want to account columns here as well.
398 if (!(script.line_offset <= this.line_ &&
399 this.line_ < script.line_offset + script.lineCount())) {
400 return false;
401 }
402 if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
403 return this.script_name_ == script.nameOrSourceURL();
404 } else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
405 return this.script_regexp_object_.test(script.nameOrSourceURL());
rossberg@chromium.org28a37082011-08-22 11:03:23 +0000406 } else {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000407 throw new Error("Unexpected breakpoint type " + this.type_);
408 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000409 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410};
411
412
413// Set the script break point in a script.
414ScriptBreakPoint.prototype.set = function (script) {
415 var column = this.column();
416 var line = this.line();
417 // If the column is undefined the break is on the line. To help locate the
418 // first piece of breakable code on the line try to find the column on the
419 // line which contains some source.
420 if (IS_UNDEFINED(column)) {
421 var source_line = script.sourceLine(this.line());
422
423 // Allocate array for caching the columns where the actual source starts.
424 if (!script.sourceColumnStart_) {
425 script.sourceColumnStart_ = new Array(script.lineCount());
426 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000427
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000428 // Fill cache if needed and get column where the actual source starts.
429 if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
430 script.sourceColumnStart_[line] =
431 source_line.match(sourceLineBeginningSkip)[0].length;
432 }
433 column = script.sourceColumnStart_[line];
434 }
435
436 // Convert the line and column into an absolute position within the script.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000437 var position = Debug.findScriptSourcePosition(script, this.line(), column);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000438
ager@chromium.org8bb60582008-12-11 12:02:20 +0000439 // If the position is not found in the script (the script might be shorter
440 // than it used to be) just ignore it.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000441 if (position === null) return;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000442
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000443 // Create a break point object and set the break point.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000444 break_point = MakeBreakPoint(position, this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445 break_point.setIgnoreCount(this.ignoreCount());
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000446 var actual_position = %SetScriptBreakPoint(script, position, break_point);
447 if (IS_UNDEFINED(actual_position)) {
448 actual_position = position;
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000449 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000450 var actual_location = script.locationFromPosition(actual_position, true);
451 break_point.actual_location = { line: actual_location.line,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000452 column: actual_location.column,
453 script_id: script.id };
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000454 this.break_points_.push(break_point);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455 return break_point;
456};
457
458
459// Clear all the break points created from this script break point
460ScriptBreakPoint.prototype.clear = function () {
461 var remaining_break_points = [];
462 for (var i = 0; i < break_points.length; i++) {
463 if (break_points[i].script_break_point() &&
464 break_points[i].script_break_point() === this) {
465 %ClearBreakPoint(break_points[i]);
466 } else {
467 remaining_break_points.push(break_points[i]);
468 }
469 }
470 break_points = remaining_break_points;
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000471 this.break_points_ = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000472};
473
474
475// Function called from runtime when a new script is compiled to set any script
476// break points set in this script.
477function UpdateScriptBreakPoints(script) {
478 for (var i = 0; i < script_break_points.length; i++) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000479 var break_point = script_break_points[i];
ulan@chromium.org967e2702012-02-28 09:49:15 +0000480 if ((break_point.type() == Debug.ScriptBreakPointType.ScriptName ||
481 break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) &&
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000482 break_point.matchesScript(script)) {
483 break_point.set(script);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484 }
485 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000486}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487
488
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000489function GetScriptBreakPoints(script) {
490 var result = [];
491 for (var i = 0; i < script_break_points.length; i++) {
492 if (script_break_points[i].matchesScript(script)) {
493 result.push(script_break_points[i]);
494 }
495 }
496 return result;
497}
498
499
iposva@chromium.org245aa852009-02-10 00:49:54 +0000500Debug.setListener = function(listener, opt_data) {
501 if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
502 throw new Error('Parameters have wrong types.');
503 }
504 %SetDebugEventListener(listener, opt_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505};
506
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000508Debug.breakExecution = function(f) {
mads.s.ager31e71382008-08-13 09:32:07 +0000509 %Break();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510};
511
512Debug.breakLocations = function(f) {
513 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
514 return %GetBreakLocations(f);
515};
516
517// Returns a Script object. If the parameter is a function the return value
518// is the script in which the function is defined. If the parameter is a string
519// the return value is the script for which the script name has that string
mads.s.agercbaa0602008-08-14 13:41:48 +0000520// value. If it is a regexp and there is a unique script whose name matches
521// we return that, otherwise undefined.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522Debug.findScript = function(func_or_script_name) {
523 if (IS_FUNCTION(func_or_script_name)) {
524 return %FunctionGetScript(func_or_script_name);
mads.s.agercbaa0602008-08-14 13:41:48 +0000525 } else if (IS_REGEXP(func_or_script_name)) {
526 var scripts = Debug.scripts();
527 var last_result = null;
528 var result_count = 0;
529 for (var i in scripts) {
530 var script = scripts[i];
531 if (func_or_script_name.test(script.name)) {
532 last_result = script;
533 result_count++;
534 }
535 }
536 // Return the unique script matching the regexp. If there are more
537 // than one we don't return a value since there is no good way to
538 // decide which one to return. Returning a "random" one, say the
539 // first, would introduce nondeterminism (or something close to it)
540 // because the order is the heap iteration order.
541 if (result_count == 1) {
542 return last_result;
543 } else {
544 return undefined;
545 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000546 } else {
547 return %GetScript(func_or_script_name);
548 }
549};
550
551// Returns the script source. If the parameter is a function the return value
552// is the script source for the script in which the function is defined. If the
553// parameter is a string the return value is the script for which the script
554// name has that string value.
555Debug.scriptSource = function(func_or_script_name) {
556 return this.findScript(func_or_script_name).source;
557};
558
559Debug.source = function(f) {
560 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
561 return %FunctionGetSourceCode(f);
562};
563
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000564Debug.disassemble = function(f) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000565 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000566 return %DebugDisassembleFunction(f);
567};
568
569Debug.disassembleConstructor = function(f) {
570 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
571 return %DebugDisassembleConstructor(f);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572};
573
ager@chromium.org357bf652010-04-12 11:30:10 +0000574Debug.ExecuteInDebugContext = function(f, without_debugger) {
575 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
576 return %ExecuteInDebugContext(f, !!without_debugger);
577};
578
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579Debug.sourcePosition = function(f) {
580 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
581 return %FunctionGetScriptSourcePosition(f);
582};
583
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000584
585Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586 var script = %FunctionGetScript(func);
587 var script_offset = %FunctionGetScriptSourcePosition(func);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000588 return script.locationFromLine(opt_line, opt_column, script_offset);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000589};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000590
591
592// Returns the character position in a script based on a line number and an
593// optional position within that line.
594Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000595 var location = script.locationFromLine(opt_line, opt_column);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000596 return location ? location.position : null;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000597};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598
599
600Debug.findBreakPoint = function(break_point_number, remove) {
601 var break_point;
602 for (var i = 0; i < break_points.length; i++) {
603 if (break_points[i].number() == break_point_number) {
604 break_point = break_points[i];
605 // Remove the break point from the list if requested.
606 if (remove) {
607 break_points.splice(i, 1);
608 }
609 break;
610 }
611 }
612 if (break_point) {
613 return break_point;
614 } else {
615 return this.findScriptBreakPoint(break_point_number, remove);
616 }
617};
618
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000619Debug.findBreakPointActualLocations = function(break_point_number) {
620 for (var i = 0; i < script_break_points.length; i++) {
621 if (script_break_points[i].number() == break_point_number) {
622 return script_break_points[i].actual_locations();
623 }
624 }
625 for (var i = 0; i < break_points.length; i++) {
626 if (break_points[i].number() == break_point_number) {
627 return [break_points[i].actual_location];
628 }
629 }
630 return [];
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000631};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000632
633Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
634 if (!IS_FUNCTION(func)) throw new Error('Parameters have wrong types.');
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000635 // Break points in API functions are not supported.
636 if (%FunctionIsAPIFunction(func)) {
637 throw new Error('Cannot set break point in native code.');
638 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000639 // Find source position relative to start of the function
640 var break_position =
641 this.findFunctionSourceLocation(func, opt_line, opt_column).position;
642 var source_position = break_position - this.sourcePosition(func);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643 // Find the script for the function.
644 var script = %FunctionGetScript(func);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000645 // Break in builtin JavaScript code is not supported.
646 if (script.type == Debug.ScriptType.Native) {
647 throw new Error('Cannot set break point in native code.');
648 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649 // If the script for the function has a name convert this to a script break
650 // point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000651 if (script && script.id) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652 // Adjust the source position to be script relative.
653 source_position += %FunctionGetScriptSourcePosition(func);
654 // Find line and column for the position in the script and set a script
655 // break point from that.
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000656 var location = script.locationFromPosition(source_position, false);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000657 return this.setScriptBreakPointById(script.id,
658 location.line, location.column,
659 opt_condition);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660 } else {
661 // Set a break point directly on the function.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000662 var break_point = MakeBreakPoint(source_position);
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000663 var actual_position =
664 %SetFunctionBreakPoint(func, source_position, break_point);
665 actual_position += this.sourcePosition(func);
666 var actual_location = script.locationFromPosition(actual_position, true);
667 break_point.actual_location = { line: actual_location.line,
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000668 column: actual_location.column,
669 script_id: script.id };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670 break_point.setCondition(opt_condition);
671 return break_point.number();
672 }
673};
674
675
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000676Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
677 condition, enabled)
678{
679 break_point = MakeBreakPoint(position);
680 break_point.setCondition(condition);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000681 if (!enabled) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000682 break_point.disable();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000683 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000684 var scripts = this.scripts();
685 for (var i = 0; i < scripts.length; i++) {
686 if (script_id == scripts[i].id) {
687 break_point.actual_position = %SetScriptBreakPoint(scripts[i], position,
688 break_point);
689 break;
690 }
691 }
692 return break_point;
693};
694
695
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000696Debug.enableBreakPoint = function(break_point_number) {
697 var break_point = this.findBreakPoint(break_point_number, false);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000698 // Only enable if the breakpoint hasn't been deleted:
699 if (break_point) {
700 break_point.enable();
701 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702};
703
704
705Debug.disableBreakPoint = function(break_point_number) {
706 var break_point = this.findBreakPoint(break_point_number, false);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000707 // Only enable if the breakpoint hasn't been deleted:
708 if (break_point) {
709 break_point.disable();
710 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711};
712
713
714Debug.changeBreakPointCondition = function(break_point_number, condition) {
715 var break_point = this.findBreakPoint(break_point_number, false);
716 break_point.setCondition(condition);
717};
718
719
720Debug.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
721 if (ignoreCount < 0) {
722 throw new Error('Invalid argument');
723 }
724 var break_point = this.findBreakPoint(break_point_number, false);
725 break_point.setIgnoreCount(ignoreCount);
726};
727
728
729Debug.clearBreakPoint = function(break_point_number) {
730 var break_point = this.findBreakPoint(break_point_number, true);
731 if (break_point) {
732 return %ClearBreakPoint(break_point);
733 } else {
734 break_point = this.findScriptBreakPoint(break_point_number, true);
735 if (!break_point) {
736 throw new Error('Invalid breakpoint');
737 }
738 }
739};
740
741
742Debug.clearAllBreakPoints = function() {
743 for (var i = 0; i < break_points.length; i++) {
744 break_point = break_points[i];
745 %ClearBreakPoint(break_point);
746 }
747 break_points = [];
748};
749
750
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000751Debug.disableAllBreakPoints = function() {
752 // Disable all user defined breakpoints:
753 for (var i = 1; i < next_break_point_number; i++) {
754 Debug.disableBreakPoint(i);
755 }
756 // Disable all exception breakpoints:
757 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
758 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
759};
760
761
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762Debug.findScriptBreakPoint = function(break_point_number, remove) {
763 var script_break_point;
764 for (var i = 0; i < script_break_points.length; i++) {
765 if (script_break_points[i].number() == break_point_number) {
766 script_break_point = script_break_points[i];
767 // Remove the break point from the list if requested.
768 if (remove) {
769 script_break_point.clear();
770 script_break_points.splice(i,1);
771 }
772 break;
773 }
774 }
775 return script_break_point;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000776};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000777
778
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000779// Sets a breakpoint in a script identified through id or name at the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780// specified source line and column within that line.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000781Debug.setScriptBreakPoint = function(type, script_id_or_name,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000782 opt_line, opt_column, opt_condition,
783 opt_groupId) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000784 // Create script break point object.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000785 var script_break_point =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000786 new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
787 opt_groupId);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788
789 // Assign number to the new script break point and add it.
790 script_break_point.number_ = next_break_point_number++;
791 script_break_point.setCondition(opt_condition);
792 script_break_points.push(script_break_point);
793
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000794 // Run through all scripts to see if this script break point matches any
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000795 // loaded scripts.
796 var scripts = this.scripts();
797 for (var i = 0; i < scripts.length; i++) {
798 if (script_break_point.matchesScript(scripts[i])) {
799 script_break_point.set(scripts[i]);
800 }
801 }
802
803 return script_break_point.number();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000804};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805
806
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000807Debug.setScriptBreakPointById = function(script_id,
808 opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000809 opt_condition, opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000810 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
811 script_id, opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000812 opt_condition, opt_groupId);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000813};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000814
815
816Debug.setScriptBreakPointByName = function(script_name,
817 opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000818 opt_condition, opt_groupId) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000819 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
820 script_name, opt_line, opt_column,
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000821 opt_condition, opt_groupId);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000822};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000823
824
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000825Debug.setScriptBreakPointByRegExp = function(script_regexp,
826 opt_line, opt_column,
827 opt_condition, opt_groupId) {
828 return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptRegExp,
829 script_regexp, opt_line, opt_column,
830 opt_condition, opt_groupId);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000831};
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000832
833
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834Debug.enableScriptBreakPoint = function(break_point_number) {
835 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
836 script_break_point.enable();
837};
838
839
840Debug.disableScriptBreakPoint = function(break_point_number) {
841 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
842 script_break_point.disable();
843};
844
845
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000846Debug.changeScriptBreakPointCondition = function(
847 break_point_number, condition) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000848 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
849 script_break_point.setCondition(condition);
850};
851
852
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000853Debug.changeScriptBreakPointIgnoreCount = function(
854 break_point_number, ignoreCount) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000855 if (ignoreCount < 0) {
856 throw new Error('Invalid argument');
857 }
858 var script_break_point = this.findScriptBreakPoint(break_point_number, false);
859 script_break_point.setIgnoreCount(ignoreCount);
860};
861
862
863Debug.scriptBreakPoints = function() {
864 return script_break_points;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000865};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866
867
868Debug.clearStepping = function() {
mads.s.ager31e71382008-08-13 09:32:07 +0000869 %ClearStepping();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000870};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871
872Debug.setBreakOnException = function() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000873 return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874};
875
876Debug.clearBreakOnException = function() {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000877 return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
878};
879
880Debug.isBreakOnException = function() {
881 return !!%IsBreakOnException(Debug.ExceptionBreak.Caught);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882};
883
884Debug.setBreakOnUncaughtException = function() {
885 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
886};
887
888Debug.clearBreakOnUncaughtException = function() {
889 return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
890};
891
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000892Debug.isBreakOnUncaughtException = function() {
893 return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
894};
895
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896Debug.showBreakPoints = function(f, full) {
897 if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
898 var source = full ? this.scriptSource(f) : this.source(f);
899 var offset = full ? this.sourcePosition(f) : 0;
900 var locations = this.breakLocations(f);
901 if (!locations) return source;
902 locations.sort(function(x, y) { return x - y; });
903 var result = "";
904 var prev_pos = 0;
905 var pos;
906 for (var i = 0; i < locations.length; i++) {
907 pos = locations[i] - offset;
908 result += source.slice(prev_pos, pos);
909 result += "[B" + i + "]";
910 prev_pos = pos;
911 }
912 pos = source.length;
913 result += source.substring(prev_pos, pos);
914 return result;
915};
916
917
918// Get all the scripts currently loaded. Locating all the scripts is based on
919// scanning the heap.
920Debug.scripts = function() {
921 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +0000922 return %DebugGetLoadedScripts();
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000923};
924
925
926Debug.debuggerFlags = function() {
927 return debugger_flags;
928};
929
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000930Debug.MakeMirror = MakeMirror;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000931
932function MakeExecutionState(break_id) {
933 return new ExecutionState(break_id);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000934}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000935
936function ExecutionState(break_id) {
937 this.break_id = break_id;
938 this.selected_frame = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000939}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000940
941ExecutionState.prototype.prepareStep = function(opt_action, opt_count) {
942 var action = Debug.StepAction.StepIn;
943 if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
944 var count = opt_count ? %ToNumber(opt_count) : 1;
945
946 return %PrepareStep(this.break_id, action, count);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000947};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000948
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000949ExecutionState.prototype.evaluateGlobal = function(source, disable_break,
950 opt_additional_context) {
951 return MakeMirror(%DebugEvaluateGlobal(this.break_id, source,
952 Boolean(disable_break),
953 opt_additional_context));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000954};
955
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000956ExecutionState.prototype.frameCount = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000957 return %GetFrameCount(this.break_id);
958};
959
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000960ExecutionState.prototype.threadCount = function() {
961 return %GetThreadCount(this.break_id);
962};
963
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000964ExecutionState.prototype.frame = function(opt_index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000965 // If no index supplied return the selected frame.
966 if (opt_index == null) opt_index = this.selected_frame;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000967 if (opt_index < 0 || opt_index >= this.frameCount()) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000968 throw new Error('Illegal frame index.');
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000969 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000970 return new FrameMirror(this.break_id, opt_index);
971};
972
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973ExecutionState.prototype.setSelectedFrame = function(index) {
974 var i = %ToNumber(index);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000975 if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000976 this.selected_frame = i;
977};
978
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000979ExecutionState.prototype.selectedFrame = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000980 return this.selected_frame;
981};
982
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000983ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) {
984 return new DebugCommandProcessor(this, opt_is_running);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000985};
986
987
988function MakeBreakEvent(exec_state, break_points_hit) {
989 return new BreakEvent(exec_state, break_points_hit);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000990}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991
992
993function BreakEvent(exec_state, break_points_hit) {
994 this.exec_state_ = exec_state;
995 this.break_points_hit_ = break_points_hit;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000996}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000997
998
ager@chromium.org8bb60582008-12-11 12:02:20 +0000999BreakEvent.prototype.executionState = function() {
1000 return this.exec_state_;
1001};
1002
1003
1004BreakEvent.prototype.eventType = function() {
1005 return Debug.DebugEvent.Break;
1006};
1007
1008
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001009BreakEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001010 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001011};
1012
1013
1014BreakEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001015 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001016};
1017
1018
1019BreakEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001020 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001021};
1022
1023
1024BreakEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001025 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001026};
1027
1028
1029BreakEvent.prototype.breakPointsHit = function() {
1030 return this.break_points_hit_;
1031};
1032
1033
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034BreakEvent.prototype.toJSONProtocol = function() {
1035 var o = { seq: next_response_seq++,
1036 type: "event",
1037 event: "break",
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001038 body: { invocationText: this.exec_state_.frame(0).invocationText(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001039 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001040 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041
1042 // Add script related information to the event if available.
1043 var script = this.func().script();
1044 if (script) {
1045 o.body.sourceLine = this.sourceLine(),
1046 o.body.sourceColumn = this.sourceColumn(),
1047 o.body.sourceLineText = this.sourceLineText(),
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001048 o.body.script = MakeScriptObject_(script, false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049 }
1050
1051 // Add an Array of break points hit if any.
1052 if (this.breakPointsHit()) {
1053 o.body.breakpoints = [];
1054 for (var i = 0; i < this.breakPointsHit().length; i++) {
1055 // Find the break point number. For break points originating from a
1056 // script break point supply the script break point number.
1057 var breakpoint = this.breakPointsHit()[i];
1058 var script_break_point = breakpoint.script_break_point();
1059 var number;
1060 if (script_break_point) {
1061 number = script_break_point.number();
1062 } else {
1063 number = breakpoint.number();
1064 }
1065 o.body.breakpoints.push(number);
1066 }
1067 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001068 return JSON.stringify(ObjectToProtocolObject_(o));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001069};
1070
1071
1072function MakeExceptionEvent(exec_state, exception, uncaught) {
1073 return new ExceptionEvent(exec_state, exception, uncaught);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001074}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001075
ager@chromium.org8bb60582008-12-11 12:02:20 +00001076
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001077function ExceptionEvent(exec_state, exception, uncaught) {
1078 this.exec_state_ = exec_state;
1079 this.exception_ = exception;
1080 this.uncaught_ = uncaught;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001081}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001082
ager@chromium.org8bb60582008-12-11 12:02:20 +00001083
1084ExceptionEvent.prototype.executionState = function() {
1085 return this.exec_state_;
1086};
1087
1088
1089ExceptionEvent.prototype.eventType = function() {
1090 return Debug.DebugEvent.Exception;
1091};
1092
1093
1094ExceptionEvent.prototype.exception = function() {
1095 return this.exception_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001096};
ager@chromium.org8bb60582008-12-11 12:02:20 +00001097
1098
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001099ExceptionEvent.prototype.uncaught = function() {
1100 return this.uncaught_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001101};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001102
ager@chromium.org8bb60582008-12-11 12:02:20 +00001103
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001104ExceptionEvent.prototype.func = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001105 return this.exec_state_.frame(0).func();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106};
1107
1108
1109ExceptionEvent.prototype.sourceLine = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001110 return this.exec_state_.frame(0).sourceLine();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001111};
1112
1113
1114ExceptionEvent.prototype.sourceColumn = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001115 return this.exec_state_.frame(0).sourceColumn();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001116};
1117
1118
1119ExceptionEvent.prototype.sourceLineText = function() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001120 return this.exec_state_.frame(0).sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121};
1122
1123
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001124ExceptionEvent.prototype.toJSONProtocol = function() {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001125 var o = new ProtocolMessage();
1126 o.event = "exception";
1127 o.body = { uncaught: this.uncaught_,
1128 exception: MakeMirror(this.exception_)
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001129 };
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001130
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001131 // Exceptions might happen whithout any JavaScript frames.
1132 if (this.exec_state_.frameCount() > 0) {
1133 o.body.sourceLine = this.sourceLine();
1134 o.body.sourceColumn = this.sourceColumn();
1135 o.body.sourceLineText = this.sourceLineText();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001136
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001137 // Add script information to the event if available.
1138 var script = this.func().script();
1139 if (script) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001140 o.body.script = MakeScriptObject_(script, false);
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001141 }
1142 } else {
1143 o.body.sourceLine = -1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001144 }
1145
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001146 return o.toJSONProtocol();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001147};
1148
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001149
iposva@chromium.org245aa852009-02-10 00:49:54 +00001150function MakeCompileEvent(exec_state, script, before) {
1151 return new CompileEvent(exec_state, script, before);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001152}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001153
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001154
iposva@chromium.org245aa852009-02-10 00:49:54 +00001155function CompileEvent(exec_state, script, before) {
1156 this.exec_state_ = exec_state;
1157 this.script_ = MakeMirror(script);
1158 this.before_ = before;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001159}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001160
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001161
iposva@chromium.org245aa852009-02-10 00:49:54 +00001162CompileEvent.prototype.executionState = function() {
1163 return this.exec_state_;
1164};
1165
1166
ager@chromium.org8bb60582008-12-11 12:02:20 +00001167CompileEvent.prototype.eventType = function() {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001168 if (this.before_) {
1169 return Debug.DebugEvent.BeforeCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001170 } else {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001171 return Debug.DebugEvent.AfterCompile;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001172 }
1173};
1174
1175
iposva@chromium.org245aa852009-02-10 00:49:54 +00001176CompileEvent.prototype.script = function() {
1177 return this.script_;
1178};
1179
1180
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001181CompileEvent.prototype.toJSONProtocol = function() {
1182 var o = new ProtocolMessage();
ager@chromium.org5ec48922009-05-05 07:25:34 +00001183 o.running = true;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001184 if (this.before_) {
1185 o.event = "beforeCompile";
1186 } else {
1187 o.event = "afterCompile";
1188 }
1189 o.body = {};
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001190 o.body.script = this.script_;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001191
1192 return o.toJSONProtocol();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001193};
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001194
1195
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001196function MakeNewFunctionEvent(func) {
1197 return new NewFunctionEvent(func);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001198}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001199
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001200
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001201function NewFunctionEvent(func) {
1202 this.func = func;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001203}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001204
ager@chromium.org8bb60582008-12-11 12:02:20 +00001205
1206NewFunctionEvent.prototype.eventType = function() {
1207 return Debug.DebugEvent.NewFunction;
1208};
1209
1210
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001211NewFunctionEvent.prototype.name = function() {
1212 return this.func.name;
1213};
1214
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001215
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001216NewFunctionEvent.prototype.setBreakPoint = function(p) {
1217 Debug.setBreakPoint(this.func, p || 0);
1218};
1219
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001220
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001221function MakeScriptCollectedEvent(exec_state, id) {
1222 return new ScriptCollectedEvent(exec_state, id);
1223}
1224
1225
1226function ScriptCollectedEvent(exec_state, id) {
1227 this.exec_state_ = exec_state;
1228 this.id_ = id;
1229}
1230
1231
1232ScriptCollectedEvent.prototype.id = function() {
1233 return this.id_;
1234};
1235
1236
1237ScriptCollectedEvent.prototype.executionState = function() {
1238 return this.exec_state_;
1239};
1240
1241
1242ScriptCollectedEvent.prototype.toJSONProtocol = function() {
1243 var o = new ProtocolMessage();
1244 o.running = true;
1245 o.event = "scriptCollected";
1246 o.body = {};
1247 o.body.script = { id: this.id() };
1248 return o.toJSONProtocol();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001249};
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001250
1251
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001252function MakeScriptObject_(script, include_source) {
1253 var o = { id: script.id(),
1254 name: script.name(),
1255 lineOffset: script.lineOffset(),
1256 columnOffset: script.columnOffset(),
1257 lineCount: script.lineCount(),
1258 };
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001259 if (!IS_UNDEFINED(script.data())) {
1260 o.data = script.data();
1261 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001262 if (include_source) {
1263 o.source = script.source();
1264 }
1265 return o;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001266}
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001267
1268
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001269function DebugCommandProcessor(exec_state, opt_is_running) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 this.exec_state_ = exec_state;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001271 this.running_ = opt_is_running || false;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001272}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273
1274
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001275DebugCommandProcessor.prototype.processDebugRequest = function (request) {
1276 return this.processDebugJSONRequest(request);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001277};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001278
1279
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001280function ProtocolMessage(request) {
1281 // Update sequence number.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282 this.seq = next_response_seq++;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001283
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001284 if (request) {
1285 // If message is based on a request this is a response. Fill the initial
1286 // response from the request.
1287 this.type = 'response';
1288 this.request_seq = request.seq;
1289 this.command = request.command;
1290 } else {
1291 // If message is not based on a request it is a dabugger generated event.
1292 this.type = 'event';
1293 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294 this.success = true;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001295 // Handler may set this field to control debugger state.
1296 this.running = undefined;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001297}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001298
1299
ager@chromium.org9085a012009-05-11 19:22:57 +00001300ProtocolMessage.prototype.setOption = function(name, value) {
1301 if (!this.options_) {
1302 this.options_ = {};
1303 }
1304 this.options_[name] = value;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001305};
ager@chromium.org9085a012009-05-11 19:22:57 +00001306
1307
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001308ProtocolMessage.prototype.failed = function(message, opt_details) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309 this.success = false;
1310 this.message = message;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001311 if (IS_OBJECT(opt_details)) {
1312 this.error_details = opt_details;
1313 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001314};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315
1316
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001317ProtocolMessage.prototype.toJSONProtocol = function() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001318 // Encode the protocol header.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001319 var json = {};
1320 json.seq= this.seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001321 if (this.request_seq) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001322 json.request_seq = this.request_seq;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001323 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001324 json.type = this.type;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001325 if (this.event) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001326 json.event = this.event;
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001327 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001328 if (this.command) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001329 json.command = this.command;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001330 }
1331 if (this.success) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001332 json.success = this.success;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001333 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001334 json.success = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001335 }
1336 if (this.body) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337 // Encode the body part.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001338 var bodyJson;
ager@chromium.org9085a012009-05-11 19:22:57 +00001339 var serializer = MakeMirrorSerializer(true, this.options_);
ager@chromium.org32912102009-01-16 10:38:43 +00001340 if (this.body instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001341 bodyJson = serializer.serializeValue(this.body);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001342 } else if (this.body instanceof Array) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001343 bodyJson = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001344 for (var i = 0; i < this.body.length; i++) {
ager@chromium.org32912102009-01-16 10:38:43 +00001345 if (this.body[i] instanceof Mirror) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001346 bodyJson.push(serializer.serializeValue(this.body[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001347 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001348 bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001349 }
1350 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001351 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001352 bodyJson = ObjectToProtocolObject_(this.body, serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001354 json.body = bodyJson;
1355 json.refs = serializer.serializeReferencedObjects();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356 }
1357 if (this.message) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001358 json.message = this.message;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359 }
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001360 if (this.error_details) {
1361 json.error_details = this.error_details;
1362 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001363 json.running = this.running;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001364 return JSON.stringify(json);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001365};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001366
1367
1368DebugCommandProcessor.prototype.createResponse = function(request) {
kasperl@chromium.org061ef742009-02-27 12:16:20 +00001369 return new ProtocolMessage(request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001370};
1371
1372
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001373DebugCommandProcessor.prototype.processDebugJSONRequest = function(
1374 json_request) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001375 var request; // Current request.
1376 var response; // Generated response.
1377 try {
1378 try {
1379 // Convert the JSON string to an object.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001380 request = JSON.parse(json_request);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001381
1382 // Create an initial response.
1383 response = this.createResponse(request);
1384
1385 if (!request.type) {
1386 throw new Error('Type not specified');
1387 }
1388
1389 if (request.type != 'request') {
1390 throw new Error("Illegal type '" + request.type + "' in request");
1391 }
1392
1393 if (!request.command) {
1394 throw new Error('Command not specified');
1395 }
1396
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001397 if (request.arguments) {
1398 var args = request.arguments;
1399 // TODO(yurys): remove request.arguments.compactFormat check once
1400 // ChromeDevTools are switched to 'inlineRefs'
1401 if (args.inlineRefs || args.compactFormat) {
1402 response.setOption('inlineRefs', true);
1403 }
1404 if (!IS_UNDEFINED(args.maxStringLength)) {
1405 response.setOption('maxStringLength', args.maxStringLength);
1406 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001407 }
1408
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001409 if (request.command == 'continue') {
1410 this.continueRequest_(request, response);
1411 } else if (request.command == 'break') {
1412 this.breakRequest_(request, response);
1413 } else if (request.command == 'setbreakpoint') {
1414 this.setBreakPointRequest_(request, response);
1415 } else if (request.command == 'changebreakpoint') {
1416 this.changeBreakPointRequest_(request, response);
1417 } else if (request.command == 'clearbreakpoint') {
1418 this.clearBreakPointRequest_(request, response);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001419 } else if (request.command == 'clearbreakpointgroup') {
1420 this.clearBreakPointGroupRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001421 } else if (request.command == 'disconnect') {
1422 this.disconnectRequest_(request, response);
1423 } else if (request.command == 'setexceptionbreak') {
1424 this.setExceptionBreakRequest_(request, response);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001425 } else if (request.command == 'listbreakpoints') {
1426 this.listBreakpointsRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001427 } else if (request.command == 'backtrace') {
1428 this.backtraceRequest_(request, response);
1429 } else if (request.command == 'frame') {
1430 this.frameRequest_(request, response);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001431 } else if (request.command == 'scopes') {
1432 this.scopesRequest_(request, response);
1433 } else if (request.command == 'scope') {
1434 this.scopeRequest_(request, response);
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001435 } else if (request.command == 'setVariableValue') {
1436 this.setVariableValueRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001437 } else if (request.command == 'evaluate') {
1438 this.evaluateRequest_(request, response);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001439 } else if (request.command == 'lookup') {
1440 this.lookupRequest_(request, response);
iposva@chromium.org245aa852009-02-10 00:49:54 +00001441 } else if (request.command == 'references') {
1442 this.referencesRequest_(request, response);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001443 } else if (request.command == 'source') {
1444 this.sourceRequest_(request, response);
1445 } else if (request.command == 'scripts') {
1446 this.scriptsRequest_(request, response);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001447 } else if (request.command == 'threads') {
1448 this.threadsRequest_(request, response);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001449 } else if (request.command == 'suspend') {
1450 this.suspendRequest_(request, response);
ager@chromium.org3811b432009-10-28 14:53:37 +00001451 } else if (request.command == 'version') {
1452 this.versionRequest_(request, response);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001453 } else if (request.command == 'profile') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001454 this.profileRequest_(request, response);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001455 } else if (request.command == 'changelive') {
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001456 this.changeLiveRequest_(request, response);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001457 } else if (request.command == 'restartframe') {
1458 this.restartFrameRequest_(request, response);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001459 } else if (request.command == 'flags') {
1460 this.debuggerFlagsRequest_(request, response);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001461 } else if (request.command == 'v8flags') {
1462 this.v8FlagsRequest_(request, response);
1463
1464 // GC tools:
1465 } else if (request.command == 'gc') {
1466 this.gcRequest_(request, response);
1467
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001468 } else {
1469 throw new Error('Unknown command "' + request.command + '" in request');
1470 }
1471 } catch (e) {
1472 // If there is no response object created one (without command).
1473 if (!response) {
1474 response = this.createResponse();
1475 }
1476 response.success = false;
1477 response.message = %ToString(e);
1478 }
1479
1480 // Return the response as a JSON encoded string.
1481 try {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001482 if (!IS_UNDEFINED(response.running)) {
1483 // Response controls running state.
1484 this.running_ = response.running;
1485 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00001486 response.running = this.running_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001487 return response.toJSONProtocol();
1488 } catch (e) {
1489 // Failed to generate response - return generic error.
1490 return '{"seq":' + response.seq + ',' +
1491 '"request_seq":' + request.seq + ',' +
1492 '"type":"response",' +
1493 '"success":false,' +
1494 '"message":"Internal error: ' + %ToString(e) + '"}';
1495 }
1496 } catch (e) {
1497 // Failed in one of the catch blocks above - most generic error.
1498 return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
1499 }
1500};
1501
1502
1503DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
1504 // Check for arguments for continue.
1505 if (request.arguments) {
1506 var count = 1;
1507 var action = Debug.StepAction.StepIn;
1508
1509 // Pull out arguments.
1510 var stepaction = request.arguments.stepaction;
1511 var stepcount = request.arguments.stepcount;
1512
1513 // Get the stepcount argument if any.
1514 if (stepcount) {
1515 count = %ToNumber(stepcount);
1516 if (count < 0) {
1517 throw new Error('Invalid stepcount argument "' + stepcount + '".');
1518 }
1519 }
1520
1521 // Get the stepaction argument.
1522 if (stepaction) {
1523 if (stepaction == 'in') {
1524 action = Debug.StepAction.StepIn;
1525 } else if (stepaction == 'min') {
1526 action = Debug.StepAction.StepMin;
1527 } else if (stepaction == 'next') {
1528 action = Debug.StepAction.StepNext;
1529 } else if (stepaction == 'out') {
1530 action = Debug.StepAction.StepOut;
1531 } else {
1532 throw new Error('Invalid stepaction argument "' + stepaction + '".');
1533 }
1534 }
1535
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001536 // Set up the VM for stepping.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 this.exec_state_.prepareStep(action, count);
1538 }
1539
1540 // VM should be running after executing this request.
1541 response.running = true;
1542};
1543
1544
1545DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
1546 // Ignore as break command does not do anything when broken.
1547};
1548
1549
1550DebugCommandProcessor.prototype.setBreakPointRequest_ =
1551 function(request, response) {
1552 // Check for legal request.
1553 if (!request.arguments) {
1554 response.failed('Missing arguments');
1555 return;
1556 }
1557
1558 // Pull out arguments.
1559 var type = request.arguments.type;
1560 var target = request.arguments.target;
1561 var line = request.arguments.line;
1562 var column = request.arguments.column;
1563 var enabled = IS_UNDEFINED(request.arguments.enabled) ?
1564 true : request.arguments.enabled;
1565 var condition = request.arguments.condition;
1566 var ignoreCount = request.arguments.ignoreCount;
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001567 var groupId = request.arguments.groupId;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001568
1569 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001570 if (!type || IS_UNDEFINED(target)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001571 response.failed('Missing argument "type" or "target"');
1572 return;
1573 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001574
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001575 // Either function or script break point.
1576 var break_point_number;
1577 if (type == 'function') {
1578 // Handle function break point.
1579 if (!IS_STRING(target)) {
1580 response.failed('Argument "target" is not a string value');
1581 return;
1582 }
1583 var f;
1584 try {
1585 // Find the function through a global evaluate.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001586 f = this.exec_state_.evaluateGlobal(target).value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001587 } catch (e) {
1588 response.failed('Error: "' + %ToString(e) +
1589 '" evaluating "' + target + '"');
1590 return;
1591 }
1592 if (!IS_FUNCTION(f)) {
1593 response.failed('"' + target + '" does not evaluate to a function');
1594 return;
1595 }
1596
1597 // Set function break point.
1598 break_point_number = Debug.setBreakPoint(f, line, column, condition);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001599 } else if (type == 'handle') {
1600 // Find the object pointed by the specified handle.
1601 var handle = parseInt(target, 10);
1602 var mirror = LookupMirror(handle);
1603 if (!mirror) {
1604 return response.failed('Object #' + handle + '# not found');
1605 }
1606 if (!mirror.isFunction()) {
1607 return response.failed('Object #' + handle + '# is not a function');
1608 }
1609
1610 // Set function break point.
1611 break_point_number = Debug.setBreakPoint(mirror.value(),
1612 line, column, condition);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001613 } else if (type == 'script') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001614 // set script break point.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001615 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001616 Debug.setScriptBreakPointByName(target, line, column, condition,
1617 groupId);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001618 } else if (type == 'scriptId') {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001619 break_point_number =
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001620 Debug.setScriptBreakPointById(target, line, column, condition, groupId);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001621 } else if (type == 'scriptRegExp') {
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001622 break_point_number =
1623 Debug.setScriptBreakPointByRegExp(target, line, column, condition,
1624 groupId);
1625 } else {
1626 response.failed('Illegal type "' + type + '"');
1627 return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628 }
1629
1630 // Set additional break point properties.
1631 var break_point = Debug.findBreakPoint(break_point_number);
1632 if (ignoreCount) {
1633 Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
1634 }
1635 if (!enabled) {
1636 Debug.disableBreakPoint(break_point_number);
1637 }
1638
1639 // Add the break point number to the response.
1640 response.body = { type: type,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001641 breakpoint: break_point_number };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001642
1643 // Add break point information to the response.
1644 if (break_point instanceof ScriptBreakPoint) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001645 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1646 response.body.type = 'scriptId';
1647 response.body.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001648 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001649 response.body.type = 'scriptName';
1650 response.body.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001651 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1652 response.body.type = 'scriptRegExp';
1653 response.body.script_regexp = break_point.script_regexp_object().source;
1654 } else {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001655 throw new Error("Internal error: Unexpected breakpoint type: " +
1656 break_point.type());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001657 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001658 response.body.line = break_point.line();
1659 response.body.column = break_point.column();
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001660 response.body.actual_locations = break_point.actual_locations();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001661 } else {
1662 response.body.type = 'function';
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001663 response.body.actual_locations = [break_point.actual_location];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001664 }
1665};
1666
1667
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001668DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(
1669 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001670 // Check for legal request.
1671 if (!request.arguments) {
1672 response.failed('Missing arguments');
1673 return;
1674 }
1675
1676 // Pull out arguments.
1677 var break_point = %ToNumber(request.arguments.breakpoint);
1678 var enabled = request.arguments.enabled;
1679 var condition = request.arguments.condition;
1680 var ignoreCount = request.arguments.ignoreCount;
1681
1682 // Check for legal arguments.
1683 if (!break_point) {
1684 response.failed('Missing argument "breakpoint"');
1685 return;
1686 }
1687
1688 // Change enabled state if supplied.
1689 if (!IS_UNDEFINED(enabled)) {
1690 if (enabled) {
1691 Debug.enableBreakPoint(break_point);
1692 } else {
1693 Debug.disableBreakPoint(break_point);
1694 }
1695 }
1696
1697 // Change condition if supplied
1698 if (!IS_UNDEFINED(condition)) {
1699 Debug.changeBreakPointCondition(break_point, condition);
1700 }
1701
1702 // Change ignore count if supplied
1703 if (!IS_UNDEFINED(ignoreCount)) {
1704 Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
1705 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001706};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001707
1708
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001709DebugCommandProcessor.prototype.clearBreakPointGroupRequest_ = function(
1710 request, response) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001711 // Check for legal request.
1712 if (!request.arguments) {
1713 response.failed('Missing arguments');
1714 return;
1715 }
1716
1717 // Pull out arguments.
1718 var group_id = request.arguments.groupId;
1719
1720 // Check for legal arguments.
1721 if (!group_id) {
1722 response.failed('Missing argument "groupId"');
1723 return;
1724 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001725
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001726 var cleared_break_points = [];
1727 var new_script_break_points = [];
1728 for (var i = 0; i < script_break_points.length; i++) {
1729 var next_break_point = script_break_points[i];
1730 if (next_break_point.groupId() == group_id) {
1731 cleared_break_points.push(next_break_point.number());
1732 next_break_point.clear();
1733 } else {
1734 new_script_break_points.push(next_break_point);
1735 }
1736 }
1737 script_break_points = new_script_break_points;
1738
1739 // Add the cleared break point numbers to the response.
1740 response.body = { breakpoints: cleared_break_points };
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001741};
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001742
1743
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001744DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(
1745 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001746 // Check for legal request.
1747 if (!request.arguments) {
1748 response.failed('Missing arguments');
1749 return;
1750 }
1751
1752 // Pull out arguments.
1753 var break_point = %ToNumber(request.arguments.breakpoint);
1754
1755 // Check for legal arguments.
1756 if (!break_point) {
1757 response.failed('Missing argument "breakpoint"');
1758 return;
1759 }
1760
1761 // Clear break point.
1762 Debug.clearBreakPoint(break_point);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001763
1764 // Add the cleared break point number to the response.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001765 response.body = { breakpoint: break_point };
1766};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001767
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001768
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001769DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(
1770 request, response) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001771 var array = [];
1772 for (var i = 0; i < script_break_points.length; i++) {
1773 var break_point = script_break_points[i];
1774
1775 var description = {
1776 number: break_point.number(),
1777 line: break_point.line(),
1778 column: break_point.column(),
1779 groupId: break_point.groupId(),
1780 hit_count: break_point.hit_count(),
1781 active: break_point.active(),
1782 condition: break_point.condition(),
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001783 ignoreCount: break_point.ignoreCount(),
1784 actual_locations: break_point.actual_locations()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001785 };
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001786
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001787 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
1788 description.type = 'scriptId';
1789 description.script_id = break_point.script_id();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001790 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) {
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001791 description.type = 'scriptName';
1792 description.script_name = break_point.script_name();
lrn@chromium.orgac2828d2011-06-23 06:29:21 +00001793 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) {
1794 description.type = 'scriptRegExp';
1795 description.script_regexp = break_point.script_regexp_object().source;
1796 } else {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001797 throw new Error("Internal error: Unexpected breakpoint type: " +
1798 break_point.type());
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001799 }
1800 array.push(description);
1801 }
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001802
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001803 response.body = {
1804 breakpoints: array,
1805 breakOnExceptions: Debug.isBreakOnException(),
1806 breakOnUncaughtExceptions: Debug.isBreakOnUncaughtException()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001807 };
1808};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001809
1810
1811DebugCommandProcessor.prototype.disconnectRequest_ =
1812 function(request, response) {
1813 Debug.disableAllBreakPoints();
1814 this.continueRequest_(request, response);
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001815};
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001816
1817
1818DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
1819 function(request, response) {
1820 // Check for legal request.
1821 if (!request.arguments) {
1822 response.failed('Missing arguments');
1823 return;
1824 }
1825
1826 // Pull out and check the 'type' argument:
1827 var type = request.arguments.type;
1828 if (!type) {
1829 response.failed('Missing argument "type"');
1830 return;
1831 }
1832
1833 // Initialize the default value of enable:
1834 var enabled;
1835 if (type == 'all') {
1836 enabled = !Debug.isBreakOnException();
1837 } else if (type == 'uncaught') {
1838 enabled = !Debug.isBreakOnUncaughtException();
rossberg@chromium.org28a37082011-08-22 11:03:23 +00001839 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001840
1841 // Pull out and check the 'enabled' argument if present:
1842 if (!IS_UNDEFINED(request.arguments.enabled)) {
1843 enabled = request.arguments.enabled;
1844 if ((enabled != true) && (enabled != false)) {
1845 response.failed('Illegal value for "enabled":"' + enabled + '"');
1846 }
1847 }
1848
1849 // Now set the exception break state:
1850 if (type == 'all') {
1851 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, enabled);
1852 } else if (type == 'uncaught') {
1853 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, enabled);
1854 } else {
1855 response.failed('Unknown "type":"' + type + '"');
1856 }
1857
1858 // Add the cleared break point number to the response.
1859 response.body = { 'type': type, 'enabled': enabled };
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001860};
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001861
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001862
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001863DebugCommandProcessor.prototype.backtraceRequest_ = function(
1864 request, response) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001865 // Get the number of frames.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001866 var total_frames = this.exec_state_.frameCount();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001867
ager@chromium.org8bb60582008-12-11 12:02:20 +00001868 // Create simple response if there are no frames.
1869 if (total_frames == 0) {
1870 response.body = {
1871 totalFrames: total_frames
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001872 };
ager@chromium.org8bb60582008-12-11 12:02:20 +00001873 return;
1874 }
1875
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001876 // Default frame range to include in backtrace.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001877 var from_index = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001878 var to_index = kDefaultBacktraceLength;
1879
1880 // Get the range from the arguments.
1881 if (request.arguments) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001882 if (request.arguments.fromFrame) {
1883 from_index = request.arguments.fromFrame;
1884 }
1885 if (request.arguments.toFrame) {
1886 to_index = request.arguments.toFrame;
1887 }
1888 if (request.arguments.bottom) {
1889 var tmp_index = total_frames - from_index;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001890 from_index = total_frames - to_index;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001891 to_index = tmp_index;
1892 }
1893 if (from_index < 0 || to_index < 0) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001894 return response.failed('Invalid frame number');
1895 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001896 }
1897
1898 // Adjust the index.
1899 to_index = Math.min(total_frames, to_index);
1900
1901 if (to_index <= from_index) {
1902 var error = 'Invalid frame range';
1903 return response.failed(error);
1904 }
1905
1906 // Create the response body.
1907 var frames = [];
1908 for (var i = from_index; i < to_index; i++) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001909 frames.push(this.exec_state_.frame(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001910 }
1911 response.body = {
1912 fromFrame: from_index,
1913 toFrame: to_index,
1914 totalFrames: total_frames,
1915 frames: frames
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001916 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001917};
1918
1919
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001920DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001921 // No frames no source.
1922 if (this.exec_state_.frameCount() == 0) {
1923 return response.failed('No frames');
1924 }
1925
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001926 // With no arguments just keep the selected frame.
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001927 if (request.arguments) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001928 var index = request.arguments.number;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001929 if (index < 0 || this.exec_state_.frameCount() <= index) {
1930 return response.failed('Invalid frame number');
1931 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001932
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001933 this.exec_state_.setSelectedFrame(request.arguments.number);
1934 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001935 response.body = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001936};
1937
1938
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001939DebugCommandProcessor.prototype.resolveFrameFromScopeDescription_ =
1940 function(scope_description) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001941 // Get the frame for which the scope or scopes are requested.
1942 // With no frameNumber argument use the currently selected frame.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001943 if (scope_description && !IS_UNDEFINED(scope_description.frameNumber)) {
1944 frame_index = scope_description.frameNumber;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001945 if (frame_index < 0 || this.exec_state_.frameCount() <= frame_index) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001946 throw new Error('Invalid frame number');
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001947 }
1948 return this.exec_state_.frame(frame_index);
1949 } else {
1950 return this.exec_state_.frame();
1951 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001952};
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001953
1954
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001955// Gets scope host object from request. It is either a function
1956// ('functionHandle' argument must be specified) or a stack frame
1957// ('frameNumber' may be specified and the current frame is taken by default).
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001958DebugCommandProcessor.prototype.resolveScopeHolder_ =
1959 function(scope_description) {
1960 if (scope_description && "functionHandle" in scope_description) {
1961 if (!IS_NUMBER(scope_description.functionHandle)) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001962 throw new Error('Function handle must be a number');
1963 }
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001964 var function_mirror = LookupMirror(scope_description.functionHandle);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001965 if (!function_mirror) {
1966 throw new Error('Failed to find function object by handle');
1967 }
1968 if (!function_mirror.isFunction()) {
1969 throw new Error('Value of non-function type is found by handle');
1970 }
1971 return function_mirror;
1972 } else {
1973 // No frames no scopes.
1974 if (this.exec_state_.frameCount() == 0) {
1975 throw new Error('No scopes');
1976 }
1977
1978 // Get the frame for which the scopes are requested.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001979 var frame = this.resolveFrameFromScopeDescription_(scope_description);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001980 return frame;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001981 }
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001982}
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001983
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001984
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001985DebugCommandProcessor.prototype.scopesRequest_ = function(request, response) {
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001986 var scope_holder = this.resolveScopeHolder_(request.arguments);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001987
1988 // Fill all scopes for this frame or function.
1989 var total_scopes = scope_holder.scopeCount();
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001990 var scopes = [];
1991 for (var i = 0; i < total_scopes; i++) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00001992 scopes.push(scope_holder.scope(i));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001993 }
1994 response.body = {
1995 fromScope: 0,
1996 toScope: total_scopes,
1997 totalScopes: total_scopes,
1998 scopes: scopes
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001999 };
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002000};
2001
2002
2003DebugCommandProcessor.prototype.scopeRequest_ = function(request, response) {
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002004 // Get the frame or function for which the scope is requested.
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002005 var scope_holder = this.resolveScopeHolder_(request.arguments);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002006
2007 // With no scope argument just return top scope.
2008 var scope_index = 0;
2009 if (request.arguments && !IS_UNDEFINED(request.arguments.number)) {
2010 scope_index = %ToNumber(request.arguments.number);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002011 if (scope_index < 0 || scope_holder.scopeCount() <= scope_index) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002012 return response.failed('Invalid scope number');
2013 }
2014 }
2015
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002016 response.body = scope_holder.scope(scope_index);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002017};
2018
2019
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002020// Reads value from protocol description. Description may be in form of type
2021// (for singletons), raw value (primitive types supported in JSON),
2022// string value description plus type (for primitive values) or handle id.
2023// Returns raw value or throws exception.
2024DebugCommandProcessor.resolveValue_ = function(value_description) {
2025 if ("handle" in value_description) {
2026 var value_mirror = LookupMirror(value_description.handle);
2027 if (!value_mirror) {
2028 throw new Error("Failed to resolve value by handle, ' #" +
2029 mapping.handle + "# not found");
2030 }
2031 return value_mirror.value();
2032 } else if ("stringDescription" in value_description) {
2033 if (value_description.type == BOOLEAN_TYPE) {
2034 return Boolean(value_description.stringDescription);
2035 } else if (value_description.type == NUMBER_TYPE) {
2036 return Number(value_description.stringDescription);
2037 } if (value_description.type == STRING_TYPE) {
2038 return String(value_description.stringDescription);
2039 } else {
2040 throw new Error("Unknown type");
2041 }
2042 } else if ("value" in value_description) {
2043 return value_description.value;
2044 } else if (value_description.type == UNDEFINED_TYPE) {
2045 return void 0;
2046 } else if (value_description.type == NULL_TYPE) {
2047 return null;
2048 } else {
2049 throw new Error("Failed to parse value description");
2050 }
2051};
2052
2053
2054DebugCommandProcessor.prototype.setVariableValueRequest_ =
2055 function(request, response) {
2056 if (!request.arguments) {
2057 response.failed('Missing arguments');
2058 return;
2059 }
2060
2061 if (IS_UNDEFINED(request.arguments.name)) {
2062 response.failed('Missing variable name');
2063 }
2064 var variable_name = request.arguments.name;
2065
2066 var scope_description = request.arguments.scope;
2067
2068 // Get the frame or function for which the scope is requested.
2069 var scope_holder = this.resolveScopeHolder_(scope_description);
2070
2071 if (IS_UNDEFINED(scope_description.number)) {
2072 response.failed('Missing scope number');
2073 }
2074 var scope_index = %ToNumber(scope_description.number);
2075
2076 var scope = scope_holder.scope(scope_index);
2077
2078 var new_value =
2079 DebugCommandProcessor.resolveValue_(request.arguments.newValue);
2080
2081 scope.setVariableValue(variable_name, new_value);
2082
2083 var new_value_mirror = MakeMirror(new_value);
2084
2085 response.body = {
2086 newValue: new_value_mirror
2087 };
2088};
2089
2090
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002091DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
2092 if (!request.arguments) {
2093 return response.failed('Missing arguments');
2094 }
2095
2096 // Pull out arguments.
2097 var expression = request.arguments.expression;
2098 var frame = request.arguments.frame;
2099 var global = request.arguments.global;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002100 var disable_break = request.arguments.disable_break;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002101 var additional_context = request.arguments.additional_context;
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002102
2103 // The expression argument could be an integer so we convert it to a
2104 // string.
2105 try {
2106 expression = String(expression);
2107 } catch(e) {
2108 return response.failed('Failed to convert expression argument to string');
2109 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002110
2111 // Check for legal arguments.
2112 if (!IS_UNDEFINED(frame) && global) {
2113 return response.failed('Arguments "frame" and "global" are exclusive');
2114 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002115
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002116 var additional_context_object;
2117 if (additional_context) {
2118 additional_context_object = {};
2119 for (var i = 0; i < additional_context.length; i++) {
2120 var mapping = additional_context[i];
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002121
2122 if (!IS_STRING(mapping.name)) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002123 return response.failed("Context element #" + i +
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002124 " doesn't contain name:string property");
rossberg@chromium.org28a37082011-08-22 11:03:23 +00002125 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002126
2127 var raw_value = DebugCommandProcessor.resolveValue_(mapping);
2128 additional_context_object[mapping.name] = raw_value;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002129 }
2130 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002131
2132 // Global evaluate.
2133 if (global) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002134 // Evaluate in the native context.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002135 response.body = this.exec_state_.evaluateGlobal(
2136 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002137 return;
2138 }
2139
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002140 // Default value for disable_break is true.
2141 if (IS_UNDEFINED(disable_break)) {
2142 disable_break = true;
2143 }
2144
ager@chromium.org381abbb2009-02-25 13:23:22 +00002145 // No frames no evaluate in frame.
2146 if (this.exec_state_.frameCount() == 0) {
2147 return response.failed('No frames');
2148 }
2149
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002150 // Check whether a frame was specified.
2151 if (!IS_UNDEFINED(frame)) {
2152 var frame_number = %ToNumber(frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002153 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002154 return response.failed('Invalid frame "' + frame + '"');
2155 }
2156 // Evaluate in the specified frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002157 response.body = this.exec_state_.frame(frame_number).evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002158 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002159 return;
2160 } else {
2161 // Evaluate in the selected frame.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002162 response.body = this.exec_state_.frame().evaluate(
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002163 expression, Boolean(disable_break), additional_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002164 return;
2165 }
2166};
2167
2168
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002169DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
2170 if (!request.arguments) {
2171 return response.failed('Missing arguments');
2172 }
2173
2174 // Pull out arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002175 var handles = request.arguments.handles;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002176
2177 // Check for legal arguments.
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002178 if (IS_UNDEFINED(handles)) {
2179 return response.failed('Argument "handles" missing');
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002180 }
2181
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002182 // Set 'includeSource' option for script lookup.
2183 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2184 includeSource = %ToBoolean(request.arguments.includeSource);
2185 response.setOption('includeSource', includeSource);
2186 }
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00002187
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002188 // Lookup handles.
2189 var mirrors = {};
2190 for (var i = 0; i < handles.length; i++) {
2191 var handle = handles[i];
2192 var mirror = LookupMirror(handle);
2193 if (!mirror) {
2194 return response.failed('Object #' + handle + '# not found');
2195 }
2196 mirrors[handle] = mirror;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002197 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002198 response.body = mirrors;
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002199};
2200
2201
iposva@chromium.org245aa852009-02-10 00:49:54 +00002202DebugCommandProcessor.prototype.referencesRequest_ =
2203 function(request, response) {
2204 if (!request.arguments) {
2205 return response.failed('Missing arguments');
2206 }
2207
2208 // Pull out arguments.
2209 var type = request.arguments.type;
2210 var handle = request.arguments.handle;
2211
2212 // Check for legal arguments.
2213 if (IS_UNDEFINED(type)) {
2214 return response.failed('Argument "type" missing');
2215 }
2216 if (IS_UNDEFINED(handle)) {
2217 return response.failed('Argument "handle" missing');
2218 }
2219 if (type != 'referencedBy' && type != 'constructedBy') {
2220 return response.failed('Invalid type "' + type + '"');
2221 }
2222
2223 // Lookup handle and return objects with references the object.
2224 var mirror = LookupMirror(handle);
2225 if (mirror) {
2226 if (type == 'referencedBy') {
2227 response.body = mirror.referencedBy();
2228 } else {
2229 response.body = mirror.constructedBy();
2230 }
2231 } else {
2232 return response.failed('Object #' + handle + '# not found');
2233 }
2234};
2235
2236
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002237DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00002238 // No frames no source.
2239 if (this.exec_state_.frameCount() == 0) {
2240 return response.failed('No source');
2241 }
2242
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002243 var from_line;
2244 var to_line;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002245 var frame = this.exec_state_.frame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002246 if (request.arguments) {
2247 // Pull out arguments.
2248 from_line = request.arguments.fromLine;
2249 to_line = request.arguments.toLine;
2250
2251 if (!IS_UNDEFINED(request.arguments.frame)) {
2252 var frame_number = %ToNumber(request.arguments.frame);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002253 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002254 return response.failed('Invalid frame "' + frame + '"');
2255 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002256 frame = this.exec_state_.frame(frame_number);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002257 }
2258 }
2259
2260 // Get the script selected.
2261 var script = frame.func().script();
2262 if (!script) {
2263 return response.failed('No source');
2264 }
2265
2266 // Get the source slice and fill it into the response.
2267 var slice = script.sourceSlice(from_line, to_line);
2268 if (!slice) {
2269 return response.failed('Invalid line interval');
2270 }
2271 response.body = {};
2272 response.body.source = slice.sourceText();
2273 response.body.fromLine = slice.from_line;
2274 response.body.toLine = slice.to_line;
2275 response.body.fromPosition = slice.from_position;
2276 response.body.toPosition = slice.to_position;
2277 response.body.totalLines = script.lineCount();
2278};
2279
2280
2281DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
2282 var types = ScriptTypeFlag(Debug.ScriptType.Normal);
ager@chromium.org41826e72009-03-30 13:30:57 +00002283 var includeSource = false;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002284 var idsToInclude = null;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002285 if (request.arguments) {
2286 // Pull out arguments.
2287 if (!IS_UNDEFINED(request.arguments.types)) {
2288 types = %ToNumber(request.arguments.types);
2289 if (isNaN(types) || types < 0) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002290 return response.failed('Invalid types "' +
2291 request.arguments.types + '"');
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002292 }
2293 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002294
ager@chromium.org41826e72009-03-30 13:30:57 +00002295 if (!IS_UNDEFINED(request.arguments.includeSource)) {
2296 includeSource = %ToBoolean(request.arguments.includeSource);
ager@chromium.org9085a012009-05-11 19:22:57 +00002297 response.setOption('includeSource', includeSource);
ager@chromium.org41826e72009-03-30 13:30:57 +00002298 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002299
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002300 if (IS_ARRAY(request.arguments.ids)) {
2301 idsToInclude = {};
2302 var ids = request.arguments.ids;
2303 for (var i = 0; i < ids.length; i++) {
2304 idsToInclude[ids[i]] = true;
2305 }
2306 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002307
2308 var filterStr = null;
2309 var filterNum = null;
2310 if (!IS_UNDEFINED(request.arguments.filter)) {
2311 var num = %ToNumber(request.arguments.filter);
2312 if (!isNaN(num)) {
2313 filterNum = num;
2314 }
2315 filterStr = request.arguments.filter;
2316 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002317 }
2318
2319 // Collect all scripts in the heap.
mads.s.ager31e71382008-08-13 09:32:07 +00002320 var scripts = %DebugGetLoadedScripts();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002321
2322 response.body = [];
2323
2324 for (var i = 0; i < scripts.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002325 if (idsToInclude && !idsToInclude[scripts[i].id]) {
2326 continue;
2327 }
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002328 if (filterStr || filterNum) {
2329 var script = scripts[i];
2330 var found = false;
2331 if (filterNum && !found) {
2332 if (script.id && script.id === filterNum) {
2333 found = true;
2334 }
2335 }
2336 if (filterStr && !found) {
2337 if (script.name && script.name.indexOf(filterStr) >= 0) {
2338 found = true;
2339 }
2340 }
2341 if (!found) continue;
2342 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002343 if (types & ScriptTypeFlag(scripts[i].type)) {
ager@chromium.org9085a012009-05-11 19:22:57 +00002344 response.body.push(MakeMirror(scripts[i]));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002345 }
2346 }
2347};
2348
2349
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002350DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
2351 // Get the number of threads.
2352 var total_threads = this.exec_state_.threadCount();
2353
2354 // Get information for all threads.
2355 var threads = [];
2356 for (var i = 0; i < total_threads; i++) {
2357 var details = %GetThreadDetails(this.exec_state_.break_id, i);
2358 var thread_info = { current: details[0],
2359 id: details[1]
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002360 };
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002361 threads.push(thread_info);
2362 }
2363
2364 // Create the response body.
2365 response.body = {
2366 totalThreads: total_threads,
2367 threads: threads
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002368 };
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002369};
2370
2371
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002372DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002373 response.running = false;
2374};
2375
2376
ager@chromium.org3811b432009-10-28 14:53:37 +00002377DebugCommandProcessor.prototype.versionRequest_ = function(request, response) {
2378 response.body = {
2379 V8Version: %GetV8Version()
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002380 };
ager@chromium.org3811b432009-10-28 14:53:37 +00002381};
2382
2383
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002384DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002385 if (request.arguments.command == 'resume') {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002386 %ProfilerResume();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002387 } else if (request.arguments.command == 'pause') {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002388 %ProfilerPause();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002389 } else {
2390 return response.failed('Unknown command');
2391 }
2392 response.body = {};
2393};
2394
2395
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002396DebugCommandProcessor.prototype.changeLiveRequest_ = function(
2397 request, response) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002398 if (!request.arguments) {
2399 return response.failed('Missing arguments');
2400 }
2401 var script_id = request.arguments.script_id;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002402 var preview_only = !!request.arguments.preview_only;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002403
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002404 var scripts = %DebugGetLoadedScripts();
2405
2406 var the_script = null;
2407 for (var i = 0; i < scripts.length; i++) {
2408 if (scripts[i].id == script_id) {
2409 the_script = scripts[i];
2410 }
2411 }
2412 if (!the_script) {
2413 response.failed('Script not found');
2414 return;
2415 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002416
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002417 var change_log = new Array();
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002418
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002419 if (!IS_STRING(request.arguments.new_source)) {
2420 throw "new_source argument expected";
lrn@chromium.org25156de2010-04-06 13:10:27 +00002421 }
2422
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002423 var new_source = request.arguments.new_source;
vegorov@chromium.org42841962010-10-18 11:18:59 +00002424
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002425 var result_description;
2426 try {
2427 result_description = Debug.LiveEdit.SetScriptSource(the_script,
2428 new_source, preview_only, change_log);
2429 } catch (e) {
2430 if (e instanceof Debug.LiveEdit.Failure && "details" in e) {
2431 response.failed(e.message, e.details);
2432 return;
2433 }
2434 throw e;
2435 }
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002436 response.body = {change_log: change_log, result: result_description};
vegorov@chromium.org42841962010-10-18 11:18:59 +00002437
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002438 if (!preview_only && !this.running_ && result_description.stack_modified) {
2439 response.body.stepin_recommended = true;
2440 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002441};
2442
2443
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00002444DebugCommandProcessor.prototype.restartFrameRequest_ = function(
2445 request, response) {
2446 if (!request.arguments) {
2447 return response.failed('Missing arguments');
2448 }
2449 var frame = request.arguments.frame;
2450
2451 // No frames to evaluate in frame.
2452 if (this.exec_state_.frameCount() == 0) {
2453 return response.failed('No frames');
2454 }
2455
2456 var frame_mirror;
2457 // Check whether a frame was specified.
2458 if (!IS_UNDEFINED(frame)) {
2459 var frame_number = %ToNumber(frame);
2460 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
2461 return response.failed('Invalid frame "' + frame + '"');
2462 }
2463 // Restart specified frame.
2464 frame_mirror = this.exec_state_.frame(frame_number);
2465 } else {
2466 // Restart selected frame.
2467 frame_mirror = this.exec_state_.frame();
2468 }
2469
2470 var result_description = Debug.LiveEdit.RestartFrame(frame_mirror);
2471 response.body = {result: result_description};
2472};
2473
2474
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002475DebugCommandProcessor.prototype.debuggerFlagsRequest_ = function(request,
2476 response) {
2477 // Check for legal request.
2478 if (!request.arguments) {
2479 response.failed('Missing arguments');
2480 return;
2481 }
2482
2483 // Pull out arguments.
2484 var flags = request.arguments.flags;
2485
2486 response.body = { flags: [] };
2487 if (!IS_UNDEFINED(flags)) {
2488 for (var i = 0; i < flags.length; i++) {
2489 var name = flags[i].name;
2490 var debugger_flag = debugger_flags[name];
2491 if (!debugger_flag) {
2492 continue;
2493 }
2494 if ('value' in flags[i]) {
2495 debugger_flag.setValue(flags[i].value);
2496 }
2497 response.body.flags.push({ name: name, value: debugger_flag.getValue() });
2498 }
2499 } else {
2500 for (var name in debugger_flags) {
2501 var value = debugger_flags[name].getValue();
2502 response.body.flags.push({ name: name, value: value });
2503 }
2504 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002505};
whesse@chromium.orge90029b2010-08-02 11:52:17 +00002506
2507
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002508DebugCommandProcessor.prototype.v8FlagsRequest_ = function(request, response) {
2509 var flags = request.arguments.flags;
2510 if (!flags) flags = '';
2511 %SetFlags(flags);
2512};
2513
2514
2515DebugCommandProcessor.prototype.gcRequest_ = function(request, response) {
2516 var type = request.arguments.type;
2517 if (!type) type = 'all';
2518
2519 var before = %GetHeapUsage();
2520 %CollectGarbage(type);
2521 var after = %GetHeapUsage();
2522
2523 response.body = { "before": before, "after": after };
2524};
2525
2526
iposva@chromium.org245aa852009-02-10 00:49:54 +00002527// Check whether the previously processed command caused the VM to become
2528// running.
2529DebugCommandProcessor.prototype.isRunning = function() {
2530 return this.running_;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002531};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002532
2533
2534DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
mads.s.ager31e71382008-08-13 09:32:07 +00002535 return %SystemBreak();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002536};
2537
2538
2539function NumberToHex8Str(n) {
2540 var r = "";
2541 for (var i = 0; i < 8; ++i) {
2542 var c = hexCharArray[n & 0x0F]; // hexCharArray is defined in uri.js
2543 r = c + r;
2544 n = n >>> 4;
2545 }
2546 return r;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002547}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002548
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002549
2550/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002551 * Convert an Object to its debugger protocol representation. The representation
2552 * may be serilized to a JSON object using JSON.stringify().
2553 * This implementation simply runs through all string property names, converts
2554 * each property value to a protocol value and adds the property to the result
2555 * object. For type "object" the function will be called recursively. Note that
2556 * circular structures will cause infinite recursion.
2557 * @param {Object} object The object to format as protocol object.
ager@chromium.org32912102009-01-16 10:38:43 +00002558 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2559 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002560 * @return {Object} Protocol object value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002561 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002562function ObjectToProtocolObject_(object, mirror_serializer) {
2563 var content = {};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002564 for (var key in object) {
2565 // Only consider string keys.
2566 if (typeof key == 'string') {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002567 // Format the value based on its type.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002568 var property_value_json = ValueToProtocolValue_(object[key],
2569 mirror_serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002570 // Add the property if relevant.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002571 if (!IS_UNDEFINED(property_value_json)) {
2572 content[key] = property_value_json;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002573 }
2574 }
2575 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002576
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002577 return content;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002578}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002579
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002580
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002581/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002582 * Convert an array to its debugger protocol representation. It will convert
2583 * each array element to a protocol value.
2584 * @param {Array} array The array to format as protocol array.
ager@chromium.org32912102009-01-16 10:38:43 +00002585 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2586 * mirror objects are encountered.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002587 * @return {Array} Protocol array value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002588 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002589function ArrayToProtocolArray_(array, mirror_serializer) {
2590 var json = [];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002591 for (var i = 0; i < array.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002592 json.push(ValueToProtocolValue_(array[i], mirror_serializer));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002593 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002594 return json;
2595}
2596
2597
2598/**
lrn@chromium.org25156de2010-04-06 13:10:27 +00002599 * Convert a value to its debugger protocol representation.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002600 * @param {*} value The value to format as protocol value.
2601 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
2602 * mirror objects are encountered.
2603 * @return {*} Protocol value.
2604 */
2605function ValueToProtocolValue_(value, mirror_serializer) {
2606 // Format the value based on its type.
2607 var json;
2608 switch (typeof value) {
2609 case 'object':
2610 if (value instanceof Mirror) {
2611 json = mirror_serializer.serializeValue(value);
2612 } else if (IS_ARRAY(value)){
2613 json = ArrayToProtocolArray_(value, mirror_serializer);
2614 } else {
2615 json = ObjectToProtocolObject_(value, mirror_serializer);
2616 }
2617 break;
2618
2619 case 'boolean':
2620 case 'string':
2621 case 'number':
2622 json = value;
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00002623 break;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002624
2625 default:
2626 json = null;
2627 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002628 return json;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002629}
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002630
2631Debug.TestApi = {
2632 CommandProcessorResolveValue: DebugCommandProcessor.resolveValue_
2633};