Chromium Code Reviews| 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:convert"; | 8 import "dart:convert"; |
| 9 import "dart:io"; | 9 import "dart:io"; |
| 10 import "dart:async"; | 10 import "dart:async"; |
| 11 | 11 |
| 12 import "../lib/commando.dart"; | |
| 13 | |
| 12 | 14 |
| 13 Map<int, Completer> outstandingCommands; | 15 Map<int, Completer> outstandingCommands; |
| 14 | 16 |
| 15 Socket vmSock; | 17 Socket vmSock; |
| 16 String vmData; | 18 String vmData; |
| 17 var stdinSubscription; | 19 Commando cmdo; |
| 18 var vmSubscription; | 20 var vmSubscription; |
| 19 int seqNum = 0; | 21 int seqNum = 0; |
| 20 int isolate_id = -1; | 22 int isolate_id = -1; |
| 21 | 23 |
| 24 Process targetProcess; | |
| 25 | |
| 22 final verbose = false; | 26 final verbose = false; |
| 23 final printMessages = false; | 27 final printMessages = false; |
| 24 | 28 |
| 25 // The location of the last paused event. | 29 // The location of the last paused event. |
| 26 Map pausedLocation = null; | 30 Map pausedLocation = null; |
| 27 | 31 |
| 28 | 32 |
| 29 void printHelp() { | 33 void printHelp() { |
| 30 print(""" | 34 print(""" |
| 31 q Quit debugger shell | 35 q Quit debugger shell |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 53 li List ids of all isolates in the VM | 57 li List ids of all isolates in the VM |
| 54 i <id> Interrupt execution of given isolate id | 58 i <id> Interrupt execution of given isolate id |
| 55 h Print help | 59 h Print help |
| 56 """); | 60 """); |
| 57 } | 61 } |
| 58 | 62 |
| 59 | 63 |
| 60 void quitShell() { | 64 void quitShell() { |
| 61 vmSubscription.cancel(); | 65 vmSubscription.cancel(); |
| 62 vmSock.close(); | 66 vmSock.close(); |
| 63 stdinSubscription.cancel(); | 67 cmdo.done(); |
| 64 } | 68 } |
| 65 | 69 |
| 66 | 70 |
| 67 Future sendCmd(Map<String, dynamic> cmd) { | 71 Future sendCmd(Map<String, dynamic> cmd) { |
| 68 var completer = new Completer(); | 72 var completer = new Completer(); |
| 69 int id = cmd["id"]; | 73 int id = cmd["id"]; |
| 70 outstandingCommands[id] = completer; | 74 outstandingCommands[id] = completer; |
| 71 if (verbose) { | 75 if (verbose) { |
| 72 print("sending: '${JSON.encode(cmd)}'"); | 76 print("sending: '${JSON.encode(cmd)}'"); |
| 73 } | 77 } |
| 74 vmSock.write(JSON.encode(cmd)); | 78 vmSock.write(JSON.encode(cmd)); |
| 75 return completer.future; | 79 return completer.future; |
| 76 } | 80 } |
| 77 | 81 |
| 82 | |
| 83 typedef void HandlerType(response); | |
|
hausner
2013/11/21 22:30:02
Would help to have a type on the parameter. Is it
turnidge
2013/11/22 19:59:59
The actual handlers did not have types, so I was c
| |
| 84 | |
| 85 HandlerType hidePrompt(void handler(response)) { | |
| 86 // Hide the command prompt immediately. | |
| 87 cmdo.hide(); | |
| 88 return (response) { | |
| 89 handler(response); | |
| 90 cmdo.show(); | |
| 91 }; | |
| 92 } | |
| 93 | |
| 94 | |
| 78 void processCommand(String cmdLine) { | 95 void processCommand(String cmdLine) { |
| 79 | 96 |
| 80 void huh() { | 97 void huh() { |
| 81 print("'$cmdLine' not understood, try h for help"); | 98 print("'$cmdLine' not understood, try h for help"); |
| 82 } | 99 } |
| 83 | 100 |
| 84 seqNum++; | 101 seqNum++; |
| 102 cmdLine = cmdLine.trim(); | |
| 85 var args = cmdLine.split(' '); | 103 var args = cmdLine.split(' '); |
| 86 if (args.length == 0) { | 104 if (args.length == 0) { |
| 87 return; | 105 return; |
| 88 } | 106 } |
| 89 var command = args[0]; | 107 var command = args[0]; |
| 90 var simple_commands = | 108 var simple_commands = |
| 91 { 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'}; | 109 { 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'}; |
| 92 if (simple_commands[command] != null) { | 110 if (simple_commands[command] != null) { |
| 93 var cmd = { "id": seqNum, | 111 var cmd = { "id": seqNum, |
| 94 "command": simple_commands[command], | 112 "command": simple_commands[command], |
| 95 "params": { "isolateId" : isolate_id } }; | 113 "params": { "isolateId" : isolate_id } }; |
| 96 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 114 sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
|
hausner
2013/11/21 22:30:02
I find it confusing that the "hidePrompt" function
turnidge
2013/11/22 19:59:59
Yeah, I didn't think this was exactly perfect eith
| |
| 97 } else if (command == "bt") { | 115 } else if (command == "bt") { |
| 98 var cmd = { "id": seqNum, | 116 var cmd = { "id": seqNum, |
| 99 "command": "getStackTrace", | 117 "command": "getStackTrace", |
| 100 "params": { "isolateId" : isolate_id } }; | 118 "params": { "isolateId" : isolate_id } }; |
| 101 sendCmd(cmd).then((result) => handleStackTraceResponse(result)); | 119 sendCmd(cmd).then(hidePrompt(handleStackTraceResponse)); |
| 102 } else if (command == "ll") { | 120 } else if (command == "ll") { |
| 103 var cmd = { "id": seqNum, | 121 var cmd = { "id": seqNum, |
| 104 "command": "getLibraries", | 122 "command": "getLibraries", |
| 105 "params": { "isolateId" : isolate_id } }; | 123 "params": { "isolateId" : isolate_id } }; |
| 106 sendCmd(cmd).then((result) => handleGetLibraryResponse(result)); | 124 sendCmd(cmd).then(hidePrompt(handleGetLibraryResponse)); |
| 107 } else if (command == "sbp" && args.length >= 2) { | 125 } else if (command == "sbp" && args.length >= 2) { |
| 108 var url, line; | 126 var url, line; |
| 109 if (args.length == 2 && pausedLocation != null) { | 127 if (args.length == 2 && pausedLocation != null) { |
| 110 url = pausedLocation["url"]; | 128 url = pausedLocation["url"]; |
| 111 assert(url != null); | 129 assert(url != null); |
| 112 line = int.parse(args[1]); | 130 line = int.parse(args[1]); |
| 113 } else { | 131 } else { |
| 114 url = args[1]; | 132 url = args[1]; |
| 115 line = int.parse(args[2]); | 133 line = int.parse(args[2]); |
| 116 } | 134 } |
| 117 var cmd = { "id": seqNum, | 135 var cmd = { "id": seqNum, |
| 118 "command": "setBreakpoint", | 136 "command": "setBreakpoint", |
| 119 "params": { "isolateId" : isolate_id, | 137 "params": { "isolateId" : isolate_id, |
| 120 "url": url, | 138 "url": url, |
| 121 "line": line }}; | 139 "line": line }}; |
| 122 sendCmd(cmd).then((result) => handleSetBpResponse(result)); | 140 sendCmd(cmd).then(hidePrompt(handleSetBpResponse)); |
| 123 } else if (command == "rbp" && args.length == 2) { | 141 } else if (command == "rbp" && args.length == 2) { |
| 124 var cmd = { "id": seqNum, | 142 var cmd = { "id": seqNum, |
| 125 "command": "removeBreakpoint", | 143 "command": "removeBreakpoint", |
| 126 "params": { "isolateId" : isolate_id, | 144 "params": { "isolateId" : isolate_id, |
| 127 "breakpointId": int.parse(args[1]) } }; | 145 "breakpointId": int.parse(args[1]) } }; |
| 128 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 146 sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
| 129 } else if (command == "ls" && args.length == 2) { | 147 } else if (command == "ls" && args.length == 2) { |
| 130 var cmd = { "id": seqNum, | 148 var cmd = { "id": seqNum, |
| 131 "command": "getScriptURLs", | 149 "command": "getScriptURLs", |
| 132 "params": { "isolateId" : isolate_id, | 150 "params": { "isolateId" : isolate_id, |
| 133 "libraryId": int.parse(args[1]) } }; | 151 "libraryId": int.parse(args[1]) } }; |
| 134 sendCmd(cmd).then((result) => handleGetScriptsResponse(result)); | 152 sendCmd(cmd).then(hidePrompt(handleGetScriptsResponse)); |
| 135 } else if (command == "eval" && args.length > 3) { | 153 } else if (command == "eval" && args.length > 3) { |
| 136 var expr = args.getRange(3, args.length).join(" "); | 154 var expr = args.getRange(3, args.length).join(" "); |
| 137 var target = args[1]; | 155 var target = args[1]; |
| 138 if (target == "obj") { | 156 if (target == "obj") { |
| 139 target = "objectId"; | 157 target = "objectId"; |
| 140 } else if (target == "cls") { | 158 } else if (target == "cls") { |
| 141 target = "classId"; | 159 target = "classId"; |
| 142 } else if (target == "lib") { | 160 } else if (target == "lib") { |
| 143 target = "libraryId"; | 161 target = "libraryId"; |
| 144 } else { | 162 } else { |
| 145 huh(); | 163 huh(); |
| 146 return; | 164 return; |
| 147 } | 165 } |
| 148 var cmd = { "id": seqNum, | 166 var cmd = { "id": seqNum, |
| 149 "command": "evaluateExpr", | 167 "command": "evaluateExpr", |
| 150 "params": { "isolateId": isolate_id, | 168 "params": { "isolateId": isolate_id, |
| 151 target: int.parse(args[2]), | 169 target: int.parse(args[2]), |
| 152 "expression": expr } }; | 170 "expression": expr } }; |
| 153 sendCmd(cmd).then((result) => handleEvalResponse(result)); | 171 sendCmd(cmd).then(hidePrompt(handleEvalResponse)); |
| 154 } else if (command == "po" && args.length == 2) { | 172 } else if (command == "po" && args.length == 2) { |
| 155 var cmd = { "id": seqNum, | 173 var cmd = { "id": seqNum, |
| 156 "command": "getObjectProperties", | 174 "command": "getObjectProperties", |
| 157 "params": { "isolateId" : isolate_id, | 175 "params": { "isolateId" : isolate_id, |
| 158 "objectId": int.parse(args[1]) } }; | 176 "objectId": int.parse(args[1]) } }; |
| 159 sendCmd(cmd).then((result) => handleGetObjPropsResponse(result)); | 177 sendCmd(cmd).then(hidePrompt(handleGetObjPropsResponse)); |
| 160 } else if (command == "pl" && args.length >= 3) { | 178 } else if (command == "pl" && args.length >= 3) { |
| 161 var cmd; | 179 var cmd; |
| 162 if (args.length == 3) { | 180 if (args.length == 3) { |
| 163 cmd = { "id": seqNum, | 181 cmd = { "id": seqNum, |
| 164 "command": "getListElements", | 182 "command": "getListElements", |
| 165 "params": { "isolateId" : isolate_id, | 183 "params": { "isolateId" : isolate_id, |
| 166 "objectId": int.parse(args[1]), | 184 "objectId": int.parse(args[1]), |
| 167 "index": int.parse(args[2]) } }; | 185 "index": int.parse(args[2]) } }; |
| 168 } else { | 186 } else { |
| 169 cmd = { "id": seqNum, | 187 cmd = { "id": seqNum, |
| 170 "command": "getListElements", | 188 "command": "getListElements", |
| 171 "params": { "isolateId" : isolate_id, | 189 "params": { "isolateId" : isolate_id, |
| 172 "objectId": int.parse(args[1]), | 190 "objectId": int.parse(args[1]), |
| 173 "index": int.parse(args[2]), | 191 "index": int.parse(args[2]), |
| 174 "length": int.parse(args[3]) } }; | 192 "length": int.parse(args[3]) } }; |
| 175 } | 193 } |
| 176 sendCmd(cmd).then((result) => handleGetListResponse(result)); | 194 sendCmd(cmd).then(hidePrompt(handleGetListResponse)); |
| 177 } else if (command == "pc" && args.length == 2) { | 195 } else if (command == "pc" && args.length == 2) { |
| 178 var cmd = { "id": seqNum, | 196 var cmd = { "id": seqNum, |
| 179 "command": "getClassProperties", | 197 "command": "getClassProperties", |
| 180 "params": { "isolateId" : isolate_id, | 198 "params": { "isolateId" : isolate_id, |
| 181 "classId": int.parse(args[1]) } }; | 199 "classId": int.parse(args[1]) } }; |
| 182 sendCmd(cmd).then((result) => handleGetClassPropsResponse(result)); | 200 sendCmd(cmd).then(hidePrompt(handleGetClassPropsResponse)); |
| 183 } else if (command == "plib" && args.length == 2) { | 201 } else if (command == "plib" && args.length == 2) { |
| 184 var cmd = { "id": seqNum, | 202 var cmd = { "id": seqNum, |
| 185 "command": "getLibraryProperties", | 203 "command": "getLibraryProperties", |
| 186 "params": {"isolateId" : isolate_id, | 204 "params": {"isolateId" : isolate_id, |
| 187 "libraryId": int.parse(args[1]) } }; | 205 "libraryId": int.parse(args[1]) } }; |
| 188 sendCmd(cmd).then((result) => handleGetLibraryPropsResponse(result)); | 206 sendCmd(cmd).then(hidePrompt(handleGetLibraryPropsResponse)); |
| 189 } else if (command == "slib" && args.length == 3) { | 207 } else if (command == "slib" && args.length == 3) { |
| 190 var cmd = { "id": seqNum, | 208 var cmd = { "id": seqNum, |
| 191 "command": "setLibraryProperties", | 209 "command": "setLibraryProperties", |
| 192 "params": {"isolateId" : isolate_id, | 210 "params": {"isolateId" : isolate_id, |
| 193 "libraryId": int.parse(args[1]), | 211 "libraryId": int.parse(args[1]), |
| 194 "debuggingEnabled": args[2] } }; | 212 "debuggingEnabled": args[2] } }; |
| 195 sendCmd(cmd).then((result) => handleSetLibraryPropsResponse(result)); | 213 sendCmd(cmd).then(hidePrompt(handleSetLibraryPropsResponse)); |
| 196 } else if (command == "pg" && args.length == 2) { | 214 } else if (command == "pg" && args.length == 2) { |
| 197 var cmd = { "id": seqNum, | 215 var cmd = { "id": seqNum, |
| 198 "command": "getGlobalVariables", | 216 "command": "getGlobalVariables", |
| 199 "params": { "isolateId" : isolate_id, | 217 "params": { "isolateId" : isolate_id, |
| 200 "libraryId": int.parse(args[1]) } }; | 218 "libraryId": int.parse(args[1]) } }; |
| 201 sendCmd(cmd).then((result) => handleGetGlobalVarsResponse(result)); | 219 sendCmd(cmd).then(hidePrompt(handleGetGlobalVarsResponse)); |
| 202 } else if (command == "gs" && args.length == 3) { | 220 } else if (command == "gs" && args.length == 3) { |
| 203 var cmd = { "id": seqNum, | 221 var cmd = { "id": seqNum, |
| 204 "command": "getScriptSource", | 222 "command": "getScriptSource", |
| 205 "params": { "isolateId" : isolate_id, | 223 "params": { "isolateId" : isolate_id, |
| 206 "libraryId": int.parse(args[1]), | 224 "libraryId": int.parse(args[1]), |
| 207 "url": args[2] } }; | 225 "url": args[2] } }; |
| 208 sendCmd(cmd).then((result) => handleGetSourceResponse(result)); | 226 sendCmd(cmd).then(hidePrompt(handleGetSourceResponse)); |
| 209 } else if (command == "tok" && args.length == 3) { | 227 } else if (command == "tok" && args.length == 3) { |
| 210 var cmd = { "id": seqNum, | 228 var cmd = { "id": seqNum, |
| 211 "command": "getLineNumberTable", | 229 "command": "getLineNumberTable", |
| 212 "params": { "isolateId" : isolate_id, | 230 "params": { "isolateId" : isolate_id, |
| 213 "libraryId": int.parse(args[1]), | 231 "libraryId": int.parse(args[1]), |
| 214 "url": args[2] } }; | 232 "url": args[2] } }; |
| 215 sendCmd(cmd).then((result) => handleGetLineTableResponse(result)); | 233 sendCmd(cmd).then(hidePrompt(handleGetLineTableResponse)); |
| 216 } else if (command == "epi" && args.length == 2) { | 234 } else if (command == "epi" && args.length == 2) { |
| 217 var cmd = { "id": seqNum, | 235 var cmd = { "id": seqNum, |
| 218 "command": "setPauseOnException", | 236 "command": "setPauseOnException", |
| 219 "params": { "isolateId" : isolate_id, | 237 "params": { "isolateId" : isolate_id, |
| 220 "exceptions": args[1] } }; | 238 "exceptions": args[1] } }; |
| 221 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 239 sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
| 222 } else if (command == "li") { | 240 } else if (command == "li") { |
| 223 var cmd = { "id": seqNum, "command": "getIsolateIds" }; | 241 var cmd = { "id": seqNum, "command": "getIsolateIds" }; |
| 224 sendCmd(cmd).then((result) => handleGetIsolatesResponse(result)); | 242 sendCmd(cmd).then(hidePrompt(handleGetIsolatesResponse)); |
| 225 } else if (command == "i" && args.length == 2) { | 243 } else if (command == "i" && args.length == 2) { |
| 226 var cmd = { "id": seqNum, | 244 var cmd = { "id": seqNum, |
| 227 "command": "interrupt", | 245 "command": "interrupt", |
| 228 "params": { "isolateId": int.parse(args[1]) } }; | 246 "params": { "isolateId": int.parse(args[1]) } }; |
| 229 sendCmd(cmd).then((result) => handleGenericResponse(result)); | 247 sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
| 230 } else if (command == "q") { | 248 } else if (command == "q") { |
| 231 quitShell(); | 249 quitShell(); |
| 232 } else if (command == "h") { | 250 } else if (command == "h") { |
| 233 printHelp(); | 251 printHelp(); |
| 234 } else { | 252 } else { |
| 235 huh(); | 253 huh(); |
| 236 } | 254 } |
| 237 } | 255 } |
| 238 | 256 |
| 239 | 257 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 359 } | 377 } |
| 360 | 378 |
| 361 | 379 |
| 362 handleGetLineTableResponse(response) { | 380 handleGetLineTableResponse(response) { |
| 363 Map result = response["result"]; | 381 Map result = response["result"]; |
| 364 var info = result["lines"]; | 382 var info = result["lines"]; |
| 365 print("Line info table:\n$info"); | 383 print("Line info table:\n$info"); |
| 366 } | 384 } |
| 367 | 385 |
| 368 | 386 |
| 369 handleGetIsolatesResponse(response) { | 387 void handleGetIsolatesResponse(response) { |
|
hausner
2013/11/21 22:30:02
Remove the void annotation?
turnidge
2013/11/22 19:59:59
I wanted it to be a match for HandlerType, above.
| |
| 370 Map result = response["result"]; | 388 Map result = response["result"]; |
| 371 print("Isolates: ${result["isolateIds"]}"); | 389 print("Isolates: ${result["isolateIds"]}"); |
| 372 } | 390 } |
| 373 | 391 |
| 374 | 392 |
| 375 void handleGetLibraryResponse(response) { | 393 void handleGetLibraryResponse(response) { |
| 376 Map result = response["result"]; | 394 Map result = response["result"]; |
| 377 List libs = result["libraries"]; | 395 List libs = result["libraries"]; |
| 378 print("Loaded libraries:"); | 396 print("Loaded libraries:"); |
| 379 print(libs); | 397 print(libs); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 } | 481 } |
| 464 | 482 |
| 465 | 483 |
| 466 void processVmMessage(String jsonString) { | 484 void processVmMessage(String jsonString) { |
| 467 var msg = JSON.decode(jsonString); | 485 var msg = JSON.decode(jsonString); |
| 468 if (msg == null) { | 486 if (msg == null) { |
| 469 return; | 487 return; |
| 470 } | 488 } |
| 471 var event = msg["event"]; | 489 var event = msg["event"]; |
| 472 if (event == "paused") { | 490 if (event == "paused") { |
| 491 cmdo.hide(); | |
| 473 handlePausedEvent(msg); | 492 handlePausedEvent(msg); |
| 493 cmdo.show(); | |
| 474 return; | 494 return; |
| 475 } | 495 } |
| 476 if (event == "breakpointResolved") { | 496 if (event == "breakpointResolved") { |
| 477 Map params = msg["params"]; | 497 Map params = msg["params"]; |
| 478 assert(params != null); | 498 assert(params != null); |
| 499 cmdo.hide(); | |
| 479 print("BP ${params["breakpointId"]} resolved and " | 500 print("BP ${params["breakpointId"]} resolved and " |
| 480 "set at line ${params["line"]}."); | 501 "set at line ${params["line"]}."); |
| 502 cmdo.show(); | |
| 481 return; | 503 return; |
| 482 } | 504 } |
| 483 if (event == "isolate") { | 505 if (event == "isolate") { |
| 484 Map params = msg["params"]; | 506 Map params = msg["params"]; |
| 485 assert(params != null); | 507 assert(params != null); |
| 508 cmdo.hide(); | |
| 486 print("Isolate ${params["id"]} has been ${params["reason"]}."); | 509 print("Isolate ${params["id"]} has been ${params["reason"]}."); |
| 510 cmdo.show(); | |
| 487 return; | 511 return; |
| 488 } | 512 } |
| 489 if (msg["id"] != null) { | 513 if (msg["id"] != null) { |
| 490 var id = msg["id"]; | 514 var id = msg["id"]; |
| 491 if (outstandingCommands.containsKey(id)) { | 515 if (outstandingCommands.containsKey(id)) { |
| 516 var completer = outstandingCommands.remove(id); | |
| 492 if (msg["error"] != null) { | 517 if (msg["error"] != null) { |
| 493 print("VM says: ${msg["error"]}"); | 518 print("VM says: ${msg["error"]}"); |
| 519 // TODO(turnidge): Rework how hide/show happen. For now | |
| 520 cmdo.show(); | |
| 494 } else { | 521 } else { |
| 495 var completer = outstandingCommands[id]; | |
| 496 completer.complete(msg); | 522 completer.complete(msg); |
| 497 } | 523 } |
| 498 outstandingCommands.remove(id); | |
| 499 } | 524 } |
| 500 } | 525 } |
| 501 } | 526 } |
| 502 | 527 |
| 503 bool haveGarbageVmData() { | 528 bool haveGarbageVmData() { |
| 504 if (vmData == null || vmData.length == 0) return false; | 529 if (vmData == null || vmData.length == 0) return false; |
| 505 var i = 0, char = " "; | 530 var i = 0, char = " "; |
| 506 while (i < vmData.length) { | 531 while (i < vmData.length) { |
| 507 char = vmData[i]; | 532 char = vmData[i]; |
| 508 if (char != " " && char != "\n" && char != "\r" && char != "\t") break; | 533 if (char != " " && char != "\n" && char != "\r" && char != "\t") break; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 nesting--; | 618 nesting--; |
| 594 if (nesting == 0) return index; | 619 if (nesting == 0) return index; |
| 595 } else if (char == '"') { | 620 } else if (char == '"') { |
| 596 // Strings can contain braces. Skip their content. | 621 // Strings can contain braces. Skip their content. |
| 597 index = skipString(index); | 622 index = skipString(index); |
| 598 } | 623 } |
| 599 } | 624 } |
| 600 return 0; | 625 return 0; |
| 601 } | 626 } |
| 602 | 627 |
| 628 List<String> debuggerCommandCompleter(List<String> commandParts) { | |
| 629 List<String> completions = new List<String>(); | |
| 630 | |
| 631 // TODO(turnidge): Have a global command table and use it to for | |
| 632 // help messages, command completion, and command dispatching. For now | |
| 633 // we hardcode the list here. | |
| 634 // | |
| 635 // TODO(turnidge): Implement completion for arguments as well. | |
| 636 List<String> allCommands = ['q', 'bt', 'r', 's', 'so', 'si', 'sbp', 'rbp', | |
| 637 'po', 'eval', 'pl', 'pc', 'll', 'plib', 'slib', | |
| 638 'pg', 'ls', 'gs', 'tok', 'epi', 'li', 'i', 'h']; | |
| 639 | |
| 640 // Completion of first word in the command. | |
| 641 if (commandParts.length == 1) { | |
| 642 String prefix = commandParts.last; | |
| 643 for (String command in allCommands) { | |
| 644 if (command.startsWith(prefix)) { | |
| 645 completions.add(command); | |
| 646 } | |
| 647 } | |
| 648 } | |
| 649 | |
| 650 return completions; | |
| 651 } | |
| 603 | 652 |
| 604 void debuggerMain() { | 653 void debuggerMain() { |
| 605 outstandingCommands = new Map<int, Completer>(); | 654 outstandingCommands = new Map<int, Completer>(); |
| 606 Socket.connect("127.0.0.1", 5858).then((s) { | 655 Socket.connect("127.0.0.1", 5858).then((s) { |
| 607 vmSock = s; | 656 vmSock = s; |
| 608 vmSock.setOption(SocketOption.TCP_NODELAY, true); | 657 vmSock.setOption(SocketOption.TCP_NODELAY, true); |
| 609 var stringStream = vmSock.transform(UTF8.decoder); | 658 var stringStream = vmSock.transform(UTF8.decoder); |
| 610 vmSubscription = stringStream.listen( | 659 vmSubscription = stringStream.listen( |
| 611 (String data) { | 660 (String data) { |
| 612 processVmData(data); | 661 processVmData(data); |
| 613 }, | 662 }, |
| 614 onDone: () { | 663 onDone: () { |
| 615 print("VM debugger connection closed"); | 664 print("VM debugger connection closed"); |
| 616 quitShell(); | 665 quitShell(); |
| 617 }, | 666 }, |
| 618 onError: (err) { | 667 onError: (err) { |
| 619 print("Error in debug connection: $err"); | 668 print("Error in debug connection: $err"); |
| 620 // TODO(floitsch): do we want to print the stack trace? | 669 // TODO(floitsch): do we want to print the stack trace? |
| 621 quitShell(); | 670 quitShell(); |
| 622 }); | 671 }); |
| 623 stdinSubscription = stdin.transform(UTF8.decoder) | 672 cmdo = new Commando(stdin, stdout, processCommand, |
| 624 .transform(new LineSplitter()) | 673 completer:debuggerCommandCompleter); |
|
hausner
2013/11/21 22:30:02
Spaces around :
turnidge
2013/11/22 19:59:59
Done.
| |
| 625 .listen((String line) => processCommand(line)); | |
| 626 }); | 674 }); |
| 627 } | 675 } |
| 628 | 676 |
| 629 void main(List<String> arguments) { | 677 void main(List<String> args) { |
| 630 if (arguments.length > 0) { | 678 if (args.length > 0) { |
| 631 arguments = <String>['--debug', '--verbose_debug']..addAll(arguments); | 679 if (verbose) { |
| 632 Process.start(Platform.executable, arguments).then((Process process) { | 680 args = <String>['--debug', '--verbose_debug']..addAll(args); |
| 633 process.stdin.close(); | 681 } else { |
| 634 process.exitCode.then((int exitCode) { | 682 args = <String>['--debug']..addAll(args); |
| 635 print('${arguments.join(" ")} exited with $exitCode'); | 683 } |
| 636 }); | 684 Process.start(Platform.executable, args).then((Process process) { |
| 685 targetProcess = process; | |
| 686 process.stdin.close(); | |
| 687 | |
| 688 // TODO(turnidge): For now we only show full lines of output | |
| 689 // from the debugged process. Should show each character. | |
| 690 process.stdout | |
| 691 .transform(UTF8.decoder) | |
| 692 .transform(new LineSplitter()) | |
| 693 .listen((String line) { | |
| 694 // Hide/show command prompt across asynchronous output. | |
| 695 if (cmdo != null) { | |
| 696 cmdo.hide(); | |
| 697 } | |
| 698 print("$line"); | |
| 699 if (cmdo != null) { | |
| 700 cmdo.show(); | |
| 701 } | |
| 702 }); | |
| 703 | |
| 704 process.exitCode.then((int exitCode) { | |
| 705 if (exitCode == 0) { | |
| 706 print('Program exited normally.'); | |
| 707 } else { | |
| 708 print('Program exited with code $exitCode.'); | |
| 709 } | |
| 710 }); | |
| 711 | |
| 637 debuggerMain(); | 712 debuggerMain(); |
| 638 }); | 713 }); |
| 639 } else { | 714 } else { |
| 640 debuggerMain(); | 715 debuggerMain(); |
| 641 } | 716 } |
| 642 } | 717 } |
| OLD | NEW |