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

Side by Side 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 unified diff | Download patch
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 part of service; 5 part of service;
6 6
7 // Some value smaller than the object ring, so requesting a large array 7 // Some value smaller than the object ring, so requesting a large array
8 // doesn't result in an expired ref because the elements lapped it in the 8 // doesn't result in an expired ref because the elements lapped it in the
9 // object ring. 9 // object ring.
10 const int kDefaultFieldLimit = 100; 10 const int kDefaultFieldLimit = 100;
(...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after
1570 } 1570 }
1571 1571
1572 Future stepInto() { 1572 Future stepInto() {
1573 return invokeRpc('resume', {'step': 'Into'}); 1573 return invokeRpc('resume', {'step': 'Into'});
1574 } 1574 }
1575 1575
1576 Future stepOver() { 1576 Future stepOver() {
1577 return invokeRpc('resume', {'step': 'Over'}); 1577 return invokeRpc('resume', {'step': 'Over'});
1578 } 1578 }
1579 1579
1580 Future stepOverAsyncContinuation() {
1581 return invokeRpc('resume', {'step': 'OverAsyncContinuation'});
1582 }
1583
1580 Future stepOut() { 1584 Future stepOut() {
1581 return invokeRpc('resume', {'step': 'Out'}); 1585 return invokeRpc('resume', {'step': 'Out'});
1582 } 1586 }
1583 1587
1584 1588
1585 static const int kFirstResume = 0; 1589 static const int kResumeFuture = 0;
1586 static const int kSecondResume = 1; 1590 static const int kPauseFuture = 1;
1587 /// result[kFirstResume] completes after the inital resume. The UI should 1591 /// result[kResumeFuture] completes after the inital resume. The UI should
1588 /// wait on this future because some other breakpoint may be hit before the 1592 /// wait on this future because some other breakpoint may be hit before the
1589 /// async continuation. 1593 /// async continuation.
1590 /// result[kSecondResume] completes after the second resume. Tests should 1594 /// result[kPauseFuture] completes when the isolate is paused after the
1591 /// wait on this future to avoid confusing the pause event at the 1595 /// await. Tests should wait on this future to know that we've completed
1592 /// state-machine switch with the pause event after the state-machine switch. 1596 /// the OverAWait.
1593 Future<List<Future>> asyncStepOver() async { 1597 Future<List<Future>> asyncStepOver() async {
1594 final Completer firstResume = new Completer(); 1598 final Completer resumedAfterSyntheticBreakpointAdded = new Completer();
1595 final Completer secondResume = new Completer(); 1599 final Completer pausedAtSyntheticBreakpoint = new Completer();
1596 final List<Future> result = [firstResume.future, secondResume.future]; 1600 final List<Future> result =
1601 [resumedAfterSyntheticBreakpointAdded.future,
1602 pausedAtSyntheticBreakpoint.future];
1597 StreamSubscription subscription; 1603 StreamSubscription subscription;
1598 1604
1599 // Inner error handling function. 1605 // Cancel the subscription.
1600 handleError(error) { 1606 cancelSubscription() {
1601 if (subscription != null) { 1607 if (subscription != null) {
1602 subscription.cancel(); 1608 subscription.cancel();
1603 subscription = null; 1609 subscription = null;
1604 } 1610 }
1605 firstResume.completeError(error);
1606 secondResume.completeError(error);
1607 } 1611 }
1608 1612
1609 if ((pauseEvent == null) || 1613 // Complete futures with with error.
1610 (pauseEvent.kind != ServiceEvent.kPauseBreakpoint) || 1614 completeError(error) {
1611 (pauseEvent.asyncContinuation == null)) { 1615 if (!resumedAfterSyntheticBreakpointAdded.isCompleted) {
1612 handleError(new Exception("No async continuation available")); 1616 resumedAfterSyntheticBreakpointAdded.completeError(error);
1613 } else { 1617 }
1614 Instance continuation = pauseEvent.asyncContinuation; 1618 if (!pausedAtSyntheticBreakpoint.isCompleted) {
1615 assert(continuation.isClosure); 1619 pausedAtSyntheticBreakpoint.completeError(error);
1620 }
1621 }
1616 1622
1617 // Add breakpoint at continuation. 1623 // Subscribe to the debugger event stream.
1618 Breakpoint continuationBpt; 1624 Stream stream;
1619 try { 1625 try {
1620 continuationBpt = await addBreakOnActivation(continuation); 1626 stream = await vm.getEventStream(VM.kDebugStream);
1621 } catch (e) { 1627 } catch (e) {
1622 handleError(e); 1628 completeError(e);
1623 return result; 1629 return result;
1630 }
1631
1632 Breakpoint syntheticBreakpoint;
1633
1634 subscription = stream.listen((ServiceEvent event) async {
1635 // Synthetic breakpoint add event. This is the first event we will
1636 // receive.
1637 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) &&
1638 (event.breakpoint.isSyntheticAsyncContinuation) &&
1639 (event.owner == this);
1640 // Resume after synthetic breakpoint added. This is the second event
1641 // we will recieve.
1642 bool isResume = (event.kind == ServiceEvent.kResume) &&
1643 (syntheticBreakpoint != null) &&
1644 (event.owner == this);
1645 // Paused at synthetic breakpoint. This is the third event we will
1646 // receive.
1647 bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) &&
1648 (syntheticBreakpoint != null) &&
1649 (event.breakpoint == syntheticBreakpoint);
1650 if (isAdd) {
1651 syntheticBreakpoint = event.breakpoint;
1652 } else if (isResume) {
1653 resumedAfterSyntheticBreakpointAdded.complete(this);
1654 } else if (isPaused) {
1655 pausedAtSyntheticBreakpoint.complete(this);
1656 syntheticBreakpoint = null;
1657 cancelSubscription();
1624 } 1658 }
1659 });
1625 1660
1626 // Subscribe to the debugger event stream. 1661 // Issue the step OverAwait command.
1627 Stream stream; 1662 try {
1628 try { 1663 await isolate.stepOverAsyncContinuation();
1629 stream = await vm.getEventStream(VM.kDebugStream); 1664 } catch (e) {
1630 } catch (e) { 1665 // This can fail when another client issued the same resume command
1631 handleError(e); 1666 // or another client has moved the isolate forward.
1632 return result; 1667 cancelSubscription();
1633 } 1668 completeError(e);
1669 }
1634 1670
1635 Completer onResume = firstResume;
1636 subscription = stream.listen((ServiceEvent event) async {
1637 if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
1638 (event.breakpoint == continuationBpt)) {
1639 // We are stopped before state-machine dispatch:
1640 // 1) Remove the continuation breakpoint.
1641 // 2) step over.
1642 // reach user code.
1643 await removeBreakpoint(continuationBpt);
1644 onResume = secondResume;
1645 stepOver().catchError(handleError);
1646 } else if (event.kind == ServiceEvent.kResume) {
1647 // We've resumed.
1648 if (onResume == secondResume) {
1649 // This is our second resume, cancel our subscription to the debug
1650 // stream.
1651 subscription.cancel();
1652 subscription = null;
1653 }
1654 // Complete onResume and clear it.
1655 if (onResume != null) {
1656 onResume.complete(this);
1657 onResume = null;
1658 }
1659 }
1660 });
1661
1662 // Call resume, which will eventually cause us to hit continuationBpt.
1663 resume().catchError(handleError);
1664 }
1665 return result; 1671 return result;
1666 } 1672 }
1667 1673
1668 Future setName(String newName) { 1674 Future setName(String newName) {
1669 return invokeRpc('setName', {'name': newName}); 1675 return invokeRpc('setName', {'name': newName});
1670 } 1676 }
1671 1677
1672 Future setExceptionPauseMode(String mode) { 1678 Future setExceptionPauseMode(String mode) {
1673 return invokeRpc('setExceptionPauseMode', {'mode': mode}); 1679 return invokeRpc('setExceptionPauseMode', {'mode': mode});
1674 } 1680 }
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 ServiceEvent.connectionClosed(this.reason) : super._empty(null) { 1913 ServiceEvent.connectionClosed(this.reason) : super._empty(null) {
1908 kind = kConnectionClosed; 1914 kind = kConnectionClosed;
1909 } 1915 }
1910 1916
1911 @observable String kind; 1917 @observable String kind;
1912 @observable DateTime timestamp; 1918 @observable DateTime timestamp;
1913 @observable Breakpoint breakpoint; 1919 @observable Breakpoint breakpoint;
1914 @observable Frame topFrame; 1920 @observable Frame topFrame;
1915 @observable String extensionRPC; 1921 @observable String extensionRPC;
1916 @observable Instance exception; 1922 @observable Instance exception;
1917 @observable Instance asyncContinuation; 1923 @observable bool atAsyncContinuation;
1918 @observable bool atAsyncJump;
1919 @observable ServiceObject inspectee; 1924 @observable ServiceObject inspectee;
1920 @observable ByteData data; 1925 @observable ByteData data;
1921 @observable int count; 1926 @observable int count;
1922 @observable String reason; 1927 @observable String reason;
1923 @observable String exceptions; 1928 @observable String exceptions;
1924 @observable String bytesAsString; 1929 @observable String bytesAsString;
1925 @observable Map logRecord; 1930 @observable Map logRecord;
1926 @observable String extensionKind; 1931 @observable String extensionKind;
1927 @observable Map extensionData; 1932 @observable Map extensionData;
1928 1933
(...skipping 28 matching lines...) Expand all
1957 breakpoint = pauseBpts[0]; 1962 breakpoint = pauseBpts[0];
1958 } 1963 }
1959 } 1964 }
1960 if (map['extensionRPC'] != null) { 1965 if (map['extensionRPC'] != null) {
1961 extensionRPC = map['extensionRPC']; 1966 extensionRPC = map['extensionRPC'];
1962 } 1967 }
1963 topFrame = map['topFrame']; 1968 topFrame = map['topFrame'];
1964 if (map['exception'] != null) { 1969 if (map['exception'] != null) {
1965 exception = map['exception']; 1970 exception = map['exception'];
1966 } 1971 }
1967 if (map['_asyncContinuation'] != null) { 1972 atAsyncContinuation = map['atAsyncContinuation'] != null;
1968 asyncContinuation = map['_asyncContinuation'];
1969 atAsyncJump = map['_atAsyncJump'];
1970 } else {
1971 atAsyncJump = false;
1972 }
1973 if (map['inspectee'] != null) { 1973 if (map['inspectee'] != null) {
1974 inspectee = map['inspectee']; 1974 inspectee = map['inspectee'];
1975 } 1975 }
1976 if (map['_data'] != null) { 1976 if (map['_data'] != null) {
1977 data = map['_data']; 1977 data = map['_data'];
1978 } 1978 }
1979 if (map['chunkIndex'] != null) { 1979 if (map['chunkIndex'] != null) {
1980 chunkIndex = map['chunkIndex']; 1980 chunkIndex = map['chunkIndex'];
1981 } 1981 }
1982 if (map['chunkCount'] != null) { 1982 if (map['chunkCount'] != null) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2033 2033
2034 // Either SourceLocation or UnresolvedSourceLocation. 2034 // Either SourceLocation or UnresolvedSourceLocation.
2035 @observable Location location; 2035 @observable Location location;
2036 2036
2037 // The breakpoint is in a file which is not yet loaded. 2037 // The breakpoint is in a file which is not yet loaded.
2038 @observable bool latent; 2038 @observable bool latent;
2039 2039
2040 // The breakpoint has been assigned to a final source location. 2040 // The breakpoint has been assigned to a final source location.
2041 @observable bool resolved; 2041 @observable bool resolved;
2042 2042
2043 // The breakpoint was synthetically created as part of an
2044 // 'OverAsyncContinuation' resume request.
2045 @observable bool isSyntheticAsyncContinuation;
2046
2043 void _update(ObservableMap map, bool mapIsRef) { 2047 void _update(ObservableMap map, bool mapIsRef) {
2044 _loaded = true; 2048 _loaded = true;
2045 _upgradeCollection(map, owner); 2049 _upgradeCollection(map, owner);
2046 2050
2047 var newNumber = map['breakpointNumber']; 2051 var newNumber = map['breakpointNumber'];
2048 // number never changes. 2052 // number never changes.
2049 assert((number == null) || (number == newNumber)); 2053 assert((number == null) || (number == newNumber));
2050 number = newNumber; 2054 number = newNumber;
2051 resolved = map['resolved']; 2055 resolved = map['resolved'];
2052 2056
2053 var oldLocation = location; 2057 var oldLocation = location;
2054 var newLocation = map['location']; 2058 var newLocation = map['location'];
2055 if (oldLocation is UnresolvedSourceLocation && 2059 if (oldLocation is UnresolvedSourceLocation &&
2056 newLocation is SourceLocation) { 2060 newLocation is SourceLocation) {
2057 // Breakpoint has been resolved. Remove old breakpoint. 2061 // Breakpoint has been resolved. Remove old breakpoint.
2058 var oldScript = oldLocation.script; 2062 var oldScript = oldLocation.script;
2059 if (oldScript != null && oldScript.loaded) { 2063 if (oldScript != null && oldScript.loaded) {
2060 oldScript._removeBreakpoint(this); 2064 oldScript._removeBreakpoint(this);
2061 } 2065 }
2062 } 2066 }
2063 location = newLocation; 2067 location = newLocation;
2064 var newScript = location.script; 2068 var newScript = location.script;
2065 if (newScript != null && newScript.loaded) { 2069 if (newScript != null && newScript.loaded) {
2066 newScript._addBreakpoint(this); 2070 newScript._addBreakpoint(this);
2067 } 2071 }
2068 2072
2073 isSyntheticAsyncContinuation = map['isSyntheticAsyncContinuation'] != null;
2074
2069 assert(resolved || location is UnresolvedSourceLocation); 2075 assert(resolved || location is UnresolvedSourceLocation);
2070 } 2076 }
2071 2077
2072 void remove() { 2078 void remove() {
2073 // Remove any references to this breakpoint. It has been removed. 2079 // Remove any references to this breakpoint. It has been removed.
2074 location.script._removeBreakpoint(this); 2080 location.script._removeBreakpoint(this);
2075 if ((isolate.pauseEvent != null) && 2081 if ((isolate.pauseEvent != null) &&
2076 (isolate.pauseEvent.breakpoint != null) && 2082 (isolate.pauseEvent.breakpoint != null) &&
2077 (isolate.pauseEvent.breakpoint.id == id)) { 2083 (isolate.pauseEvent.breakpoint.id == id)) {
2078 isolate.pauseEvent.breakpoint = null; 2084 isolate.pauseEvent.breakpoint = null;
2079 } 2085 }
2080 } 2086 }
2081 2087
2082 String toString() { 2088 String toString() {
2083 if (number != null) { 2089 if (number != null) {
2084 return 'Breakpoint ${number} at ${location})'; 2090 if (isSyntheticAsyncContinuation) {
2091 return 'Synthetic Async Continuation Breakpoint ${number}';
2092 } else {
2093 return 'Breakpoint ${number} at ${location}';
2094 }
2085 } else { 2095 } else {
2086 return 'Uninitialized breakpoint'; 2096 return 'Uninitialized breakpoint';
2087 } 2097 }
2088 } 2098 }
2089 } 2099 }
2090 2100
2091 2101
2092 class LibraryDependency { 2102 class LibraryDependency {
2093 @reflectable final bool isImport; 2103 @reflectable final bool isImport;
2094 @reflectable final bool isDeferred; 2104 @reflectable final bool isDeferred;
(...skipping 1957 matching lines...) Expand 10 before | Expand all | Expand 10 after
4052 var v = list[i]; 4062 var v = list[i];
4053 if ((v is ObservableMap) && _isServiceMap(v)) { 4063 if ((v is ObservableMap) && _isServiceMap(v)) {
4054 list[i] = owner.getFromMap(v); 4064 list[i] = owner.getFromMap(v);
4055 } else if (v is ObservableList) { 4065 } else if (v is ObservableList) {
4056 _upgradeObservableList(v, owner); 4066 _upgradeObservableList(v, owner);
4057 } else if (v is ObservableMap) { 4067 } else if (v is ObservableMap) {
4058 _upgradeObservableMap(v, owner); 4068 _upgradeObservableMap(v, owner);
4059 } 4069 }
4060 } 4070 }
4061 } 4071 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698