| OLD | NEW | 
|---|
| 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 836 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 847   } | 847   } | 
| 848 | 848 | 
| 849   String helpShort = 'Refresh debugging information of various sorts'; | 849   String helpShort = 'Refresh debugging information of various sorts'; | 
| 850 | 850 | 
| 851   String helpLong = | 851   String helpLong = | 
| 852       'Refresh debugging information of various sorts.\n' | 852       'Refresh debugging information of various sorts.\n' | 
| 853       '\n' | 853       '\n' | 
| 854       'Syntax: refresh <subcommand>\n'; | 854       'Syntax: refresh <subcommand>\n'; | 
| 855 } | 855 } | 
| 856 | 856 | 
|  | 857 class _VMStreamPrinter { | 
|  | 858   ObservatoryDebugger _debugger; | 
|  | 859 | 
|  | 860   _VMStreamPrinter(this._debugger); | 
|  | 861 | 
|  | 862   String _savedStream; | 
|  | 863   String _savedIsolate; | 
|  | 864   String _savedLine; | 
|  | 865   List<String> _buffer = []; | 
|  | 866 | 
|  | 867   void onEvent(String streamName, ServiceEvent event) { | 
|  | 868     String isolateName = event.isolate.name; | 
|  | 869     // If we get a line from a different isolate/stream, flush | 
|  | 870     // any pending output, even if it is not newline-terminated. | 
|  | 871     if ((_savedIsolate != null && isolateName != _savedIsolate) || | 
|  | 872         (_savedStream != null && streamName != _savedStream)) { | 
|  | 873        flush(); | 
|  | 874     } | 
|  | 875     String data = event.bytesAsString; | 
|  | 876     bool hasNewline = data.endsWith('\n'); | 
|  | 877     if (_savedLine != null) { | 
|  | 878        data = _savedLine + data; | 
|  | 879       _savedIsolate = null; | 
|  | 880       _savedStream = null; | 
|  | 881       _savedLine = null; | 
|  | 882     } | 
|  | 883     var lines = data.split('\n').where((line) => line != '').toList(); | 
|  | 884     if (lines.isEmpty) { | 
|  | 885       return; | 
|  | 886     } | 
|  | 887     int limit = (hasNewline ? lines.length : lines.length - 1); | 
|  | 888     for (int i = 0; i < limit; i++) { | 
|  | 889       _buffer.add(_format(isolateName, streamName, lines[i])); | 
|  | 890     } | 
|  | 891     // If there is no newline, we save the last line of output for next time. | 
|  | 892     if (!hasNewline) { | 
|  | 893       _savedIsolate = isolateName; | 
|  | 894       _savedStream = streamName; | 
|  | 895       _savedLine = lines[lines.length - 1]; | 
|  | 896     } | 
|  | 897   } | 
|  | 898 | 
|  | 899   void flush() { | 
|  | 900     // If there is any saved output, flush it now. | 
|  | 901     if (_savedLine != null) { | 
|  | 902       _buffer.add(_format(_savedIsolate, _savedStream, _savedLine)); | 
|  | 903       _savedIsolate = null; | 
|  | 904       _savedStream = null; | 
|  | 905       _savedLine = null; | 
|  | 906     } | 
|  | 907     if (_buffer.isNotEmpty) { | 
|  | 908       _debugger.console.printStdio(_buffer); | 
|  | 909       _buffer.clear(); | 
|  | 910     } | 
|  | 911   } | 
|  | 912 | 
|  | 913   String _format(String isolateName, String streamName, String line) { | 
|  | 914     return '${isolateName}:${streamName}> ${line}'; | 
|  | 915   } | 
|  | 916 } | 
|  | 917 | 
| 857 // Tracks the state for an isolate debugging session. | 918 // Tracks the state for an isolate debugging session. | 
| 858 class ObservatoryDebugger extends Debugger { | 919 class ObservatoryDebugger extends Debugger { | 
| 859   RootCommand cmd; | 920   RootCommand cmd; | 
| 860   DebuggerPageElement page; | 921   DebuggerPageElement page; | 
| 861   DebuggerConsoleElement console; | 922   DebuggerConsoleElement console; | 
| 862   DebuggerInputElement input; | 923   DebuggerInputElement input; | 
| 863   DebuggerStackElement stackElement; | 924   DebuggerStackElement stackElement; | 
| 864   ServiceMap stack; | 925   ServiceMap stack; | 
| 865   String exceptions = "none";  // Last known setting. | 926   String exceptions = "none";  // Last known setting. | 
| 866 | 927 | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 891         new StepCommand(this), | 952         new StepCommand(this), | 
| 892         new FinishCommand(this), | 953         new FinishCommand(this), | 
| 893         new BreakCommand(this), | 954         new BreakCommand(this), | 
| 894         new SetCommand(this), | 955         new SetCommand(this), | 
| 895         new ClearCommand(this), | 956         new ClearCommand(this), | 
| 896         new DeleteCommand(this), | 957         new DeleteCommand(this), | 
| 897         new InfoCommand(this), | 958         new InfoCommand(this), | 
| 898         new IsolateCommand(this), | 959         new IsolateCommand(this), | 
| 899         new RefreshCommand(this), | 960         new RefreshCommand(this), | 
| 900     ]); | 961     ]); | 
|  | 962     _stdioPrinter = new _VMStreamPrinter(this); | 
| 901   } | 963   } | 
| 902 | 964 | 
| 903   VM get vm => page.app.vm; | 965   VM get vm => page.app.vm; | 
| 904 | 966 | 
| 905   void updateIsolate(Isolate iso) { | 967   void updateIsolate(Isolate iso) { | 
| 906     _isolate = iso; | 968     _isolate = iso; | 
| 907     if (_isolate != null) { | 969     if (_isolate != null) { | 
| 908       if (exceptions != iso.exceptionsPauseInfo) { | 970       if (exceptions != iso.exceptionsPauseInfo) { | 
| 909         exceptions = iso.exceptionsPauseInfo; | 971         exceptions = iso.exceptionsPauseInfo; | 
| 910         console.print("Now pausing for $exceptions exceptions"); | 972         console.print("Now pausing for $exceptions exceptions"); | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 990       if (stack['frames'].length > 0) { | 1052       if (stack['frames'].length > 0) { | 
| 991         currentFrame = 0; | 1053         currentFrame = 0; | 
| 992       } else { | 1054       } else { | 
| 993         currentFrame = null; | 1055         currentFrame = null; | 
| 994       } | 1056       } | 
| 995       input.focus(); | 1057       input.focus(); | 
| 996     }); | 1058     }); | 
| 997   } | 1059   } | 
| 998 | 1060 | 
| 999   void reportStatus() { | 1061   void reportStatus() { | 
|  | 1062     flushStdio(); | 
| 1000     if (_isolate == null) { | 1063     if (_isolate == null) { | 
| 1001       console.print('No current isolate'); | 1064       console.print('No current isolate'); | 
| 1002     } else if (_isolate.idle) { | 1065     } else if (_isolate.idle) { | 
| 1003       console.print('Isolate is idle'); | 1066       console.print('Isolate is idle'); | 
| 1004     } else if (_isolate.running) { | 1067     } else if (_isolate.running) { | 
| 1005       console.print("Isolate is running (type 'pause' to interrupt)"); | 1068       console.print("Isolate is running (type 'pause' to interrupt)"); | 
| 1006     } else if (_isolate.pauseEvent != null) { | 1069     } else if (_isolate.pauseEvent != null) { | 
| 1007       _reportPause(_isolate.pauseEvent); | 1070       _reportPause(_isolate.pauseEvent); | 
| 1008     } else { | 1071     } else { | 
| 1009       console.print('Isolate is in unknown state'); | 1072       console.print('Isolate is in unknown state'); | 
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1109         console.print("Isolate ${iso.number} renamed to '${iso.name}'"); | 1172         console.print("Isolate ${iso.number} renamed to '${iso.name}'"); | 
| 1110         break; | 1173         break; | 
| 1111 | 1174 | 
| 1112       case ServiceEvent.kPauseStart: | 1175       case ServiceEvent.kPauseStart: | 
| 1113       case ServiceEvent.kPauseExit: | 1176       case ServiceEvent.kPauseExit: | 
| 1114       case ServiceEvent.kPauseBreakpoint: | 1177       case ServiceEvent.kPauseBreakpoint: | 
| 1115       case ServiceEvent.kPauseInterrupted: | 1178       case ServiceEvent.kPauseInterrupted: | 
| 1116       case ServiceEvent.kPauseException: | 1179       case ServiceEvent.kPauseException: | 
| 1117         if (event.owner == isolate) { | 1180         if (event.owner == isolate) { | 
| 1118           _refreshStack(event).then((_) { | 1181           _refreshStack(event).then((_) { | 
|  | 1182             flushStdio(); | 
| 1119             _reportPause(event); | 1183             _reportPause(event); | 
| 1120           }); | 1184           }); | 
| 1121         } | 1185         } | 
| 1122         break; | 1186         break; | 
| 1123 | 1187 | 
| 1124       case ServiceEvent.kResume: | 1188       case ServiceEvent.kResume: | 
| 1125         if (event.owner == isolate) { | 1189         if (event.owner == isolate) { | 
|  | 1190           flushStdio(); | 
| 1126           console.print('Continuing...'); | 1191           console.print('Continuing...'); | 
| 1127         } | 1192         } | 
| 1128         break; | 1193         break; | 
| 1129 | 1194 | 
| 1130       case ServiceEvent.kBreakpointAdded: | 1195       case ServiceEvent.kBreakpointAdded: | 
| 1131       case ServiceEvent.kBreakpointResolved: | 1196       case ServiceEvent.kBreakpointResolved: | 
| 1132       case ServiceEvent.kBreakpointRemoved: | 1197       case ServiceEvent.kBreakpointRemoved: | 
| 1133         if (event.owner == isolate) { | 1198         if (event.owner == isolate) { | 
| 1134           _reportBreakpointEvent(event); | 1199           _reportBreakpointEvent(event); | 
| 1135         } | 1200         } | 
| 1136         break; | 1201         break; | 
| 1137 | 1202 | 
| 1138       case ServiceEvent.kIsolateStart: | 1203       case ServiceEvent.kIsolateStart: | 
| 1139       case ServiceEvent.kGraph: | 1204       case ServiceEvent.kGraph: | 
| 1140       case ServiceEvent.kGC: | 1205       case ServiceEvent.kGC: | 
| 1141       case ServiceEvent.kInspect: | 1206       case ServiceEvent.kInspect: | 
| 1142         break; | 1207         break; | 
| 1143 | 1208 | 
| 1144       default: | 1209       default: | 
| 1145         console.print('Unrecognized event: $event'); | 1210         console.print('Unrecognized event: $event'); | 
| 1146         break; | 1211         break; | 
| 1147     } | 1212     } | 
| 1148   } | 1213   } | 
| 1149 | 1214 | 
|  | 1215   _VMStreamPrinter _stdioPrinter; | 
|  | 1216 | 
|  | 1217   void flushStdio() { | 
|  | 1218     _stdioPrinter.flush(); | 
|  | 1219   } | 
|  | 1220 | 
|  | 1221   void onStdout(ServiceEvent event) { | 
|  | 1222     _stdioPrinter.onEvent('stdout', event); | 
|  | 1223   } | 
|  | 1224 | 
|  | 1225   void onStderr(ServiceEvent event) { | 
|  | 1226     _stdioPrinter.onEvent('stderr', event); | 
|  | 1227   } | 
|  | 1228 | 
| 1150   static String _commonPrefix(String a, String b) { | 1229   static String _commonPrefix(String a, String b) { | 
| 1151     int pos = 0; | 1230     int pos = 0; | 
| 1152     while (pos < a.length && pos < b.length) { | 1231     while (pos < a.length && pos < b.length) { | 
| 1153       if (a.codeUnitAt(pos) != b.codeUnitAt(pos)) { | 1232       if (a.codeUnitAt(pos) != b.codeUnitAt(pos)) { | 
| 1154         break; | 1233         break; | 
| 1155       } | 1234       } | 
| 1156       pos++; | 1235       pos++; | 
| 1157     } | 1236     } | 
| 1158     return a.substring(0, pos); | 1237     return a.substring(0, pos); | 
| 1159   } | 1238   } | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1229     } | 1308     } | 
| 1230   } | 1309   } | 
| 1231   ObservatoryDebugger debugger = new ObservatoryDebugger(); | 1310   ObservatoryDebugger debugger = new ObservatoryDebugger(); | 
| 1232 | 1311 | 
| 1233   DebuggerPageElement.created() : super.created() { | 1312   DebuggerPageElement.created() : super.created() { | 
| 1234     debugger.page = this; | 1313     debugger.page = this; | 
| 1235   } | 1314   } | 
| 1236 | 1315 | 
| 1237   Future<StreamSubscription> _isolateSubscriptionFuture; | 1316   Future<StreamSubscription> _isolateSubscriptionFuture; | 
| 1238   Future<StreamSubscription> _debugSubscriptionFuture; | 1317   Future<StreamSubscription> _debugSubscriptionFuture; | 
|  | 1318   Future<StreamSubscription> _stdoutSubscriptionFuture; | 
|  | 1319   Future<StreamSubscription> _stderrSubscriptionFuture; | 
| 1239 | 1320 | 
| 1240   @override | 1321   @override | 
| 1241   void attached() { | 1322   void attached() { | 
| 1242     super.attached(); | 1323     super.attached(); | 
| 1243 | 1324 | 
| 1244     var navbarDiv = $['navbarDiv']; | 1325     var navbarDiv = $['navbarDiv']; | 
| 1245     var stackDiv = $['stackDiv']; | 1326     var stackDiv = $['stackDiv']; | 
| 1246     var splitterDiv = $['splitterDiv']; | 1327     var splitterDiv = $['splitterDiv']; | 
| 1247     var cmdDiv = $['commandDiv']; | 1328     var cmdDiv = $['commandDiv']; | 
| 1248 | 1329 | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 1262     stackElement.debugger = debugger; | 1343     stackElement.debugger = debugger; | 
| 1263     debugger.console = $['console']; | 1344     debugger.console = $['console']; | 
| 1264     debugger.input = $['commandline']; | 1345     debugger.input = $['commandline']; | 
| 1265     debugger.input.debugger = debugger; | 1346     debugger.input.debugger = debugger; | 
| 1266     debugger.init(); | 1347     debugger.init(); | 
| 1267 | 1348 | 
| 1268     _isolateSubscriptionFuture = | 1349     _isolateSubscriptionFuture = | 
| 1269         app.vm.listenEventStream(VM.kIsolateStream, debugger.onEvent); | 1350         app.vm.listenEventStream(VM.kIsolateStream, debugger.onEvent); | 
| 1270     _debugSubscriptionFuture = | 1351     _debugSubscriptionFuture = | 
| 1271         app.vm.listenEventStream(VM.kDebugStream, debugger.onEvent); | 1352         app.vm.listenEventStream(VM.kDebugStream, debugger.onEvent); | 
|  | 1353     _stdoutSubscriptionFuture = | 
|  | 1354         app.vm.listenEventStream(VM.kStdoutStream, debugger.onStdout); | 
|  | 1355     _stderrSubscriptionFuture = | 
|  | 1356         app.vm.listenEventStream(VM.kStderrStream, debugger.onStderr); | 
|  | 1357 | 
|  | 1358     // Turn on the periodic poll timer for this page. | 
|  | 1359     pollPeriod = const Duration(milliseconds:100); | 
| 1272 | 1360 | 
| 1273     onClick.listen((event) { | 1361     onClick.listen((event) { | 
| 1274       // Random clicks should focus on the text box.  If the user selects | 1362       // Random clicks should focus on the text box.  If the user selects | 
| 1275       // a range, don't interfere. | 1363       // a range, don't interfere. | 
| 1276       var selection = window.getSelection(); | 1364       var selection = window.getSelection(); | 
| 1277       if (selection == null || selection.type == 'Caret') { | 1365       if (selection == null || selection.type == 'Caret') { | 
| 1278         debugger.input.focus(); | 1366         debugger.input.focus(); | 
| 1279       } | 1367       } | 
| 1280     }); | 1368     }); | 
| 1281   } | 1369   } | 
| 1282 | 1370 | 
|  | 1371   void onPoll() { | 
|  | 1372     debugger.flushStdio(); | 
|  | 1373   } | 
|  | 1374 | 
| 1283   @override | 1375   @override | 
| 1284   void detached() { | 1376   void detached() { | 
| 1285     cancelFutureSubscription(_isolateSubscriptionFuture); | 1377     cancelFutureSubscription(_isolateSubscriptionFuture); | 
| 1286     _isolateSubscriptionFuture = null; | 1378     _isolateSubscriptionFuture = null; | 
| 1287     cancelFutureSubscription(_debugSubscriptionFuture); | 1379     cancelFutureSubscription(_debugSubscriptionFuture); | 
| 1288     _debugSubscriptionFuture = null; | 1380     _debugSubscriptionFuture = null; | 
|  | 1381     cancelFutureSubscription(_stdoutSubscriptionFuture); | 
|  | 1382     _stdoutSubscriptionFuture = null; | 
|  | 1383     cancelFutureSubscription(_stderrSubscriptionFuture); | 
|  | 1384     _stderrSubscriptionFuture = null; | 
| 1289     super.detached(); | 1385     super.detached(); | 
| 1290   } | 1386   } | 
| 1291 } | 1387 } | 
| 1292 | 1388 | 
| 1293 @CustomTag('debugger-stack') | 1389 @CustomTag('debugger-stack') | 
| 1294 class DebuggerStackElement extends ObservatoryElement { | 1390 class DebuggerStackElement extends ObservatoryElement { | 
| 1295   @published Isolate isolate; | 1391   @published Isolate isolate; | 
| 1296   @observable bool hasStack = false; | 1392   @observable bool hasStack = false; | 
| 1297   @observable bool hasMessages = false; | 1393   @observable bool hasMessages = false; | 
| 1298   @observable bool isSampled = false; | 1394   @observable bool isSampled = false; | 
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1658     var span = new SpanElement(); | 1754     var span = new SpanElement(); | 
| 1659     span.classes.add('red'); | 1755     span.classes.add('red'); | 
| 1660     span.appendText(line); | 1756     span.appendText(line); | 
| 1661     if (newline) { | 1757     if (newline) { | 
| 1662       span.appendText('\n'); | 1758       span.appendText('\n'); | 
| 1663     } | 1759     } | 
| 1664     $['consoleText'].children.add(span); | 1760     $['consoleText'].children.add(span); | 
| 1665     span.scrollIntoView(); | 1761     span.scrollIntoView(); | 
| 1666   } | 1762   } | 
| 1667 | 1763 | 
|  | 1764   void printStdio(List<String> lines) { | 
|  | 1765     var lastSpan; | 
|  | 1766     for (var line in lines) { | 
|  | 1767       var span = new SpanElement(); | 
|  | 1768       span.classes.add('green'); | 
|  | 1769       span.appendText(line); | 
|  | 1770       span.appendText('\n'); | 
|  | 1771       $['consoleText'].children.add(span); | 
|  | 1772       lastSpan = span; | 
|  | 1773     } | 
|  | 1774     if (lastSpan != null) { | 
|  | 1775       lastSpan.scrollIntoView(); | 
|  | 1776     } | 
|  | 1777   } | 
|  | 1778 | 
| 1668   void printRef(Instance ref, { bool newline:true }) { | 1779   void printRef(Instance ref, { bool newline:true }) { | 
| 1669     var refElement = new Element.tag('instance-ref'); | 1780     var refElement = new Element.tag('instance-ref'); | 
| 1670     refElement.ref = ref; | 1781     refElement.ref = ref; | 
| 1671     $['consoleText'].children.add(refElement); | 1782     $['consoleText'].children.add(refElement); | 
| 1672     if (newline) { | 1783     if (newline) { | 
| 1673       this.newline(); | 1784       this.newline(); | 
| 1674     } | 1785     } | 
| 1675     refElement.scrollIntoView(); | 1786     refElement.scrollIntoView(); | 
| 1676   } | 1787   } | 
| 1677 | 1788 | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1740       }); | 1851       }); | 
| 1741   } | 1852   } | 
| 1742 | 1853 | 
| 1743   void focus() { | 1854   void focus() { | 
| 1744     $['textBox'].focus(); | 1855     $['textBox'].focus(); | 
| 1745   } | 1856   } | 
| 1746 | 1857 | 
| 1747   DebuggerInputElement.created() : super.created(); | 1858   DebuggerInputElement.created() : super.created(); | 
| 1748 } | 1859 } | 
| 1749 | 1860 | 
| OLD | NEW | 
|---|