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

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: fix tests 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): Checking 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;
518 }); 556 });
519 } 557 }
520 558
521 Future<ObservableMap> _fetchDirect() { 559 Future<ObservableMap> _fetchDirect() {
560 print("FETCH DIRECT VM");
522 return invokeRpcNoUpgrade('getVM', {}); 561 return invokeRpcNoUpgrade('getVM', {});
523 } 562 }
524 563
525 Future<ServiceObject> getFlagList() { 564 Future<ServiceObject> getFlagList() {
526 return invokeRpc('getFlagList', {}); 565 return invokeRpc('getFlagList', {});
527 } 566 }
528 567
529 /// Force the VM to disconnect. 568 /// Force the VM to disconnect.
530 void disconnect(); 569 void disconnect();
531 /// Completes when the VM first connects. 570 /// Completes when the VM first connects.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 Future get onConnect { 649 Future get onConnect {
611 if (_onConnect != null) { 650 if (_onConnect != null) {
612 return _onConnect; 651 return _onConnect;
613 } 652 }
614 _onConnect = new Future.value(this); 653 _onConnect = new Future.value(this);
615 return _onConnect; 654 return _onConnect;
616 } 655 }
617 // Only complete when requested. 656 // Only complete when requested.
618 Completer _onDisconnect = new Completer(); 657 Completer _onDisconnect = new Completer();
619 Future get onDisconnect => _onDisconnect.future; 658 Future get onDisconnect => _onDisconnect.future;
659 bool get isDisconnected => _onDisconnect.isCompleted;
620 660
621 Future<Map> invokeRpcRaw(String method, Map params) { 661 Future<Map> invokeRpcRaw(String method, Map params) {
622 if (params.isEmpty) { 662 if (params.isEmpty) {
623 params = null; 663 params = null;
624 } 664 }
625 var key = _canonicalizeUri(new Uri(path: method, queryParameters: params)); 665 var key = _canonicalizeUri(new Uri(path: method, queryParameters: params));
626 var response = _responses[key]; 666 var response = _responses[key];
627 if (response == null) { 667 if (response == null) {
628 return new Future.error({ 668 return new Future.error(new FakeVMRpcException(
629 'type': 'ServiceException', 669 "Unable to find key '${key}' in cached response set"));
630 'kind': 'NotContainedInResponses',
631 'key': key
632 });
633 } 670 }
634 return new Future.value(response); 671 return new Future.value(response);
635 } 672 }
636 } 673 }
637 674
638 675
639 /// Snapshot in time of tag counters. 676 /// Snapshot in time of tag counters.
640 class TagProfileSnapshot { 677 class TagProfileSnapshot {
641 final double seconds; 678 final double seconds;
642 final List<int> counters; 679 final List<int> counters;
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 // Ignore GC events for now. 1136 // Ignore GC events for now.
1100 break; 1137 break;
1101 1138
1102 default: 1139 default:
1103 // Log unrecognized events. 1140 // Log unrecognized events.
1104 Logger.root.severe('Unrecognized event: $event'); 1141 Logger.root.severe('Unrecognized event: $event');
1105 break; 1142 break;
1106 } 1143 }
1107 } 1144 }
1108 1145
1109 Future<ServiceObject> addBreakpoint(Script script, int line) { 1146 Future<ServiceObject> addBreakpoint(Script script, int line) async {
1110 // TODO(turnidge): Pass line as an int instead of a string. 1147 // TODO(turnidge): Pass line as an int instead of a string.
1111 Map params = { 1148 try {
1112 'scriptId': script.id, 1149 Map params = {
1113 'line': '$line', 1150 'scriptId': script.id,
1114 }; 1151 'line': '$line',
1115 return invokeRpc('addBreakpoint', params).then((result) { 1152 };
1116 if (result is DartError) { 1153 Breakpoint bpt = await invokeRpc('addBreakpoint', params);
1117 return result;
1118 }
1119 Breakpoint bpt = result;
1120 if (bpt.resolved && 1154 if (bpt.resolved &&
1121 script.loaded && 1155 script.loaded &&
1122 script.tokenToLine(result.tokenPos) != line) { 1156 script.tokenToLine(bpt.tokenPos) != line) {
1123 // Unable to set a breakpoint at desired line. 1157 // TODO(turnidge): Can this still happen?
1124 script.lines[line - 1].possibleBpt = false; 1158 script.getLine(line).possibleBpt = false;
1125 } 1159 }
1126 return result; 1160 return bpt;
1127 }); 1161 } on ServerRpcException catch(e) {
1162 if (e.code == ServerRpcException.kNoBreakAtLine) {
1163 // Unable to set a breakpoint at the desired line.
1164 script.getLine(line).possibleBpt = false;
1165 }
1166 rethrow;
1167 }
1128 } 1168 }
1129 1169
1130 Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) { 1170 Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) {
1131 return invokeRpc('addBreakpointAtEntry', 1171 return invokeRpc('addBreakpointAtEntry',
1132 { 'functionId': function.id }); 1172 { 'functionId': function.id });
1133 } 1173 }
1134 1174
1135 Future removeBreakpoint(Breakpoint bpt) { 1175 Future removeBreakpoint(Breakpoint bpt) {
1136 return invokeRpc('removeBreakpoint', 1176 return invokeRpc('removeBreakpoint',
1137 { 'breakpointId': bpt.id }); 1177 { 'breakpointId': bpt.id });
1138 } 1178 }
1139 1179
1140 Future pause() { 1180 Future pause() {
1141 return invokeRpc('pause', {}).then((result) { 1181 return invokeRpc('pause', {});
1142 if (result is DartError) {
1143 // TODO(turnidge): Handle this more gracefully.
1144 Logger.root.severe(result.message);
1145 }
1146 return result;
1147 });
1148 } 1182 }
1149 1183
1150 Future resume() { 1184 Future resume() {
1151 return invokeRpc('resume', {}).then((result) { 1185 return invokeRpc('resume', {});
1152 if (result is DartError) {
1153 // TODO(turnidge): Handle this more gracefully.
1154 Logger.root.severe(result.message);
1155 }
1156 return result;
1157 });
1158 } 1186 }
1159 1187
1160 Future stepInto() { 1188 Future stepInto() {
1161 return invokeRpc('resume', {'step': 'into'}).then((result) { 1189 return invokeRpc('resume', {'step': 'into'});
1162 if (result is DartError) {
1163 // TODO(turnidge): Handle this more gracefully.
1164 Logger.root.severe(result.message);
1165 }
1166 return result;
1167 });
1168 } 1190 }
1169 1191
1170 Future stepOver() { 1192 Future stepOver() {
1171 return invokeRpc('resume', {'step': 'over'}).then((result) { 1193 return invokeRpc('resume', {'step': 'over'});
1172 if (result is DartError) {
1173 // TODO(turnidge): Handle this more gracefully.
1174 Logger.root.severe(result.message);
1175 }
1176 return result;
1177 });
1178 } 1194 }
1179 1195
1180 Future stepOut() { 1196 Future stepOut() {
1181 return invokeRpc('resume', {'step': 'out'}).then((result) { 1197 return invokeRpc('resume', {'step': 'out'});
1182 if (result is DartError) {
1183 // TODO(turnidge): Handle this more gracefully.
1184 Logger.root.severe(result.message);
1185 }
1186 return result;
1187 });
1188 } 1198 }
1189 1199
1190 Future setName(String newName) { 1200 Future setName(String newName) {
1191 Map params = { 1201 return invokeRpc('setName', {'name': newName});
1192 'name': newName,
1193 };
1194 return invokeRpc('setName', params);
1195 } 1202 }
1196 1203
1197 Future<ServiceMap> getStack() { 1204 Future<ServiceMap> getStack() {
1198 return invokeRpc('getStack', {}).then((result) { 1205 return invokeRpc('getStack', {});
1199 if (result is DartError) {
1200 // TODO(turnidge): Handle this more gracefully.
1201 Logger.root.severe(result.message);
1202 }
1203 return result;
1204 });
1205 } 1206 }
1206 1207
1207 Future<ServiceObject> eval(ServiceObject target, 1208 Future<ServiceObject> eval(ServiceObject target,
1208 String expression) { 1209 String expression) {
1209 Map params = { 1210 Map params = {
1210 'targetId': target.id, 1211 'targetId': target.id,
1211 'expression': expression, 1212 'expression': expression,
1212 }; 1213 };
1213 return invokeRpc('eval', params); 1214 return invokeRpc('eval', params);
1214 } 1215 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 new ObservableMap<String, ServiceMetric>(); 1273 new ObservableMap<String, ServiceMetric>();
1273 1274
1274 final ObservableMap<String, ServiceMetric> nativeMetrics = 1275 final ObservableMap<String, ServiceMetric> nativeMetrics =
1275 new ObservableMap<String, ServiceMetric>(); 1276 new ObservableMap<String, ServiceMetric>();
1276 1277
1277 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics( 1278 Future<ObservableMap<String, ServiceMetric>> _refreshMetrics(
1278 String metricType, 1279 String metricType,
1279 ObservableMap<String, ServiceMetric> metricsMap) { 1280 ObservableMap<String, ServiceMetric> metricsMap) {
1280 return invokeRpc('getIsolateMetricList', 1281 return invokeRpc('getIsolateMetricList',
1281 { 'type': metricType }).then((result) { 1282 { 'type': metricType }).then((result) {
1282 if (result is DartError) {
1283 // TODO(turnidge): Handle this more gracefully.
1284 Logger.root.severe(result.message);
1285 return null;
1286 }
1287 // Clear metrics map. 1283 // Clear metrics map.
1288 metricsMap.clear(); 1284 metricsMap.clear();
1289 // Repopulate metrics map. 1285 // Repopulate metrics map.
1290 var metrics = result['metrics']; 1286 var metrics = result['metrics'];
1291 for (var metric in metrics) { 1287 for (var metric in metrics) {
1292 metricsMap[metric.id] = metric; 1288 metricsMap[metric.id] = metric;
1293 } 1289 }
1294 return metricsMap; 1290 return metricsMap;
1295 }); 1291 });
1296 } 1292 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 message = map['message']; 1383 message = map['message'];
1388 exception = new ServiceObject._fromMap(owner, map['exception']); 1384 exception = new ServiceObject._fromMap(owner, map['exception']);
1389 stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']); 1385 stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']);
1390 name = 'DartError $kind'; 1386 name = 'DartError $kind';
1391 vmName = name; 1387 vmName = name;
1392 } 1388 }
1393 1389
1394 String toString() => 'DartError($message)'; 1390 String toString() => 'DartError($message)';
1395 } 1391 }
1396 1392
1397 /// A [ServiceError] is an error that was triggered in the service
1398 /// server or client. Errors are prorammer mistakes that could have
1399 /// been prevented, for example, requesting a non-existant path over the
1400 /// service.
1401 class ServiceError extends ServiceObject {
1402 ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner);
1403
1404 @observable String kind;
1405 @observable String message;
1406
1407 void _update(ObservableMap map, bool mapIsRef) {
1408 _loaded = true;
1409 kind = map['kind'];
1410 message = map['message'];
1411 name = 'ServiceError $kind';
1412 vmName = name;
1413 }
1414
1415 String toString() => 'ServiceError($message)';
1416 }
1417
1418 /// A [ServiceException] is an exception that was triggered in the service
1419 /// server or client. Exceptions are events that should be handled,
1420 /// for example, an isolate went away or the connection to the VM was lost.
1421 class ServiceException extends ServiceObject {
1422 ServiceException._empty(ServiceObject owner) : super._empty(owner);
1423
1424 @observable String kind;
1425 @observable String message;
1426 @observable dynamic response;
1427
1428 void _update(ObservableMap map, bool mapIsRef) {
1429 kind = map['kind'];
1430 message = map['message'];
1431 response = map['response'];
1432 name = 'ServiceException $kind';
1433 vmName = name;
1434 }
1435
1436 String toString() => 'ServiceException($message)';
1437 }
1438
1439 /// A [ServiceEvent] is an asynchronous event notification from the vm. 1393 /// A [ServiceEvent] is an asynchronous event notification from the vm.
1440 class ServiceEvent extends ServiceObject { 1394 class ServiceEvent extends ServiceObject {
1441 /// The possible 'eventType' values. 1395 /// The possible 'eventType' values.
1442 static const kIsolateStart = 'IsolateStart'; 1396 static const kIsolateStart = 'IsolateStart';
1443 static const kIsolateExit = 'IsolateExit'; 1397 static const kIsolateExit = 'IsolateExit';
1444 static const kIsolateUpdate = 'IsolateUpdate'; 1398 static const kIsolateUpdate = 'IsolateUpdate';
1445 static const kPauseStart = 'PauseStart'; 1399 static const kPauseStart = 'PauseStart';
1446 static const kPauseExit = 'PauseExit'; 1400 static const kPauseExit = 'PauseExit';
1447 static const kPauseBreakpoint = 'PauseBreakpoint'; 1401 static const kPauseBreakpoint = 'PauseBreakpoint';
1448 static const kPauseInterrupted = 'PauseInterrupted'; 1402 static const kPauseInterrupted = 'PauseInterrupted';
(...skipping 15 matching lines...) Expand all
1464 1418
1465 @observable String eventType; 1419 @observable String eventType;
1466 @observable Breakpoint breakpoint; 1420 @observable Breakpoint breakpoint;
1467 @observable ServiceMap topFrame; 1421 @observable ServiceMap topFrame;
1468 @observable ServiceMap exception; 1422 @observable ServiceMap exception;
1469 @observable ServiceObject inspectee; 1423 @observable ServiceObject inspectee;
1470 @observable ByteData data; 1424 @observable ByteData data;
1471 @observable int count; 1425 @observable int count;
1472 @observable String reason; 1426 @observable String reason;
1473 1427
1428 @observable bool get isPauseEvent {
1429 return (eventType == kPauseStart ||
1430 eventType == kPauseExit ||
1431 eventType == kPauseBreakpoint ||
1432 eventType == kPauseInterrupted ||
1433 eventType == kPauseException);
1434 }
1435
1474 void _update(ObservableMap map, bool mapIsRef) { 1436 void _update(ObservableMap map, bool mapIsRef) {
1475 _loaded = true; 1437 _loaded = true;
1476 _upgradeCollection(map, owner); 1438 _upgradeCollection(map, owner);
1477 assert(map['isolate'] == null || owner == map['isolate']); 1439 assert(map['isolate'] == null || owner == map['isolate']);
1478 eventType = map['eventType']; 1440 eventType = map['eventType'];
1441 notifyPropertyChange(#isPauseEvent, 0, 1);
1479 name = 'ServiceEvent $eventType'; 1442 name = 'ServiceEvent $eventType';
1480 vmName = name; 1443 vmName = name;
1481 if (map['breakpoint'] != null) { 1444 if (map['breakpoint'] != null) {
1482 breakpoint = map['breakpoint']; 1445 breakpoint = map['breakpoint'];
1483 } 1446 }
1484 if (map['topFrame'] != null) { 1447 if (map['topFrame'] != null) {
1485 topFrame = map['topFrame']; 1448 topFrame = map['topFrame'];
1486 } 1449 }
1487 if (map['exception'] != null) { 1450 if (map['exception'] != null) {
1488 exception = map['exception']; 1451 exception = map['exception'];
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 @observable int tokenPos; 1636 @observable int tokenPos;
1674 @observable int endTokenPos; 1637 @observable int endTokenPos;
1675 1638
1676 @observable ServiceMap error; 1639 @observable ServiceMap error;
1677 @observable int vmCid; 1640 @observable int vmCid;
1678 1641
1679 final Allocations newSpace = new Allocations(); 1642 final Allocations newSpace = new Allocations();
1680 final Allocations oldSpace = new Allocations(); 1643 final Allocations oldSpace = new Allocations();
1681 final AllocationCount promotedByLastNewGC = new AllocationCount(); 1644 final AllocationCount promotedByLastNewGC = new AllocationCount();
1682 1645
1683 bool get hasNoAllocations => newSpace.empty && oldSpace.empty; 1646 @observable bool get hasNoAllocations => newSpace.empty && oldSpace.empty;
1684 1647
1685 @reflectable final fields = new ObservableList<Field>(); 1648 @reflectable final fields = new ObservableList<Field>();
1686 @reflectable final functions = new ObservableList<ServiceFunction>(); 1649 @reflectable final functions = new ObservableList<ServiceFunction>();
1687 1650
1688 @observable Class superclass; 1651 @observable Class superclass;
1689 @reflectable final interfaces = new ObservableList<Instance>(); 1652 @reflectable final interfaces = new ObservableList<Instance>();
1690 @reflectable final subclasses = new ObservableList<Class>(); 1653 @reflectable final subclasses = new ObservableList<Class>();
1691 1654
1692 bool get canCache => true; 1655 bool get canCache => true;
1693 bool get immutable => false; 1656 bool get immutable => false;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 // Work-around Object not tracking its subclasses in the VM. 1712 // Work-around Object not tracking its subclasses in the VM.
1750 if (superclass != null && superclass.name == "Object") { 1713 if (superclass != null && superclass.name == "Object") {
1751 superclass._addSubclass(this); 1714 superclass._addSubclass(this);
1752 } 1715 }
1753 error = map['error']; 1716 error = map['error'];
1754 1717
1755 var allocationStats = map['allocationStats']; 1718 var allocationStats = map['allocationStats'];
1756 if (allocationStats != null) { 1719 if (allocationStats != null) {
1757 newSpace.update(allocationStats['new']); 1720 newSpace.update(allocationStats['new']);
1758 oldSpace.update(allocationStats['old']); 1721 oldSpace.update(allocationStats['old']);
1722 notifyPropertyChange(#hasNoAllocations, 0, 1);
1759 promotedByLastNewGC.instances = allocationStats['promotedInstances']; 1723 promotedByLastNewGC.instances = allocationStats['promotedInstances'];
1760 promotedByLastNewGC.bytes = allocationStats['promotedBytes']; 1724 promotedByLastNewGC.bytes = allocationStats['promotedBytes'];
1761 } 1725 }
1762 } 1726 }
1763 1727
1764 void _addSubclass(Class subclass) { 1728 void _addSubclass(Class subclass) {
1765 if (subclasses.contains(subclass)) { 1729 if (subclasses.contains(subclass)) {
1766 return; 1730 return;
1767 } 1731 }
1768 subclasses.add(subclass); 1732 subclasses.add(subclass);
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 @observable Library library; 2169 @observable Library library;
2206 bool get canCache => true; 2170 bool get canCache => true;
2207 bool get immutable => true; 2171 bool get immutable => true;
2208 2172
2209 String _shortUrl; 2173 String _shortUrl;
2210 String _url; 2174 String _url;
2211 2175
2212 Script._empty(ServiceObjectOwner owner) : super._empty(owner); 2176 Script._empty(ServiceObjectOwner owner) : super._empty(owner);
2213 2177
2214 ScriptLine getLine(int line) { 2178 ScriptLine getLine(int line) {
2179 assert(_loaded);
2215 assert(line >= 1); 2180 assert(line >= 1);
2216 return lines[line - lineOffset - 1]; 2181 return lines[line - lineOffset - 1];
2217 } 2182 }
2218 2183
2219 /// This function maps a token position to a line number. 2184 /// This function maps a token position to a line number.
2220 int tokenToLine(int token) => _tokenToLine[token]; 2185 int tokenToLine(int token) => _tokenToLine[token];
2221 Map _tokenToLine = {}; 2186 Map _tokenToLine = {};
2222 2187
2223 /// This function maps a token position to a column number. 2188 /// This function maps a token position to a column number.
2224 int tokenToCol(int token) => _tokenToCol[token]; 2189 int tokenToCol(int token) => _tokenToCol[token];
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2665 return Native; 2630 return Native;
2666 } else if (s == 'Dart') { 2631 } else if (s == 'Dart') {
2667 return Dart; 2632 return Dart;
2668 } else if (s == 'Collected') { 2633 } else if (s == 'Collected') {
2669 return Collected; 2634 return Collected;
2670 } else if (s == 'Tag') { 2635 } else if (s == 'Tag') {
2671 return Tag; 2636 return Tag;
2672 } else if (s == 'Stub') { 2637 } else if (s == 'Stub') {
2673 return Stub; 2638 return Stub;
2674 } 2639 }
2675 Logger.root.severe('Unrecognized code kind: $s'); 2640 Logger.root.severe("Unrecognized code kind: '$s'");
2676 throw new FallThroughError(); 2641 throw new FallThroughError();
2677 } 2642 }
2678 static const Collected = const CodeKind._internal('Collected'); 2643 static const Collected = const CodeKind._internal('Collected');
2679 static const Dart = const CodeKind._internal('Dart'); 2644 static const Dart = const CodeKind._internal('Dart');
2680 static const Native = const CodeKind._internal('Native'); 2645 static const Native = const CodeKind._internal('Native');
2681 static const Stub = const CodeKind._internal('Stub'); 2646 static const Stub = const CodeKind._internal('Stub');
2682 static const Tag = const CodeKind._internal('Tag'); 2647 static const Tag = const CodeKind._internal('Tag');
2683 } 2648 }
2684 2649
2685 class CodeInlineInterval { 2650 class CodeInlineInterval {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2739 } 2704 }
2740 // Load the script and then update descriptors. 2705 // Load the script and then update descriptors.
2741 script.load().then(_updateDescriptors); 2706 script.load().then(_updateDescriptors);
2742 }); 2707 });
2743 return; 2708 return;
2744 } 2709 }
2745 // Load the script and then update descriptors. 2710 // Load the script and then update descriptors.
2746 function.script.load().then(_updateDescriptors); 2711 function.script.load().then(_updateDescriptors);
2747 } 2712 }
2748 2713
2749 /// Reload [this]. Returns a future which completes to [this] or 2714 /// Reload [this]. Returns a future which completes to [this] or an
2750 /// a [ServiceError]. 2715 /// exception.
2751 Future<ServiceObject> reload() { 2716 Future<ServiceObject> reload() {
2752 assert(kind != null); 2717 assert(kind != null);
2753 if (isDartCode) { 2718 if (isDartCode) {
2754 // We only reload Dart code. 2719 // We only reload Dart code.
2755 return super.reload(); 2720 return super.reload();
2756 } 2721 }
2757 return new Future.value(this); 2722 return new Future.value(this);
2758 } 2723 }
2759 2724
2760 void _update(ObservableMap m, bool mapIsRef) { 2725 void _update(ObservableMap m, bool mapIsRef) {
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
3133 var v = list[i]; 3098 var v = list[i];
3134 if ((v is ObservableMap) && _isServiceMap(v)) { 3099 if ((v is ObservableMap) && _isServiceMap(v)) {
3135 list[i] = owner.getFromMap(v); 3100 list[i] = owner.getFromMap(v);
3136 } else if (v is ObservableList) { 3101 } else if (v is ObservableList) {
3137 _upgradeObservableList(v, owner); 3102 _upgradeObservableList(v, owner);
3138 } else if (v is ObservableMap) { 3103 } else if (v is ObservableMap) {
3139 _upgradeObservableMap(v, owner); 3104 _upgradeObservableMap(v, owner);
3140 } 3105 }
3141 } 3106 }
3142 } 3107 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/vm_view.dart ('k') | runtime/observatory/observatory_sources.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698