OLD | NEW |
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dartino 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 library dartino.vm_session; | 5 library dartino.vm_session; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'dart:typed_data' show | 9 import 'dart:typed_data' show |
10 ByteData; | 10 ByteData; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 // TODO(sigurdm): for now only the stdio and stderr events are actually | 77 // TODO(sigurdm): for now only the stdio and stderr events are actually |
78 // notified. | 78 // notified. |
79 abstract class DebugListener { | 79 abstract class DebugListener { |
80 // Notification that a new process has started. | 80 // Notification that a new process has started. |
81 processStart(int processId) {} | 81 processStart(int processId) {} |
82 // Notification that a process is ready to run. | 82 // Notification that a process is ready to run. |
83 processRunnable(int processId) {} | 83 processRunnable(int processId) {} |
84 // Notification that a process has exited. | 84 // Notification that a process has exited. |
85 processExit(int processId) {} | 85 processExit(int processId) {} |
86 // A process has paused at start, before executing code. | 86 // A process has paused at start, before executing code. |
87 pauseStart(int processId, BackTraceFrame topframe) {} | 87 // This is sent on spawning processes. |
| 88 pauseStart(int processId) {} |
88 // An process has paused at exit, before terminating. | 89 // An process has paused at exit, before terminating. |
89 pauseExit(int processId, BackTraceFrame topframe) {} | 90 pauseExit(int processId, BackTraceFrame topFrame) {} |
90 // A process has paused at a breakpoint or due to stepping. | 91 // A process has paused at a breakpoint or due to stepping. |
91 pauseBreakpoint(int processId, BackTraceFrame topframe, int breakpointId) {} | 92 pauseBreakpoint( |
| 93 int processId, BackTraceFrame topFrame, Breakpoint breakpoint) {} |
92 // A process has paused due to interruption. | 94 // A process has paused due to interruption. |
93 pauseInterrupted(int processId, BackTraceFrame topframe) {} | 95 pauseInterrupted(int processId, BackTraceFrame topFrame) {} |
94 // A process has paused due to an exception. | 96 // A process has paused due to an exception. |
95 pauseException(int processId, BackTraceFrame topframe, RemoteObject thrown) {} | 97 pauseException(int processId, BackTraceFrame topFrame, RemoteObject thrown) {} |
96 // A process has started or resumed execution. | 98 // A process has started or resumed execution. |
97 resume(int processId) {} | 99 resume(int processId) {} |
98 // A breakpoint has been added for a process. | 100 // A breakpoint has been added for a process. |
99 breakpointAdded(int processId, Breakpoint breakpoint) {} | 101 breakpointAdded(int processId, Breakpoint breakpoint) {} |
100 // A breakpoint has been removed. | 102 // A breakpoint has been removed. |
101 breakpointRemoved(int processId, Breakpoint breakpoint) {} | 103 breakpointRemoved(int processId, Breakpoint breakpoint) {} |
102 // A garbage collection event. | 104 // A garbage collection event. |
103 gc(int processId) {} | 105 gc(int processId) {} |
104 // Notification of bytes written to stdout. | 106 // Notification of bytes written to stdout. |
105 writeStdOut(int processId, List<int> data) {} | 107 writeStdOut(int processId, List<int> data) {} |
106 // Notification of bytes written stderr. | 108 // Notification of bytes written stderr. |
107 writeStdErr(int processId, List<int> data) {} | 109 writeStdErr(int processId, List<int> data) {} |
108 // The connection to the vm was lost. | 110 // The connection to the vm was lost. |
109 lostConnection() {} | 111 lostConnection() {} |
| 112 // The debugged program is over. |
| 113 terminated() {} |
110 } | 114 } |
111 | 115 |
112 class SinkDebugListener extends DebugListener { | 116 class SinkDebugListener extends DebugListener { |
113 final Sink stdoutSink; | 117 final Sink stdoutSink; |
114 final Sink stderrSink; | 118 final Sink stderrSink; |
115 SinkDebugListener(this.stdoutSink, this.stderrSink); | 119 SinkDebugListener(this.stdoutSink, this.stderrSink); |
116 | 120 |
117 writeStdOut(int processId, List<int> data) { | 121 writeStdOut(int processId, List<int> data) { |
118 stdoutSink.add(data); | 122 stdoutSink.add(data); |
119 } | 123 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 new StreamIterator<Pair<int, ByteData>>(connection.input.transform( | 205 new StreamIterator<Pair<int, ByteData>>(connection.input.transform( |
202 new SessionCommandTransformerBuilder().build())) { | 206 new SessionCommandTransformerBuilder().build())) { |
203 connection.done.catchError((_, __) {}).then((_) { | 207 connection.done.catchError((_, __) {}).then((_) { |
204 vmState = VmState.terminated; | 208 vmState = VmState.terminated; |
205 }); | 209 }); |
206 | 210 |
207 // TODO(ajohnsen): Should only be initialized on debug()/testDebugger(). | 211 // TODO(ajohnsen): Should only be initialized on debug()/testDebugger(). |
208 debugState = new DebugState(this); | 212 debugState = new DebugState(this); |
209 } | 213 } |
210 | 214 |
| 215 void notifyListeners(void f(DebugListener listener)) { |
| 216 listeners.forEach(f); |
| 217 } |
| 218 |
211 /// Convenience around [runCommands] for running just a single command. | 219 /// Convenience around [runCommands] for running just a single command. |
212 Future<VmCommand> runCommand(VmCommand command) { | 220 Future<VmCommand> runCommand(VmCommand command) { |
213 return runCommands([command]); | 221 return runCommands([command]); |
214 } | 222 } |
215 | 223 |
216 /// Sends the given commands to a dartino-vm and reads response commands | 224 /// Sends the given commands to a dartino-vm and reads response commands |
217 /// (if necessary). | 225 /// (if necessary). |
218 /// | 226 /// |
219 /// If all commands have been successfully applied and responses been awaited, | 227 /// If all commands have been successfully applied and responses been awaited, |
220 /// this function will complete with the last received [VmCommand] from the | 228 /// this function will complete with the last received [VmCommand] from the |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 | 276 |
269 Pair<int, ByteData> c = _commandIterator.current; | 277 Pair<int, ByteData> c = _commandIterator.current; |
270 | 278 |
271 if (c == null) return null; | 279 if (c == null) return null; |
272 | 280 |
273 VmCommand command = new VmCommand.fromBuffer( | 281 VmCommand command = new VmCommand.fromBuffer( |
274 VmCommandCode.values[c.fst], toUint8ListView(c.snd), | 282 VmCommandCode.values[c.fst], toUint8ListView(c.snd), |
275 translateFunctionMessage, | 283 translateFunctionMessage, |
276 translateClassMessage); | 284 translateClassMessage); |
277 if (command is StdoutData) { | 285 if (command is StdoutData) { |
278 listeners.forEach((DebugListener listener) { | 286 notifyListeners((DebugListener listener) { |
279 listener.writeStdOut(0, command.value); | 287 listener.writeStdOut(0, command.value); |
280 }); | 288 }); |
281 } else if (command is StderrData) { | 289 } else if (command is StderrData) { |
282 listeners.forEach((DebugListener listener) { | 290 notifyListeners((DebugListener listener) { |
283 listener.writeStdErr(0, command.value); | 291 listener.writeStdErr(0, command.value); |
284 }); | 292 }); |
285 } else { | 293 } else { |
286 result = command; | 294 result = command; |
287 } | 295 } |
288 | 296 |
289 } | 297 } |
290 return result; | 298 return result; |
291 } | 299 } |
292 | 300 |
293 /// Closes the connection to the dartino-vm and drains the remaining response | 301 /// Closes the connection to the dartino-vm and drains the remaining response |
294 /// commands. | 302 /// commands. |
295 /// | 303 /// |
296 /// If [ignoreExtraCommands] is `false` it will throw a StateError if the | 304 /// If [ignoreExtraCommands] is `false` it will throw a StateError if the |
297 /// dartino-vm sent any commands. | 305 /// dartino-vm sent any commands. |
298 Future shutdown({bool ignoreExtraCommands: false}) async { | 306 Future shutdown({bool ignoreExtraCommands: false}) async { |
299 await connection.close().catchError((_) {}); | 307 await connection.close().catchError((_) {}); |
300 | 308 |
301 while (!_drainedIncomingCommands) { | 309 while (!_drainedIncomingCommands) { |
302 VmCommand response = await readNextCommand(force: false); | 310 VmCommand response = await readNextCommand(force: false); |
303 if (!ignoreExtraCommands && response != null) { | 311 if (!ignoreExtraCommands && response != null) { |
304 await kill(); | 312 await kill(); |
305 throw new StateError( | 313 throw new StateError( |
306 "Got unexpected command from dartino-vm during shutdown " | 314 "Got unexpected command from dartino-vm during shutdown " |
307 "($response)"); | 315 "($response)"); |
308 } | 316 } |
309 } | 317 } |
310 vmState = VmState.terminated; | 318 vmState = VmState.terminated; |
| 319 notifyListeners((DebugListener listener) { |
| 320 listener.terminated(); |
| 321 }); |
311 return connection.done; | 322 return connection.done; |
312 } | 323 } |
313 | 324 |
314 Future interrupt() { | 325 Future interrupt() { |
315 return sendCommand(const ProcessDebugInterrupt()); | 326 return sendCommand(const ProcessDebugInterrupt()); |
316 } | 327 } |
317 | 328 |
318 /// Closes the connection to the dartino-vm. It does not wait until it shuts | 329 /// Closes the connection to the dartino-vm. It does not wait until it shuts |
319 /// down. | 330 /// down. |
320 /// | 331 /// |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 VmCommand reply = await runCommand(const Debugging()); | 413 VmCommand reply = await runCommand(const Debugging()); |
403 if (reply == null || reply is! DebuggingReply) { | 414 if (reply == null || reply is! DebuggingReply) { |
404 throw new Exception("Expected a reply from the debugging command"); | 415 throw new Exception("Expected a reply from the debugging command"); |
405 } | 416 } |
406 return reply; | 417 return reply; |
407 } | 418 } |
408 | 419 |
409 Future spawnProcess(List<String> arguments) async { | 420 Future spawnProcess(List<String> arguments) async { |
410 await runCommand(new ProcessSpawnForMain(arguments)); | 421 await runCommand(new ProcessSpawnForMain(arguments)); |
411 vmState = VmState.spawned; | 422 vmState = VmState.spawned; |
| 423 notifyListeners((DebugListener listener) { |
| 424 listener.pauseStart(0); |
| 425 listener.processRunnable(0); |
| 426 }); |
412 } | 427 } |
413 | 428 |
414 /// Returns the [NameOffsetMapping] stored in the '.info.json' adjacent to a | 429 /// Returns the [NameOffsetMapping] stored in the '.info.json' adjacent to a |
415 /// snapshot location. | 430 /// snapshot location. |
416 Future<NameOffsetMapping> getInfoFromSnapshotLocation(Uri snapshot) async { | 431 Future<NameOffsetMapping> getInfoFromSnapshotLocation(Uri snapshot) async { |
417 Uri info = snapshot.replace(path: "${snapshot.path}.info.json"); | 432 Uri info = snapshot.replace(path: "${snapshot.path}.info.json"); |
418 File infoFile = new File.fromUri(info); | 433 File infoFile = new File.fromUri(info); |
419 | 434 |
420 if (!await infoFile.exists()) { | 435 if (!await infoFile.exists()) { |
421 await shutdown(); | 436 await shutdown(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 // This method handles the various responses a command can return to indicate | 515 // This method handles the various responses a command can return to indicate |
501 // the process has stopped running. | 516 // the process has stopped running. |
502 // The session's state is updated to match the current state of the vm. | 517 // The session's state is updated to match the current state of the vm. |
503 Future<VmCommand> handleProcessStop(VmCommand response) async { | 518 Future<VmCommand> handleProcessStop(VmCommand response) async { |
504 interactiveExitCode = exit_codes.COMPILER_EXITCODE_CRASH; | 519 interactiveExitCode = exit_codes.COMPILER_EXITCODE_CRASH; |
505 debugState.reset(); | 520 debugState.reset(); |
506 switch (response.code) { | 521 switch (response.code) { |
507 case VmCommandCode.UncaughtException: | 522 case VmCommandCode.UncaughtException: |
508 interactiveExitCode = exit_codes.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION; | 523 interactiveExitCode = exit_codes.DART_VM_EXITCODE_UNCAUGHT_EXCEPTION; |
509 vmState = VmState.terminating; | 524 vmState = VmState.terminating; |
| 525 UncaughtException command = response; |
| 526 debugState.currentProcess = command.processId; |
| 527 var function = dartinoSystem.lookupFunctionById(command.functionId); |
| 528 debugState.topFrame = new BackTraceFrame( |
| 529 function, command.bytecodeIndex, compiler, debugState); |
| 530 RemoteObject thrown = await uncaughtException(); |
| 531 notifyListeners((DebugListener listener) { |
| 532 listener.pauseException( |
| 533 debugState.currentProcess, debugState.topFrame, thrown); |
| 534 }); |
510 break; | 535 break; |
511 | 536 |
512 case VmCommandCode.ProcessCompileTimeError: | 537 case VmCommandCode.ProcessCompileTimeError: |
| 538 notifyListeners((DebugListener listener) { |
| 539 // TODO(sigurdm): Add processId and exception data. |
| 540 listener.pauseException(0, null, null); |
| 541 }); |
513 interactiveExitCode = exit_codes.DART_VM_EXITCODE_COMPILE_TIME_ERROR; | 542 interactiveExitCode = exit_codes.DART_VM_EXITCODE_COMPILE_TIME_ERROR; |
514 vmState = VmState.terminating; | 543 vmState = VmState.terminating; |
515 break; | 544 break; |
516 | 545 |
517 case VmCommandCode.ProcessTerminated: | 546 case VmCommandCode.ProcessTerminated: |
518 interactiveExitCode = 0; | 547 interactiveExitCode = 0; |
519 vmState = VmState.terminating; | 548 vmState = VmState.terminating; |
| 549 notifyListeners((DebugListener listener) { |
| 550 // TODO(sigurdm): Communicate process id. |
| 551 listener.processExit(0); |
| 552 }); |
520 break; | 553 break; |
521 | 554 |
522 case VmCommandCode.ConnectionError: | 555 case VmCommandCode.ConnectionError: |
523 interactiveExitCode = exit_codes.COMPILER_EXITCODE_CONNECTION_ERROR; | 556 interactiveExitCode = exit_codes.COMPILER_EXITCODE_CONNECTION_ERROR; |
524 vmState = VmState.terminating; | 557 vmState = VmState.terminating; |
525 await shutdown(); | 558 await shutdown(); |
| 559 notifyListeners((DebugListener listener) { |
| 560 listener.lostConnection(); |
| 561 }); |
526 break; | 562 break; |
527 | 563 |
528 case VmCommandCode.ProcessBreakpoint: | 564 case VmCommandCode.ProcessBreakpoint: |
529 interactiveExitCode = 0; | 565 interactiveExitCode = 0; |
530 ProcessBreakpoint command = response; | 566 ProcessBreakpoint command = response; |
531 debugState.currentProcess = command.processId; | 567 debugState.currentProcess = command.processId; |
532 var function = dartinoSystem.lookupFunctionById(command.functionId); | 568 var function = dartinoSystem.lookupFunctionById(command.functionId); |
533 debugState.topFrame = new BackTraceFrame( | 569 debugState.topFrame = new BackTraceFrame( |
534 function, command.bytecodeIndex, compiler, debugState); | 570 function, command.bytecodeIndex, compiler, debugState); |
535 vmState = VmState.paused; | 571 vmState = VmState.paused; |
| 572 Breakpoint bp = debugState.breakpoints[command.breakpointId]; |
| 573 if (bp == null) { |
| 574 notifyListeners((DebugListener listener) { |
| 575 listener.pauseInterrupted( |
| 576 command.processId, |
| 577 debugState.topFrame); |
| 578 }); |
| 579 } else { |
| 580 notifyListeners((DebugListener listener) { |
| 581 listener.pauseBreakpoint( |
| 582 command.processId, |
| 583 debugState.topFrame, |
| 584 bp); |
| 585 }); |
| 586 } |
536 break; | 587 break; |
537 | 588 |
538 default: | 589 default: |
539 throw new StateError( | 590 throw new StateError( |
540 "Unhandled response from Dartino VM connection: ${response.code}"); | 591 "Unhandled response from Dartino VM connection: ${response.code}"); |
541 | 592 |
542 } | 593 } |
543 return response; | 594 return response; |
544 } | 595 } |
545 | 596 |
546 Future<VmCommand> startRunning() async { | 597 Future<VmCommand> startRunning() async { |
547 await sendCommand(const ProcessRun()); | 598 await sendCommand(const ProcessRun()); |
548 vmState = VmState.running; | 599 vmState = VmState.running; |
| 600 notifyListeners((DebugListener listener) { |
| 601 listener.processStart(0); |
| 602 }); |
| 603 notifyListeners((DebugListener listener) { |
| 604 listener.processRunnable(0); |
| 605 }); |
| 606 notifyListeners((DebugListener listener) { |
| 607 listener.resume(0); |
| 608 }); |
549 return handleProcessStop(await readNextCommand()); | 609 return handleProcessStop(await readNextCommand()); |
550 } | 610 } |
551 | 611 |
552 Future setBreakpointHelper(String name, | 612 Future<Breakpoint> setBreakpointHelper(DartinoFunction function, |
553 DartinoFunction function, | |
554 int bytecodeIndex) async { | 613 int bytecodeIndex) async { |
555 ProcessSetBreakpoint response = await runCommands([ | 614 ProcessSetBreakpoint response = await runCommands([ |
556 new PushFromMap(MapId.methods, function.functionId), | 615 new PushFromMap(MapId.methods, function.functionId), |
557 new ProcessSetBreakpoint(bytecodeIndex), | 616 new ProcessSetBreakpoint(bytecodeIndex), |
558 ]); | 617 ]); |
559 int breakpointId = response.value; | 618 int breakpointId = response.value; |
560 var breakpoint = new Breakpoint(function, bytecodeIndex, breakpointId); | 619 Breakpoint breakpoint = |
| 620 new Breakpoint(function, bytecodeIndex, breakpointId); |
561 debugState.breakpoints[breakpointId] = breakpoint; | 621 debugState.breakpoints[breakpointId] = breakpoint; |
| 622 notifyListeners( |
| 623 (DebugListener listener) => listener.breakpointAdded(0, breakpoint)); |
562 return breakpoint; | 624 return breakpoint; |
563 } | 625 } |
564 | 626 |
565 // TODO(ager): Let setBreakpoint return a stream instead and deal with | 627 // TODO(ager): Let setBreakpoint return a stream instead and deal with |
566 // error situations such as bytecode indices that are out of bounds for | 628 // error situations such as bytecode indices that are out of bounds for |
567 // some of the methods with the given name. | 629 // some of the methods with the given name. |
568 Future setBreakpoint({String methodName, int bytecodeIndex}) async { | 630 Future setBreakpoint({String methodName, int bytecodeIndex}) async { |
569 Iterable<DartinoFunction> functions = | 631 Iterable<DartinoFunction> functions = |
570 dartinoSystem.functionsWhere((f) => f.name == methodName); | 632 dartinoSystem.functionsWhere((f) => f.name == methodName); |
571 List<Breakpoint> breakpoints = []; | 633 List<Breakpoint> breakpoints = []; |
572 for (DartinoFunction function in functions) { | 634 for (DartinoFunction function in functions) { |
573 breakpoints.add( | 635 breakpoints.add( |
574 await setBreakpointHelper(methodName, function, bytecodeIndex)); | 636 await setBreakpointHelper(function, bytecodeIndex)); |
575 } | 637 } |
576 return breakpoints; | 638 return breakpoints; |
577 } | 639 } |
578 | 640 |
579 Future setFileBreakpointFromPosition(String name, | 641 Future<Breakpoint> setFileBreakpointFromPosition(String name, |
580 Uri file, | 642 Uri file, |
581 int position) async { | 643 int position) async { |
582 if (position == null) { | 644 if (position == null) { |
583 return null; | 645 return null; |
584 } | 646 } |
585 DebugInfo debugInfo = compiler.debugInfoForPosition( | 647 DebugInfo debugInfo = compiler.debugInfoForPosition( |
586 file, | 648 file, |
587 position, | 649 position, |
588 dartinoSystem); | 650 dartinoSystem); |
589 if (debugInfo == null) { | 651 if (debugInfo == null) { |
590 return null; | 652 return null; |
591 } | 653 } |
592 SourceLocation location = debugInfo.locationForPosition(position); | 654 SourceLocation location = debugInfo.locationForPosition(position); |
593 if (location == null) { | 655 if (location == null) { |
594 return null; | 656 return null; |
595 } | 657 } |
596 DartinoFunction function = debugInfo.function; | 658 DartinoFunction function = debugInfo.function; |
597 int bytecodeIndex = location.bytecodeIndex; | 659 int bytecodeIndex = location.bytecodeIndex; |
598 return setBreakpointHelper(function.name, function, bytecodeIndex); | 660 return setBreakpointHelper(function, bytecodeIndex); |
599 } | 661 } |
600 | 662 |
601 Future setFileBreakpointFromPattern(Uri file, | 663 Future<Breakpoint> setFileBreakpointFromPattern(Uri file, |
602 int line, | 664 int line, |
603 String pattern) async { | 665 String pattern) async { |
604 assert(line > 0); | 666 assert(line > 0); |
605 int position = compiler.positionInFileFromPattern(file, line - 1, pattern); | 667 int position = compiler.positionInFileFromPattern(file, line - 1, pattern); |
606 return setFileBreakpointFromPosition( | 668 return setFileBreakpointFromPosition( |
607 '$file:$line:$pattern', file, position); | 669 '$file:$line:$pattern', file, position); |
608 } | 670 } |
609 | 671 |
610 Future setFileBreakpoint(Uri file, int line, int column) async { | 672 Future<Breakpoint> setFileBreakpoint(Uri file, int line, int column) async { |
611 assert(line > 0 && column > 0); | 673 assert(line > 0 && column > 0); |
612 int position = compiler.positionInFile(file, line - 1, column - 1); | 674 int position = compiler.positionInFile(file, line - 1, column - 1); |
613 return setFileBreakpointFromPosition('$file:$line:$column', file, position); | 675 return setFileBreakpointFromPosition('$file:$line:$column', file, position); |
614 } | 676 } |
615 | 677 |
616 Future doDeleteOneShotBreakpoint(int processId, int breakpointId) async { | 678 Future<Null> doDeleteOneShotBreakpoint( |
| 679 int processId, int breakpointId) async { |
617 ProcessDeleteBreakpoint response = await runCommand( | 680 ProcessDeleteBreakpoint response = await runCommand( |
618 new ProcessDeleteOneShotBreakpoint(processId, breakpointId)); | 681 new ProcessDeleteOneShotBreakpoint(processId, breakpointId)); |
619 assert(response.id == breakpointId); | 682 assert(response.id == breakpointId); |
620 } | 683 } |
621 | 684 |
622 Future<Breakpoint> deleteBreakpoint(int id) async { | 685 Future<Breakpoint> deleteBreakpoint(int id) async { |
| 686 assert(!isRunning && !isTerminated); |
623 if (!debugState.breakpoints.containsKey(id)) { | 687 if (!debugState.breakpoints.containsKey(id)) { |
624 return null; | 688 return null; |
625 } | 689 } |
626 ProcessDeleteBreakpoint response = | 690 ProcessDeleteBreakpoint response = |
627 await runCommand(new ProcessDeleteBreakpoint(id)); | 691 await runCommand(new ProcessDeleteBreakpoint(id)); |
628 assert(response.id == id); | 692 assert(response.id == id); |
629 return debugState.breakpoints.remove(id); | 693 Breakpoint breakpoint = debugState.breakpoints.remove(id); |
| 694 notifyListeners((DebugListener listener) { |
| 695 listener.breakpointRemoved(0, breakpoint); |
| 696 }); |
| 697 return breakpoint; |
630 } | 698 } |
631 | 699 |
632 List<Breakpoint> breakpoints() { | 700 List<Breakpoint> breakpoints() { |
633 assert(debugState.breakpoints != null); | 701 assert(debugState.breakpoints != null); |
634 return debugState.breakpoints.values.toList(); | 702 return debugState.breakpoints.values.toList(); |
635 } | 703 } |
636 | 704 |
637 Iterable<Uri> findSourceFiles(Pattern pattern) { | 705 Iterable<Uri> findSourceFiles(Pattern pattern) { |
638 return compiler.findSourceFiles(pattern); | 706 return compiler.findSourceFiles(pattern); |
639 } | 707 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 response.breakpointId == setBreakpoint.value; | 810 response.breakpointId == setBreakpoint.value; |
743 if (!success && !isTerminated && setBreakpoint.value != -1) { | 811 if (!success && !isTerminated && setBreakpoint.value != -1) { |
744 // Delete the initial one-time breakpoint as it wasn't hit. | 812 // Delete the initial one-time breakpoint as it wasn't hit. |
745 await doDeleteOneShotBreakpoint(processId, setBreakpoint.value); | 813 await doDeleteOneShotBreakpoint(processId, setBreakpoint.value); |
746 } | 814 } |
747 return response; | 815 return response; |
748 } | 816 } |
749 | 817 |
750 Future<VmCommand> cont() async { | 818 Future<VmCommand> cont() async { |
751 assert(isPaused); | 819 assert(isPaused); |
| 820 notifyListeners((DebugListener listener) { |
| 821 listener.resume(0); |
| 822 }); |
752 return handleProcessStop(await runCommand(const ProcessContinue())); | 823 return handleProcessStop(await runCommand(const ProcessContinue())); |
753 } | 824 } |
754 | 825 |
755 bool selectFrame(int frame) { | 826 bool selectFrame(int frame) { |
756 if (debugState.currentBackTrace == null || | 827 if (debugState.currentBackTrace == null || |
757 debugState.currentBackTrace.actualFrameNumber(frame) == -1) { | 828 debugState.currentBackTrace.actualFrameNumber(frame) == -1) { |
758 return false; | 829 return false; |
759 } | 830 } |
760 debugState.currentFrame = frame; | 831 debugState.currentFrame = frame; |
761 return true; | 832 return true; |
(...skipping 29 matching lines...) Expand all Loading... |
791 } else { | 862 } else { |
792 assert(response is InstanceStructure); | 863 assert(response is InstanceStructure); |
793 List<DartValue> fields = await readInstanceStructureFields(response); | 864 List<DartValue> fields = await readInstanceStructureFields(response); |
794 debugState.currentUncaughtException = | 865 debugState.currentUncaughtException = |
795 new RemoteInstance(response, fields); | 866 new RemoteInstance(response, fields); |
796 } | 867 } |
797 } | 868 } |
798 return debugState.currentUncaughtException; | 869 return debugState.currentUncaughtException; |
799 } | 870 } |
800 | 871 |
801 Future<BackTrace> backTrace() async { | 872 Future<BackTrace> backTrace({int processId}) async { |
| 873 processId ??= debugState.currentProcess; |
802 assert(isSpawned); | 874 assert(isSpawned); |
803 if (debugState.currentBackTrace == null) { | 875 if (debugState.currentBackTrace == null) { |
804 ProcessBacktrace backtraceResponse = | 876 ProcessBacktrace backtraceResponse = |
805 await runCommand( | 877 await runCommand( |
806 new ProcessBacktraceRequest(debugState.currentProcess)); | 878 new ProcessBacktraceRequest(processId)); |
807 debugState.currentBackTrace = | 879 debugState.currentBackTrace = |
808 stackTraceFromBacktraceResponse(backtraceResponse); | 880 stackTraceFromBacktraceResponse(backtraceResponse); |
809 } | 881 } |
810 return debugState.currentBackTrace; | 882 return debugState.currentBackTrace; |
811 } | 883 } |
812 | 884 |
813 Future<BackTrace> backtraceForFiber(int fiber) async { | 885 Future<BackTrace> backtraceForFiber(int fiber) async { |
814 ProcessBacktrace backtraceResponse = | 886 ProcessBacktrace backtraceResponse = |
815 await runCommand(new ProcessFiberBacktraceRequest(fiber)); | 887 await runCommand(new ProcessFiberBacktraceRequest(fiber)); |
816 return stackTraceFromBacktraceResponse(backtraceResponse); | 888 return stackTraceFromBacktraceResponse(backtraceResponse); |
817 } | 889 } |
818 | 890 |
819 Future<List<BackTrace>> fibers() async { | 891 Future<List<BackTrace>> fibers() async { |
820 assert(isRunning || isPaused); | 892 assert(isRunning || isPaused); |
821 await runCommand(const NewMap(MapId.fibers)); | 893 await runCommand(const NewMap(MapId.fibers)); |
822 ProcessNumberOfStacks response = | 894 ProcessNumberOfStacks response = |
823 await runCommand(const ProcessAddFibersToMap()); | 895 await runCommand(const ProcessAddFibersToMap()); |
824 int numberOfFibers = response.value; | 896 int numberOfFibers = response.value; |
825 List<BackTrace> stacktraces = new List(numberOfFibers); | 897 List<BackTrace> stacktraces = new List(numberOfFibers); |
826 for (int i = 0; i < numberOfFibers; i++) { | 898 for (int i = 0; i < numberOfFibers; i++) { |
827 stacktraces[i] = await backtraceForFiber(i); | 899 stacktraces[i] = await backtraceForFiber(i); |
828 } | 900 } |
829 await runCommand(const DeleteMap(MapId.fibers)); | 901 await runCommand(const DeleteMap(MapId.fibers)); |
830 return stacktraces; | 902 return stacktraces; |
831 } | 903 } |
832 | 904 |
833 Future<List<int>> processes() async { | 905 Future<List<int>> processes() async { |
834 assert(isRunning || isPaused); | 906 assert(isSpawned); |
835 ProcessGetProcessIdsResult response = | 907 ProcessGetProcessIdsResult response = |
836 await runCommand(const ProcessGetProcessIds()); | 908 await runCommand(const ProcessGetProcessIds()); |
837 return response.ids; | 909 return response.ids; |
838 } | 910 } |
839 | 911 |
840 Future<BackTrace> processStack(int processId) async { | 912 Future<BackTrace> processStack(int processId) async { |
841 assert(isPaused); | 913 assert(isPaused); |
842 ProcessBacktrace backtraceResponse = | 914 ProcessBacktrace backtraceResponse = |
843 await runCommand(new ProcessBacktraceRequest(processId)); | 915 await runCommand(new ProcessBacktraceRequest(processId)); |
844 return stackTraceFromBacktraceResponse(backtraceResponse); | 916 return stackTraceFromBacktraceResponse(backtraceResponse); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 } | 1130 } |
1059 | 1131 |
1060 bool toggleInternal() { | 1132 bool toggleInternal() { |
1061 debugState.showInternalFrames = !debugState.showInternalFrames; | 1133 debugState.showInternalFrames = !debugState.showInternalFrames; |
1062 if (debugState.currentBackTrace != null) { | 1134 if (debugState.currentBackTrace != null) { |
1063 debugState.currentBackTrace.visibilityChanged(); | 1135 debugState.currentBackTrace.visibilityChanged(); |
1064 } | 1136 } |
1065 return debugState.showInternalFrames; | 1137 return debugState.showInternalFrames; |
1066 } | 1138 } |
1067 } | 1139 } |
OLD | NEW |