blob: aa60a75a08c3bec106a82977687aadf19c954be1 [file] [log] [blame]
// Copyright (c) 2015, 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.
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';
import 'package:stack_trace/stack_trace.dart';
import 'bound_field.dart';
import 'class.dart';
import 'context.dart';
import 'exceptions.dart';
import 'function.dart';
import 'object.dart';
import 'scope.dart';
import 'sentinel.dart';
import 'type_arguments.dart';
import 'utils.dart';
VMInstanceRef newVMInstanceRef(Scope scope, Map json) {
if (json == null) return null;
assert(json["type"] == "@Instance" || json["type"] == "Instance");
switch (json["kind"]) {
case "Null":
return new VMNullInstanceRef._(scope, json);
case "Bool":
return new VMBoolInstanceRef._(scope, json);
case "Double":
return new VMDoubleInstanceRef._(scope, json);
case "Int":
return new VMIntInstanceRef._(scope, json);
case "String":
return new VMStringInstanceRef._(scope, json);
case "Float32x4":
return new VMFloat32x4InstanceRef._(scope, json);
case "Float64x2":
return new VMFloat64x2InstanceRef._(scope, json);
case "Int32x4":
return new VMInt32x4InstanceRef._(scope, json);
case "StackTrace":
return new VMStackTraceInstanceRef._(scope, json);
case "List":
return new VMListInstanceRef._(scope, json);
case "Map":
return new VMMapInstanceRef._(scope, json);
case "Uint8ClampedList":
return new VMTypedDataInstanceRef<Uint8ClampedList>._(scope, json);
case "Uint8List":
return new VMTypedDataInstanceRef<Uint8List>._(scope, json);
case "Uint16List":
return new VMTypedDataInstanceRef<Uint16List>._(scope, json);
case "Uint32List":
return new VMTypedDataInstanceRef<Uint32List>._(scope, json);
case "Uint64List":
return new VMTypedDataInstanceRef<Uint64List>._(scope, json);
case "Int8List":
return new VMTypedDataInstanceRef<Int8List>._(scope, json);
case "Int16List":
return new VMTypedDataInstanceRef<Int16List>._(scope, json);
case "Int32List":
return new VMTypedDataInstanceRef<Int32List>._(scope, json);
case "Int64List":
return new VMTypedDataInstanceRef<Int64List>._(scope, json);
case "Float32List":
return new VMTypedDataInstanceRef<Float32List>._(scope, json);
case "Float64List":
return new VMTypedDataInstanceRef<Float64List>._(scope, json);
case "Int32x4List":
return new VMTypedDataInstanceRef<Int32x4List>._(scope, json);
case "Float32x4List":
return new VMTypedDataInstanceRef<Float32x4List>._(scope, json);
case "Float64x2List":
return new VMTypedDataInstanceRef<Float64x2List>._(scope, json);
case "Closure":
return new VMClosureInstanceRef._(scope, json);
case "MirrorReference":
return new VMMirrorReferenceInstanceRef._(scope, json);
case "RegExp":
return new VMRegExpInstanceRef._(scope, json);
case "WeakProperty":
return new VMWeakPropertyInstanceRef._(scope, json);
case "Type":
return new VMTypeInstanceRef._(scope, json);
case "TypeParameter":
return new VMTypeParameterInstanceRef._(scope, json);
case "TypeRef":
return new VMTypeRefInstanceRef._(scope, json);
case "BoundedType":
return new VMBoundedTypeInstanceRef._(scope, json);
default:
// The VM service protocol specifies that unknown instance kinds are to be
// treated as plain instances.
return new VMInstanceRef._(scope, json);
}
}
VMInstanceRef newVMInstance(Scope scope, Map json) {
if (json == null) return null;
assert(json["type"] == "Instance");
switch (json["kind"]) {
case "Null":
return new VMNullInstance._(scope, json);
case "Bool":
return new VMBoolInstance._(scope, json);
case "Double":
return new VMDoubleInstance._(scope, json);
case "Int":
return new VMIntInstance._(scope, json);
case "String":
return new VMStringInstance._(scope, json);
case "Float32x4":
return new VMFloat32x4Instance._(scope, json);
case "Float64x2":
return new VMFloat64x2Instance._(scope, json);
case "Int32x4":
return new VMInt32x4Instance._(scope, json);
case "StackTrace":
return new VMStackTraceInstance._(scope, json);
case "List":
return new VMListInstance._(scope, json);
case "Map":
return new VMMapInstance._(scope, json);
case "Uint8ClampedList":
case "Uint8List":
case "Uint16List":
case "Uint32List":
case "Uint64List":
case "Int8List":
case "Int16List":
case "Int32List":
case "Int64List":
case "Float32List":
case "Float64List":
case "Int32x4List":
case "Float32x4List":
case "Float64x2List":
return new VMTypedDataInstance._(scope, json);
case "Closure":
return new VMClosureInstance._(scope, json);
case "MirrorReference":
return new VMMirrorReferenceInstance._(scope, json);
case "RegExp":
return new VMRegExpInstance._(scope, json);
case "WeakProperty":
return new VMWeakPropertyInstance._(scope, json);
case "Type":
return new VMTypeInstance._(scope, json);
case "TypeParameter":
return new VMTypeParameterInstance._(scope, json);
case "TypeRef":
return new VMTypeRefInstance._(scope, json);
case "BoundedType":
return new VMBoundedTypeInstance._(scope, json);
default:
// The VM service protocol specifies that unknown instance kinds are to be
// treated as plain instances.
return new VMInstance._(scope, json);
}
}
VMTypeLikeInstanceRef newVMTypeLikeInstanceRef(Scope scope, Map json) {
if (json == null) return null;
assert(json["type"] == "@Instance" || json["type"] == "Instance");
switch (json["kind"]) {
case "Type":
return new VMTypeInstanceRef._(scope, json);
case "TypeParameter":
return new VMTypeParameterInstanceRef._(scope, json);
case "TypeRef":
return new VMTypeRefInstanceRef._(scope, json);
case "BoundedType":
return new VMBoundedTypeInstanceRef._(scope, json);
default:
throw new StateError('Unknown Type-like kind "${json["kind"]}".');
}
}
VMTypeInstanceRef newVMTypeInstanceRef(Scope scope, Map json) {
if (json == null) return null;
assert(json["type"] == "@Instance" || json["type"] == "Instance");
assert(json["kind"] == "Type");
return new VMTypeInstanceRef._(scope, json);
}
newVMInstanceRefOrSentinel(Scope scope, Map json) {
if (json == null) return null;
if (json["type"] == "Sentinel") return newVMSentinel(json);
return newVMInstanceRef(scope, json);
}
/// A reference to an instance of a Dart class on the remote VM.
///
/// Note that subclasses of this like [List] and [Map] will only be used for the
/// built-in implementations of those classes. User-defined implementations will
/// be plain [VMInstanceRef]s or [VMInstance]s instead.
class VMInstanceRef implements VMObjectRef {
final Scope _scope;
/// The ID for this instance, which is unique relative to its isolate.
final String _id;
/// Whether [_id] is guaranteed to be the same for different VM service
/// instance objects that refer to the same instance.
final bool _fixedId;
Uri get observatoryUrl => _scope.observatoryUrlFor(_id);
final VMClassRef klass;
VMInstanceRef._(Scope scope, Map json)
: _scope = scope,
_id = json["id"],
_fixedId = json["fixedId"] ?? false,
klass = newVMClassRef(scope, json["class"]);
/// Returns a local Dart copy of the remote Dart object.
///
/// This creates a copy of all copyable objects with corresponding
/// [VMInstanceRef] subclasses. If an uncopyable or unknown instance is
/// encountered, an [UnsupportedError] is thrown. If an instance has exired, a
/// [VMSentinelException] is thrown.
///
/// If [onUnknownValue] is provided, it's called with any uncopyable instances
/// or sentinels that are encountered. Its return value is used as the value
/// of that instance or sentinel. It may return a [Future], in which case the
/// completion value of the future is used.
///
/// This is safe to use with object graphs that contain loops. Within the
/// scope of a call to [getValue], including within calls to [onUnknownValue],
/// return values are cached, so multiple calls to [getValue] for the same
/// instance will return identical Dart objects.
Future<Object> getValue({onUnknownValue(value)}) async {
if (Zone.current[#_cache] != null) return _getValue(onUnknownValue);
return runZoned(() => _getValue(onUnknownValue), zoneValues: {#_cache: {}});
}
/// A helper method for [getValue] that doesn't try to create a new cache.
Future<Object> _getValue(onUnknownValue(value)) async {
var cache = Zone.current[#_cache];
if (!cache.containsKey(this)) {
if (onUnknownValue != null) {
cache[this] = await onUnknownValue(this);
} else {
throw new UnsupportedError(
"Can't get the value of a ${klass.name} instance.");
}
}
return cache[this];
}
Future<VMInstance> load() async => new VMInstance._(_scope, await _load());
/// Evaluates [expression] in the context of this instance.
///
/// Throws a [VMErrorException] if evaluating the expression throws an error.
/// Throws a [VMSentinelException] if this instance has expired.
Future<VMInstanceRef> evaluate(String expression) =>
_scope.evaluate(_id, expression);
Future<Map> _load() => _scope.loadObject(_id);
bool operator ==(other) =>
other is VMInstanceRef && (_fixedId ? _id == other._id : super == other);
int get hashCode => _fixedId ? _id.hashCode : super.hashCode;
String toString() => "Remote instance of '${klass.name}'";
}
/// An instance of a Dart class on the remote VM.
class VMInstance extends VMInstanceRef implements VMObject {
final int size;
/// The instance's fields.
final Map<String, VMBoundField> fields;
VMInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
// Value objects
/// A reference to an instance whose value is synchronously accessible via
/// the reference.
abstract class VMValueInstanceRef<T> extends VMInstanceRef {
/// The value as a local Dart instance.
T get value;
VMValueInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMValueInstance<T>> load();
Future<T> getValue({onUnknownValue(value)}) =>
super.getValue(onUnknownValue: onUnknownValue).then((v) => v as T);
Future<T> _getValue(onUnknownValue(value)) async => value;
String toString() => value.toString();
}
/// An instance whose value is synchronously accessible via the reference.
abstract class VMValueInstance<T> implements VMValueInstanceRef<T>, VMInstance {
}
/// A reference to a `null` instance.
class VMNullInstanceRef extends VMValueInstanceRef<Null> {
Null get value => null;
VMNullInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMNullInstance> load() async =>
new VMNullInstance._(_scope, await _load());
}
/// A `null` instance.
class VMNullInstance extends VMNullInstanceRef
implements VMValueInstance<Null> {
final int size;
final Map<String, VMBoundField> fields;
VMNullInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
/// A reference to an instance of [bool].
class VMBoolInstanceRef extends VMValueInstanceRef<bool> {
final bool value;
VMBoolInstanceRef._(Scope scope, Map json)
: value = json["valueAsString"] == "true",
super._(scope, json);
Future<VMBoolInstance> load() async =>
new VMBoolInstance._(_scope, await _load());
}
/// An instance of [bool].
class VMBoolInstance extends VMBoolInstanceRef
implements VMValueInstance<bool> {
final int size;
final Map<String, VMBoundField> fields;
VMBoolInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
/// A reference to an instance of [double].
class VMDoubleInstanceRef extends VMValueInstanceRef<double> {
final double value;
VMDoubleInstanceRef._(Scope scope, Map json)
: value = double.parse(json["valueAsString"]),
super._(scope, json);
Future<VMDoubleInstance> load() async =>
new VMDoubleInstance._(_scope, await _load());
}
/// An instance of [double].
class VMDoubleInstance extends VMDoubleInstanceRef
implements VMValueInstance<double> {
final int size;
final Map<String, VMBoundField> fields;
VMDoubleInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
/// A reference to an instance of [int].
class VMIntInstanceRef extends VMValueInstanceRef<int> {
final int value;
/// The string representation of [value].
///
/// When compiled to JS, the [int] type is limited to 53 bits, but on the Dart
/// VM ints are unbounded. When dealing with ints of an unknown size in code
/// that may run on a browser, this should be used for maximum portability.
final String valueAsString;
VMIntInstanceRef._(Scope scope, Map json)
: valueAsString = json["valueAsString"],
value = int.parse(json["valueAsString"]),
super._(scope, json);
Future<VMIntInstance> load() async =>
new VMIntInstance._(_scope, await _load());
String toString() => valueAsString;
}
/// An instance of [int].
class VMIntInstance extends VMIntInstanceRef implements VMValueInstance<int> {
final int size;
final Map<String, VMBoundField> fields;
VMIntInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
/// A reference to an instance of [Float32x4].
class VMFloat32x4InstanceRef extends VMValueInstanceRef<Float32x4> {
final Float32x4 value;
VMFloat32x4InstanceRef._(Scope scope, Map json)
: value = _parse(json["valueAsString"]),
super._(scope, json);
/// Parses the [Float32x4] from the string representation of value, which is
/// of the form "[W, X, Y, Z]" where W, X, Y, and Z are floats.
static Float32x4 _parse(String value) {
var lanes = value
// Substring to get rid of the surrounding [ and ].
.substring(1, value.length - 1)
.split(",")
.map(double.parse)
.toList();
return new Float32x4(lanes[0], lanes[1], lanes[2], lanes[3]);
}
Future<Float32x4> _getValue(onUnknownValue(value)) async => value;
Future<VMFloat32x4Instance> load() async =>
new VMFloat32x4Instance._(_scope, await _load());
}
/// An instance of [Float32x4].
class VMFloat32x4Instance extends VMFloat32x4InstanceRef
implements VMValueInstance<Float32x4> {
final int size;
final Map<String, VMBoundField> fields;
VMFloat32x4Instance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
/// An instance of [Float64x2].
class VMFloat64x2InstanceRef extends VMValueInstanceRef<Float64x2> {
final Float64x2 value;
VMFloat64x2InstanceRef._(Scope scope, Map json)
: value = _parse(json["valueAsString"]),
super._(scope, json);
/// Parses the [Float64x2] from the string representation of value, which is
/// of the form "[X, Y]" where X and Y are floats.
static Float64x2 _parse(String value) {
var lanes = value
// Substring to get rid of the surrounding [ and ].
.substring(1, value.length - 1)
.split(",")
.map(double.parse)
.toList();
return new Float64x2(lanes[0], lanes[1]);
}
Future<VMFloat64x2Instance> load() async =>
new VMFloat64x2Instance._(_scope, await _load());
}
/// An instance of [Float64x2].
class VMFloat64x2Instance extends VMFloat64x2InstanceRef
implements VMValueInstance<Float64x2> {
final int size;
final Map<String, VMBoundField> fields;
VMFloat64x2Instance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
/// A reference to an instance of [Int32x4].
class VMInt32x4InstanceRef extends VMValueInstanceRef<Int32x4> {
final Int32x4 value;
VMInt32x4InstanceRef._(Scope scope, Map json)
: value = _parse(json["valueAsString"]),
super._(scope, json);
/// Parses the [Int32x4] from the string representation of value, which is
/// of the form "[M, N, P, Q]" where N, M, P, and Q are integers.
static Int32x4 _parse(String value) {
var lanes = value
// Substring to get rid of the surrounding [ and ].
.substring(1, value.length - 1)
.split(",")
.map((lane) => int.parse(lane, radix: 16))
.toList();
return new Int32x4(lanes[0], lanes[1], lanes[2], lanes[3]);
}
Future<VMInt32x4Instance> load() async =>
new VMInt32x4Instance._(_scope, await _load());
}
/// An instance of [Int32x4].
class VMInt32x4Instance extends VMInt32x4InstanceRef
implements VMValueInstance<Int32x4> {
final int size;
final Map<String, VMBoundField> fields;
VMInt32x4Instance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
class VMStackTraceInstanceRef extends VMValueInstanceRef<StackTrace> {
final Trace value;
VMStackTraceInstanceRef._(Scope scope, Map json)
: value = new Trace.parseVM(json["valueAsString"]),
super._(scope, json);
Future<VMStackTraceInstance> load() async =>
new VMStackTraceInstance._(_scope, await _load());
}
class VMStackTraceInstance extends VMStackTraceInstanceRef
implements VMValueInstance<StackTrace> {
final int size;
final Map<String, VMBoundField> fields;
VMStackTraceInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
}
// Instances of userspace Dart classes
/// A reference to an instance of [String].
class VMStringInstanceRef extends VMInstanceRef {
/// Note that the value of a reference to a string may be truncated for long
/// strings. If so, [isValueTruncated] will be `true`, and the full value can
/// be accessed using [getValue] or [VMStringInstance.value].
final String value;
/// Whether [value] is truncated for being too long.
final bool isValueTruncated;
VMStringInstanceRef._(Scope scope, Map json)
: value = json["valueAsString"],
isValueTruncated = json["valueAsStringIsTruncated"] ?? false,
super._(scope, json);
Future<String> _getValue(onUnknownValue(value)) async {
try {
return (await load()).value;
} on VMSentinelException catch (error) {
if (onUnknownValue != null) return onUnknownValue(error.sentinel);
rethrow;
}
}
Future<VMStringInstance> load() async =>
new VMStringInstance._(_scope, await _load());
String toString() {
var contents = isValueTruncated ? "$value..." : value;
return '"' + escapeString(contents).replaceAll('"', '\\"') + '"';
}
}
/// An instance of [String].
class VMStringInstance extends VMStringInstanceRef implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
VMStringInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
super._(scope, json);
Future<String> _getValue(onUnknownValue(value)) async => value;
}
/// A reference to an instance of [List].
class VMListInstanceRef extends VMInstanceRef {
/// The length of the list.
final int length;
VMListInstanceRef._(Scope scope, Map json)
: length = json["length"],
super._(scope, json);
Future<List> _getValue(onUnknownValue(value)) async {
try {
return (await load())._getValue(onUnknownValue);
} on VMSentinelException catch (error) {
if (onUnknownValue != null) return onUnknownValue(error.sentinel);
rethrow;
}
}
Future<VMListInstance> load() async =>
new VMListInstance._(_scope, await _load());
String toString() => "[...]";
}
/// An instance of [List].
class VMListInstance extends VMListInstanceRef implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
/// The elements of the list.
///
/// Each element is either a [VMInstanceRef] or a [VMSentinel], indicating
/// that the value has expired.
final List elements;
VMListInstance._(Scope scope, Map json)
: size = json["size"],
elements = new List.unmodifiable(json["elements"]
.map((element) => newVMInstanceRefOrSentinel(scope, element))),
fields = _fields(scope, json),
super._(scope, json);
Future<List> _getValue(onUnknownValue(value)) async {
var cache = Zone.current[#_cache];
if (cache.containsKey(this)) return cache[this];
var list = [];
cache[this] = list;
await Future.wait(elements.map((element) async {
if (element is VMInstanceRef) {
list.add(await element._getValue(onUnknownValue));
} else if (onUnknownValue != null) {
list.add(await onUnknownValue(element));
} else {
throw new VMSentinelException(element);
}
}), eagerError: true);
return list;
}
String toString() => "[${elements.join(", ")}]";
}
/// A reference to an instance of [Map].
class VMMapInstanceRef extends VMInstanceRef {
/// The length of the map.
final int length;
VMMapInstanceRef._(Scope scope, Map json)
: length = json["length"],
super._(scope, json);
Future<Map> _getValue(onUnknownValue(value)) async {
try {
return (await load())._getValue(onUnknownValue);
} on VMSentinelException catch (error) {
if (onUnknownValue != null) return onUnknownValue(error.sentinel);
rethrow;
}
}
Future<VMMapInstance> load() async =>
new VMMapInstance._(_scope, await _load());
String toString() => "{...}";
}
/// An instance of [Map].
class VMMapInstance extends VMMapInstanceRef implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
/// The key/value pairs in the map.
final List<VMMapAssociation> associations;
VMMapInstance._(Scope scope, Map json)
: size = json["size"],
associations = new List.unmodifiable(json["associations"]
.map((element) => new VMMapAssociation._(scope, element))),
fields = _fields(scope, json),
super._(scope, json);
Future<Map> _getValue(onUnknownValue(value)) async {
var cache = Zone.current[#_cache];
if (cache.containsKey(this)) return cache[this];
var map = {};
cache[this] = map;
await Future.wait(associations.map((association) async {
var results = await Future.wait(
[association.key, association.value].map((value) {
if (value is VMInstanceRef) {
return value._getValue(onUnknownValue);
} else if (onUnknownValue != null) {
return onUnknownValue(value);
} else {
throw new VMSentinelException(value);
}
}),
eagerError: true);
map[results.first] = results.last;
}), eagerError: true);
return map;
}
String toString() => "{${associations.join(", ")}}";
}
/// A single key/value pair in a [VMMapInstance].
class VMMapAssociation {
/// The key.
///
/// This is either a [VMInstance] or a [VMSentinel], indicating that the key
/// has expired.
final key;
/// The value.
///
/// This is either a [VMInstance] or a [VMSentinel], indicating that the value
/// has expired.
final value;
VMMapAssociation._(scope, json)
: key = newVMInstanceRefOrSentinel(scope, json["key"]),
value = newVMInstanceRefOrSentinel(scope, json["value"]);
String toString() => "$key: $value";
}
/// A reference to an instance of [TypedData].
class VMTypedDataInstanceRef<T extends TypedData> extends VMInstanceRef {
/// The length of the data.
final int length;
/// The length of the data in bytes.
final int lengthInBytes;
VMTypedDataInstanceRef._(Scope scope, Map json)
: length = json["length"],
lengthInBytes = json["length"] * _bytesPerValue(json["kind"]),
super._(scope, json);
/// Returns the number of bytes each element takes up for the typed data kind
/// [kind].
static int _bytesPerValue(String kind) {
switch (kind) {
case "Uint8ClampedList":
case "Uint8List":
case "Int8List":
return 8;
case "Uint16List":
case "Int16List":
return 16;
case "Uint32List":
case "Int32List":
case "Float32List":
return 32;
case "Uint64List":
case "Int64List":
case "Float64List":
return 64;
case "Int32x4List":
case "Float32x4List":
case "Float64x2List":
return 128;
default:
throw new StateError('Unknown TypedData kind "$kind".');
}
}
Future<T> _getValue(onUnknownValue(value)) async {
try {
return (await load())._getValue(onUnknownValue);
} on VMSentinelException catch (error) {
if (onUnknownValue != null) return onUnknownValue(error.sentinel);
rethrow;
}
}
Future<VMTypedDataInstance<T>> load() async =>
new VMTypedDataInstance<T>._(_scope, await _load());
String toString() => "[...]";
}
/// An instance of [TypedData].
class VMTypedDataInstance<T extends TypedData> extends VMTypedDataInstanceRef<T>
implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
/// A local copy of the value of the data.
final T value;
VMTypedDataInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
value = _value(json) as T,
super._(scope, json);
static TypedData _value(Map json) {
List<int> byteList = base64Decode(json["bytes"]);
var bytes = new Uint8List.fromList(byteList);
switch (json["kind"]) {
case "Uint8ClampedList":
return bytes.buffer.asUint8ClampedList();
case "Uint8List":
return bytes.buffer.asUint8List();
case "Uint16List":
return bytes.buffer.asUint16List();
case "Uint32List":
return bytes.buffer.asUint32List();
case "Uint64List":
return bytes.buffer.asUint64List();
case "Int8List":
return bytes.buffer.asInt8List();
case "Int16List":
return bytes.buffer.asInt16List();
case "Int32List":
return bytes.buffer.asInt32List();
case "Int64List":
return bytes.buffer.asInt64List();
case "Float32List":
return bytes.buffer.asFloat32List();
case "Float64List":
return bytes.buffer.asFloat64List();
case "Int32x4List":
return bytes.buffer.asInt32x4List();
case "Float32x4List":
return bytes.buffer.asFloat32x4List();
case "Float64x2List":
return bytes.buffer.asFloat64x2List();
default:
throw new StateError('Unknown TypedData kind "${json["kind"]}".');
}
}
Future<T> _getValue(onUnknownValue(value)) async => value;
String toString() => value.toString();
}
/// A reference to an instance of [RegExp].
///
/// Note that [getValue] is only guaranteed to be accurate in version 3.0 and
/// later of the VM service protocol. In previous version, there was no way to
/// get the values of the [RegExp.isCaseSensitive] and [RegExp.isMultiLine]
/// flags.
class VMRegExpInstanceRef extends VMInstanceRef {
/// The RegExp's pattern.
final VMStringInstanceRef pattern;
VMRegExpInstanceRef._(Scope scope, Map json)
: pattern = new VMStringInstanceRef._(scope, json["pattern"]),
super._(scope, json);
Future<RegExp> _getValue(onUnknownValue(value)) async {
try {
return (await load())._getValue(onUnknownValue);
} on VMSentinelException catch (error) {
if (onUnknownValue != null) return onUnknownValue(error.sentinel);
rethrow;
}
}
Future<VMRegExpInstance> load() async =>
new VMRegExpInstance._(_scope, await _load());
String toString() => pattern.toString();
}
/// An instance of [RegExp].
class VMRegExpInstance extends VMRegExpInstanceRef implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
/// Whether the RegExp is case-sensitive.
///
/// This is only guaranteed to be accurate in version 3.0 and later of the VM
/// service protocol
final bool isCaseSensitive;
/// Whether the RegExp is multi-line-aware.
///
/// This is only guaranteed to be accurate in version 3.0 and later of the VM
/// service protocol
final bool isMultiLine;
VMRegExpInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
isCaseSensitive = json["isCaseSensitive"] ?? true,
isMultiLine = json["isMultiLine"] ?? false,
super._(scope, json);
Future<RegExp> _getValue(onUnknownValue(value)) async {
var value =
pattern.isValueTruncated ? (await pattern.load()).value : pattern.value;
return new RegExp(value,
multiLine: isMultiLine, caseSensitive: isCaseSensitive);
}
}
// Internal VM objects
/// A reference to an instance of the built-in VM closure implementation.
class VMClosureInstanceRef extends VMInstanceRef {
VMClosureInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMClosureInstance> load() async =>
new VMClosureInstance._(_scope, await _load());
}
/// An instance of the built-in VM closure implementation.
class VMClosureInstance extends VMClosureInstanceRef implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
/// The function associated with this closure.
final VMFunctionRef function;
/// The context of this closure.
///
/// This contains the variables captures by the closure.
final VMContextRef context;
VMClosureInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
function = newVMFunctionRef(scope, json["closureFunction"]),
context = newVMContextRef(scope, json["closureContext"]),
super._(scope, json);
}
/// A reference to an instance of the VM-internal MirrorReference class.
class VMMirrorReferenceInstanceRef extends VMInstanceRef {
VMMirrorReferenceInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMMirrorReferenceInstance> load() async =>
new VMMirrorReferenceInstance._(_scope, await _load());
}
/// An instance of the VM-internal MirrorReference class.
class VMMirrorReferenceInstance extends VMMirrorReferenceInstanceRef
implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
final VMInstanceRef referent;
VMMirrorReferenceInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
referent = newVMInstanceRef(scope, json["mirrorReferent"]),
super._(scope, json);
}
/// A reference to an instance of the VM-internal WeakProperty class.
class VMWeakPropertyInstanceRef extends VMInstanceRef {
VMWeakPropertyInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMWeakPropertyInstance> load() async =>
new VMWeakPropertyInstance._(_scope, await _load());
}
/// An instance of the VM-internal WeakProperty class.
class VMWeakPropertyInstance extends VMWeakPropertyInstanceRef
implements VMInstance {
final int size;
final Map<String, VMBoundField> fields;
final VMInstanceRef key;
final VMInstanceRef value;
VMWeakPropertyInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
key = newVMInstanceRef(scope, json["propertyKey"]),
value = newVMInstanceRef(scope, json["propertyValue"]),
super._(scope, json);
}
/// A reference to an instance that's used as a type.
abstract class VMTypeLikeInstanceRef extends VMInstanceRef {
VMTypeLikeInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMTypeLikeInstance> load();
}
/// An instance that's used as a type.
abstract class VMTypeLikeInstance implements VMTypeLikeInstanceRef, VMInstance {
}
/// A reference to an instance of [Type].
class VMTypeInstanceRef extends VMTypeLikeInstanceRef {
/// The name of the type.
final String name;
final VMClassRef typeClass;
VMTypeInstanceRef._(Scope scope, Map json)
: name = json["name"],
typeClass = newVMClassRef(scope, json["typeClass"]),
super._(scope, json);
Future<VMTypeInstance> load() async =>
new VMTypeInstance._(_scope, await _load());
String toString() => name;
}
/// An instance of [Type].
class VMTypeInstance extends VMTypeInstanceRef implements VMTypeLikeInstance {
final int size;
final Map<String, VMBoundField> fields;
/// The type arguments for this type.
///
/// This will be empty unless this is an instantiated generic type.
final VMTypeArgumentsRef arguments;
VMTypeInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
arguments = newVMTypeArgumentsRef(scope, json["typeArguments"]),
super._(scope, json);
}
/// A reference to an instance of the VM-internal TypeParameter class.
class VMTypeParameterInstanceRef extends VMTypeLikeInstanceRef {
final VMClassRef parameterizedClass;
VMTypeParameterInstanceRef._(Scope scope, Map json)
: parameterizedClass = newVMClassRef(scope, json["parameterizedClass"]),
super._(scope, json);
Future<VMTypeParameterInstance> load() async =>
new VMTypeParameterInstance._(_scope, await _load());
String toString() => "?";
}
/// An instance of the VM-internal TypeParameter class.
class VMTypeParameterInstance extends VMTypeParameterInstanceRef
implements VMTypeLikeInstance {
final int size;
final Map<String, VMBoundField> fields;
final int index;
VMTypeParameterInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
index = json["index"],
super._(scope, json);
}
/// A reference to an instance of the VM-internal TypeRef class.
class VMTypeRefInstanceRef extends VMTypeLikeInstanceRef {
VMTypeRefInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMTypeRefInstance> load() async =>
new VMTypeRefInstance._(_scope, await _load());
}
/// An instance of the VM-internal TypeRef class.
class VMTypeRefInstance extends VMTypeRefInstanceRef
implements VMTypeLikeInstance {
final int size;
final Map<String, VMBoundField> fields;
final VMTypeLikeInstanceRef referent;
VMTypeRefInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
referent = newVMTypeLikeInstanceRef(scope, json["targetType"]),
super._(scope, json);
}
/// A reference to an instance of the VM-internal BoundedType class.
class VMBoundedTypeInstanceRef extends VMTypeLikeInstanceRef {
VMBoundedTypeInstanceRef._(Scope scope, Map json) : super._(scope, json);
Future<VMBoundedTypeInstance> load() async =>
new VMBoundedTypeInstance._(_scope, await _load());
}
/// An instance of the VM-internal BoundedType class.
class VMBoundedTypeInstance extends VMBoundedTypeInstanceRef
implements VMTypeLikeInstance {
final int size;
final Map<String, VMBoundField> fields;
final VMTypeLikeInstanceRef bounded;
VMBoundedTypeInstance._(Scope scope, Map json)
: size = json["size"],
fields = _fields(scope, json),
bounded = newVMTypeLikeInstanceRef(scope, json["targetType"]),
super._(scope, json);
}
/// Returns a map that provides access to the internal fields of an `Instance`
/// described by [json].
Map<String, VMBoundField> _fields(Scope scope, Map json) {
if (json["fields"] == null) return const {};
return new UnmodifiableMapView(new Map.fromIterable(json["fields"],
key: (field) => field["decl"]["name"],
value: (field) => newVMBoundField(scope, field)));
}