| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Simple interactive debugger shell that connects to the Dart VM's debugger | 5 // Simple interactive debugger shell that connects to the Dart VM's debugger |
| 6 // connection port. | 6 // connection port. |
| 7 | 7 |
| 8 #import("dart:io"); | 8 import "dart:io"; |
| 9 #import("dart:json"); | 9 import "dart:json"; |
| 10 #import("dart:math", prefix: "Math"); | 10 import "dart:utf"; |
| 11 #import("dart:utf"); | |
| 12 | 11 |
| 13 | 12 |
| 14 Map<int, Completer> outstandingCommands; | 13 Map<int, Completer> outstandingCommands; |
| 15 | 14 |
| 16 Socket vmSock; | 15 Socket vmSock; |
| 17 String vmData; | 16 String vmData; |
| 18 OutputStream vmStream; | 17 OutputStream vmStream; |
| 19 int seqNum = 0; | 18 int seqNum = 0; |
| 20 int isolate_id = -1; | 19 int isolate_id = -1; |
| 21 | 20 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 vmSock.close(); | 59 vmSock.close(); |
| 61 stdin.close(); | 60 stdin.close(); |
| 62 } | 61 } |
| 63 | 62 |
| 64 | 63 |
| 65 Future sendCmd(Map<String, dynamic> cmd) { | 64 Future sendCmd(Map<String, dynamic> cmd) { |
| 66 var completer = new Completer(); | 65 var completer = new Completer(); |
| 67 int id = cmd["id"]; | 66 int id = cmd["id"]; |
| 68 outstandingCommands[id] = completer; | 67 outstandingCommands[id] = completer; |
| 69 if (verbose) { | 68 if (verbose) { |
| 70 print("sending: '${JSON.stringify(cmd)}'"); | 69 print("sending: '${jsonStringify(cmd)}'"); |
| 71 } | 70 } |
| 72 vmStream.writeString(JSON.stringify(cmd)); | 71 vmStream.writeString(jsonStringify(cmd)); |
| 73 return completer.future; | 72 return completer.future; |
| 74 } | 73 } |
| 75 | 74 |
| 76 | 75 |
| 77 void processCommand(String cmdLine) { | 76 void processCommand(String cmdLine) { |
| 78 seqNum++; | 77 seqNum++; |
| 79 var args = cmdLine.split(' '); | 78 var args = cmdLine.split(' '); |
| 80 if (args.length == 0) { | 79 if (args.length == 0) { |
| 81 return; | 80 return; |
| 82 } | 81 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 96 sendCmd(cmd).then((result) => handleStackTraceResponse(result)); | 95 sendCmd(cmd).then((result) => handleStackTraceResponse(result)); |
| 97 } else if (command == "ll") { | 96 } else if (command == "ll") { |
| 98 var cmd = { "id": seqNum, | 97 var cmd = { "id": seqNum, |
| 99 "command": "getLibraries", | 98 "command": "getLibraries", |
| 100 "params": { "isolateId" : isolate_id } }; | 99 "params": { "isolateId" : isolate_id } }; |
| 101 sendCmd(cmd).then((result) => handleGetLibraryResponse(result)); | 100 sendCmd(cmd).then((result) => handleGetLibraryResponse(result)); |
| 102 } else if (command == "sbp" && args.length >= 2) { | 101 } else if (command == "sbp" && args.length >= 2) { |
| 103 var url, line; | 102 var url, line; |
| 104 if (args.length == 2) { | 103 if (args.length == 2) { |
| 105 url = stackTrace[0]["location"]["url"]; | 104 url = stackTrace[0]["location"]["url"]; |
| 106 line = Math.parseInt(args[1]); | 105 line = int.parse(args[1]); |
| 107 } else { | 106 } else { |
| 108 url = args[1]; | 107 url = args[1]; |
| 109 line = Math.parseInt(args[2]); | 108 line = int.parse(args[2]); |
| 110 } | 109 } |
| 111 var cmd = { "id": seqNum, | 110 var cmd = { "id": seqNum, |
| 112 "command": "setBreakpoint", | 111 "command": "setBreakpoint", |
| 113 "params": { "isolateId" : isolate_id, | 112 "params": { "isolateId" : isolate_id, |
| 114 "url": url, | 113 "url": url, |
| 115 "line": line }}; | 114 "line": line }}; |
| 116 sendCmd(cmd).then((result) => handleSetBpResponse(result)); | 115 sendCmd(cmd).then((result) => handleSetBpResponse(result)); |
| 117 } else if (command == "rbp" && args.length == 2) { | 116 } else if (command == "rbp" && args.length == 2) { |
| 118 var cmd = { "id": seqNum, | 117 var cmd = { "id": seqNum, |
| 119 "command": "removeBreakpoint", | 118 "command": "removeBreakpoint", |
| 120 "params": { "isolateId" : isolate_id, | 119 "params": { "isolateId" : isolate_id, |
| 121 "breakpointId": Math.parseInt(args[1]) } }; | 120 "breakpointId": int.parse(args[1]) } }; |
| 122 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 121 sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| 123 } else if (command == "ls" && args.length == 2) { | 122 } else if (command == "ls" && args.length == 2) { |
| 124 var cmd = { "id": seqNum, | 123 var cmd = { "id": seqNum, |
| 125 "command": "getScriptURLs", | 124 "command": "getScriptURLs", |
| 126 "params": { "isolateId" : isolate_id, | 125 "params": { "isolateId" : isolate_id, |
| 127 "libraryId": Math.parseInt(args[1]) } }; | 126 "libraryId": int.parse(args[1]) } }; |
| 128 sendCmd(cmd).then((result) => handleGetScriptsResponse(result)); | 127 sendCmd(cmd).then((result) => handleGetScriptsResponse(result)); |
| 129 } else if (command == "po" && args.length == 2) { | 128 } else if (command == "po" && args.length == 2) { |
| 130 var cmd = { "id": seqNum, | 129 var cmd = { "id": seqNum, |
| 131 "command": "getObjectProperties", | 130 "command": "getObjectProperties", |
| 132 "params": { "isolateId" : isolate_id, | 131 "params": { "isolateId" : isolate_id, |
| 133 "objectId": Math.parseInt(args[1]) } }; | 132 "objectId": int.parse(args[1]) } }; |
| 134 sendCmd(cmd).then((result) => handleGetObjPropsResponse(result)); | 133 sendCmd(cmd).then((result) => handleGetObjPropsResponse(result)); |
| 135 } else if (command == "pl" && args.length >= 3) { | 134 } else if (command == "pl" && args.length >= 3) { |
| 136 var cmd; | 135 var cmd; |
| 137 if (args.length == 3) { | 136 if (args.length == 3) { |
| 138 cmd = { "id": seqNum, | 137 cmd = { "id": seqNum, |
| 139 "command": "getListElements", | 138 "command": "getListElements", |
| 140 "params": { "isolateId" : isolate_id, | 139 "params": { "isolateId" : isolate_id, |
| 141 "objectId": Math.parseInt(args[1]), | 140 "objectId": int.parse(args[1]), |
| 142 "index": Math.parseInt(args[2]) } }; | 141 "index": int.parse(args[2]) } }; |
| 143 } else { | 142 } else { |
| 144 cmd = { "id": seqNum, | 143 cmd = { "id": seqNum, |
| 145 "command": "getListElements", | 144 "command": "getListElements", |
| 146 "params": { "isolateId" : isolate_id, | 145 "params": { "isolateId" : isolate_id, |
| 147 "objectId": Math.parseInt(args[1]), | 146 "objectId": int.parse(args[1]), |
| 148 "index": Math.parseInt(args[2]), | 147 "index": int.parse(args[2]), |
| 149 "length": Math.parseInt(args[3]) } }; | 148 "length": int.parse(args[3]) } }; |
| 150 } | 149 } |
| 151 sendCmd(cmd).then((result) => handleGetListResponse(result)); | 150 sendCmd(cmd).then((result) => handleGetListResponse(result)); |
| 152 } else if (command == "pc" && args.length == 2) { | 151 } else if (command == "pc" && args.length == 2) { |
| 153 var cmd = { "id": seqNum, | 152 var cmd = { "id": seqNum, |
| 154 "command": "getClassProperties", | 153 "command": "getClassProperties", |
| 155 "params": { "isolateId" : isolate_id, | 154 "params": { "isolateId" : isolate_id, |
| 156 "classId": Math.parseInt(args[1]) } }; | 155 "classId": int.parse(args[1]) } }; |
| 157 sendCmd(cmd).then((result) => handleGetClassPropsResponse(result)); | 156 sendCmd(cmd).then((result) => handleGetClassPropsResponse(result)); |
| 158 } else if (command == "plib" && args.length == 2) { | 157 } else if (command == "plib" && args.length == 2) { |
| 159 var cmd = { "id": seqNum, | 158 var cmd = { "id": seqNum, |
| 160 "command": "getLibraryProperties", | 159 "command": "getLibraryProperties", |
| 161 "params": {"isolateId" : isolate_id, | 160 "params": {"isolateId" : isolate_id, |
| 162 "libraryId": Math.parseInt(args[1]) } }; | 161 "libraryId": int.parse(args[1]) } }; |
| 163 sendCmd(cmd).then((result) => handleGetLibraryPropsResponse(result)); | 162 sendCmd(cmd).then((result) => handleGetLibraryPropsResponse(result)); |
| 164 } else if (command == "slib" && args.length == 3) { | 163 } else if (command == "slib" && args.length == 3) { |
| 165 var cmd = { "id": seqNum, | 164 var cmd = { "id": seqNum, |
| 166 "command": "setLibraryProperties", | 165 "command": "setLibraryProperties", |
| 167 "params": {"isolateId" : isolate_id, | 166 "params": {"isolateId" : isolate_id, |
| 168 "libraryId": Math.parseInt(args[1]), | 167 "libraryId": int.parse(args[1]), |
| 169 "debuggingEnabled": args[2] } }; | 168 "debuggingEnabled": args[2] } }; |
| 170 sendCmd(cmd).then((result) => handleSetLibraryPropsResponse(result)); | 169 sendCmd(cmd).then((result) => handleSetLibraryPropsResponse(result)); |
| 171 } else if (command == "pg" && args.length == 2) { | 170 } else if (command == "pg" && args.length == 2) { |
| 172 var cmd = { "id": seqNum, | 171 var cmd = { "id": seqNum, |
| 173 "command": "getGlobalVariables", | 172 "command": "getGlobalVariables", |
| 174 "params": { "isolateId" : isolate_id, | 173 "params": { "isolateId" : isolate_id, |
| 175 "libraryId": Math.parseInt(args[1]) } }; | 174 "libraryId": int.parse(args[1]) } }; |
| 176 sendCmd(cmd).then((result) => handleGetGlobalVarsResponse(result)); | 175 sendCmd(cmd).then((result) => handleGetGlobalVarsResponse(result)); |
| 177 } else if (command == "gs" && args.length == 3) { | 176 } else if (command == "gs" && args.length == 3) { |
| 178 var cmd = { "id": seqNum, | 177 var cmd = { "id": seqNum, |
| 179 "command": "getScriptSource", | 178 "command": "getScriptSource", |
| 180 "params": { "isolateId" : isolate_id, | 179 "params": { "isolateId" : isolate_id, |
| 181 "libraryId": Math.parseInt(args[1]), | 180 "libraryId": int.parse(args[1]), |
| 182 "url": args[2] } }; | 181 "url": args[2] } }; |
| 183 sendCmd(cmd).then((result) => handleGetSourceResponse(result)); | 182 sendCmd(cmd).then((result) => handleGetSourceResponse(result)); |
| 184 } else if (command == "epi" && args.length == 2) { | 183 } else if (command == "epi" && args.length == 2) { |
| 185 var cmd = { "id": seqNum, | 184 var cmd = { "id": seqNum, |
| 186 "command": "setPauseOnException", | 185 "command": "setPauseOnException", |
| 187 "params": { "isolateId" : isolate_id, | 186 "params": { "isolateId" : isolate_id, |
| 188 "exceptions": args[1] } }; | 187 "exceptions": args[1] } }; |
| 189 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 188 sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| 190 } else if (command == "i" && args.length == 2) { | 189 } else if (command == "i" && args.length == 2) { |
| 191 var cmd = { "id": seqNum, | 190 var cmd = { "id": seqNum, |
| 192 "command": "interrupt", | 191 "command": "interrupt", |
| 193 "params": { "isolateId": Math.parseInt(args[1]) } }; | 192 "params": { "isolateId": int.parse(args[1]) } }; |
| 194 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 193 sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| 195 } else if (command == "q") { | 194 } else if (command == "q") { |
| 196 quitShell(); | 195 quitShell(); |
| 197 } else if (command == "h") { | 196 } else if (command == "h") { |
| 198 printHelp(); | 197 printHelp(); |
| 199 } else { | 198 } else { |
| 200 print("command '$command' not understood, try h for help"); | 199 print("command '$command' not understood, try h for help"); |
| 201 } | 200 } |
| 202 } | 201 } |
| 203 | 202 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 var excObj = msg["params"]["exception"]; | 404 var excObj = msg["params"]["exception"]; |
| 406 print("Isolate $isolate_id paused on exception"); | 405 print("Isolate $isolate_id paused on exception"); |
| 407 print(remoteObject(excObj)); | 406 print(remoteObject(excObj)); |
| 408 } | 407 } |
| 409 print("Stack trace:"); | 408 print("Stack trace:"); |
| 410 printStackTrace(stackTrace); | 409 printStackTrace(stackTrace); |
| 411 } | 410 } |
| 412 | 411 |
| 413 | 412 |
| 414 void processVmMessage(String json) { | 413 void processVmMessage(String json) { |
| 415 var msg = JSON.parse(json); | 414 var msg = parseJson(json); |
| 416 if (msg == null) { | 415 if (msg == null) { |
| 417 return; | 416 return; |
| 418 } | 417 } |
| 419 var event = msg["event"]; | 418 var event = msg["event"]; |
| 420 if (event == "paused") { | 419 if (event == "paused") { |
| 421 handlePausedEvent(msg); | 420 handlePausedEvent(msg); |
| 422 return; | 421 return; |
| 423 } | 422 } |
| 424 if (event == "breakpointResolved") { | 423 if (event == "breakpointResolved") { |
| 425 Map params = msg["params"]; | 424 Map params = msg["params"]; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 vmData = vmData.substring(msg_len); | 475 vmData = vmData.substring(msg_len); |
| 477 msg_len = jsonObjectLength(vmData); | 476 msg_len = jsonObjectLength(vmData); |
| 478 } | 477 } |
| 479 if (printMessages) { print("leftover vm data '$vmData'"); } | 478 if (printMessages) { print("leftover vm data '$vmData'"); } |
| 480 } | 479 } |
| 481 | 480 |
| 482 /** | 481 /** |
| 483 * Skip past a JSON object value. | 482 * Skip past a JSON object value. |
| 484 * The object value must start with '{' and continues to the | 483 * The object value must start with '{' and continues to the |
| 485 * matching '}'. No attempt is made to otherwise validate the contents | 484 * matching '}'. No attempt is made to otherwise validate the contents |
| 486 * as JSON. If it is invalid, a later [JSON.parse] will fail. | 485 * as JSON. If it is invalid, a later [parseJson] will fail. |
| 487 */ | 486 */ |
| 488 int jsonObjectLength(String string) { | 487 int jsonObjectLength(String string) { |
| 489 int skipWhitespace(int index) { | 488 int skipWhitespace(int index) { |
| 490 while (index < string.length) { | 489 while (index < string.length) { |
| 491 String char = string[index]; | 490 String char = string[index]; |
| 492 if (char != " " && char != "\n" && char != "\r" && char != "\t") break; | 491 if (char != " " && char != "\n" && char != "\r" && char != "\t") break; |
| 493 index++; | 492 index++; |
| 494 } | 493 } |
| 495 return index; | 494 return index; |
| 496 } | 495 } |
| 497 int skipString(int index) { | 496 int skipString(int index) { |
| 498 assert(string[index - 1] == '"'); | 497 assert(string[index - 1] == '"'); |
| 499 while (index < string.length) { | 498 while (index < string.length) { |
| 500 String char = string[index]; | 499 String char = string[index]; |
| 501 if (char == '"') return index + 1; | 500 if (char == '"') return index + 1; |
| 502 if (char == r'\') index++; | 501 if (char == r'\') index++; |
| 503 if (index == string.length) return index; | 502 if (index == string.length) return index; |
| 504 index++; | 503 index++; |
| 505 } | 504 } |
| 506 return index; | 505 return index; |
| 507 } | 506 } |
| 508 int index = 0; | 507 int index = 0; |
| 509 index = skipWhitespace(index); | 508 index = skipWhitespace(index); |
| 510 // Bail out if the first non-whitespace character isn't '{'. | 509 // Bail out if the first non-whitespace character isn't '{'. |
| 511 if (index == string.length || string[index] != '{') return 0; | 510 if (index == string.length || string[index] != '{') return 0; |
| 512 int nexting = 0; | 511 int nesting = 0; |
| 513 while (index < string.length) { | 512 while (index < string.length) { |
| 514 String char = string[index++]; | 513 String char = string[index++]; |
| 515 if (char == '{') { | 514 if (char == '{') { |
| 516 nexting++; | 515 nesting++; |
| 517 } else if (char == '}') { | 516 } else if (char == '}') { |
| 518 nexting--; | 517 nesting--; |
| 519 if (nexting == 0) return index; | 518 if (nesting == 0) return index; |
| 520 } else if (char == '"') { | 519 } else if (char == '"') { |
| 521 // Strings can contain braces. Skip their content. | 520 // Strings can contain braces. Skip their content. |
| 522 index = skipString(index); | 521 index = skipString(index); |
| 523 } | 522 } |
| 524 } | 523 } |
| 525 return 0; | 524 return 0; |
| 526 } | 525 } |
| 527 | 526 |
| 528 | 527 |
| 529 void debuggerMain() { | 528 void debuggerMain() { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 // are coming from the debugger, and which errors are coming | 563 // are coming from the debugger, and which errors are coming |
| 565 // from the process being debugged. | 564 // from the process being debugged. |
| 566 process.stderr.pipe(stdout); | 565 process.stderr.pipe(stdout); |
| 567 process.stdout.pipe(stdout); | 566 process.stdout.pipe(stdout); |
| 568 debuggerMain(); | 567 debuggerMain(); |
| 569 }); | 568 }); |
| 570 } else { | 569 } else { |
| 571 debuggerMain(); | 570 debuggerMain(); |
| 572 } | 571 } |
| 573 } | 572 } |
| OLD | NEW |