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

Side by Side Diff: runtime/observatory/lib/src/service/object.dart

Issue 1120133002: Rework error handling in the service protocol and in Observatory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 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 | Annotate | Revision Log
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 /// 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698