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

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

Issue 918003002: Add 'break' and 'clear' commands to Observatory debugger. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 5 years, 10 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';
11 import 'package:observatory/debugger.dart';
11 import 'package:observatory/service.dart'; 12 import 'package:observatory/service.dart';
12 import 'package:polymer/polymer.dart'; 13 import 'package:polymer/polymer.dart';
13 14
14 // TODO(turnidge): Move Debugger, DebuggerCommand to their own lib. 15 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library.
15 abstract class DebuggerCommand extends Command { 16 abstract class DebuggerCommand extends Command {
16 Debugger debugger; 17 ObservatoryDebugger debugger;
17 18
18 DebuggerCommand(this.debugger, name, children) 19 DebuggerCommand(this.debugger, name, children)
19 : super(name, children); 20 : super(name, children);
20 } 21 }
21 22
22 class HelpCommand extends DebuggerCommand { 23 class HelpCommand extends DebuggerCommand {
23 HelpCommand(Debugger debugger) : super(debugger, 'help', []); 24 HelpCommand(Debugger debugger) : super(debugger, 'help', []);
24 25
25 Future run(List<String> args) { 26 Future run(List<String> args) {
26 var con = debugger.console; 27 var con = debugger.console;
27 con.printLine('List of commands:'); 28 con.printLine('List of commands:');
28 con.newline(); 29 con.newline();
29 30
30 // TODO(turnidge): Build a real help system. 31 // TODO(turnidge): Build a real help system.
31 List completions = debugger.cmd.completeCommand(''); 32 return debugger.cmd.completeCommand('').then((completions) {
32 completions = completions.map((s )=> s.trimRight()).toList(); 33 completions = completions.map((s) => s.trimRight()).toList();
33 completions.sort(); 34 completions.sort();
34 con.printLine(completions.toString()); 35 con.printLine(completions.toString());
35 con.newline(); 36 con.newline();
36 con.printLine("Command prefixes are accepted (e.g. 'h' for 'help')"); 37 con.printLine("Command prefixes are accepted (e.g. 'h' for 'help')");
37 con.printLine("Hit [TAB] to complete a command (try 'i[TAB][TAB]')"); 38 con.printLine("Hit [TAB] to complete a command (try 'i[TAB][TAB]')");
38 con.printLine("Hit [ENTER] to repeat the last command"); 39 con.printLine("Hit [ENTER] to repeat the last command");
39 40 });
40 return new Future.value(null);
41 } 41 }
42 } 42 }
43 43
44 class PauseCommand extends DebuggerCommand { 44 class PauseCommand extends DebuggerCommand {
45 PauseCommand(Debugger debugger) : super(debugger, 'pause', []); 45 PauseCommand(Debugger debugger) : super(debugger, 'pause', []);
46 46
47 Future run(List<String> args) { 47 Future run(List<String> args) {
48 if (!debugger.isolatePaused()) { 48 if (!debugger.isolatePaused()) {
49 return debugger.isolate.pause(); 49 return debugger.isolate.pause();
50 } else { 50 } else {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 Future run(List<String> args) { 119 Future run(List<String> args) {
120 if (debugger.isolatePaused()) { 120 if (debugger.isolatePaused()) {
121 return debugger.isolate.stepOut(); 121 return debugger.isolate.stepOut();
122 } else { 122 } else {
123 debugger.console.printLine('The program is already running'); 123 debugger.console.printLine('The program is already running');
124 return new Future.value(null); 124 return new Future.value(null);
125 } 125 }
126 } 126 }
127 } 127 }
128 128
129 class BreakCommand extends DebuggerCommand {
130 BreakCommand(Debugger debugger) : super(debugger, 'break', []);
131
132 Future run(List<String> args) {
133 if (args.length > 1) {
134 debugger.console.printLine('not implemented');
135 return new Future.value(null);
136 }
137 var arg = (args.length == 0 ? '' : args[0]);
138 return SourceLocation.parse(debugger, arg).then((loc) {
139 if (loc.valid) {
140 if (loc.function != null) {
141 debugger.console.printLine(
142 'Ignoring breakpoint at $loc: '
143 'Function entry breakpoints not yet implemented');
144 return null;
145 }
146 if (loc.col != null) {
147 // TODO(turnidge): Add tokenPos breakpoint support.
148 debugger.console.printLine(
149 'Ignoring column: '
150 'adding breakpoint at a specific column not yet implemented');
151 }
152 return debugger.isolate.addBreakpoint(loc.script, loc.line).then((result ) {
153 if (result is DartError) {
154 debugger.console.printLine('Unable to set breakpoint at ${loc}');
155 } else {
156 // TODO(turnidge): Adding a duplicate breakpoint is
157 // currently ignored. May want to change the protocol to
158 // inform us when this happens.
159
160 // The BreakpointResolved event prints resolved
161 // breakpoints already. Just print the unresolved ones here.
162 ServiceMap bpt = result;
163 if (!bpt['resolved']) {
164 var script = bpt['location']['script'];
165 var bpId = bpt['breakpointNumber'];
166 var tokenPos = bpt['location']['tokenPos'];
167 return script.load().then((_) {
168 var line = script.tokenToLine(tokenPos);
169 var col = script.tokenToCol(tokenPos);
170 debugger.console.printLine(
171 'Future breakpoint ${bpId} added at '
172 '${script.name}:${line}:${col}');
173 });
174 }
175 }
176 });
177 } else {
178 debugger.console.printLine(loc.errorMessage);
179 }
180 });
181 }
182
183 Future<List<String>> complete(List<String> args) {
184 if (args.length != 1) {
185 return new Future.value([]);
186 }
187 // TODO - fix SourceLocation complete
188 return new Future.value(SourceLocation.complete(debugger, args[0]));
189 }
190 }
191
192 class ClearCommand extends DebuggerCommand {
193 ClearCommand(Debugger debugger) : super(debugger, 'clear', []);
194
195 Future run(List<String> args) {
196 if (args.length > 1) {
197 debugger.console.printLine('not implemented');
198 return new Future.value(null);
199 }
200 var arg = (args.length == 0 ? '' : args[0]);
201 return SourceLocation.parse(debugger, arg).then((loc) {
202 if (loc.valid) {
203 if (loc.function != null) {
204 debugger.console.printLine(
205 'Ignoring breakpoint at $loc: '
206 'Function entry breakpoints not yet implemented');
207 return null;
208 }
209 if (loc.col != null) {
210 // TODO(turnidge): Add tokenPos clear support.
211 debugger.console.printLine(
212 'Ignoring column: '
213 'clearing breakpoint at a specific column not yet implemented');
214 }
215
216 for (var bpt in debugger.isolate.breakpoints) {
217 var script = bpt['location']['script'];
218 if (script.id == loc.script.id) {
219 assert(script.loaded);
220 var line = script.tokenToLine(bpt['location']['tokenPos']);
221 if (line == loc.line) {
222 return debugger.isolate.removeBreakpoint(bpt).then((result) {
223 if (result is DartError) {
224 debugger.console.printLine(
225 'Unable to clear breakpoint at ${loc}: ${result.message}') ;
226 return;
227 } else {
228 // TODO(turnidge): Add a BreakpointRemoved event to
229 // the service instead of printing here.
230 var bpId = bpt['breakpointNumber'];
231 debugger.console.printLine(
232 'Breakpoint ${bpId} removed at ${loc}');
233 return;
234 }
235 });
236 }
237 }
238 }
239 debugger.console.printLine('No breakpoint found at ${loc}');
240 } else {
241 debugger.console.printLine(loc.errorMessage);
242 }
243 });
244 }
245
246 Future<List<String>> complete(List<String> args) {
247 if (args.length != 1) {
248 return new Future.value([]);
249 }
250 return new Future.value(SourceLocation.complete(debugger, args[0]));
251 }
252 }
253
129 // TODO(turnidge): Add argument completion. 254 // TODO(turnidge): Add argument completion.
130 class DeleteCommand extends DebuggerCommand { 255 class DeleteCommand extends DebuggerCommand {
131 DeleteCommand(Debugger debugger) : super(debugger, 'delete', []); 256 DeleteCommand(Debugger debugger) : super(debugger, 'delete', []);
132 257
133 Future run(List<String> args) { 258 Future run(List<String> args) {
134 if (args.length < 1) { 259 if (args.length < 1) {
135 debugger.console.printLine('delete expects one or more arguments'); 260 debugger.console.printLine('delete expects one or more arguments');
136 return new Future.value(null); 261 return new Future.value(null);
137 } 262 }
138 List toDelete = []; 263 List toDelete = [];
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 return debugger.isolate.reloadBreakpoints().then((_) { 295 return debugger.isolate.reloadBreakpoints().then((_) {
171 if (debugger.isolate.breakpoints.isEmpty) { 296 if (debugger.isolate.breakpoints.isEmpty) {
172 debugger.console.printLine('No breakpoints'); 297 debugger.console.printLine('No breakpoints');
173 } 298 }
174 for (var bpt in debugger.isolate.breakpoints) { 299 for (var bpt in debugger.isolate.breakpoints) {
175 var bpId = bpt['breakpointNumber']; 300 var bpId = bpt['breakpointNumber'];
176 var script = bpt['location']['script']; 301 var script = bpt['location']['script'];
177 var tokenPos = bpt['location']['tokenPos']; 302 var tokenPos = bpt['location']['tokenPos'];
178 var line = script.tokenToLine(tokenPos); 303 var line = script.tokenToLine(tokenPos);
179 var col = script.tokenToCol(tokenPos); 304 var col = script.tokenToCol(tokenPos);
305 var extras = new StringBuffer();
306 if (!bpt['resolved']) {
307 extras.write(' unresolved');
308 }
309 if (!bpt['enabled']) {
310 extras.write(' disabled');
311 }
180 debugger.console.printLine( 312 debugger.console.printLine(
181 'Breakpoint ${bpId} at ${script.name}:${line}:${col}'); 313 'Breakpoint ${bpId} at ${script.name}:${line}:${col}${extras}');
182 } 314 }
183 }); 315 });
184 } 316 }
185 } 317 }
186 318
187 class InfoIsolatesCommand extends DebuggerCommand { 319 class InfoIsolatesCommand extends DebuggerCommand {
188 InfoIsolatesCommand(Debugger debugger) : super(debugger, 'isolates', []); 320 InfoIsolatesCommand(Debugger debugger) : super(debugger, 'isolates', []);
189 321
190 Future run(List<String> args) { 322 Future run(List<String> args) {
191 for (var isolate in debugger.isolate.vm.isolates) { 323 for (var isolate in debugger.isolate.vm.isolates) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 RefreshCommand(Debugger debugger) : super(debugger, 'refresh', [ 359 RefreshCommand(Debugger debugger) : super(debugger, 'refresh', [
228 new RefreshCoverageCommand(debugger), 360 new RefreshCoverageCommand(debugger),
229 ]); 361 ]);
230 362
231 Future run(List<String> args) { 363 Future run(List<String> args) {
232 return debugger.refreshStack(); 364 return debugger.refreshStack();
233 } 365 }
234 } 366 }
235 367
236 // Tracks the state for an isolate debugging session. 368 // Tracks the state for an isolate debugging session.
237 class Debugger { 369 class ObservatoryDebugger extends Debugger {
238 RootCommand cmd; 370 RootCommand cmd;
239 DebuggerConsoleElement console; 371 DebuggerConsoleElement console;
240 DebuggerStackElement stackElement; 372 DebuggerStackElement stackElement;
241 ServiceMap stack; 373 ServiceMap stack;
374 int currentFrame = 0;
242 375
243 Debugger() { 376 ObservatoryDebugger() {
244 cmd = new RootCommand([ 377 cmd = new RootCommand([
245 new HelpCommand(this), 378 new HelpCommand(this),
246 new PauseCommand(this), 379 new PauseCommand(this),
247 new ContinueCommand(this), 380 new ContinueCommand(this),
248 new NextCommand(this), 381 new NextCommand(this),
249 new StepCommand(this), 382 new StepCommand(this),
250 new FinishCommand(this), 383 new FinishCommand(this),
384 new BreakCommand(this),
385 new ClearCommand(this),
251 new DeleteCommand(this), 386 new DeleteCommand(this),
252 new InfoCommand(this), 387 new InfoCommand(this),
253 new RefreshCommand(this), 388 new RefreshCommand(this),
254 ]); 389 ]);
255 } 390 }
256 391
257 void set isolate(Isolate iso) { 392 void set isolate(Isolate iso) {
258 _isolate = iso; 393 _isolate = iso;
259 if (_isolate != null) { 394 if (_isolate != null) {
260 _isolate.reload().then((_) { 395 _isolate.reload().then((_) {
261 _isolate.vm.events.stream.listen(_onEvent); 396 // TODO(turnidge): Currently the debugger relies on all libs
262 _refreshStack(isolate.pauseEvent).then((_) { 397 // being loaded. Fix this.
263 reportStatus(); 398 var pending = [];
399 for (var lib in _isolate.libraries) {
400 if (!lib.loaded) {
401 pending.add(lib.load());
402 }
403 }
404 Future.wait(pending).then((_) {
405 _isolate.vm.events.stream.listen(_onEvent);
406 _refreshStack(isolate.pauseEvent).then((_) {
407 reportStatus();
408 });
264 }); 409 });
265 }); 410 });
266 } 411 }
267 } 412 }
268 Isolate get isolate => _isolate; 413 Isolate get isolate => _isolate;
269 Isolate _isolate; 414 Isolate _isolate;
270 415
271 void init() { 416 void init() {
272 console.newline(); 417 console.newline();
273 console.printBold("Type 'h' for help"); 418 console.printBold("Type 'h' for help");
(...skipping 19 matching lines...) Expand all
293 stackElement.isSampled = true; 438 stackElement.isSampled = true;
294 } 439 }
295 }); 440 });
296 } 441 }
297 442
298 Future<ServiceMap> _refreshStack(ServiceEvent pauseEvent) { 443 Future<ServiceMap> _refreshStack(ServiceEvent pauseEvent) {
299 return isolate.getStack().then((result) { 444 return isolate.getStack().then((result) {
300 stack = result; 445 stack = result;
301 // TODO(turnidge): Replace only the changed part of the stack to 446 // TODO(turnidge): Replace only the changed part of the stack to
302 // reduce flicker. 447 // reduce flicker.
303 // stackElement.stack = stack;
304 stackElement.updateStack(stack, pauseEvent); 448 stackElement.updateStack(stack, pauseEvent);
305 }); 449 });
306 } 450 }
307 451
308 void reportStatus() { 452 void reportStatus() {
309 if (_isolate.idle) { 453 if (_isolate.idle) {
310 console.printLine('Isolate is idle'); 454 console.printLine('Isolate is idle');
311 } else if (_isolate.running) { 455 } else if (_isolate.running) {
312 console.printLine("Isolate is running (type 'pause' to interrupt)"); 456 console.printLine("Isolate is running (type 'pause' to interrupt)");
313 } else if (_isolate.pauseEvent != null) { 457 } else if (_isolate.pauseEvent != null) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 case 'ExceptionThrown': 504 case 'ExceptionThrown':
361 _refreshStack(event).then((_) { 505 _refreshStack(event).then((_) {
362 _reportPause(event); 506 _reportPause(event);
363 }); 507 });
364 break; 508 break;
365 509
366 case 'IsolateResumed': 510 case 'IsolateResumed':
367 console.printLine('Continuing...'); 511 console.printLine('Continuing...');
368 break; 512 break;
369 513
514 case 'BreakpointResolved':
515 var bpId = event.breakpoint['breakpointNumber'];
516 var script = event.breakpoint['location']['script'];
517 var tokenPos = event.breakpoint['location']['tokenPos'];
518 var line = script.tokenToLine(tokenPos);
519 var col = script.tokenToCol(tokenPos);
520 console.printLine(
521 'Breakpoint ${bpId} added at ${script.name}:${line}:${col}');
522 break;
523
370 case '_Graph': 524 case '_Graph':
371 case 'BreakpointResolved':
372 case 'IsolateCreated': 525 case 'IsolateCreated':
373 case 'GC': 526 case 'GC':
374 // Ignore these events for now. 527 // Ignore these events for now.
375 break; 528 break;
376 529
377 default: 530 default:
378 console.printLine('Unrecognized event: $event'); 531 console.printLine('Unrecognized event: $event');
379 break; 532 break;
380 } 533 }
381 } 534 }
382 535
383 String complete(String line) { 536 static String _commonPrefix(String a, String b) {
384 List<String> completions = cmd.completeCommand(line); 537 int pos = 0;
385 if (completions.length == 0) { 538 while (pos < a.length && pos < b.length) {
386 // No completions. Leave the line alone. 539 if (a.codeUnitAt(pos) != b.codeUnitAt(pos)) {
387 return line; 540 break;
388 } else if (completions.length == 1) { 541 }
389 // Unambiguous completion. 542 pos++;
390 return completions[0]; 543 }
391 } else { 544 return a.substring(0, pos);
392 // Ambigous completion. 545 }
393 completions = completions.map((s )=> s.trimRight()).toList();
394 completions.sort();
395 console.printBold(completions.toString());
396 546
397 // TODO(turnidge): Complete to common prefix of all completions. 547 static String _foldCompletions(List<String> values) {
398 return line; 548 if (values.length == 0) {
549 return '';
399 } 550 }
551 var prefix = values[0];
552 for (int i = 1; i < values.length; i++) {
553 prefix = _commonPrefix(prefix, values[i]);
554 }
555 return prefix;
556 }
557
558 Future<String> complete(String line) {
559 return cmd.completeCommand(line).then((completions) {
560 if (completions.length == 0) {
561 // No completions. Leave the line alone.
562 return line;
563 } else if (completions.length == 1) {
564 // Unambiguous completion.
565 return completions[0];
566 } else {
567 // Ambigous completion.
568 completions = completions.map((s )=> s.trimRight()).toList();
569 console.printBold(completions.toString());
570 return _foldCompletions(completions);
571 }
572 });
400 } 573 }
401 574
402 // TODO(turnidge): Implement real command line history. 575 // TODO(turnidge): Implement real command line history.
403 String lastCommand; 576 String lastCommand;
404 bool busy = false;
405 577
406 Future run(String command) { 578 Future run(String command) {
407 assert(!busy); 579 if (command == '' && lastCommand != null) {
408 busy = true;
409 if (command == '') {
410 command = lastCommand; 580 command = lastCommand;
411 } 581 }
412 lastCommand = command;
413 console.printBold('\$ $command'); 582 console.printBold('\$ $command');
414 return cmd.runCommand(command).then((_) { 583 return cmd.runCommand(command).then((_) {
415 busy = false; 584 lastCommand = command;
416 }).catchError((e) { 585 }).catchError((e) {
417 console.printLine('ERROR $e'); 586 console.printLine('ERROR $e');
418 }); 587 });
419 } 588 }
420 } 589 }
421 590
422 @CustomTag('debugger-page') 591 @CustomTag('debugger-page')
423 class DebuggerPageElement extends ObservatoryElement { 592 class DebuggerPageElement extends ObservatoryElement {
424 @published Isolate isolate; 593 @published Isolate isolate;
425 594
426 isolateChanged(oldValue) { 595 isolateChanged(oldValue) {
427 if (isolate != null) { 596 if (isolate != null) {
428 debugger.isolate = isolate; 597 debugger.isolate = isolate;
429 } 598 }
430 } 599 }
431 Debugger debugger = new Debugger(); 600 ObservatoryDebugger debugger = new ObservatoryDebugger();
432 601
433 DebuggerPageElement.created() : super.created(); 602 DebuggerPageElement.created() : super.created();
434 603
435 @override 604 @override
436 void attached() { 605 void attached() {
437 super.attached(); 606 super.attached();
438 607
439 var navbarDiv = $['navbarDiv']; 608 var navbarDiv = $['navbarDiv'];
440 var stackDiv = $['stackDiv']; 609 var stackDiv = $['stackDiv'];
441 var splitterDiv = $['splitterDiv']; 610 var splitterDiv = $['splitterDiv'];
(...skipping 19 matching lines...) Expand all
461 debugger.init(); 630 debugger.init();
462 } 631 }
463 632
464 } 633 }
465 634
466 @CustomTag('debugger-stack') 635 @CustomTag('debugger-stack')
467 class DebuggerStackElement extends ObservatoryElement { 636 class DebuggerStackElement extends ObservatoryElement {
468 @published Isolate isolate; 637 @published Isolate isolate;
469 @observable bool hasStack = false; 638 @observable bool hasStack = false;
470 @observable bool isSampled = false; 639 @observable bool isSampled = false;
471 Debugger debugger = null; 640 ObservatoryDebugger debugger;
472 641
473 _addFrame(List frameList, ObservableMap frameInfo, bool expand) { 642 _addFrame(List frameList, ObservableMap frameInfo, bool expand) {
474 DebuggerFrameElement frameElement = new Element.tag('debugger-frame'); 643 DebuggerFrameElement frameElement = new Element.tag('debugger-frame');
475 frameElement.expand = expand; 644 frameElement.expand = expand;
476 frameElement.frame = frameInfo; 645 frameElement.frame = frameInfo;
477 646
478 var li = new LIElement(); 647 var li = new LIElement();
479 li.classes.add('list-group-item'); 648 li.classes.add('list-group-item');
480 li.children.insert(0, frameElement); 649 li.children.insert(0, frameElement);
481 650
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 var br = new BRElement(); 814 var br = new BRElement();
646 $['consoleText'].children.add(br); 815 $['consoleText'].children.add(br);
647 br.scrollIntoView(); 816 br.scrollIntoView();
648 } 817 }
649 } 818 }
650 819
651 @CustomTag('debugger-input') 820 @CustomTag('debugger-input')
652 class DebuggerInputElement extends ObservatoryElement { 821 class DebuggerInputElement extends ObservatoryElement {
653 @published Isolate isolate; 822 @published Isolate isolate;
654 @published String text = ''; 823 @published String text = '';
655 @observable Debugger debugger; 824 @observable ObservatoryDebugger debugger;
825 @observable bool busy = false;
826
827 void _notBusy() {
828 busy = false;
829 }
656 830
657 @override 831 @override
658 void ready() { 832 void ready() {
659 super.ready(); 833 super.ready();
660 var textBox = $['textBox']; 834 var textBox = $['textBox'];
661 textBox.select(); 835 textBox.select();
662 textBox.onKeyDown.listen((KeyboardEvent e) { 836 textBox.onKeyDown.listen((KeyboardEvent e) {
837 // TODO(turnidge): Ignore *all* key events while busy.
663 switch (e.keyCode) { 838 switch (e.keyCode) {
664 case KeyCode.TAB: 839 case KeyCode.TAB:
665 e.preventDefault(); 840 e.preventDefault();
666 int cursorPos = textBox.selectionStart; 841 if (!busy) {
667 var completion = debugger.complete(text.substring(0, cursorPos)); 842 busy = true;
668 text = completion + text.substring(cursorPos); 843 int cursorPos = textBox.selectionStart;
669 // TODO(turnidge): Move the cursor to the end of the 844 debugger.complete(text.substring(0, cursorPos)).then((completion) {
670 // completion, rather than the end of the string. 845 text = completion + text.substring(cursorPos);
846 // TODO(turnidge): Move the cursor to the end of the
847 // completion, rather than the end of the string.
848 }).whenComplete(_notBusy);
849 }
671 break; 850 break;
672 case KeyCode.ENTER: 851 case KeyCode.ENTER:
673 if (!debugger.busy) { 852 if (!busy) {
674 debugger.run(text); 853 busy = true;
854 var command = text;
675 text = ''; 855 text = '';
856 debugger.run(command).whenComplete(_notBusy);
676 } 857 }
677 break; 858 break;
678 } 859 }
679 }); 860 });
680 } 861 }
681 862
682 DebuggerInputElement.created() : super.created(); 863 DebuggerInputElement.created() : super.created();
683 } 864 }
684 865
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/debugger/source_location.dart ('k') | runtime/observatory/lib/src/service/object.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698