| 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 /// A [ServiceObject] is an object known to the VM service and is tied | 7 /// A [ServiceObject] is an object known to the VM service and is tied |
| 8 /// to an owning [Isolate]. | 8 /// to an owning [Isolate]. |
| 9 abstract class ServiceObject extends Observable { | 9 abstract class ServiceObject extends Observable { |
| 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 /// The [VM] which owns this [ServiceObject]. | 23 /// The [VM] which owns this [ServiceObject]. |
| 24 @reflectable VM get vm => _owner.vm; | 24 @reflectable VM get vm => _owner.vm; |
| 25 | 25 |
| 26 /// The [Isolate] which owns this [ServiceObject]. May be null. | 26 /// The [Isolate] which owns this [ServiceObject]. May be null. |
| 27 @reflectable Isolate get isolate => _owner.isolate; | 27 @reflectable Isolate get isolate => _owner.isolate; |
| 28 | 28 |
| 29 /// The id of this object. | 29 /// The id of this object. |
| 30 @reflectable String get id => _id; | 30 @reflectable String get id => _id; |
| 31 String _id; | 31 String _id; |
| 32 | 32 |
| 33 /// The service type of this object. | 33 /// The user-level type of this object. |
| 34 @reflectable String get serviceType => _serviceType; | 34 @reflectable String get type => _type; |
| 35 String _serviceType; | 35 String _type; |
| 36 |
| 37 /// The vm type of this object. |
| 38 @reflectable String get vmType => _vmType; |
| 39 String _vmType; |
| 36 | 40 |
| 37 /// The complete service url of this object. | 41 /// The complete service url of this object. |
| 38 @reflectable String get link => _owner.relativeLink(_id); | 42 @reflectable String get link => _owner.relativeLink(_id); |
| 39 | 43 |
| 40 /// Has this object been fully loaded? | 44 /// Has this object been fully loaded? |
| 41 bool get loaded => _loaded; | 45 bool get loaded => _loaded; |
| 42 bool _loaded = false; | 46 bool _loaded = false; |
| 43 // TODO(turnidge): Make loaded observable and get rid of loading | 47 // TODO(turnidge): Make loaded observable and get rid of loading |
| 44 // from Isolate. | 48 // from Isolate. |
| 45 | 49 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 return reload(); | 130 return reload(); |
| 127 } | 131 } |
| 128 | 132 |
| 129 Future<ServiceObject> _inProgressReload; | 133 Future<ServiceObject> _inProgressReload; |
| 130 | 134 |
| 131 /// Reload [this]. Returns a future which completes to [this] or | 135 /// Reload [this]. Returns a future which completes to [this] or |
| 132 /// a [ServiceError]. | 136 /// a [ServiceError]. |
| 133 Future<ServiceObject> reload() { | 137 Future<ServiceObject> reload() { |
| 134 if (id == '') { | 138 if (id == '') { |
| 135 // Errors don't have ids. | 139 // Errors don't have ids. |
| 136 assert(serviceType == 'Error'); | 140 assert(type == 'Error'); |
| 137 return new Future.value(this); | 141 return new Future.value(this); |
| 138 } | 142 } |
| 139 if (loaded && immutable) { | 143 if (loaded && immutable) { |
| 140 return new Future.value(this); | 144 return new Future.value(this); |
| 141 } | 145 } |
| 142 if (_inProgressReload == null) { | 146 if (_inProgressReload == null) { |
| 143 _inProgressReload = vm.getAsMap(link).then((ObservableMap map) { | 147 _inProgressReload = vm.getAsMap(link).then((ObservableMap map) { |
| 144 var mapType = _stripRef(map['type']); | 148 var mapType = _stripRef(map['type']); |
| 145 if (mapType != _serviceType) { | 149 if (mapType != _type) { |
| 146 // If the type changes, return a new object instead of | 150 // If the type changes, return a new object instead of |
| 147 // updating the existing one. | 151 // updating the existing one. |
| 152 // |
| 153 // TODO(turnidge): Check for vmType changing as well? |
| 148 assert(mapType == 'Error' || mapType == 'Null'); | 154 assert(mapType == 'Error' || mapType == 'Null'); |
| 149 return new ServiceObject._fromMap(owner, map); | 155 return new ServiceObject._fromMap(owner, map); |
| 150 } | 156 } |
| 151 update(map); | 157 update(map); |
| 152 return this; | 158 return this; |
| 153 }).whenComplete(() { | 159 }).whenComplete(() { |
| 154 // This reload is complete. | 160 // This reload is complete. |
| 155 _inProgressReload = null; | 161 _inProgressReload = null; |
| 156 }); | 162 }); |
| 157 } | 163 } |
| 158 return _inProgressReload; | 164 return _inProgressReload; |
| 159 } | 165 } |
| 160 | 166 |
| 161 /// Update [this] using [map] as a source. [map] can be a reference. | 167 /// Update [this] using [map] as a source. [map] can be a reference. |
| 162 void update(ObservableMap map) { | 168 void update(ObservableMap map) { |
| 163 assert(_isServiceMap(map)); | 169 assert(_isServiceMap(map)); |
| 164 | 170 |
| 165 // Don't allow the type to change on an object update. | 171 // Don't allow the type to change on an object update. |
| 166 // TODO(turnidge): Make this a ServiceError? | 172 // TODO(turnidge): Make this a ServiceError? |
| 167 var mapIsRef = _hasRef(map['type']); | 173 var mapIsRef = _hasRef(map['type']); |
| 168 var mapType = _stripRef(map['type']); | 174 var mapType = _stripRef(map['type']); |
| 169 assert(_serviceType == null || _serviceType == mapType); | 175 assert(_type == null || _type == mapType); |
| 170 | 176 |
| 171 if (_id != null && _id != map['id']) { | 177 if (_id != null && _id != map['id']) { |
| 172 // It is only safe to change an id when the object isn't cacheable. | 178 // It is only safe to change an id when the object isn't cacheable. |
| 173 assert(!canCache); | 179 assert(!canCache); |
| 174 } | 180 } |
| 175 _id = map['id']; | 181 _id = map['id']; |
| 176 | 182 |
| 177 _serviceType = mapType; | 183 _type = mapType; |
| 184 |
| 185 // When the response specifies a specific vmType, use it. |
| 186 // Otherwise the vmType of the response is the same as the 'user' |
| 187 // type. |
| 188 if (map.containsKey('vmType')) { |
| 189 _vmType = _stripRef(map['vmType']); |
| 190 } else { |
| 191 _vmType = _type; |
| 192 } |
| 193 |
| 178 _update(map, mapIsRef); | 194 _update(map, mapIsRef); |
| 179 } | 195 } |
| 180 | 196 |
| 181 // Updates internal state from [map]. [map] can be a reference. | 197 // Updates internal state from [map]. [map] can be a reference. |
| 182 void _update(ObservableMap map, bool mapIsRef); | 198 void _update(ObservableMap map, bool mapIsRef); |
| 183 | 199 |
| 184 String relativeLink(String id) { | 200 String relativeLink(String id) { |
| 185 assert(id != null); | 201 assert(id != null); |
| 186 return "${link}/${id}"; | 202 return "${link}/${id}"; |
| 187 } | 203 } |
| 188 } | 204 } |
| 189 | 205 |
| 190 abstract class Coverage { | 206 abstract class Coverage { |
| 191 // Following getters and functions will be provided by [ServiceObject]. | 207 // Following getters and functions will be provided by [ServiceObject]. |
| 192 ServiceObjectOwner get owner; | 208 ServiceObjectOwner get owner; |
| 193 String get serviceType; | 209 String get type; |
| 194 VM get vm; | 210 VM get vm; |
| 195 String relativeLink(String id); | 211 String relativeLink(String id); |
| 196 | 212 |
| 197 /// Default handler for coverage data. | 213 /// Default handler for coverage data. |
| 198 void processCoverageData(List coverageData) { | 214 void processCoverageData(List coverageData) { |
| 199 coverageData.forEach((scriptCoverage) { | 215 coverageData.forEach((scriptCoverage) { |
| 200 assert(scriptCoverage['script'] != null); | 216 assert(scriptCoverage['script'] != null); |
| 201 scriptCoverage['script']._processHits(scriptCoverage['hits']); | 217 scriptCoverage['script']._processHits(scriptCoverage['hits']); |
| 202 }); | 218 }); |
| 203 } | 219 } |
| 204 | 220 |
| 205 Future refreshCoverage() { | 221 Future refreshCoverage() { |
| 206 return vm.getAsMap(relativeLink('coverage')).then((ObservableMap map) { | 222 return vm.getAsMap(relativeLink('coverage')).then((ObservableMap map) { |
| 207 var coverageOwner = (serviceType == 'Isolate') ? this : owner; | 223 var coverageOwner = (type == 'Isolate') ? this : owner; |
| 208 var coverage = new ServiceObject._fromMap(coverageOwner, map); | 224 var coverage = new ServiceObject._fromMap(coverageOwner, map); |
| 209 assert(coverage.serviceType == 'CodeCoverage'); | 225 assert(coverage.type == 'CodeCoverage'); |
| 210 var coverageList = coverage['coverage']; | 226 var coverageList = coverage['coverage']; |
| 211 assert(coverageList != null); | 227 assert(coverageList != null); |
| 212 processCoverageData(coverageList); | 228 processCoverageData(coverageList); |
| 213 }); | 229 }); |
| 214 } | 230 } |
| 215 } | 231 } |
| 216 | 232 |
| 217 abstract class ServiceObjectOwner extends ServiceObject { | 233 abstract class ServiceObjectOwner extends ServiceObject { |
| 218 /// Creates an empty [ServiceObjectOwner]. | 234 /// Creates an empty [ServiceObjectOwner]. |
| 219 ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner); | 235 ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner); |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 | 640 |
| 625 static const TAG_ROOT_ID = 'code/tag-0'; | 641 static const TAG_ROOT_ID = 'code/tag-0'; |
| 626 | 642 |
| 627 /// Returns the Code object for the root tag. | 643 /// Returns the Code object for the root tag. |
| 628 Code tagRoot() { | 644 Code tagRoot() { |
| 629 // TODO(turnidge): Use get() here instead? | 645 // TODO(turnidge): Use get() here instead? |
| 630 return _cache[TAG_ROOT_ID]; | 646 return _cache[TAG_ROOT_ID]; |
| 631 } | 647 } |
| 632 | 648 |
| 633 void processProfile(ServiceMap profile) { | 649 void processProfile(ServiceMap profile) { |
| 634 assert(profile.serviceType == 'Profile'); | 650 assert(profile.type == 'Profile'); |
| 635 var codeTable = new List<Code>(); | 651 var codeTable = new List<Code>(); |
| 636 var codeRegions = profile['codes']; | 652 var codeRegions = profile['codes']; |
| 637 for (var codeRegion in codeRegions) { | 653 for (var codeRegion in codeRegions) { |
| 638 Code code = codeRegion['code']; | 654 Code code = codeRegion['code']; |
| 639 assert(code != null); | 655 assert(code != null); |
| 640 codeTable.add(code); | 656 codeTable.add(code); |
| 641 } | 657 } |
| 642 _resetProfileData(); | 658 _resetProfileData(); |
| 643 _updateProfileData(profile, codeTable); | 659 _updateProfileData(profile, codeTable); |
| 644 var exclusiveTrie = profile['exclusive_trie']; | 660 var exclusiveTrie = profile['exclusive_trie']; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 666 } | 682 } |
| 667 | 683 |
| 668 /// Fetches and builds the class hierarchy for this isolate. Returns the | 684 /// Fetches and builds the class hierarchy for this isolate. Returns the |
| 669 /// Object class object. | 685 /// Object class object. |
| 670 Future<Class> getClassHierarchy() { | 686 Future<Class> getClassHierarchy() { |
| 671 return get('classes').then(_loadClasses).then(_buildClassHierarchy); | 687 return get('classes').then(_loadClasses).then(_buildClassHierarchy); |
| 672 } | 688 } |
| 673 | 689 |
| 674 /// Given the class list, loads each class. | 690 /// Given the class list, loads each class. |
| 675 Future<List<Class>> _loadClasses(ServiceMap classList) { | 691 Future<List<Class>> _loadClasses(ServiceMap classList) { |
| 676 assert(classList.serviceType == 'ClassList'); | 692 assert(classList.type == 'ClassList'); |
| 677 var futureClasses = []; | 693 var futureClasses = []; |
| 678 for (var cls in classList['members']) { | 694 for (var cls in classList['members']) { |
| 679 // Skip over non-class classes. | 695 // Skip over non-class classes. |
| 680 if (cls is Class) { | 696 if (cls is Class) { |
| 681 futureClasses.add(cls.load()); | 697 futureClasses.add(cls.load()); |
| 682 } | 698 } |
| 683 } | 699 } |
| 684 return Future.wait(futureClasses); | 700 return Future.wait(futureClasses); |
| 685 } | 701 } |
| 686 | 702 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 mainPort = map['mainPort']; | 783 mainPort = map['mainPort']; |
| 768 name = map['name']; | 784 name = map['name']; |
| 769 vmName = map['name']; | 785 vmName = map['name']; |
| 770 if (mapIsRef) { | 786 if (mapIsRef) { |
| 771 return; | 787 return; |
| 772 } | 788 } |
| 773 _loaded = true; | 789 _loaded = true; |
| 774 loading = false; | 790 loading = false; |
| 775 | 791 |
| 776 reloadBreakpoints(); | 792 reloadBreakpoints(); |
| 777 | |
| 778 // Remap DebuggerEvent to ServiceEvent so that the observatory can | |
| 779 // work against 1.5 vms in the short term. | |
| 780 // | |
| 781 // TODO(turnidge): Remove this when no longer needed. | |
| 782 var pause = map['pauseEvent']; | |
| 783 if (pause != null) { | |
| 784 if (pause['type'] == 'DebuggerEvent') { | |
| 785 pause['type'] = 'ServiceEvent'; | |
| 786 } | |
| 787 } | |
| 788 | |
| 789 _upgradeCollection(map, isolate); | 793 _upgradeCollection(map, isolate); |
| 790 if (map['rootLib'] == null || | 794 if (map['rootLib'] == null || |
| 791 map['timers'] == null || | 795 map['timers'] == null || |
| 792 map['heaps'] == null) { | 796 map['heaps'] == null) { |
| 793 Logger.root.severe("Malformed 'Isolate' response: $map"); | 797 Logger.root.severe("Malformed 'Isolate' response: $map"); |
| 794 return; | 798 return; |
| 795 } | 799 } |
| 796 rootLib = map['rootLib']; | 800 rootLib = map['rootLib']; |
| 797 if (map['entry'] != null) { | 801 if (map['entry'] != null) { |
| 798 entry = map['entry']; | 802 entry = map['entry']; |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 | 1093 |
| 1090 String toString() => "Isolate($_id)"; | 1094 String toString() => "Isolate($_id)"; |
| 1091 } | 1095 } |
| 1092 | 1096 |
| 1093 /// A [ServiceObject] which implements [ObservableMap]. | 1097 /// A [ServiceObject] which implements [ObservableMap]. |
| 1094 class ServiceMap extends ServiceObject implements ObservableMap { | 1098 class ServiceMap extends ServiceObject implements ObservableMap { |
| 1095 final ObservableMap _map = new ObservableMap(); | 1099 final ObservableMap _map = new ObservableMap(); |
| 1096 static String objectIdRingPrefix = 'objects/'; | 1100 static String objectIdRingPrefix = 'objects/'; |
| 1097 | 1101 |
| 1098 bool get canCache { | 1102 bool get canCache { |
| 1099 return (_serviceType == 'Class' || | 1103 return (_type == 'Class' || |
| 1100 _serviceType == 'Function' || | 1104 _type == 'Function' || |
| 1101 _serviceType == 'Field') && | 1105 _type == 'Field') && |
| 1102 !_id.startsWith(objectIdRingPrefix); | 1106 !_id.startsWith(objectIdRingPrefix); |
| 1103 } | 1107 } |
| 1104 bool get immutable => false; | 1108 bool get immutable => false; |
| 1105 | 1109 |
| 1106 ServiceMap._empty(ServiceObjectOwner owner) : super._empty(owner); | 1110 ServiceMap._empty(ServiceObjectOwner owner) : super._empty(owner); |
| 1107 | 1111 |
| 1108 void _upgradeValues() { | 1112 void _upgradeValues() { |
| 1109 assert(owner != null); | 1113 assert(owner != null); |
| 1110 _upgradeCollection(_map, owner); | 1114 _upgradeCollection(_map, owner); |
| 1111 } | 1115 } |
| (...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 metric.reload().then((m) { | 2354 metric.reload().then((m) { |
| 2351 m.addSample(new MetricSample(m.value)); | 2355 m.addSample(new MetricSample(m.value)); |
| 2352 }); | 2356 }); |
| 2353 } | 2357 } |
| 2354 } | 2358 } |
| 2355 } | 2359 } |
| 2356 | 2360 |
| 2357 // Convert any ServiceMaps representing a null instance into an actual null. | 2361 // Convert any ServiceMaps representing a null instance into an actual null. |
| 2358 _convertNull(obj) { | 2362 _convertNull(obj) { |
| 2359 if (obj is ServiceMap && | 2363 if (obj is ServiceMap && |
| 2360 obj.serviceType == 'Null') { | 2364 obj.type == 'Null') { |
| 2361 return null; | 2365 return null; |
| 2362 } | 2366 } |
| 2363 return obj; | 2367 return obj; |
| 2364 } | 2368 } |
| 2365 | 2369 |
| 2366 // Returns true if [map] is a service map. i.e. it has the following keys: | 2370 // Returns true if [map] is a service map. i.e. it has the following keys: |
| 2367 // 'id' and a 'type'. | 2371 // 'id' and a 'type'. |
| 2368 bool _isServiceMap(ObservableMap m) { | 2372 bool _isServiceMap(ObservableMap m) { |
| 2369 return (m != null) && (m['id'] != null) && (m['type'] != null); | 2373 return (m != null) && (m['id'] != null) && (m['type'] != null); |
| 2370 } | 2374 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 var v = list[i]; | 2407 var v = list[i]; |
| 2404 if ((v is ObservableMap) && _isServiceMap(v)) { | 2408 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 2405 list[i] = owner.getFromMap(v); | 2409 list[i] = owner.getFromMap(v); |
| 2406 } else if (v is ObservableList) { | 2410 } else if (v is ObservableList) { |
| 2407 _upgradeObservableList(v, owner); | 2411 _upgradeObservableList(v, owner); |
| 2408 } else if (v is ObservableMap) { | 2412 } else if (v is ObservableMap) { |
| 2409 _upgradeObservableMap(v, owner); | 2413 _upgradeObservableMap(v, owner); |
| 2410 } | 2414 } |
| 2411 } | 2415 } |
| 2412 } | 2416 } |
| OLD | NEW |