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

Unified Diff: runtime/bin/vmservice/client/lib/src/service/service.dart

Issue 192443004: Complete the switch to ServiceObject (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: runtime/bin/vmservice/client/lib/src/service/service.dart
diff --git a/runtime/bin/vmservice/client/lib/src/service/service.dart b/runtime/bin/vmservice/client/lib/src/service/service.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0ffa7daa52a3c8c736b56ed00222bd4c0c6fb175
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/service/service.dart
@@ -0,0 +1,184 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+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;
+
+ /// Owning isolate.
+ Isolate get isolate => _isolate;
+
+ /// Owning vm.
+ VM get vm => _isolate.vm;
+
+ /// The complete service url of this object.
+ String get link => isolate.relativeLink(_id);
+
+ /// The complete service url of this object with a '#/' prefix.
+ String get hashLink => isolate.relativeHashLink(_id);
+
+ String _id;
+ /// The id of this object.
+ String get id => _id;
+
+ String _serviceType;
+ /// The service type of this object.
+ String get serviceType => _serviceType;
+
+ bool _ref;
+
+ @observable String name;
+ @observable String vmName;
+
+ ServiceObject(this._isolate, 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']);
+ _created();
+ update(m);
+ }
+
+ /// If [this] was created from a reference, load the full object
+ /// from the service by calling [reload]. Else, return [this].
+ Future<ServiceObject> load() {
+ if (!_ref) {
+ // Not a reference.
+ return new Future.value(this);
+ }
+ // Call refresh which will fill in the entire object.
+ return reload();
+ }
+
+ /// 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);
+ }
+
+ /// Update [this] using [m] as a source. [m] can be a reference.
+ ServiceObject update(ObservableMap m) {
+ // Assert that m is a service map.
+ assert(ServiceObject.isServiceMap(m));
+ if ((m['type'] == 'Error') && (_serviceType != 'Error')) {
+ // Got an unexpected error. Don't update the object.
+ return _upgradeToServiceObject(vm, isolate, m);
+ }
+ // TODO(johnmccutchan): Should we allow for a ServiceObject's id
+ // or type to change?
+ _id = m['id'];
+ _serviceType = stripRef(m['type']);
+ _update(m);
+ return this;
+ }
+
+ // 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) {
+ return (m != null) && (m['id'] != null) && (m['type'] != null);
+ }
+
+ /// Returns true if [type] is a reference type. i.e. it begins with an
+ /// '@' character.
+ static bool isRefType(String type) {
+ return type.startsWith('@');
+ }
+
+ /// Returns the unreffed version of [type].
+ static String stripRef(String type) {
+ if (!isRefType(type)) {
+ return type;
+ }
+ // Strip off the '@' character.
+ return type.substring(1);
+ }
+}
+
+/// Recursively upgrades all [ServiceObject]s inside [collection] which must
+/// be an [ObservableMap] or an [ObservableList]. Upgraded elements will be
+/// associated with [vm] and [isolate].
+void upgradeCollection(collection, VM vm, Isolate isolate) {
+ if (collection is ObservableMap) {
+ _upgradeObservableMap(collection, vm, isolate);
+ } else if (collection is ObservableList) {
+ _upgradeObservableList(collection, vm, isolate);
+ }
+}
+
+void _upgradeObservableMap(ObservableMap map, VM vm, Isolate isolate) {
+ map.forEach((k, v) {
+ if ((v is ObservableMap) && ServiceObject.isServiceMap(v)) {
+ map[k] = v = _upgradeToServiceObject(vm, isolate, v);
+ } else if (v is ObservableList) {
+ _upgradeObservableList(v, vm, isolate);
+ } else if (v is ObservableMap) {
+ _upgradeObservableMap(v, vm, isolate);
+ }
+ });
+}
+
+void _upgradeObservableList(ObservableList list, VM vm, Isolate isolate) {
+ for (var i = 0; i < list.length; i++) {
+ var v = list[i];
+ if ((v is ObservableMap) && ServiceObject.isServiceMap(v)) {
+ list[i] = _upgradeToServiceObject(vm, isolate, v);
+ } else if (v is ObservableList) {
+ _upgradeObservableList(v, vm, isolate);
+ } else if (v is ObservableMap) {
+ _upgradeObservableMap(v, vm, isolate);
+ }
+ }
+}
+
+/// Upgrades response ([m]) from [vm] and [isolate] to a [ServiceObject].
+/// This acts like a factory which consumes an ObservableMap and returns
+/// a fully upgraded ServiceObject.
+ServiceObject _upgradeToServiceObject(VM vm, Isolate isolate, ObservableMap m) {
+ assert(ServiceObject.isServiceMap(m));
+ var type = ServiceObject.stripRef(m['type']);
+ switch (type) {
+ case 'Error':
+ return new ServiceError.fromMap(isolate, m);
+ case 'IsolateList':
+ vm.isolates.update(m);
+ return vm.isolates;
+ case 'Script':
+ return isolate.scripts.putIfAbsent(m);
+ case 'Code':
+ return isolate.codes.putIfAbsent(m);
+ case 'Isolate':
+ return vm.isolates.getIsolateFromMap(m);
+ case 'Class':
+ return isolate.classes.putIfAbsent(m);
+ }
+ return new ServiceMap.fromMap(isolate, m);
+}

Powered by Google App Engine
This is Rietveld 408576698