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

Unified Diff: runtime/observatory/lib/src/service/object.dart

Issue 1699153002: Add step OverAwait to service protocol (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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 side-by-side diff with in-line comments
Download patch
Index: runtime/observatory/lib/src/service/object.dart
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index bd76e67d0caa9d24a4791ee05345935b0b0feb5e..ec786e1156e38dee1bfdf0308bf85b52fde974ec 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1577,91 +1577,88 @@ class Isolate extends ServiceObjectOwner {
return invokeRpc('resume', {'step': 'Over'});
}
+ Future stepOverAwait() {
+ return invokeRpc('resume', {'step': 'OverAwait'});
+ }
+
Future stepOut() {
return invokeRpc('resume', {'step': 'Out'});
}
- static const int kFirstResume = 0;
- static const int kSecondResume = 1;
- /// result[kFirstResume] completes after the inital resume. The UI should
+ static const int kUIFuture = 0;
+ static const int kTestFuture = 1;
+ /// result[kUIFuture] completes after the inital resume. The UI should
/// wait on this future because some other breakpoint may be hit before the
/// async continuation.
- /// result[kSecondResume] completes after the second resume. Tests should
+ /// result[kTestFuture] completes after the second resume. Tests should
/// wait on this future to avoid confusing the pause event at the
/// state-machine switch with the pause event after the state-machine switch.
Future<List<Future>> asyncStepOver() async {
- final Completer firstResume = new Completer();
- final Completer secondResume = new Completer();
- final List<Future> result = [firstResume.future, secondResume.future];
+ final Completer breakpointAdded = new Completer();
+ final Completer breakpointRemoved = new Completer();
rmacnak 2016/02/16 21:21:58 It would make more sense for the tests to wait for
Cutch 2016/02/17 18:24:21 Event sequence is now: - kBreapointAdded (#1). -
+ final List<Future> result =
+ [breakpointAdded.future, breakpointRemoved.future];
StreamSubscription subscription;
- // Inner error handling function.
- handleError(error) {
+ // Cancel the subscription.
+ cancelSubscription() {
if (subscription != null) {
subscription.cancel();
subscription = null;
}
- firstResume.completeError(error);
- secondResume.completeError(error);
}
- if ((pauseEvent == null) ||
- (pauseEvent.kind != ServiceEvent.kPauseBreakpoint) ||
- (pauseEvent.asyncContinuation == null)) {
- handleError(new Exception("No async continuation available"));
- } else {
- Instance continuation = pauseEvent.asyncContinuation;
- assert(continuation.isClosure);
-
- // Add breakpoint at continuation.
- Breakpoint continuationBpt;
- try {
- continuationBpt = await addBreakOnActivation(continuation);
- } catch (e) {
- handleError(e);
- return result;
+ // Complete futures with with error.
+ completeError(error) {
+ if (!breakpointAdded.isCompleted) {
+ breakpointAdded.completeError(error);
}
-
- // Subscribe to the debugger event stream.
- Stream stream;
- try {
- stream = await vm.getEventStream(VM.kDebugStream);
- } catch (e) {
- handleError(e);
- return result;
+ if (!breakpointRemoved.isCompleted) {
+ breakpointRemoved.completeError(error);
}
+ }
- Completer onResume = firstResume;
- subscription = stream.listen((ServiceEvent event) async {
- if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
- (event.breakpoint == continuationBpt)) {
- // We are stopped before state-machine dispatch:
- // 1) Remove the continuation breakpoint.
- // 2) step over.
- // reach user code.
- await removeBreakpoint(continuationBpt);
- onResume = secondResume;
- stepOver().catchError(handleError);
- } else if (event.kind == ServiceEvent.kResume) {
- // We've resumed.
- if (onResume == secondResume) {
- // This is our second resume, cancel our subscription to the debug
- // stream.
- subscription.cancel();
- subscription = null;
- }
- // Complete onResume and clear it.
- if (onResume != null) {
- onResume.complete(this);
- onResume = null;
- }
- }
- });
+ // Subscribe to the debugger event stream.
+ Stream stream;
+ try {
+ stream = await vm.getEventStream(VM.kDebugStream);
+ } catch (e) {
+ completeError(e);
+ return result;
+ }
+
+ Breakpoint syntheticBreakpoint;
+
+ subscription = stream.listen((ServiceEvent event) async {
+ // Synthetic breakpoint add event for this isolate.
+ bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) &&
+ (event.breakpoint.isSyntheticAsync) &&
+ (event.owner == this);
+ // Synthetic breakpoint remove event.
+ bool isRemove = (event.kind == ServiceEvent.kBreakpointRemoved) &&
+ (syntheticBreakpoint != null) &&
+ (event.breakpoint == syntheticBreakpoint);
+ if (isAdd) {
+ syntheticBreakpoint = event.breakpoint;
+ breakpointAdded.complete(this);
+ } else if (isRemove) {
+ breakpointRemoved.complete(this);
+ // We are finished, cancel the subscription.
+ cancelSubscription();
+ }
+ });
- // Call resume, which will eventually cause us to hit continuationBpt.
- resume().catchError(handleError);
+ // Issue the step OverAwait command.
+ try {
+ await isolate.stepOverAwait();
+ } catch (e) {
+ // This can fail when another client issued the same resume command
+ // or another client has moved the isolate forward.
+ cancelSubscription();
+ completeError(e);
}
+
return result;
}
@@ -1916,6 +1913,7 @@ class ServiceEvent extends ServiceObject {
@observable Instance exception;
@observable Instance asyncContinuation;
@observable bool atAsyncJump;
rmacnak 2016/02/16 21:21:58 Don't need atAsyncJump anymore.
Cutch 2016/02/17 18:24:21 Removed this and asyncContinuation.
+ @observable bool atAwait;
@observable ServiceObject inspectee;
@observable ByteData data;
@observable int count;
@@ -1970,6 +1968,11 @@ class ServiceEvent extends ServiceObject {
} else {
atAsyncJump = false;
}
+ if (map['atAwait'] != null) {
+ atAwait = true;
+ } else {
+ atAwait = false;
+ }
if (map['inspectee'] != null) {
inspectee = map['inspectee'];
}
@@ -2040,6 +2043,10 @@ class Breakpoint extends ServiceObject {
// The breakpoint has been assigned to a final source location.
@observable bool resolved;
+ // The breakpoint was synthetically created as part of an 'OverAWait' resume
+ // request.
+ @observable bool isSyntheticAsync;
+
void _update(ObservableMap map, bool mapIsRef) {
_loaded = true;
_upgradeCollection(map, owner);
@@ -2066,6 +2073,8 @@ class Breakpoint extends ServiceObject {
newScript._addBreakpoint(this);
}
+ isSyntheticAsync = map['isSyntheticAsyncBreakpoint'] != null;
+
assert(resolved || location is UnresolvedSourceLocation);
}
@@ -2081,7 +2090,11 @@ class Breakpoint extends ServiceObject {
String toString() {
if (number != null) {
- return 'Breakpoint ${number} at ${location})';
+ if (isSyntheticAsync) {
+ return 'Async Synthetic Breakpoint ${number} at ${location}';
+ } else {
+ return 'Breakpoint ${number} at ${location}';
+ }
} else {
return 'Uninitialized breakpoint';
}

Powered by Google App Engine
This is Rietveld 408576698