Chromium Code Reviews| Index: tools/ddbg/bin/ddbg.dart |
| =================================================================== |
| --- tools/ddbg/bin/ddbg.dart (revision 0) |
| +++ tools/ddbg/bin/ddbg.dart (working copy) |
| @@ -9,16 +9,20 @@ |
| import "dart:io"; |
| import "dart:async"; |
| +import "../lib/commando.dart"; |
| + |
| Map<int, Completer> outstandingCommands; |
| Socket vmSock; |
| String vmData; |
| -var stdinSubscription; |
| +Commando cmdo; |
| var vmSubscription; |
| int seqNum = 0; |
| int isolate_id = -1; |
| +Process targetProcess; |
| + |
| final verbose = false; |
| final printMessages = false; |
| @@ -60,7 +64,7 @@ |
| void quitShell() { |
| vmSubscription.cancel(); |
| vmSock.close(); |
| - stdinSubscription.cancel(); |
| + cmdo.done(); |
| } |
| @@ -75,6 +79,19 @@ |
| return completer.future; |
| } |
| + |
| +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
|
| + |
| +HandlerType hidePrompt(void handler(response)) { |
| + // Hide the command prompt immediately. |
| + cmdo.hide(); |
| + return (response) { |
| + handler(response); |
| + cmdo.show(); |
| + }; |
| +} |
| + |
| + |
| void processCommand(String cmdLine) { |
| void huh() { |
| @@ -82,6 +99,7 @@ |
| } |
| seqNum++; |
| + cmdLine = cmdLine.trim(); |
| var args = cmdLine.split(' '); |
| if (args.length == 0) { |
| return; |
| @@ -93,17 +111,17 @@ |
| var cmd = { "id": seqNum, |
| "command": simple_commands[command], |
| "params": { "isolateId" : isolate_id } }; |
| - sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| + 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
|
| } else if (command == "bt") { |
| var cmd = { "id": seqNum, |
| "command": "getStackTrace", |
| "params": { "isolateId" : isolate_id } }; |
| - sendCmd(cmd).then((result) => handleStackTraceResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleStackTraceResponse)); |
| } else if (command == "ll") { |
| var cmd = { "id": seqNum, |
| "command": "getLibraries", |
| "params": { "isolateId" : isolate_id } }; |
| - sendCmd(cmd).then((result) => handleGetLibraryResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetLibraryResponse)); |
| } else if (command == "sbp" && args.length >= 2) { |
| var url, line; |
| if (args.length == 2 && pausedLocation != null) { |
| @@ -119,19 +137,19 @@ |
| "params": { "isolateId" : isolate_id, |
| "url": url, |
| "line": line }}; |
| - sendCmd(cmd).then((result) => handleSetBpResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleSetBpResponse)); |
| } else if (command == "rbp" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "removeBreakpoint", |
| "params": { "isolateId" : isolate_id, |
| "breakpointId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
| } else if (command == "ls" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "getScriptURLs", |
| "params": { "isolateId" : isolate_id, |
| "libraryId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGetScriptsResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetScriptsResponse)); |
| } else if (command == "eval" && args.length > 3) { |
| var expr = args.getRange(3, args.length).join(" "); |
| var target = args[1]; |
| @@ -150,83 +168,83 @@ |
| "params": { "isolateId": isolate_id, |
| target: int.parse(args[2]), |
| "expression": expr } }; |
| - sendCmd(cmd).then((result) => handleEvalResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleEvalResponse)); |
| } else if (command == "po" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "getObjectProperties", |
| "params": { "isolateId" : isolate_id, |
| "objectId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGetObjPropsResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetObjPropsResponse)); |
| } else if (command == "pl" && args.length >= 3) { |
| - var cmd; |
| - if (args.length == 3) { |
| - cmd = { "id": seqNum, |
| - "command": "getListElements", |
| - "params": { "isolateId" : isolate_id, |
| - "objectId": int.parse(args[1]), |
| - "index": int.parse(args[2]) } }; |
| + var cmd; |
| + if (args.length == 3) { |
| + cmd = { "id": seqNum, |
| + "command": "getListElements", |
| + "params": { "isolateId" : isolate_id, |
| + "objectId": int.parse(args[1]), |
| + "index": int.parse(args[2]) } }; |
| } else { |
| - cmd = { "id": seqNum, |
| - "command": "getListElements", |
| - "params": { "isolateId" : isolate_id, |
| - "objectId": int.parse(args[1]), |
| - "index": int.parse(args[2]), |
| - "length": int.parse(args[3]) } }; |
| + cmd = { "id": seqNum, |
| + "command": "getListElements", |
| + "params": { "isolateId" : isolate_id, |
| + "objectId": int.parse(args[1]), |
| + "index": int.parse(args[2]), |
| + "length": int.parse(args[3]) } }; |
| } |
| - sendCmd(cmd).then((result) => handleGetListResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetListResponse)); |
| } else if (command == "pc" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "getClassProperties", |
| "params": { "isolateId" : isolate_id, |
| "classId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGetClassPropsResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetClassPropsResponse)); |
| } else if (command == "plib" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "getLibraryProperties", |
| "params": {"isolateId" : isolate_id, |
| "libraryId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGetLibraryPropsResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetLibraryPropsResponse)); |
| } else if (command == "slib" && args.length == 3) { |
| var cmd = { "id": seqNum, |
| "command": "setLibraryProperties", |
| "params": {"isolateId" : isolate_id, |
| "libraryId": int.parse(args[1]), |
| "debuggingEnabled": args[2] } }; |
| - sendCmd(cmd).then((result) => handleSetLibraryPropsResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleSetLibraryPropsResponse)); |
| } else if (command == "pg" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "getGlobalVariables", |
| "params": { "isolateId" : isolate_id, |
| "libraryId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGetGlobalVarsResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetGlobalVarsResponse)); |
| } else if (command == "gs" && args.length == 3) { |
| var cmd = { "id": seqNum, |
| "command": "getScriptSource", |
| "params": { "isolateId" : isolate_id, |
| "libraryId": int.parse(args[1]), |
| "url": args[2] } }; |
| - sendCmd(cmd).then((result) => handleGetSourceResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetSourceResponse)); |
| } else if (command == "tok" && args.length == 3) { |
| var cmd = { "id": seqNum, |
| "command": "getLineNumberTable", |
| "params": { "isolateId" : isolate_id, |
| "libraryId": int.parse(args[1]), |
| "url": args[2] } }; |
| - sendCmd(cmd).then((result) => handleGetLineTableResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetLineTableResponse)); |
| } else if (command == "epi" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "setPauseOnException", |
| "params": { "isolateId" : isolate_id, |
| "exceptions": args[1] } }; |
| - sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
| } else if (command == "li") { |
| var cmd = { "id": seqNum, "command": "getIsolateIds" }; |
| - sendCmd(cmd).then((result) => handleGetIsolatesResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGetIsolatesResponse)); |
| } else if (command == "i" && args.length == 2) { |
| var cmd = { "id": seqNum, |
| "command": "interrupt", |
| "params": { "isolateId": int.parse(args[1]) } }; |
| - sendCmd(cmd).then((result) => handleGenericResponse(result)); |
| + sendCmd(cmd).then(hidePrompt(handleGenericResponse)); |
| } else if (command == "q") { |
| quitShell(); |
| } else if (command == "h") { |
| @@ -366,7 +384,7 @@ |
| } |
| -handleGetIsolatesResponse(response) { |
| +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.
|
| Map result = response["result"]; |
| print("Isolates: ${result["isolateIds"]}"); |
| } |
| @@ -470,32 +488,39 @@ |
| } |
| var event = msg["event"]; |
| if (event == "paused") { |
| + cmdo.hide(); |
| handlePausedEvent(msg); |
| + cmdo.show(); |
| return; |
| } |
| if (event == "breakpointResolved") { |
| Map params = msg["params"]; |
| assert(params != null); |
| + cmdo.hide(); |
| print("BP ${params["breakpointId"]} resolved and " |
| "set at line ${params["line"]}."); |
| + cmdo.show(); |
| return; |
| } |
| if (event == "isolate") { |
| Map params = msg["params"]; |
| assert(params != null); |
| + cmdo.hide(); |
| print("Isolate ${params["id"]} has been ${params["reason"]}."); |
| + cmdo.show(); |
| return; |
| } |
| if (msg["id"] != null) { |
| var id = msg["id"]; |
| if (outstandingCommands.containsKey(id)) { |
| + var completer = outstandingCommands.remove(id); |
| if (msg["error"] != null) { |
| print("VM says: ${msg["error"]}"); |
| + // TODO(turnidge): Rework how hide/show happen. For now |
| + cmdo.show(); |
| } else { |
| - var completer = outstandingCommands[id]; |
| completer.complete(msg); |
| } |
| - outstandingCommands.remove(id); |
| } |
| } |
| } |
| @@ -600,7 +625,31 @@ |
| return 0; |
| } |
| +List<String> debuggerCommandCompleter(List<String> commandParts) { |
| + List<String> completions = new List<String>(); |
| + // TODO(turnidge): Have a global command table and use it to for |
| + // help messages, command completion, and command dispatching. For now |
| + // we hardcode the list here. |
| + // |
| + // TODO(turnidge): Implement completion for arguments as well. |
| + List<String> allCommands = ['q', 'bt', 'r', 's', 'so', 'si', 'sbp', 'rbp', |
| + 'po', 'eval', 'pl', 'pc', 'll', 'plib', 'slib', |
| + 'pg', 'ls', 'gs', 'tok', 'epi', 'li', 'i', 'h']; |
| + |
| + // Completion of first word in the command. |
| + if (commandParts.length == 1) { |
| + String prefix = commandParts.last; |
| + for (String command in allCommands) { |
| + if (command.startsWith(prefix)) { |
| + completions.add(command); |
| + } |
| + } |
| + } |
| + |
| + return completions; |
| +} |
| + |
| void debuggerMain() { |
| outstandingCommands = new Map<int, Completer>(); |
| Socket.connect("127.0.0.1", 5858).then((s) { |
| @@ -620,20 +669,46 @@ |
| // TODO(floitsch): do we want to print the stack trace? |
| quitShell(); |
| }); |
| - stdinSubscription = stdin.transform(UTF8.decoder) |
| - .transform(new LineSplitter()) |
| - .listen((String line) => processCommand(line)); |
| + cmdo = new Commando(stdin, stdout, processCommand, |
| + completer:debuggerCommandCompleter); |
|
hausner
2013/11/21 22:30:02
Spaces around :
turnidge
2013/11/22 19:59:59
Done.
|
| }); |
| } |
| -void main(List<String> arguments) { |
| - if (arguments.length > 0) { |
| - arguments = <String>['--debug', '--verbose_debug']..addAll(arguments); |
| - Process.start(Platform.executable, arguments).then((Process process) { |
| - process.stdin.close(); |
| - process.exitCode.then((int exitCode) { |
| - print('${arguments.join(" ")} exited with $exitCode'); |
| - }); |
| +void main(List<String> args) { |
| + if (args.length > 0) { |
| + if (verbose) { |
| + args = <String>['--debug', '--verbose_debug']..addAll(args); |
| + } else { |
| + args = <String>['--debug']..addAll(args); |
| + } |
| + Process.start(Platform.executable, args).then((Process process) { |
| + targetProcess = process; |
| + process.stdin.close(); |
| + |
| + // TODO(turnidge): For now we only show full lines of output |
| + // from the debugged process. Should show each character. |
| + process.stdout |
| + .transform(UTF8.decoder) |
| + .transform(new LineSplitter()) |
| + .listen((String line) { |
| + // Hide/show command prompt across asynchronous output. |
| + if (cmdo != null) { |
| + cmdo.hide(); |
| + } |
| + print("$line"); |
| + if (cmdo != null) { |
| + cmdo.show(); |
| + } |
| + }); |
| + |
| + process.exitCode.then((int exitCode) { |
| + if (exitCode == 0) { |
| + print('Program exited normally.'); |
| + } else { |
| + print('Program exited with code $exitCode.'); |
| + } |
| + }); |
| + |
| debuggerMain(); |
| }); |
| } else { |