| OLD | NEW |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 "use strict"; | 5 "use strict"; |
| 6 | 6 |
| 7 String.prototype.startsWith = function (str) { | 7 String.prototype.startsWith = function (str) { |
| 8 if (str.length > this.length) { | 8 if (str.length > this.length) { |
| 9 return false; | 9 return false; |
| 10 } | 10 } |
| 11 return this.substr(0, str.length) == str; | 11 return this.substr(0, str.length) == str; |
| 12 }; | 12 }; |
| 13 | 13 |
| 14 function log10(num) { | |
| 15 return Math.log(num)/Math.log(10); | |
| 16 } | |
| 17 | |
| 18 function ToInspectableObject(obj) { | 14 function ToInspectableObject(obj) { |
| 19 if (!obj && typeof obj === 'object') { | 15 if (!obj && typeof obj === 'object') { |
| 20 return UNDEFINED; | 16 return UNDEFINED; |
| 21 } else { | 17 } else { |
| 22 return Object(obj); | 18 return Object(obj); |
| 23 } | 19 } |
| 24 } | 20 } |
| 25 | 21 |
| 26 function GetCompletions(global, last, full) { | 22 function GetCompletions(global, last, full) { |
| 27 var full_tokens = full.split(); | 23 var full_tokens = full.split(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 46 var name = properties[i].name(); | 42 var name = properties[i].name(); |
| 47 if (typeof name === 'string' && name.startsWith(last)) { | 43 if (typeof name === 'string' && name.startsWith(last)) { |
| 48 result.push(name); | 44 result.push(name); |
| 49 } | 45 } |
| 50 } | 46 } |
| 51 current = ToInspectableObject(Object.getPrototypeOf(current)); | 47 current = ToInspectableObject(Object.getPrototypeOf(current)); |
| 52 } | 48 } |
| 53 return result; | 49 return result; |
| 54 } | 50 } |
| 55 | 51 |
| 56 | |
| 57 // Global object holding debugger related constants and state. | |
| 58 var Debug = {}; | |
| 59 | |
| 60 | |
| 61 // Debug events which can occour in the V8 JavaScript engine. These originate | |
| 62 // from the API include file v8-debug.h. | |
| 63 Debug.DebugEvent = { Break: 1, | |
| 64 Exception: 2, | |
| 65 NewFunction: 3, | |
| 66 BeforeCompile: 4, | |
| 67 AfterCompile: 5 }; | |
| 68 | |
| 69 | |
| 70 // The different types of scripts matching enum ScriptType in objects.h. | |
| 71 Debug.ScriptType = { Native: 0, | |
| 72 Extension: 1, | |
| 73 Normal: 2 }; | |
| 74 | |
| 75 | |
| 76 // The different types of script compilations matching enum | |
| 77 // Script::CompilationType in objects.h. | |
| 78 Debug.ScriptCompilationType = { Host: 0, | |
| 79 Eval: 1, | |
| 80 JSON: 2 }; | |
| 81 | |
| 82 | |
| 83 // The different types of scopes matching constants runtime.cc. | |
| 84 Debug.ScopeType = { Global: 0, | |
| 85 Local: 1, | |
| 86 With: 2, | |
| 87 Closure: 3, | |
| 88 Catch: 4, | |
| 89 Block: 5 }; | |
| 90 | |
| 91 | |
| 92 // Current debug state. | |
| 93 var kNoFrame = -1; | |
| 94 Debug.State = { | |
| 95 currentFrame: kNoFrame, | |
| 96 displaySourceStartLine: -1, | |
| 97 displaySourceEndLine: -1, | |
| 98 currentSourceLine: -1 | |
| 99 }; | |
| 100 var trace_compile = false; // Tracing all compile events? | |
| 101 var trace_debug_json = false; // Tracing all debug json packets? | |
| 102 var last_cmd = ''; | |
| 103 var repeat_cmd_line = ''; | |
| 104 var is_running = true; | |
| 105 // Global variable used to store whether a handle was requested. | |
| 106 var lookup_handle = null; | |
| 107 | |
| 108 // Copied from debug-delay.js. This is needed below: | |
| 109 function ScriptTypeFlag(type) { | |
| 110 return (1 << type); | |
| 111 } | |
| 112 | |
| 113 | |
| 114 // Process a debugger JSON message into a display text and a running status. | |
| 115 // This function returns an object with properties "text" and "running" holding | |
| 116 // this information. | |
| 117 function DebugMessageDetails(message) { | |
| 118 if (trace_debug_json) { | |
| 119 print("received: '" + message + "'"); | |
| 120 } | |
| 121 // Convert the JSON string to an object. | |
| 122 var response = new ProtocolPackage(message); | |
| 123 is_running = response.running(); | |
| 124 | |
| 125 if (response.type() == 'event') { | |
| 126 return DebugEventDetails(response); | |
| 127 } else { | |
| 128 return DebugResponseDetails(response); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 function DebugEventDetails(response) { | |
| 133 var details = {text:'', running:false}; | |
| 134 | |
| 135 // Get the running state. | |
| 136 details.running = response.running(); | |
| 137 | |
| 138 var body = response.body(); | |
| 139 var result = ''; | |
| 140 switch (response.event()) { | |
| 141 case 'break': | |
| 142 if (body.breakpoints) { | |
| 143 result += 'breakpoint'; | |
| 144 if (body.breakpoints.length > 1) { | |
| 145 result += 's'; | |
| 146 } | |
| 147 result += ' #'; | |
| 148 for (var i = 0; i < body.breakpoints.length; i++) { | |
| 149 if (i > 0) { | |
| 150 result += ', #'; | |
| 151 } | |
| 152 result += body.breakpoints[i]; | |
| 153 } | |
| 154 } else { | |
| 155 result += 'break'; | |
| 156 } | |
| 157 result += ' in '; | |
| 158 result += body.invocationText; | |
| 159 result += ', '; | |
| 160 result += SourceInfo(body); | |
| 161 result += '\n'; | |
| 162 result += SourceUnderline(body.sourceLineText, body.sourceColumn); | |
| 163 Debug.State.currentSourceLine = body.sourceLine; | |
| 164 Debug.State.displaySourceStartLine = -1; | |
| 165 Debug.State.displaySourceEndLine = -1; | |
| 166 Debug.State.currentFrame = 0; | |
| 167 details.text = result; | |
| 168 break; | |
| 169 | |
| 170 case 'exception': | |
| 171 if (body.uncaught) { | |
| 172 result += 'Uncaught: '; | |
| 173 } else { | |
| 174 result += 'Exception: '; | |
| 175 } | |
| 176 result += '"'; | |
| 177 result += body.exception.text; | |
| 178 result += '"'; | |
| 179 if (body.sourceLine >= 0) { | |
| 180 result += ', '; | |
| 181 result += SourceInfo(body); | |
| 182 result += '\n'; | |
| 183 result += SourceUnderline(body.sourceLineText, body.sourceColumn); | |
| 184 Debug.State.currentSourceLine = body.sourceLine; | |
| 185 Debug.State.displaySourceStartLine = -1; | |
| 186 Debug.State.displaySourceEndLine = -1; | |
| 187 Debug.State.currentFrame = 0; | |
| 188 } else { | |
| 189 result += ' (empty stack)'; | |
| 190 Debug.State.currentSourceLine = -1; | |
| 191 Debug.State.displaySourceStartLine = -1; | |
| 192 Debug.State.displaySourceEndLine = -1; | |
| 193 Debug.State.currentFrame = kNoFrame; | |
| 194 } | |
| 195 details.text = result; | |
| 196 break; | |
| 197 | |
| 198 case 'afterCompile': | |
| 199 if (trace_compile) { | |
| 200 result = 'Source ' + body.script.name + ' compiled:\n'; | |
| 201 var source = body.script.source; | |
| 202 if (!(source[source.length - 1] == '\n')) { | |
| 203 result += source; | |
| 204 } else { | |
| 205 result += source.substring(0, source.length - 1); | |
| 206 } | |
| 207 } | |
| 208 details.text = result; | |
| 209 break; | |
| 210 | |
| 211 default: | |
| 212 details.text = 'Unknown debug event ' + response.event(); | |
| 213 } | |
| 214 | |
| 215 return details; | |
| 216 } | |
| 217 | |
| 218 | |
| 219 function SourceInfo(body) { | |
| 220 var result = ''; | |
| 221 | |
| 222 if (body.script) { | |
| 223 if (body.script.name) { | |
| 224 result += body.script.name; | |
| 225 } else { | |
| 226 result += '[unnamed]'; | |
| 227 } | |
| 228 } | |
| 229 result += ' line '; | |
| 230 result += body.sourceLine + 1; | |
| 231 result += ' column '; | |
| 232 result += body.sourceColumn + 1; | |
| 233 | |
| 234 return result; | |
| 235 } | |
| 236 | |
| 237 | |
| 238 function SourceUnderline(source_text, position) { | |
| 239 if (!source_text) { | |
| 240 return; | |
| 241 } | |
| 242 | |
| 243 // Create an underline with a caret pointing to the source position. If the | |
| 244 // source contains a tab character the underline will have a tab character in | |
| 245 // the same place otherwise the underline will have a space character. | |
| 246 var underline = ''; | |
| 247 for (var i = 0; i < position; i++) { | |
| 248 if (source_text[i] == '\t') { | |
| 249 underline += '\t'; | |
| 250 } else { | |
| 251 underline += ' '; | |
| 252 } | |
| 253 } | |
| 254 underline += '^'; | |
| 255 | |
| 256 // Return the source line text with the underline beneath. | |
| 257 return source_text + '\n' + underline; | |
| 258 } | |
| 259 | |
| 260 | |
| 261 // Converts a text command to a JSON request. | |
| 262 function DebugCommandToJSONRequest(cmd_line) { | |
| 263 var result = new DebugRequest(cmd_line).JSONRequest(); | |
| 264 if (trace_debug_json && result) { | |
| 265 print("sending: '" + result + "'"); | |
| 266 } | |
| 267 return result; | |
| 268 } | |
| 269 | |
| 270 | |
| 271 function DebugRequest(cmd_line) { | |
| 272 // If the very first character is a { assume that a JSON request have been | |
| 273 // entered as a command. Converting that to a JSON request is trivial. | |
| 274 if (cmd_line && cmd_line.length > 0 && cmd_line.charAt(0) == '{') { | |
| 275 this.request_ = cmd_line; | |
| 276 return; | |
| 277 } | |
| 278 | |
| 279 // Check for a simple carriage return to repeat the last command: | |
| 280 var is_repeating = false; | |
| 281 if (cmd_line == '\n') { | |
| 282 if (is_running) { | |
| 283 cmd_line = 'break'; // Not in debugger mode, break with a frame request. | |
| 284 } else { | |
| 285 cmd_line = repeat_cmd_line; // use command to repeat. | |
| 286 is_repeating = true; | |
| 287 } | |
| 288 } | |
| 289 if (!is_running) { // Only save the command if in debugger mode. | |
| 290 repeat_cmd_line = cmd_line; // save last command. | |
| 291 } | |
| 292 | |
| 293 // Trim string for leading and trailing whitespace. | |
| 294 cmd_line = cmd_line.replace(/^\s+|\s+$/g, ''); | |
| 295 | |
| 296 // Find the command. | |
| 297 var pos = cmd_line.indexOf(' '); | |
| 298 var cmd; | |
| 299 var args; | |
| 300 if (pos == -1) { | |
| 301 cmd = cmd_line; | |
| 302 args = ''; | |
| 303 } else { | |
| 304 cmd = cmd_line.slice(0, pos); | |
| 305 args = cmd_line.slice(pos).replace(/^\s+|\s+$/g, ''); | |
| 306 } | |
| 307 | |
| 308 if ((cmd === undefined) || !cmd) { | |
| 309 this.request_ = UNDEFINED; | |
| 310 return; | |
| 311 } | |
| 312 | |
| 313 last_cmd = cmd; | |
| 314 | |
| 315 // Switch on command. | |
| 316 switch (cmd) { | |
| 317 case 'continue': | |
| 318 case 'c': | |
| 319 this.request_ = this.continueCommandToJSONRequest_(args); | |
| 320 break; | |
| 321 | |
| 322 case 'step': | |
| 323 case 's': | |
| 324 this.request_ = this.stepCommandToJSONRequest_(args, 'in'); | |
| 325 break; | |
| 326 | |
| 327 case 'stepi': | |
| 328 case 'si': | |
| 329 this.request_ = this.stepCommandToJSONRequest_(args, 'min'); | |
| 330 break; | |
| 331 | |
| 332 case 'next': | |
| 333 case 'n': | |
| 334 this.request_ = this.stepCommandToJSONRequest_(args, 'next'); | |
| 335 break; | |
| 336 | |
| 337 case 'finish': | |
| 338 case 'fin': | |
| 339 this.request_ = this.stepCommandToJSONRequest_(args, 'out'); | |
| 340 break; | |
| 341 | |
| 342 case 'backtrace': | |
| 343 case 'bt': | |
| 344 this.request_ = this.backtraceCommandToJSONRequest_(args); | |
| 345 break; | |
| 346 | |
| 347 case 'frame': | |
| 348 case 'f': | |
| 349 this.request_ = this.frameCommandToJSONRequest_(args); | |
| 350 break; | |
| 351 | |
| 352 case 'scopes': | |
| 353 this.request_ = this.scopesCommandToJSONRequest_(args); | |
| 354 break; | |
| 355 | |
| 356 case 'scope': | |
| 357 this.request_ = this.scopeCommandToJSONRequest_(args); | |
| 358 break; | |
| 359 | |
| 360 case 'disconnect': | |
| 361 case 'exit': | |
| 362 case 'quit': | |
| 363 this.request_ = this.disconnectCommandToJSONRequest_(args); | |
| 364 break; | |
| 365 | |
| 366 case 'up': | |
| 367 this.request_ = | |
| 368 this.frameCommandToJSONRequest_('' + | |
| 369 (Debug.State.currentFrame + 1)); | |
| 370 break; | |
| 371 | |
| 372 case 'down': | |
| 373 case 'do': | |
| 374 this.request_ = | |
| 375 this.frameCommandToJSONRequest_('' + | |
| 376 (Debug.State.currentFrame - 1)); | |
| 377 break; | |
| 378 | |
| 379 case 'set': | |
| 380 case 'print': | |
| 381 case 'p': | |
| 382 this.request_ = this.printCommandToJSONRequest_(args); | |
| 383 break; | |
| 384 | |
| 385 case 'dir': | |
| 386 this.request_ = this.dirCommandToJSONRequest_(args); | |
| 387 break; | |
| 388 | |
| 389 case 'references': | |
| 390 this.request_ = this.referencesCommandToJSONRequest_(args); | |
| 391 break; | |
| 392 | |
| 393 case 'instances': | |
| 394 this.request_ = this.instancesCommandToJSONRequest_(args); | |
| 395 break; | |
| 396 | |
| 397 case 'list': | |
| 398 case 'l': | |
| 399 this.request_ = this.listCommandToJSONRequest_(args); | |
| 400 break; | |
| 401 case 'source': | |
| 402 this.request_ = this.sourceCommandToJSONRequest_(args); | |
| 403 break; | |
| 404 | |
| 405 case 'scripts': | |
| 406 case 'script': | |
| 407 case 'scr': | |
| 408 this.request_ = this.scriptsCommandToJSONRequest_(args); | |
| 409 break; | |
| 410 | |
| 411 case 'break': | |
| 412 case 'b': | |
| 413 this.request_ = this.breakCommandToJSONRequest_(args); | |
| 414 break; | |
| 415 | |
| 416 case 'breakpoints': | |
| 417 case 'bb': | |
| 418 this.request_ = this.breakpointsCommandToJSONRequest_(args); | |
| 419 break; | |
| 420 | |
| 421 case 'clear': | |
| 422 case 'delete': | |
| 423 case 'd': | |
| 424 this.request_ = this.clearCommandToJSONRequest_(args); | |
| 425 break; | |
| 426 | |
| 427 case 'threads': | |
| 428 this.request_ = this.threadsCommandToJSONRequest_(args); | |
| 429 break; | |
| 430 | |
| 431 case 'cond': | |
| 432 this.request_ = this.changeBreakpointCommandToJSONRequest_(args, 'cond'); | |
| 433 break; | |
| 434 | |
| 435 case 'enable': | |
| 436 case 'en': | |
| 437 this.request_ = | |
| 438 this.changeBreakpointCommandToJSONRequest_(args, 'enable'); | |
| 439 break; | |
| 440 | |
| 441 case 'disable': | |
| 442 case 'dis': | |
| 443 this.request_ = | |
| 444 this.changeBreakpointCommandToJSONRequest_(args, 'disable'); | |
| 445 break; | |
| 446 | |
| 447 case 'ignore': | |
| 448 this.request_ = | |
| 449 this.changeBreakpointCommandToJSONRequest_(args, 'ignore'); | |
| 450 break; | |
| 451 | |
| 452 case 'info': | |
| 453 case 'inf': | |
| 454 this.request_ = this.infoCommandToJSONRequest_(args); | |
| 455 break; | |
| 456 | |
| 457 case 'flags': | |
| 458 this.request_ = this.v8FlagsToJSONRequest_(args); | |
| 459 break; | |
| 460 | |
| 461 case 'gc': | |
| 462 this.request_ = this.gcToJSONRequest_(args); | |
| 463 break; | |
| 464 | |
| 465 case 'trace': | |
| 466 case 'tr': | |
| 467 // Return undefined to indicate command handled internally (no JSON). | |
| 468 this.request_ = UNDEFINED; | |
| 469 this.traceCommand_(args); | |
| 470 break; | |
| 471 | |
| 472 case 'help': | |
| 473 case '?': | |
| 474 this.helpCommand_(args); | |
| 475 // Return undefined to indicate command handled internally (no JSON). | |
| 476 this.request_ = UNDEFINED; | |
| 477 break; | |
| 478 | |
| 479 default: | |
| 480 throw new Error('Unknown command "' + cmd + '"'); | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 DebugRequest.prototype.JSONRequest = function() { | |
| 485 return this.request_; | |
| 486 }; | |
| 487 | |
| 488 | |
| 489 function RequestPacket(command) { | |
| 490 this.seq = 0; | |
| 491 this.type = 'request'; | |
| 492 this.command = command; | |
| 493 } | |
| 494 | |
| 495 | |
| 496 RequestPacket.prototype.toJSONProtocol = function() { | |
| 497 // Encode the protocol header. | |
| 498 var json = '{'; | |
| 499 json += '"seq":' + this.seq; | |
| 500 json += ',"type":"' + this.type + '"'; | |
| 501 if (this.command) { | |
| 502 json += ',"command":' + JSON.stringify(this.command); | |
| 503 } | |
| 504 if (this.arguments) { | |
| 505 json += ',"arguments":'; | |
| 506 // Encode the arguments part. | |
| 507 if (this.arguments.toJSONProtocol) { | |
| 508 json += this.arguments.toJSONProtocol(); | |
| 509 } else { | |
| 510 json += JSON.stringify(this.arguments); | |
| 511 } | |
| 512 } | |
| 513 json += '}'; | |
| 514 return json; | |
| 515 }; | |
| 516 | |
| 517 | |
| 518 DebugRequest.prototype.createRequest = function(command) { | |
| 519 return new RequestPacket(command); | |
| 520 }; | |
| 521 | |
| 522 | |
| 523 // Create a JSON request for the evaluation command. | |
| 524 DebugRequest.prototype.makeEvaluateJSONRequest_ = function(expression) { | |
| 525 lookup_handle = null; | |
| 526 | |
| 527 // Check if the expression is a handle id in the form #<handle>#. | |
| 528 var handle_match = expression.match(/^#([0-9]*)#$/); | |
| 529 if (handle_match) { | |
| 530 // Remember the handle requested in a global variable. | |
| 531 lookup_handle = parseInt(handle_match[1]); | |
| 532 // Build a lookup request. | |
| 533 var request = this.createRequest('lookup'); | |
| 534 request.arguments = {}; | |
| 535 request.arguments.handles = [ lookup_handle ]; | |
| 536 return request.toJSONProtocol(); | |
| 537 } else { | |
| 538 // Build an evaluate request. | |
| 539 var request = this.createRequest('evaluate'); | |
| 540 request.arguments = {}; | |
| 541 request.arguments.expression = expression; | |
| 542 // Request a global evaluation if there is no current frame. | |
| 543 if (Debug.State.currentFrame == kNoFrame) { | |
| 544 request.arguments.global = true; | |
| 545 } | |
| 546 return request.toJSONProtocol(); | |
| 547 } | |
| 548 }; | |
| 549 | |
| 550 | |
| 551 // Create a JSON request for the references/instances command. | |
| 552 DebugRequest.prototype.makeReferencesJSONRequest_ = function(handle, type) { | |
| 553 // Build a references request. | |
| 554 var handle_match = handle.match(/^#([0-9]*)#$/); | |
| 555 if (handle_match) { | |
| 556 var request = this.createRequest('references'); | |
| 557 request.arguments = {}; | |
| 558 request.arguments.type = type; | |
| 559 request.arguments.handle = parseInt(handle_match[1]); | |
| 560 return request.toJSONProtocol(); | |
| 561 } else { | |
| 562 throw new Error('Invalid object id.'); | |
| 563 } | |
| 564 }; | |
| 565 | |
| 566 | |
| 567 // Create a JSON request for the continue command. | |
| 568 DebugRequest.prototype.continueCommandToJSONRequest_ = function(args) { | |
| 569 var request = this.createRequest('continue'); | |
| 570 return request.toJSONProtocol(); | |
| 571 }; | |
| 572 | |
| 573 | |
| 574 // Create a JSON request for the step command. | |
| 575 DebugRequest.prototype.stepCommandToJSONRequest_ = function(args, type) { | |
| 576 // Requesting a step is through the continue command with additional | |
| 577 // arguments. | |
| 578 var request = this.createRequest('continue'); | |
| 579 request.arguments = {}; | |
| 580 | |
| 581 // Process arguments if any. | |
| 582 | |
| 583 // Only process args if the command is 'step' which is indicated by type being | |
| 584 // set to 'in'. For all other commands, ignore the args. | |
| 585 if (args && args.length > 0) { | |
| 586 args = args.split(/\s+/g); | |
| 587 | |
| 588 if (args.length > 2) { | |
| 589 throw new Error('Invalid step arguments.'); | |
| 590 } | |
| 591 | |
| 592 if (args.length > 0) { | |
| 593 // Check if we have a gdb stype step command. If so, the 1st arg would | |
| 594 // be the step count. If it's not a number, then assume that we're | |
| 595 // parsing for the legacy v8 step command. | |
| 596 var stepcount = Number(args[0]); | |
| 597 if (stepcount == Number.NaN) { | |
| 598 // No step count at arg 1. Process as legacy d8 step command: | |
| 599 if (args.length == 2) { | |
| 600 var stepcount = parseInt(args[1]); | |
| 601 if (isNaN(stepcount) || stepcount <= 0) { | |
| 602 throw new Error('Invalid step count argument "' + args[0] + '".'); | |
| 603 } | |
| 604 request.arguments.stepcount = stepcount; | |
| 605 } | |
| 606 | |
| 607 // Get the step action. | |
| 608 switch (args[0]) { | |
| 609 case 'in': | |
| 610 case 'i': | |
| 611 request.arguments.stepaction = 'in'; | |
| 612 break; | |
| 613 | |
| 614 case 'min': | |
| 615 case 'm': | |
| 616 request.arguments.stepaction = 'min'; | |
| 617 break; | |
| 618 | |
| 619 case 'next': | |
| 620 case 'n': | |
| 621 request.arguments.stepaction = 'next'; | |
| 622 break; | |
| 623 | |
| 624 case 'out': | |
| 625 case 'o': | |
| 626 request.arguments.stepaction = 'out'; | |
| 627 break; | |
| 628 | |
| 629 default: | |
| 630 throw new Error('Invalid step argument "' + args[0] + '".'); | |
| 631 } | |
| 632 | |
| 633 } else { | |
| 634 // gdb style step commands: | |
| 635 request.arguments.stepaction = type; | |
| 636 request.arguments.stepcount = stepcount; | |
| 637 } | |
| 638 } | |
| 639 } else { | |
| 640 // Default is step of the specified type. | |
| 641 request.arguments.stepaction = type; | |
| 642 } | |
| 643 | |
| 644 return request.toJSONProtocol(); | |
| 645 }; | |
| 646 | |
| 647 | |
| 648 // Create a JSON request for the backtrace command. | |
| 649 DebugRequest.prototype.backtraceCommandToJSONRequest_ = function(args) { | |
| 650 // Build a backtrace request from the text command. | |
| 651 var request = this.createRequest('backtrace'); | |
| 652 | |
| 653 // Default is to show top 10 frames. | |
| 654 request.arguments = {}; | |
| 655 request.arguments.fromFrame = 0; | |
| 656 request.arguments.toFrame = 10; | |
| 657 | |
| 658 args = args.split(/\s*[ ]+\s*/g); | |
| 659 if (args.length == 1 && args[0].length > 0) { | |
| 660 var frameCount = parseInt(args[0]); | |
| 661 if (frameCount > 0) { | |
| 662 // Show top frames. | |
| 663 request.arguments.fromFrame = 0; | |
| 664 request.arguments.toFrame = frameCount; | |
| 665 } else { | |
| 666 // Show bottom frames. | |
| 667 request.arguments.fromFrame = 0; | |
| 668 request.arguments.toFrame = -frameCount; | |
| 669 request.arguments.bottom = true; | |
| 670 } | |
| 671 } else if (args.length == 2) { | |
| 672 var fromFrame = parseInt(args[0]); | |
| 673 var toFrame = parseInt(args[1]); | |
| 674 if (isNaN(fromFrame) || fromFrame < 0) { | |
| 675 throw new Error('Invalid start frame argument "' + args[0] + '".'); | |
| 676 } | |
| 677 if (isNaN(toFrame) || toFrame < 0) { | |
| 678 throw new Error('Invalid end frame argument "' + args[1] + '".'); | |
| 679 } | |
| 680 if (fromFrame > toFrame) { | |
| 681 throw new Error('Invalid arguments start frame cannot be larger ' + | |
| 682 'than end frame.'); | |
| 683 } | |
| 684 // Show frame range. | |
| 685 request.arguments.fromFrame = fromFrame; | |
| 686 request.arguments.toFrame = toFrame + 1; | |
| 687 } else if (args.length > 2) { | |
| 688 throw new Error('Invalid backtrace arguments.'); | |
| 689 } | |
| 690 | |
| 691 return request.toJSONProtocol(); | |
| 692 }; | |
| 693 | |
| 694 | |
| 695 // Create a JSON request for the frame command. | |
| 696 DebugRequest.prototype.frameCommandToJSONRequest_ = function(args) { | |
| 697 // Build a frame request from the text command. | |
| 698 var request = this.createRequest('frame'); | |
| 699 args = args.split(/\s*[ ]+\s*/g); | |
| 700 if (args.length > 0 && args[0].length > 0) { | |
| 701 request.arguments = {}; | |
| 702 request.arguments.number = args[0]; | |
| 703 } | |
| 704 return request.toJSONProtocol(); | |
| 705 }; | |
| 706 | |
| 707 | |
| 708 // Create a JSON request for the scopes command. | |
| 709 DebugRequest.prototype.scopesCommandToJSONRequest_ = function(args) { | |
| 710 // Build a scopes request from the text command. | |
| 711 var request = this.createRequest('scopes'); | |
| 712 return request.toJSONProtocol(); | |
| 713 }; | |
| 714 | |
| 715 | |
| 716 // Create a JSON request for the scope command. | |
| 717 DebugRequest.prototype.scopeCommandToJSONRequest_ = function(args) { | |
| 718 // Build a scope request from the text command. | |
| 719 var request = this.createRequest('scope'); | |
| 720 args = args.split(/\s*[ ]+\s*/g); | |
| 721 if (args.length > 0 && args[0].length > 0) { | |
| 722 request.arguments = {}; | |
| 723 request.arguments.number = args[0]; | |
| 724 } | |
| 725 return request.toJSONProtocol(); | |
| 726 }; | |
| 727 | |
| 728 | |
| 729 // Create a JSON request for the print command. | |
| 730 DebugRequest.prototype.printCommandToJSONRequest_ = function(args) { | |
| 731 // Build an evaluate request from the text command. | |
| 732 if (args.length == 0) { | |
| 733 throw new Error('Missing expression.'); | |
| 734 } | |
| 735 return this.makeEvaluateJSONRequest_(args); | |
| 736 }; | |
| 737 | |
| 738 | |
| 739 // Create a JSON request for the dir command. | |
| 740 DebugRequest.prototype.dirCommandToJSONRequest_ = function(args) { | |
| 741 // Build an evaluate request from the text command. | |
| 742 if (args.length == 0) { | |
| 743 throw new Error('Missing expression.'); | |
| 744 } | |
| 745 return this.makeEvaluateJSONRequest_(args); | |
| 746 }; | |
| 747 | |
| 748 | |
| 749 // Create a JSON request for the references command. | |
| 750 DebugRequest.prototype.referencesCommandToJSONRequest_ = function(args) { | |
| 751 // Build an evaluate request from the text command. | |
| 752 if (args.length == 0) { | |
| 753 throw new Error('Missing object id.'); | |
| 754 } | |
| 755 | |
| 756 return this.makeReferencesJSONRequest_(args, 'referencedBy'); | |
| 757 }; | |
| 758 | |
| 759 | |
| 760 // Create a JSON request for the instances command. | |
| 761 DebugRequest.prototype.instancesCommandToJSONRequest_ = function(args) { | |
| 762 // Build an evaluate request from the text command. | |
| 763 if (args.length == 0) { | |
| 764 throw new Error('Missing object id.'); | |
| 765 } | |
| 766 | |
| 767 // Build a references request. | |
| 768 return this.makeReferencesJSONRequest_(args, 'constructedBy'); | |
| 769 }; | |
| 770 | |
| 771 | |
| 772 // Create a JSON request for the list command. | |
| 773 DebugRequest.prototype.listCommandToJSONRequest_ = function(args) { | |
| 774 | |
| 775 // Default is ten lines starting five lines before the current location. | |
| 776 if (Debug.State.displaySourceEndLine == -1) { | |
| 777 // If we list forwards, we will start listing after the last source end | |
| 778 // line. Set it to start from 5 lines before the current location. | |
| 779 Debug.State.displaySourceEndLine = Debug.State.currentSourceLine - 5; | |
| 780 // If we list backwards, we will start listing backwards from the last | |
| 781 // source start line. Set it to start from 1 lines before the current | |
| 782 // location. | |
| 783 Debug.State.displaySourceStartLine = Debug.State.currentSourceLine + 1; | |
| 784 } | |
| 785 | |
| 786 var from = Debug.State.displaySourceEndLine + 1; | |
| 787 var lines = 10; | |
| 788 | |
| 789 // Parse the arguments. | |
| 790 args = args.split(/\s*,\s*/g); | |
| 791 if (args == '') { | |
| 792 } else if ((args.length == 1) && (args[0] == '-')) { | |
| 793 from = Debug.State.displaySourceStartLine - lines; | |
| 794 } else if (args.length == 2) { | |
| 795 from = parseInt(args[0]); | |
| 796 lines = parseInt(args[1]) - from + 1; // inclusive of the ending line. | |
| 797 } else { | |
| 798 throw new Error('Invalid list arguments.'); | |
| 799 } | |
| 800 Debug.State.displaySourceStartLine = from; | |
| 801 Debug.State.displaySourceEndLine = from + lines - 1; | |
| 802 var sourceArgs = '' + from + ' ' + lines; | |
| 803 return this.sourceCommandToJSONRequest_(sourceArgs); | |
| 804 }; | |
| 805 | |
| 806 | |
| 807 // Create a JSON request for the source command. | |
| 808 DebugRequest.prototype.sourceCommandToJSONRequest_ = function(args) { | |
| 809 // Build a evaluate request from the text command. | |
| 810 var request = this.createRequest('source'); | |
| 811 | |
| 812 // Default is ten lines starting five lines before the current location. | |
| 813 var from = Debug.State.currentSourceLine - 5; | |
| 814 var lines = 10; | |
| 815 | |
| 816 // Parse the arguments. | |
| 817 args = args.split(/\s*[ ]+\s*/g); | |
| 818 if (args.length > 1 && args[0].length > 0 && args[1].length > 0) { | |
| 819 from = parseInt(args[0]) - 1; | |
| 820 lines = parseInt(args[1]); | |
| 821 } else if (args.length > 0 && args[0].length > 0) { | |
| 822 from = parseInt(args[0]) - 1; | |
| 823 } | |
| 824 | |
| 825 if (from < 0) from = 0; | |
| 826 if (lines < 0) lines = 10; | |
| 827 | |
| 828 // Request source arround current source location. | |
| 829 request.arguments = {}; | |
| 830 request.arguments.fromLine = from; | |
| 831 request.arguments.toLine = from + lines; | |
| 832 | |
| 833 return request.toJSONProtocol(); | |
| 834 }; | |
| 835 | |
| 836 | |
| 837 // Create a JSON request for the scripts command. | |
| 838 DebugRequest.prototype.scriptsCommandToJSONRequest_ = function(args) { | |
| 839 // Build a evaluate request from the text command. | |
| 840 var request = this.createRequest('scripts'); | |
| 841 | |
| 842 // Process arguments if any. | |
| 843 if (args && args.length > 0) { | |
| 844 args = args.split(/\s*[ ]+\s*/g); | |
| 845 | |
| 846 if (args.length > 1) { | |
| 847 throw new Error('Invalid scripts arguments.'); | |
| 848 } | |
| 849 | |
| 850 request.arguments = {}; | |
| 851 switch (args[0]) { | |
| 852 case 'natives': | |
| 853 request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Native); | |
| 854 break; | |
| 855 | |
| 856 case 'extensions': | |
| 857 request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Extension); | |
| 858 break; | |
| 859 | |
| 860 case 'all': | |
| 861 request.arguments.types = | |
| 862 ScriptTypeFlag(Debug.ScriptType.Normal) | | |
| 863 ScriptTypeFlag(Debug.ScriptType.Native) | | |
| 864 ScriptTypeFlag(Debug.ScriptType.Extension); | |
| 865 break; | |
| 866 | |
| 867 default: | |
| 868 // If the arg is not one of the know one aboves, then it must be a | |
| 869 // filter used for filtering the results: | |
| 870 request.arguments.filter = args[0]; | |
| 871 break; | |
| 872 } | |
| 873 } | |
| 874 | |
| 875 return request.toJSONProtocol(); | |
| 876 }; | |
| 877 | |
| 878 | |
| 879 // Create a JSON request for the break command. | |
| 880 DebugRequest.prototype.breakCommandToJSONRequest_ = function(args) { | |
| 881 // Build a evaluate request from the text command. | |
| 882 // Process arguments if any. | |
| 883 if (args && args.length > 0) { | |
| 884 var target = args; | |
| 885 var type = 'function'; | |
| 886 var line; | |
| 887 var column; | |
| 888 var condition; | |
| 889 var pos; | |
| 890 | |
| 891 var request = this.createRequest('setbreakpoint'); | |
| 892 | |
| 893 // Break the args into target spec and condition if appropriate. | |
| 894 | |
| 895 // Check for breakpoint condition. | |
| 896 pos = args.indexOf(' '); | |
| 897 if (pos > 0) { | |
| 898 target = args.substring(0, pos); | |
| 899 condition = args.substring(pos + 1, args.length); | |
| 900 } | |
| 901 | |
| 902 // Check for script breakpoint (name:line[:column]). If no ':' in break | |
| 903 // specification it is considered a function break point. | |
| 904 pos = target.indexOf(':'); | |
| 905 if (pos > 0) { | |
| 906 var tmp = target.substring(pos + 1, target.length); | |
| 907 target = target.substring(0, pos); | |
| 908 if (target[0] == '/' && target[target.length - 1] == '/') { | |
| 909 type = 'scriptRegExp'; | |
| 910 target = target.substring(1, target.length - 1); | |
| 911 } else { | |
| 912 type = 'script'; | |
| 913 } | |
| 914 | |
| 915 // Check for both line and column. | |
| 916 pos = tmp.indexOf(':'); | |
| 917 if (pos > 0) { | |
| 918 column = parseInt(tmp.substring(pos + 1, tmp.length)) - 1; | |
| 919 line = parseInt(tmp.substring(0, pos)) - 1; | |
| 920 } else { | |
| 921 line = parseInt(tmp) - 1; | |
| 922 } | |
| 923 } else if (target[0] == '#' && target[target.length - 1] == '#') { | |
| 924 type = 'handle'; | |
| 925 target = target.substring(1, target.length - 1); | |
| 926 } else { | |
| 927 type = 'function'; | |
| 928 } | |
| 929 | |
| 930 request.arguments = {}; | |
| 931 request.arguments.type = type; | |
| 932 request.arguments.target = target; | |
| 933 request.arguments.line = line; | |
| 934 request.arguments.column = column; | |
| 935 request.arguments.condition = condition; | |
| 936 } else { | |
| 937 var request = this.createRequest('suspend'); | |
| 938 } | |
| 939 | |
| 940 return request.toJSONProtocol(); | |
| 941 }; | |
| 942 | |
| 943 | |
| 944 DebugRequest.prototype.breakpointsCommandToJSONRequest_ = function(args) { | |
| 945 if (args && args.length > 0) { | |
| 946 throw new Error('Unexpected arguments.'); | |
| 947 } | |
| 948 var request = this.createRequest('listbreakpoints'); | |
| 949 return request.toJSONProtocol(); | |
| 950 }; | |
| 951 | |
| 952 | |
| 953 // Create a JSON request for the clear command. | |
| 954 DebugRequest.prototype.clearCommandToJSONRequest_ = function(args) { | |
| 955 // Build a evaluate request from the text command. | |
| 956 var request = this.createRequest('clearbreakpoint'); | |
| 957 | |
| 958 // Process arguments if any. | |
| 959 if (args && args.length > 0) { | |
| 960 request.arguments = {}; | |
| 961 request.arguments.breakpoint = parseInt(args); | |
| 962 } else { | |
| 963 throw new Error('Invalid break arguments.'); | |
| 964 } | |
| 965 | |
| 966 return request.toJSONProtocol(); | |
| 967 }; | |
| 968 | |
| 969 | |
| 970 // Create a JSON request for the change breakpoint command. | |
| 971 DebugRequest.prototype.changeBreakpointCommandToJSONRequest_ = | |
| 972 function(args, command) { | |
| 973 | |
| 974 var request; | |
| 975 | |
| 976 // Check for exception breaks first: | |
| 977 // en[able] exc[eptions] [all|unc[aught]] | |
| 978 // en[able] [all|unc[aught]] exc[eptions] | |
| 979 // dis[able] exc[eptions] [all|unc[aught]] | |
| 980 // dis[able] [all|unc[aught]] exc[eptions] | |
| 981 if ((command == 'enable' || command == 'disable') && | |
| 982 args && args.length > 1) { | |
| 983 var nextPos = args.indexOf(' '); | |
| 984 var arg1 = (nextPos > 0) ? args.substring(0, nextPos) : args; | |
| 985 var excType = null; | |
| 986 | |
| 987 // Check for: | |
| 988 // en[able] exc[eptions] [all|unc[aught]] | |
| 989 // dis[able] exc[eptions] [all|unc[aught]] | |
| 990 if (arg1 == 'exc' || arg1 == 'exception' || arg1 == 'exceptions') { | |
| 991 | |
| 992 var arg2 = (nextPos > 0) ? | |
| 993 args.substring(nextPos + 1, args.length) : 'all'; | |
| 994 if (!arg2) { | |
| 995 arg2 = 'all'; // if unspecified, set for all. | |
| 996 } else if (arg2 == 'unc') { // check for short cut. | |
| 997 arg2 = 'uncaught'; | |
| 998 } | |
| 999 excType = arg2; | |
| 1000 | |
| 1001 // Check for: | |
| 1002 // en[able] [all|unc[aught]] exc[eptions] | |
| 1003 // dis[able] [all|unc[aught]] exc[eptions] | |
| 1004 } else if (arg1 == 'all' || arg1 == 'unc' || arg1 == 'uncaught') { | |
| 1005 | |
| 1006 var arg2 = (nextPos > 0) ? | |
| 1007 args.substring(nextPos + 1, args.length) : null; | |
| 1008 if (arg2 == 'exc' || arg1 == 'exception' || arg1 == 'exceptions') { | |
| 1009 excType = arg1; | |
| 1010 if (excType == 'unc') { | |
| 1011 excType = 'uncaught'; | |
| 1012 } | |
| 1013 } | |
| 1014 } | |
| 1015 | |
| 1016 // If we matched one of the command formats, then excType will be non-null: | |
| 1017 if (excType) { | |
| 1018 // Build a evaluate request from the text command. | |
| 1019 request = this.createRequest('setexceptionbreak'); | |
| 1020 | |
| 1021 request.arguments = {}; | |
| 1022 request.arguments.type = excType; | |
| 1023 request.arguments.enabled = (command == 'enable'); | |
| 1024 | |
| 1025 return request.toJSONProtocol(); | |
| 1026 } | |
| 1027 } | |
| 1028 | |
| 1029 // Build a evaluate request from the text command. | |
| 1030 request = this.createRequest('changebreakpoint'); | |
| 1031 | |
| 1032 // Process arguments if any. | |
| 1033 if (args && args.length > 0) { | |
| 1034 request.arguments = {}; | |
| 1035 var pos = args.indexOf(' '); | |
| 1036 var breakpointArg = args; | |
| 1037 var otherArgs; | |
| 1038 if (pos > 0) { | |
| 1039 breakpointArg = args.substring(0, pos); | |
| 1040 otherArgs = args.substring(pos + 1, args.length); | |
| 1041 } | |
| 1042 | |
| 1043 request.arguments.breakpoint = parseInt(breakpointArg); | |
| 1044 | |
| 1045 switch(command) { | |
| 1046 case 'cond': | |
| 1047 request.arguments.condition = otherArgs ? otherArgs : null; | |
| 1048 break; | |
| 1049 case 'enable': | |
| 1050 request.arguments.enabled = true; | |
| 1051 break; | |
| 1052 case 'disable': | |
| 1053 request.arguments.enabled = false; | |
| 1054 break; | |
| 1055 case 'ignore': | |
| 1056 request.arguments.ignoreCount = parseInt(otherArgs); | |
| 1057 break; | |
| 1058 default: | |
| 1059 throw new Error('Invalid arguments.'); | |
| 1060 } | |
| 1061 } else { | |
| 1062 throw new Error('Invalid arguments.'); | |
| 1063 } | |
| 1064 | |
| 1065 return request.toJSONProtocol(); | |
| 1066 }; | |
| 1067 | |
| 1068 | |
| 1069 // Create a JSON request for the disconnect command. | |
| 1070 DebugRequest.prototype.disconnectCommandToJSONRequest_ = function(args) { | |
| 1071 var request; | |
| 1072 request = this.createRequest('disconnect'); | |
| 1073 return request.toJSONProtocol(); | |
| 1074 }; | |
| 1075 | |
| 1076 | |
| 1077 // Create a JSON request for the info command. | |
| 1078 DebugRequest.prototype.infoCommandToJSONRequest_ = function(args) { | |
| 1079 var request; | |
| 1080 if (args && (args == 'break' || args == 'br')) { | |
| 1081 // Build a evaluate request from the text command. | |
| 1082 request = this.createRequest('listbreakpoints'); | |
| 1083 last_cmd = 'info break'; | |
| 1084 } else if (args && (args == 'locals' || args == 'lo')) { | |
| 1085 // Build a evaluate request from the text command. | |
| 1086 request = this.createRequest('frame'); | |
| 1087 last_cmd = 'info locals'; | |
| 1088 } else if (args && (args == 'args' || args == 'ar')) { | |
| 1089 // Build a evaluate request from the text command. | |
| 1090 request = this.createRequest('frame'); | |
| 1091 last_cmd = 'info args'; | |
| 1092 } else { | |
| 1093 throw new Error('Invalid info arguments.'); | |
| 1094 } | |
| 1095 | |
| 1096 return request.toJSONProtocol(); | |
| 1097 }; | |
| 1098 | |
| 1099 | |
| 1100 DebugRequest.prototype.v8FlagsToJSONRequest_ = function(args) { | |
| 1101 var request; | |
| 1102 request = this.createRequest('v8flags'); | |
| 1103 request.arguments = {}; | |
| 1104 request.arguments.flags = args; | |
| 1105 return request.toJSONProtocol(); | |
| 1106 }; | |
| 1107 | |
| 1108 | |
| 1109 DebugRequest.prototype.gcToJSONRequest_ = function(args) { | |
| 1110 var request; | |
| 1111 if (!args) { | |
| 1112 args = 'all'; | |
| 1113 } | |
| 1114 var args = args.split(/\s+/g); | |
| 1115 var cmd = args[0]; | |
| 1116 | |
| 1117 switch(cmd) { | |
| 1118 case 'all': | |
| 1119 case 'quick': | |
| 1120 case 'full': | |
| 1121 case 'young': | |
| 1122 case 'old': | |
| 1123 case 'compact': | |
| 1124 case 'sweep': | |
| 1125 case 'scavenge': { | |
| 1126 if (cmd == 'young') { cmd = 'quick'; } | |
| 1127 else if (cmd == 'old') { cmd = 'full'; } | |
| 1128 | |
| 1129 request = this.createRequest('gc'); | |
| 1130 request.arguments = {}; | |
| 1131 request.arguments.type = cmd; | |
| 1132 break; | |
| 1133 } | |
| 1134 // Else fall thru to the default case below to report the error. | |
| 1135 default: | |
| 1136 throw new Error('Missing arguments after ' + cmd + '.'); | |
| 1137 } | |
| 1138 return request.toJSONProtocol(); | |
| 1139 }; | |
| 1140 | |
| 1141 | |
| 1142 // Create a JSON request for the threads command. | |
| 1143 DebugRequest.prototype.threadsCommandToJSONRequest_ = function(args) { | |
| 1144 // Build a threads request from the text command. | |
| 1145 var request = this.createRequest('threads'); | |
| 1146 return request.toJSONProtocol(); | |
| 1147 }; | |
| 1148 | |
| 1149 | |
| 1150 // Handle the trace command. | |
| 1151 DebugRequest.prototype.traceCommand_ = function(args) { | |
| 1152 // Process arguments. | |
| 1153 if (args && args.length > 0) { | |
| 1154 if (args == 'compile') { | |
| 1155 trace_compile = !trace_compile; | |
| 1156 print('Tracing of compiled scripts ' + (trace_compile ? 'on' : 'off')); | |
| 1157 } else if (args === 'debug json' || args === 'json' || args === 'packets') { | |
| 1158 trace_debug_json = !trace_debug_json; | |
| 1159 print('Tracing of debug json packets ' + | |
| 1160 (trace_debug_json ? 'on' : 'off')); | |
| 1161 } else { | |
| 1162 throw new Error('Invalid trace arguments.'); | |
| 1163 } | |
| 1164 } else { | |
| 1165 throw new Error('Invalid trace arguments.'); | |
| 1166 } | |
| 1167 }; | |
| 1168 | |
| 1169 // Handle the help command. | |
| 1170 DebugRequest.prototype.helpCommand_ = function(args) { | |
| 1171 // Help os quite simple. | |
| 1172 if (args && args.length > 0) { | |
| 1173 print('warning: arguments to \'help\' are ignored'); | |
| 1174 } | |
| 1175 | |
| 1176 print('Note: <> denotes symbollic values to be replaced with real values.'); | |
| 1177 print('Note: [] denotes optional parts of commands, or optional options / argu
ments.'); | |
| 1178 print(' e.g. d[elete] - you get the same command if you type d or delete.
'); | |
| 1179 print(''); | |
| 1180 print('[break] - break as soon as possible'); | |
| 1181 print('b[reak] location [condition]'); | |
| 1182 print(' - break on named function: location is a function name'); | |
| 1183 print(' - break on function: location is #<id>#'); | |
| 1184 print(' - break on script position: location is name:line[:column]'); | |
| 1185 print(''); | |
| 1186 print('clear <breakpoint #> - deletes the specified user defined breakpo
int'); | |
| 1187 print('d[elete] <breakpoint #> - deletes the specified user defined breakpo
int'); | |
| 1188 print('dis[able] <breakpoint #> - disables the specified user defined breakp
oint'); | |
| 1189 print('dis[able] exc[eptions] [[all] | unc[aught]]'); | |
| 1190 print(' - disables breaking on exceptions'); | |
| 1191 print('en[able] <breakpoint #> - enables the specified user defined breakpo
int'); | |
| 1192 print('en[able] exc[eptions] [[all] | unc[aught]]'); | |
| 1193 print(' - enables breaking on exceptions'); | |
| 1194 print(''); | |
| 1195 print('b[ack]t[race] [n] | [-n] | [from to]'); | |
| 1196 print(' - prints the stack back trace'); | |
| 1197 print('f[rame] - prints info about the current frame contex
t'); | |
| 1198 print('f[rame] <frame #> - set context to specified frame #'); | |
| 1199 print('scopes'); | |
| 1200 print('scope <scope #>'); | |
| 1201 print(''); | |
| 1202 print('up - set context to caller of current frame'); | |
| 1203 print('do[wn] - set context to callee of current frame'); | |
| 1204 print('inf[o] br[eak] - prints info about breakpoints in use'); | |
| 1205 print('inf[o] ar[gs] - prints info about arguments of the current
function'); | |
| 1206 print('inf[o] lo[cals] - prints info about locals in the current fu
nction'); | |
| 1207 print(''); | |
| 1208 print('step [in | next | out| min [step count]]'); | |
| 1209 print('c[ontinue] - continue executing after a breakpoint'); | |
| 1210 print('s[tep] [<N>] - step into the next N callees (default N is
1)'); | |
| 1211 print('s[tep]i [<N>] - step into the next N callees (default N is
1)'); | |
| 1212 print('n[ext] [<N>] - step over the next N callees (default N is
1)'); | |
| 1213 print('fin[ish] [<N>] - step out of N frames (default N is 1)'); | |
| 1214 print(''); | |
| 1215 print('p[rint] <expression> - prints the result of the specified express
ion'); | |
| 1216 print('dir <expression> - prints the object structure of the result'
); | |
| 1217 print('set <var> = <expression> - executes the specified statement'); | |
| 1218 print(''); | |
| 1219 print('l[ist] - list the source code around for the curren
t pc'); | |
| 1220 print('l[ist] [- | <start>,<end>] - list the specified range of source code'); | |
| 1221 print('source [from line [num lines]]'); | |
| 1222 print('scr[ipts] [native|extensions|all]'); | |
| 1223 print('scr[ipts] [<filter text>] - list scripts with the specified text in it
s description'); | |
| 1224 print(''); | |
| 1225 print('gc - runs the garbage collector'); | |
| 1226 print(''); | |
| 1227 print('trace compile'); | |
| 1228 // hidden command: trace debug json - toggles tracing of debug json packets | |
| 1229 print(''); | |
| 1230 print('disconnect|exit|quit - disconnects and quits the debugger'); | |
| 1231 print('help - prints this help information'); | |
| 1232 }; | |
| 1233 | |
| 1234 | |
| 1235 function formatHandleReference_(value) { | |
| 1236 if (value.handle() >= 0) { | |
| 1237 return '#' + value.handle() + '#'; | |
| 1238 } else { | |
| 1239 return '#Transient#'; | |
| 1240 } | |
| 1241 } | |
| 1242 | |
| 1243 | |
| 1244 function formatObject_(value, include_properties) { | |
| 1245 var result = ''; | |
| 1246 result += formatHandleReference_(value); | |
| 1247 result += ', type: object'; | |
| 1248 result += ', constructor '; | |
| 1249 var ctor = value.constructorFunctionValue(); | |
| 1250 result += formatHandleReference_(ctor); | |
| 1251 result += ', __proto__ '; | |
| 1252 var proto = value.protoObjectValue(); | |
| 1253 result += formatHandleReference_(proto); | |
| 1254 result += ', '; | |
| 1255 result += value.propertyCount(); | |
| 1256 result += ' properties.'; | |
| 1257 if (include_properties) { | |
| 1258 result += '\n'; | |
| 1259 for (var i = 0; i < value.propertyCount(); i++) { | |
| 1260 result += ' '; | |
| 1261 result += value.propertyName(i); | |
| 1262 result += ': '; | |
| 1263 var property_value = value.propertyValue(i); | |
| 1264 if (property_value instanceof ProtocolReference) { | |
| 1265 result += '<no type>'; | |
| 1266 } else { | |
| 1267 if (property_value && property_value.type()) { | |
| 1268 result += property_value.type(); | |
| 1269 } else { | |
| 1270 result += '<no type>'; | |
| 1271 } | |
| 1272 } | |
| 1273 result += ' '; | |
| 1274 result += formatHandleReference_(property_value); | |
| 1275 result += '\n'; | |
| 1276 } | |
| 1277 } | |
| 1278 return result; | |
| 1279 } | |
| 1280 | |
| 1281 | |
| 1282 function formatScope_(scope) { | |
| 1283 var result = ''; | |
| 1284 var index = scope.index; | |
| 1285 result += '#' + (index <= 9 ? '0' : '') + index; | |
| 1286 result += ' '; | |
| 1287 switch (scope.type) { | |
| 1288 case Debug.ScopeType.Global: | |
| 1289 result += 'Global, '; | |
| 1290 result += '#' + scope.object.ref + '#'; | |
| 1291 break; | |
| 1292 case Debug.ScopeType.Local: | |
| 1293 result += 'Local'; | |
| 1294 break; | |
| 1295 case Debug.ScopeType.With: | |
| 1296 result += 'With, '; | |
| 1297 result += '#' + scope.object.ref + '#'; | |
| 1298 break; | |
| 1299 case Debug.ScopeType.Catch: | |
| 1300 result += 'Catch, '; | |
| 1301 result += '#' + scope.object.ref + '#'; | |
| 1302 break; | |
| 1303 case Debug.ScopeType.Closure: | |
| 1304 result += 'Closure'; | |
| 1305 break; | |
| 1306 default: | |
| 1307 result += 'UNKNOWN'; | |
| 1308 } | |
| 1309 return result; | |
| 1310 } | |
| 1311 | |
| 1312 | |
| 1313 function refObjectToString_(protocolPackage, handle) { | |
| 1314 var value = protocolPackage.lookup(handle); | |
| 1315 var result = ''; | |
| 1316 if (value.isString()) { | |
| 1317 result = '"' + value.value() + '"'; | |
| 1318 } else if (value.isPrimitive()) { | |
| 1319 result = value.valueString(); | |
| 1320 } else if (value.isObject()) { | |
| 1321 result += formatObject_(value, true); | |
| 1322 } | |
| 1323 return result; | |
| 1324 } | |
| 1325 | |
| 1326 | |
| 1327 // Rounds number 'num' to 'length' decimal places. | |
| 1328 function roundNumber(num, length) { | |
| 1329 var factor = Math.pow(10, length); | |
| 1330 return Math.round(num * factor) / factor; | |
| 1331 } | |
| 1332 | |
| 1333 | |
| 1334 // Convert a JSON response to text for display in a text based debugger. | |
| 1335 function DebugResponseDetails(response) { | |
| 1336 var details = { text: '', running: false }; | |
| 1337 | |
| 1338 try { | |
| 1339 if (!response.success()) { | |
| 1340 details.text = response.message(); | |
| 1341 return details; | |
| 1342 } | |
| 1343 | |
| 1344 // Get the running state. | |
| 1345 details.running = response.running(); | |
| 1346 | |
| 1347 var body = response.body(); | |
| 1348 var result = ''; | |
| 1349 switch (response.command()) { | |
| 1350 case 'suspend': | |
| 1351 details.text = 'stopped'; | |
| 1352 break; | |
| 1353 | |
| 1354 case 'setbreakpoint': | |
| 1355 result = 'set breakpoint #'; | |
| 1356 result += body.breakpoint; | |
| 1357 details.text = result; | |
| 1358 break; | |
| 1359 | |
| 1360 case 'clearbreakpoint': | |
| 1361 result = 'cleared breakpoint #'; | |
| 1362 result += body.breakpoint; | |
| 1363 details.text = result; | |
| 1364 break; | |
| 1365 | |
| 1366 case 'changebreakpoint': | |
| 1367 result = 'successfully changed breakpoint'; | |
| 1368 details.text = result; | |
| 1369 break; | |
| 1370 | |
| 1371 case 'listbreakpoints': | |
| 1372 result = 'breakpoints: (' + body.breakpoints.length + ')'; | |
| 1373 for (var i = 0; i < body.breakpoints.length; i++) { | |
| 1374 var breakpoint = body.breakpoints[i]; | |
| 1375 result += '\n id=' + breakpoint.number; | |
| 1376 result += ' type=' + breakpoint.type; | |
| 1377 if (breakpoint.script_id) { | |
| 1378 result += ' script_id=' + breakpoint.script_id; | |
| 1379 } | |
| 1380 if (breakpoint.script_name) { | |
| 1381 result += ' script_name=' + breakpoint.script_name; | |
| 1382 } | |
| 1383 if (breakpoint.script_regexp) { | |
| 1384 result += ' script_regexp=' + breakpoint.script_regexp; | |
| 1385 } | |
| 1386 result += ' line=' + (breakpoint.line + 1); | |
| 1387 if (breakpoint.column != null) { | |
| 1388 result += ' column=' + (breakpoint.column + 1); | |
| 1389 } | |
| 1390 if (breakpoint.groupId) { | |
| 1391 result += ' groupId=' + breakpoint.groupId; | |
| 1392 } | |
| 1393 if (breakpoint.ignoreCount) { | |
| 1394 result += ' ignoreCount=' + breakpoint.ignoreCount; | |
| 1395 } | |
| 1396 if (breakpoint.active === false) { | |
| 1397 result += ' inactive'; | |
| 1398 } | |
| 1399 if (breakpoint.condition) { | |
| 1400 result += ' condition=' + breakpoint.condition; | |
| 1401 } | |
| 1402 result += ' hit_count=' + breakpoint.hit_count; | |
| 1403 } | |
| 1404 if (body.breakpoints.length === 0) { | |
| 1405 result = "No user defined breakpoints\n"; | |
| 1406 } else { | |
| 1407 result += '\n'; | |
| 1408 } | |
| 1409 if (body.breakOnExceptions) { | |
| 1410 result += '* breaking on ALL exceptions is enabled\n'; | |
| 1411 } else if (body.breakOnUncaughtExceptions) { | |
| 1412 result += '* breaking on UNCAUGHT exceptions is enabled\n'; | |
| 1413 } else { | |
| 1414 result += '* all exception breakpoints are disabled\n'; | |
| 1415 } | |
| 1416 details.text = result; | |
| 1417 break; | |
| 1418 | |
| 1419 case 'setexceptionbreak': | |
| 1420 result = 'Break on ' + body.type + ' exceptions: '; | |
| 1421 result += body.enabled ? 'enabled' : 'disabled'; | |
| 1422 details.text = result; | |
| 1423 break; | |
| 1424 | |
| 1425 case 'backtrace': | |
| 1426 if (body.totalFrames == 0) { | |
| 1427 result = '(empty stack)'; | |
| 1428 } else { | |
| 1429 var result = 'Frames #' + body.fromFrame + ' to #' + | |
| 1430 (body.toFrame - 1) + ' of ' + body.totalFrames + '\n'; | |
| 1431 for (i = 0; i < body.frames.length; i++) { | |
| 1432 if (i != 0) result += '\n'; | |
| 1433 result += body.frames[i].text; | |
| 1434 } | |
| 1435 } | |
| 1436 details.text = result; | |
| 1437 break; | |
| 1438 | |
| 1439 case 'frame': | |
| 1440 if (last_cmd === 'info locals') { | |
| 1441 var locals = body.locals; | |
| 1442 if (locals.length === 0) { | |
| 1443 result = 'No locals'; | |
| 1444 } else { | |
| 1445 for (var i = 0; i < locals.length; i++) { | |
| 1446 var local = locals[i]; | |
| 1447 result += local.name + ' = '; | |
| 1448 result += refObjectToString_(response, local.value.ref); | |
| 1449 result += '\n'; | |
| 1450 } | |
| 1451 } | |
| 1452 } else if (last_cmd === 'info args') { | |
| 1453 var args = body.arguments; | |
| 1454 if (args.length === 0) { | |
| 1455 result = 'No arguments'; | |
| 1456 } else { | |
| 1457 for (var i = 0; i < args.length; i++) { | |
| 1458 var arg = args[i]; | |
| 1459 result += arg.name + ' = '; | |
| 1460 result += refObjectToString_(response, arg.value.ref); | |
| 1461 result += '\n'; | |
| 1462 } | |
| 1463 } | |
| 1464 } else { | |
| 1465 result = SourceUnderline(body.sourceLineText, | |
| 1466 body.column); | |
| 1467 Debug.State.currentSourceLine = body.line; | |
| 1468 Debug.State.currentFrame = body.index; | |
| 1469 Debug.State.displaySourceStartLine = -1; | |
| 1470 Debug.State.displaySourceEndLine = -1; | |
| 1471 } | |
| 1472 details.text = result; | |
| 1473 break; | |
| 1474 | |
| 1475 case 'scopes': | |
| 1476 if (body.totalScopes == 0) { | |
| 1477 result = '(no scopes)'; | |
| 1478 } else { | |
| 1479 result = 'Scopes #' + body.fromScope + ' to #' + | |
| 1480 (body.toScope - 1) + ' of ' + body.totalScopes + '\n'; | |
| 1481 for (i = 0; i < body.scopes.length; i++) { | |
| 1482 if (i != 0) { | |
| 1483 result += '\n'; | |
| 1484 } | |
| 1485 result += formatScope_(body.scopes[i]); | |
| 1486 } | |
| 1487 } | |
| 1488 details.text = result; | |
| 1489 break; | |
| 1490 | |
| 1491 case 'scope': | |
| 1492 result += formatScope_(body); | |
| 1493 result += '\n'; | |
| 1494 var scope_object_value = response.lookup(body.object.ref); | |
| 1495 result += formatObject_(scope_object_value, true); | |
| 1496 details.text = result; | |
| 1497 break; | |
| 1498 | |
| 1499 case 'evaluate': | |
| 1500 case 'lookup': | |
| 1501 case 'getobj': | |
| 1502 if (last_cmd == 'p' || last_cmd == 'print') { | |
| 1503 result = body.text; | |
| 1504 } else { | |
| 1505 var value; | |
| 1506 if (lookup_handle) { | |
| 1507 value = response.bodyValue(lookup_handle); | |
| 1508 } else { | |
| 1509 value = response.bodyValue(); | |
| 1510 } | |
| 1511 if (value.isObject()) { | |
| 1512 result += formatObject_(value, true); | |
| 1513 } else { | |
| 1514 result += 'type: '; | |
| 1515 result += value.type(); | |
| 1516 if (!value.isUndefined() && !value.isNull()) { | |
| 1517 result += ', '; | |
| 1518 if (value.isString()) { | |
| 1519 result += '"'; | |
| 1520 } | |
| 1521 result += value.value(); | |
| 1522 if (value.isString()) { | |
| 1523 result += '"'; | |
| 1524 } | |
| 1525 } | |
| 1526 result += '\n'; | |
| 1527 } | |
| 1528 } | |
| 1529 details.text = result; | |
| 1530 break; | |
| 1531 | |
| 1532 case 'references': | |
| 1533 var count = body.length; | |
| 1534 result += 'found ' + count + ' objects'; | |
| 1535 result += '\n'; | |
| 1536 for (var i = 0; i < count; i++) { | |
| 1537 var value = response.bodyValue(i); | |
| 1538 result += formatObject_(value, false); | |
| 1539 result += '\n'; | |
| 1540 } | |
| 1541 details.text = result; | |
| 1542 break; | |
| 1543 | |
| 1544 case 'source': | |
| 1545 // Get the source from the response. | |
| 1546 var source = body.source; | |
| 1547 var from_line = body.fromLine + 1; | |
| 1548 var lines = source.split('\n'); | |
| 1549 var maxdigits = 1 + Math.floor(log10(from_line + lines.length)); | |
| 1550 if (maxdigits < 3) { | |
| 1551 maxdigits = 3; | |
| 1552 } | |
| 1553 var result = ''; | |
| 1554 for (var num = 0; num < lines.length; num++) { | |
| 1555 // Check if there's an extra newline at the end. | |
| 1556 if (num == (lines.length - 1) && lines[num].length == 0) { | |
| 1557 break; | |
| 1558 } | |
| 1559 | |
| 1560 var current_line = from_line + num; | |
| 1561 var spacer = maxdigits - (1 + Math.floor(log10(current_line))); | |
| 1562 if (current_line == Debug.State.currentSourceLine + 1) { | |
| 1563 for (var i = 0; i < maxdigits; i++) { | |
| 1564 result += '>'; | |
| 1565 } | |
| 1566 result += ' '; | |
| 1567 } else { | |
| 1568 for (var i = 0; i < spacer; i++) { | |
| 1569 result += ' '; | |
| 1570 } | |
| 1571 result += current_line + ': '; | |
| 1572 } | |
| 1573 result += lines[num]; | |
| 1574 result += '\n'; | |
| 1575 } | |
| 1576 details.text = result; | |
| 1577 break; | |
| 1578 | |
| 1579 case 'scripts': | |
| 1580 var result = ''; | |
| 1581 for (i = 0; i < body.length; i++) { | |
| 1582 if (i != 0) result += '\n'; | |
| 1583 if (body[i].id) { | |
| 1584 result += body[i].id; | |
| 1585 } else { | |
| 1586 result += '[no id]'; | |
| 1587 } | |
| 1588 result += ', '; | |
| 1589 if (body[i].name) { | |
| 1590 result += body[i].name; | |
| 1591 } else { | |
| 1592 if (body[i].compilationType == Debug.ScriptCompilationType.Eval | |
| 1593 && body[i].evalFromScript | |
| 1594 ) { | |
| 1595 result += 'eval from '; | |
| 1596 var script_value = response.lookup(body[i].evalFromScript.ref); | |
| 1597 result += ' ' + script_value.field('name'); | |
| 1598 result += ':' + (body[i].evalFromLocation.line + 1); | |
| 1599 result += ':' + body[i].evalFromLocation.column; | |
| 1600 } else if (body[i].compilationType == | |
| 1601 Debug.ScriptCompilationType.JSON) { | |
| 1602 result += 'JSON '; | |
| 1603 } else { // body[i].compilation == Debug.ScriptCompilationType.Host | |
| 1604 result += '[unnamed] '; | |
| 1605 } | |
| 1606 } | |
| 1607 result += ' (lines: '; | |
| 1608 result += body[i].lineCount; | |
| 1609 result += ', length: '; | |
| 1610 result += body[i].sourceLength; | |
| 1611 if (body[i].type == Debug.ScriptType.Native) { | |
| 1612 result += ', native'; | |
| 1613 } else if (body[i].type == Debug.ScriptType.Extension) { | |
| 1614 result += ', extension'; | |
| 1615 } | |
| 1616 result += '), ['; | |
| 1617 var sourceStart = body[i].sourceStart; | |
| 1618 if (sourceStart.length > 40) { | |
| 1619 sourceStart = sourceStart.substring(0, 37) + '...'; | |
| 1620 } | |
| 1621 result += sourceStart; | |
| 1622 result += ']'; | |
| 1623 } | |
| 1624 if (body.length == 0) { | |
| 1625 result = "no matching scripts found"; | |
| 1626 } | |
| 1627 details.text = result; | |
| 1628 break; | |
| 1629 | |
| 1630 case 'threads': | |
| 1631 var result = 'Active V8 threads: ' + body.totalThreads + '\n'; | |
| 1632 body.threads.sort(function(a, b) { return a.id - b.id; }); | |
| 1633 for (i = 0; i < body.threads.length; i++) { | |
| 1634 result += body.threads[i].current ? '*' : ' '; | |
| 1635 result += ' '; | |
| 1636 result += body.threads[i].id; | |
| 1637 result += '\n'; | |
| 1638 } | |
| 1639 details.text = result; | |
| 1640 break; | |
| 1641 | |
| 1642 case 'continue': | |
| 1643 details.text = "(running)"; | |
| 1644 break; | |
| 1645 | |
| 1646 case 'v8flags': | |
| 1647 details.text = "flags set"; | |
| 1648 break; | |
| 1649 | |
| 1650 case 'gc': | |
| 1651 details.text = "GC " + body.before + " => " + body.after; | |
| 1652 if (body.after > (1024*1024)) { | |
| 1653 details.text += | |
| 1654 " (" + roundNumber(body.before/(1024*1024), 1) + "M => " + | |
| 1655 roundNumber(body.after/(1024*1024), 1) + "M)"; | |
| 1656 } else if (body.after > 1024) { | |
| 1657 details.text += | |
| 1658 " (" + roundNumber(body.before/1024, 1) + "K => " + | |
| 1659 roundNumber(body.after/1024, 1) + "K)"; | |
| 1660 } | |
| 1661 break; | |
| 1662 | |
| 1663 default: | |
| 1664 details.text = | |
| 1665 'Response for unknown command \'' + response.command() + '\'' + | |
| 1666 ' (' + response.raw_json() + ')'; | |
| 1667 } | |
| 1668 } catch (e) { | |
| 1669 details.text = 'Error: "' + e + '" formatting response'; | |
| 1670 } | |
| 1671 | |
| 1672 return details; | |
| 1673 } | |
| 1674 | |
| 1675 | |
| 1676 /** | |
| 1677 * Protocol packages send from the debugger. | |
| 1678 * @param {string} json - raw protocol packet as JSON string. | |
| 1679 * @constructor | |
| 1680 */ | |
| 1681 function ProtocolPackage(json) { | |
| 1682 this.raw_json_ = json; | |
| 1683 this.packet_ = JSON.parse(json); | |
| 1684 this.refs_ = []; | |
| 1685 if (this.packet_.refs) { | |
| 1686 for (var i = 0; i < this.packet_.refs.length; i++) { | |
| 1687 this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i]; | |
| 1688 } | |
| 1689 } | |
| 1690 } | |
| 1691 | |
| 1692 | |
| 1693 /** | |
| 1694 * Get the packet type. | |
| 1695 * @return {String} the packet type | |
| 1696 */ | |
| 1697 ProtocolPackage.prototype.type = function() { | |
| 1698 return this.packet_.type; | |
| 1699 }; | |
| 1700 | |
| 1701 | |
| 1702 /** | |
| 1703 * Get the packet event. | |
| 1704 * @return {Object} the packet event | |
| 1705 */ | |
| 1706 ProtocolPackage.prototype.event = function() { | |
| 1707 return this.packet_.event; | |
| 1708 }; | |
| 1709 | |
| 1710 | |
| 1711 /** | |
| 1712 * Get the packet request sequence. | |
| 1713 * @return {number} the packet request sequence | |
| 1714 */ | |
| 1715 ProtocolPackage.prototype.requestSeq = function() { | |
| 1716 return this.packet_.request_seq; | |
| 1717 }; | |
| 1718 | |
| 1719 | |
| 1720 /** | |
| 1721 * Get the packet request sequence. | |
| 1722 * @return {number} the packet request sequence | |
| 1723 */ | |
| 1724 ProtocolPackage.prototype.running = function() { | |
| 1725 return this.packet_.running ? true : false; | |
| 1726 }; | |
| 1727 | |
| 1728 | |
| 1729 ProtocolPackage.prototype.success = function() { | |
| 1730 return this.packet_.success ? true : false; | |
| 1731 }; | |
| 1732 | |
| 1733 | |
| 1734 ProtocolPackage.prototype.message = function() { | |
| 1735 return this.packet_.message; | |
| 1736 }; | |
| 1737 | |
| 1738 | |
| 1739 ProtocolPackage.prototype.command = function() { | |
| 1740 return this.packet_.command; | |
| 1741 }; | |
| 1742 | |
| 1743 | |
| 1744 ProtocolPackage.prototype.body = function() { | |
| 1745 return this.packet_.body; | |
| 1746 }; | |
| 1747 | |
| 1748 | |
| 1749 ProtocolPackage.prototype.bodyValue = function(index) { | |
| 1750 if (index != null) { | |
| 1751 return new ProtocolValue(this.packet_.body[index], this); | |
| 1752 } else { | |
| 1753 return new ProtocolValue(this.packet_.body, this); | |
| 1754 } | |
| 1755 }; | |
| 1756 | |
| 1757 | |
| 1758 ProtocolPackage.prototype.body = function() { | |
| 1759 return this.packet_.body; | |
| 1760 }; | |
| 1761 | |
| 1762 | |
| 1763 ProtocolPackage.prototype.lookup = function(handle) { | |
| 1764 var value = this.refs_[handle]; | |
| 1765 if (value) { | |
| 1766 return new ProtocolValue(value, this); | |
| 1767 } else { | |
| 1768 return new ProtocolReference(handle); | |
| 1769 } | |
| 1770 }; | |
| 1771 | |
| 1772 | |
| 1773 ProtocolPackage.prototype.raw_json = function() { | |
| 1774 return this.raw_json_; | |
| 1775 }; | |
| 1776 | |
| 1777 | |
| 1778 function ProtocolValue(value, packet) { | |
| 1779 this.value_ = value; | |
| 1780 this.packet_ = packet; | |
| 1781 } | |
| 1782 | |
| 1783 | |
| 1784 /** | |
| 1785 * Get the value type. | |
| 1786 * @return {String} the value type | |
| 1787 */ | |
| 1788 ProtocolValue.prototype.type = function() { | |
| 1789 return this.value_.type; | |
| 1790 }; | |
| 1791 | |
| 1792 | |
| 1793 /** | |
| 1794 * Get a metadata field from a protocol value. | |
| 1795 * @return {Object} the metadata field value | |
| 1796 */ | |
| 1797 ProtocolValue.prototype.field = function(name) { | |
| 1798 return this.value_[name]; | |
| 1799 }; | |
| 1800 | |
| 1801 | |
| 1802 /** | |
| 1803 * Check is the value is a primitive value. | |
| 1804 * @return {boolean} true if the value is primitive | |
| 1805 */ | |
| 1806 ProtocolValue.prototype.isPrimitive = function() { | |
| 1807 return this.isUndefined() || this.isNull() || this.isBoolean() || | |
| 1808 this.isNumber() || this.isString(); | |
| 1809 }; | |
| 1810 | |
| 1811 | |
| 1812 /** | |
| 1813 * Get the object handle. | |
| 1814 * @return {number} the value handle | |
| 1815 */ | |
| 1816 ProtocolValue.prototype.handle = function() { | |
| 1817 return this.value_.handle; | |
| 1818 }; | |
| 1819 | |
| 1820 | |
| 1821 /** | |
| 1822 * Check is the value is undefined. | |
| 1823 * @return {boolean} true if the value is undefined | |
| 1824 */ | |
| 1825 ProtocolValue.prototype.isUndefined = function() { | |
| 1826 return this.value_.type == 'undefined'; | |
| 1827 }; | |
| 1828 | |
| 1829 | |
| 1830 /** | |
| 1831 * Check is the value is null. | |
| 1832 * @return {boolean} true if the value is null | |
| 1833 */ | |
| 1834 ProtocolValue.prototype.isNull = function() { | |
| 1835 return this.value_.type == 'null'; | |
| 1836 }; | |
| 1837 | |
| 1838 | |
| 1839 /** | |
| 1840 * Check is the value is a boolean. | |
| 1841 * @return {boolean} true if the value is a boolean | |
| 1842 */ | |
| 1843 ProtocolValue.prototype.isBoolean = function() { | |
| 1844 return this.value_.type == 'boolean'; | |
| 1845 }; | |
| 1846 | |
| 1847 | |
| 1848 /** | |
| 1849 * Check is the value is a number. | |
| 1850 * @return {boolean} true if the value is a number | |
| 1851 */ | |
| 1852 ProtocolValue.prototype.isNumber = function() { | |
| 1853 return this.value_.type == 'number'; | |
| 1854 }; | |
| 1855 | |
| 1856 | |
| 1857 /** | |
| 1858 * Check is the value is a string. | |
| 1859 * @return {boolean} true if the value is a string | |
| 1860 */ | |
| 1861 ProtocolValue.prototype.isString = function() { | |
| 1862 return this.value_.type == 'string'; | |
| 1863 }; | |
| 1864 | |
| 1865 | |
| 1866 /** | |
| 1867 * Check is the value is an object. | |
| 1868 * @return {boolean} true if the value is an object | |
| 1869 */ | |
| 1870 ProtocolValue.prototype.isObject = function() { | |
| 1871 return this.value_.type == 'object' || this.value_.type == 'function' || | |
| 1872 this.value_.type == 'error' || this.value_.type == 'regexp'; | |
| 1873 }; | |
| 1874 | |
| 1875 | |
| 1876 /** | |
| 1877 * Get the constructor function | |
| 1878 * @return {ProtocolValue} constructor function | |
| 1879 */ | |
| 1880 ProtocolValue.prototype.constructorFunctionValue = function() { | |
| 1881 var ctor = this.value_.constructorFunction; | |
| 1882 return this.packet_.lookup(ctor.ref); | |
| 1883 }; | |
| 1884 | |
| 1885 | |
| 1886 /** | |
| 1887 * Get the __proto__ value | |
| 1888 * @return {ProtocolValue} __proto__ value | |
| 1889 */ | |
| 1890 ProtocolValue.prototype.protoObjectValue = function() { | |
| 1891 var proto = this.value_.protoObject; | |
| 1892 return this.packet_.lookup(proto.ref); | |
| 1893 }; | |
| 1894 | |
| 1895 | |
| 1896 /** | |
| 1897 * Get the number og properties. | |
| 1898 * @return {number} the number of properties | |
| 1899 */ | |
| 1900 ProtocolValue.prototype.propertyCount = function() { | |
| 1901 return this.value_.properties ? this.value_.properties.length : 0; | |
| 1902 }; | |
| 1903 | |
| 1904 | |
| 1905 /** | |
| 1906 * Get the specified property name. | |
| 1907 * @return {string} property name | |
| 1908 */ | |
| 1909 ProtocolValue.prototype.propertyName = function(index) { | |
| 1910 var property = this.value_.properties[index]; | |
| 1911 return property.name; | |
| 1912 }; | |
| 1913 | |
| 1914 | |
| 1915 /** | |
| 1916 * Return index for the property name. | |
| 1917 * @param name The property name to look for | |
| 1918 * @return {number} index for the property name | |
| 1919 */ | |
| 1920 ProtocolValue.prototype.propertyIndex = function(name) { | |
| 1921 for (var i = 0; i < this.propertyCount(); i++) { | |
| 1922 if (this.value_.properties[i].name == name) { | |
| 1923 return i; | |
| 1924 } | |
| 1925 } | |
| 1926 return null; | |
| 1927 }; | |
| 1928 | |
| 1929 | |
| 1930 /** | |
| 1931 * Get the specified property value. | |
| 1932 * @return {ProtocolValue} property value | |
| 1933 */ | |
| 1934 ProtocolValue.prototype.propertyValue = function(index) { | |
| 1935 var property = this.value_.properties[index]; | |
| 1936 return this.packet_.lookup(property.ref); | |
| 1937 }; | |
| 1938 | |
| 1939 | |
| 1940 /** | |
| 1941 * Check is the value is a string. | |
| 1942 * @return {boolean} true if the value is a string | |
| 1943 */ | |
| 1944 ProtocolValue.prototype.value = function() { | |
| 1945 return this.value_.value; | |
| 1946 }; | |
| 1947 | |
| 1948 | |
| 1949 ProtocolValue.prototype.valueString = function() { | |
| 1950 return this.value_.text; | |
| 1951 }; | |
| 1952 | |
| 1953 | |
| 1954 function ProtocolReference(handle) { | |
| 1955 this.handle_ = handle; | |
| 1956 } | |
| 1957 | |
| 1958 | |
| 1959 ProtocolReference.prototype.handle = function() { | |
| 1960 return this.handle_; | |
| 1961 }; | |
| 1962 | |
| 1963 | |
| 1964 // A more universal stringify that supports more types than JSON. | 52 // A more universal stringify that supports more types than JSON. |
| 1965 // Used by the d8 shell to output results. | 53 // Used by the d8 shell to output results. |
| 1966 var stringifyDepthLimit = 4; // To avoid crashing on cyclic objects | 54 var stringifyDepthLimit = 4; // To avoid crashing on cyclic objects |
| 1967 | 55 |
| 1968 function Stringify(x, depth) { | 56 function Stringify(x, depth) { |
| 1969 if (depth === undefined) | 57 if (depth === undefined) |
| 1970 depth = stringifyDepthLimit; | 58 depth = stringifyDepthLimit; |
| 1971 else if (depth === 0) | 59 else if (depth === 0) |
| 1972 return "*"; | 60 return "*"; |
| 1973 switch (typeof x) { | 61 switch (typeof x) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 var getter = Stringify(desc.get); | 98 var getter = Stringify(desc.get); |
| 2011 props.push("get " + name + getter.slice(getter.indexOf('('))); | 99 props.push("get " + name + getter.slice(getter.indexOf('('))); |
| 2012 } | 100 } |
| 2013 if (desc.set) { | 101 if (desc.set) { |
| 2014 var setter = Stringify(desc.set); | 102 var setter = Stringify(desc.set); |
| 2015 props.push("set " + name + setter.slice(setter.indexOf('('))); | 103 props.push("set " + name + setter.slice(setter.indexOf('('))); |
| 2016 } | 104 } |
| 2017 } | 105 } |
| 2018 return "{" + props.join(", ") + "}"; | 106 return "{" + props.join(", ") + "}"; |
| 2019 default: | 107 default: |
| 2020 return "[crazy non-standard shit]"; | 108 return "[crazy non-standard value]"; |
| 2021 } | 109 } |
| 2022 } | 110 } |
| OLD | NEW |