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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 bool deliverChanges() => _map.deliverChanges(); | 735 bool deliverChanges() => _map.deliverChanges(); |
597 void notifyChange(ChangeRecord record) => _map.notifyChange(record); | 736 void notifyChange(ChangeRecord record) => _map.notifyChange(record); |
598 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => | 737 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => |
599 _map.notifyPropertyChange(field, oldValue, newValue); | 738 _map.notifyPropertyChange(field, oldValue, newValue); |
600 void observed() => _map.observed(); | 739 void observed() => _map.observed(); |
601 void unobserved() => _map.unobserved(); | 740 void unobserved() => _map.unobserved(); |
602 Stream<List<ChangeRecord>> get changes => _map.changes; | 741 Stream<List<ChangeRecord>> get changes => _map.changes; |
603 bool get hasObservers => _map.hasObservers; | 742 bool get hasObservers => _map.hasObservers; |
604 } | 743 } |
605 | 744 |
| 745 /// A [DartError] is peered to a Dart Error object. |
| 746 class DartError extends ServiceObject { |
| 747 DartError._empty(ServiceObject owner) : super._empty(owner); |
| 748 |
| 749 @observable String kind; |
| 750 @observable String message; |
| 751 @observable ServiceMap exception; |
| 752 @observable ServiceMap stacktrace; |
| 753 |
| 754 void _update(ObservableMap map, bool mapIsRef) { |
| 755 kind = map['kind']; |
| 756 message = map['message']; |
| 757 exception = new ServiceObject._fromMap(owner, map['exception']); |
| 758 stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']); |
| 759 name = 'DartError $kind'; |
| 760 vmName = name; |
| 761 } |
| 762 } |
| 763 |
| 764 /// A [ServiceError] is an error that was triggered in the service |
| 765 /// server or client. Errors are prorammer mistakes that could have |
| 766 /// been prevented, for example, requesting a non-existant path over the |
| 767 /// service. |
606 class ServiceError extends ServiceObject { | 768 class ServiceError extends ServiceObject { |
607 ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner); | 769 ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner); |
608 | 770 |
609 @observable String kind; | 771 @observable String kind; |
610 @observable String message; | 772 @observable String message; |
611 | 773 |
612 void _update(ObservableMap map, bool mapIsRef) { | 774 void _update(ObservableMap map, bool mapIsRef) { |
613 _loaded = true; | 775 _loaded = true; |
614 kind = map['kind']; | 776 kind = map['kind']; |
615 message = map['message']; | 777 message = map['message']; |
616 name = 'ServiceError $kind'; | 778 name = 'ServiceError $kind'; |
617 vmName = name; | 779 vmName = name; |
618 } | 780 } |
| 781 } |
619 | 782 |
620 // TODO: stackTrace? | 783 /// A [ServiceException] is an exception that was triggered in the service |
| 784 /// server or client. Exceptions are events that should be handled, |
| 785 /// for example, an isolate went away or the connection to the VM was lost. |
| 786 class ServiceException extends ServiceObject { |
| 787 ServiceException._empty(ServiceObject owner) : super._empty(owner); |
| 788 |
| 789 @observable String kind; |
| 790 @observable String message; |
| 791 @observable dynamic response; |
| 792 |
| 793 void _update(ObservableMap map, bool mapIsRef) { |
| 794 kind = map['kind']; |
| 795 message = map['message']; |
| 796 response = map['response']; |
| 797 name = 'ServiceException $kind'; |
| 798 vmName = name; |
| 799 } |
621 } | 800 } |
622 | 801 |
623 class ScriptLine { | 802 class ScriptLine { |
624 @reflectable final int line; | 803 @reflectable final int line; |
625 @reflectable final String text; | 804 @reflectable final String text; |
626 ScriptLine(this.line, this.text); | 805 ScriptLine(this.line, this.text); |
627 } | 806 } |
628 | 807 |
629 class Script extends ServiceObject { | 808 class Script extends ServiceObject { |
630 @reflectable final lines = new ObservableList<ScriptLine>(); | 809 @reflectable final lines = new ObservableList<ScriptLine>(); |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 var v = list[i]; | 1172 var v = list[i]; |
994 if ((v is ObservableMap) && _isServiceMap(v)) { | 1173 if ((v is ObservableMap) && _isServiceMap(v)) { |
995 list[i] = owner.getFromMap(v); | 1174 list[i] = owner.getFromMap(v); |
996 } else if (v is ObservableList) { | 1175 } else if (v is ObservableList) { |
997 _upgradeObservableList(v, owner); | 1176 _upgradeObservableList(v, owner); |
998 } else if (v is ObservableMap) { | 1177 } else if (v is ObservableMap) { |
999 _upgradeObservableMap(v, owner); | 1178 _upgradeObservableMap(v, owner); |
1000 } | 1179 } |
1001 } | 1180 } |
1002 } | 1181 } |
OLD | NEW |