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

Side by Side Diff: runtime/observatory/lib/src/elements/debugger.dart

Issue 993613002: Implement 'print', 'up', 'down', and 'frame' commands in the Observatory debugger. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library debugger_page_element; 5 library debugger_page_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'observatory_element.dart'; 9 import 'observatory_element.dart';
10 import 'package:observatory/cli.dart'; 10 import 'package:observatory/cli.dart';
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 97
98 String helpShort = 'List commands or provide details about a specific command' ; 98 String helpShort = 'List commands or provide details about a specific command' ;
99 99
100 String helpLong = 100 String helpLong =
101 'List commands or provide details about a specific command.\n' 101 'List commands or provide details about a specific command.\n'
102 '\n' 102 '\n'
103 'Syntax: help - Show a list of all commands\n' 103 'Syntax: help - Show a list of all commands\n'
104 ' help <command> - Help for a specific command\n'; 104 ' help <command> - Help for a specific command\n';
105 } 105 }
106 106
107 class PrintCommand extends DebuggerCommand {
108 PrintCommand(Debugger debugger) : super(debugger, 'print', []) {
109 alias = 'p';
110 }
111
112 Future run(List<String> args) {
113 if (args.length < 1) {
114 debugger.console.print('print expects arguments');
115 return new Future.value(null);
116 }
117 var expr = args.join('');
118 return debugger.isolate.evalFrame(debugger.currentFrame, expr)
119 .then((response) {
120 if (response is DartError) {
121 debugger.console.print(response.message);
122 } else {
123 ServiceMap instance = response;
124 debugger.console.print('= ', newline:false);
125 debugger.console.printRef(instance);
126 }
127 });
128 }
129
130 String helpShort = 'Evaluate and print an expression in the current frame';
131
132 String helpLong =
133 'Evaluate and print an expression in the current frame.\n'
134 '\n'
135 'Syntax: print <expression>\n'
136 ' p <expression>\n';
137 }
138
139 class DownCommand extends DebuggerCommand {
140 DownCommand(Debugger debugger) : super(debugger, 'down', []);
141
142 Future run(List<String> args) {
143 int count = 1;
144 if (args.length == 1) {
145 count = int.parse(args[0]);
146 } else if (args.length > 1) {
147 debugger.console.print('down expects 0 or 1 argument');
148 return new Future.value(null);
149 }
150 debugger.currentFrame -= count;
Cutch 2015/03/09 17:43:49 Should you notify the user on underflow?
151 debugger.console.print('frame = ${debugger.currentFrame}');
152 return new Future.value(null);
153 }
154
155 String helpShort = 'Move down one or more frames';
156
157 String helpLong =
158 'Move down one or more frames.\n'
159 '\n'
160 'Syntax: down\n'
161 ' down <count>\n';
162 }
163
164 class UpCommand extends DebuggerCommand {
165 UpCommand(Debugger debugger) : super(debugger, 'up', []);
166
167 Future run(List<String> args) {
168 int count = 1;
169 if (args.length == 1) {
170 count = int.parse(args[0]);
171 } else if (args.length > 1) {
172 debugger.console.print('up expects 0 or 1 argument');
173 return new Future.value(null);
174 }
175 debugger.currentFrame += count;
Cutch 2015/03/09 17:43:49 Should you notify the user on overflow?
176 debugger.console.print('frame = ${debugger.currentFrame}');
177 return new Future.value(null);
178 }
179
180 String helpShort = 'Move up one or more frames';
181
182 String helpLong =
183 'Move up one or more frames.\n'
184 '\n'
185 'Syntax: up\n'
186 ' up <count>\n';
187 }
188
189 class FrameCommand extends DebuggerCommand {
190 FrameCommand(Debugger debugger) : super(debugger, 'frame', []) {
191 alias = 'f';
192 }
193
194 Future run(List<String> args) {
195 int frame = 1;
196 if (args.length == 1) {
197 frame = int.parse(args[0]);
198 } else {
199 debugger.console.print('frame expects 1 argument');
200 return new Future.value(null);
201 }
202 debugger.currentFrame = frame;
203 debugger.console.print('frame = ${debugger.currentFrame}');
204 return new Future.value(null);
205 }
206
207 String helpShort = 'Set the current frame';
208
209 String helpLong =
210 'Set the current frame.\n'
211 '\n'
212 'Syntax: frame <number>\n'
213 ' f <count>\n';
214 }
215
107 class PauseCommand extends DebuggerCommand { 216 class PauseCommand extends DebuggerCommand {
108 PauseCommand(Debugger debugger) : super(debugger, 'pause', []); 217 PauseCommand(Debugger debugger) : super(debugger, 'pause', []);
109 218
110 Future run(List<String> args) { 219 Future run(List<String> args) {
111 if (!debugger.isolatePaused()) { 220 if (!debugger.isolatePaused()) {
112 return debugger.isolate.pause(); 221 return debugger.isolate.pause();
113 } else { 222 } else {
114 debugger.console.print('The program is already paused'); 223 debugger.console.print('The program is already paused');
115 return new Future.value(null); 224 return new Future.value(null);
116 } 225 }
(...skipping 21 matching lines...) Expand all
138 debugger.console.print('The program must be paused'); 247 debugger.console.print('The program must be paused');
139 return new Future.value(null); 248 return new Future.value(null);
140 } 249 }
141 } 250 }
142 251
143 String helpShort = 'Resume execution of the isolate'; 252 String helpShort = 'Resume execution of the isolate';
144 253
145 String helpLong = 254 String helpLong =
146 'Continue running the isolate.\n' 255 'Continue running the isolate.\n'
147 '\n' 256 '\n'
148 'Syntax: continue\n'; 257 'Syntax: continue\n'
258 ' c\n';
149 } 259 }
150 260
151 class NextCommand extends DebuggerCommand { 261 class NextCommand extends DebuggerCommand {
152 NextCommand(Debugger debugger) : super(debugger, 'next', []); 262 NextCommand(Debugger debugger) : super(debugger, 'next', []);
153 263
154 Future run(List<String> args) { 264 Future run(List<String> args) {
155 if (debugger.isolatePaused()) { 265 if (debugger.isolatePaused()) {
156 var event = debugger.isolate.pauseEvent; 266 var event = debugger.isolate.pauseEvent;
157 if (event.eventType == ServiceEvent.kPauseStart) { 267 if (event.eventType == ServiceEvent.kPauseStart) {
158 debugger.console.print("Type 'continue' to start the isolate"); 268 debugger.console.print("Type 'continue' to start the isolate");
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 } 593 }
484 594
485 String helpShort = 'List all isolates'; 595 String helpShort = 'List all isolates';
486 596
487 String helpLong = 597 String helpLong =
488 'List all isolates.\n' 598 'List all isolates.\n'
489 '\n' 599 '\n'
490 'Syntax: info isolates\n'; 600 'Syntax: info isolates\n';
491 } 601 }
492 602
603 class InfoFrameCommand extends DebuggerCommand {
604 InfoFrameCommand(Debugger debugger) : super(debugger, 'frame', []);
605
606 Future run(List<String> args) {
607 if (args.length > 0) {
608 debugger.console.print('info frame expects 1 argument');
609 return new Future.value(null);
610 }
611 debugger.console.print('frame = ${debugger.currentFrame}');
612 return new Future.value(null);
613 }
614
615 String helpShort = 'Show current frame';
616
617 String helpLong =
618 'Show current frame.\n'
619 '\n'
620 'Syntax: info frame\n';
621 }
622
493 class InfoCommand extends DebuggerCommand { 623 class InfoCommand extends DebuggerCommand {
494 InfoCommand(Debugger debugger) : super(debugger, 'info', [ 624 InfoCommand(Debugger debugger) : super(debugger, 'info', [
495 new InfoBreakpointsCommand(debugger), 625 new InfoBreakpointsCommand(debugger),
496 new InfoIsolatesCommand(debugger), 626 new InfoIsolatesCommand(debugger),
627 new InfoFrameCommand(debugger),
497 ]); 628 ]);
498 629
499 Future run(List<String> args) { 630 Future run(List<String> args) {
500 debugger.console.print("'info' expects a subcommand (see 'help info')"); 631 debugger.console.print("'info' expects a subcommand (see 'help info')");
501 return new Future.value(null); 632 return new Future.value(null);
502 } 633 }
503 634
504 String helpShort = 'Show information on a variety of topics'; 635 String helpShort = 'Show information on a variety of topics';
505 636
506 String helpLong = 637 String helpLong =
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 '\n' 697 '\n'
567 'Syntax: refresh <subcommand>\n'; 698 'Syntax: refresh <subcommand>\n';
568 } 699 }
569 700
570 // Tracks the state for an isolate debugging session. 701 // Tracks the state for an isolate debugging session.
571 class ObservatoryDebugger extends Debugger { 702 class ObservatoryDebugger extends Debugger {
572 RootCommand cmd; 703 RootCommand cmd;
573 DebuggerConsoleElement console; 704 DebuggerConsoleElement console;
574 DebuggerStackElement stackElement; 705 DebuggerStackElement stackElement;
575 ServiceMap stack; 706 ServiceMap stack;
576 int currentFrame = 0; 707
708 int get currentFrame => _currentFrame;
709 void set currentFrame(int value) {
710 if (value >= 0 && value < stackDepth) {
711 _currentFrame = value;
712 if (stackElement != null) {
713 stackElement.setCurrentFrame(value);
714 }
715 }
716 }
717 int _currentFrame = null;
718
719 int get stackDepth => stack['frames'].length;
577 720
578 ObservatoryDebugger() { 721 ObservatoryDebugger() {
579 cmd = new RootCommand([ 722 cmd = new RootCommand([
580 new HelpCommand(this), 723 new HelpCommand(this),
724 new PrintCommand(this),
725 new DownCommand(this),
726 new UpCommand(this),
727 new FrameCommand(this),
581 new PauseCommand(this), 728 new PauseCommand(this),
582 new ContinueCommand(this), 729 new ContinueCommand(this),
583 new NextCommand(this), 730 new NextCommand(this),
584 new StepCommand(this), 731 new StepCommand(this),
585 new FinishCommand(this), 732 new FinishCommand(this),
586 new BreakCommand(this), 733 new BreakCommand(this),
587 new ClearCommand(this), 734 new ClearCommand(this),
588 new DeleteCommand(this), 735 new DeleteCommand(this),
589 new InfoCommand(this), 736 new InfoCommand(this),
590 new RefreshCommand(this), 737 new RefreshCommand(this),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 } 789 }
643 }); 790 });
644 } 791 }
645 792
646 Future<ServiceMap> _refreshStack(ServiceEvent pauseEvent) { 793 Future<ServiceMap> _refreshStack(ServiceEvent pauseEvent) {
647 return isolate.getStack().then((result) { 794 return isolate.getStack().then((result) {
648 stack = result; 795 stack = result;
649 // TODO(turnidge): Replace only the changed part of the stack to 796 // TODO(turnidge): Replace only the changed part of the stack to
650 // reduce flicker. 797 // reduce flicker.
651 stackElement.updateStack(stack, pauseEvent); 798 stackElement.updateStack(stack, pauseEvent);
799 currentFrame = 0;
652 }); 800 });
653 } 801 }
654 802
655 void reportStatus() { 803 void reportStatus() {
656 if (_isolate.idle) { 804 if (_isolate.idle) {
657 console.print('Isolate is idle'); 805 console.print('Isolate is idle');
658 } else if (_isolate.running) { 806 } else if (_isolate.running) {
659 console.print("Isolate is running (type 'pause' to interrupt)"); 807 console.print("Isolate is running (type 'pause' to interrupt)");
660 } else if (_isolate.pauseEvent != null) { 808 } else if (_isolate.pauseEvent != null) {
661 _reportPause(_isolate.pauseEvent); 809 _reportPause(_isolate.pauseEvent);
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 debugger.init(); 1019 debugger.init();
872 } 1020 }
873 1021
874 } 1022 }
875 1023
876 @CustomTag('debugger-stack') 1024 @CustomTag('debugger-stack')
877 class DebuggerStackElement extends ObservatoryElement { 1025 class DebuggerStackElement extends ObservatoryElement {
878 @published Isolate isolate; 1026 @published Isolate isolate;
879 @observable bool hasStack = false; 1027 @observable bool hasStack = false;
880 @observable bool isSampled = false; 1028 @observable bool isSampled = false;
1029 @observable int currentFrame;
881 ObservatoryDebugger debugger; 1030 ObservatoryDebugger debugger;
882 1031
883 _addFrame(List frameList, ObservableMap frameInfo, bool expand) { 1032 _addFrame(List frameList, ObservableMap frameInfo) {
884 DebuggerFrameElement frameElement = new Element.tag('debugger-frame'); 1033 DebuggerFrameElement frameElement = new Element.tag('debugger-frame');
885 frameElement.expand = expand;
886 frameElement.frame = frameInfo; 1034 frameElement.frame = frameInfo;
887 1035
1036 if (frameInfo['depth'] == currentFrame) {
1037 frameElement.setCurrent(true);
1038 } else {
1039 frameElement.setCurrent(false);
1040 }
1041
888 var li = new LIElement(); 1042 var li = new LIElement();
889 li.classes.add('list-group-item'); 1043 li.classes.add('list-group-item');
890 li.children.insert(0, frameElement); 1044 li.children.insert(0, frameElement);
891 1045
892 frameList.insert(0, li); 1046 frameList.insert(0, li);
893 } 1047 }
894 1048
895 void updateStack(ServiceMap newStack, ServiceEvent pauseEvent) { 1049 void updateStack(ServiceMap newStack, ServiceEvent pauseEvent) {
896 List frameElements = $['frameList'].children; 1050 List frameElements = $['frameList'].children;
897 List newFrames = newStack['frames']; 1051 List newFrames = newStack['frames'];
(...skipping 23 matching lines...) Expand all
921 frameElements.removeAt(0); 1075 frameElements.removeAt(0);
922 } 1076 }
923 } 1077 }
924 1078
925 // Add any new frames. 1079 // Add any new frames.
926 int newCount = 0; 1080 int newCount = 0;
927 if (frameElements.length < newFrames.length) { 1081 if (frameElements.length < newFrames.length) {
928 // Add new frames to the top of stack. 1082 // Add new frames to the top of stack.
929 newCount = newFrames.length - frameElements.length; 1083 newCount = newFrames.length - frameElements.length;
930 for (int i = newCount-1; i >= 0; i--) { 1084 for (int i = newCount-1; i >= 0; i--) {
931 _addFrame(frameElements, newFrames[i], i == 0); 1085 _addFrame(frameElements, newFrames[i]);
932 } 1086 }
933 } 1087 }
934 assert(frameElements.length == newFrames.length); 1088 assert(frameElements.length == newFrames.length);
935 1089
936 if (frameElements.isNotEmpty) { 1090 if (frameElements.isNotEmpty) {
937 frameElements[0].children[0].expand = true;
938 for (int i = newCount; i < frameElements.length; i++) { 1091 for (int i = newCount; i < frameElements.length; i++) {
939 frameElements[i].children[0].updateFrame(newFrames[i]); 1092 frameElements[i].children[0].updateFrame(newFrames[i]);
940 } 1093 }
941 } 1094 }
942 1095
943 isSampled = pauseEvent == null; 1096 isSampled = pauseEvent == null;
944 hasStack = frameElements.isNotEmpty; 1097 hasStack = frameElements.isNotEmpty;
945 } 1098 }
946 1099
1100 void setCurrentFrame(int value) {
1101 currentFrame = value;
1102 List frameElements = $['frameList'].children;
1103 for (var frameElement in frameElements) {
1104 var dbgFrameElement = frameElement.children[0];
1105 if (dbgFrameElement.frame['depth'] == currentFrame) {
1106 dbgFrameElement.setCurrent(true);
1107 } else {
1108 dbgFrameElement.setCurrent(false);
1109 }
1110 }
1111 }
1112
947 Set<Script> activeScripts() { 1113 Set<Script> activeScripts() {
948 var s = new Set<Script>(); 1114 var s = new Set<Script>();
949 List frameElements = $['frameList'].children; 1115 List frameElements = $['frameList'].children;
950 for (var frameElement in frameElements) { 1116 for (var frameElement in frameElements) {
951 s.add(frameElement.children[0].script); 1117 s.add(frameElement.children[0].script);
952 } 1118 }
953 return s; 1119 return s;
954 } 1120 }
955 1121
956 doPauseIsolate(_) { 1122 doPauseIsolate(_) {
(...skipping 12 matching lines...) Expand all
969 } 1135 }
970 } 1136 }
971 1137
972 DebuggerStackElement.created() : super.created(); 1138 DebuggerStackElement.created() : super.created();
973 } 1139 }
974 1140
975 @CustomTag('debugger-frame') 1141 @CustomTag('debugger-frame')
976 class DebuggerFrameElement extends ObservatoryElement { 1142 class DebuggerFrameElement extends ObservatoryElement {
977 @published ObservableMap frame; 1143 @published ObservableMap frame;
978 1144
979 // When true, the frame will start out expanded. 1145 // Is this the current frame?
980 @published bool expand = false; 1146 bool _current = false;
1147
1148 // Has this frame been pinned open?
1149 bool _pinned = false;
1150
1151 void setCurrent(bool value) {
1152 busy = true;
1153 frame['function'].load().then((func) {
1154 _current = value;
1155 var frameOuter = $['frameOuter'];
1156 if (_current) {
1157 frameOuter.classes.add('current');
1158 expanded = true;
1159 frameOuter.classes.add('shadow');
1160 scrollIntoView();
1161 } else {
1162 frameOuter.classes.remove('current');
1163 if (_pinned) {
1164 expanded = true;
1165 frameOuter.classes.add('shadow');
1166 } else {
1167 expanded = false;
1168 frameOuter.classes.remove('shadow');
1169 }
1170 }
1171 busy = false;
1172 });
1173 }
981 1174
982 @observable String scriptHeight; 1175 @observable String scriptHeight;
983 @observable bool expanded = false; 1176 @observable bool expanded = false;
984 @observable bool busy = false; 1177 @observable bool busy = false;
985 1178
986 DebuggerFrameElement.created() : super.created(); 1179 DebuggerFrameElement.created() : super.created();
987 1180
988 bool matchFrame(ObservableMap newFrame) { 1181 bool matchFrame(ObservableMap newFrame) {
989 return newFrame['function'].id == frame['function'].id; 1182 return newFrame['function'].id == frame['function'].id;
990 } 1183 }
991 1184
992 void updateFrame(ObservableMap newFrame) { 1185 void updateFrame(ObservableMap newFrame) {
993 assert(matchFrame(newFrame)); 1186 assert(matchFrame(newFrame));
994 frame['depth'] = newFrame['depth']; 1187 frame['depth'] = newFrame['depth'];
995 frame['tokenPos'] = newFrame['tokenPos']; 1188 frame['tokenPos'] = newFrame['tokenPos'];
996 frame['vars'] = newFrame['vars']; 1189 frame['vars'] = newFrame['vars'];
997 } 1190 }
998 1191
999 Script get script => frame['script']; 1192 Script get script => frame['script'];
1000 1193
1001 @override 1194 @override
1002 void attached() { 1195 void attached() {
1003 super.attached(); 1196 super.attached();
1004 int windowHeight = window.innerHeight; 1197 int windowHeight = window.innerHeight;
1005 scriptHeight = '${windowHeight ~/ 1.6}px'; 1198 scriptHeight = '${windowHeight ~/ 1.6}px';
1006 } 1199 }
1007 1200
1008 void expandChanged(oldValue) {
1009 if (expand != expanded) {
1010 toggleExpand(null, null, null);
1011 }
1012 }
1013
1014 void toggleExpand(var a, var b, var c) { 1201 void toggleExpand(var a, var b, var c) {
1015 if (busy) { 1202 if (busy) {
1016 return; 1203 return;
1017 } 1204 }
1018 busy = true; 1205 busy = true;
1019 frame['function'].load().then((func) { 1206 frame['function'].load().then((func) {
1020 expanded = !expanded; 1207 _pinned = !_pinned;
1021 var frameOuter = $['frameOuter']; 1208 var frameOuter = $['frameOuter'];
1022 if (expanded) { 1209 if (_pinned) {
1210 expanded = true;
1023 frameOuter.classes.add('shadow'); 1211 frameOuter.classes.add('shadow');
1024 } else { 1212 } else {
1213 expanded = false;
1025 frameOuter.classes.remove('shadow'); 1214 frameOuter.classes.remove('shadow');
1026 } 1215 }
1027 busy = false; 1216 busy = false;
1028 }); 1217 });
1029 } 1218 }
1030 } 1219 }
1031 1220
1032 @CustomTag('debugger-console') 1221 @CustomTag('debugger-console')
1033 class DebuggerConsoleElement extends ObservatoryElement { 1222 class DebuggerConsoleElement extends ObservatoryElement {
1034 @published Isolate isolate; 1223 @published Isolate isolate;
(...skipping 15 matching lines...) Expand all
1050 var span = new SpanElement(); 1239 var span = new SpanElement();
1051 span.classes.add('bold'); 1240 span.classes.add('bold');
1052 span.appendText(line); 1241 span.appendText(line);
1053 if (newline) { 1242 if (newline) {
1054 span.appendText('\n'); 1243 span.appendText('\n');
1055 } 1244 }
1056 $['consoleText'].children.add(span); 1245 $['consoleText'].children.add(span);
1057 span.scrollIntoView(); 1246 span.scrollIntoView();
1058 } 1247 }
1059 1248
1249 void printRef(ServiceMap ref, { bool newline:true }) {
1250 var refElement = new Element.tag('instance-ref');
1251 refElement.ref = ref;
1252 $['consoleText'].children.add(refElement);
1253 if (newline) {
1254 this.newline();
1255 }
1256 refElement.scrollIntoView();
1257 }
1258
1060 void newline() { 1259 void newline() {
1061 var br = new BRElement(); 1260 var br = new BRElement();
1062 $['consoleText'].children.add(br); 1261 $['consoleText'].children.add(br);
1063 br.scrollIntoView(); 1262 br.scrollIntoView();
1064 } 1263 }
1065 } 1264 }
1066 1265
1067 @CustomTag('debugger-input') 1266 @CustomTag('debugger-input')
1068 class DebuggerInputElement extends ObservatoryElement { 1267 class DebuggerInputElement extends ObservatoryElement {
1069 @published Isolate isolate; 1268 @published Isolate isolate;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 default: 1317 default:
1119 busy = false; 1318 busy = false;
1120 break; 1319 break;
1121 } 1320 }
1122 }); 1321 });
1123 } 1322 }
1124 1323
1125 DebuggerInputElement.created() : super.created(); 1324 DebuggerInputElement.created() : super.created();
1126 } 1325 }
1127 1326
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/debugger/source_location.dart ('k') | runtime/observatory/lib/src/elements/debugger.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698