Chromium Code Reviews| Index: runtime/bin/vmservice/client/lib/src/service/object.dart |
| diff --git a/runtime/bin/vmservice/client/lib/src/service/object.dart b/runtime/bin/vmservice/client/lib/src/service/object.dart |
| index 7df9eb6046302504f5c05592b78f4115bedd88ab..a24d1a6062af684bbe8edf2d58baa82357183991 100644 |
| --- a/runtime/bin/vmservice/client/lib/src/service/object.dart |
| +++ b/runtime/bin/vmservice/client/lib/src/service/object.dart |
| @@ -29,11 +29,6 @@ abstract class ServiceObject extends Observable { |
| /// The complete service url of this object. |
| @reflectable String get link => _owner.relativeLink(_id); |
| - /// The complete service url of this object with a '#/' prefix. |
| - // TODO(turnidge): Figure out why using a getter here messes up polymer. |
| - @reflectable String get hashLink => '#/${link}'; |
| - @reflectable set hashLink(var o) { /* silence polymer */ } |
| - |
| /// Has this object been fully loaded? |
| bool get loaded => _loaded; |
| bool _loaded = false; |
| @@ -67,6 +62,9 @@ abstract class ServiceObject extends Observable { |
| var obj = null; |
| assert(type != 'VM'); |
| switch (type) { |
| + case 'Class': |
| + obj = new Class._empty(owner); |
| + break; |
| case 'Code': |
| obj = new Code._empty(owner); |
| break; |
| @@ -252,14 +250,7 @@ abstract class VM extends ServiceObjectOwner { |
| } |
| Future<ServiceObject> get(String id) { |
| - var parts = id.split('#'); |
| - assert(parts.length >= 1); |
| - // We should never see more than two hashes. |
| - assert(parts.length <= 2); |
| - // The ID does not include anything after the # (or the # itself). |
| - id = parts[0]; |
| - // I'm serious. |
| - assert(!id.contains('#')); |
| + assert(id.startsWith('/') == false); |
| // Isolates are handled specially, since they can cache sub-objects. |
| if (id.startsWith(_isolatesPrefix)) { |
| String isolateId = _parseIsolateId(id); |
| @@ -283,14 +274,15 @@ abstract class VM extends ServiceObjectOwner { |
| if (obj != null) { |
| return obj.reload(); |
| } |
| + |
| // Cache miss. Get the object from the vm directly. |
| return getAsMap(id).then((ObservableMap map) { |
| - var obj = new ServiceObject._fromMap(this, map); |
| - if (obj.canCache) { |
| - _cache.putIfAbsent(id, () => obj); |
| - } |
| - return obj; |
| - }); |
| + var obj = new ServiceObject._fromMap(this, map); |
| + if (obj.canCache) { |
| + _cache.putIfAbsent(id, () => obj); |
| + } |
| + return obj; |
| + }); |
| } |
| dynamic _reviver(dynamic key, dynamic value) { |
| @@ -498,8 +490,7 @@ class Isolate extends ServiceObjectOwner { |
| @reflectable Isolate get isolate => this; |
| @observable ObservableMap counters = new ObservableMap(); |
| - String get link => _id; |
| - String get hashLink => '#/$_id'; |
| + String get link => '/${_id}'; |
| @observable ServiceMap pauseEvent = null; |
| bool get _isPaused => pauseEvent != null; |
| @@ -517,9 +508,7 @@ class Isolate extends ServiceObjectOwner { |
| } |
| /// Creates a link to [id] relative to [this]. |
| - @reflectable String relativeLink(String id) => '${this.id}/$id'; |
| - /// Creates a relative link to [id] with a '#/' prefix. |
| - @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; |
| + @reflectable String relativeLink(String id) => '/${this.id}/$id'; |
| static const TAG_ROOT_ID = 'code/tag-0'; |
| @@ -585,6 +574,37 @@ class Isolate extends ServiceObjectOwner { |
| script._processHits(scriptCoverage['hits']); |
| } |
| + Future getClassHierarchy() { |
|
turnidge
2014/06/04 18:02:24
Can we add a type param to this Future? I think
Cutch
2014/06/04 20:28:57
Done.
|
| + return get('classes').then(_processClasses).then(_postProcessClasses); |
| + } |
| + |
| + Future _processClasses(ServiceMap classList) { |
|
turnidge
2014/06/04 18:02:24
Maybe name this _loadClasses?
Cutch
2014/06/04 20:28:57
Woah! I made that rename before reading this comme
|
| + assert(classList.serviceType == 'ClassList'); |
| + var futureClasses = []; |
| + for (var cls in classList['members']) { |
| + // Skip over non-class classes. |
| + if (cls is Class) { |
| + futureClasses.add(cls.load()); |
| + } |
| + } |
| + return Future.wait(futureClasses); |
| + } |
| + |
| + Future _postProcessClasses(List<Class> classes) { |
| + rootClasses.clear(); |
| + objectClass = null; |
| + for (var cls in classes) { |
| + if (cls.superClass == null) { |
| + rootClasses.add(cls); |
|
turnidge
2014/06/04 18:02:24
I thought that Object was the root class. Am I be
Cutch
2014/06/04 20:28:57
Internal VM classes (Field, Function, etc).
Note,
|
| + } |
| + if ((cls.vmName == 'Object') && (cls.isPatch == false)) { |
| + objectClass = cls; |
| + } |
| + } |
| + assert(objectClass != null); |
| + return new Future.value(objectClass); |
| + } |
| + |
| ServiceObject getFromMap(ObservableMap map) { |
| if (map == null) { |
| return null; |
| @@ -619,6 +639,9 @@ class Isolate extends ServiceObjectOwner { |
| }); |
| } |
| + @observable Class objectClass; |
| + @observable final rootClasses = new ObservableList<Class>(); |
| + |
| @observable Library rootLib; |
| @observable ObservableList<Library> libraries = |
| new ObservableList<Library>(); |
| @@ -906,7 +929,7 @@ class Library extends ServiceObject { |
| @observable String url; |
| @reflectable final imports = new ObservableList<Library>(); |
| @reflectable final scripts = new ObservableList<Script>(); |
| - @reflectable final classes = new ObservableList<ServiceMap>(); |
| + @reflectable final classes = new ObservableList<Class>(); |
| @reflectable final variables = new ObservableList<ServiceMap>(); |
| @reflectable final functions = new ObservableList<ServiceMap>(); |
| @@ -945,6 +968,92 @@ class Library extends ServiceObject { |
| } |
| } |
| +class Class extends ServiceObject { |
| + @observable Library library; |
| + @observable Script script; |
| + @observable Class superClass; |
| + |
| + @observable bool isAbstract; |
| + @observable bool isConst; |
| + @observable bool isFinalized; |
| + @observable bool isPatch; |
| + @observable bool isImplemented; |
| + |
| + @observable int tokenPos; |
| + |
| + @observable ServiceMap error; |
| + |
| + @reflectable final children = new ObservableList<Class>(); |
| + @reflectable final subClasses = new ObservableList<Class>(); |
| + @reflectable final fields = new ObservableList<ServiceMap>(); |
| + @reflectable final functions = new ObservableList<ServiceMap>(); |
| + @reflectable final interfaces = new ObservableList<Class>(); |
| + |
| + bool get canCache => true; |
| + bool get immutable => false; |
| + |
| + Class._empty(ServiceObjectOwner owner) : super._empty(owner) { |
| + } |
|
turnidge
2014/06/04 18:02:24
Instead of empty body, just use a ';'?
Cutch
2014/06/04 20:28:57
Done.
|
| + |
| + String toString() { |
| + return 'Service Class: $vmName'; |
| + } |
| + |
| + void _update(ObservableMap map, bool mapIsRef) { |
| + name = map['user_name']; |
| + vmName = map['name']; |
| + |
| + if (mapIsRef) { |
| + return; |
| + } |
| + |
| + // We are fully loaded. |
| + _loaded = true; |
| + |
| + // Extract full properties. |
| + _upgradeCollection(map, isolate); |
| + |
| + // Some builtin classes aren't associated with a library. |
| + if (map['library'] is Library) { |
| + library = map['library']; |
| + } else { |
| + library = null; |
| + } |
| + |
| + script = map['script']; |
| + |
| + isAbstract = map['abstract']; |
| + isConst = map['const']; |
| + isFinalized = map['finalized']; |
| + isPatch = map['patch']; |
| + isImplemented = map['implemented']; |
| + |
| + tokenPos = map['tokenPos']; |
| + |
| + subClasses.clear(); |
| + subClasses.addAll(map['subclasses']); |
| + |
| + fields.clear(); |
| + fields.addAll(map['fields']); |
| + |
| + functions.clear(); |
| + functions.addAll(map['functions']); |
| + |
| + superClass = map['super']; |
| + if (superClass != null) { |
| + superClass._addToChildren(this); |
| + } |
| + error = map['error']; |
| + } |
| + |
| + void _addToChildren(Class cls) { |
| + if (children.contains(cls)) { |
| + return; |
| + } |
| + children.add(cls); |
| + } |
| +} |
| + |
| class ScriptLine { |
| @reflectable final int line; |
| @reflectable final String text; |