OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of service; | 5 part of service; |
6 | 6 |
7 /// A [ServiceObject] is an object known to the VM service and is tied | 7 /// A [ServiceObject] is an object known to the VM service and is tied |
8 /// to an owning [Isolate]. | 8 /// to an owning [Isolate]. |
9 abstract class ServiceObject extends Observable { | 9 abstract class ServiceObject extends Observable { |
10 /// The owner of this [ServiceObject]. This can be an [Isolate], a | 10 /// The owner of this [ServiceObject]. This can be an [Isolate], a |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 | 46 |
47 @observable String name; | 47 @observable String name; |
48 @observable String vmName; | 48 @observable String vmName; |
49 | 49 |
50 /// Creates an empty [ServiceObject]. | 50 /// Creates an empty [ServiceObject]. |
51 ServiceObject._empty(this._owner); | 51 ServiceObject._empty(this._owner); |
52 | 52 |
53 /// Creates a [ServiceObject] initialized from [map]. | 53 /// Creates a [ServiceObject] initialized from [map]. |
54 factory ServiceObject._fromMap(ServiceObjectOwner owner, | 54 factory ServiceObject._fromMap(ServiceObjectOwner owner, |
55 ObservableMap map) { | 55 ObservableMap map) { |
56 if (map == null) { | |
57 return null; | |
58 } | |
56 if (!_isServiceMap(map)) { | 59 if (!_isServiceMap(map)) { |
57 Logger.root.severe('Malformed service object: $map'); | 60 Logger.root.severe('Malformed service object: $map'); |
58 } | 61 } |
59 assert(_isServiceMap(map)); | 62 assert(_isServiceMap(map)); |
60 var type = _stripRef(map['type']); | 63 var type = _stripRef(map['type']); |
61 var obj = null; | 64 var obj = null; |
62 assert(type != 'VM'); | 65 assert(type != 'VM'); |
63 switch (type) { | 66 switch (type) { |
64 case 'Code': | 67 case 'Code': |
65 obj = new Code._empty(owner); | 68 obj = new Code._empty(owner); |
66 break; | 69 break; |
67 case 'Error': | 70 case 'Error': |
68 obj = new ServiceError._empty(owner); | 71 obj = new DartError._empty(owner); |
69 break; | 72 break; |
70 case 'Isolate': | 73 case 'Isolate': |
71 obj = new Isolate._empty(owner); | 74 obj = new Isolate._empty(owner); |
72 break; | 75 break; |
76 case 'ServiceError': | |
77 obj = new ServiceError._empty(owner); | |
78 break; | |
79 case 'ServiceException': | |
80 obj = new ServiceException._empty(owner); | |
81 break; | |
73 case 'Script': | 82 case 'Script': |
74 obj = new Script._empty(owner); | 83 obj = new Script._empty(owner); |
75 break; | 84 break; |
76 default: | 85 default: |
77 obj = new ServiceMap._empty(owner); | 86 obj = new ServiceMap._empty(owner); |
78 } | 87 } |
79 obj.update(map); | 88 obj.update(map); |
80 return obj; | 89 return obj; |
81 } | 90 } |
82 | 91 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 @observable String architecture = 'unknown'; | 170 @observable String architecture = 'unknown'; |
162 @observable double uptime = 0.0; | 171 @observable double uptime = 0.0; |
163 | 172 |
164 VM() : super._empty(null) { | 173 VM() : super._empty(null) { |
165 name = 'vm'; | 174 name = 'vm'; |
166 vmName = 'vm'; | 175 vmName = 'vm'; |
167 _cache['vm'] = this; | 176 _cache['vm'] = this; |
168 update(toObservable({'id':'vm', 'type':'@VM'})); | 177 update(toObservable({'id':'vm', 'type':'@VM'})); |
169 } | 178 } |
170 | 179 |
180 final StreamController<ServiceException> exceptions = | |
181 new StreamController.broadcast(); | |
182 final StreamController<ServiceError> errors = | |
183 new StreamController.broadcast(); | |
184 | |
171 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); | 185 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); |
172 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)'); | 186 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+/'); |
173 static final String _isolatesPrefix = 'isolates/'; | 187 static final String _isolatesPrefix = 'isolates/'; |
174 | 188 |
175 String _parseObjectId(String id) { | 189 String _parseObjectId(String id) { |
176 Match m = _currentObjectMatcher.matchAsPrefix(id); | 190 Match m = _currentObjectMatcher.matchAsPrefix(id); |
177 if (m == null) { | 191 if (m == null) { |
178 return null; | 192 return null; |
179 } | 193 } |
180 return m.input.substring(m.end); | 194 return m.input.substring(m.end); |
181 } | 195 } |
182 | 196 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 // Cache miss. Get the object from the vm directly. | 255 // Cache miss. Get the object from the vm directly. |
242 return getAsMap(id).then((ObservableMap map) { | 256 return getAsMap(id).then((ObservableMap map) { |
243 var obj = new ServiceObject._fromMap(this, map); | 257 var obj = new ServiceObject._fromMap(this, map); |
244 if (obj.canCache) { | 258 if (obj.canCache) { |
245 _cache.putIfAbsent(id, () => obj); | 259 _cache.putIfAbsent(id, () => obj); |
246 } | 260 } |
247 return obj; | 261 return obj; |
248 }); | 262 }); |
249 } | 263 } |
250 | 264 |
251 /// Gets [id] as an [ObservableMap] from the service directly. | 265 /// Gets [id] as an [ObservableMap] from the service directly. If |
266 /// an error occurs, the future is completed as an error with a | |
267 /// ServiceError or ServiceException. Therefore any chained then() calls | |
268 /// will only receive a map encoding a valid ServiceObject. | |
252 Future<ObservableMap> getAsMap(String id) { | 269 Future<ObservableMap> getAsMap(String id) { |
253 return getString(id).then((response) { | 270 return getString(id).then((response) { |
254 try { | 271 try { |
255 var map = JSON.decode(response); | 272 var map = toObservable(JSON.decode(response)); |
256 return toObservable(map); | 273 // Verify that the top level response is a service map. |
274 if (!_isServiceMap(map)) { | |
275 return new Future.error( | |
276 new ServiceObject._fromMap(this, toObservable({ | |
277 'type': 'ServiceException', | |
278 'id': '', | |
279 'kind': 'FormatException', | |
280 'response': map, | |
281 'message': 'Top level service responses must be service maps.', | |
282 }))); | |
283 } | |
284 // Preemptively capture ServiceError and ServiceExceptions. | |
285 if (map['type'] == 'ServiceError') { | |
286 return new Future.error(new ServiceObject._fromMap(this, map)); | |
287 } else if (map['type'] == 'ServiceException') { | |
288 return new Future.error(new ServiceObject._fromMap(this, map)); | |
289 } | |
290 // map is now guaranteed to be a non-error/exception ServiceObject. | |
291 return map; | |
257 } catch (e, st) { | 292 } catch (e, st) { |
258 return toObservable({ | 293 print(e); |
259 'type': 'Error', | 294 print(st); |
295 return new Future.error( | |
296 new ServiceObject._fromMap(this, toObservable({ | |
297 'type': 'ServiceException', | |
260 'id': '', | 298 'id': '', |
261 'kind': 'DecodeError', | 299 'kind': 'DecodeException', |
262 'message': '$e', | 300 'response': response, |
263 }); | 301 'message': 'Could not decode JSON: $e', |
302 }))); | |
264 } | 303 } |
265 }).catchError((error) { | 304 }).catchError((error) { |
266 return toObservable({ | 305 // ServiceError, forward to VM's ServiceError stream. |
267 'type': 'Error', | 306 errors.add(error); |
268 'id': '', | 307 return new Future.error(error); |
269 'kind': 'LastResort', | 308 }, test: (e) => e is ServiceError).catchError((exception) { |
270 'message': '$error' | 309 // ServiceException, forward to VM's ServiceException stream. |
271 }); | 310 exceptions.add(exception); |
272 }); | 311 return new Future.error(exception); |
312 }, test: (e) => e is ServiceException); | |
273 } | 313 } |
274 | 314 |
275 /// Get [id] as a [String] from the service directly. See [getAsMap]. | 315 /// Get [id] as a [String] from the service directly. See [getAsMap]. |
276 Future<String> getString(String id); | 316 Future<String> getString(String id); |
277 | 317 |
278 void _update(ObservableMap map, bool mapIsRef) { | 318 void _update(ObservableMap map, bool mapIsRef) { |
279 if (mapIsRef) { | 319 if (mapIsRef) { |
280 return; | 320 return; |
281 } | 321 } |
282 _loaded = true; | 322 _loaded = true; |
(...skipping 19 matching lines...) Expand all Loading... | |
302 } | 342 } |
303 // Update the individual isolates asynchronously. | 343 // Update the individual isolates asynchronously. |
304 newIsolateCache.forEach((isolateId, isolate) { | 344 newIsolateCache.forEach((isolateId, isolate) { |
305 isolate.reload(); | 345 isolate.reload(); |
306 }); | 346 }); |
307 | 347 |
308 _isolateCache = newIsolateCache; | 348 _isolateCache = newIsolateCache; |
309 } | 349 } |
310 } | 350 } |
311 | 351 |
352 /// Snapshot in time of tag counters. | |
353 class TagProfileSnapshot { | |
354 final double seconds; | |
355 final List<int> counters; | |
356 int get sum => _sum; | |
357 int _sum = 0; | |
358 TagProfileSnapshot(this.seconds, int countersLength) | |
359 : counters = new List<int>(countersLength); | |
360 | |
361 /// Set [counters] and update [sum]. | |
362 void set(List<int> counters) { | |
363 this.counters.setAll(0, counters); | |
364 for (var i = 0; i < this.counters.length; i++) { | |
365 _sum += this.counters[i]; | |
366 } | |
367 } | |
368 | |
369 /// Set [counters] with the delta from [counters] to [old_counters] | |
370 /// and update [sum]. | |
371 void delta(List<int> counters, List<int> old_counters) { | |
372 for (var i = 0; i < this.counters.length; i++) { | |
373 this.counters[i] = counters[i] - old_counters[i]; | |
374 _sum += this.counters[i]; | |
375 } | |
376 } | |
377 | |
378 /// Update [counters] with new maximum values seen in [counters]. | |
379 void max(List<int> counters) { | |
380 for (var i = 0; i < counters.length; i++) { | |
381 var c = counters[i]; | |
382 this.counters[i] = this.counters[i] > c ? this.counters[i] : c; | |
383 } | |
384 } | |
385 | |
386 /// Zero [counters]. | |
387 void zero() { | |
388 for (var i = 0; i < counters.length; i++) { | |
389 counters[i] = 0; | |
390 } | |
391 } | |
392 } | |
393 | |
394 class TagProfile { | |
395 final List<String> names = new List<String>(); | |
396 final List<TagProfileSnapshot> snapshots = new List<TagProfileSnapshot>(); | |
397 double get updatedAtSeconds => _seconds; | |
398 double _seconds; | |
399 TagProfileSnapshot _maxSnapshot; | |
400 int _historySize; | |
401 int _countersLength = 0; | |
402 | |
403 TagProfile(this._historySize); | |
404 | |
405 void _processTagProfile(double seconds, ObservableMap tagProfile) { | |
406 _seconds = seconds; | |
407 var counters = tagProfile['counters']; | |
408 if (names.length == 0) { | |
409 // Initialization. | |
410 names.addAll(tagProfile['names']); | |
411 _countersLength = tagProfile['counters'].length; | |
412 for (var i = 0; i < _historySize; i++) { | |
413 var snapshot = new TagProfileSnapshot(0.0, _countersLength); | |
414 snapshot.zero(); | |
415 snapshots.add(snapshot); | |
416 } | |
417 // The counters monotonically grow, keep track of the maximum value. | |
418 _maxSnapshot = new TagProfileSnapshot(0.0, _countersLength); | |
419 _maxSnapshot.set(counters); | |
420 return; | |
421 } | |
422 var snapshot = new TagProfileSnapshot(seconds, _countersLength); | |
423 // We snapshot the delta from the current counters to the maximum counter | |
424 // values. | |
425 snapshot.delta(counters, _maxSnapshot.counters); | |
426 _maxSnapshot.max(counters); | |
427 snapshots.add(snapshot); | |
428 // Only keep _historySize snapshots. | |
429 if (snapshots.length > _historySize) { | |
430 snapshots.removeAt(0); | |
431 } | |
432 } | |
433 } | |
434 | |
312 /// State for a running isolate. | 435 /// State for a running isolate. |
313 class Isolate extends ServiceObjectOwner { | 436 class Isolate extends ServiceObjectOwner { |
314 @reflectable VM get vm => owner; | 437 @reflectable VM get vm => owner; |
315 @reflectable Isolate get isolate => this; | 438 @reflectable Isolate get isolate => this; |
316 | 439 |
317 String get link => _id; | 440 String get link => _id; |
318 String get hashLink => '#/$_id'; | 441 String get hashLink => '#/$_id'; |
319 | 442 |
320 @observable bool pausedOnStart = false; | 443 @observable bool pausedOnStart = false; |
321 @observable bool pausedOnExit = false; | 444 @observable bool pausedOnExit = false; |
322 @observable bool running = false; | 445 @observable bool running = false; |
323 @observable bool idle = false; | 446 @observable bool idle = false; |
324 | 447 |
325 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); | 448 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); |
449 final TagProfile tagProfile = new TagProfile(20); | |
326 | 450 |
327 Isolate._empty(ServiceObjectOwner owner) : super._empty(owner); | 451 Isolate._empty(ServiceObjectOwner owner) : super._empty(owner) { |
452 assert(owner is VM); | |
453 } | |
328 | 454 |
329 /// Creates a link to [id] relative to [this]. | 455 /// Creates a link to [id] relative to [this]. |
330 @reflectable String relativeLink(String id) => '${this.id}/$id'; | 456 @reflectable String relativeLink(String id) => '${this.id}/$id'; |
331 /// Creates a relative link to [id] with a '#/' prefix. | 457 /// Creates a relative link to [id] with a '#/' prefix. |
332 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; | 458 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; |
333 | 459 |
334 static const TAG_ROOT_ID = 'code/tag-0'; | 460 static const TAG_ROOT_ID = 'code/tag-0'; |
335 | 461 |
336 /// Returns the Code object for the root tag. | 462 /// Returns the Code object for the root tag. |
337 Code tagRoot() { | 463 Code tagRoot() { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 } | 531 } |
406 // Build the object from the map directly. | 532 // Build the object from the map directly. |
407 obj = new ServiceObject._fromMap(this, map); | 533 obj = new ServiceObject._fromMap(this, map); |
408 if (obj.canCache) { | 534 if (obj.canCache) { |
409 _cache[id] = obj; | 535 _cache[id] = obj; |
410 } | 536 } |
411 return obj; | 537 return obj; |
412 } | 538 } |
413 | 539 |
414 Future<ServiceObject> get(String id) { | 540 Future<ServiceObject> get(String id) { |
541 // Do not allow null ids or empty ids. | |
542 assert(id != null && id != ''); | |
415 var obj = _cache[id]; | 543 var obj = _cache[id]; |
416 if (obj != null) { | 544 if (obj != null) { |
417 return obj.reload(); | 545 return obj.reload(); |
418 } | 546 } |
419 // Cache miss. Get the object from the vm directly. | 547 // Cache miss. Get the object from the vm directly. |
420 return vm.getAsMap(relativeLink(id)).then((ObservableMap map) { | 548 return vm.getAsMap(relativeLink(id)).then((ObservableMap map) { |
421 var obj = new ServiceObject._fromMap(this, map); | 549 var obj = new ServiceObject._fromMap(this, map); |
422 if (obj.canCache) { | 550 if (obj.canCache) { |
423 _cache.putIfAbsent(id, () => obj); | 551 _cache.putIfAbsent(id, () => obj); |
424 } | 552 } |
(...skipping 12 matching lines...) Expand all Loading... | |
437 @observable final Map<String, double> timers = | 565 @observable final Map<String, double> timers = |
438 toObservable(new Map<String, double>()); | 566 toObservable(new Map<String, double>()); |
439 | 567 |
440 @observable int newHeapUsed = 0; | 568 @observable int newHeapUsed = 0; |
441 @observable int oldHeapUsed = 0; | 569 @observable int oldHeapUsed = 0; |
442 @observable int newHeapCapacity = 0; | 570 @observable int newHeapCapacity = 0; |
443 @observable int oldHeapCapacity = 0; | 571 @observable int oldHeapCapacity = 0; |
444 | 572 |
445 @observable String fileAndLine; | 573 @observable String fileAndLine; |
446 | 574 |
575 @observable DartError error; | |
576 | |
447 void _update(ObservableMap map, bool mapIsRef) { | 577 void _update(ObservableMap map, bool mapIsRef) { |
448 mainPort = map['mainPort']; | 578 mainPort = map['mainPort']; |
449 name = map['name']; | 579 name = map['name']; |
450 vmName = map['name']; | 580 vmName = map['name']; |
451 if (mapIsRef) { | 581 if (mapIsRef) { |
452 return; | 582 return; |
453 } | 583 } |
454 _loaded = true; | 584 _loaded = true; |
455 _upgradeCollection(map, isolate); | 585 _upgradeCollection(map, isolate); |
456 if (map['rootLib'] == null || | 586 if (map['rootLib'] == null || |
(...skipping 28 matching lines...) Expand all Loading... | |
485 newHeapUsed = map['heap']['usedNew']; | 615 newHeapUsed = map['heap']['usedNew']; |
486 oldHeapUsed = map['heap']['usedOld']; | 616 oldHeapUsed = map['heap']['usedOld']; |
487 newHeapCapacity = map['heap']['capacityNew']; | 617 newHeapCapacity = map['heap']['capacityNew']; |
488 oldHeapCapacity = map['heap']['capacityOld']; | 618 oldHeapCapacity = map['heap']['capacityOld']; |
489 | 619 |
490 // Isolate status | 620 // Isolate status |
491 pausedOnStart = map['pausedOnStart']; | 621 pausedOnStart = map['pausedOnStart']; |
492 pausedOnExit = map['pausedOnExit']; | 622 pausedOnExit = map['pausedOnExit']; |
493 running = map['topFrame'] != null; | 623 running = map['topFrame'] != null; |
494 idle = !pausedOnStart && !pausedOnExit && !running; | 624 idle = !pausedOnStart && !pausedOnExit && !running; |
625 error = map['error']; | |
626 } | |
627 | |
628 Future<TagProfile> updateTagProfile() { | |
629 return vm.getAsMap(relativeLink('profile/tag')).then((ObservableMap m) { | |
630 var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0; | |
631 tagProfile._processTagProfile(seconds, m); | |
632 return tagProfile; | |
633 }); | |
495 } | 634 } |
496 | 635 |
497 @reflectable CodeTrieNode profileTrieRoot; | 636 @reflectable CodeTrieNode profileTrieRoot; |
498 // The profile trie is serialized as a list of integers. Each node | 637 // The profile trie is serialized as a list of integers. Each node |
499 // is recreated by consuming some portion of the list. The format is as | 638 // is recreated by consuming some portion of the list. The format is as |
500 // follows: | 639 // follows: |
501 // [0] index into codeTable of code object. | 640 // [0] index into codeTable of code object. |
502 // [1] tick count (number of times this stack frame occured). | 641 // [1] tick count (number of times this stack frame occured). |
503 // [2] child node count | 642 // [2] child node count |
504 // Reading the trie is done by recursively reading the tree depth-first | 643 // Reading the trie is done by recursively reading the tree depth-first |
(...skipping 28 matching lines...) Expand all Loading... | |
533 // Recursively read child nodes. | 672 // Recursively read child nodes. |
534 for (var i = 0; i < children; i++) { | 673 for (var i = 0; i < children; i++) { |
535 var child = _readTrieNode(codeTable); | 674 var child = _readTrieNode(codeTable); |
536 node.children.add(child); | 675 node.children.add(child); |
537 node.summedChildCount += child.count; | 676 node.summedChildCount += child.count; |
538 } | 677 } |
539 return node; | 678 return node; |
540 } | 679 } |
541 } | 680 } |
542 | 681 |
682 | |
turnidge
2014/03/25 17:52:53
Extra blank line.
Cutch
2014/03/25 18:01:52
Done.
| |
543 /// A [ServiceObject] which implements [ObservableMap]. | 683 /// A [ServiceObject] which implements [ObservableMap]. |
544 class ServiceMap extends ServiceObject implements ObservableMap { | 684 class ServiceMap extends ServiceObject implements ObservableMap { |
545 final ObservableMap _map = new ObservableMap(); | 685 final ObservableMap _map = new ObservableMap(); |
546 static String objectIdRingPrefix = 'objects/'; | 686 static String objectIdRingPrefix = 'objects/'; |
547 | 687 |
548 bool get canCache { | 688 bool get canCache { |
549 return (_serviceType == 'Class' || | 689 return (_serviceType == 'Class' || |
550 _serviceType == 'Function' || | 690 _serviceType == 'Function' || |
551 _serviceType == 'Library') && | 691 _serviceType == 'Library') && |
552 !_id.startsWith(objectIdRingPrefix); | 692 !_id.startsWith(objectIdRingPrefix); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
596 bool deliverChanges() => _map.deliverChanges(); | 736 bool deliverChanges() => _map.deliverChanges(); |
597 void notifyChange(ChangeRecord record) => _map.notifyChange(record); | 737 void notifyChange(ChangeRecord record) => _map.notifyChange(record); |
598 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => | 738 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => |
599 _map.notifyPropertyChange(field, oldValue, newValue); | 739 _map.notifyPropertyChange(field, oldValue, newValue); |
600 void observed() => _map.observed(); | 740 void observed() => _map.observed(); |
601 void unobserved() => _map.unobserved(); | 741 void unobserved() => _map.unobserved(); |
602 Stream<List<ChangeRecord>> get changes => _map.changes; | 742 Stream<List<ChangeRecord>> get changes => _map.changes; |
603 bool get hasObservers => _map.hasObservers; | 743 bool get hasObservers => _map.hasObservers; |
604 } | 744 } |
605 | 745 |
746 /// A [DartError] is peered to a Dart Error object. | |
747 class DartError extends ServiceObject { | |
748 DartError._empty(ServiceObject owner) : super._empty(owner); | |
749 | |
750 @observable String kind; | |
751 @observable String message; | |
752 @observable ServiceMap exception; | |
753 @observable ServiceMap stacktrace; | |
754 | |
755 void _update(ObservableMap map, bool mapIsRef) { | |
756 kind = map['kind']; | |
757 message = map['message']; | |
758 exception = new ServiceObject._fromMap(owner, map['exception']); | |
759 stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']); | |
760 name = 'DartError $kind'; | |
761 vmName = name; | |
762 } | |
763 } | |
764 | |
765 /// A [ServiceError] is an error that was triggered in the service | |
766 /// server or client. Errors are prorammer mistakes that could have | |
767 /// been prevented, for example, requesting a non-existant path over the | |
768 /// service. | |
606 class ServiceError extends ServiceObject { | 769 class ServiceError extends ServiceObject { |
607 ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner); | 770 ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner); |
608 | 771 |
609 @observable String kind; | 772 @observable String kind; |
610 @observable String message; | 773 @observable String message; |
611 | 774 |
612 void _update(ObservableMap map, bool mapIsRef) { | 775 void _update(ObservableMap map, bool mapIsRef) { |
613 _loaded = true; | 776 _loaded = true; |
614 kind = map['kind']; | 777 kind = map['kind']; |
615 message = map['message']; | 778 message = map['message']; |
616 name = 'ServiceError $kind'; | 779 name = 'ServiceError $kind'; |
617 vmName = name; | 780 vmName = name; |
618 } | 781 } |
782 } | |
619 | 783 |
620 // TODO: stackTrace? | 784 /// A [ServiceException] is an exception that was triggered in the service |
785 /// server or client. Exceptions are events that should be handled, | |
786 /// for example, an isolate went away or the connection to the VM was lost. | |
787 class ServiceException extends ServiceObject { | |
788 ServiceException._empty(ServiceObject owner) : super._empty(owner); | |
789 | |
790 @observable String kind; | |
791 @observable String message; | |
792 @observable dynamic response; | |
793 | |
794 void _update(ObservableMap map, bool mapIsRef) { | |
795 kind = map['kind']; | |
796 message = map['message']; | |
797 response = map['response']; | |
798 name = 'ServiceException $kind'; | |
799 vmName = name; | |
800 } | |
621 } | 801 } |
622 | 802 |
623 class ScriptLine { | 803 class ScriptLine { |
624 @reflectable final int line; | 804 @reflectable final int line; |
625 @reflectable final String text; | 805 @reflectable final String text; |
626 ScriptLine(this.line, this.text); | 806 ScriptLine(this.line, this.text); |
627 } | 807 } |
628 | 808 |
629 class Script extends ServiceObject { | 809 class Script extends ServiceObject { |
630 @reflectable final lines = new ObservableList<ScriptLine>(); | 810 @reflectable final lines = new ObservableList<ScriptLine>(); |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
993 var v = list[i]; | 1173 var v = list[i]; |
994 if ((v is ObservableMap) && _isServiceMap(v)) { | 1174 if ((v is ObservableMap) && _isServiceMap(v)) { |
995 list[i] = owner.getFromMap(v); | 1175 list[i] = owner.getFromMap(v); |
996 } else if (v is ObservableList) { | 1176 } else if (v is ObservableList) { |
997 _upgradeObservableList(v, owner); | 1177 _upgradeObservableList(v, owner); |
998 } else if (v is ObservableMap) { | 1178 } else if (v is ObservableMap) { |
999 _upgradeObservableMap(v, owner); | 1179 _upgradeObservableMap(v, owner); |
1000 } | 1180 } |
1001 } | 1181 } |
1002 } | 1182 } |
OLD | NEW |