Chromium Code Reviews| 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/app.dart'; | |
| 10 import 'package:observatory/cli.dart'; | 11 import 'package:observatory/cli.dart'; |
| 11 import 'package:observatory/debugger.dart'; | 12 import 'package:observatory/debugger.dart'; |
| 12 import 'package:observatory/service.dart'; | 13 import 'package:observatory/service.dart'; |
| 13 import 'package:logging/logging.dart'; | 14 import 'package:logging/logging.dart'; |
| 14 import 'package:polymer/polymer.dart'; | 15 import 'package:polymer/polymer.dart'; |
| 15 | 16 |
| 16 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library. | 17 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library. |
| 17 abstract class DebuggerCommand extends Command { | 18 abstract class DebuggerCommand extends Command { |
| 18 ObservatoryDebugger debugger; | 19 ObservatoryDebugger debugger; |
| 19 | 20 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 count = int.parse(args[0]); | 184 count = int.parse(args[0]); |
| 184 } else if (args.length > 1) { | 185 } else if (args.length > 1) { |
| 185 debugger.console.print('down expects 0 or 1 argument'); | 186 debugger.console.print('down expects 0 or 1 argument'); |
| 186 return new Future.value(null); | 187 return new Future.value(null); |
| 187 } | 188 } |
| 188 if (debugger.currentFrame == null) { | 189 if (debugger.currentFrame == null) { |
| 189 debugger.console.print('No stack'); | 190 debugger.console.print('No stack'); |
| 190 return new Future.value(null); | 191 return new Future.value(null); |
| 191 } | 192 } |
| 192 try { | 193 try { |
| 193 debugger.currentFrame += count; | 194 debugger.downFrame(count); |
| 194 debugger.console.print('frame = ${debugger.currentFrame}'); | 195 debugger.console.print('frame = ${debugger.currentFrame}'); |
| 195 } catch (e) { | 196 } catch (e) { |
| 196 debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); | 197 debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); |
| 197 } | 198 } |
| 198 return new Future.value(null); | 199 return new Future.value(null); |
| 199 } | 200 } |
| 200 | 201 |
| 201 String helpShort = 'Move down one or more frames (hotkey: [Page Down])'; | 202 String helpShort = 'Move down one or more frames (hotkey: [Page Down])'; |
| 202 | 203 |
| 203 String helpLong = | 204 String helpLong = |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 218 count = int.parse(args[0]); | 219 count = int.parse(args[0]); |
| 219 } else if (args.length > 1) { | 220 } else if (args.length > 1) { |
| 220 debugger.console.print('up expects 0 or 1 argument'); | 221 debugger.console.print('up expects 0 or 1 argument'); |
| 221 return new Future.value(null); | 222 return new Future.value(null); |
| 222 } | 223 } |
| 223 if (debugger.currentFrame == null) { | 224 if (debugger.currentFrame == null) { |
| 224 debugger.console.print('No stack'); | 225 debugger.console.print('No stack'); |
| 225 return new Future.value(null); | 226 return new Future.value(null); |
| 226 } | 227 } |
| 227 try { | 228 try { |
| 228 debugger.currentFrame -= count; | 229 debugger.upFrame(count); |
| 229 debugger.console.print('frame = ${debugger.currentFrame}'); | 230 debugger.console.print('frame = ${debugger.currentFrame}'); |
| 230 } on RangeError catch (e) { | 231 } on RangeError catch (e) { |
| 231 debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); | 232 debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); |
| 232 } | 233 } |
| 233 return new Future.value(null); | 234 return new Future.value(null); |
| 234 } | 235 } |
| 235 | 236 |
| 236 String helpShort = 'Move up one or more frames (hotkey: [Page Up])'; | 237 String helpShort = 'Move up one or more frames (hotkey: [Page Up])'; |
| 237 | 238 |
| 238 String helpLong = | 239 String helpLong = |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 String helpLong = | 490 String helpLong = |
| 490 'Continue running the isolate until the current function exits.\n' | 491 'Continue running the isolate until the current function exits.\n' |
| 491 '\n' | 492 '\n' |
| 492 'Syntax: finish\n'; | 493 'Syntax: finish\n'; |
| 493 } | 494 } |
| 494 | 495 |
| 495 class SetCommand extends DebuggerCommand { | 496 class SetCommand extends DebuggerCommand { |
| 496 SetCommand(Debugger debugger) | 497 SetCommand(Debugger debugger) |
| 497 : super(debugger, 'set', []); | 498 : super(debugger, 'set', []); |
| 498 | 499 |
| 500 static var _boeValues = ['all', 'none', 'unhandled']; | |
| 501 static var _boolValues = ['false', 'true']; | |
| 502 | |
| 503 static var _options = { | |
| 504 'break-on-exception': [_boeValues, | |
| 505 _setBreakOnException, | |
| 506 (debugger, _) => debugger.breakOnException], | |
| 507 'up-is-down': [_boolValues, | |
| 508 _setUpIsDown, | |
| 509 (debugger, _) => debugger.upIsDown], | |
| 510 }; | |
| 511 | |
| 512 static Future _setBreakOnException(debugger, name, value) async { | |
| 513 var result = await debugger.isolate.setExceptionPauseInfo(value); | |
| 514 if (result.isError) { | |
| 515 debugger.console.print(result.toString()); | |
| 516 } else { | |
| 517 // Printing will occur elsewhere. | |
| 518 debugger.breakOnException = value; | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 static Future _setUpIsDown(debugger, name, value) async { | |
| 523 if (value == 'true') { | |
| 524 debugger.upIsDown = true; | |
| 525 } else { | |
| 526 debugger.upIsDown = false; | |
| 527 } | |
| 528 debugger.console.print('${name} = ${value}'); | |
| 529 } | |
| 530 | |
| 499 Future run(List<String> args) async { | 531 Future run(List<String> args) async { |
| 532 if (args.length == 0) { | |
| 533 for (var name in _options.keys) { | |
| 534 var getHandler = _options[name][2]; | |
| 535 var value = await getHandler(debugger, name); | |
| 536 debugger.console.print("${name} = ${value}"); | |
| 537 } | |
| 538 } else if (args.length == 1) { | |
| 539 var name = args[0].trim(); | |
| 540 var optionInfo = _options[name]; | |
| 541 if (optionInfo == null) { | |
| 542 debugger.console.print("unrecognized option: $name"); | |
| 543 return; | |
| 544 } else { | |
| 545 var getHandler = optionInfo[2]; | |
| 546 var value = await getHandler(debugger, name); | |
| 547 debugger.console.print("${name} = ${value}"); | |
| 548 } | |
| 549 } else if (args.length == 2) { | |
| 550 var name = args[0].trim(); | |
| 551 var value = args[1].trim(); | |
| 552 var optionInfo = _options[name]; | |
| 553 if (optionInfo == null) { | |
| 554 debugger.console.print("unrecognized option: $name"); | |
| 555 return; | |
| 556 } | |
| 557 var validValues = optionInfo[0]; | |
| 558 if (!validValues.contains(value)) { | |
| 559 debugger.console.print("'${value}' is not in ${validValues}"); | |
| 560 return; | |
| 561 } | |
| 562 var setHandler = optionInfo[1]; | |
| 563 await setHandler(debugger, name, value); | |
| 564 } else { | |
| 565 debugger.console.print("set expects 0, 1, or 2 arguments"); | |
| 566 } | |
| 567 } | |
| 568 | |
| 569 Future<List<String>> complete(List<String> args) { | |
| 570 if (args.length < 1 || args.length > 2) { | |
| 571 return new Future.value([args.join('')]); | |
| 572 } | |
| 573 var result = []; | |
| 574 if (args.length == 1) { | |
| 575 var prefix = args[0]; | |
| 576 for (var option in _options.keys) { | |
| 577 if (option.startsWith(prefix)) { | |
| 578 result.add('${option} '); | |
| 579 } | |
| 580 } | |
| 581 } | |
| 500 if (args.length == 2) { | 582 if (args.length == 2) { |
| 501 var option = args[0].trim(); | 583 var name = args[0].trim(); |
| 502 if (option == 'break-on-exceptions') { | 584 var prefix = args[1]; |
| 503 var result = await debugger.isolate.setExceptionPauseInfo(args[1]); | 585 var optionInfo = _options[name]; |
| 504 if (result.isError) { | 586 if (optionInfo != null) { |
| 505 debugger.console.print(result.toString()); | 587 var validValues = optionInfo[0]; |
| 588 for (var value in validValues) { | |
| 589 if (value.startsWith(prefix)) { | |
| 590 result.add('${args[0]}${value} '); | |
| 591 } | |
| 506 } | 592 } |
| 507 } else { | |
| 508 debugger.console.print("unknown option '$option'"); | |
| 509 } | 593 } |
| 510 } else { | |
| 511 debugger.console.print("set expects 2 arguments"); | |
| 512 } | 594 } |
| 595 return new Future.value(result); | |
| 513 } | 596 } |
| 514 | 597 |
| 515 String helpShort = | 598 String helpShort = |
| 516 'Set a debugger option'; | 599 'Set a debugger option'; |
| 517 | 600 |
| 518 String helpLong = | 601 String helpLong = |
| 519 'Set a debugger option' | 602 'Set a debugger option.\n' |
| 520 '\n' | 603 '\n' |
| 521 'Syntax: set break-on-exceptions "all" | "none" | "unhandled"\n'; | 604 'Known options:\n' |
| 605 ' break-on-exceptions # Should the debugger break on exceptions?\n' | |
| 606 " # {'all', 'none', 'unhandled'}\n" | |
|
Cutch
2015/08/07 19:55:10
can you do string interpolation here and below?
e
turnidge
2015/08/07 20:16:42
Done.
| |
| 607 ' up-is-down # Reverse meaning of up/down commands?\n' | |
| 608 " # {'false', 'true''}\n" | |
| 609 '\n' | |
| 610 'Syntax: set # Display all option settings\n' | |
| 611 ' set <option> # Get current value for option\n' | |
| 612 ' set <option> <value> # Set value for option'; | |
| 522 } | 613 } |
| 523 | 614 |
| 524 class BreakCommand extends DebuggerCommand { | 615 class BreakCommand extends DebuggerCommand { |
| 525 BreakCommand(Debugger debugger) : super(debugger, 'break', []); | 616 BreakCommand(Debugger debugger) : super(debugger, 'break', []); |
| 526 | 617 |
| 527 Future run(List<String> args) async { | 618 Future run(List<String> args) async { |
| 528 if (args.length > 1) { | 619 if (args.length > 1) { |
| 529 debugger.console.print('not implemented'); | 620 debugger.console.print('not implemented'); |
| 530 return new Future.value(null); | 621 return new Future.value(null); |
| 531 } | 622 } |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 } | 1138 } |
| 1048 } | 1139 } |
| 1049 | 1140 |
| 1050 String _format(String isolateName, String streamName, String line) { | 1141 String _format(String isolateName, String streamName, String line) { |
| 1051 return '${isolateName}:${streamName}> ${line}'; | 1142 return '${isolateName}:${streamName}> ${line}'; |
| 1052 } | 1143 } |
| 1053 } | 1144 } |
| 1054 | 1145 |
| 1055 // Tracks the state for an isolate debugging session. | 1146 // Tracks the state for an isolate debugging session. |
| 1056 class ObservatoryDebugger extends Debugger { | 1147 class ObservatoryDebugger extends Debugger { |
| 1148 SettingsGroup settings = new SettingsGroup('debugger'); | |
|
Cutch
2015/08/07 19:55:10
nit: add final
turnidge
2015/08/07 20:16:42
Done.
| |
| 1057 RootCommand cmd; | 1149 RootCommand cmd; |
| 1058 DebuggerPageElement page; | 1150 DebuggerPageElement page; |
| 1059 DebuggerConsoleElement console; | 1151 DebuggerConsoleElement console; |
| 1060 DebuggerInputElement input; | 1152 DebuggerInputElement input; |
| 1061 DebuggerStackElement stackElement; | 1153 DebuggerStackElement stackElement; |
| 1062 ServiceMap stack; | 1154 ServiceMap stack; |
| 1063 String exceptions = "none"; // Last known setting. | 1155 String breakOnException = "none"; // Last known setting. |
| 1064 | 1156 |
| 1065 int get currentFrame => _currentFrame; | 1157 int get currentFrame => _currentFrame; |
| 1158 | |
| 1066 void set currentFrame(int value) { | 1159 void set currentFrame(int value) { |
| 1067 if (value != null && (value < 0 || value >= stackDepth)) { | 1160 if (value != null && (value < 0 || value >= stackDepth)) { |
| 1068 throw new RangeError.range(value, 0, stackDepth); | 1161 throw new RangeError.range(value, 0, stackDepth); |
| 1069 } | 1162 } |
| 1070 _currentFrame = value; | 1163 _currentFrame = value; |
| 1071 if (stackElement != null) { | 1164 if (stackElement != null) { |
| 1072 stackElement.setCurrentFrame(value); | 1165 stackElement.setCurrentFrame(value); |
| 1073 } | 1166 } |
| 1074 } | 1167 } |
| 1075 int _currentFrame = null; | 1168 int _currentFrame = null; |
| 1076 | 1169 |
| 1170 bool get upIsDown => _upIsDown; | |
| 1171 void set upIsDown(bool value) { | |
| 1172 settings.set('up-is-down', value); | |
| 1173 _upIsDown = value; | |
| 1174 } | |
| 1175 bool _upIsDown; | |
| 1176 | |
| 1177 void upFrame(int count) { | |
| 1178 if (_upIsDown) { | |
| 1179 currentFrame += count; | |
| 1180 } else { | |
| 1181 currentFrame -= count; | |
| 1182 } | |
| 1183 } | |
| 1184 | |
| 1185 void downFrame(int count) { | |
| 1186 if (_upIsDown) { | |
| 1187 currentFrame -= count; | |
| 1188 } else { | |
| 1189 currentFrame += count; | |
| 1190 } | |
| 1191 } | |
| 1192 | |
| 1077 int get stackDepth => stack['frames'].length; | 1193 int get stackDepth => stack['frames'].length; |
| 1078 | 1194 |
| 1079 ObservatoryDebugger() { | 1195 ObservatoryDebugger() { |
| 1196 _upIsDown = settings.get('up-is-down'); | |
|
Cutch
2015/08/07 19:55:10
maybe factor this into a helper:
_loadSettings();
turnidge
2015/08/07 20:16:42
Done.
| |
| 1080 cmd = new RootCommand([ | 1197 cmd = new RootCommand([ |
| 1081 new HelpCommand(this), | 1198 new HelpCommand(this), |
| 1082 new PrintCommand(this), | 1199 new PrintCommand(this), |
| 1083 new DownCommand(this), | 1200 new DownCommand(this), |
| 1084 new UpCommand(this), | 1201 new UpCommand(this), |
| 1085 new FrameCommand(this), | 1202 new FrameCommand(this), |
| 1086 new PauseCommand(this), | 1203 new PauseCommand(this), |
| 1087 new ContinueCommand(this), | 1204 new ContinueCommand(this), |
| 1088 new NextCommand(this), | 1205 new NextCommand(this), |
| 1089 new StepCommand(this), | 1206 new StepCommand(this), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1100 new ClsCommand(this), | 1217 new ClsCommand(this), |
| 1101 ]); | 1218 ]); |
| 1102 _consolePrinter = new _ConsoleStreamPrinter(this); | 1219 _consolePrinter = new _ConsoleStreamPrinter(this); |
| 1103 } | 1220 } |
| 1104 | 1221 |
| 1105 VM get vm => page.app.vm; | 1222 VM get vm => page.app.vm; |
| 1106 | 1223 |
| 1107 void updateIsolate(Isolate iso) { | 1224 void updateIsolate(Isolate iso) { |
| 1108 _isolate = iso; | 1225 _isolate = iso; |
| 1109 if (_isolate != null) { | 1226 if (_isolate != null) { |
| 1110 if ((exceptions != iso.exceptionsPauseInfo) && | 1227 if ((breakOnException != iso.exceptionsPauseInfo) && |
| 1111 (iso.exceptionsPauseInfo != null)) { | 1228 (iso.exceptionsPauseInfo != null)) { |
| 1112 exceptions = iso.exceptionsPauseInfo; | 1229 breakOnException = iso.exceptionsPauseInfo; |
| 1113 console.print("Now pausing for $exceptions exceptions"); | 1230 console.print("Now pausing for exceptions: $breakOnException"); |
| 1114 } | 1231 } |
| 1115 | 1232 |
| 1116 _isolate.reload().then((response) { | 1233 _isolate.reload().then((response) { |
| 1117 // TODO(turnidge): Currently the debugger relies on all libs | 1234 // TODO(turnidge): Currently the debugger relies on all libs |
| 1118 // being loaded. Fix this. | 1235 // being loaded. Fix this. |
| 1119 var pending = []; | 1236 var pending = []; |
| 1120 for (var lib in _isolate.libraries) { | 1237 for (var lib in _isolate.libraries) { |
| 1121 if (!lib.loaded) { | 1238 if (!lib.loaded) { |
| 1122 pending.add(lib.load()); | 1239 pending.add(lib.load()); |
| 1123 } | 1240 } |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1298 if (iso == isolate) { | 1415 if (iso == isolate) { |
| 1299 console.print("The current isolate has exited"); | 1416 console.print("The current isolate has exited"); |
| 1300 } else { | 1417 } else { |
| 1301 console.print( | 1418 console.print( |
| 1302 "Isolate ${iso.number} '${iso.name}' has exited"); | 1419 "Isolate ${iso.number} '${iso.name}' has exited"); |
| 1303 } | 1420 } |
| 1304 } | 1421 } |
| 1305 break; | 1422 break; |
| 1306 | 1423 |
| 1307 case ServiceEvent.kDebuggerSettingsUpdate: | 1424 case ServiceEvent.kDebuggerSettingsUpdate: |
| 1308 if (exceptions != event.exceptions) { | 1425 if (breakOnException != event.exceptions) { |
| 1309 exceptions = event.exceptions; | 1426 breakOnException = event.exceptions; |
|
Cutch
2015/08/07 19:55:10
Should this update the setting?
turnidge
2015/08/07 20:16:42
Discussed offline -- this is all we need to do, bu
| |
| 1310 console.print("Now pausing for $exceptions exceptions"); | 1427 console.print("Now pausing for exceptions: $breakOnException"); |
| 1311 } | 1428 } |
| 1312 break; | 1429 break; |
| 1313 | 1430 |
| 1314 case ServiceEvent.kIsolateUpdate: | 1431 case ServiceEvent.kIsolateUpdate: |
| 1315 var iso = event.owner; | 1432 var iso = event.owner; |
| 1316 console.print("Isolate ${iso.number} renamed to '${iso.name}'"); | 1433 console.print("Isolate ${iso.number} renamed to '${iso.name}'"); |
| 1317 break; | 1434 break; |
| 1318 | 1435 |
| 1319 case ServiceEvent.kPauseStart: | 1436 case ServiceEvent.kPauseStart: |
| 1320 case ServiceEvent.kPauseExit: | 1437 case ServiceEvent.kPauseExit: |
| (...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2108 | 2225 |
| 2109 case KeyCode.DOWN: | 2226 case KeyCode.DOWN: |
| 2110 e.preventDefault(); | 2227 e.preventDefault(); |
| 2111 text = debugger.historyNext(text); | 2228 text = debugger.historyNext(text); |
| 2112 busy = false; | 2229 busy = false; |
| 2113 break; | 2230 break; |
| 2114 | 2231 |
| 2115 case KeyCode.PAGE_UP: | 2232 case KeyCode.PAGE_UP: |
| 2116 e.preventDefault(); | 2233 e.preventDefault(); |
| 2117 try { | 2234 try { |
| 2118 debugger.currentFrame -= 1; | 2235 debugger.upFrame(1); |
| 2119 } on RangeError catch (e) { | 2236 } on RangeError catch (e) { |
| 2120 // Ignore. | 2237 // Ignore. |
| 2121 } | 2238 } |
| 2122 busy = false; | 2239 busy = false; |
| 2123 break; | 2240 break; |
| 2124 | 2241 |
| 2125 case KeyCode.PAGE_DOWN: | 2242 case KeyCode.PAGE_DOWN: |
| 2126 e.preventDefault(); | 2243 e.preventDefault(); |
| 2127 try { | 2244 try { |
| 2128 debugger.currentFrame += 1; | 2245 debugger.downFrame(1); |
| 2129 } on RangeError catch (e) { | 2246 } on RangeError catch (e) { |
| 2130 // Ignore. | 2247 // Ignore. |
| 2131 } | 2248 } |
| 2132 busy = false; | 2249 busy = false; |
| 2133 break; | 2250 break; |
| 2134 | 2251 |
| 2135 case KeyCode.F7: | 2252 case KeyCode.F7: |
| 2136 e.preventDefault(); | 2253 e.preventDefault(); |
| 2137 debugger.resume().whenComplete(() { | 2254 debugger.resume().whenComplete(() { |
| 2138 busy = false; | 2255 busy = false; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2178 } | 2295 } |
| 2179 }); | 2296 }); |
| 2180 } | 2297 } |
| 2181 | 2298 |
| 2182 void focus() { | 2299 void focus() { |
| 2183 $['textBox'].focus(); | 2300 $['textBox'].focus(); |
| 2184 } | 2301 } |
| 2185 | 2302 |
| 2186 DebuggerInputElement.created() : super.created(); | 2303 DebuggerInputElement.created() : super.created(); |
| 2187 } | 2304 } |
| OLD | NEW |