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 63e253f021a4a60c53cc05b7034d73c2bfb178a6..3d384c5432026053af72f5bdbde7aa96a1054ffa 100644 |
| --- a/runtime/bin/vmservice/client/lib/src/service/object.dart |
| +++ b/runtime/bin/vmservice/client/lib/src/service/object.dart |
| @@ -7,47 +7,73 @@ part of service; |
| /// A [ServiceObject] is an object known to the VM service and is tied |
| /// to an owning [Isolate]. |
| abstract class ServiceObject extends Observable { |
| - Isolate _isolate; |
| + /// The owner of this [ServiceObject]. This can be an [Isolate], a |
| + /// [VM], or null. |
| + @reflectable ServiceObject get owner => _owner; |
| + ServiceObject _owner; |
| + |
| + /// The [VM] which owns this [ServiceObject]. |
| + @reflectable VM get vm { |
| + if (owner == null) { |
| + assert(this is VM); |
| + return this; |
| + } else if (owner is VM) { |
| + return owner; |
| + } else { |
| + assert(owner.owner is VM); |
| + return owner.owner; |
| + } |
| + } |
| - /// Owning isolate. |
| - @reflectable Isolate get isolate => _isolate; |
| + /// The [Isolate] which owns this [ServiceObject]. May be null. |
| + @reflectable Isolate get isolate { |
| + if (owner == null) { |
| + return null; |
| + } else if (this is Isolate) { |
| + return this; |
| + } else { |
| + assert(owner is Isolate); |
| + return owner; |
| + } |
| + } |
| + |
| + /// The id of this object. |
| + @reflectable String get id => _id; |
| + String _id; |
| - /// Owning vm. |
| - @reflectable VM get vm => _isolate.vm; |
| + /// The service type of this object. |
| + @reflectable String get serviceType => _serviceType; |
| + String _serviceType; |
| /// The complete service url of this object. |
| @reflectable String get link => isolate.relativeLink(_id); |
| /// The complete service url of this object with a '#/' prefix. |
| - @reflectable String get hashLink => isolate.relativeHashLink(_id); |
| + @reflectable String get hashLink => '#/${link}'; |
| set hashLink(var o) { /* silence polymer */ } |
| - String _id; |
| - /// The id of this object. |
| - @reflectable String get id => _id; |
| - |
| - String _serviceType; |
| - /// The service type of this object. |
| - @reflectable String get serviceType => _serviceType; |
| - |
| + /// Returns true if [this] has only been partially initialized via |
| + /// a reference. See [load]. |
| + bool isRef() => _ref; |
| bool _ref; |
| @observable String name; |
| @observable String vmName; |
| + @observable String mainPort; |
| - ServiceObject(this._isolate, this._id, this._serviceType) { |
| + ServiceObject(this._owner, this._id, this._serviceType) { |
| _ref = isRefType(_serviceType); |
| _serviceType = stripRef(_serviceType); |
| _created(); |
| } |
| - ServiceObject.fromMap(this._isolate, ObservableMap m) { |
| - assert(isServiceMap(m)); |
| - _id = m['id']; |
| - _ref = isRefType(m['type']); |
| - _serviceType = stripRef(m['type']); |
| + ServiceObject.fromMap(this._owner, ObservableMap map) { |
| + assert(isServiceMap(map)); |
| + _id = map['id']; |
| + _ref = isRefType(map['type']); |
| + _serviceType = stripRef(map['type']); |
| + update(map); |
| _created(); |
| - update(m); |
| } |
| /// If [this] was created from a reference, load the full object |
| @@ -64,13 +90,12 @@ abstract class ServiceObject extends Observable { |
| /// Reload [this]. Returns a future which completes to [this] or |
| /// a [ServiceError]. |
| Future<ServiceObject> reload() { |
| - assert(isolate != null); |
| if (id == '') { |
| // Errors don't have ids. |
| assert(serviceType == 'Error'); |
| return new Future.value(this); |
| } |
| - return isolate.vm.getAsMap(link).then(update); |
| + return vm.getAsMap(link).then(update); |
| } |
| /// Update [this] using [m] as a source. [m] can be a reference. |
| @@ -92,16 +117,14 @@ abstract class ServiceObject extends Observable { |
| // update internal state from [map]. [map] can be a reference. |
| void _update(ObservableMap map); |
| - /// Returns true if [this] has only been partially initialized via |
| - /// a reference. See [load]. |
| - bool isRef() => _ref; |
| - |
| void _created() { |
| var refNotice = _ref ? ' Created from reference.' : ''; |
| Logger.root.info('Created ServiceObject for \'${_id}\' with type ' |
| '\'${_serviceType}\'.' + refNotice); |
| } |
| + // ------------------------------------------------------ |
| + |
| /// Returns true if [map] is a service map. i.e. it has the following keys: |
| /// 'id' and a 'type'. |
| static bool isServiceMap(ObservableMap m) { |
| @@ -125,20 +148,80 @@ abstract class ServiceObject extends Observable { |
| } |
| /// State for a VM being inspected. |
| -abstract class VM extends Observable { |
| +abstract class VM extends ServiceObject { |
| @reflectable IsolateList _isolates; |
| @reflectable IsolateList get isolates => _isolates; |
| + @reflectable String get link => "$id"; |
| + |
| + @observable String version = 'unknown'; |
| + @observable String architecture = 'unknown'; |
| + @observable double uptime = 0.0; |
| + |
| void _initOnce() { |
| assert(_isolates == null); |
| _isolates = new IsolateList(this); |
| + name = "vm"; |
| + vmName = "vm"; |
| } |
| - VM() { |
| + VM() : super(null, "vm", "VM") { |
| _initOnce(); |
| } |
| - /// Get [id] as an [ObservableMap] from the service directly. |
| + static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); |
| + static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)'); |
| + |
| + String _parseObjectId(String id) { |
| + Match m = _currentObjectMatcher.matchAsPrefix(id); |
| + if (m == null) { |
| + return null; |
| + } |
| + return m.input.substring(m.end); |
| + } |
| + |
| + String _parseIsolateId(String id) { |
| + Match m = _currentIsolateMatcher.matchAsPrefix(id); |
| + if (m == null) { |
| + print("NO MATCH"); |
|
Cutch
2014/03/20 18:25:56
Logger.root.warning ?
turnidge
2014/03/20 19:08:02
Actually this happens legitimately on the /vm page
|
| + return ''; |
| + } |
| + return id.substring(0, m.end); |
| + } |
| + |
| + Future<ServiceObject> _getDirect(String id) { |
| + return vm.getAsMap(id).then((ObservableMap m) { |
| + return _upgradeToServiceObject(vm, null, m); |
| + }); |
| + } |
| + |
| + Future<ServiceObject> get(String id) { |
| + if (id.startsWith('isolates/')) { |
| + String isolateId = _parseIsolateId(id); |
| + if (isolateId == '') { |
| + return reload(); |
| + } else { |
| + Isolate isolate = _isolates.getIsolate(isolateId); |
| + if (isolate == null) { |
| + // TODO(turnidge): Isolate not found error. |
| + return reload(); |
| + } else { |
| + String objectId = _parseObjectId(id); |
| + if (objectId == null) { |
| + return isolate.reload(); |
| + } else { |
| + return isolate.get(objectId); |
| + } |
| + } |
| + } |
| + } else if (id == 'vm') { |
| + return reload(); |
| + } else { |
| + return _getDirect(id); |
| + } |
| + } |
| + |
| + /// Gets [id] as an [ObservableMap] from the service directly. |
| Future<ObservableMap> getAsMap(String id) { |
| return getString(id).then((response) { |
| try { |
| @@ -165,14 +248,27 @@ abstract class VM extends Observable { |
| /// Get [id] as a [String] from the service directly. See [getAsMap]. |
| Future<String> getString(String id); |
| + |
| + void _update(ObservableMap map) { |
| + print("$map"); |
|
Cutch
2014/03/20 18:25:56
remove?
turnidge
2014/03/20 19:08:02
Done.
|
| + _ref = false; |
| + version = map['version']; |
| + architecture = map['architecture']; |
| + uptime = map['uptime']; |
| + _isolates.updateIsolates(map['isolates']); |
| + } |
| } |
| /// State for a running isolate. |
| class Isolate extends ServiceObject { |
| - final VM vm; |
| String get link => _id; |
| String get hashLink => '#/$_id'; |
| + @observable bool pausedOnStart = false; |
| + @observable bool pausedOnExit = false; |
| + @observable bool running = false; |
| + @observable bool idle = false; |
| + |
| ScriptCache _scripts; |
| /// Script cache. |
| ScriptCache get scripts => _scripts; |
| @@ -188,19 +284,18 @@ class Isolate extends ServiceObject { |
| void _initOnce() { |
| // Only called once. |
| - assert(_isolate == null); |
| - _isolate = this; |
| + assert(_scripts == null); |
| _scripts = new ScriptCache(this); |
| _codes = new CodeCache(this); |
| _classes = new ClassCache(this); |
| _functions = new FunctionCache(this); |
| } |
| - Isolate.fromId(this.vm, String id) : super(null, id, '@Isolate') { |
| + Isolate.fromId(VM vm, String id) : super(vm, id, '@Isolate') { |
| _initOnce(); |
| } |
| - Isolate.fromMap(this.vm, Map map) : super.fromMap(null, map) { |
| + Isolate.fromMap(VM vm, Map map) : super.fromMap(vm, map) { |
| _initOnce(); |
| } |
| @@ -230,7 +325,7 @@ class Isolate extends ServiceObject { |
| } |
| } |
| - Future<ServiceObject> getDirect(String serviceId) { |
| + Future<ServiceObject> _getDirect(String serviceId) { |
| return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) { |
| return _upgradeToServiceObject(vm, this, m); |
| }); |
| @@ -254,7 +349,7 @@ class Isolate extends ServiceObject { |
| if (_functions.cachesId(serviceId)) { |
| return _functions.get(serviceId); |
| } |
| - return getDirect(serviceId); |
| + return _getDirect(serviceId); |
| } |
| @observable ServiceMap rootLib; |
| @@ -276,6 +371,11 @@ class Isolate extends ServiceObject { |
| void _update(ObservableMap map) { |
| upgradeCollection(map, vm, this); |
| + mainPort = map['mainPort']; |
| + name = map['name']; |
| + if (ServiceObject.isRefType(map['type'])) { |
| + return; |
| + } |
| _ref = false; |
| if (map['rootLib'] == null || |
| map['timers'] == null || |
| @@ -287,10 +387,6 @@ class Isolate extends ServiceObject { |
| vmName = map['name']; |
| if (map['entry'] != null) { |
| entry = map['entry']; |
| - name = entry['name']; |
| - } else { |
| - // fred |
| - name = 'root'; |
| } |
| if (map['topFrame'] != null) { |
| topFrame = map['topFrame']; |
| @@ -315,6 +411,12 @@ class Isolate extends ServiceObject { |
| oldHeapUsed = map['heap']['usedOld']; |
| newHeapCapacity = map['heap']['capacityNew']; |
| oldHeapCapacity = map['heap']['capacityOld']; |
| + |
| + // Isolate status |
| + pausedOnStart = map['pausedOnStart']; |
| + pausedOnExit = map['pausedOnExit']; |
| + running = map['topFrame'] != null; |
| + idle = !pausedOnStart && !pausedOnExit && !running; |
| } |
| @reflectable CodeTrieNode profileTrieRoot; |
| @@ -364,28 +466,13 @@ class Isolate extends ServiceObject { |
| } |
| // TODO(johnmccutchan): Make this into an IsolateCache. |
| -class IsolateList extends ServiceObject { |
| +class IsolateList { |
| final VM _vm; |
| - VM get vm => _vm; |
| @observable final isolates = new ObservableMap<String, Isolate>(); |
| - IsolateList(this._vm) : super(null, 'isolates', 'IsolateList') { |
| - name = 'IsolateList'; |
| - vmName = name; |
| - } |
| - IsolateList.fromMap(this._vm, Map m) : super.fromMap(null, m) { |
| - name = 'IsolateList'; |
| - vmName = name; |
| - } |
| - |
| - Future<ServiceObject> reload() { |
| - return vm.getAsMap(id).then(update); |
| - } |
| - void _update(ObservableMap map) { |
| - _updateIsolates(map['members']); |
| - } |
| + IsolateList(this._vm); |
| - void _updateIsolates(List<Map> members) { |
| + void updateIsolates(List<Map> members) { |
| // Find dead isolates. |
| var deadIsolates = []; |
| isolates.forEach((k, v) { |
| @@ -404,7 +491,7 @@ class IsolateList extends ServiceObject { |
| var id = map['id']; |
| var isolate = isolates[id]; |
| if (isolate == null) { |
| - isolate = new Isolate.fromMap(vm, map); |
| + isolate = new Isolate.fromMap(_vm, map); |
| Logger.root.info('Created ServiceObject for \'${isolate.id}\' with ' |
| 'type \'${isolate.serviceType}\''); |
| isolates[id] = isolate; |
| @@ -429,7 +516,7 @@ class IsolateList extends ServiceObject { |
| if (isolate != null) { |
| return isolate; |
| } |
| - isolate = new Isolate.fromId(vm, id); |
| + isolate = new Isolate.fromId(_vm, id); |
| isolates[id] = isolate; |
| isolate.load(); |
| return isolate; |
| @@ -444,7 +531,7 @@ class IsolateList extends ServiceObject { |
| isolate.update(m); |
| return isolate; |
| } |
| - isolate = new Isolate.fromMap(vm, m); |
| + isolate = new Isolate.fromMap(_vm, m); |
| isolates[id] = isolate; |
| isolate.load(); |
| return isolate; |
| @@ -509,7 +596,7 @@ class ServiceMap extends ServiceObject implements ObservableMap { |
| } |
| class ServiceError extends ServiceObject { |
| - ServiceError.fromMap(Isolate isolate, Map m) : super.fromMap(isolate, m); |
| + ServiceError.fromMap(ServiceObject owner, Map m) : super.fromMap(owner, m); |
| @observable String kind; |
| @observable String message; |