| 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);
|
| +
|
| +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));
|
| } 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) {
|
| 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);
|
| });
|
| }
|
|
|
| -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 {
|
|
|