OLD | NEW |
---|---|
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 Loading... | |
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 stepOverAwait() { | |
1581 return invokeRpc('resume', {'step': 'OverAwait'}); | |
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 kUIFuture = 0; |
1586 static const int kSecondResume = 1; | 1590 static const int kTestFuture = 1; |
1587 /// result[kFirstResume] completes after the inital resume. The UI should | 1591 /// result[kUIFuture] 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[kTestFuture] completes after the second resume. Tests should |
1591 /// wait on this future to avoid confusing the pause event at the | 1595 /// wait on this future to avoid confusing the pause event at the |
1592 /// state-machine switch with the pause event after the state-machine switch. | 1596 /// state-machine switch with the pause event after the state-machine switch. |
1593 Future<List<Future>> asyncStepOver() async { | 1597 Future<List<Future>> asyncStepOver() async { |
1594 final Completer firstResume = new Completer(); | 1598 final Completer breakpointAdded = new Completer(); |
1595 final Completer secondResume = new Completer(); | 1599 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).
-
| |
1596 final List<Future> result = [firstResume.future, secondResume.future]; | 1600 final List<Future> result = |
1601 [breakpointAdded.future, breakpointRemoved.future]; | |
1597 StreamSubscription subscription; | 1602 StreamSubscription subscription; |
1598 | 1603 |
1599 // Inner error handling function. | 1604 // Cancel the subscription. |
1600 handleError(error) { | 1605 cancelSubscription() { |
1601 if (subscription != null) { | 1606 if (subscription != null) { |
1602 subscription.cancel(); | 1607 subscription.cancel(); |
1603 subscription = null; | 1608 subscription = null; |
1604 } | 1609 } |
1605 firstResume.completeError(error); | |
1606 secondResume.completeError(error); | |
1607 } | 1610 } |
1608 | 1611 |
1609 if ((pauseEvent == null) || | 1612 // Complete futures with with error. |
1610 (pauseEvent.kind != ServiceEvent.kPauseBreakpoint) || | 1613 completeError(error) { |
1611 (pauseEvent.asyncContinuation == null)) { | 1614 if (!breakpointAdded.isCompleted) { |
1612 handleError(new Exception("No async continuation available")); | 1615 breakpointAdded.completeError(error); |
1613 } else { | 1616 } |
1614 Instance continuation = pauseEvent.asyncContinuation; | 1617 if (!breakpointRemoved.isCompleted) { |
1615 assert(continuation.isClosure); | 1618 breakpointRemoved.completeError(error); |
1619 } | |
1620 } | |
1616 | 1621 |
1617 // Add breakpoint at continuation. | 1622 // Subscribe to the debugger event stream. |
1618 Breakpoint continuationBpt; | 1623 Stream stream; |
1619 try { | 1624 try { |
1620 continuationBpt = await addBreakOnActivation(continuation); | 1625 stream = await vm.getEventStream(VM.kDebugStream); |
1621 } catch (e) { | 1626 } catch (e) { |
1622 handleError(e); | 1627 completeError(e); |
1623 return result; | 1628 return result; |
1629 } | |
1630 | |
1631 Breakpoint syntheticBreakpoint; | |
1632 | |
1633 subscription = stream.listen((ServiceEvent event) async { | |
1634 // Synthetic breakpoint add event for this isolate. | |
1635 bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) && | |
1636 (event.breakpoint.isSyntheticAsync) && | |
1637 (event.owner == this); | |
1638 // Synthetic breakpoint remove event. | |
1639 bool isRemove = (event.kind == ServiceEvent.kBreakpointRemoved) && | |
1640 (syntheticBreakpoint != null) && | |
1641 (event.breakpoint == syntheticBreakpoint); | |
1642 if (isAdd) { | |
1643 syntheticBreakpoint = event.breakpoint; | |
1644 breakpointAdded.complete(this); | |
1645 } else if (isRemove) { | |
1646 breakpointRemoved.complete(this); | |
1647 // We are finished, cancel the subscription. | |
1648 cancelSubscription(); | |
1624 } | 1649 } |
1650 }); | |
1625 | 1651 |
1626 // Subscribe to the debugger event stream. | 1652 // Issue the step OverAwait command. |
1627 Stream stream; | 1653 try { |
1628 try { | 1654 await isolate.stepOverAwait(); |
1629 stream = await vm.getEventStream(VM.kDebugStream); | 1655 } catch (e) { |
1630 } catch (e) { | 1656 // This can fail when another client issued the same resume command |
1631 handleError(e); | 1657 // or another client has moved the isolate forward. |
1632 return result; | 1658 cancelSubscription(); |
1633 } | 1659 completeError(e); |
1660 } | |
1634 | 1661 |
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; | 1662 return result; |
1666 } | 1663 } |
1667 | 1664 |
1668 Future setName(String newName) { | 1665 Future setName(String newName) { |
1669 return invokeRpc('setName', {'name': newName}); | 1666 return invokeRpc('setName', {'name': newName}); |
1670 } | 1667 } |
1671 | 1668 |
1672 Future setExceptionPauseMode(String mode) { | 1669 Future setExceptionPauseMode(String mode) { |
1673 return invokeRpc('setExceptionPauseMode', {'mode': mode}); | 1670 return invokeRpc('setExceptionPauseMode', {'mode': mode}); |
1674 } | 1671 } |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1908 kind = kConnectionClosed; | 1905 kind = kConnectionClosed; |
1909 } | 1906 } |
1910 | 1907 |
1911 @observable String kind; | 1908 @observable String kind; |
1912 @observable DateTime timestamp; | 1909 @observable DateTime timestamp; |
1913 @observable Breakpoint breakpoint; | 1910 @observable Breakpoint breakpoint; |
1914 @observable Frame topFrame; | 1911 @observable Frame topFrame; |
1915 @observable String extensionRPC; | 1912 @observable String extensionRPC; |
1916 @observable Instance exception; | 1913 @observable Instance exception; |
1917 @observable Instance asyncContinuation; | 1914 @observable Instance asyncContinuation; |
1918 @observable bool atAsyncJump; | 1915 @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.
| |
1916 @observable bool atAwait; | |
1919 @observable ServiceObject inspectee; | 1917 @observable ServiceObject inspectee; |
1920 @observable ByteData data; | 1918 @observable ByteData data; |
1921 @observable int count; | 1919 @observable int count; |
1922 @observable String reason; | 1920 @observable String reason; |
1923 @observable String exceptions; | 1921 @observable String exceptions; |
1924 @observable String bytesAsString; | 1922 @observable String bytesAsString; |
1925 @observable Map logRecord; | 1923 @observable Map logRecord; |
1926 @observable String extensionKind; | 1924 @observable String extensionKind; |
1927 @observable Map extensionData; | 1925 @observable Map extensionData; |
1928 | 1926 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1963 topFrame = map['topFrame']; | 1961 topFrame = map['topFrame']; |
1964 if (map['exception'] != null) { | 1962 if (map['exception'] != null) { |
1965 exception = map['exception']; | 1963 exception = map['exception']; |
1966 } | 1964 } |
1967 if (map['_asyncContinuation'] != null) { | 1965 if (map['_asyncContinuation'] != null) { |
1968 asyncContinuation = map['_asyncContinuation']; | 1966 asyncContinuation = map['_asyncContinuation']; |
1969 atAsyncJump = map['_atAsyncJump']; | 1967 atAsyncJump = map['_atAsyncJump']; |
1970 } else { | 1968 } else { |
1971 atAsyncJump = false; | 1969 atAsyncJump = false; |
1972 } | 1970 } |
1971 if (map['atAwait'] != null) { | |
1972 atAwait = true; | |
1973 } else { | |
1974 atAwait = false; | |
1975 } | |
1973 if (map['inspectee'] != null) { | 1976 if (map['inspectee'] != null) { |
1974 inspectee = map['inspectee']; | 1977 inspectee = map['inspectee']; |
1975 } | 1978 } |
1976 if (map['_data'] != null) { | 1979 if (map['_data'] != null) { |
1977 data = map['_data']; | 1980 data = map['_data']; |
1978 } | 1981 } |
1979 if (map['chunkIndex'] != null) { | 1982 if (map['chunkIndex'] != null) { |
1980 chunkIndex = map['chunkIndex']; | 1983 chunkIndex = map['chunkIndex']; |
1981 } | 1984 } |
1982 if (map['chunkCount'] != null) { | 1985 if (map['chunkCount'] != null) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2033 | 2036 |
2034 // Either SourceLocation or UnresolvedSourceLocation. | 2037 // Either SourceLocation or UnresolvedSourceLocation. |
2035 @observable Location location; | 2038 @observable Location location; |
2036 | 2039 |
2037 // The breakpoint is in a file which is not yet loaded. | 2040 // The breakpoint is in a file which is not yet loaded. |
2038 @observable bool latent; | 2041 @observable bool latent; |
2039 | 2042 |
2040 // The breakpoint has been assigned to a final source location. | 2043 // The breakpoint has been assigned to a final source location. |
2041 @observable bool resolved; | 2044 @observable bool resolved; |
2042 | 2045 |
2046 // The breakpoint was synthetically created as part of an 'OverAWait' resume | |
2047 // request. | |
2048 @observable bool isSyntheticAsync; | |
2049 | |
2043 void _update(ObservableMap map, bool mapIsRef) { | 2050 void _update(ObservableMap map, bool mapIsRef) { |
2044 _loaded = true; | 2051 _loaded = true; |
2045 _upgradeCollection(map, owner); | 2052 _upgradeCollection(map, owner); |
2046 | 2053 |
2047 var newNumber = map['breakpointNumber']; | 2054 var newNumber = map['breakpointNumber']; |
2048 // number never changes. | 2055 // number never changes. |
2049 assert((number == null) || (number == newNumber)); | 2056 assert((number == null) || (number == newNumber)); |
2050 number = newNumber; | 2057 number = newNumber; |
2051 resolved = map['resolved']; | 2058 resolved = map['resolved']; |
2052 | 2059 |
2053 var oldLocation = location; | 2060 var oldLocation = location; |
2054 var newLocation = map['location']; | 2061 var newLocation = map['location']; |
2055 if (oldLocation is UnresolvedSourceLocation && | 2062 if (oldLocation is UnresolvedSourceLocation && |
2056 newLocation is SourceLocation) { | 2063 newLocation is SourceLocation) { |
2057 // Breakpoint has been resolved. Remove old breakpoint. | 2064 // Breakpoint has been resolved. Remove old breakpoint. |
2058 var oldScript = oldLocation.script; | 2065 var oldScript = oldLocation.script; |
2059 if (oldScript != null && oldScript.loaded) { | 2066 if (oldScript != null && oldScript.loaded) { |
2060 oldScript._removeBreakpoint(this); | 2067 oldScript._removeBreakpoint(this); |
2061 } | 2068 } |
2062 } | 2069 } |
2063 location = newLocation; | 2070 location = newLocation; |
2064 var newScript = location.script; | 2071 var newScript = location.script; |
2065 if (newScript != null && newScript.loaded) { | 2072 if (newScript != null && newScript.loaded) { |
2066 newScript._addBreakpoint(this); | 2073 newScript._addBreakpoint(this); |
2067 } | 2074 } |
2068 | 2075 |
2076 isSyntheticAsync = map['isSyntheticAsyncBreakpoint'] != null; | |
2077 | |
2069 assert(resolved || location is UnresolvedSourceLocation); | 2078 assert(resolved || location is UnresolvedSourceLocation); |
2070 } | 2079 } |
2071 | 2080 |
2072 void remove() { | 2081 void remove() { |
2073 // Remove any references to this breakpoint. It has been removed. | 2082 // Remove any references to this breakpoint. It has been removed. |
2074 location.script._removeBreakpoint(this); | 2083 location.script._removeBreakpoint(this); |
2075 if ((isolate.pauseEvent != null) && | 2084 if ((isolate.pauseEvent != null) && |
2076 (isolate.pauseEvent.breakpoint != null) && | 2085 (isolate.pauseEvent.breakpoint != null) && |
2077 (isolate.pauseEvent.breakpoint.id == id)) { | 2086 (isolate.pauseEvent.breakpoint.id == id)) { |
2078 isolate.pauseEvent.breakpoint = null; | 2087 isolate.pauseEvent.breakpoint = null; |
2079 } | 2088 } |
2080 } | 2089 } |
2081 | 2090 |
2082 String toString() { | 2091 String toString() { |
2083 if (number != null) { | 2092 if (number != null) { |
2084 return 'Breakpoint ${number} at ${location})'; | 2093 if (isSyntheticAsync) { |
2094 return 'Async Synthetic Breakpoint ${number} at ${location}'; | |
2095 } else { | |
2096 return 'Breakpoint ${number} at ${location}'; | |
2097 } | |
2085 } else { | 2098 } else { |
2086 return 'Uninitialized breakpoint'; | 2099 return 'Uninitialized breakpoint'; |
2087 } | 2100 } |
2088 } | 2101 } |
2089 } | 2102 } |
2090 | 2103 |
2091 | 2104 |
2092 class LibraryDependency { | 2105 class LibraryDependency { |
2093 @reflectable final bool isImport; | 2106 @reflectable final bool isImport; |
2094 @reflectable final bool isDeferred; | 2107 @reflectable final bool isDeferred; |
(...skipping 1957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4052 var v = list[i]; | 4065 var v = list[i]; |
4053 if ((v is ObservableMap) && _isServiceMap(v)) { | 4066 if ((v is ObservableMap) && _isServiceMap(v)) { |
4054 list[i] = owner.getFromMap(v); | 4067 list[i] = owner.getFromMap(v); |
4055 } else if (v is ObservableList) { | 4068 } else if (v is ObservableList) { |
4056 _upgradeObservableList(v, owner); | 4069 _upgradeObservableList(v, owner); |
4057 } else if (v is ObservableMap) { | 4070 } else if (v is ObservableMap) { |
4058 _upgradeObservableMap(v, owner); | 4071 _upgradeObservableMap(v, owner); |
4059 } | 4072 } |
4060 } | 4073 } |
4061 } | 4074 } |
OLD | NEW |