| 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 |