| 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 /// An RpcException represents an exceptional event that happened |
| 8 /// while invoking an rpc. |
| 9 abstract class RpcException implements Exception { |
| 10 RpcException(this.message); |
| 11 |
| 12 String message; |
| 13 } |
| 14 |
| 15 /// A ServerRpcException represents an error returned by the VM. |
| 16 class ServerRpcException extends RpcException { |
| 17 /// A list of well-known server error codes. |
| 18 static const kParseError = -32700; |
| 19 static const kInvalidRequest = -32600; |
| 20 static const kMethodNotFound = -32601; |
| 21 static const kInvalidParams = -32602; |
| 22 static const kInternalError = -32603; |
| 23 static const kVMMustBePaused = 100; |
| 24 static const kNoBreakAtLine = 101; |
| 25 static const kNoBreakAtFunction = 102; |
| 26 static const kProfilingDisabled = 200; |
| 27 |
| 28 int code; |
| 29 Map data; |
| 30 |
| 31 static _getMessage(Map errorMap) { |
| 32 Map data = errorMap['data']; |
| 33 if (data != null && data['details'] != null) { |
| 34 return data['details']; |
| 35 } else { |
| 36 return errorMap['message']; |
| 37 } |
| 38 } |
| 39 |
| 40 ServerRpcException.fromMap(Map errorMap) : super(_getMessage(errorMap)) { |
| 41 code = errorMap['code']; |
| 42 data = errorMap['data']; |
| 43 } |
| 44 |
| 45 String toString() => 'ServerRpcException(${message})'; |
| 46 } |
| 47 |
| 48 /// A NetworkRpcException is used to indicate that an rpc has |
| 49 /// been canceled due to network error. |
| 50 class NetworkRpcException extends RpcException { |
| 51 NetworkRpcException(String message) : super(message); |
| 52 |
| 53 String toString() => 'NetworkRpcException(${message})'; |
| 54 } |
| 55 |
| 56 class MalformedResponseRpcException extends RpcException { |
| 57 MalformedResponseRpcException(String message, this.response) |
| 58 : super(message); |
| 59 |
| 60 Map response; |
| 61 |
| 62 String toString() => 'MalformedResponseRpcException(${message})'; |
| 63 } |
| 64 |
| 65 class FakeVMRpcException extends RpcException { |
| 66 FakeVMRpcException(String message) : super(message); |
| 67 |
| 68 String toString() => 'FakeVMRpcException(${message})'; |
| 69 } |
| 70 |
| 7 /// A [ServiceObject] represents a persistent object within the vm. | 71 /// A [ServiceObject] represents a persistent object within the vm. |
| 8 abstract class ServiceObject extends Observable { | 72 abstract class ServiceObject extends Observable { |
| 9 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 73 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
| 10 return o1.name.compareTo(o2.name); | 74 return o1.name.compareTo(o2.name); |
| 11 } | 75 } |
| 12 | 76 |
| 13 List removeDuplicatesAndSortLexical(List<ServiceObject> list) { | 77 List removeDuplicatesAndSortLexical(List<ServiceObject> list) { |
| 14 return list.toSet().toList()..sort(LexicalSortName); | 78 return list.toSet().toList()..sort(LexicalSortName); |
| 15 } | 79 } |
| 16 | 80 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 obj = new PcDescriptors._empty(owner); | 227 obj = new PcDescriptors._empty(owner); |
| 164 break; | 228 break; |
| 165 case 'LocalVarDescriptors': | 229 case 'LocalVarDescriptors': |
| 166 obj = new LocalVarDescriptors._empty(owner); | 230 obj = new LocalVarDescriptors._empty(owner); |
| 167 break; | 231 break; |
| 168 case 'TokenStream': | 232 case 'TokenStream': |
| 169 obj = new TokenStream._empty(owner); | 233 obj = new TokenStream._empty(owner); |
| 170 break; | 234 break; |
| 171 } | 235 } |
| 172 break; | 236 break; |
| 173 case 'ServiceError': | |
| 174 obj = new ServiceError._empty(owner); | |
| 175 break; | |
| 176 case 'ServiceEvent': | 237 case 'ServiceEvent': |
| 177 obj = new ServiceEvent._empty(owner); | 238 obj = new ServiceEvent._empty(owner); |
| 178 break; | 239 break; |
| 179 case 'ServiceException': | |
| 180 obj = new ServiceException._empty(owner); | |
| 181 break; | |
| 182 case 'Script': | 240 case 'Script': |
| 183 obj = new Script._empty(owner); | 241 obj = new Script._empty(owner); |
| 184 break; | 242 break; |
| 185 case 'Socket': | 243 case 'Socket': |
| 186 obj = new Socket._empty(owner); | 244 obj = new Socket._empty(owner); |
| 187 break; | 245 break; |
| 188 default: | 246 default: |
| 189 if (_isInstanceType(type) || | 247 if (_isInstanceType(type) || |
| 190 type == 'Sentinel') { // TODO(rmacnak): Separate this out. | 248 type == 'Sentinel') { // TODO(rmacnak): Separate this out. |
| 191 obj = new Instance._empty(owner); | 249 obj = new Instance._empty(owner); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 212 Future<ServiceObject> _inProgressReload; | 270 Future<ServiceObject> _inProgressReload; |
| 213 | 271 |
| 214 Future<ObservableMap> _fetchDirect() { | 272 Future<ObservableMap> _fetchDirect() { |
| 215 Map params = { | 273 Map params = { |
| 216 'objectId': id, | 274 'objectId': id, |
| 217 }; | 275 }; |
| 218 return isolate.invokeRpcNoUpgrade('getObject', params); | 276 return isolate.invokeRpcNoUpgrade('getObject', params); |
| 219 } | 277 } |
| 220 | 278 |
| 221 /// Reload [this]. Returns a future which completes to [this] or | 279 /// Reload [this]. Returns a future which completes to [this] or |
| 222 /// a [ServiceError]. | 280 /// an exception. |
| 223 Future<ServiceObject> reload() { | 281 Future<ServiceObject> reload() { |
| 224 if (id == '') { | 282 // TODO(turnidge): Checkign for a null id should be part of the |
| 225 // Errors don't have ids. | 283 // "immmutable" check. |
| 226 assert(type == 'Error'); | 284 if (id == null || id == '') { |
| 227 return new Future.value(this); | 285 return new Future.value(this); |
| 228 } | 286 } |
| 229 if (loaded && immutable) { | 287 if (loaded && immutable) { |
| 230 return new Future.value(this); | 288 return new Future.value(this); |
| 231 } | 289 } |
| 232 if (_inProgressReload == null) { | 290 if (_inProgressReload == null) { |
| 233 _inProgressReload = _fetchDirect().then((ObservableMap map) { | 291 var completer = new Completer<ServiceObject>(); |
| 234 var mapType = _stripRef(map['type']); | 292 _inProgressReload = completer.future; |
| 235 if (mapType != _type) { | 293 _fetchDirect().then((ObservableMap map) { |
| 236 // If the type changes, return a new object instead of | 294 var mapType = _stripRef(map['type']); |
| 237 // updating the existing one. | 295 if (mapType == 'Sentinel') { |
| 238 // | 296 // An object may have been collected, etc. |
| 239 // TODO(turnidge): Check for vmType changing as well? | 297 completer.complete(new ServiceObject._fromMap(owner, map)); |
| 240 assert(mapType == 'Error' || mapType == 'Sentinel'); | 298 } else { |
| 241 return new ServiceObject._fromMap(owner, map); | 299 // TODO(turnidge): Check for vmType changing as well? |
| 242 } | 300 assert(mapType == _type); |
| 243 update(map); | 301 update(map); |
| 244 return this; | 302 completer.complete(this); |
| 303 } |
| 304 |
| 305 }).catchError((e, st) { |
| 306 Logger.root.severe("Unable to reload object: $e\n$st"); |
| 307 _inProgressReload = null; |
| 308 completer.completeError(e, st); |
| 245 }).whenComplete(() { | 309 }).whenComplete(() { |
| 246 // This reload is complete. | 310 // This reload is complete. |
| 247 _inProgressReload = null; | 311 _inProgressReload = null; |
| 248 }); | 312 }); |
| 249 } | 313 } |
| 250 return _inProgressReload; | 314 return _inProgressReload; |
| 251 } | 315 } |
| 252 | 316 |
| 253 /// Update [this] using [map] as a source. [map] can be a reference. | 317 /// Update [this] using [map] as a source. [map] can be a reference. |
| 254 void update(ObservableMap map) { | 318 void update(ObservableMap map) { |
| 255 assert(_isServiceMap(map)); | 319 assert(_isServiceMap(map)); |
| 256 | 320 |
| 257 // Don't allow the type to change on an object update. | 321 // Don't allow the type to change on an object update. |
| 258 // TODO(turnidge): Make this a ServiceError? | |
| 259 var mapIsRef = _hasRef(map['type']); | 322 var mapIsRef = _hasRef(map['type']); |
| 260 var mapType = _stripRef(map['type']); | 323 var mapType = _stripRef(map['type']); |
| 261 assert(_type == null || _type == mapType); | 324 assert(_type == null || _type == mapType); |
| 262 | 325 |
| 263 if (_id != null && _id != map['id']) { | 326 if (_id != null && _id != map['id']) { |
| 264 // It is only safe to change an id when the object isn't cacheable. | 327 // It is only safe to change an id when the object isn't cacheable. |
| 265 assert(!canCache); | 328 assert(!canCache); |
| 266 } | 329 } |
| 267 _id = map['id']; | 330 _id = map['id']; |
| 268 | 331 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 /// The result may come from the cache. The result will not necessarily | 394 /// The result may come from the cache. The result will not necessarily |
| 332 /// be [loaded]. | 395 /// be [loaded]. |
| 333 ServiceObject getFromMap(ObservableMap map); | 396 ServiceObject getFromMap(ObservableMap map); |
| 334 } | 397 } |
| 335 | 398 |
| 336 /// State for a VM being inspected. | 399 /// State for a VM being inspected. |
| 337 abstract class VM extends ServiceObjectOwner { | 400 abstract class VM extends ServiceObjectOwner { |
| 338 @reflectable VM get vm => this; | 401 @reflectable VM get vm => this; |
| 339 @reflectable Isolate get isolate => null; | 402 @reflectable Isolate get isolate => null; |
| 340 | 403 |
| 404 // TODO(turnidge): The connection should not be stored in the VM object. |
| 405 bool get isDisconnected; |
| 406 |
| 341 // TODO(johnmccutchan): Ensure that isolates do not end up in _cache. | 407 // TODO(johnmccutchan): Ensure that isolates do not end up in _cache. |
| 342 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); | 408 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); |
| 343 final ObservableMap<String,Isolate> _isolateCache = | 409 final ObservableMap<String,Isolate> _isolateCache = |
| 344 new ObservableMap<String,Isolate>(); | 410 new ObservableMap<String,Isolate>(); |
| 345 | 411 |
| 346 @reflectable Iterable<Isolate> get isolates => _isolateCache.values; | 412 @reflectable Iterable<Isolate> get isolates => _isolateCache.values; |
| 347 | 413 |
| 348 @observable String version = 'unknown'; | 414 @observable String version = 'unknown'; |
| 349 @observable String targetCPU; | 415 @observable String targetCPU; |
| 350 @observable int architectureBits; | 416 @observable int architectureBits; |
| 351 @observable bool assertsEnabled = false; | 417 @observable bool assertsEnabled = false; |
| 352 @observable bool typeChecksEnabled = false; | 418 @observable bool typeChecksEnabled = false; |
| 353 @observable String pid = ''; | 419 @observable String pid = ''; |
| 354 @observable DateTime startTime; | 420 @observable DateTime startTime; |
| 355 @observable DateTime refreshTime; | 421 @observable DateTime refreshTime; |
| 356 @observable Duration get upTime => | 422 @observable Duration get upTime => |
| 357 (new DateTime.now().difference(startTime)); | 423 (new DateTime.now().difference(startTime)); |
| 358 | 424 |
| 359 VM() : super._empty(null) { | 425 VM() : super._empty(null) { |
| 360 name = 'vm'; | 426 name = 'vm'; |
| 361 vmName = 'vm'; | 427 vmName = 'vm'; |
| 362 _cache['vm'] = this; | 428 _cache['vm'] = this; |
| 363 update(toObservable({'id':'vm', 'type':'@VM'})); | 429 update(toObservable({'id':'vm', 'type':'@VM'})); |
| 364 } | 430 } |
| 365 | 431 |
| 366 final StreamController<ServiceException> exceptions = | |
| 367 new StreamController.broadcast(); | |
| 368 final StreamController<ServiceError> errors = | |
| 369 new StreamController.broadcast(); | |
| 370 final StreamController<ServiceEvent> events = | 432 final StreamController<ServiceEvent> events = |
| 371 new StreamController.broadcast(); | 433 new StreamController.broadcast(); |
| 372 | 434 |
| 373 void postServiceEvent(Map response, ByteData data) { | 435 void postServiceEvent(Map response, ByteData data) { |
| 374 var map = toObservable(response); | 436 var map = toObservable(response); |
| 375 assert(!map.containsKey('_data')); | 437 assert(!map.containsKey('_data')); |
| 376 if (data != null) { | 438 if (data != null) { |
| 377 map['_data'] = data; | 439 map['_data'] = data; |
| 378 } | 440 } |
| 379 if (map['type'] != 'ServiceEvent') { | 441 if (map['type'] != 'ServiceEvent') { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 // Note that this function does not reload the isolate if it found | 515 // Note that this function does not reload the isolate if it found |
| 454 // in the cache. | 516 // in the cache. |
| 455 Future<ServiceObject> getIsolate(String isolateId) { | 517 Future<ServiceObject> getIsolate(String isolateId) { |
| 456 if (!loaded) { | 518 if (!loaded) { |
| 457 // Trigger a VM load, then get the isolate. | 519 // Trigger a VM load, then get the isolate. |
| 458 return load().then((_) => getIsolate(isolateId)).catchError(_ignoreError); | 520 return load().then((_) => getIsolate(isolateId)).catchError(_ignoreError); |
| 459 } | 521 } |
| 460 return new Future.value(_isolateCache[isolateId]); | 522 return new Future.value(_isolateCache[isolateId]); |
| 461 } | 523 } |
| 462 | 524 |
| 463 Future<ObservableMap> _processMap(ObservableMap map) { | |
| 464 // Verify that the top level response is a service map. | |
| 465 if (!_isServiceMap(map)) { | |
| 466 return new Future.error( | |
| 467 new ServiceObject._fromMap(this, toObservable({ | |
| 468 'type': 'ServiceException', | |
| 469 'kind': 'ResponseFormatException', | |
| 470 'response': map, | |
| 471 'message': "Response is missing the 'type' field.", | |
| 472 }))); | |
| 473 } | |
| 474 // Preemptively capture ServiceError and ServiceExceptions. | |
| 475 if (map['type'] == 'ServiceError') { | |
| 476 return new Future.error(new ServiceObject._fromMap(this, map)); | |
| 477 } else if (map['type'] == 'ServiceException') { | |
| 478 return new Future.error(new ServiceObject._fromMap(this, map)); | |
| 479 } | |
| 480 // map is now guaranteed to be a non-error/exception ServiceObject. | |
| 481 return new Future.value(map); | |
| 482 } | |
| 483 | |
| 484 // Implemented in subclass. | 525 // Implemented in subclass. |
| 485 Future<Map> invokeRpcRaw(String method, Map params); | 526 Future<Map> invokeRpcRaw(String method, Map params); |
| 486 | 527 |
| 487 Future<ObservableMap> invokeRpcNoUpgrade(String method, Map params) { | 528 Future<ObservableMap> invokeRpcNoUpgrade(String method, Map params) { |
| 488 return invokeRpcRaw(method, params).then((Map response) { | 529 return invokeRpcRaw(method, params).then((Map response) { |
| 489 var map = toObservable(response); | 530 var map = toObservable(response); |
| 490 if (Tracer.current != null) { | 531 if (Tracer.current != null) { |
| 491 Tracer.current.trace("Received response for ${method}/${params}}", | 532 Tracer.current.trace("Received response for ${method}/${params}}", |
| 492 map:map); | 533 map:map); |
| 493 } | 534 } |
| 494 | 535 if (!_isServiceMap(map)) { |
| 495 // Check for ill-formed responses. | 536 var exception = |
| 496 return _processMap(map); | 537 new MalformedResponseRpcException( |
| 497 }).catchError((error) { | 538 "Response is missing the 'type' field", map); |
| 498 | 539 return new Future.error(exception); |
| 499 // ServiceError, forward to VM's ServiceError stream. | 540 } |
| 500 errors.add(error); | 541 return new Future.value(map); |
| 501 return new Future.error(error); | 542 }).catchError((e) { |
| 502 }, test: (e) => e is ServiceError).catchError((exception) { | 543 // Errors pass through. |
| 503 | 544 return new Future.error(e); |
| 504 // ServiceException, forward to VM's ServiceException stream. | 545 }); |
| 505 exceptions.add(exception); | |
| 506 return new Future.error(exception); | |
| 507 }, test: (e) => e is ServiceException); | |
| 508 } | 546 } |
| 509 | 547 |
| 510 Future<ServiceObject> invokeRpc(String method, Map params) { | 548 Future<ServiceObject> invokeRpc(String method, Map params) { |
| 511 return invokeRpcNoUpgrade(method, params).then((ObservableMap response) { | 549 return invokeRpcNoUpgrade(method, params).then((ObservableMap response) { |
| 512 var obj = new ServiceObject._fromMap(this, response); | 550 var obj = new ServiceObject._fromMap(this, response); |
| 513 if ((obj != null) && obj.canCache) { | 551 if ((obj != null) && obj.canCache) { |
| 514 String objId = obj.id; | 552 String objId = obj.id; |
| 515 _cache.putIfAbsent(objId, () => obj); | 553 _cache.putIfAbsent(objId, () => obj); |
| 516 } | 554 } |
| 517 return obj; | 555 return obj; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 Future get onConnect { | 651 Future get onConnect { |
| 614 if (_onConnect != null) { | 652 if (_onConnect != null) { |
| 615 return _onConnect; | 653 return _onConnect; |
| 616 } | 654 } |
| 617 _onConnect = new Future.value(this); | 655 _onConnect = new Future.value(this); |
| 618 return _onConnect; | 656 return _onConnect; |
| 619 } | 657 } |
| 620 // Only complete when requested. | 658 // Only complete when requested. |
| 621 Completer _onDisconnect = new Completer(); | 659 Completer _onDisconnect = new Completer(); |
| 622 Future get onDisconnect => _onDisconnect.future; | 660 Future get onDisconnect => _onDisconnect.future; |
| 661 bool get isDisconnected => _onDisconnect.isCompleted; |
| 623 | 662 |
| 624 Future<Map> invokeRpcRaw(String method, Map params) { | 663 Future<Map> invokeRpcRaw(String method, Map params) { |
| 625 if (params.isEmpty) { | 664 if (params.isEmpty) { |
| 626 params = null; | 665 params = null; |
| 627 } | 666 } |
| 628 var key = _canonicalizeUri(new Uri(path: method, queryParameters: params)); | 667 var key = _canonicalizeUri(new Uri(path: method, queryParameters: params)); |
| 629 var response = _responses[key]; | 668 var response = _responses[key]; |
| 630 if (response == null) { | 669 if (response == null) { |
| 631 return new Future.error({ | 670 return new Future.error(new FakeVMRpcException( |
| 632 'type': 'ServiceException', | 671 "Unable to find key '${key}' in cached response set")); |
| 633 'kind': 'NotContainedInResponses', | |
| 634 'key': key | |
| 635 }); | |
| 636 } | 672 } |
| 637 return new Future.value(response); | 673 return new Future.value(response); |
| 638 } | 674 } |
| 639 } | 675 } |
| 640 | 676 |
| 641 | 677 |
| 642 /// Snapshot in time of tag counters. | 678 /// Snapshot in time of tag counters. |
| 643 class TagProfileSnapshot { | 679 class TagProfileSnapshot { |
| 644 final double seconds; | 680 final double seconds; |
| 645 final List<int> counters; | 681 final List<int> counters; |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 // Ignore GC events for now. | 1138 // Ignore GC events for now. |
| 1103 break; | 1139 break; |
| 1104 | 1140 |
| 1105 default: | 1141 default: |
| 1106 // Log unrecognized events. | 1142 // Log unrecognized events. |
| 1107 Logger.root.severe('Unrecognized event: $event'); | 1143 Logger.root.severe('Unrecognized event: $event'); |
| 1108 break; | 1144 break; |
| 1109 } | 1145 } |
| 1110 } | 1146 } |
| 1111 | 1147 |
| 1112 Future<ServiceObject> addBreakpoint(Script script, int line) { | 1148 Future<ServiceObject> addBreakpoint(Script script, int line) async { |
| 1113 // TODO(turnidge): Pass line as an int instead of a string. | 1149 // TODO(turnidge): Pass line as an int instead of a string. |
| 1114 Map params = { | 1150 try { |
| 1115 'scriptId': script.id, | 1151 Map params = { |
| 1116 'line': '$line', | 1152 'scriptId': script.id, |
| 1117 }; | 1153 'line': '$line', |
| 1118 return invokeRpc('addBreakpoint', params).then((result) { | 1154 }; |
| 1119 if (result is DartError) { | 1155 Breakpoint bpt = await invokeRpc('addBreakpoint', params); |
| 1120 return result; | |
| 1121 } | |
| 1122 Breakpoint bpt = result; | |
| 1123 if (bpt.resolved && | 1156 if (bpt.resolved && |
| 1124 script.loaded && | 1157 script.loaded && |
| 1125 script.tokenToLine(result.tokenPos) != line) { | 1158 script.tokenToLine(bpt.tokenPos) != line) { |
| 1126 // Unable to set a breakpoint at desired line. | 1159 // TODO(turnidge): Can this still happen? |
| 1127 script.lines[line - 1].possibleBpt = false; | 1160 script.getLine(line).possibleBpt = false; |
| 1128 } | 1161 } |
| 1129 return result; | 1162 return bpt; |
| 1130 }); | 1163 } on ServerRpcException catch(e) { |
| 1164 if (e.code == ServerRpcException.kNoBreakAtLine) { |
| 1165 // Unable to set a breakpoint at the desired line. |
| 1166 script.getLine(line).possibleBpt = false; |
| 1167 } |
| 1168 rethrow; |
| 1169 } |
| 1131 } | 1170 } |
| 1132 | 1171 |
| 1133 Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) { | 1172 Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) { |
| 1134 return invokeRpc('addBreakpointAtEntry', | 1173 return invokeRpc('addBreakpointAtEntry', |
| 1135 { 'functionId': function.id }); | 1174 { 'functionId': function.id }); |
| 1136 } | 1175 } |
| 1137 | 1176 |
| 1138 Future removeBreakpoint(Breakpoint bpt) { | 1177 Future removeBreakpoint(Breakpoint bpt) { |
| 1139 return invokeRpc('removeBreakpoint', | 1178 return invokeRpc('removeBreakpoint', |
| 1140 { 'breakpointId': bpt.id }); | 1179 { 'breakpointId': bpt.id }); |
| 1141 } | 1180 } |
| 1142 | 1181 |
| 1143 Future pause() { | 1182 Future pause() { |
| 1144 return invokeRpc('pause', {}).then((result) { | 1183 return invokeRpc('pause', {}); |
| 1145 if (result is DartError) { | |
| 1146 // TODO(turnidge): Handle this more gracefully. | |
| 1147 Logger.root.severe(result.message); | |
| 1148 } | |
| 1149 return result; | |
| 1150 }); | |
| 1151 } | 1184 } |
| 1152 | 1185 |
| 1153 Future resume() { | 1186 Future resume() { |
| 1154 return invokeRpc('resume', {}).then((result) { | 1187 return invokeRpc('resume', {}); |
| 1155 if (result is DartError) { | |
| 1156 // TODO(turnidge): Handle this more gracefully. | |
| 1157 Logger.root.severe(result.message); | |
| 1158 } | |
| 1159 return result; | |
| 1160 }); | |
| 1161 } | 1188 } |
| 1162 | 1189 |
| 1163 Future stepInto() { | 1190 Future stepInto() { |
| 1164 return invokeRpc('resume', {'step': 'into'}).then((result) { | 1191 return invokeRpc('resume', {'step': 'into'}); |
| 1165 if (result is DartError) { | |
| 1166 // TODO(turnidge): Handle this more gracefully. | |
| 1167 Logger.root.severe(result.message); | |
| 1168 } | |
| 1169 return result; | |
| 1170 }); | |
| 1171 } | 1192 } |
| 1172 | 1193 |
| 1173 Future stepOver() { | 1194 Future stepOver() { |
| 1174 return invokeRpc('resume', {'step': 'over'}).then((result) { | 1195 return invokeRpc('resume', {'step': 'over'}); |
| 1175 if (result is DartError) { | |
| 1176 // TODO(turnidge): Handle this more gracefully. | |
| 1177 Logger.root.severe(result.message); | |
| 1178 } | |
| 1179 return result; | |
| 1180 }); | |
| 1181 } | 1196 } |
| 1182 | 1197 |
| 1183 Future stepOut() { | 1198 Future stepOut() { |
| 1184 return invokeRpc('resume', {'step': 'out'}).then((result) { | 1199 return invokeRpc('resume', {'step': 'out'}); |
| 1185 if (result is DartError) { | |
| 1186 // TODO(turnidge): Handle this more gracefully. | |
| 1187 Logger.root.severe(result.message); | |
| 1188 } | |
| 1189 return result; | |
| 1190 }); | |
| 1191 } | 1200 } |
| 1192 | 1201 |
| 1193 Future setName(String newName) { | 1202 Future setName(String newName) { |
| 1194 Map params = { | 1203 return invokeRpc('setName', {'name': newName}); |
| 1195 'name': newName, | |
| 1196 }; | |
| 1197 return invokeRpc('setName', params); | |
| 1198 } | 1204 } |
| 1199 | 1205 |
| 1200 Future<ServiceMap> getStack() { | 1206 Future<ServiceMap> getStack() { |
| 1201 return invokeRpc('getStack', {}).then((result) { | 1207 return invokeRpc('getStack', {}); |
| 1202 if (result is DartError) { | |
| 1203 // TODO(turnidge): Handle this more gracefully. | |
| 1204 Logger.root.severe(result.message); | |
| 1205 } | |
| 1206 return result; | |
| 1207 }); | |
| 1208 } | 1208 } |
| 1209 | 1209 |
| 1210 Future<ServiceObject> eval(ServiceObject target, | 1210 Future<ServiceObject> eval(ServiceObject target, |
| 1211 String expression) { | 1211 String expression) { |
| 1212 Map params = { | 1212 Map params = { |
| 1213 'targetId': target.id, | 1213 'targetId': target.id, |
| 1214 'expression': expression, | 1214 'expression': expression, |
| 1215 }; | 1215 }; |
| 1216 return invokeRpc('eval', params); | 1216 return invokeRpc('eval', params); |
| 1217 } | 1217 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 new ObservableMap<String, ServiceMetric>(); | 1275 new ObservableMap<String, ServiceMetric>(); |
| 1276 | 1276 |
| 1277 final ObservableMap<String, ServiceMetric> nativeMetrics = | 1277 final ObservableMap<String, ServiceMetric> nativeMetrics = |
| 1278 new ObservableMap<String, ServiceMetric>(); | 1278 new ObservableMap<String, ServiceMetric>(); |
| 1279 | 1279 |
| 1280 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics( | 1280 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics( |
| 1281 String metricType, | 1281 String metricType, |
| 1282 ObservableMap<String, ServiceMetric> metricsMap) { | 1282 ObservableMap<String, ServiceMetric> metricsMap) { |
| 1283 return invokeRpc('getIsolateMetricList', | 1283 return invokeRpc('getIsolateMetricList', |
| 1284 { 'type': metricType }).then((result) { | 1284 { 'type': metricType }).then((result) { |
| 1285 if (result is DartError) { | |
| 1286 // TODO(turnidge): Handle this more gracefully. | |
| 1287 Logger.root.severe(result.message); | |
| 1288 return null; | |
| 1289 } | |
| 1290 // Clear metrics map. | 1285 // Clear metrics map. |
| 1291 metricsMap.clear(); | 1286 metricsMap.clear(); |
| 1292 // Repopulate metrics map. | 1287 // Repopulate metrics map. |
| 1293 var metrics = result['metrics']; | 1288 var metrics = result['metrics']; |
| 1294 for (var metric in metrics) { | 1289 for (var metric in metrics) { |
| 1295 metricsMap[metric.id] = metric; | 1290 metricsMap[metric.id] = metric; |
| 1296 } | 1291 } |
| 1297 return metricsMap; | 1292 return metricsMap; |
| 1298 }); | 1293 }); |
| 1299 } | 1294 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 message = map['message']; | 1385 message = map['message']; |
| 1391 exception = new ServiceObject._fromMap(owner, map['exception']); | 1386 exception = new ServiceObject._fromMap(owner, map['exception']); |
| 1392 stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']); | 1387 stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']); |
| 1393 name = 'DartError $kind'; | 1388 name = 'DartError $kind'; |
| 1394 vmName = name; | 1389 vmName = name; |
| 1395 } | 1390 } |
| 1396 | 1391 |
| 1397 String toString() => 'DartError($message)'; | 1392 String toString() => 'DartError($message)'; |
| 1398 } | 1393 } |
| 1399 | 1394 |
| 1400 /// A [ServiceError] is an error that was triggered in the service | |
| 1401 /// server or client. Errors are prorammer mistakes that could have | |
| 1402 /// been prevented, for example, requesting a non-existant path over the | |
| 1403 /// service. | |
| 1404 class ServiceError extends ServiceObject { | |
| 1405 ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner); | |
| 1406 | |
| 1407 @observable String kind; | |
| 1408 @observable String message; | |
| 1409 | |
| 1410 void _update(ObservableMap map, bool mapIsRef) { | |
| 1411 _loaded = true; | |
| 1412 kind = map['kind']; | |
| 1413 message = map['message']; | |
| 1414 name = 'ServiceError $kind'; | |
| 1415 vmName = name; | |
| 1416 } | |
| 1417 | |
| 1418 String toString() => 'ServiceError($message)'; | |
| 1419 } | |
| 1420 | |
| 1421 /// A [ServiceException] is an exception that was triggered in the service | |
| 1422 /// server or client. Exceptions are events that should be handled, | |
| 1423 /// for example, an isolate went away or the connection to the VM was lost. | |
| 1424 class ServiceException extends ServiceObject { | |
| 1425 ServiceException._empty(ServiceObject owner) : super._empty(owner); | |
| 1426 | |
| 1427 @observable String kind; | |
| 1428 @observable String message; | |
| 1429 @observable dynamic response; | |
| 1430 | |
| 1431 void _update(ObservableMap map, bool mapIsRef) { | |
| 1432 kind = map['kind']; | |
| 1433 message = map['message']; | |
| 1434 response = map['response']; | |
| 1435 name = 'ServiceException $kind'; | |
| 1436 vmName = name; | |
| 1437 } | |
| 1438 | |
| 1439 String toString() => 'ServiceException($message)'; | |
| 1440 } | |
| 1441 | |
| 1442 /// A [ServiceEvent] is an asynchronous event notification from the vm. | 1395 /// A [ServiceEvent] is an asynchronous event notification from the vm. |
| 1443 class ServiceEvent extends ServiceObject { | 1396 class ServiceEvent extends ServiceObject { |
| 1444 /// The possible 'eventType' values. | 1397 /// The possible 'eventType' values. |
| 1445 static const kIsolateStart = 'IsolateStart'; | 1398 static const kIsolateStart = 'IsolateStart'; |
| 1446 static const kIsolateExit = 'IsolateExit'; | 1399 static const kIsolateExit = 'IsolateExit'; |
| 1447 static const kIsolateUpdate = 'IsolateUpdate'; | 1400 static const kIsolateUpdate = 'IsolateUpdate'; |
| 1448 static const kPauseStart = 'PauseStart'; | 1401 static const kPauseStart = 'PauseStart'; |
| 1449 static const kPauseExit = 'PauseExit'; | 1402 static const kPauseExit = 'PauseExit'; |
| 1450 static const kPauseBreakpoint = 'PauseBreakpoint'; | 1403 static const kPauseBreakpoint = 'PauseBreakpoint'; |
| 1451 static const kPauseInterrupted = 'PauseInterrupted'; | 1404 static const kPauseInterrupted = 'PauseInterrupted'; |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1676 @observable int tokenPos; | 1629 @observable int tokenPos; |
| 1677 @observable int endTokenPos; | 1630 @observable int endTokenPos; |
| 1678 | 1631 |
| 1679 @observable ServiceMap error; | 1632 @observable ServiceMap error; |
| 1680 @observable int vmCid; | 1633 @observable int vmCid; |
| 1681 | 1634 |
| 1682 final Allocations newSpace = new Allocations(); | 1635 final Allocations newSpace = new Allocations(); |
| 1683 final Allocations oldSpace = new Allocations(); | 1636 final Allocations oldSpace = new Allocations(); |
| 1684 final AllocationCount promotedByLastNewGC = new AllocationCount(); | 1637 final AllocationCount promotedByLastNewGC = new AllocationCount(); |
| 1685 | 1638 |
| 1686 bool get hasNoAllocations => newSpace.empty && oldSpace.empty; | 1639 @observable bool get hasNoAllocations => newSpace.empty && oldSpace.empty; |
| 1687 | 1640 |
| 1688 @reflectable final fields = new ObservableList<Field>(); | 1641 @reflectable final fields = new ObservableList<Field>(); |
| 1689 @reflectable final functions = new ObservableList<ServiceFunction>(); | 1642 @reflectable final functions = new ObservableList<ServiceFunction>(); |
| 1690 | 1643 |
| 1691 @observable Class superclass; | 1644 @observable Class superclass; |
| 1692 @reflectable final interfaces = new ObservableList<Instance>(); | 1645 @reflectable final interfaces = new ObservableList<Instance>(); |
| 1693 @reflectable final subclasses = new ObservableList<Class>(); | 1646 @reflectable final subclasses = new ObservableList<Class>(); |
| 1694 | 1647 |
| 1695 bool get canCache => true; | 1648 bool get canCache => true; |
| 1696 bool get immutable => false; | 1649 bool get immutable => false; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1752 // Work-around Object not tracking its subclasses in the VM. | 1705 // Work-around Object not tracking its subclasses in the VM. |
| 1753 if (superclass != null && superclass.name == "Object") { | 1706 if (superclass != null && superclass.name == "Object") { |
| 1754 superclass._addSubclass(this); | 1707 superclass._addSubclass(this); |
| 1755 } | 1708 } |
| 1756 error = map['error']; | 1709 error = map['error']; |
| 1757 | 1710 |
| 1758 var allocationStats = map['allocationStats']; | 1711 var allocationStats = map['allocationStats']; |
| 1759 if (allocationStats != null) { | 1712 if (allocationStats != null) { |
| 1760 newSpace.update(allocationStats['new']); | 1713 newSpace.update(allocationStats['new']); |
| 1761 oldSpace.update(allocationStats['old']); | 1714 oldSpace.update(allocationStats['old']); |
| 1715 notifyPropertyChange(#hasNoAllocations, 0, 1); |
| 1762 promotedByLastNewGC.instances = allocationStats['promotedInstances']; | 1716 promotedByLastNewGC.instances = allocationStats['promotedInstances']; |
| 1763 promotedByLastNewGC.bytes = allocationStats['promotedBytes']; | 1717 promotedByLastNewGC.bytes = allocationStats['promotedBytes']; |
| 1764 } | 1718 } |
| 1765 } | 1719 } |
| 1766 | 1720 |
| 1767 void _addSubclass(Class subclass) { | 1721 void _addSubclass(Class subclass) { |
| 1768 if (subclasses.contains(subclass)) { | 1722 if (subclasses.contains(subclass)) { |
| 1769 return; | 1723 return; |
| 1770 } | 1724 } |
| 1771 subclasses.add(subclass); | 1725 subclasses.add(subclass); |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2187 @observable Library library; | 2141 @observable Library library; |
| 2188 bool get canCache => true; | 2142 bool get canCache => true; |
| 2189 bool get immutable => true; | 2143 bool get immutable => true; |
| 2190 | 2144 |
| 2191 String _shortUrl; | 2145 String _shortUrl; |
| 2192 String _url; | 2146 String _url; |
| 2193 | 2147 |
| 2194 Script._empty(ServiceObjectOwner owner) : super._empty(owner); | 2148 Script._empty(ServiceObjectOwner owner) : super._empty(owner); |
| 2195 | 2149 |
| 2196 ScriptLine getLine(int line) { | 2150 ScriptLine getLine(int line) { |
| 2151 assert(_loaded); |
| 2197 assert(line >= 1); | 2152 assert(line >= 1); |
| 2198 return lines[line - lineOffset - 1]; | 2153 return lines[line - lineOffset - 1]; |
| 2199 } | 2154 } |
| 2200 | 2155 |
| 2201 /// This function maps a token position to a line number. | 2156 /// This function maps a token position to a line number. |
| 2202 int tokenToLine(int token) => _tokenToLine[token]; | 2157 int tokenToLine(int token) => _tokenToLine[token]; |
| 2203 Map _tokenToLine = {}; | 2158 Map _tokenToLine = {}; |
| 2204 | 2159 |
| 2205 /// This function maps a token position to a column number. | 2160 /// This function maps a token position to a column number. |
| 2206 int tokenToCol(int token) => _tokenToCol[token]; | 2161 int tokenToCol(int token) => _tokenToCol[token]; |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2533 return Native; | 2488 return Native; |
| 2534 } else if (s == 'Dart') { | 2489 } else if (s == 'Dart') { |
| 2535 return Dart; | 2490 return Dart; |
| 2536 } else if (s == 'Collected') { | 2491 } else if (s == 'Collected') { |
| 2537 return Collected; | 2492 return Collected; |
| 2538 } else if (s == 'Tag') { | 2493 } else if (s == 'Tag') { |
| 2539 return Tag; | 2494 return Tag; |
| 2540 } else if (s == 'Stub') { | 2495 } else if (s == 'Stub') { |
| 2541 return Stub; | 2496 return Stub; |
| 2542 } | 2497 } |
| 2543 Logger.root.severe('Unrecognized code kind: $s'); | 2498 Logger.root.severe("Unrecognized code kind: '$s'"); |
| 2544 throw new FallThroughError(); | 2499 throw new FallThroughError(); |
| 2545 } | 2500 } |
| 2546 static const Collected = const CodeKind._internal('Collected'); | 2501 static const Collected = const CodeKind._internal('Collected'); |
| 2547 static const Dart = const CodeKind._internal('Dart'); | 2502 static const Dart = const CodeKind._internal('Dart'); |
| 2548 static const Native = const CodeKind._internal('Native'); | 2503 static const Native = const CodeKind._internal('Native'); |
| 2549 static const Stub = const CodeKind._internal('Stub'); | 2504 static const Stub = const CodeKind._internal('Stub'); |
| 2550 static const Tag = const CodeKind._internal('Tag'); | 2505 static const Tag = const CodeKind._internal('Tag'); |
| 2551 } | 2506 } |
| 2552 | 2507 |
| 2553 class CodeInlineInterval { | 2508 class CodeInlineInterval { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2607 } | 2562 } |
| 2608 // Load the script and then update descriptors. | 2563 // Load the script and then update descriptors. |
| 2609 script.load().then(_updateDescriptors); | 2564 script.load().then(_updateDescriptors); |
| 2610 }); | 2565 }); |
| 2611 return; | 2566 return; |
| 2612 } | 2567 } |
| 2613 // Load the script and then update descriptors. | 2568 // Load the script and then update descriptors. |
| 2614 function.script.load().then(_updateDescriptors); | 2569 function.script.load().then(_updateDescriptors); |
| 2615 } | 2570 } |
| 2616 | 2571 |
| 2617 /// Reload [this]. Returns a future which completes to [this] or | 2572 /// Reload [this]. Returns a future which completes to [this] or an |
| 2618 /// a [ServiceError]. | 2573 /// exception. |
| 2619 Future<ServiceObject> reload() { | 2574 Future<ServiceObject> reload() { |
| 2620 assert(kind != null); | 2575 assert(kind != null); |
| 2621 if (isDartCode) { | 2576 if (isDartCode) { |
| 2622 // We only reload Dart code. | 2577 // We only reload Dart code. |
| 2623 return super.reload(); | 2578 return super.reload(); |
| 2624 } | 2579 } |
| 2625 return new Future.value(this); | 2580 return new Future.value(this); |
| 2626 } | 2581 } |
| 2627 | 2582 |
| 2628 void _update(ObservableMap m, bool mapIsRef) { | 2583 void _update(ObservableMap m, bool mapIsRef) { |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3001 var v = list[i]; | 2956 var v = list[i]; |
| 3002 if ((v is ObservableMap) && _isServiceMap(v)) { | 2957 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 3003 list[i] = owner.getFromMap(v); | 2958 list[i] = owner.getFromMap(v); |
| 3004 } else if (v is ObservableList) { | 2959 } else if (v is ObservableList) { |
| 3005 _upgradeObservableList(v, owner); | 2960 _upgradeObservableList(v, owner); |
| 3006 } else if (v is ObservableMap) { | 2961 } else if (v is ObservableMap) { |
| 3007 _upgradeObservableMap(v, owner); | 2962 _upgradeObservableMap(v, owner); |
| 3008 } | 2963 } |
| 3009 } | 2964 } |
| 3010 } | 2965 } |
| OLD | NEW |