Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: tools/ddbg_service/lib/debugger.dart

Issue 575853002: Add tools/ddbg_service. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: gen js Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/ddbg_service/lib/commando.dart ('k') | tools/ddbg_service/lib/terminfo.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/ddbg_service/lib/debugger.dart
diff --git a/tools/ddbg_service/lib/debugger.dart b/tools/ddbg_service/lib/debugger.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a5dbb6d9cb64db557729aaa6e66c220c0ba10f31
--- /dev/null
+++ b/tools/ddbg_service/lib/debugger.dart
@@ -0,0 +1,437 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library debugger;
+
+import "dart:async";
+import "dart:io";
+
+import "package:ddbg/commando.dart";
+import "package:observatory/service_io.dart";
+
+class Debugger {
+ Commando cmdo;
+ var _cmdoSubscription;
+
+ VM _vm;
+ VM get vm => _vm;
+ set vm(VM vm) {
+ if (_vm == vm) {
+ // Do nothing.
+ return;
+ }
+ if (_vm != null) {
+ _vm.disconnect();
+ }
+ if (vm != null) {
+ vm.onConnect.then(_vmConnected);
+ vm.onDisconnect.then(_vmDisconnected);
+ vm.errors.stream.listen(_onServiceError);
+ vm.exceptions.stream.listen(_onServiceException);
+ vm.events.stream.listen(_onServiceEvent);
+ }
+ _vm = vm;
+ }
+
+ _vmConnected(VM vm) {
+ cmdo.print('Connected to vm');
+ }
+
+ _vmDisconnected(VM vm) {
+ cmdo.print('Disconnected from vm');
+ }
+
+ _onServiceError(ServiceError error) {
+ cmdo.print('error $error');
+ }
+
+ _onServiceException(ServiceException exception) {
+ cmdo.print('${exception.message}');
+ }
+
+ _onServiceEvent(ServiceEvent event) {
+ switch (event.eventType) {
+ case 'GC':
+ // Ignore GC events for now.
+ break;
+ default:
+ cmdo.print('event $event');
+ break;
+ }
+ }
+
+ VM _isolate;
+ VM get isolate => _isolate;
+ set isolate(Isolate isolate) {
+ _isolate = isolate;
+ cmdo.print('Current isolate is now isolate ${getIsolateIndex(_isolate)}');
+ }
+
+ Map _isolateIndexMap = new Map();
+ int _nextIsolateIndex = 0;
+ int getIsolateIndex(Isolate isolate) {
+ var index = _isolateIndexMap[isolate.id];
+ if (index == null) {
+ index = _nextIsolateIndex++;
+ _isolateIndexMap[isolate.id] = index;
+ }
+ return index;
+ }
+
+ void onUncaughtError(error, StackTrace trace) {
+ if (error is ServiceException ||
+ error is ServiceError) {
+ // These are handled elsewhere. Ignore.
+ return;
+ }
+ cmdo.print('\n--------\nExiting due to unexpected error:\n'
+ ' $error\n$trace\n');
+ quit();
+ }
+
+ Debugger() {
+ cmdo = new Commando(completer: completeCommand);
+ _cmdoSubscription = cmdo.commands.listen(_processCommand,
+ onError: _cmdoError,
+ onDone: _cmdoDone);
+ }
+
+ Future _closeCmdo() {
+ var sub = _cmdoSubscription;
+ _cmdoSubscription = null;
+ cmdo = null;
+
+ var future = sub.cancel();
+ if (future != null) {
+ return future;
+ } else {
+ return new Future.value();
+ }
+ }
+
+ Future quit() {
+ return Future.wait([_closeCmdo()]).then((_) {
+ exit(0);
+ });
+ }
+
+ void _cmdoError(self, parent, zone, error, StackTrace trace) {
+ cmdo.print('\n--------\nExiting due to unexpected error:\n'
+ ' $error\n$trace\n');
+ quit();
+ }
+
+ void _cmdoDone() {
+ quit();
+ }
+
+ void _processCommand(String cmdLine) {
+ void huh() {
+ cmdo.print("'$cmdLine' not understood, try 'help' for help.");
+ }
+
+ cmdo.hide();
+ cmdLine = cmdLine.trim();
+ var args = cmdLine.split(' ');
+ if (args.length == 0) {
+ return;
+ }
+ var command = args[0];
+ var matches = matchCommand(command, true);
+ if (matches.length == 0) {
+ huh();
+ cmdo.show();
+ } else if (matches.length == 1) {
+ matches[0].run(this, args).then((_) {
+ cmdo.show();
+ });
+ } else {
+ var matchNames = matches.map((handler) => handler.name);
+ cmdo.print("Ambigous command '$command' : ${matchNames.toList()}");
+ cmdo.show();
+ }
+ }
+
+}
+
+// Every debugger command extends this base class.
+abstract class Command {
+ String get name;
+ String get helpShort;
+ void printHelp(Debugger debugger, List<String> args);
+ Future run(Debugger debugger, List<String> args);
+}
+
+class AttachCommand extends Command {
+ final name = 'attach';
+ final helpShort = 'Attach to a running Dart VM';
+ void printHelp(Debugger debugger, List<String> args) {
+ debugger.cmdo.print('''
+----- attach -----
+
+Attach to the Dart VM running at the indicated host:port. If no
+host:port is provided, attach to the VM running on the default port.
+
+Usage:
+ attach
+ attach <host:port>
+''');
+ }
+
+ Future run(Debugger debugger, List<String> args) {
+ var cmdo = debugger.cmdo;
+ if (args.length > 2) {
+ cmdo.print('$name expects 0 or 1 arguments');
+ return new Future.value();
+ }
+ String hostPort = 'localhost:8181';
+ if (args.length > 1) {
+ hostPort = args[1];
+ }
+
+ debugger.vm = new WebSocketVM(new WebSocketVMTarget('ws://${hostPort}/ws'));
+ return debugger.vm.load().then((vm) {
+ if (debugger.isolate == null) {
+ for (var isolate in vm.isolates) {
+ if (isolate.name == 'root') {
+ debugger.isolate = isolate;
+ }
+ }
+ }
+ });
+ }
+}
+
+class DetachCommand extends Command {
+ final name = 'detach';
+ final helpShort = 'Detach from a running Dart VM';
+ void printHelp(Debugger debugger, List<String> args) {
+ cmdo.print('''
+----- detach -----
+
+Detach from the Dart VM.
+
+Usage:
+ detach
+''');
+ }
+
+ Future run(Debugger debugger, List<String> args) {
+ var cmdo = debugger.cmdo;
+ if (args.length > 1) {
+ cmdo.print('$name expects no arguments');
+ return new Future.value();
+ }
+ if (debugger.vm == null) {
+ cmdo.print('No VM is attached');
+ } else {
+ debugger.vm = null;
+ }
+ return new Future.value();
+ }
+}
+
+class HelpCommand extends Command {
+ final name = 'help';
+ final helpShort = 'Show a list of debugger commands';
+ void printHelp(Debugger debugger, List<String> args) {
+ debugger.cmdo.print('''
+----- help -----
+
+Show a list of debugger commands or get more information about a
+particular command.
+
+Usage:
+ help
+ help <command>
+''');
+ }
+
+ Future run(Debugger debugger, List<String> args) {
+ var cmdo = debugger.cmdo;
+ if (args.length <= 1) {
+ cmdo.print("\nDebugger commands:\n");
+ for (var command in commandList) {
+ cmdo.print(' ${command.name.padRight(11)} ${command.helpShort}');
+ }
+ cmdo.print("For more information about a particular command, type:\n\n"
+ " help <command>\n");
+
+ cmdo.print("Commands may be abbreviated: e.g. type 'h' for 'help.\n");
+ } else {
+ var commandName = args[1];
+ var matches = matchCommand(commandName, true);
+ if (matches.length == 0) {
+ cmdo.print("Command '$commandName' not recognized. "
+ "Try 'help' for a list of commands.");
+ } else {
+ for (var command in matches) {
+ command.printHelp(debugger, args);
+ }
+ }
+ }
+
+ return new Future.value();
+ }
+}
+
+class IsolateCommand extends Command {
+ final name = 'isolate';
+ final helpShort = 'Isolate control';
+ void printHelp(Debugger debugger, List<String> args) {
+ debugger.cmdo.print('''
+----- isolate -----
+
+List all isolates.
+
+Usage:
+ isolate
+ isolate list
+
+Set current isolate.
+
+Usage:
+ isolate <id>
+''');
+ }
+
+ Future run(Debugger debugger, List<String> args) {
+ var cmdo = debugger.cmdo;
+ if (args.length == 1 ||
+ (args.length == 2 && args[1] == 'list')) {
+ return _listIsolates(debugger);
+ } else if (args.length == 2) {
+ cmdo.print('UNIMPLEMENTED');
+ return new Future.value();
+ } else {
+ if (args.length > 1) {
+ cmdo.print('Unrecognized isolate command');
+ printHelp(debugger, []);
+ return new Future.value();
+ }
+ }
+ }
+
+ Future _listIsolates(Debugger debugger) {
+ var cmdo = debugger.cmdo;
+ if (debugger.vm == null) {
+ cmdo.print('No VM is attached');
+ return new Future.value();
+ }
+ return debugger.vm.reload().then((vm) {
+ // Sort the isolates by their indices.
+ var isolates = vm.isolates.toList();
+ isolates.sort((iso1, iso2) {
+ return (debugger.getIsolateIndex(iso1) -
+ debugger.getIsolateIndex(iso2));
+ });
+
+ StringBuffer sb = new StringBuffer();
+ cmdo.print(' ID NAME STATE');
+ cmdo.print('-----------------------------------------------');
+ for (var isolate in isolates) {
+ if (isolate == debugger.isolate) {
+ sb.write('* ');
+ } else {
+ sb.write(' ');
+ }
+ sb.write(debugger.getIsolateIndex(isolate).toString().padRight(8));
+ sb.write(' ');
+ sb.write(isolate.name.padRight(12));
+ sb.write(' ');
+ if (isolate.pauseEvent != null) {
+ switch (isolate.pauseEvent.eventType) {
+ case 'IsolateCreated':
+ sb.write('paused at isolate start');
+ break;
+ case 'IsolateShutdown':
+ sb.write('paused at isolate exit');
+ break;
+ case 'IsolateInterrupted':
+ sb.write('paused');
+ break;
+ case 'BreakpointReached':
+ sb.write('paused by breakpoint');
+ break;
+ case 'ExceptionThrown':
+ sb.write('paused by exception');
+ break;
+ default:
+ sb.write('paused by unknown cause');
+ break;
+ }
+ } else if (isolate.running) {
+ sb.write('running');
+ } else if (isolate.idle) {
+ sb.write('idle');
+ } else if (isolate.loading) {
+ // TODO(turnidge): This is weird in a command line debugger.
+ sb.write('(not available)');
+ }
+ sb.write('\n');
+ }
+ cmdo.print(sb);
+ });
+ return new Future.value();
+ }
+}
+
+class QuitCommand extends Command {
+ final name = 'quit';
+ final helpShort = 'Quit the debugger.';
+ void printHelp(Debugger debugger, List<String> args) {
+ debugger.cmdo.print('''
+----- quit -----
+
+Quit the debugger.
+
+Usage:
+ quit
+''');
+ }
+
+ Future run(Debugger debugger, List<String> args) {
+ var cmdo = debugger.cmdo;
+ if (args.length > 1) {
+ cmdo.print("Unexpected arguments to $name command.");
+ return new Future.value();
+ }
+ return debugger.quit();
+ }
+}
+
+List<Command> commandList =
+ [ new AttachCommand(),
+ new DetachCommand(),
+ new HelpCommand(),
+ new IsolateCommand(),
+ new QuitCommand() ];
+
+List<Command> matchCommand(String commandName, bool exactMatchWins) {
+ var matches = [];
+ for (var command in commandList) {
+ if (command.name.startsWith(commandName)) {
+ if (exactMatchWins && command.name == commandName) {
+ // Exact match
+ return [command];
+ } else {
+ matches.add(command);
+ }
+ }
+ }
+ return matches;
+}
+
+List<String> completeCommand(List<String> commandParts) {
+ var completions = new List<String>();
+ if (commandParts.length == 1) {
+ String prefix = commandParts[0];
+ for (var command in commandList) {
+ if (command.name.startsWith(prefix)) {
+ completions.add(command.name);
+ }
+ }
+ }
+ return completions;
+}
« no previous file with comments | « tools/ddbg_service/lib/commando.dart ('k') | tools/ddbg_service/lib/terminfo.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698